Code

Fix test failure on poseidon
[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  * Copyright (c) 2006 Nagios Plugin Development Team
9  * License: GPL
10  *
11  * $Revision$
12  * $Date$
13  ****************************************************************************/
15 #define LOCAL_TIMEOUT_ALARM_HANDLER
17 #include "common.h"
18 #include "utils.h"
19 #include "utils_base.h"
20 #include <stdarg.h>
21 #include <limits.h>
23 #include <arpa/inet.h>
25 extern void print_usage (void);
26 extern const char *progname;
28 #define STRLEN 64
29 #define TXTBLK 128
31 /* **************************************************************************
32  * max_state(STATE_x, STATE_y)
33  * compares STATE_x to  STATE_y and returns result based on the following
34  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
35  *
36  * Note that numerically the above does not hold
37  ****************************************************************************/
39 int
40 max_state (int a, int b)
41 {
42         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
43                 return STATE_CRITICAL;
44         else if (a == STATE_WARNING || b == STATE_WARNING)
45                 return STATE_WARNING;
46         else if (a == STATE_OK || b == STATE_OK)
47                 return STATE_OK;
48         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
49                 return STATE_UNKNOWN;
50         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
51                 return STATE_DEPENDENT;
52         else
53                 return max (a, b);
54 }
56 void usage (const char *msg)
57 {
58         printf ("%s\n", msg);
59         print_usage ();
60         exit (STATE_UNKNOWN);
61 }
63 void usage_va (const char *fmt, ...)
64 {
65         va_list ap;
66         printf("%s: ", progname);
67         va_start(ap, fmt);
68         vprintf(fmt, ap);
69         va_end(ap);
70         printf("\n");
71         exit (STATE_UNKNOWN);
72 }
74 void usage2(const char *msg, const char *arg)
75 {
76         printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
77         print_usage ();
78         exit (STATE_UNKNOWN);
79 }
81 void
82 usage3 (const char *msg, int arg)
83 {
84         printf ("%s: %s - %c\n", progname, msg, arg);
85         print_usage();
86         exit (STATE_UNKNOWN);
87 }
89 void
90 usage4 (const char *msg)
91 {
92         printf ("%s: %s\n", progname, msg);
93         print_usage();
94         exit (STATE_UNKNOWN);
95 }
97 char *
98 clean_revstring (const char *revstring)
99 {
100         char plugin_revision[STRLEN];
101         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
102                 return strscpy (NULL, plugin_revision);
103         else
104           return strscpy (NULL, "N/A");
107 void
108 print_revision (const char *command_name, const char *revision_string)
110         char plugin_revision[STRLEN];
112         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
113                 strncpy (plugin_revision, "N/A", STRLEN);
114         printf ("%s (%s %s) %s\n",
115                                         command_name, PACKAGE, VERSION, plugin_revision);
118 const char *
119 state_text (int result)
121         switch (result) {
122         case STATE_OK:
123                 return "OK";
124         case STATE_WARNING:
125                 return "WARNING";
126         case STATE_CRITICAL:
127                 return "CRITICAL";
128         case STATE_DEPENDENT:
129                 return "DEPENDENT";
130         default:
131                 return "UNKNOWN";
132         }
135 void
136 timeout_alarm_handler (int signo)
138         if (signo == SIGALRM) {
139                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
140                                                 timeout_interval);
141                 exit (STATE_CRITICAL);
142         }
145 int
146 is_numeric (char *number)
148         char tmp[1];
149         float x;
151         if (!number)
152                 return FALSE;
153         else if (sscanf (number, "%f%c", &x, tmp) == 1)
154                 return TRUE;
155         else
156                 return FALSE;
159 int
160 is_positive (char *number)
162         if (is_numeric (number) && atof (number) > 0.0)
163                 return TRUE;
164         else
165                 return FALSE;
168 int
169 is_negative (char *number)
171         if (is_numeric (number) && atof (number) < 0.0)
172                 return TRUE;
173         else
174                 return FALSE;
177 int
178 is_nonnegative (char *number)
180         if (is_numeric (number) && atof (number) >= 0.0)
181                 return TRUE;
182         else
183                 return FALSE;
186 int
187 is_percentage (char *number)
189         int x;
190         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
191                 return TRUE;
192         else
193                 return FALSE;
196 int
197 is_integer (char *number)
199         long int n;
201         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
202                 return FALSE;
204         n = strtol (number, NULL, 10);
206         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
207                 return TRUE;
208         else
209                 return FALSE;
212 int
213 is_intpos (char *number)
215         if (is_integer (number) && atoi (number) > 0)
216                 return TRUE;
217         else
218                 return FALSE;
221 int
222 is_intneg (char *number)
224         if (is_integer (number) && atoi (number) < 0)
225                 return TRUE;
226         else
227                 return FALSE;
230 int
231 is_intnonneg (char *number)
233         if (is_integer (number) && atoi (number) >= 0)
234                 return TRUE;
235         else
236                 return FALSE;
239 int
240 is_intpercent (char *number)
242         int i;
243         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
244                 return TRUE;
245         else
246                 return FALSE;
249 int
250 is_option (char *str)
252         if (!str)
253                 return FALSE;
254         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
255                 return TRUE;
256         else
257                 return FALSE;
260 #ifdef NEED_GETTIMEOFDAY
261 int
262 gettimeofday (struct timeval *tv, struct timezone *tz)
264         tv->tv_usec = 0;
265         tv->tv_sec = (long) time ((time_t) 0);
267 #endif
271 double
272 delta_time (struct timeval tv)
274         struct timeval now;
276         gettimeofday (&now, NULL);
277         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
282 long
283 deltime (struct timeval tv)
285         struct timeval now;
286         gettimeofday (&now, NULL);
287         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
293 void
294 strip (char *buffer)
296         size_t x;
297         int i;
299         for (x = strlen (buffer); x >= 1; x--) {
300                 i = x - 1;
301                 if (buffer[i] == ' ' ||
302                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
303                         buffer[i] = '\0';
304                 else
305                         break;
306         }
307         return;
311 /******************************************************************************
312  *
313  * Copies one string to another. Any previously existing data in
314  * the destination string is lost.
315  *
316  * Example:
317  *
318  * char *str=NULL;
319  * str = strscpy("This is a line of text with no trailing newline");
320  *
321  *****************************************************************************/
323 char *
324 strscpy (char *dest, const char *src)
326         if (src == NULL)
327                 return NULL;
329         asprintf (&dest, "%s", src);
331         return dest;
336 /******************************************************************************
337  *
338  * Returns a pointer to the next line of a multiline string buffer
339  *
340  * Given a pointer string, find the text following the next sequence
341  * of \r and \n characters. This has the effect of skipping blank
342  * lines as well
343  *
344  * Example:
345  *
346  * Given text as follows:
347  *
348  * ==============================
349  * This
350  * is
351  * a
352  * 
353  * multiline string buffer
354  * ==============================
355  *
356  * int i=0;
357  * char *str=NULL;
358  * char *ptr=NULL;
359  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
360  * ptr = str;
361  * while (ptr) {
362  *   printf("%d %s",i++,firstword(ptr));
363  *   ptr = strnl(ptr);
364  * }
365  * 
366  * Produces the following:
367  *
368  * 1 This
369  * 2 is
370  * 3 a
371  * 4 multiline
372  *
373  * NOTE: The 'firstword()' function is conceptual only and does not
374  *       exist in this package.
375  *
376  * NOTE: Although the second 'ptr' variable is not strictly needed in
377  *       this example, it is good practice with these utilities. Once
378  *       the * pointer is advance in this manner, it may no longer be
379  *       handled with * realloc(). So at the end of the code fragment
380  *       above, * strscpy(str,"foo") work perfectly fine, but
381  *       strscpy(ptr,"foo") will * cause the the program to crash with
382  *       a segmentation fault.
383  *
384  *****************************************************************************/
386 char *
387 strnl (char *str)
389         size_t len;
390         if (str == NULL)
391                 return NULL;
392         str = strpbrk (str, "\r\n");
393         if (str == NULL)
394                 return NULL;
395         len = strspn (str, "\r\n");
396         if (str[len] == '\0')
397                 return NULL;
398         str += len;
399         if (strlen (str) == 0)
400                 return NULL;
401         return str;
405 /******************************************************************************
406  *
407  * Like strscpy, except only the portion of the source string up to
408  * the provided delimiter is copied.
409  *
410  * Example:
411  *
412  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
413  * printf("%s\n",str);
414  *
415  * Produces:
416  *
417  *This is a line of te
418  *
419  *****************************************************************************/
421 char *
422 strpcpy (char *dest, const char *src, const char *str)
424         size_t len;
426         if (src)
427                 len = strcspn (src, str);
428         else
429                 return NULL;
431         if (dest == NULL || strlen (dest) < len)
432                 dest = realloc (dest, len + 1);
433         if (dest == NULL)
434                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
436         strncpy (dest, src, len);
437         dest[len] = '\0';
439         return dest;
444 /******************************************************************************
445  *
446  * Like strscat, except only the portion of the source string up to
447  * the provided delimiter is copied.
448  *
449  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
450  * str = strpcat(str,"This is a line of text with no trailing newline","x");
451  * printf("%s\n",str);
452  * 
453  *This is a line of texThis is a line of tex
454  *
455  *****************************************************************************/
457 char *
458 strpcat (char *dest, const char *src, const char *str)
460         size_t len, l2;
462         if (dest)
463                 len = strlen (dest);
464         else
465                 len = 0;
467         if (src) {
468                 l2 = strcspn (src, str);
469         }
470         else {
471                 return dest;
472         }
474         dest = realloc (dest, len + l2 + 1);
475         if (dest == NULL)
476                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
478         strncpy (dest + len, src, l2);
479         dest[len + l2] = '\0';
481         return dest;
484 /******************************************************************************
485  *
486  * Print perfdata in a standard format
487  *
488  ******************************************************************************/
490 char *perfdata (const char *label,
491  long int val,
492  const char *uom,
493  int warnp,
494  long int warn,
495  int critp,
496  long int crit,
497  int minp,
498  long int minv,
499  int maxp,
500  long int maxv)
502         char *data = NULL;
504         if (strpbrk (label, "'= "))
505                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
506         else
507                 asprintf (&data, "%s=%ld%s;", label, val, uom);
509         if (warnp)
510                 asprintf (&data, "%s%ld;", data, warn);
511         else
512                 asprintf (&data, "%s;", data);
514         if (critp)
515                 asprintf (&data, "%s%ld;", data, crit);
516         else
517                 asprintf (&data, "%s;", data);
519         if (minp)
520                 asprintf (&data, "%s%ld", data, minv);
522         if (maxp)
523                 asprintf (&data, "%s;%ld", data, maxv);
525         return data;
529 char *fperfdata (const char *label,
530  double val,
531  const char *uom,
532  int warnp,
533  double warn,
534  int critp,
535  double crit,
536  int minp,
537  double minv,
538  int maxp,
539  double maxv)
541         char *data = NULL;
543         if (strpbrk (label, "'= "))
544                 asprintf (&data, "'%s'=", label);
545         else
546                 asprintf (&data, "%s=", label);
548         asprintf (&data, "%s%f", data, val);
549         asprintf (&data, "%s%s;", data, uom);
551         if (warnp)
552                 asprintf (&data, "%s%f", data, warn);
554         asprintf (&data, "%s;", data);
556         if (critp)
557                 asprintf (&data, "%s%f", data, crit);
559         asprintf (&data, "%s;", data);
561         if (minp)
562                 asprintf (&data, "%s%f", data, minv);
564         if (maxp) {
565                 asprintf (&data, "%s;", data);
566                 asprintf (&data, "%s%f", data, maxv);
567         }
569         return data;