Revert "Make use of xasprintf instead of asprintf"
[monitoring-plugins.git] / plugins / utils.c
blob58b153d8b58336a8a7066931d007e6af9d183f53
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 Monitoring Plugins Development Team
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************/
25 #include "common.h"
26 #include "utils.h"
27 #include "utils_base.h"
28 #include <stdarg.h>
29 #include <limits.h>
31 #include <arpa/inet.h>
33 extern void print_usage (void);
34 extern const char *progname;
36 #define STRLEN 64
37 #define TXTBLK 128
39 unsigned int timeout_state = STATE_CRITICAL;
40 unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
42 time_t start_time, end_time;
44 /* **************************************************************************
45 * max_state(STATE_x, STATE_y)
46 * compares STATE_x to STATE_y and returns result based on the following
47 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
49 * Note that numerically the above does not hold
50 ****************************************************************************/
52 int
53 max_state (int a, int b)
55 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
56 return STATE_CRITICAL;
57 else if (a == STATE_WARNING || b == STATE_WARNING)
58 return STATE_WARNING;
59 else if (a == STATE_OK || b == STATE_OK)
60 return STATE_OK;
61 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
62 return STATE_UNKNOWN;
63 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
64 return STATE_DEPENDENT;
65 else
66 return max (a, b);
69 /* **************************************************************************
70 * max_state_alt(STATE_x, STATE_y)
71 * compares STATE_x to STATE_y and returns result based on the following
72 * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
74 * The main difference between max_state_alt and max_state it that it doesn't
75 * allow setting a default to UNKNOWN. It will instead prioritixe any valid
76 * non-OK state.
77 ****************************************************************************/
79 int
80 max_state_alt (int a, int b)
82 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
83 return STATE_CRITICAL;
84 else if (a == STATE_WARNING || b == STATE_WARNING)
85 return STATE_WARNING;
86 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
87 return STATE_UNKNOWN;
88 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
89 return STATE_DEPENDENT;
90 else if (a == STATE_OK || b == STATE_OK)
91 return STATE_OK;
92 else
93 return max (a, b);
96 void usage (const char *msg)
98 printf ("%s\n", msg);
99 print_usage ();
100 exit (STATE_UNKNOWN);
103 void usage_va (const char *fmt, ...)
105 va_list ap;
106 printf("%s: ", progname);
107 va_start(ap, fmt);
108 vprintf(fmt, ap);
109 va_end(ap);
110 printf("\n");
111 exit (STATE_UNKNOWN);
114 void usage2(const char *msg, const char *arg)
116 printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
117 print_usage ();
118 exit (STATE_UNKNOWN);
121 void
122 usage3 (const char *msg, int arg)
124 printf ("%s: %s - %c\n", progname, msg, arg);
125 print_usage();
126 exit (STATE_UNKNOWN);
129 void
130 usage4 (const char *msg)
132 printf ("%s: %s\n", progname, msg);
133 print_usage();
134 exit (STATE_UNKNOWN);
137 void
138 usage5 (void)
140 print_usage();
141 exit (STATE_UNKNOWN);
144 void
145 print_revision (const char *command_name, const char *revision)
147 char plugin_revision[STRLEN];
149 printf ("%s v%s (%s %s)\n",
150 command_name, revision, PACKAGE, VERSION);
153 const char *
154 state_text (int result)
156 switch (result) {
157 case STATE_OK:
158 return "OK";
159 case STATE_WARNING:
160 return "WARNING";
161 case STATE_CRITICAL:
162 return "CRITICAL";
163 case STATE_DEPENDENT:
164 return "DEPENDENT";
165 default:
166 return "UNKNOWN";
170 void
171 timeout_alarm_handler (int signo)
173 if (signo == SIGALRM) {
174 printf (_("%s - Plugin timed out after %d seconds\n"),
175 state_text(timeout_state), timeout_interval);
176 exit (timeout_state);
181 is_numeric (char *number)
183 char tmp[1];
184 float x;
186 if (!number)
187 return FALSE;
188 else if (sscanf (number, "%f%c", &x, tmp) == 1)
189 return TRUE;
190 else
191 return FALSE;
195 is_positive (char *number)
197 if (is_numeric (number) && atof (number) > 0.0)
198 return TRUE;
199 else
200 return FALSE;
204 is_negative (char *number)
206 if (is_numeric (number) && atof (number) < 0.0)
207 return TRUE;
208 else
209 return FALSE;
213 is_nonnegative (char *number)
215 if (is_numeric (number) && atof (number) >= 0.0)
216 return TRUE;
217 else
218 return FALSE;
222 is_percentage (char *number)
224 int x;
225 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
226 return TRUE;
227 else
228 return FALSE;
232 is_integer (char *number)
234 long int n;
236 if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
237 return FALSE;
239 n = strtol (number, NULL, 10);
241 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
242 return TRUE;
243 else
244 return FALSE;
248 is_intpos (char *number)
250 if (is_integer (number) && atoi (number) > 0)
251 return TRUE;
252 else
253 return FALSE;
257 is_intneg (char *number)
259 if (is_integer (number) && atoi (number) < 0)
260 return TRUE;
261 else
262 return FALSE;
266 is_intnonneg (char *number)
268 if (is_integer (number) && atoi (number) >= 0)
269 return TRUE;
270 else
271 return FALSE;
275 is_intpercent (char *number)
277 int i;
278 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
279 return TRUE;
280 else
281 return FALSE;
285 is_option (char *str)
287 if (!str)
288 return FALSE;
289 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
290 return TRUE;
291 else
292 return FALSE;
295 #ifdef NEED_GETTIMEOFDAY
297 gettimeofday (struct timeval *tv, struct timezone *tz)
299 tv->tv_usec = 0;
300 tv->tv_sec = (long) time ((time_t) 0);
302 #endif
306 double
307 delta_time (struct timeval tv)
309 struct timeval now;
311 gettimeofday (&now, NULL);
312 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
317 long
318 deltime (struct timeval tv)
320 struct timeval now;
321 gettimeofday (&now, NULL);
322 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
328 void
329 strip (char *buffer)
331 size_t x;
332 int i;
334 for (x = strlen (buffer); x >= 1; x--) {
335 i = x - 1;
336 if (buffer[i] == ' ' ||
337 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
338 buffer[i] = '\0';
339 else
340 break;
342 return;
346 /******************************************************************************
348 * Copies one string to another. Any previously existing data in
349 * the destination string is lost.
351 * Example:
353 * char *str=NULL;
354 * str = strscpy("This is a line of text with no trailing newline");
356 *****************************************************************************/
358 char *
359 strscpy (char *dest, const char *src)
361 if (src == NULL)
362 return NULL;
364 xasprintf (&dest, "%s", src);
366 return dest;
371 /******************************************************************************
373 * Returns a pointer to the next line of a multiline string buffer
375 * Given a pointer string, find the text following the next sequence
376 * of \r and \n characters. This has the effect of skipping blank
377 * lines as well
379 * Example:
381 * Given text as follows:
383 * ==============================
384 * This
385 * is
388 * multiline string buffer
389 * ==============================
391 * int i=0;
392 * char *str=NULL;
393 * char *ptr=NULL;
394 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
395 * ptr = str;
396 * while (ptr) {
397 * printf("%d %s",i++,firstword(ptr));
398 * ptr = strnl(ptr);
401 * Produces the following:
403 * 1 This
404 * 2 is
405 * 3 a
406 * 4 multiline
408 * NOTE: The 'firstword()' function is conceptual only and does not
409 * exist in this package.
411 * NOTE: Although the second 'ptr' variable is not strictly needed in
412 * this example, it is good practice with these utilities. Once
413 * the * pointer is advance in this manner, it may no longer be
414 * handled with * realloc(). So at the end of the code fragment
415 * above, * strscpy(str,"foo") work perfectly fine, but
416 * strscpy(ptr,"foo") will * cause the the program to crash with
417 * a segmentation fault.
419 *****************************************************************************/
421 char *
422 strnl (char *str)
424 size_t len;
425 if (str == NULL)
426 return NULL;
427 str = strpbrk (str, "\r\n");
428 if (str == NULL)
429 return NULL;
430 len = strspn (str, "\r\n");
431 if (str[len] == '\0')
432 return NULL;
433 str += len;
434 if (strlen (str) == 0)
435 return NULL;
436 return str;
440 /******************************************************************************
442 * Like strscpy, except only the portion of the source string up to
443 * the provided delimiter is copied.
445 * Example:
447 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
448 * printf("%s\n",str);
450 * Produces:
452 *This is a line of te
454 *****************************************************************************/
456 char *
457 strpcpy (char *dest, const char *src, const char *str)
459 size_t len;
461 if (src)
462 len = strcspn (src, str);
463 else
464 return NULL;
466 if (dest == NULL || strlen (dest) < len)
467 dest = realloc (dest, len + 1);
468 if (dest == NULL)
469 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
471 strncpy (dest, src, len);
472 dest[len] = '\0';
474 return dest;
479 /******************************************************************************
481 * Like strscat, except only the portion of the source string up to
482 * the provided delimiter is copied.
484 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
485 * str = strpcat(str,"This is a line of text with no trailing newline","x");
486 * printf("%s\n",str);
488 *This is a line of texThis is a line of tex
490 *****************************************************************************/
492 char *
493 strpcat (char *dest, const char *src, const char *str)
495 size_t len, l2;
497 if (dest)
498 len = strlen (dest);
499 else
500 len = 0;
502 if (src) {
503 l2 = strcspn (src, str);
505 else {
506 return dest;
509 dest = realloc (dest, len + l2 + 1);
510 if (dest == NULL)
511 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
513 strncpy (dest + len, src, l2);
514 dest[len + l2] = '\0';
516 return dest;
520 /******************************************************************************
522 * asprintf, but die on failure
524 ******************************************************************************/
527 xvasprintf (char **strp, const char *fmt, va_list ap)
529 int result = vasprintf (strp, fmt, ap);
530 if (result == -1 || *strp == NULL)
531 die (STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
532 return result;
536 xasprintf (char **strp, const char *fmt, ...)
538 va_list ap;
539 int result;
540 va_start (ap, fmt);
541 result = xvasprintf (strp, fmt, ap);
542 va_end (ap);
543 return result;
546 /******************************************************************************
548 * Print perfdata in a standard format
550 ******************************************************************************/
552 char *perfdata (const char *label,
553 long int val,
554 const char *uom,
555 int warnp,
556 long int warn,
557 int critp,
558 long int crit,
559 int minp,
560 long int minv,
561 int maxp,
562 long int maxv)
564 char *data = NULL;
566 if (strpbrk (label, "'= "))
567 xasprintf (&data, "'%s'=%ld%s;", label, val, uom);
568 else
569 xasprintf (&data, "%s=%ld%s;", label, val, uom);
571 if (warnp)
572 xasprintf (&data, "%s%ld;", data, warn);
573 else
574 xasprintf (&data, "%s;", data);
576 if (critp)
577 xasprintf (&data, "%s%ld;", data, crit);
578 else
579 xasprintf (&data, "%s;", data);
581 if (minp)
582 xasprintf (&data, "%s%ld", data, minv);
584 if (maxp)
585 xasprintf (&data, "%s;%ld", data, maxv);
587 return data;
591 char *fperfdata (const char *label,
592 double val,
593 const char *uom,
594 int warnp,
595 double warn,
596 int critp,
597 double crit,
598 int minp,
599 double minv,
600 int maxp,
601 double maxv)
603 char *data = NULL;
605 if (strpbrk (label, "'= "))
606 xasprintf (&data, "'%s'=", label);
607 else
608 xasprintf (&data, "%s=", label);
610 xasprintf (&data, "%s%f", data, val);
611 xasprintf (&data, "%s%s;", data, uom);
613 if (warnp)
614 xasprintf (&data, "%s%f", data, warn);
616 xasprintf (&data, "%s;", data);
618 if (critp)
619 xasprintf (&data, "%s%f", data, crit);
621 xasprintf (&data, "%s;", data);
623 if (minp)
624 xasprintf (&data, "%s%f", data, minv);
626 if (maxp) {
627 xasprintf (&data, "%s;", data);
628 xasprintf (&data, "%s%f", data, maxv);
631 return data;