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 * 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.
13 *
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.
18 *
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/>.
21 *
22 *
23 *****************************************************************************/
25 #define LOCAL_TIMEOUT_ALARM_HANDLER
27 #include "common.h"
28 #include "utils.h"
29 #include "utils_base.h"
30 #include <stdarg.h>
31 #include <limits.h>
33 #include <arpa/inet.h>
35 extern void print_usage (void);
36 extern const char *progname;
38 #define STRLEN 64
39 #define TXTBLK 128
41 /* **************************************************************************
42 * max_state(STATE_x, STATE_y)
43 * compares STATE_x to STATE_y and returns result based on the following
44 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
45 *
46 * Note that numerically the above does not hold
47 ****************************************************************************/
49 int
50 max_state (int a, int b)
51 {
52 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
53 return STATE_CRITICAL;
54 else if (a == STATE_WARNING || b == STATE_WARNING)
55 return STATE_WARNING;
56 else if (a == STATE_OK || b == STATE_OK)
57 return STATE_OK;
58 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
59 return STATE_UNKNOWN;
60 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
61 return STATE_DEPENDENT;
62 else
63 return max (a, b);
64 }
66 /* **************************************************************************
67 * max_state_alt(STATE_x, STATE_y)
68 * compares STATE_x to STATE_y and returns result based on the following
69 * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
70 *
71 * The main difference between max_state_alt and max_state it that it doesn't
72 * allow setting a default to UNKNOWN. It will instead prioritixe any valid
73 * non-OK state.
74 ****************************************************************************/
76 int
77 max_state_alt (int a, int b)
78 {
79 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
80 return STATE_CRITICAL;
81 else if (a == STATE_WARNING || b == STATE_WARNING)
82 return STATE_WARNING;
83 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
84 return STATE_UNKNOWN;
85 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
86 return STATE_DEPENDENT;
87 else if (a == STATE_OK || b == STATE_OK)
88 return STATE_OK;
89 else
90 return max (a, b);
91 }
93 void usage (const char *msg)
94 {
95 printf ("%s\n", msg);
96 print_usage ();
97 exit (STATE_UNKNOWN);
98 }
100 void usage_va (const char *fmt, ...)
101 {
102 va_list ap;
103 printf("%s: ", progname);
104 va_start(ap, fmt);
105 vprintf(fmt, ap);
106 va_end(ap);
107 printf("\n");
108 exit (STATE_UNKNOWN);
109 }
111 void usage2(const char *msg, const char *arg)
112 {
113 printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
114 print_usage ();
115 exit (STATE_UNKNOWN);
116 }
118 void
119 usage3 (const char *msg, int arg)
120 {
121 printf ("%s: %s - %c\n", progname, msg, arg);
122 print_usage();
123 exit (STATE_UNKNOWN);
124 }
126 void
127 usage4 (const char *msg)
128 {
129 printf ("%s: %s\n", progname, msg);
130 print_usage();
131 exit (STATE_UNKNOWN);
132 }
134 void
135 usage5 (void)
136 {
137 print_usage();
138 exit (STATE_UNKNOWN);
139 }
141 void
142 print_revision (const char *command_name, const char *revision)
143 {
144 char plugin_revision[STRLEN];
146 printf ("%s v%s (%s %s)\n",
147 command_name, revision, PACKAGE, VERSION);
148 }
150 const char *
151 state_text (int result)
152 {
153 switch (result) {
154 case STATE_OK:
155 return "OK";
156 case STATE_WARNING:
157 return "WARNING";
158 case STATE_CRITICAL:
159 return "CRITICAL";
160 case STATE_DEPENDENT:
161 return "DEPENDENT";
162 default:
163 return "UNKNOWN";
164 }
165 }
167 void
168 timeout_alarm_handler (int signo)
169 {
170 if (signo == SIGALRM) {
171 printf (_("%s - Plugin timed out after %d seconds\n"),
172 state_text(timeout_state), timeout_interval);
173 exit (timeout_state);
174 }
175 }
177 int
178 is_numeric (char *number)
179 {
180 char tmp[1];
181 float x;
183 if (!number)
184 return FALSE;
185 else if (sscanf (number, "%f%c", &x, tmp) == 1)
186 return TRUE;
187 else
188 return FALSE;
189 }
191 int
192 is_positive (char *number)
193 {
194 if (is_numeric (number) && atof (number) > 0.0)
195 return TRUE;
196 else
197 return FALSE;
198 }
200 int
201 is_negative (char *number)
202 {
203 if (is_numeric (number) && atof (number) < 0.0)
204 return TRUE;
205 else
206 return FALSE;
207 }
209 int
210 is_nonnegative (char *number)
211 {
212 if (is_numeric (number) && atof (number) >= 0.0)
213 return TRUE;
214 else
215 return FALSE;
216 }
218 int
219 is_percentage (char *number)
220 {
221 int x;
222 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
223 return TRUE;
224 else
225 return FALSE;
226 }
228 int
229 is_integer (char *number)
230 {
231 long int n;
233 if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
234 return FALSE;
236 n = strtol (number, NULL, 10);
238 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
239 return TRUE;
240 else
241 return FALSE;
242 }
244 int
245 is_intpos (char *number)
246 {
247 if (is_integer (number) && atoi (number) > 0)
248 return TRUE;
249 else
250 return FALSE;
251 }
253 int
254 is_intneg (char *number)
255 {
256 if (is_integer (number) && atoi (number) < 0)
257 return TRUE;
258 else
259 return FALSE;
260 }
262 int
263 is_intnonneg (char *number)
264 {
265 if (is_integer (number) && atoi (number) >= 0)
266 return TRUE;
267 else
268 return FALSE;
269 }
271 int
272 is_intpercent (char *number)
273 {
274 int i;
275 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
276 return TRUE;
277 else
278 return FALSE;
279 }
281 int
282 is_option (char *str)
283 {
284 if (!str)
285 return FALSE;
286 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
287 return TRUE;
288 else
289 return FALSE;
290 }
292 #ifdef NEED_GETTIMEOFDAY
293 int
294 gettimeofday (struct timeval *tv, struct timezone *tz)
295 {
296 tv->tv_usec = 0;
297 tv->tv_sec = (long) time ((time_t) 0);
298 }
299 #endif
303 double
304 delta_time (struct timeval tv)
305 {
306 struct timeval now;
308 gettimeofday (&now, NULL);
309 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
310 }
314 long
315 deltime (struct timeval tv)
316 {
317 struct timeval now;
318 gettimeofday (&now, NULL);
319 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
320 }
325 void
326 strip (char *buffer)
327 {
328 size_t x;
329 int i;
331 for (x = strlen (buffer); x >= 1; x--) {
332 i = x - 1;
333 if (buffer[i] == ' ' ||
334 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
335 buffer[i] = '\0';
336 else
337 break;
338 }
339 return;
340 }
343 /******************************************************************************
344 *
345 * Copies one string to another. Any previously existing data in
346 * the destination string is lost.
347 *
348 * Example:
349 *
350 * char *str=NULL;
351 * str = strscpy("This is a line of text with no trailing newline");
352 *
353 *****************************************************************************/
355 char *
356 strscpy (char *dest, const char *src)
357 {
358 if (src == NULL)
359 return NULL;
361 asprintf (&dest, "%s", src);
363 return dest;
364 }
368 /******************************************************************************
369 *
370 * Returns a pointer to the next line of a multiline string buffer
371 *
372 * Given a pointer string, find the text following the next sequence
373 * of \r and \n characters. This has the effect of skipping blank
374 * lines as well
375 *
376 * Example:
377 *
378 * Given text as follows:
379 *
380 * ==============================
381 * This
382 * is
383 * a
384 *
385 * multiline string buffer
386 * ==============================
387 *
388 * int i=0;
389 * char *str=NULL;
390 * char *ptr=NULL;
391 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
392 * ptr = str;
393 * while (ptr) {
394 * printf("%d %s",i++,firstword(ptr));
395 * ptr = strnl(ptr);
396 * }
397 *
398 * Produces the following:
399 *
400 * 1 This
401 * 2 is
402 * 3 a
403 * 4 multiline
404 *
405 * NOTE: The 'firstword()' function is conceptual only and does not
406 * exist in this package.
407 *
408 * NOTE: Although the second 'ptr' variable is not strictly needed in
409 * this example, it is good practice with these utilities. Once
410 * the * pointer is advance in this manner, it may no longer be
411 * handled with * realloc(). So at the end of the code fragment
412 * above, * strscpy(str,"foo") work perfectly fine, but
413 * strscpy(ptr,"foo") will * cause the the program to crash with
414 * a segmentation fault.
415 *
416 *****************************************************************************/
418 char *
419 strnl (char *str)
420 {
421 size_t len;
422 if (str == NULL)
423 return NULL;
424 str = strpbrk (str, "\r\n");
425 if (str == NULL)
426 return NULL;
427 len = strspn (str, "\r\n");
428 if (str[len] == '\0')
429 return NULL;
430 str += len;
431 if (strlen (str) == 0)
432 return NULL;
433 return str;
434 }
437 /******************************************************************************
438 *
439 * Like strscpy, except only the portion of the source string up to
440 * the provided delimiter is copied.
441 *
442 * Example:
443 *
444 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
445 * printf("%s\n",str);
446 *
447 * Produces:
448 *
449 *This is a line of te
450 *
451 *****************************************************************************/
453 char *
454 strpcpy (char *dest, const char *src, const char *str)
455 {
456 size_t len;
458 if (src)
459 len = strcspn (src, str);
460 else
461 return NULL;
463 if (dest == NULL || strlen (dest) < len)
464 dest = realloc (dest, len + 1);
465 if (dest == NULL)
466 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
468 strncpy (dest, src, len);
469 dest[len] = '\0';
471 return dest;
472 }
476 /******************************************************************************
477 *
478 * Like strscat, except only the portion of the source string up to
479 * the provided delimiter is copied.
480 *
481 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
482 * str = strpcat(str,"This is a line of text with no trailing newline","x");
483 * printf("%s\n",str);
484 *
485 *This is a line of texThis is a line of tex
486 *
487 *****************************************************************************/
489 char *
490 strpcat (char *dest, const char *src, const char *str)
491 {
492 size_t len, l2;
494 if (dest)
495 len = strlen (dest);
496 else
497 len = 0;
499 if (src) {
500 l2 = strcspn (src, str);
501 }
502 else {
503 return dest;
504 }
506 dest = realloc (dest, len + l2 + 1);
507 if (dest == NULL)
508 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
510 strncpy (dest + len, src, l2);
511 dest[len + l2] = '\0';
513 return dest;
514 }
516 /******************************************************************************
517 *
518 * Print perfdata in a standard format
519 *
520 ******************************************************************************/
522 char *perfdata (const char *label,
523 long int val,
524 const char *uom,
525 int warnp,
526 long int warn,
527 int critp,
528 long int crit,
529 int minp,
530 long int minv,
531 int maxp,
532 long int maxv)
533 {
534 char *data = NULL;
536 if (strpbrk (label, "'= "))
537 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
538 else
539 asprintf (&data, "%s=%ld%s;", label, val, uom);
541 if (warnp)
542 asprintf (&data, "%s%ld;", data, warn);
543 else
544 asprintf (&data, "%s;", data);
546 if (critp)
547 asprintf (&data, "%s%ld;", data, crit);
548 else
549 asprintf (&data, "%s;", data);
551 if (minp)
552 asprintf (&data, "%s%ld", data, minv);
554 if (maxp)
555 asprintf (&data, "%s;%ld", data, maxv);
557 return data;
558 }
561 char *fperfdata (const char *label,
562 double val,
563 const char *uom,
564 int warnp,
565 double warn,
566 int critp,
567 double crit,
568 int minp,
569 double minv,
570 int maxp,
571 double maxv)
572 {
573 char *data = NULL;
575 if (strpbrk (label, "'= "))
576 asprintf (&data, "'%s'=", label);
577 else
578 asprintf (&data, "%s=", label);
580 asprintf (&data, "%s%f", data, val);
581 asprintf (&data, "%s%s;", data, uom);
583 if (warnp)
584 asprintf (&data, "%s%f", data, warn);
586 asprintf (&data, "%s;", data);
588 if (critp)
589 asprintf (&data, "%s%f", data, crit);
591 asprintf (&data, "%s;", data);
593 if (minp)
594 asprintf (&data, "%s%f", data, minv);
596 if (maxp) {
597 asprintf (&data, "%s;", data);
598 asprintf (&data, "%s%f", data, maxv);
599 }
601 return data;
602 }