Code

7e1e58a20060187204b4fb523632c5d418465a2e
[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 void
98 usage5 (void)
99 {
100         print_usage();
101         exit (STATE_UNKNOWN);
104 char *
105 clean_revstring (const char *revstring)
107         char plugin_revision[STRLEN];
108         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
109                 return strscpy (NULL, plugin_revision);
110         else
111           return strscpy (NULL, "N/A");
114 void
115 print_revision (const char *command_name, const char *revision_string)
117         char plugin_revision[STRLEN];
119         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
120                 strncpy (plugin_revision, "N/A", STRLEN);
121         printf ("%s (%s %s) %s\n",
122                                         command_name, PACKAGE, VERSION, plugin_revision);
125 const char *
126 state_text (int result)
128         switch (result) {
129         case STATE_OK:
130                 return "OK";
131         case STATE_WARNING:
132                 return "WARNING";
133         case STATE_CRITICAL:
134                 return "CRITICAL";
135         case STATE_DEPENDENT:
136                 return "DEPENDENT";
137         default:
138                 return "UNKNOWN";
139         }
142 void
143 timeout_alarm_handler (int signo)
145         if (signo == SIGALRM) {
146                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
147                                                 timeout_interval);
148                 exit (STATE_CRITICAL);
149         }
152 int
153 is_numeric (char *number)
155         char tmp[1];
156         float x;
158         if (!number)
159                 return FALSE;
160         else if (sscanf (number, "%f%c", &x, tmp) == 1)
161                 return TRUE;
162         else
163                 return FALSE;
166 int
167 is_positive (char *number)
169         if (is_numeric (number) && atof (number) > 0.0)
170                 return TRUE;
171         else
172                 return FALSE;
175 int
176 is_negative (char *number)
178         if (is_numeric (number) && atof (number) < 0.0)
179                 return TRUE;
180         else
181                 return FALSE;
184 int
185 is_nonnegative (char *number)
187         if (is_numeric (number) && atof (number) >= 0.0)
188                 return TRUE;
189         else
190                 return FALSE;
193 int
194 is_percentage (char *number)
196         int x;
197         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
198                 return TRUE;
199         else
200                 return FALSE;
203 int
204 is_integer (char *number)
206         long int n;
208         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
209                 return FALSE;
211         n = strtol (number, NULL, 10);
213         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
214                 return TRUE;
215         else
216                 return FALSE;
219 int
220 is_intpos (char *number)
222         if (is_integer (number) && atoi (number) > 0)
223                 return TRUE;
224         else
225                 return FALSE;
228 int
229 is_intneg (char *number)
231         if (is_integer (number) && atoi (number) < 0)
232                 return TRUE;
233         else
234                 return FALSE;
237 int
238 is_intnonneg (char *number)
240         if (is_integer (number) && atoi (number) >= 0)
241                 return TRUE;
242         else
243                 return FALSE;
246 int
247 is_intpercent (char *number)
249         int i;
250         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
251                 return TRUE;
252         else
253                 return FALSE;
256 int
257 is_option (char *str)
259         if (!str)
260                 return FALSE;
261         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
262                 return TRUE;
263         else
264                 return FALSE;
267 #ifdef NEED_GETTIMEOFDAY
268 int
269 gettimeofday (struct timeval *tv, struct timezone *tz)
271         tv->tv_usec = 0;
272         tv->tv_sec = (long) time ((time_t) 0);
274 #endif
278 double
279 delta_time (struct timeval tv)
281         struct timeval now;
283         gettimeofday (&now, NULL);
284         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
289 long
290 deltime (struct timeval tv)
292         struct timeval now;
293         gettimeofday (&now, NULL);
294         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
300 void
301 strip (char *buffer)
303         size_t x;
304         int i;
306         for (x = strlen (buffer); x >= 1; x--) {
307                 i = x - 1;
308                 if (buffer[i] == ' ' ||
309                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
310                         buffer[i] = '\0';
311                 else
312                         break;
313         }
314         return;
318 /******************************************************************************
319  *
320  * Copies one string to another. Any previously existing data in
321  * the destination string is lost.
322  *
323  * Example:
324  *
325  * char *str=NULL;
326  * str = strscpy("This is a line of text with no trailing newline");
327  *
328  *****************************************************************************/
330 char *
331 strscpy (char *dest, const char *src)
333         if (src == NULL)
334                 return NULL;
336         asprintf (&dest, "%s", src);
338         return dest;
343 /******************************************************************************
344  *
345  * Returns a pointer to the next line of a multiline string buffer
346  *
347  * Given a pointer string, find the text following the next sequence
348  * of \r and \n characters. This has the effect of skipping blank
349  * lines as well
350  *
351  * Example:
352  *
353  * Given text as follows:
354  *
355  * ==============================
356  * This
357  * is
358  * a
359  * 
360  * multiline string buffer
361  * ==============================
362  *
363  * int i=0;
364  * char *str=NULL;
365  * char *ptr=NULL;
366  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
367  * ptr = str;
368  * while (ptr) {
369  *   printf("%d %s",i++,firstword(ptr));
370  *   ptr = strnl(ptr);
371  * }
372  * 
373  * Produces the following:
374  *
375  * 1 This
376  * 2 is
377  * 3 a
378  * 4 multiline
379  *
380  * NOTE: The 'firstword()' function is conceptual only and does not
381  *       exist in this package.
382  *
383  * NOTE: Although the second 'ptr' variable is not strictly needed in
384  *       this example, it is good practice with these utilities. Once
385  *       the * pointer is advance in this manner, it may no longer be
386  *       handled with * realloc(). So at the end of the code fragment
387  *       above, * strscpy(str,"foo") work perfectly fine, but
388  *       strscpy(ptr,"foo") will * cause the the program to crash with
389  *       a segmentation fault.
390  *
391  *****************************************************************************/
393 char *
394 strnl (char *str)
396         size_t len;
397         if (str == NULL)
398                 return NULL;
399         str = strpbrk (str, "\r\n");
400         if (str == NULL)
401                 return NULL;
402         len = strspn (str, "\r\n");
403         if (str[len] == '\0')
404                 return NULL;
405         str += len;
406         if (strlen (str) == 0)
407                 return NULL;
408         return str;
412 /******************************************************************************
413  *
414  * Like strscpy, except only the portion of the source string up to
415  * the provided delimiter is copied.
416  *
417  * Example:
418  *
419  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
420  * printf("%s\n",str);
421  *
422  * Produces:
423  *
424  *This is a line of te
425  *
426  *****************************************************************************/
428 char *
429 strpcpy (char *dest, const char *src, const char *str)
431         size_t len;
433         if (src)
434                 len = strcspn (src, str);
435         else
436                 return NULL;
438         if (dest == NULL || strlen (dest) < len)
439                 dest = realloc (dest, len + 1);
440         if (dest == NULL)
441                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
443         strncpy (dest, src, len);
444         dest[len] = '\0';
446         return dest;
451 /******************************************************************************
452  *
453  * Like strscat, except only the portion of the source string up to
454  * the provided delimiter is copied.
455  *
456  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
457  * str = strpcat(str,"This is a line of text with no trailing newline","x");
458  * printf("%s\n",str);
459  * 
460  *This is a line of texThis is a line of tex
461  *
462  *****************************************************************************/
464 char *
465 strpcat (char *dest, const char *src, const char *str)
467         size_t len, l2;
469         if (dest)
470                 len = strlen (dest);
471         else
472                 len = 0;
474         if (src) {
475                 l2 = strcspn (src, str);
476         }
477         else {
478                 return dest;
479         }
481         dest = realloc (dest, len + l2 + 1);
482         if (dest == NULL)
483                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
485         strncpy (dest + len, src, l2);
486         dest[len + l2] = '\0';
488         return dest;
491 /******************************************************************************
492  *
493  * Print perfdata in a standard format
494  *
495  ******************************************************************************/
497 char *perfdata (const char *label,
498  long int val,
499  const char *uom,
500  int warnp,
501  long int warn,
502  int critp,
503  long int crit,
504  int minp,
505  long int minv,
506  int maxp,
507  long int maxv)
509         char *data = NULL;
511         if (strpbrk (label, "'= "))
512                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
513         else
514                 asprintf (&data, "%s=%ld%s;", label, val, uom);
516         if (warnp)
517                 asprintf (&data, "%s%ld;", data, warn);
518         else
519                 asprintf (&data, "%s;", data);
521         if (critp)
522                 asprintf (&data, "%s%ld;", data, crit);
523         else
524                 asprintf (&data, "%s;", data);
526         if (minp)
527                 asprintf (&data, "%s%ld", data, minv);
529         if (maxp)
530                 asprintf (&data, "%s;%ld", data, maxv);
532         return data;
536 char *fperfdata (const char *label,
537  double val,
538  const char *uom,
539  int warnp,
540  double warn,
541  int critp,
542  double crit,
543  int minp,
544  double minv,
545  int maxp,
546  double maxv)
548         char *data = NULL;
550         if (strpbrk (label, "'= "))
551                 asprintf (&data, "'%s'=", label);
552         else
553                 asprintf (&data, "%s=", label);
555         asprintf (&data, "%s%f", data, val);
556         asprintf (&data, "%s%s;", data, uom);
558         if (warnp)
559                 asprintf (&data, "%s%f", data, warn);
561         asprintf (&data, "%s;", data);
563         if (critp)
564                 asprintf (&data, "%s%f", data, crit);
566         asprintf (&data, "%s;", data);
568         if (minp)
569                 asprintf (&data, "%s%f", data, minv);
571         if (maxp) {
572                 asprintf (&data, "%s;", data);
573                 asprintf (&data, "%s%f", data, maxv);
574         }
576         return data;