Code

Changed default test values for check_dns (using nagios.com)
[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 /* **************************************************************************
57  * max_state_alt(STATE_x, STATE_y)
58  * compares STATE_x to  STATE_y and returns result based on the following
59  * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
60  *
61  * The main difference between max_state_alt and max_state it that it doesn't
62  * allow setting a default to UNKNOWN. It will instead prioritixe any valid
63  * non-OK state.
64  ****************************************************************************/
66 int
67 max_state_alt (int a, int b)
68 {
69         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
70                 return STATE_CRITICAL;
71         else if (a == STATE_WARNING || b == STATE_WARNING)
72                 return STATE_WARNING;
73         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
74                 return STATE_UNKNOWN;
75         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
76                 return STATE_DEPENDENT;
77         else if (a == STATE_OK || b == STATE_OK)
78                 return STATE_OK;
79         else
80                 return max (a, b);
81 }
83 void usage (const char *msg)
84 {
85         printf ("%s\n", msg);
86         print_usage ();
87         exit (STATE_UNKNOWN);
88 }
90 void usage_va (const char *fmt, ...)
91 {
92         va_list ap;
93         printf("%s: ", progname);
94         va_start(ap, fmt);
95         vprintf(fmt, ap);
96         va_end(ap);
97         printf("\n");
98         exit (STATE_UNKNOWN);
99 }
101 void usage2(const char *msg, const char *arg)
103         printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
104         print_usage ();
105         exit (STATE_UNKNOWN);
108 void
109 usage3 (const char *msg, int arg)
111         printf ("%s: %s - %c\n", progname, msg, arg);
112         print_usage();
113         exit (STATE_UNKNOWN);
116 void
117 usage4 (const char *msg)
119         printf ("%s: %s\n", progname, msg);
120         print_usage();
121         exit (STATE_UNKNOWN);
124 void
125 usage5 (void)
127         print_usage();
128         exit (STATE_UNKNOWN);
131 char *
132 clean_revstring (const char *revstring)
134         char plugin_revision[STRLEN];
135         plugin_revision[0] = 'v';
136         if (sscanf (revstring,"$Revision: %[0-9.]", plugin_revision + 1) == 1)
137                 return strscpy (NULL, plugin_revision);
138         else
139                 return strscpy (NULL, "N/A");
142 void
143 print_revision (const char *command_name, const char *revision_string)
145         char plugin_revision[STRLEN];
147         printf ("%s %s (%s %s)\n",
148                  command_name, clean_revstring(revision_string), PACKAGE, VERSION);
151 const char *
152 state_text (int result)
154         switch (result) {
155         case STATE_OK:
156                 return "OK";
157         case STATE_WARNING:
158                 return "WARNING";
159         case STATE_CRITICAL:
160                 return "CRITICAL";
161         case STATE_DEPENDENT:
162                 return "DEPENDENT";
163         default:
164                 return "UNKNOWN";
165         }
168 void
169 timeout_alarm_handler (int signo)
171         if (signo == SIGALRM) {
172                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
173                                                 timeout_interval);
174                 exit (STATE_CRITICAL);
175         }
178 int
179 is_numeric (char *number)
181         char tmp[1];
182         float x;
184         if (!number)
185                 return FALSE;
186         else if (sscanf (number, "%f%c", &x, tmp) == 1)
187                 return TRUE;
188         else
189                 return FALSE;
192 int
193 is_positive (char *number)
195         if (is_numeric (number) && atof (number) > 0.0)
196                 return TRUE;
197         else
198                 return FALSE;
201 int
202 is_negative (char *number)
204         if (is_numeric (number) && atof (number) < 0.0)
205                 return TRUE;
206         else
207                 return FALSE;
210 int
211 is_nonnegative (char *number)
213         if (is_numeric (number) && atof (number) >= 0.0)
214                 return TRUE;
215         else
216                 return FALSE;
219 int
220 is_percentage (char *number)
222         int x;
223         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
224                 return TRUE;
225         else
226                 return FALSE;
229 int
230 is_integer (char *number)
232         long int n;
234         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
235                 return FALSE;
237         n = strtol (number, NULL, 10);
239         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
240                 return TRUE;
241         else
242                 return FALSE;
245 int
246 is_intpos (char *number)
248         if (is_integer (number) && atoi (number) > 0)
249                 return TRUE;
250         else
251                 return FALSE;
254 int
255 is_intneg (char *number)
257         if (is_integer (number) && atoi (number) < 0)
258                 return TRUE;
259         else
260                 return FALSE;
263 int
264 is_intnonneg (char *number)
266         if (is_integer (number) && atoi (number) >= 0)
267                 return TRUE;
268         else
269                 return FALSE;
272 int
273 is_intpercent (char *number)
275         int i;
276         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
277                 return TRUE;
278         else
279                 return FALSE;
282 int
283 is_option (char *str)
285         if (!str)
286                 return FALSE;
287         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
288                 return TRUE;
289         else
290                 return FALSE;
293 #ifdef NEED_GETTIMEOFDAY
294 int
295 gettimeofday (struct timeval *tv, struct timezone *tz)
297         tv->tv_usec = 0;
298         tv->tv_sec = (long) time ((time_t) 0);
300 #endif
304 double
305 delta_time (struct timeval tv)
307         struct timeval now;
309         gettimeofday (&now, NULL);
310         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
315 long
316 deltime (struct timeval tv)
318         struct timeval now;
319         gettimeofday (&now, NULL);
320         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
326 void
327 strip (char *buffer)
329         size_t x;
330         int i;
332         for (x = strlen (buffer); x >= 1; x--) {
333                 i = x - 1;
334                 if (buffer[i] == ' ' ||
335                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
336                         buffer[i] = '\0';
337                 else
338                         break;
339         }
340         return;
344 /******************************************************************************
345  *
346  * Copies one string to another. Any previously existing data in
347  * the destination string is lost.
348  *
349  * Example:
350  *
351  * char *str=NULL;
352  * str = strscpy("This is a line of text with no trailing newline");
353  *
354  *****************************************************************************/
356 char *
357 strscpy (char *dest, const char *src)
359         if (src == NULL)
360                 return NULL;
362         asprintf (&dest, "%s", src);
364         return dest;
369 /******************************************************************************
370  *
371  * Returns a pointer to the next line of a multiline string buffer
372  *
373  * Given a pointer string, find the text following the next sequence
374  * of \r and \n characters. This has the effect of skipping blank
375  * lines as well
376  *
377  * Example:
378  *
379  * Given text as follows:
380  *
381  * ==============================
382  * This
383  * is
384  * a
385  * 
386  * multiline string buffer
387  * ==============================
388  *
389  * int i=0;
390  * char *str=NULL;
391  * char *ptr=NULL;
392  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
393  * ptr = str;
394  * while (ptr) {
395  *   printf("%d %s",i++,firstword(ptr));
396  *   ptr = strnl(ptr);
397  * }
398  * 
399  * Produces the following:
400  *
401  * 1 This
402  * 2 is
403  * 3 a
404  * 4 multiline
405  *
406  * NOTE: The 'firstword()' function is conceptual only and does not
407  *       exist in this package.
408  *
409  * NOTE: Although the second 'ptr' variable is not strictly needed in
410  *       this example, it is good practice with these utilities. Once
411  *       the * pointer is advance in this manner, it may no longer be
412  *       handled with * realloc(). So at the end of the code fragment
413  *       above, * strscpy(str,"foo") work perfectly fine, but
414  *       strscpy(ptr,"foo") will * cause the the program to crash with
415  *       a segmentation fault.
416  *
417  *****************************************************************************/
419 char *
420 strnl (char *str)
422         size_t len;
423         if (str == NULL)
424                 return NULL;
425         str = strpbrk (str, "\r\n");
426         if (str == NULL)
427                 return NULL;
428         len = strspn (str, "\r\n");
429         if (str[len] == '\0')
430                 return NULL;
431         str += len;
432         if (strlen (str) == 0)
433                 return NULL;
434         return str;
438 /******************************************************************************
439  *
440  * Like strscpy, except only the portion of the source string up to
441  * the provided delimiter is copied.
442  *
443  * Example:
444  *
445  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
446  * printf("%s\n",str);
447  *
448  * Produces:
449  *
450  *This is a line of te
451  *
452  *****************************************************************************/
454 char *
455 strpcpy (char *dest, const char *src, const char *str)
457         size_t len;
459         if (src)
460                 len = strcspn (src, str);
461         else
462                 return NULL;
464         if (dest == NULL || strlen (dest) < len)
465                 dest = realloc (dest, len + 1);
466         if (dest == NULL)
467                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
469         strncpy (dest, src, len);
470         dest[len] = '\0';
472         return dest;
477 /******************************************************************************
478  *
479  * Like strscat, except only the portion of the source string up to
480  * the provided delimiter is copied.
481  *
482  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
483  * str = strpcat(str,"This is a line of text with no trailing newline","x");
484  * printf("%s\n",str);
485  * 
486  *This is a line of texThis is a line of tex
487  *
488  *****************************************************************************/
490 char *
491 strpcat (char *dest, const char *src, const char *str)
493         size_t len, l2;
495         if (dest)
496                 len = strlen (dest);
497         else
498                 len = 0;
500         if (src) {
501                 l2 = strcspn (src, str);
502         }
503         else {
504                 return dest;
505         }
507         dest = realloc (dest, len + l2 + 1);
508         if (dest == NULL)
509                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
511         strncpy (dest + len, src, l2);
512         dest[len + l2] = '\0';
514         return dest;
517 /******************************************************************************
518  *
519  * Print perfdata in a standard format
520  *
521  ******************************************************************************/
523 char *perfdata (const char *label,
524  long int val,
525  const char *uom,
526  int warnp,
527  long int warn,
528  int critp,
529  long int crit,
530  int minp,
531  long int minv,
532  int maxp,
533  long int maxv)
535         char *data = NULL;
537         if (strpbrk (label, "'= "))
538                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
539         else
540                 asprintf (&data, "%s=%ld%s;", label, val, uom);
542         if (warnp)
543                 asprintf (&data, "%s%ld;", data, warn);
544         else
545                 asprintf (&data, "%s;", data);
547         if (critp)
548                 asprintf (&data, "%s%ld;", data, crit);
549         else
550                 asprintf (&data, "%s;", data);
552         if (minp)
553                 asprintf (&data, "%s%ld", data, minv);
555         if (maxp)
556                 asprintf (&data, "%s;%ld", data, maxv);
558         return data;
562 char *fperfdata (const char *label,
563  double val,
564  const char *uom,
565  int warnp,
566  double warn,
567  int critp,
568  double crit,
569  int minp,
570  double minv,
571  int maxp,
572  double maxv)
574         char *data = NULL;
576         if (strpbrk (label, "'= "))
577                 asprintf (&data, "'%s'=", label);
578         else
579                 asprintf (&data, "%s=", label);
581         asprintf (&data, "%s%f", data, val);
582         asprintf (&data, "%s%s;", data, uom);
584         if (warnp)
585                 asprintf (&data, "%s%f", data, warn);
587         asprintf (&data, "%s;", data);
589         if (critp)
590                 asprintf (&data, "%s%f", data, crit);
592         asprintf (&data, "%s;", data);
594         if (minp)
595                 asprintf (&data, "%s%f", data, minv);
597         if (maxp) {
598                 asprintf (&data, "%s;", data);
599                 asprintf (&data, "%s%f", data, maxv);
600         }
602         return data;