Code

initial merging of ae's np_runcmd code into selected plugins.
[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 usage_va (const char *fmt, ...)
62 {
63         va_list ap;
64         printf("%s: ", progname);
65         va_start(ap, fmt);
66         vprintf(fmt, ap);
67         va_end(ap);
68         printf("\n");
69         exit (STATE_UNKNOWN);
70 }
72 void usage2(const char *msg, const char *arg)
73 {
74         printf ("%s: %s - %s\n",progname,msg,arg);
75         print_usage ();
76         exit (STATE_UNKNOWN);
77 }
79 void
80 usage3 (const char *msg, int arg)
81 {
82         printf ("%s: %s - %c\n", progname, msg, arg);
83         print_usage();
84         exit (STATE_UNKNOWN);
85 }
87 void
88 usage4 (const char *msg)
89 {
90         printf ("%s: %s\n", progname, msg);
91         print_usage();
92         exit (STATE_UNKNOWN);
93 }
95 char *
96 clean_revstring (const char *revstring)
97 {
98         char plugin_revision[STRLEN];
99         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
100                 return strscpy (NULL, plugin_revision);
101         else
102           return strscpy (NULL, "N/A");
105 void
106 print_revision (const char *command_name, const char *revision_string)
108         char plugin_revision[STRLEN];
110         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
111                 strncpy (plugin_revision, "N/A", STRLEN);
112         printf ("%s (%s %s) %s\n",
113                                         command_name, PACKAGE, VERSION, plugin_revision);
116 const char *
117 state_text (int result)
119         switch (result) {
120         case STATE_OK:
121                 return "OK";
122         case STATE_WARNING:
123                 return "WARNING";
124         case STATE_CRITICAL:
125                 return "CRITICAL";
126         case STATE_DEPENDENT:
127                 return "DEPENDENT";
128         default:
129                 return "UNKNOWN";
130         }
133 void
134 die (int result, const char *fmt, ...)
136         va_list ap;
137         va_start (ap, fmt);
138         vprintf (fmt, ap);
139         va_end (ap);
140         exit (result);
143 void
144 timeout_alarm_handler (int signo)
146         if (signo == SIGALRM) {
147                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
148                                                 timeout_interval);
149                 exit (STATE_CRITICAL);
150         }
153 int
154 is_numeric (char *number)
156         char tmp[1];
157         float x;
159         if (!number)
160                 return FALSE;
161         else if (sscanf (number, "%f%c", &x, tmp) == 1)
162                 return TRUE;
163         else
164                 return FALSE;
167 int
168 is_positive (char *number)
170         if (is_numeric (number) && atof (number) > 0.0)
171                 return TRUE;
172         else
173                 return FALSE;
176 int
177 is_negative (char *number)
179         if (is_numeric (number) && atof (number) < 0.0)
180                 return TRUE;
181         else
182                 return FALSE;
185 int
186 is_nonnegative (char *number)
188         if (is_numeric (number) && atof (number) >= 0.0)
189                 return TRUE;
190         else
191                 return FALSE;
194 int
195 is_percentage (char *number)
197         int x;
198         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
199                 return TRUE;
200         else
201                 return FALSE;
204 int
205 is_integer (char *number)
207         long int n;
209         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
210                 return FALSE;
212         n = strtol (number, NULL, 10);
214         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
215                 return TRUE;
216         else
217                 return FALSE;
220 int
221 is_intpos (char *number)
223         if (is_integer (number) && atoi (number) > 0)
224                 return TRUE;
225         else
226                 return FALSE;
229 int
230 is_intneg (char *number)
232         if (is_integer (number) && atoi (number) < 0)
233                 return TRUE;
234         else
235                 return FALSE;
238 int
239 is_intnonneg (char *number)
241         if (is_integer (number) && atoi (number) >= 0)
242                 return TRUE;
243         else
244                 return FALSE;
247 int
248 is_intpercent (char *number)
250         int i;
251         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
252                 return TRUE;
253         else
254                 return FALSE;
257 int
258 is_option (char *str)
260         if (!str)
261                 return FALSE;
262         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
263                 return TRUE;
264         else
265                 return FALSE;
270 #ifdef NEED_GETTIMEOFDAY
271 int
272 gettimeofday (struct timeval *tv, struct timezone *tz)
274         tv->tv_usec = 0;
275         tv->tv_sec = (long) time ((time_t) 0);
277 #endif
281 double
282 delta_time (struct timeval tv)
284         struct timeval now;
286         gettimeofday (&now, NULL);
287         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
292 long
293 deltime (struct timeval tv)
295         struct timeval now;
296         gettimeofday (&now, NULL);
297         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
303 void
304 strip (char *buffer)
306         size_t x;
307         int i;
309         for (x = strlen (buffer); x >= 1; x--) {
310                 i = x - 1;
311                 if (buffer[i] == ' ' ||
312                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
313                         buffer[i] = '\0';
314                 else
315                         break;
316         }
317         return;
321 /******************************************************************************
322  *
323  * Copies one string to another. Any previously existing data in
324  * the destination string is lost.
325  *
326  * Example:
327  *
328  * char *str=NULL;
329  * str = strscpy("This is a line of text with no trailing newline");
330  *
331  *****************************************************************************/
333 char *
334 strscpy (char *dest, const char *src)
336         if (src == NULL)
337                 return NULL;
339         asprintf (&dest, "%s", src);
341         return dest;
346 /******************************************************************************
347  *
348  * Returns a pointer to the next line of a multiline string buffer
349  *
350  * Given a pointer string, find the text following the next sequence
351  * of \r and \n characters. This has the effect of skipping blank
352  * lines as well
353  *
354  * Example:
355  *
356  * Given text as follows:
357  *
358  * ==============================
359  * This
360  * is
361  * a
362  * 
363  * multiline string buffer
364  * ==============================
365  *
366  * int i=0;
367  * char *str=NULL;
368  * char *ptr=NULL;
369  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
370  * ptr = str;
371  * while (ptr) {
372  *   printf("%d %s",i++,firstword(ptr));
373  *   ptr = strnl(ptr);
374  * }
375  * 
376  * Produces the following:
377  *
378  * 1 This
379  * 2 is
380  * 3 a
381  * 4 multiline
382  *
383  * NOTE: The 'firstword()' function is conceptual only and does not
384  *       exist in this package.
385  *
386  * NOTE: Although the second 'ptr' variable is not strictly needed in
387  *       this example, it is good practice with these utilities. Once
388  *       the * pointer is advance in this manner, it may no longer be
389  *       handled with * realloc(). So at the end of the code fragment
390  *       above, * strscpy(str,"foo") work perfectly fine, but
391  *       strscpy(ptr,"foo") will * cause the the program to crash with
392  *       a segmentation fault.
393  *
394  *****************************************************************************/
396 char *
397 strnl (char *str)
399         size_t len;
400         if (str == NULL)
401                 return NULL;
402         str = strpbrk (str, "\r\n");
403         if (str == NULL)
404                 return NULL;
405         len = strspn (str, "\r\n");
406         if (str[len] == '\0')
407                 return NULL;
408         str += len;
409         if (strlen (str) == 0)
410                 return NULL;
411         return str;
415 /******************************************************************************
416  *
417  * Like strscpy, except only the portion of the source string up to
418  * the provided delimiter is copied.
419  *
420  * Example:
421  *
422  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
423  * printf("%s\n",str);
424  *
425  * Produces:
426  *
427  *This is a line of te
428  *
429  *****************************************************************************/
431 char *
432 strpcpy (char *dest, const char *src, const char *str)
434         size_t len;
436         if (src)
437                 len = strcspn (src, str);
438         else
439                 return NULL;
441         if (dest == NULL || strlen (dest) < len)
442                 dest = realloc (dest, len + 1);
443         if (dest == NULL)
444                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
446         strncpy (dest, src, len);
447         dest[len] = '\0';
449         return dest;
454 /******************************************************************************
455  *
456  * Like strscat, except only the portion of the source string up to
457  * the provided delimiter is copied.
458  *
459  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
460  * str = strpcat(str,"This is a line of text with no trailing newline","x");
461  * printf("%s\n",str);
462  * 
463  *This is a line of texThis is a line of tex
464  *
465  *****************************************************************************/
467 char *
468 strpcat (char *dest, const char *src, const char *str)
470         size_t len, l2;
472         if (dest)
473                 len = strlen (dest);
474         else
475                 len = 0;
477         if (src) {
478                 l2 = strcspn (src, str);
479         }
480         else {
481                 return dest;
482         }
484         dest = realloc (dest, len + l2 + 1);
485         if (dest == NULL)
486                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
488         strncpy (dest + len, src, l2);
489         dest[len + l2] = '\0';
491         return dest;
495 /******************************************************************************
496  *
497  * Print perfdata in a standard format
498  *
499  ******************************************************************************/
501 char *perfdata (const char *label,
502  long int val,
503  const char *uom,
504  int warnp,
505  long int warn,
506  int critp,
507  long int crit,
508  int minp,
509  long int minv,
510  int maxp,
511  long int maxv)
513         char *data = NULL;
515         if (strpbrk (label, "'= "))
516                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
517         else
518                 asprintf (&data, "%s=%ld%s;", label, val, uom);
520         if (warnp)
521                 asprintf (&data, "%s%ld;", data, warn);
522         else
523                 asprintf (&data, "%s;", data);
525         if (critp)
526                 asprintf (&data, "%s%ld;", data, crit);
527         else
528                 asprintf (&data, "%s;", data);
530         if (minp)
531                 asprintf (&data, "%s%ld", data, minv);
533         if (maxp)
534                 asprintf (&data, "%s;%ld", data, maxv);
536         return data;
540 char *fperfdata (const char *label,
541  double val,
542  const char *uom,
543  int warnp,
544  double warn,
545  int critp,
546  double crit,
547  int minp,
548  double minv,
549  int maxp,
550  double maxv)
552         char *data = NULL;
554         if (strpbrk (label, "'= "))
555                 asprintf (&data, "'%s'=", label);
556         else
557                 asprintf (&data, "%s=", label);
559         asprintf (&data, "%s%f", data, val);
560         asprintf (&data, "%s%s;", data, uom);
562         if (warnp)
563                 asprintf (&data, "%s%f", data, warn);
565         asprintf (&data, "%s;", data);
567         if (critp)
568                 asprintf (&data, "%s%f", data, crit);
570         asprintf (&data, "%s;", data);
572         if (minp)
573                 asprintf (&data, "%s%f", data, minv);
575         if (maxp) {
576                 asprintf (&data, "%s;", data);
577                 asprintf (&data, "%s%f", data, maxv);
578         }
580         return data;