Code

check_ntp_peer/check_ntp_time used to show port in --help but ignored the argument...
[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 * Last Modified: $Date$
10
11
12 * This program is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation, either version 3 of the License, or
15 * (at your option) any later version.
16
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 * GNU General Public License for more details.
21
22 * You should have received a copy of the GNU General Public License
23 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
24
25 * $Id$
26
27 *****************************************************************************/
29 #define LOCAL_TIMEOUT_ALARM_HANDLER
31 #include "common.h"
32 #include "utils.h"
33 #include "utils_base.h"
34 #include <stdarg.h>
35 #include <limits.h>
37 #include <arpa/inet.h>
39 extern void print_usage (void);
40 extern const char *progname;
42 #define STRLEN 64
43 #define TXTBLK 128
45 /* **************************************************************************
46  * max_state(STATE_x, STATE_y)
47  * compares STATE_x to  STATE_y and returns result based on the following
48  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
49  *
50  * Note that numerically the above does not hold
51  ****************************************************************************/
53 int
54 max_state (int a, int b)
55 {
56         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
57                 return STATE_CRITICAL;
58         else if (a == STATE_WARNING || b == STATE_WARNING)
59                 return STATE_WARNING;
60         else if (a == STATE_OK || b == STATE_OK)
61                 return STATE_OK;
62         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
63                 return STATE_UNKNOWN;
64         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
65                 return STATE_DEPENDENT;
66         else
67                 return max (a, b);
68 }
70 /* **************************************************************************
71  * max_state_alt(STATE_x, STATE_y)
72  * compares STATE_x to  STATE_y and returns result based on the following
73  * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
74  *
75  * The main difference between max_state_alt and max_state it that it doesn't
76  * allow setting a default to UNKNOWN. It will instead prioritixe any valid
77  * non-OK state.
78  ****************************************************************************/
80 int
81 max_state_alt (int a, int b)
82 {
83         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
84                 return STATE_CRITICAL;
85         else if (a == STATE_WARNING || b == STATE_WARNING)
86                 return STATE_WARNING;
87         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
88                 return STATE_UNKNOWN;
89         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
90                 return STATE_DEPENDENT;
91         else if (a == STATE_OK || b == STATE_OK)
92                 return STATE_OK;
93         else
94                 return max (a, b);
95 }
97 void usage (const char *msg)
98 {
99         printf ("%s\n", msg);
100         print_usage ();
101         exit (STATE_UNKNOWN);
104 void usage_va (const char *fmt, ...)
106         va_list ap;
107         printf("%s: ", progname);
108         va_start(ap, fmt);
109         vprintf(fmt, ap);
110         va_end(ap);
111         printf("\n");
112         exit (STATE_UNKNOWN);
115 void usage2(const char *msg, const char *arg)
117         printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
118         print_usage ();
119         exit (STATE_UNKNOWN);
122 void
123 usage3 (const char *msg, int arg)
125         printf ("%s: %s - %c\n", progname, msg, arg);
126         print_usage();
127         exit (STATE_UNKNOWN);
130 void
131 usage4 (const char *msg)
133         printf ("%s: %s\n", progname, msg);
134         print_usage();
135         exit (STATE_UNKNOWN);
138 void
139 usage5 (void)
141         print_usage();
142         exit (STATE_UNKNOWN);
145 char *
146 clean_revstring (const char *revstring)
148         char plugin_revision[STRLEN];
149         plugin_revision[0] = 'v';
150         if (sscanf (revstring,"$Revision: %[0-9.]", plugin_revision + 1) == 1)
151                 return strscpy (NULL, plugin_revision);
152         else
153                 return strscpy (NULL, "N/A");
156 void
157 print_revision (const char *command_name, const char *revision_string)
159         char plugin_revision[STRLEN];
161         printf ("%s %s (%s %s)\n",
162                  command_name, clean_revstring(revision_string), PACKAGE, VERSION);
165 const char *
166 state_text (int result)
168         switch (result) {
169         case STATE_OK:
170                 return "OK";
171         case STATE_WARNING:
172                 return "WARNING";
173         case STATE_CRITICAL:
174                 return "CRITICAL";
175         case STATE_DEPENDENT:
176                 return "DEPENDENT";
177         default:
178                 return "UNKNOWN";
179         }
182 void
183 timeout_alarm_handler (int signo)
185         if (signo == SIGALRM) {
186                 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
187                                                 timeout_interval);
188                 exit (STATE_CRITICAL);
189         }
192 int
193 is_numeric (char *number)
195         char tmp[1];
196         float x;
198         if (!number)
199                 return FALSE;
200         else if (sscanf (number, "%f%c", &x, tmp) == 1)
201                 return TRUE;
202         else
203                 return FALSE;
206 int
207 is_positive (char *number)
209         if (is_numeric (number) && atof (number) > 0.0)
210                 return TRUE;
211         else
212                 return FALSE;
215 int
216 is_negative (char *number)
218         if (is_numeric (number) && atof (number) < 0.0)
219                 return TRUE;
220         else
221                 return FALSE;
224 int
225 is_nonnegative (char *number)
227         if (is_numeric (number) && atof (number) >= 0.0)
228                 return TRUE;
229         else
230                 return FALSE;
233 int
234 is_percentage (char *number)
236         int x;
237         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
238                 return TRUE;
239         else
240                 return FALSE;
243 int
244 is_integer (char *number)
246         long int n;
248         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
249                 return FALSE;
251         n = strtol (number, NULL, 10);
253         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
254                 return TRUE;
255         else
256                 return FALSE;
259 int
260 is_intpos (char *number)
262         if (is_integer (number) && atoi (number) > 0)
263                 return TRUE;
264         else
265                 return FALSE;
268 int
269 is_intneg (char *number)
271         if (is_integer (number) && atoi (number) < 0)
272                 return TRUE;
273         else
274                 return FALSE;
277 int
278 is_intnonneg (char *number)
280         if (is_integer (number) && atoi (number) >= 0)
281                 return TRUE;
282         else
283                 return FALSE;
286 int
287 is_intpercent (char *number)
289         int i;
290         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
291                 return TRUE;
292         else
293                 return FALSE;
296 int
297 is_option (char *str)
299         if (!str)
300                 return FALSE;
301         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
302                 return TRUE;
303         else
304                 return FALSE;
307 #ifdef NEED_GETTIMEOFDAY
308 int
309 gettimeofday (struct timeval *tv, struct timezone *tz)
311         tv->tv_usec = 0;
312         tv->tv_sec = (long) time ((time_t) 0);
314 #endif
318 double
319 delta_time (struct timeval tv)
321         struct timeval now;
323         gettimeofday (&now, NULL);
324         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
329 long
330 deltime (struct timeval tv)
332         struct timeval now;
333         gettimeofday (&now, NULL);
334         return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
340 void
341 strip (char *buffer)
343         size_t x;
344         int i;
346         for (x = strlen (buffer); x >= 1; x--) {
347                 i = x - 1;
348                 if (buffer[i] == ' ' ||
349                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
350                         buffer[i] = '\0';
351                 else
352                         break;
353         }
354         return;
358 /******************************************************************************
359  *
360  * Copies one string to another. Any previously existing data in
361  * the destination string is lost.
362  *
363  * Example:
364  *
365  * char *str=NULL;
366  * str = strscpy("This is a line of text with no trailing newline");
367  *
368  *****************************************************************************/
370 char *
371 strscpy (char *dest, const char *src)
373         if (src == NULL)
374                 return NULL;
376         asprintf (&dest, "%s", src);
378         return dest;
383 /******************************************************************************
384  *
385  * Returns a pointer to the next line of a multiline string buffer
386  *
387  * Given a pointer string, find the text following the next sequence
388  * of \r and \n characters. This has the effect of skipping blank
389  * lines as well
390  *
391  * Example:
392  *
393  * Given text as follows:
394  *
395  * ==============================
396  * This
397  * is
398  * a
399  * 
400  * multiline string buffer
401  * ==============================
402  *
403  * int i=0;
404  * char *str=NULL;
405  * char *ptr=NULL;
406  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
407  * ptr = str;
408  * while (ptr) {
409  *   printf("%d %s",i++,firstword(ptr));
410  *   ptr = strnl(ptr);
411  * }
412  * 
413  * Produces the following:
414  *
415  * 1 This
416  * 2 is
417  * 3 a
418  * 4 multiline
419  *
420  * NOTE: The 'firstword()' function is conceptual only and does not
421  *       exist in this package.
422  *
423  * NOTE: Although the second 'ptr' variable is not strictly needed in
424  *       this example, it is good practice with these utilities. Once
425  *       the * pointer is advance in this manner, it may no longer be
426  *       handled with * realloc(). So at the end of the code fragment
427  *       above, * strscpy(str,"foo") work perfectly fine, but
428  *       strscpy(ptr,"foo") will * cause the the program to crash with
429  *       a segmentation fault.
430  *
431  *****************************************************************************/
433 char *
434 strnl (char *str)
436         size_t len;
437         if (str == NULL)
438                 return NULL;
439         str = strpbrk (str, "\r\n");
440         if (str == NULL)
441                 return NULL;
442         len = strspn (str, "\r\n");
443         if (str[len] == '\0')
444                 return NULL;
445         str += len;
446         if (strlen (str) == 0)
447                 return NULL;
448         return str;
452 /******************************************************************************
453  *
454  * Like strscpy, except only the portion of the source string up to
455  * the provided delimiter is copied.
456  *
457  * Example:
458  *
459  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
460  * printf("%s\n",str);
461  *
462  * Produces:
463  *
464  *This is a line of te
465  *
466  *****************************************************************************/
468 char *
469 strpcpy (char *dest, const char *src, const char *str)
471         size_t len;
473         if (src)
474                 len = strcspn (src, str);
475         else
476                 return NULL;
478         if (dest == NULL || strlen (dest) < len)
479                 dest = realloc (dest, len + 1);
480         if (dest == NULL)
481                 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
483         strncpy (dest, src, len);
484         dest[len] = '\0';
486         return dest;
491 /******************************************************************************
492  *
493  * Like strscat, except only the portion of the source string up to
494  * the provided delimiter is copied.
495  *
496  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
497  * str = strpcat(str,"This is a line of text with no trailing newline","x");
498  * printf("%s\n",str);
499  * 
500  *This is a line of texThis is a line of tex
501  *
502  *****************************************************************************/
504 char *
505 strpcat (char *dest, const char *src, const char *str)
507         size_t len, l2;
509         if (dest)
510                 len = strlen (dest);
511         else
512                 len = 0;
514         if (src) {
515                 l2 = strcspn (src, str);
516         }
517         else {
518                 return dest;
519         }
521         dest = realloc (dest, len + l2 + 1);
522         if (dest == NULL)
523                 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
525         strncpy (dest + len, src, l2);
526         dest[len + l2] = '\0';
528         return dest;
531 /******************************************************************************
532  *
533  * Print perfdata in a standard format
534  *
535  ******************************************************************************/
537 char *perfdata (const char *label,
538  long int val,
539  const char *uom,
540  int warnp,
541  long int warn,
542  int critp,
543  long int crit,
544  int minp,
545  long int minv,
546  int maxp,
547  long int maxv)
549         char *data = NULL;
551         if (strpbrk (label, "'= "))
552                 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
553         else
554                 asprintf (&data, "%s=%ld%s;", label, val, uom);
556         if (warnp)
557                 asprintf (&data, "%s%ld;", data, warn);
558         else
559                 asprintf (&data, "%s;", data);
561         if (critp)
562                 asprintf (&data, "%s%ld;", data, crit);
563         else
564                 asprintf (&data, "%s;", data);
566         if (minp)
567                 asprintf (&data, "%s%ld", data, minv);
569         if (maxp)
570                 asprintf (&data, "%s;%ld", data, maxv);
572         return data;
576 char *fperfdata (const char *label,
577  double val,
578  const char *uom,
579  int warnp,
580  double warn,
581  int critp,
582  double crit,
583  int minp,
584  double minv,
585  int maxp,
586  double maxv)
588         char *data = NULL;
590         if (strpbrk (label, "'= "))
591                 asprintf (&data, "'%s'=", label);
592         else
593                 asprintf (&data, "%s=", label);
595         asprintf (&data, "%s%f", data, val);
596         asprintf (&data, "%s%s;", data, uom);
598         if (warnp)
599                 asprintf (&data, "%s%f", data, warn);
601         asprintf (&data, "%s;", data);
603         if (critp)
604                 asprintf (&data, "%s%f", data, crit);
606         asprintf (&data, "%s;", data);
608         if (minp)
609                 asprintf (&data, "%s%f", data, minv);
611         if (maxp) {
612                 asprintf (&data, "%s;", data);
613                 asprintf (&data, "%s%f", data, maxv);
614         }
616         return data;