Code

Fixed tests (Mathew Ericson - 738604)
[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 <stdarg.h>
17 #include <limits.h>
19 #include <arpa/inet.h>
21 extern int timeout_interval;
22 extern const char *progname;
24 void support (void);
25 char *clean_revstring (const char *);
26 void print_revision (const char *, const char *);
27 void die (int result, const char *fmt, ...);
28 void terminate (int result, const char *fmt, ...);
29 RETSIGTYPE timeout_alarm_handler (int);
31 int is_integer (char *);
32 int is_intpos (char *);
33 int is_intneg (char *);
34 int is_intnonneg (char *);
35 int is_intpercent (char *);
37 int is_numeric (char *);
38 int is_positive (char *);
39 int is_negative (char *);
40 int is_nonnegative (char *);
41 int is_percentage (char *);
43 int is_option (char *str);
45 double delta_time (struct timeval tv);
47 void strip (char *);
48 char *strscpy (char *dest, const char *src);
49 char *strscat (char *dest, char *src);
50 char *strnl (char *str);
51 char *strpcpy (char *dest, const char *src, const char *str);
52 char *strpcat (char *dest, const char *src, const char *str);
54 char *state_text (int result);
56 #define LABELLEN 63
57 #define STRLEN 64
58 #define TXTBLK 128
60 /* **************************************************************************
61  /* max_state(STATE_x, STATE_y)
62  * compares STATE_x to  STATE_y and returns result based on the following
63  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
64  *
65  * Note that numerically the above does not hold
66  ****************************************************************************/
68 #define max(a,b) (((a)>(b))?(a):(b))
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 void usage (char *msg)
88 {
89         printf (msg);
90         print_usage ();
91         exit (STATE_UNKNOWN);
92 }
94 void usage2(char *msg, char *arg)
95 {
96         printf ("%s: %s - %s\n",progname,msg,arg);
97         print_usage ();
98         exit (STATE_UNKNOWN);
99 }
101 void
102 usage3 (char *msg, char arg)
104         printf ("%s: %s - %c\n", progname, msg, arg);
105         print_usage();
106         exit (STATE_UNKNOWN);
110 void
111 support (void)
113         printf
114                 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
115                  "regarding use of this software. To submit patches or suggest improvements,\n"
116                  "send email to nagiosplug-devel@lists.sourceforge.net\n");
120 char *
121 clean_revstring (const char *revstring)
123         char plugin_revision[STRLEN];
124         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
125                 return strscpy (NULL, plugin_revision);
126         else
127           return strscpy (NULL, "N/A");
130 void
131 print_revision (const char *command_name, const char *revision_string)
133         char plugin_revision[STRLEN];
135         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
136                 strncpy (plugin_revision, "N/A", STRLEN);
137         printf ("%s (nagios-plugins %s) %s\n",
138                                         progname, VERSION, plugin_revision);
139         printf
140                 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
141                  "copies of the plugins under the terms of the GNU General Public License.\n"
142                  "For more information about these matters, see the file named COPYING.\n");
146 char *
147 state_text (int result)
149         switch (result) {
150         case STATE_OK:
151                 return "OK";
152         case STATE_WARNING:
153                 return "WARNING";
154         case STATE_CRITICAL:
155                 return "CRITICAL";
156         case STATE_DEPENDENT:
157                 return "DEPENDENT";
158         default:
159                 return "UNKNOWN";
160         }
163 void
164 die (int result, const char *fmt, ...)
166         va_list ap;
167         printf ("%s %s: ", sizeof (char) + index(progname, '_'), state_text(result));
168         va_start (ap, fmt);
169         vprintf (fmt, ap);
170         va_end (ap);
171         exit (result);
174 void
175 terminate (int result, const char *fmt, ...)
177         va_list ap;
178         va_start (ap, fmt);
179         vprintf (fmt, ap);
180         va_end (ap);
181         exit (result);
184 void
185 timeout_alarm_handler (int signo)
187         if (signo == SIGALRM) {
188                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
189                                                 timeout_interval);
190                 exit (STATE_CRITICAL);
191         }
194 int
195 is_numeric (char *number)
197         char tmp[1];
198         float x;
200         if (!number)
201                 return FALSE;
202         else if (sscanf (number, "%f%c", &x, tmp) == 1)
203                 return TRUE;
204         else
205                 return FALSE;
208 int
209 is_positive (char *number)
211         if (is_numeric (number) && atof (number) > 0.0)
212                 return TRUE;
213         else
214                 return FALSE;
217 int
218 is_negative (char *number)
220         if (is_numeric (number) && atof (number) < 0.0)
221                 return TRUE;
222         else
223                 return FALSE;
226 int
227 is_nonnegative (char *number)
229         if (is_numeric (number) && atof (number) >= 0.0)
230                 return TRUE;
231         else
232                 return FALSE;
235 int
236 is_percentage (char *number)
238         int x;
239         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
240                 return TRUE;
241         else
242                 return FALSE;
245 int
246 is_integer (char *number)
248         long int n;
250         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
251                 return FALSE;
253         n = strtol (number, NULL, 10);
255         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
256                 return TRUE;
257         else
258                 return FALSE;
261 int
262 is_intpos (char *number)
264         if (is_integer (number) && atoi (number) > 0)
265                 return TRUE;
266         else
267                 return FALSE;
270 int
271 is_intneg (char *number)
273         if (is_integer (number) && atoi (number) < 0)
274                 return TRUE;
275         else
276                 return FALSE;
279 int
280 is_intnonneg (char *number)
282         if (is_integer (number) && atoi (number) >= 0)
283                 return TRUE;
284         else
285                 return FALSE;
288 int
289 is_intpercent (char *number)
291         int i;
292         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
293                 return TRUE;
294         else
295                 return FALSE;
298 int
299 is_option (char *str)
301         if (!str)
302                 return FALSE;
303         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
304                 return TRUE;
305         else
306                 return FALSE;
311 #ifdef NEED_GETTIMEOFDAY
312 int
313 gettimeofday (struct timeval *tv, struct timezone *tz)
315         tv->tv_usec = 0;
316         tv->tv_sec = (long) time ((time_t) 0);
318 #endif
322 double
323 delta_time (struct timeval tv)
325         struct timeval now;
327         gettimeofday (&now, NULL);
328         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
334 void
335 strip (char *buffer)
337         size_t x;
338         int i;
340         for (x = strlen (buffer); x >= 1; x--) {
341                 i = x - 1;
342                 if (buffer[i] == ' ' ||
343                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
344                         buffer[i] = '\0';
345                 else
346                         break;
347         }
348         return;
355 /******************************************************************************
356  *
357  * Copies one string to another. Any previously existing data in
358  * the destination string is lost.
359  *
360  * Example:
361  *
362  * char *str=NULL;
363  * str = strscpy("This is a line of text with no trailing newline");
364  *
365  *****************************************************************************/
367 char *
368 strscpy (char *dest, const char *src)
370         if (src == NULL)
371                 return NULL;
373         asprintf (&dest, "%s", src);
375         return dest;
382 /******************************************************************************
383  *
384  * Concatenates one string to the end of another
385  *
386  * Given a pointer destination string, which may or may not already
387  * hold some text, and a source string with additional text (possibly
388  * NULL or empty), returns a pointer to a string that is the first
389  * string with the second concatenated to it. Uses realloc to free 
390  * memory held by the dest argument if new storage space is required.
391  *
392  * Example:
393  *
394  * char *str=NULL;
395  * str = strscpy("This is a line of text with no trailing newline");
396  * str = strscat(str,"\n");
397  *
398  *****************************************************************************/
400 char *
401 strscat (char *dest, char *src)
404         if (dest == NULL)
405                 return src;
406         if (src != NULL)
407                 asprintf (&dest, "%s%s", dest, src);
409         return dest;
416 /******************************************************************************
417  *
418  * Returns a pointer to the next line of a multiline string buffer
419  *
420  * Given a pointer string, find the text following the next sequence
421  * of \r and \n characters. This has the effect of skipping blank
422  * lines as well
423  *
424  * Example:
425  *
426  * Given text as follows:
427  *
428  * ==============================
429  * This
430  * is
431  * a
432  * 
433  * multiline string buffer
434  * ==============================
435  *
436  * int i=0;
437  * char *str=NULL;
438  * char *ptr=NULL;
439  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
440  * ptr = str;
441  * while (ptr) {
442  *   printf("%d %s",i++,firstword(ptr));
443  *   ptr = strnl(ptr);
444  * }
445  * 
446  * Produces the following:
447  *
448  * 1 This
449  * 2 is
450  * 3 a
451  * 4 multiline
452  *
453  * NOTE: The 'firstword()' function is conceptual only and does not
454  *       exist in this package.
455  *
456  * NOTE: Although the second 'ptr' variable is not strictly needed in
457  *       this example, it is good practice with these utilities. Once
458  *       the * pointer is advance in this manner, it may no longer be
459  *       handled with * realloc(). So at the end of the code fragment
460  *       above, * strscpy(str,"foo") work perfectly fine, but
461  *       strscpy(ptr,"foo") will * cause the the program to crash with
462  *       a segmentation fault.
463  *
464  *****************************************************************************/
466 char *
467 strnl (char *str)
469         size_t len;
470         if (str == NULL)
471                 return NULL;
472         str = strpbrk (str, "\r\n");
473         if (str == NULL)
474                 return NULL;
475         len = strspn (str, "\r\n");
476         if (str[len] == '\0')
477                 return NULL;
478         str += len;
479         if (strlen (str) == 0)
480                 return NULL;
481         return str;
488 /******************************************************************************
489  *
490  * Like strscpy, except only the portion of the source string up to
491  * the provided delimiter is copied.
492  *
493  * Example:
494  *
495  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
496  * printf("%s\n",str);
497  *
498  * Produces:
499  *
500  *This is a line of te
501  *
502  *****************************************************************************/
504 char *
505 strpcpy (char *dest, const char *src, const char *str)
507         size_t len;
509         if (src)
510                 len = strcspn (src, str);
511         else
512                 return NULL;
514         if (dest == NULL || strlen (dest) < len)
515                 dest = realloc (dest, len + 1);
516         if (dest == NULL)
517                 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
519         strncpy (dest, src, len);
520         dest[len] = '\0';
522         return dest;
529 /******************************************************************************
530  *
531  * Like strscat, except only the portion of the source string up to
532  * the provided delimiter is copied.
533  *
534  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
535  * str = strpcat(str,"This is a line of text with no trailing newline","x");
536  * printf("%s\n",str);
537  * 
538  *This is a line of texThis is a line of tex
539  *
540  *****************************************************************************/
542 char *
543 strpcat (char *dest, const char *src, const char *str)
545         size_t len, l2;
547         if (dest)
548                 len = strlen (dest);
549         else
550                 len = 0;
552         if (src) {
553                 l2 = strcspn (src, str);
554         }
555         else {
556                 return dest;
557         }
559         dest = realloc (dest, len + l2 + 1);
560         if (dest == NULL)
561                 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
563         strncpy (dest + len, src, l2);
564         dest[len + l2] = '\0';
566         return dest;