Code

Fix for regex input of '|', being output causing problems with Nagios' parsing of
[nagiosplug.git] / plugins / utils.c
1 /*****************************************************************************
2
3 * Library of useful functions for plugins
4
5 * License: GPL
6 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
7 * Copyright (c) 2002-2007 Nagios Plugin Development Team
8
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 * GNU General Public License for more details.
18
19 * You should have received a copy of the GNU General Public License
20 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22
23 *****************************************************************************/
25 #define LOCAL_TIMEOUT_ALARM_HANDLER
27 #include "common.h"
28 #include "utils.h"
29 #include "utils_base.h"
30 #include <stdarg.h>
31 #include <limits.h>
33 #include <arpa/inet.h>
35 extern void print_usage (void);
36 extern const char *progname;
38 #define STRLEN 64
39 #define TXTBLK 128
41 /* **************************************************************************
42  * max_state(STATE_x, STATE_y)
43  * compares STATE_x to  STATE_y and returns result based on the following
44  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
45  *
46  * Note that numerically the above does not hold
47  ****************************************************************************/
49 int
50 max_state (int a, int b)
51 {
52         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
53                 return STATE_CRITICAL;
54         else if (a == STATE_WARNING || b == STATE_WARNING)
55                 return STATE_WARNING;
56         else if (a == STATE_OK || b == STATE_OK)
57                 return STATE_OK;
58         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
59                 return STATE_UNKNOWN;
60         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
61                 return STATE_DEPENDENT;
62         else
63                 return max (a, b);
64 }
66 /* **************************************************************************
67  * max_state_alt(STATE_x, STATE_y)
68  * compares STATE_x to  STATE_y and returns result based on the following
69  * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
70  *
71  * The main difference between max_state_alt and max_state it that it doesn't
72  * allow setting a default to UNKNOWN. It will instead prioritixe any valid
73  * non-OK state.
74  ****************************************************************************/
76 int
77 max_state_alt (int a, int b)
78 {
79         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
80                 return STATE_CRITICAL;
81         else if (a == STATE_WARNING || b == STATE_WARNING)
82                 return STATE_WARNING;
83         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
84                 return STATE_UNKNOWN;
85         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
86                 return STATE_DEPENDENT;
87         else if (a == STATE_OK || b == STATE_OK)
88                 return STATE_OK;
89         else
90                 return max (a, b);
91 }
93 void usage (const char *msg)
94 {
95         printf ("%s\n", msg);
96         print_usage ();
97         exit (STATE_UNKNOWN);
98 }
100 void usage_va (const char *fmt, ...)
102         va_list ap;
103         printf("%s: ", progname);
104         va_start(ap, fmt);
105         vprintf(fmt, ap);
106         va_end(ap);
107         printf("\n");
108         exit (STATE_UNKNOWN);
111 void usage2(const char *msg, const char *arg)
113         printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
114         print_usage ();
115         exit (STATE_UNKNOWN);
118 void
119 usage3 (const char *msg, int arg)
121         printf ("%s: %s - %c\n", progname, msg, arg);
122         print_usage();
123         exit (STATE_UNKNOWN);
126 void
127 usage4 (const char *msg)
129         printf ("%s: %s\n", progname, msg);
130         print_usage();
131         exit (STATE_UNKNOWN);
134 void
135 usage5 (void)
137         print_usage();
138         exit (STATE_UNKNOWN);
141 void
142 print_revision (const char *command_name, const char *revision)
144         char plugin_revision[STRLEN];
146         printf ("%s v%s (%s %s)\n",
147                  command_name, revision, PACKAGE, VERSION);
150 const char *
151 state_text (int result)
153         switch (result) {
154         case STATE_OK:
155                 return "OK";
156         case STATE_WARNING:
157                 return "WARNING";
158         case STATE_CRITICAL:
159                 return "CRITICAL";
160         case STATE_DEPENDENT:
161                 return "DEPENDENT";
162         default:
163                 return "UNKNOWN";
164         }
167 void
168 timeout_alarm_handler (int signo)
170         if (signo == SIGALRM) {
171                 printf (_("%s - Plugin timed out after %d seconds\n"),
172                                                 state_text(timeout_state), timeout_interval);
173                 exit (timeout_state);
174         }
177 int
178 is_numeric (char *number)
180         char tmp[1];
181         float x;
183         if (!number)
184                 return FALSE;
185         else if (sscanf (number, "%f%c", &x, tmp) == 1)
186                 return TRUE;
187         else
188                 return FALSE;
191 int
192 is_positive (char *number)
194         if (is_numeric (number) && atof (number) > 0.0)
195                 return TRUE;
196         else
197                 return FALSE;
200 int
201 is_negative (char *number)
203         if (is_numeric (number) && atof (number) < 0.0)
204                 return TRUE;
205         else
206                 return FALSE;
209 int
210 is_nonnegative (char *number)
212         if (is_numeric (number) && atof (number) >= 0.0)
213                 return TRUE;
214         else
215                 return FALSE;
218 int
219 is_percentage (char *number)
221         int x;
222         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
223                 return TRUE;
224         else
225                 return FALSE;
228 int
229 is_integer (char *number)
231         long int n;
233         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
234                 return FALSE;
236         n = strtol (number, NULL, 10);
238         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
239                 return TRUE;
240         else
241                 return FALSE;
244 int
245 is_intpos (char *number)
247         if (is_integer (number) && atoi (number) > 0)
248                 return TRUE;
249         else
250                 return FALSE;
253 int
254 is_intneg (char *number)
256         if (is_integer (number) && atoi (number) < 0)
257                 return TRUE;
258         else
259                 return FALSE;
262 int
263 is_intnonneg (char *number)
265         if (is_integer (number) && atoi (number) >= 0)
266                 return TRUE;
267         else
268                 return FALSE;
271 int
272 is_intpercent (char *number)
274         int i;
275         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
276                 return TRUE;
277         else
278                 return FALSE;
281 int
282 is_option (char *str)
284         if (!str)
285                 return FALSE;
286         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
287                 return TRUE;
288         else
289                 return FALSE;
292 #ifdef NEED_GETTIMEOFDAY
293 int
294 gettimeofday (struct timeval *tv, struct timezone *tz)
296         tv->tv_usec = 0;
297         tv->tv_sec = (long) time ((time_t) 0);
299 #endif
303 double
304 delta_time (struct timeval tv)
306         struct timeval now;
308         gettimeofday (&now, NULL);
309         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
314 long
315 deltime (struct timeval tv)
317         struct timeval now;
318         gettimeofday (&now, NULL);
319         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
325 void
326 strip (char *buffer)
328         size_t x;
329         int i;
331         for (x = strlen (buffer); x >= 1; x--) {
332                 i = x - 1;
333                 if (buffer[i] == ' ' ||
334                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
335                         buffer[i] = '\0';
336                 else
337                         break;
338         }
339         return;
343 /******************************************************************************
344  *
345  * Copies one string to another. Any previously existing data in
346  * the destination string is lost.
347  *
348  * Example:
349  *
350  * char *str=NULL;
351  * str = strscpy("This is a line of text with no trailing newline");
352  *
353  *****************************************************************************/
355 char *
356 strscpy (char *dest, const char *src)
358         if (src == NULL)
359                 return NULL;
361         asprintf (&dest, "%s", src);
363         return dest;
368 /******************************************************************************
369  *
370  * Returns a pointer to the next line of a multiline string buffer
371  *
372  * Given a pointer string, find the text following the next sequence
373  * of \r and \n characters. This has the effect of skipping blank
374  * lines as well
375  *
376  * Example:
377  *
378  * Given text as follows:
379  *
380  * ==============================
381  * This
382  * is
383  * a
384  * 
385  * multiline string buffer
386  * ==============================
387  *
388  * int i=0;
389  * char *str=NULL;
390  * char *ptr=NULL;
391  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
392  * ptr = str;
393  * while (ptr) {
394  *   printf("%d %s",i++,firstword(ptr));
395  *   ptr = strnl(ptr);
396  * }
397  * 
398  * Produces the following:
399  *
400  * 1 This
401  * 2 is
402  * 3 a
403  * 4 multiline
404  *
405  * NOTE: The 'firstword()' function is conceptual only and does not
406  *       exist in this package.
407  *
408  * NOTE: Although the second 'ptr' variable is not strictly needed in
409  *       this example, it is good practice with these utilities. Once
410  *       the * pointer is advance in this manner, it may no longer be
411  *       handled with * realloc(). So at the end of the code fragment
412  *       above, * strscpy(str,"foo") work perfectly fine, but
413  *       strscpy(ptr,"foo") will * cause the the program to crash with
414  *       a segmentation fault.
415  *
416  *****************************************************************************/
418 char *
419 strnl (char *str)
421         size_t len;
422         if (str == NULL)
423                 return NULL;
424         str = strpbrk (str, "\r\n");
425         if (str == NULL)
426                 return NULL;
427         len = strspn (str, "\r\n");
428         if (str[len] == '\0')
429                 return NULL;
430         str += len;
431         if (strlen (str) == 0)
432                 return NULL;
433         return str;
437 /******************************************************************************
438  *
439  * Like strscpy, except only the portion of the source string up to
440  * the provided delimiter is copied.
441  *
442  * Example:
443  *
444  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
445  * printf("%s\n",str);
446  *
447  * Produces:
448  *
449  *This is a line of te
450  *
451  *****************************************************************************/
453 char *
454 strpcpy (char *dest, const char *src, const char *str)
456         size_t len;
458         if (src)
459                 len = strcspn (src, str);
460         else
461                 return NULL;
463         if (dest == NULL || strlen (dest) < len)
464                 dest = realloc (dest, len + 1);
465         if (dest == NULL)
466                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
468         strncpy (dest, src, len);
469         dest[len] = '\0';
471         return dest;
476 /******************************************************************************
477  *
478  * Like strscat, except only the portion of the source string up to
479  * the provided delimiter is copied.
480  *
481  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
482  * str = strpcat(str,"This is a line of text with no trailing newline","x");
483  * printf("%s\n",str);
484  * 
485  *This is a line of texThis is a line of tex
486  *
487  *****************************************************************************/
489 char *
490 strpcat (char *dest, const char *src, const char *str)
492         size_t len, l2;
494         if (dest)
495                 len = strlen (dest);
496         else
497                 len = 0;
499         if (src) {
500                 l2 = strcspn (src, str);
501         }
502         else {
503                 return dest;
504         }
506         dest = realloc (dest, len + l2 + 1);
507         if (dest == NULL)
508                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
510         strncpy (dest + len, src, l2);
511         dest[len + l2] = '\0';
513         return dest;
516 /******************************************************************************
517  *
518  * Print perfdata in a standard format
519  *
520  ******************************************************************************/
522 char *perfdata (const char *label,
523  long int val,
524  const char *uom,
525  int warnp,
526  long int warn,
527  int critp,
528  long int crit,
529  int minp,
530  long int minv,
531  int maxp,
532  long int maxv)
534         char *data = NULL;
536         if (strpbrk (label, "'= "))
537                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
538         else
539                 asprintf (&data, "%s=%ld%s;", label, val, uom);
541         if (warnp)
542                 asprintf (&data, "%s%ld;", data, warn);
543         else
544                 asprintf (&data, "%s;", data);
546         if (critp)
547                 asprintf (&data, "%s%ld;", data, crit);
548         else
549                 asprintf (&data, "%s;", data);
551         if (minp)
552                 asprintf (&data, "%s%ld", data, minv);
554         if (maxp)
555                 asprintf (&data, "%s;%ld", data, maxv);
557         return data;
561 char *fperfdata (const char *label,
562  double val,
563  const char *uom,
564  int warnp,
565  double warn,
566  int critp,
567  double crit,
568  int minp,
569  double minv,
570  int maxp,
571  double maxv)
573         char *data = NULL;
575         if (strpbrk (label, "'= "))
576                 asprintf (&data, "'%s'=", label);
577         else
578                 asprintf (&data, "%s=", label);
580         asprintf (&data, "%s%f", data, val);
581         asprintf (&data, "%s%s;", data, uom);
583         if (warnp)
584                 asprintf (&data, "%s%f", data, warn);
586         asprintf (&data, "%s;", data);
588         if (critp)
589                 asprintf (&data, "%s%f", data, crit);
591         asprintf (&data, "%s;", data);
593         if (minp)
594                 asprintf (&data, "%s%f", data, minv);
596         if (maxp) {
597                 asprintf (&data, "%s;", data);
598                 asprintf (&data, "%s%f", data, maxv);
599         }
601         return data;