1 /*****************************************************************************
5 * Library of useful functions for plugins
7 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
12 ****************************************************************************/
14 #define LOCAL_TIMEOUT_ALARM_HANDLER
21 #include <arpa/inet.h>
23 extern void print_usage (void);
24 extern const char *progname
;
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
34 * Note that numerically the above does not hold
35 ****************************************************************************/
38 max_state (int a
, int b
)
40 if (a
== STATE_CRITICAL
|| b
== STATE_CRITICAL
)
41 return STATE_CRITICAL
;
42 else if (a
== STATE_WARNING
|| b
== STATE_WARNING
)
44 else if (a
== STATE_OK
|| b
== STATE_OK
)
46 else if (a
== STATE_UNKNOWN
|| b
== STATE_UNKNOWN
)
48 else if (a
== STATE_DEPENDENT
|| b
== STATE_DEPENDENT
)
49 return STATE_DEPENDENT
;
54 void usage (const char *msg
)
61 void usage_va (const char *fmt
, ...)
64 printf("%s: ", progname
);
72 void usage2(const char *msg
, const char *arg
)
74 printf ("%s: %s - %s\n",progname
,msg
,arg
);
80 usage3 (const char *msg
, int arg
)
82 printf ("%s: %s - %c\n", progname
, msg
, arg
);
88 usage4 (const char *msg
)
90 printf ("%s: %s\n", progname
, msg
);
96 clean_revstring (const char *revstring
)
98 char plugin_revision
[STRLEN
];
99 if (sscanf (revstring
,"$Revision: %[0-9.]",plugin_revision
) == 1)
100 return strscpy (NULL
, plugin_revision
);
102 return strscpy (NULL
, "N/A");
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
);
117 state_text (int result
)
126 case STATE_DEPENDENT
:
134 die (int result
, const char *fmt
, ...)
144 timeout_alarm_handler (int signo
)
146 if (signo
== SIGALRM
) {
147 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
149 exit (STATE_CRITICAL
);
154 is_numeric (char *number
)
161 else if (sscanf (number
, "%f%c", &x
, tmp
) == 1)
168 is_positive (char *number
)
170 if (is_numeric (number
) && atof (number
) > 0.0)
177 is_negative (char *number
)
179 if (is_numeric (number
) && atof (number
) < 0.0)
186 is_nonnegative (char *number
)
188 if (is_numeric (number
) && atof (number
) >= 0.0)
195 is_percentage (char *number
)
198 if (is_numeric (number
) && (x
= atof (number
)) >= 0 && x
<= 100)
205 is_integer (char *number
)
209 if (!number
|| (strspn (number
, "-0123456789 ") != strlen (number
)))
212 n
= strtol (number
, NULL
, 10);
214 if (errno
!= ERANGE
&& n
>= INT_MIN
&& n
<= INT_MAX
)
221 is_intpos (char *number
)
223 if (is_integer (number
) && atoi (number
) > 0)
230 is_intneg (char *number
)
232 if (is_integer (number
) && atoi (number
) < 0)
239 is_intnonneg (char *number
)
241 if (is_integer (number
) && atoi (number
) >= 0)
248 is_intpercent (char *number
)
251 if (is_integer (number
) && (i
= atoi (number
)) >= 0 && i
<= 100)
258 is_option (char *str
)
262 else if (strspn (str
, "-") == 1 || strspn (str
, "-") == 2)
268 void set_range_start (range
*this, double value
) {
270 this->start_infinity
= FALSE
;
273 void set_range_end (range
*this, double value
) {
275 this->end_infinity
= FALSE
;
279 *parse_range_string (char *str
) {
285 temp_range
= (range
*) malloc(sizeof(range
));
288 temp_range
->start
= 0;
289 temp_range
->start_infinity
= FALSE
;
291 temp_range
->end_infinity
= TRUE
;
292 temp_range
->alert_on
= OUTSIDE
;
295 temp_range
->alert_on
= INSIDE
;
299 end_str
= index(str
, ':');
300 if (end_str
!= NULL
) {
302 temp_range
->start_infinity
= TRUE
;
304 start
= strtod(str
, NULL
); /* Will stop at the ':' */
305 set_range_start(temp_range
, start
);
307 end_str
++; /* Move past the ':' */
311 end
= strtod(end_str
, NULL
);
312 if (strcmp(end_str
, "") != 0) {
313 set_range_end(temp_range
, end
);
316 if (temp_range
->start_infinity
== TRUE
||
317 temp_range
->end_infinity
== TRUE
||
318 temp_range
->start
<= temp_range
->end
) {
325 /* returns 0 if okay, otherwise 1 */
327 _set_thresholds(thresholds
**my_thresholds
, char *warn_string
, char *critical_string
)
329 thresholds
*temp_thresholds
= NULL
;
331 temp_thresholds
= malloc(sizeof(temp_thresholds
));
333 temp_thresholds
->warning
= NULL
;
334 temp_thresholds
->critical
= NULL
;
336 if (warn_string
!= NULL
) {
337 if ((temp_thresholds
->warning
= parse_range_string(warn_string
)) == NULL
) {
341 if (critical_string
!= NULL
) {
342 if ((temp_thresholds
->critical
= parse_range_string(critical_string
)) == NULL
) {
347 if (*my_thresholds
!= 0) {
348 /* printf("Freeing here: %d\n", *my_thresholds); */
349 free(*my_thresholds
);
351 *my_thresholds
= temp_thresholds
;
357 set_thresholds(thresholds
**my_thresholds
, char *warn_string
, char *critical_string
)
359 if (_set_thresholds(my_thresholds
, warn_string
, critical_string
) == 0) {
362 usage("Range format incorrect");
366 /* Returns TRUE if alert should be raised based on the range */
368 check_range(double value
, range
*my_range
)
373 if (my_range
->alert_on
== INSIDE
) {
378 if (my_range
->end_infinity
== FALSE
&& my_range
->start_infinity
== FALSE
) {
379 if ((my_range
->start
<= value
) && (value
<= my_range
->end
)) {
384 } else if (my_range
->start_infinity
== FALSE
&& my_range
->end_infinity
== TRUE
) {
385 if (my_range
->start
<= value
) {
390 } else if (my_range
->start_infinity
== TRUE
&& my_range
->end_infinity
== FALSE
) {
391 if (value
<= my_range
->end
) {
403 get_status(double value
, thresholds
*my_thresholds
)
405 if (my_thresholds
->critical
!= NULL
) {
406 if (check_range(value
, my_thresholds
->critical
) == TRUE
) {
407 return STATE_CRITICAL
;
410 if (my_thresholds
->warning
!= NULL
) {
411 if (check_range(value
, my_thresholds
->warning
) == TRUE
) {
412 return STATE_WARNING
;
418 #ifdef NEED_GETTIMEOFDAY
420 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
423 tv
->tv_sec
= (long) time ((time_t) 0);
430 delta_time (struct timeval tv
)
434 gettimeofday (&now
, NULL
);
435 return ((double)(now
.tv_sec
- tv
.tv_sec
) + (double)(now
.tv_usec
- tv
.tv_usec
) / (double)1000000);
441 deltime (struct timeval tv
)
444 gettimeofday (&now
, NULL
);
445 return (now
.tv_sec
- tv
.tv_sec
)*1000000 + now
.tv_usec
- tv
.tv_usec
;
457 for (x
= strlen (buffer
); x
>= 1; x
--) {
459 if (buffer
[i
] == ' ' ||
460 buffer
[i
] == '\r' || buffer
[i
] == '\n' || buffer
[i
] == '\t')
469 /******************************************************************************
471 * Copies one string to another. Any previously existing data in
472 * the destination string is lost.
477 * str = strscpy("This is a line of text with no trailing newline");
479 *****************************************************************************/
482 strscpy (char *dest
, const char *src
)
487 asprintf (&dest
, "%s", src
);
494 /******************************************************************************
496 * Returns a pointer to the next line of a multiline string buffer
498 * Given a pointer string, find the text following the next sequence
499 * of \r and \n characters. This has the effect of skipping blank
504 * Given text as follows:
506 * ==============================
511 * multiline string buffer
512 * ==============================
517 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
520 * printf("%d %s",i++,firstword(ptr));
524 * Produces the following:
531 * NOTE: The 'firstword()' function is conceptual only and does not
532 * exist in this package.
534 * NOTE: Although the second 'ptr' variable is not strictly needed in
535 * this example, it is good practice with these utilities. Once
536 * the * pointer is advance in this manner, it may no longer be
537 * handled with * realloc(). So at the end of the code fragment
538 * above, * strscpy(str,"foo") work perfectly fine, but
539 * strscpy(ptr,"foo") will * cause the the program to crash with
540 * a segmentation fault.
542 *****************************************************************************/
550 str
= strpbrk (str
, "\r\n");
553 len
= strspn (str
, "\r\n");
554 if (str
[len
] == '\0')
557 if (strlen (str
) == 0)
563 /******************************************************************************
565 * Like strscpy, except only the portion of the source string up to
566 * the provided delimiter is copied.
570 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
571 * printf("%s\n",str);
575 *This is a line of te
577 *****************************************************************************/
580 strpcpy (char *dest
, const char *src
, const char *str
)
585 len
= strcspn (src
, str
);
589 if (dest
== NULL
|| strlen (dest
) < len
)
590 dest
= realloc (dest
, len
+ 1);
592 die (STATE_UNKNOWN
, _("failed realloc in strpcpy\n"));
594 strncpy (dest
, src
, len
);
602 /******************************************************************************
604 * Like strscat, except only the portion of the source string up to
605 * the provided delimiter is copied.
607 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
608 * str = strpcat(str,"This is a line of text with no trailing newline","x");
609 * printf("%s\n",str);
611 *This is a line of texThis is a line of tex
613 *****************************************************************************/
616 strpcat (char *dest
, const char *src
, const char *str
)
626 l2
= strcspn (src
, str
);
632 dest
= realloc (dest
, len
+ l2
+ 1);
634 die (STATE_UNKNOWN
, _("failed malloc in strscat\n"));
636 strncpy (dest
+ len
, src
, l2
);
637 dest
[len
+ l2
] = '\0';
643 /******************************************************************************
645 * Print perfdata in a standard format
647 ******************************************************************************/
649 char *perfdata (const char *label
,
663 if (strpbrk (label
, "'= "))
664 asprintf (&data
, "'%s'=%ld%s;", label
, val
, uom
);
666 asprintf (&data
, "%s=%ld%s;", label
, val
, uom
);
669 asprintf (&data
, "%s%ld;", data
, warn
);
671 asprintf (&data
, "%s;", data
);
674 asprintf (&data
, "%s%ld;", data
, crit
);
676 asprintf (&data
, "%s;", data
);
679 asprintf (&data
, "%s%ld", data
, minv
);
682 asprintf (&data
, "%s;%ld", data
, maxv
);
688 char *fperfdata (const char *label
,
702 if (strpbrk (label
, "'= "))
703 asprintf (&data
, "'%s'=", label
);
705 asprintf (&data
, "%s=", label
);
707 asprintf (&data
, "%s%f", data
, val
);
708 asprintf (&data
, "%s%s;", data
, uom
);
711 asprintf (&data
, "%s%f", data
, warn
);
713 asprintf (&data
, "%s;", data
);
716 asprintf (&data
, "%s%f", data
, crit
);
718 asprintf (&data
, "%s;", data
);
721 asprintf (&data
, "%s%f", data
, minv
);
724 asprintf (&data
, "%s;", data
);
725 asprintf (&data
, "%s%f", data
, maxv
);