1 /*****************************************************************************
3 * Library of useful functions for plugins
6 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
7 * Copyright (c) 2002-2007 Nagios Plugin Development Team
9 * Last Modified: $Date$
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.
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.
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/>.
27 *****************************************************************************/
29 #define LOCAL_TIMEOUT_ALARM_HANDLER
33 #include "utils_base.h"
37 #include <arpa/inet.h>
39 extern void print_usage (void);
40 extern const char *progname
;
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
50 * Note that numerically the above does not hold
51 ****************************************************************************/
54 max_state (int a
, int b
)
56 if (a
== STATE_CRITICAL
|| b
== STATE_CRITICAL
)
57 return STATE_CRITICAL
;
58 else if (a
== STATE_WARNING
|| b
== STATE_WARNING
)
60 else if (a
== STATE_OK
|| b
== STATE_OK
)
62 else if (a
== STATE_UNKNOWN
|| b
== STATE_UNKNOWN
)
64 else if (a
== STATE_DEPENDENT
|| b
== STATE_DEPENDENT
)
65 return STATE_DEPENDENT
;
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
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
78 ****************************************************************************/
81 max_state_alt (int a
, int b
)
83 if (a
== STATE_CRITICAL
|| b
== STATE_CRITICAL
)
84 return STATE_CRITICAL
;
85 else if (a
== STATE_WARNING
|| b
== STATE_WARNING
)
87 else if (a
== STATE_UNKNOWN
|| b
== STATE_UNKNOWN
)
89 else if (a
== STATE_DEPENDENT
|| b
== STATE_DEPENDENT
)
90 return STATE_DEPENDENT
;
91 else if (a
== STATE_OK
|| b
== STATE_OK
)
97 void usage (const char *msg
)
101 exit (STATE_UNKNOWN
);
104 void usage_va (const char *fmt
, ...)
107 printf("%s: ", progname
);
112 exit (STATE_UNKNOWN
);
115 void usage2(const char *msg
, const char *arg
)
117 printf ("%s: %s - %s\n", progname
, msg
, arg
?arg
:"(null)" );
119 exit (STATE_UNKNOWN
);
123 usage3 (const char *msg
, int arg
)
125 printf ("%s: %s - %c\n", progname
, msg
, arg
);
127 exit (STATE_UNKNOWN
);
131 usage4 (const char *msg
)
133 printf ("%s: %s\n", progname
, msg
);
135 exit (STATE_UNKNOWN
);
142 exit (STATE_UNKNOWN
);
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
);
153 return strscpy (NULL
, "N/A");
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
);
166 state_text (int result
)
175 case STATE_DEPENDENT
:
183 timeout_alarm_handler (int signo
)
185 if (signo
== SIGALRM
) {
186 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
188 exit (STATE_CRITICAL
);
193 is_numeric (char *number
)
200 else if (sscanf (number
, "%f%c", &x
, tmp
) == 1)
207 is_positive (char *number
)
209 if (is_numeric (number
) && atof (number
) > 0.0)
216 is_negative (char *number
)
218 if (is_numeric (number
) && atof (number
) < 0.0)
225 is_nonnegative (char *number
)
227 if (is_numeric (number
) && atof (number
) >= 0.0)
234 is_percentage (char *number
)
237 if (is_numeric (number
) && (x
= atof (number
)) >= 0 && x
<= 100)
244 is_integer (char *number
)
248 if (!number
|| (strspn (number
, "-0123456789 ") != strlen (number
)))
251 n
= strtol (number
, NULL
, 10);
253 if (errno
!= ERANGE
&& n
>= INT_MIN
&& n
<= INT_MAX
)
260 is_intpos (char *number
)
262 if (is_integer (number
) && atoi (number
) > 0)
269 is_intneg (char *number
)
271 if (is_integer (number
) && atoi (number
) < 0)
278 is_intnonneg (char *number
)
280 if (is_integer (number
) && atoi (number
) >= 0)
287 is_intpercent (char *number
)
290 if (is_integer (number
) && (i
= atoi (number
)) >= 0 && i
<= 100)
297 is_option (char *str
)
301 else if (strspn (str
, "-") == 1 || strspn (str
, "-") == 2)
307 #ifdef NEED_GETTIMEOFDAY
309 gettimeofday (struct timeval
*tv
, struct timezone
*tz
)
312 tv
->tv_sec
= (long) time ((time_t) 0);
319 delta_time (struct timeval tv
)
323 gettimeofday (&now
, NULL
);
324 return ((double)(now
.tv_sec
- tv
.tv_sec
) + (double)(now
.tv_usec
- tv
.tv_usec
) / (double)1000000);
330 deltime (struct timeval tv
)
333 gettimeofday (&now
, NULL
);
334 return (now
.tv_sec
- tv
.tv_sec
)*1000000 + now
.tv_usec
- tv
.tv_usec
;
346 for (x
= strlen (buffer
); x
>= 1; x
--) {
348 if (buffer
[i
] == ' ' ||
349 buffer
[i
] == '\r' || buffer
[i
] == '\n' || buffer
[i
] == '\t')
358 /******************************************************************************
360 * Copies one string to another. Any previously existing data in
361 * the destination string is lost.
366 * str = strscpy("This is a line of text with no trailing newline");
368 *****************************************************************************/
371 strscpy (char *dest
, const char *src
)
376 asprintf (&dest
, "%s", src
);
383 /******************************************************************************
385 * Returns a pointer to the next line of a multiline string buffer
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
393 * Given text as follows:
395 * ==============================
400 * multiline string buffer
401 * ==============================
406 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
409 * printf("%d %s",i++,firstword(ptr));
413 * Produces the following:
420 * NOTE: The 'firstword()' function is conceptual only and does not
421 * exist in this package.
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.
431 *****************************************************************************/
439 str
= strpbrk (str
, "\r\n");
442 len
= strspn (str
, "\r\n");
443 if (str
[len
] == '\0')
446 if (strlen (str
) == 0)
452 /******************************************************************************
454 * Like strscpy, except only the portion of the source string up to
455 * the provided delimiter is copied.
459 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
460 * printf("%s\n",str);
464 *This is a line of te
466 *****************************************************************************/
469 strpcpy (char *dest
, const char *src
, const char *str
)
474 len
= strcspn (src
, str
);
478 if (dest
== NULL
|| strlen (dest
) < len
)
479 dest
= realloc (dest
, len
+ 1);
481 die (STATE_UNKNOWN
, _("failed realloc in strpcpy\n"));
483 strncpy (dest
, src
, len
);
491 /******************************************************************************
493 * Like strscat, except only the portion of the source string up to
494 * the provided delimiter is copied.
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);
500 *This is a line of texThis is a line of tex
502 *****************************************************************************/
505 strpcat (char *dest
, const char *src
, const char *str
)
515 l2
= strcspn (src
, str
);
521 dest
= realloc (dest
, len
+ l2
+ 1);
523 die (STATE_UNKNOWN
, _("failed malloc in strscat\n"));
525 strncpy (dest
+ len
, src
, l2
);
526 dest
[len
+ l2
] = '\0';
531 /******************************************************************************
533 * Print perfdata in a standard format
535 ******************************************************************************/
537 char *perfdata (const char *label
,
551 if (strpbrk (label
, "'= "))
552 asprintf (&data
, "'%s'=%ld%s;", label
, val
, uom
);
554 asprintf (&data
, "%s=%ld%s;", label
, val
, uom
);
557 asprintf (&data
, "%s%ld;", data
, warn
);
559 asprintf (&data
, "%s;", data
);
562 asprintf (&data
, "%s%ld;", data
, crit
);
564 asprintf (&data
, "%s;", data
);
567 asprintf (&data
, "%s%ld", data
, minv
);
570 asprintf (&data
, "%s;%ld", data
, maxv
);
576 char *fperfdata (const char *label
,
590 if (strpbrk (label
, "'= "))
591 asprintf (&data
, "'%s'=", label
);
593 asprintf (&data
, "%s=", label
);
595 asprintf (&data
, "%s%f", data
, val
);
596 asprintf (&data
, "%s%s;", data
, uom
);
599 asprintf (&data
, "%s%f", data
, warn
);
601 asprintf (&data
, "%s;", data
);
604 asprintf (&data
, "%s%f", data
, crit
);
606 asprintf (&data
, "%s;", data
);
609 asprintf (&data
, "%s%f", data
, minv
);
612 asprintf (&data
, "%s;", data
);
613 asprintf (&data
, "%s%f", data
, maxv
);