Code

b9a19d3fe0c2f8f39d0fd1f5c9bfbd30c1279448
[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 #define LOCAL_TIMEOUT_ALARM_HANDLER
16 #include "common.h"
17 #include "utils.h"
18 #include <stdarg.h>
19 #include <limits.h>
21 #include <arpa/inet.h>
23 extern void print_usage (void);
24 extern const char *progname;
26 #define STRLEN 64
27 #define TXTBLK 128
29 /* **************************************************************************
30  * max_state(STATE_x, STATE_y)
31  * compares STATE_x to  STATE_y and returns result based on the following
32  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
33  *
34  * Note that numerically the above does not hold
35  ****************************************************************************/
37 int
38 max_state (int a, int b)
39 {
40         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
41                 return STATE_CRITICAL;
42         else if (a == STATE_WARNING || b == STATE_WARNING)
43                 return STATE_WARNING;
44         else if (a == STATE_OK || b == STATE_OK)
45                 return STATE_OK;
46         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
47                 return STATE_UNKNOWN;
48         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
49                 return STATE_DEPENDENT;
50         else
51                 return max (a, b);
52 }
54 void usage (const char *msg)
55 {
56         printf ("%s\n", msg);
57         print_usage ();
58         exit (STATE_UNKNOWN);
59 }
61 void usage2(const char *msg, const char *arg)
62 {
63         printf ("%s: %s - %s\n",progname,msg,arg);
64         print_usage ();
65         exit (STATE_UNKNOWN);
66 }
68 void
69 usage3 (const char *msg, int arg)
70 {
71         printf ("%s: %s - %c\n", progname, msg, arg);
72         print_usage();
73         exit (STATE_UNKNOWN);
74 }
76 void
77 usage4 (const char *msg)
78 {
79         printf ("%s: %s\n", progname, msg);
80         print_usage();
81         exit (STATE_UNKNOWN);
82 }
84 char *
85 clean_revstring (const char *revstring)
86 {
87         char plugin_revision[STRLEN];
88         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
89                 return strscpy (NULL, plugin_revision);
90         else
91           return strscpy (NULL, "N/A");
92 }
94 void
95 print_revision (const char *command_name, const char *revision_string)
96 {
97         char plugin_revision[STRLEN];
99         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
100                 strncpy (plugin_revision, "N/A", STRLEN);
101         printf ("%s (%s %s) %s\n",
102                                         command_name, PACKAGE, VERSION, plugin_revision);
105 const char *
106 state_text (int result)
108         switch (result) {
109         case STATE_OK:
110                 return "OK";
111         case STATE_WARNING:
112                 return "WARNING";
113         case STATE_CRITICAL:
114                 return "CRITICAL";
115         case STATE_DEPENDENT:
116                 return "DEPENDENT";
117         default:
118                 return "UNKNOWN";
119         }
122 void
123 die (int result, const char *fmt, ...)
125         va_list ap;
126         va_start (ap, fmt);
127         vprintf (fmt, ap);
128         va_end (ap);
129         exit (result);
132 void
133 timeout_alarm_handler (int signo)
135         if (signo == SIGALRM) {
136                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
137                                                 timeout_interval);
138                 exit (STATE_CRITICAL);
139         }
142 int
143 is_numeric (char *number)
145         char tmp[1];
146         float x;
148         if (!number)
149                 return FALSE;
150         else if (sscanf (number, "%f%c", &x, tmp) == 1)
151                 return TRUE;
152         else
153                 return FALSE;
156 int
157 is_positive (char *number)
159         if (is_numeric (number) && atof (number) > 0.0)
160                 return TRUE;
161         else
162                 return FALSE;
165 int
166 is_negative (char *number)
168         if (is_numeric (number) && atof (number) < 0.0)
169                 return TRUE;
170         else
171                 return FALSE;
174 int
175 is_nonnegative (char *number)
177         if (is_numeric (number) && atof (number) >= 0.0)
178                 return TRUE;
179         else
180                 return FALSE;
183 int
184 is_percentage (char *number)
186         int x;
187         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
188                 return TRUE;
189         else
190                 return FALSE;
193 int
194 is_integer (char *number)
196         long int n;
198         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
199                 return FALSE;
201         n = strtol (number, NULL, 10);
203         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
204                 return TRUE;
205         else
206                 return FALSE;
209 int
210 is_intpos (char *number)
212         if (is_integer (number) && atoi (number) > 0)
213                 return TRUE;
214         else
215                 return FALSE;
218 int
219 is_intneg (char *number)
221         if (is_integer (number) && atoi (number) < 0)
222                 return TRUE;
223         else
224                 return FALSE;
227 int
228 is_intnonneg (char *number)
230         if (is_integer (number) && atoi (number) >= 0)
231                 return TRUE;
232         else
233                 return FALSE;
236 int
237 is_intpercent (char *number)
239         int i;
240         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
241                 return TRUE;
242         else
243                 return FALSE;
246 int
247 is_option (char *str)
249         if (!str)
250                 return FALSE;
251         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
252                 return TRUE;
253         else
254                 return FALSE;
259 #ifdef NEED_GETTIMEOFDAY
260 int
261 gettimeofday (struct timeval *tv, struct timezone *tz)
263         tv->tv_usec = 0;
264         tv->tv_sec = (long) time ((time_t) 0);
266 #endif
270 double
271 delta_time (struct timeval tv)
273         struct timeval now;
275         gettimeofday (&now, NULL);
276         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
281 long
282 deltime (struct timeval tv)
284         struct timeval now;
285         gettimeofday (&now, NULL);
286         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
292 void
293 strip (char *buffer)
295         size_t x;
296         int i;
298         for (x = strlen (buffer); x >= 1; x--) {
299                 i = x - 1;
300                 if (buffer[i] == ' ' ||
301                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
302                         buffer[i] = '\0';
303                 else
304                         break;
305         }
306         return;
310 /******************************************************************************
311  *
312  * Copies one string to another. Any previously existing data in
313  * the destination string is lost.
314  *
315  * Example:
316  *
317  * char *str=NULL;
318  * str = strscpy("This is a line of text with no trailing newline");
319  *
320  *****************************************************************************/
322 char *
323 strscpy (char *dest, const char *src)
325         if (src == NULL)
326                 return NULL;
328         asprintf (&dest, "%s", src);
330         return dest;
335 /******************************************************************************
336  *
337  * Returns a pointer to the next line of a multiline string buffer
338  *
339  * Given a pointer string, find the text following the next sequence
340  * of \r and \n characters. This has the effect of skipping blank
341  * lines as well
342  *
343  * Example:
344  *
345  * Given text as follows:
346  *
347  * ==============================
348  * This
349  * is
350  * a
351  * 
352  * multiline string buffer
353  * ==============================
354  *
355  * int i=0;
356  * char *str=NULL;
357  * char *ptr=NULL;
358  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
359  * ptr = str;
360  * while (ptr) {
361  *   printf("%d %s",i++,firstword(ptr));
362  *   ptr = strnl(ptr);
363  * }
364  * 
365  * Produces the following:
366  *
367  * 1 This
368  * 2 is
369  * 3 a
370  * 4 multiline
371  *
372  * NOTE: The 'firstword()' function is conceptual only and does not
373  *       exist in this package.
374  *
375  * NOTE: Although the second 'ptr' variable is not strictly needed in
376  *       this example, it is good practice with these utilities. Once
377  *       the * pointer is advance in this manner, it may no longer be
378  *       handled with * realloc(). So at the end of the code fragment
379  *       above, * strscpy(str,"foo") work perfectly fine, but
380  *       strscpy(ptr,"foo") will * cause the the program to crash with
381  *       a segmentation fault.
382  *
383  *****************************************************************************/
385 char *
386 strnl (char *str)
388         size_t len;
389         if (str == NULL)
390                 return NULL;
391         str = strpbrk (str, "\r\n");
392         if (str == NULL)
393                 return NULL;
394         len = strspn (str, "\r\n");
395         if (str[len] == '\0')
396                 return NULL;
397         str += len;
398         if (strlen (str) == 0)
399                 return NULL;
400         return str;
404 /******************************************************************************
405  *
406  * Like strscpy, except only the portion of the source string up to
407  * the provided delimiter is copied.
408  *
409  * Example:
410  *
411  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
412  * printf("%s\n",str);
413  *
414  * Produces:
415  *
416  *This is a line of te
417  *
418  *****************************************************************************/
420 char *
421 strpcpy (char *dest, const char *src, const char *str)
423         size_t len;
425         if (src)
426                 len = strcspn (src, str);
427         else
428                 return NULL;
430         if (dest == NULL || strlen (dest) < len)
431                 dest = realloc (dest, len + 1);
432         if (dest == NULL)
433                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
435         strncpy (dest, src, len);
436         dest[len] = '\0';
438         return dest;
443 /******************************************************************************
444  *
445  * Like strscat, except only the portion of the source string up to
446  * the provided delimiter is copied.
447  *
448  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
449  * str = strpcat(str,"This is a line of text with no trailing newline","x");
450  * printf("%s\n",str);
451  * 
452  *This is a line of texThis is a line of tex
453  *
454  *****************************************************************************/
456 char *
457 strpcat (char *dest, const char *src, const char *str)
459         size_t len, l2;
461         if (dest)
462                 len = strlen (dest);
463         else
464                 len = 0;
466         if (src) {
467                 l2 = strcspn (src, str);
468         }
469         else {
470                 return dest;
471         }
473         dest = realloc (dest, len + l2 + 1);
474         if (dest == NULL)
475                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
477         strncpy (dest + len, src, l2);
478         dest[len + l2] = '\0';
480         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;