Code

more readable max_state() code
[nagiosplug.git] / plugins / utils.c
1 /*****************************************************************************
2  *
3  * utils.c
4  *
5  * Library of useful functions for plugins
6  *
7  * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
8  * License: GPL
9  *
10  * $Revision$
11  * $Date$
12  ****************************************************************************/
14 #include "config.h"
15 #include "common.h"
16 #include "version.h"
17 #include <stdarg.h>
18 #include <limits.h>
20 extern int timeout_interval;
22 char *my_basename (char *);
23 void support (void);
24 char *clean_revstring (const char *);
25 void print_revision (char *, const char *);
26 void terminate (int, const char *fmt, ...);
27 RETSIGTYPE timeout_alarm_handler (int);
29 int is_host (char *);
30 int is_dotted_quad (char *);
31 int is_hostname (char *);
33 int is_integer (char *);
34 int is_intpos (char *);
35 int is_intneg (char *);
36 int is_intnonneg (char *);
37 int is_intpercent (char *);
39 int is_numeric (char *);
40 int is_positive (char *);
41 int is_negative (char *);
42 int is_nonnegative (char *);
43 int is_percentage (char *);
45 int is_option (char *str);
47 double delta_time (struct timeval tv);
49 void strip (char *);
50 char *strscpy (char *dest, const char *src);
51 char *strscat (char *dest, char *src);
52 char *strnl (char *str);
53 char *strpcpy (char *dest, const char *src, const char *str);
54 char *strpcat (char *dest, const char *src, const char *str);
56 #define LABELLEN 63
57 #define STRLEN 64
58 #define TXTBLK 128
60 #define max(a,b) ((a)>(b))?(a):(b)
62 /* **************************************************************************
63  * max_state(STATE_x, STATE_y)
64  * compares STATE_x to  STATE_y and returns result based on the following
65  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
66  *
67  * Note that numerically the above does not hold
68  ****************************************************************************/
70 int
71 max_state(int a, int b)
72 {
73         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
74                 return STATE_CRITICAL;
75         else if (a == STATE_WARNING || b == STATE_WARNING)
76                 return STATE_WARNING;
77         else if (a == STATE_OK || b == STATE_OK)
78                 return STATE_OK;
79         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
80                 return STATE_UNKNOWN;
81         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
82                 return STATE_DEPENDENT;
83         else
84                 return max (a, b);
85 }
87 char *
88 my_basename (char *path)
89 {
90         if (!strstr (path, "/"))
91                 return path;
92         else
93                 return 1 + strrchr (path, '/');
94 }
97 void
98 support (void)
99 {
100         printf
101                 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
102                  "regarding use of this software. To submit patches or suggest improvements,\n"
103                  "send email to nagiosplug-devel@lists.sourceforge.net\n");
107 char *
108 clean_revstring (const char *revstring)
110         char plugin_revision[STRLEN];
111         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
112                 return strscpy (NULL, plugin_revision);
113         else
114           return strscpy (NULL, "N/A");
117 void
118 print_revision (char *command_name, const char *revision_string)
120         char plugin_revision[STRLEN];
122         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
123                 strncpy (plugin_revision, "N/A", STRLEN);
124         printf ("%s (nagios-plugins %s) %s\n",
125                                         my_basename (command_name), VERSION, plugin_revision);
126         printf
127                 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
128                  "copies of the plugins under the terms of the GNU General Public License.\n"
129                  "For more information about these matters, see the file named COPYING.\n");
134 void
135 terminate (int result, const char *fmt, ...)
137         va_list ap;
138         va_start (ap, fmt);
139         vprintf (fmt, ap);
140         va_end (ap);
141         exit (result);
144 void
145 timeout_alarm_handler (int signo)
147         if (signo == SIGALRM) {
148                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
149                                                 timeout_interval);
150                 exit (STATE_CRITICAL);
151         }
154 int
155 is_host (char *address)
157         if (is_dotted_quad (address) || is_hostname (address))
158                 return (TRUE);
159         return (FALSE);
162 int
163 is_dotted_quad (char *address)
165         int o1, o2, o3, o4;
166         char c[1];
168         if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4)
169                 return FALSE;
170         else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255)
171                 return FALSE;
172         else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0)
173                 return FALSE;
174         else
175                 return TRUE;
178 /* from RFC-1035
179  * 
180  * The labels must follow the rules for ARPANET host names.  They must
181  * start with a letter, end with a letter or digit, and have as interior
182  * characters only letters, digits, and hyphen.  There are also some
183  * restrictions on the length.  Labels must be 63 characters or less. */
185 int
186 is_hostname (char *s1)
188         if (strlen (s1) > 63)
189                 return FALSE;
190         if (strcspn
191                         (s1,
192                          "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") !=
193                         0) return FALSE;
194         if (strspn (s1, "0123456789-.") == 1)
195                 return FALSE;
196         while ((s1 = index (s1, '.'))) {
197                 s1++;
198                 if (strspn (s1, "0123456789-.") == 1) {
199                         printf ("%s\n", s1);
200                         return FALSE;
201                 }
202         }
203         return TRUE;
206 int
207 is_numeric (char *number)
209         char tmp[1];
210         float x;
211         if (sscanf (number, "%f%c", &x, tmp) == 1)
212                 return (TRUE);
213         return (FALSE);
216 int
217 is_positive (char *number)
219         if (is_numeric (number) && atof (number) > 0.0)
220                 return (TRUE);
221         return (FALSE);
224 int
225 is_negative (char *number)
227         if (is_numeric (number) && atof (number) < 0.0)
228                 return (TRUE);
229         return (FALSE);
232 int
233 is_nonnegative (char *number)
235         if (is_numeric (number) && atof (number) >= 0.0)
236                 return (TRUE);
237         return (FALSE);
240 int
241 is_percentage (char *number)
243         int x;
244         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
245                 return (TRUE);
246         return (FALSE);
249 int
250 is_integer (char *number)
252         long int n;
254         if (strspn (number, "-0123456789 ") != strlen (number))
255                 return (FALSE);
257         n = strtol (number, NULL, 10);
258         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
259                 return (TRUE);
260         return (FALSE);
263 int
264 is_intpos (char *number)
266         if (is_integer (number) && atoi (number) > 0)
267                 return (TRUE);
268         return (FALSE);
271 int
272 is_intneg (char *number)
274         if (is_integer (number) && atoi (number) < 0)
275                 return (TRUE);
276         return (FALSE);
279 int
280 is_intnonneg (char *number)
282         if (is_integer (number) && atoi (number) >= 0)
283                 return (TRUE);
284         return (FALSE);
287 int
288 is_intpercent (char *number)
290         int i;
291         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
292                 return (TRUE);
293         return (FALSE);
296 int
297 is_option (char *str)
299         if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
300                 return TRUE;
301         return FALSE;
306 #ifdef NEED_GETTIMEOFDAY
307 int
308 gettimeofday (struct timeval *tv, struct timezone *tz)
310         tv->tv_usec = 0;
311         tv->tv_sec = (long) time ((time_t) 0);
313 #endif
317 double
318 delta_time (struct timeval tv)
320         struct timeval now;
322         gettimeofday (&now, NULL);
323         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
329 void
330 strip (char *buffer)
332         size_t x;
333         int i;
335         for (x = strlen (buffer); x >= 1; x--) {
336                 i = x - 1;
337                 if (buffer[i] == ' ' ||
338                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
339                         buffer[i] = '\0';
340                 else
341                         break;
342         }
343         return;
350 /******************************************************************************
351  *
352  * Copies one string to another. Any previously existing data in
353  * the destination string is lost.
354  *
355  * Example:
356  *
357  * char *str=NULL;
358  * str = strscpy("This is a line of text with no trailing newline");
359  *
360  *****************************************************************************/
362 char *
363 strscpy (char *dest, const char *src)
365         if (src == NULL)
366                 return NULL;
368         asprintf (&dest, "%s", src);
370         return dest;
377 /******************************************************************************
378  *
379  * Concatenates one string to the end of another
380  *
381  * Given a pointer destination string, which may or may not already
382  * hold some text, and a source string with additional text (possibly
383  * NULL or empty), returns a pointer to a string that is the first
384  * string with the second concatenated to it. Uses realloc to free 
385  * memory held by the dest argument if new storage space is required.
386  *
387  * Example:
388  *
389  * char *str=NULL;
390  * str = strscpy("This is a line of text with no trailing newline");
391  * str = strscat(str,"\n");
392  *
393  *****************************************************************************/
395 char *
396 strscat (char *dest, char *src)
399         if (dest == NULL)
400                 return src;
401         if (src != NULL)
402                 asprintf (&dest, "%s%s", dest, src);
404         return dest;
411 /******************************************************************************
412  *
413  * Returns a pointer to the next line of a multiline string buffer
414  *
415  * Given a pointer string, find the text following the next sequence
416  * of \r and \n characters. This has the effect of skipping blank
417  * lines as well
418  *
419  * Example:
420  *
421  * Given text as follows:
422  *
423  * ==============================
424  * This
425  * is
426  * a
427  * 
428  * multiline string buffer
429  * ==============================
430  *
431  * int i=0;
432  * char *str=NULL;
433  * char *ptr=NULL;
434  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
435  * ptr = str;
436  * while (ptr) {
437  *   printf("%d %s",i++,firstword(ptr));
438  *   ptr = strnl(ptr);
439  * }
440  * 
441  * Produces the following:
442  *
443  * 1 This
444  * 2 is
445  * 3 a
446  * 4 multiline
447  *
448  * NOTE: The 'firstword()' function is conceptual only and does not
449  *       exist in this package.
450  *
451  * NOTE: Although the second 'ptr' variable is not strictly needed in
452  *       this example, it is good practice with these utilities. Once
453  *       the * pointer is advance in this manner, it may no longer be
454  *       handled with * realloc(). So at the end of the code fragment
455  *       above, * strscpy(str,"foo") work perfectly fine, but
456  *       strscpy(ptr,"foo") will * cause the the program to crash with
457  *       a segmentation fault.
458  *
459  *****************************************************************************/
461 char *
462 strnl (char *str)
464         size_t len;
465         if (str == NULL)
466                 return NULL;
467         str = strpbrk (str, "\r\n");
468         if (str == NULL)
469                 return NULL;
470         len = strspn (str, "\r\n");
471         if (str[len] == '\0')
472                 return NULL;
473         str += len;
474         if (strlen (str) == 0)
475                 return NULL;
476         return str;
483 /******************************************************************************
484  *
485  * Like strscpy, except only the portion of the source string up to
486  * the provided delimiter is copied.
487  *
488  * Example:
489  *
490  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
491  * printf("%s\n",str);
492  *
493  * Produces:
494  *
495  *This is a line of te
496  *
497  *****************************************************************************/
499 char *
500 strpcpy (char *dest, const char *src, const char *str)
502         size_t len;
504         if (src)
505                 len = strcspn (src, str);
506         else
507                 return NULL;
509         if (dest == NULL || strlen (dest) < len)
510                 dest = realloc (dest, len + 1);
511         if (dest == NULL)
512                 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
514         strncpy (dest, src, len);
515         dest[len] = '\0';
517         return dest;
524 /******************************************************************************
525  *
526  * Like strscat, except only the portion of the source string up to
527  * the provided delimiter is copied.
528  *
529  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
530  * str = strpcat(str,"This is a line of text with no trailing newline","x");
531  * printf("%s\n",str);
532  * 
533  *This is a line of texThis is a line of tex
534  *
535  *****************************************************************************/
537 char *
538 strpcat (char *dest, const char *src, const char *str)
540         size_t len, l2;
542         if (dest)
543                 len = strlen (dest);
544         else
545                 len = 0;
547         if (src) {
548                 l2 = strcspn (src, str);
549         }
550         else {
551                 return dest;
552         }
554         dest = realloc (dest, len + l2 + 1);
555         if (dest == NULL)
556                 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
558         strncpy (dest + len, src, l2);
559         dest[len + l2] = '\0';
561         return dest;