Code

Changed output order of print_revision
[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         plugin_revision[0] = 'v';
109         if (sscanf (revstring,"$Revision: %[0-9.]", plugin_revision + 1) == 1)
110                 return strscpy (NULL, plugin_revision);
111         else
112                 return strscpy (NULL, "N/A");
115 void
116 print_revision (const char *command_name, const char *revision_string)
118         char plugin_revision[STRLEN];
120         printf ("%s %s (%s %s)\n",
121                  command_name, clean_revstring(revision_string), PACKAGE, VERSION);
124 const char *
125 state_text (int result)
127         switch (result) {
128         case STATE_OK:
129                 return "OK";
130         case STATE_WARNING:
131                 return "WARNING";
132         case STATE_CRITICAL:
133                 return "CRITICAL";
134         case STATE_DEPENDENT:
135                 return "DEPENDENT";
136         default:
137                 return "UNKNOWN";
138         }
141 void
142 timeout_alarm_handler (int signo)
144         if (signo == SIGALRM) {
145                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
146                                                 timeout_interval);
147                 exit (STATE_CRITICAL);
148         }
151 int
152 is_numeric (char *number)
154         char tmp[1];
155         float x;
157         if (!number)
158                 return FALSE;
159         else if (sscanf (number, "%f%c", &x, tmp) == 1)
160                 return TRUE;
161         else
162                 return FALSE;
165 int
166 is_positive (char *number)
168         if (is_numeric (number) && atof (number) > 0.0)
169                 return TRUE;
170         else
171                 return FALSE;
174 int
175 is_negative (char *number)
177         if (is_numeric (number) && atof (number) < 0.0)
178                 return TRUE;
179         else
180                 return FALSE;
183 int
184 is_nonnegative (char *number)
186         if (is_numeric (number) && atof (number) >= 0.0)
187                 return TRUE;
188         else
189                 return FALSE;
192 int
193 is_percentage (char *number)
195         int x;
196         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
197                 return TRUE;
198         else
199                 return FALSE;
202 int
203 is_integer (char *number)
205         long int n;
207         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
208                 return FALSE;
210         n = strtol (number, NULL, 10);
212         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
213                 return TRUE;
214         else
215                 return FALSE;
218 int
219 is_intpos (char *number)
221         if (is_integer (number) && atoi (number) > 0)
222                 return TRUE;
223         else
224                 return FALSE;
227 int
228 is_intneg (char *number)
230         if (is_integer (number) && atoi (number) < 0)
231                 return TRUE;
232         else
233                 return FALSE;
236 int
237 is_intnonneg (char *number)
239         if (is_integer (number) && atoi (number) >= 0)
240                 return TRUE;
241         else
242                 return FALSE;
245 int
246 is_intpercent (char *number)
248         int i;
249         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
250                 return TRUE;
251         else
252                 return FALSE;
255 int
256 is_option (char *str)
258         if (!str)
259                 return FALSE;
260         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
261                 return TRUE;
262         else
263                 return FALSE;
266 #ifdef NEED_GETTIMEOFDAY
267 int
268 gettimeofday (struct timeval *tv, struct timezone *tz)
270         tv->tv_usec = 0;
271         tv->tv_sec = (long) time ((time_t) 0);
273 #endif
277 double
278 delta_time (struct timeval tv)
280         struct timeval now;
282         gettimeofday (&now, NULL);
283         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
288 long
289 deltime (struct timeval tv)
291         struct timeval now;
292         gettimeofday (&now, NULL);
293         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
299 void
300 strip (char *buffer)
302         size_t x;
303         int i;
305         for (x = strlen (buffer); x >= 1; x--) {
306                 i = x - 1;
307                 if (buffer[i] == ' ' ||
308                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
309                         buffer[i] = '\0';
310                 else
311                         break;
312         }
313         return;
317 /******************************************************************************
318  *
319  * Copies one string to another. Any previously existing data in
320  * the destination string is lost.
321  *
322  * Example:
323  *
324  * char *str=NULL;
325  * str = strscpy("This is a line of text with no trailing newline");
326  *
327  *****************************************************************************/
329 char *
330 strscpy (char *dest, const char *src)
332         if (src == NULL)
333                 return NULL;
335         asprintf (&dest, "%s", src);
337         return dest;
342 /******************************************************************************
343  *
344  * Returns a pointer to the next line of a multiline string buffer
345  *
346  * Given a pointer string, find the text following the next sequence
347  * of \r and \n characters. This has the effect of skipping blank
348  * lines as well
349  *
350  * Example:
351  *
352  * Given text as follows:
353  *
354  * ==============================
355  * This
356  * is
357  * a
358  * 
359  * multiline string buffer
360  * ==============================
361  *
362  * int i=0;
363  * char *str=NULL;
364  * char *ptr=NULL;
365  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
366  * ptr = str;
367  * while (ptr) {
368  *   printf("%d %s",i++,firstword(ptr));
369  *   ptr = strnl(ptr);
370  * }
371  * 
372  * Produces the following:
373  *
374  * 1 This
375  * 2 is
376  * 3 a
377  * 4 multiline
378  *
379  * NOTE: The 'firstword()' function is conceptual only and does not
380  *       exist in this package.
381  *
382  * NOTE: Although the second 'ptr' variable is not strictly needed in
383  *       this example, it is good practice with these utilities. Once
384  *       the * pointer is advance in this manner, it may no longer be
385  *       handled with * realloc(). So at the end of the code fragment
386  *       above, * strscpy(str,"foo") work perfectly fine, but
387  *       strscpy(ptr,"foo") will * cause the the program to crash with
388  *       a segmentation fault.
389  *
390  *****************************************************************************/
392 char *
393 strnl (char *str)
395         size_t len;
396         if (str == NULL)
397                 return NULL;
398         str = strpbrk (str, "\r\n");
399         if (str == NULL)
400                 return NULL;
401         len = strspn (str, "\r\n");
402         if (str[len] == '\0')
403                 return NULL;
404         str += len;
405         if (strlen (str) == 0)
406                 return NULL;
407         return str;
411 /******************************************************************************
412  *
413  * Like strscpy, except only the portion of the source string up to
414  * the provided delimiter is copied.
415  *
416  * Example:
417  *
418  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
419  * printf("%s\n",str);
420  *
421  * Produces:
422  *
423  *This is a line of te
424  *
425  *****************************************************************************/
427 char *
428 strpcpy (char *dest, const char *src, const char *str)
430         size_t len;
432         if (src)
433                 len = strcspn (src, str);
434         else
435                 return NULL;
437         if (dest == NULL || strlen (dest) < len)
438                 dest = realloc (dest, len + 1);
439         if (dest == NULL)
440                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
442         strncpy (dest, src, len);
443         dest[len] = '\0';
445         return dest;
450 /******************************************************************************
451  *
452  * Like strscat, except only the portion of the source string up to
453  * the provided delimiter is copied.
454  *
455  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
456  * str = strpcat(str,"This is a line of text with no trailing newline","x");
457  * printf("%s\n",str);
458  * 
459  *This is a line of texThis is a line of tex
460  *
461  *****************************************************************************/
463 char *
464 strpcat (char *dest, const char *src, const char *str)
466         size_t len, l2;
468         if (dest)
469                 len = strlen (dest);
470         else
471                 len = 0;
473         if (src) {
474                 l2 = strcspn (src, str);
475         }
476         else {
477                 return dest;
478         }
480         dest = realloc (dest, len + l2 + 1);
481         if (dest == NULL)
482                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
484         strncpy (dest + len, src, l2);
485         dest[len + l2] = '\0';
487         return dest;
490 /******************************************************************************
491  *
492  * Print perfdata in a standard format
493  *
494  ******************************************************************************/
496 char *perfdata (const char *label,
497  long int val,
498  const char *uom,
499  int warnp,
500  long int warn,
501  int critp,
502  long int crit,
503  int minp,
504  long int minv,
505  int maxp,
506  long int maxv)
508         char *data = NULL;
510         if (strpbrk (label, "'= "))
511                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
512         else
513                 asprintf (&data, "%s=%ld%s;", label, val, uom);
515         if (warnp)
516                 asprintf (&data, "%s%ld;", data, warn);
517         else
518                 asprintf (&data, "%s;", data);
520         if (critp)
521                 asprintf (&data, "%s%ld;", data, crit);
522         else
523                 asprintf (&data, "%s;", data);
525         if (minp)
526                 asprintf (&data, "%s%ld", data, minv);
528         if (maxp)
529                 asprintf (&data, "%s;%ld", data, maxv);
531         return data;
535 char *fperfdata (const char *label,
536  double val,
537  const char *uom,
538  int warnp,
539  double warn,
540  int critp,
541  double crit,
542  int minp,
543  double minv,
544  int maxp,
545  double maxv)
547         char *data = NULL;
549         if (strpbrk (label, "'= "))
550                 asprintf (&data, "'%s'=", label);
551         else
552                 asprintf (&data, "%s=", label);
554         asprintf (&data, "%s%f", data, val);
555         asprintf (&data, "%s%s;", data, uom);
557         if (warnp)
558                 asprintf (&data, "%s%f", data, warn);
560         asprintf (&data, "%s;", data);
562         if (critp)
563                 asprintf (&data, "%s%f", data, crit);
565         asprintf (&data, "%s;", data);
567         if (minp)
568                 asprintf (&data, "%s%f", data, minv);
570         if (maxp) {
571                 asprintf (&data, "%s;", data);
572                 asprintf (&data, "%s%f", data, maxv);
573         }
575         return data;