1 /*****************************************************************************
5 * Library of useful functions for plugins
7 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
8 * Copyright (c) 2006 Nagios Plugin Development Team
13 ****************************************************************************/
15 #define LOCAL_TIMEOUT_ALARM_HANDLER
19 #include "utils_base.h"
23 #include <arpa/inet.h>
25 extern void print_usage (void);
26 extern const char *progname
;
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
36 * Note that numerically the above does not hold
37 ****************************************************************************/
40 max_state (int a
, int b
)
42 if (a
== STATE_CRITICAL
|| b
== STATE_CRITICAL
)
43 return STATE_CRITICAL
;
44 else if (a
== STATE_WARNING
|| b
== STATE_WARNING
)
46 else if (a
== STATE_OK
|| b
== STATE_OK
)
48 else if (a
== STATE_UNKNOWN
|| b
== STATE_UNKNOWN
)
50 else if (a
== STATE_DEPENDENT
|| b
== STATE_DEPENDENT
)
51 return STATE_DEPENDENT
;
56 /* **************************************************************************
57 * max_state_alt(STATE_x, STATE_y)
58 * compares STATE_x to STATE_y and returns result based on the following
59 * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
61 * The main difference between max_state_alt and max_state it that it doesn't
62 * allow setting a default to UNKNOWN. It will instead prioritixe any valid
64 ****************************************************************************/
67 max_state_alt (int a
, int b
)
69 if (a
== STATE_CRITICAL
|| b
== STATE_CRITICAL
)
70 return STATE_CRITICAL
;
71 else if (a
== STATE_WARNING
|| b
== STATE_WARNING
)
73 else if (a
== STATE_UNKNOWN
|| b
== STATE_UNKNOWN
)
75 else if (a
== STATE_DEPENDENT
|| b
== STATE_DEPENDENT
)
76 return STATE_DEPENDENT
;
77 else if (a
== STATE_OK
|| b
== STATE_OK
)
83 void usage (const char *msg
)
90 void usage_va (const char *fmt
, ...)
93 printf("%s: ", progname
);
101 void usage2(const char *msg
, const char *arg
)
103 printf ("%s: %s - %s\n", progname
, msg
, arg
?arg
:"(null)" );
105 exit (STATE_UNKNOWN
);
109 usage3 (const char *msg
, int arg
)
111 printf ("%s: %s - %c\n", progname
, msg
, arg
);
113 exit (STATE_UNKNOWN
);
117 usage4 (const char *msg
)
119 printf ("%s: %s\n", progname
, msg
);
121 exit (STATE_UNKNOWN
);
128 exit (STATE_UNKNOWN
);
132 clean_revstring (const char *revstring
)
134 char plugin_revision
[STRLEN
];
135 plugin_revision
[0] = 'v';
136 if (sscanf (revstring
,"$Revision: %[0-9.]", plugin_revision
+ 1) == 1)
137 return strscpy (NULL
, plugin_revision
);
139 return strscpy (NULL
, "N/A");
143 print_revision (const char *command_name
, const char *revision_string
)
145 char plugin_revision
[STRLEN
];
147 printf ("%s %s (%s %s)\n",
148 command_name
, clean_revstring(revision_string
), PACKAGE
, VERSION
);
152 state_text (int result
)
161 case STATE_DEPENDENT
:
169 timeout_alarm_handler (int signo
)
171 if (signo
== SIGALRM
) {
172 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
174 exit (STATE_CRITICAL
);
179 is_numeric (char *number
)
186 else if (sscanf (number
, "%f%c", &x
, tmp
) == 1)
193 is_positive (char *number
)
195 if (is_numeric (number
) && atof (number
) > 0.0)
202 is_negative (char *number
)
204 if (is_numeric (number
) && atof (number
) < 0.0)
211 is_nonnegative (char *number
)
213 if (is_numeric (number
) && atof (number
) >= 0.0)
220 is_percentage (char *number
)
223 if (is_numeric (number
) && (x
= atof (number
)) >= 0 && x
<= 100)
230 is_integer (char *number
)
234 if (!number
|| (strspn (number
, "-0123456789 ") != strlen (number
)))
237 n
= strtol (number
, NULL
, 10);
239 if (errno
!= ERANGE
&& n
>= INT_MIN
&& n
<= INT_MAX
)
246 is_intpos (char *number
)
248 if (is_integer (number
) && atoi (number
) > 0)
255 is_intneg (char *number
)
257 if (is_integer (number
) && atoi (number
) < 0)
264 is_intnonneg (char *number
)
266 if (is_integer (number
) && atoi (number
) >= 0)
273 is_intpercent (char *number
)
276 if (is_integer (number
) && (i
= atoi (number
)) >= 0 && i
<= 100)
283 is_option (char *str
)
287 else if (strspn (str
, "-") == 1 || strspn (str
, "-") == 2)
293 #ifdef NEED_GETTIMEOFDAY
295 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
298 tv
->tv_sec
= (long) time ((time_t) 0);
305 delta_time (struct timeval tv
)
309 gettimeofday (&now
, NULL
);
310 return ((double)(now
.tv_sec
- tv
.tv_sec
) + (double)(now
.tv_usec
- tv
.tv_usec
) / (double)1000000);
316 deltime (struct timeval tv
)
319 gettimeofday (&now
, NULL
);
320 return (now
.tv_sec
- tv
.tv_sec
)*1000000 + now
.tv_usec
- tv
.tv_usec
;
332 for (x
= strlen (buffer
); x
>= 1; x
--) {
334 if (buffer
[i
] == ' ' ||
335 buffer
[i
] == '\r' || buffer
[i
] == '\n' || buffer
[i
] == '\t')
344 /******************************************************************************
346 * Copies one string to another. Any previously existing data in
347 * the destination string is lost.
352 * str = strscpy("This is a line of text with no trailing newline");
354 *****************************************************************************/
357 strscpy (char *dest
, const char *src
)
362 asprintf (&dest
, "%s", src
);
369 /******************************************************************************
371 * Returns a pointer to the next line of a multiline string buffer
373 * Given a pointer string, find the text following the next sequence
374 * of \r and \n characters. This has the effect of skipping blank
379 * Given text as follows:
381 * ==============================
386 * multiline string buffer
387 * ==============================
392 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
395 * printf("%d %s",i++,firstword(ptr));
399 * Produces the following:
406 * NOTE: The 'firstword()' function is conceptual only and does not
407 * exist in this package.
409 * NOTE: Although the second 'ptr' variable is not strictly needed in
410 * this example, it is good practice with these utilities. Once
411 * the * pointer is advance in this manner, it may no longer be
412 * handled with * realloc(). So at the end of the code fragment
413 * above, * strscpy(str,"foo") work perfectly fine, but
414 * strscpy(ptr,"foo") will * cause the the program to crash with
415 * a segmentation fault.
417 *****************************************************************************/
425 str
= strpbrk (str
, "\r\n");
428 len
= strspn (str
, "\r\n");
429 if (str
[len
] == '\0')
432 if (strlen (str
) == 0)
438 /******************************************************************************
440 * Like strscpy, except only the portion of the source string up to
441 * the provided delimiter is copied.
445 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
446 * printf("%s\n",str);
450 *This is a line of te
452 *****************************************************************************/
455 strpcpy (char *dest
, const char *src
, const char *str
)
460 len
= strcspn (src
, str
);
464 if (dest
== NULL
|| strlen (dest
) < len
)
465 dest
= realloc (dest
, len
+ 1);
467 die (STATE_UNKNOWN
, _("failed realloc in strpcpy\n"));
469 strncpy (dest
, src
, len
);
477 /******************************************************************************
479 * Like strscat, except only the portion of the source string up to
480 * the provided delimiter is copied.
482 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
483 * str = strpcat(str,"This is a line of text with no trailing newline","x");
484 * printf("%s\n",str);
486 *This is a line of texThis is a line of tex
488 *****************************************************************************/
491 strpcat (char *dest
, const char *src
, const char *str
)
501 l2
= strcspn (src
, str
);
507 dest
= realloc (dest
, len
+ l2
+ 1);
509 die (STATE_UNKNOWN
, _("failed malloc in strscat\n"));
511 strncpy (dest
+ len
, src
, l2
);
512 dest
[len
+ l2
] = '\0';
517 /******************************************************************************
519 * Print perfdata in a standard format
521 ******************************************************************************/
523 char *perfdata (const char *label
,
537 if (strpbrk (label
, "'= "))
538 asprintf (&data
, "'%s'=%ld%s;", label
, val
, uom
);
540 asprintf (&data
, "%s=%ld%s;", label
, val
, uom
);
543 asprintf (&data
, "%s%ld;", data
, warn
);
545 asprintf (&data
, "%s;", data
);
548 asprintf (&data
, "%s%ld;", data
, crit
);
550 asprintf (&data
, "%s;", data
);
553 asprintf (&data
, "%s%ld", data
, minv
);
556 asprintf (&data
, "%s;%ld", data
, maxv
);
562 char *fperfdata (const char *label
,
576 if (strpbrk (label
, "'= "))
577 asprintf (&data
, "'%s'=", label
);
579 asprintf (&data
, "%s=", label
);
581 asprintf (&data
, "%s%f", data
, val
);
582 asprintf (&data
, "%s%s;", data
, uom
);
585 asprintf (&data
, "%s%f", data
, warn
);
587 asprintf (&data
, "%s;", data
);
590 asprintf (&data
, "%s%f", data
, crit
);
592 asprintf (&data
, "%s;", data
);
595 asprintf (&data
, "%s%f", data
, minv
);
598 asprintf (&data
, "%s;", data
);
599 asprintf (&data
, "%s%f", data
, maxv
);