1 /*****************************************************************************
2 *
3 * utils.c
4 *
5 * Library of useful functions for plugins
6 *
7 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
8 * License: GPL
9 *
10 * $Revision$
11 * $Date$
12 ****************************************************************************/
14 #define LOCAL_TIMEOUT_ALARM_HANDLER
16 #include "common.h"
17 #include "utils.h"
18 #include <stdarg.h>
19 #include <limits.h>
21 #include <arpa/inet.h>
23 extern void print_usage (void);
24 extern const char *progname;
26 #define STRLEN 64
27 #define TXTBLK 128
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
33 *
34 * Note that numerically the above does not hold
35 ****************************************************************************/
37 int
38 max_state (int a, int b)
39 {
40 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
41 return STATE_CRITICAL;
42 else if (a == STATE_WARNING || b == STATE_WARNING)
43 return STATE_WARNING;
44 else if (a == STATE_OK || b == STATE_OK)
45 return STATE_OK;
46 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
47 return STATE_UNKNOWN;
48 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
49 return STATE_DEPENDENT;
50 else
51 return max (a, b);
52 }
54 void usage (const char *msg)
55 {
56 printf ("%s", msg);
57 print_usage ();
58 exit (STATE_UNKNOWN);
59 }
61 void usage2(const char *msg, const char *arg)
62 {
63 printf ("%s: %s - %s\n",progname,msg,arg);
64 print_usage ();
65 exit (STATE_UNKNOWN);
66 }
68 void
69 usage3 (const char *msg, int arg)
70 {
71 printf ("%s: %s - %c\n", progname, msg, arg);
72 print_usage();
73 exit (STATE_UNKNOWN);
74 }
77 void
78 support (void)
79 {
80 printf (_("\n\
81 Send email to nagios-users@lists.sourceforge.net if you have questions\n\
82 regarding use of this software. To submit patches or suggest improvements,\n\
83 send email to nagiosplug-devel@lists.sourceforge.net\n"));
84 }
87 char *
88 clean_revstring (const char *revstring)
89 {
90 char plugin_revision[STRLEN];
91 if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
92 return strscpy (NULL, plugin_revision);
93 else
94 return strscpy (NULL, "N/A");
95 }
97 void
98 print_revision (const char *command_name, const char *revision_string)
99 {
100 char plugin_revision[STRLEN];
102 if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
103 strncpy (plugin_revision, "N/A", STRLEN);
104 printf ("%s (%s %s) %s\n",
105 command_name, PACKAGE, VERSION, plugin_revision);
106 printf (_("\
107 The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n\
108 copies of the plugins under the terms of the GNU General Public License.\n\
109 For more information about these matters, see the file named COPYING.\n"));
111 }
113 const char *
114 state_text (int result)
115 {
116 switch (result) {
117 case STATE_OK:
118 return "OK";
119 case STATE_WARNING:
120 return "WARNING";
121 case STATE_CRITICAL:
122 return "CRITICAL";
123 case STATE_DEPENDENT:
124 return "DEPENDENT";
125 default:
126 return "UNKNOWN";
127 }
128 }
130 void
131 die (int result, const char *fmt, ...)
132 {
133 va_list ap;
134 va_start (ap, fmt);
135 vprintf (fmt, ap);
136 va_end (ap);
137 exit (result);
138 }
140 void
141 timeout_alarm_handler (int signo)
142 {
143 if (signo == SIGALRM) {
144 printf ("CRITICAL - Plugin timed out after %d seconds\n",
145 timeout_interval);
146 exit (STATE_CRITICAL);
147 }
148 }
150 int
151 is_numeric (char *number)
152 {
153 char tmp[1];
154 float x;
156 if (!number)
157 return FALSE;
158 else if (sscanf (number, "%f%c", &x, tmp) == 1)
159 return TRUE;
160 else
161 return FALSE;
162 }
164 int
165 is_positive (char *number)
166 {
167 if (is_numeric (number) && atof (number) > 0.0)
168 return TRUE;
169 else
170 return FALSE;
171 }
173 int
174 is_negative (char *number)
175 {
176 if (is_numeric (number) && atof (number) < 0.0)
177 return TRUE;
178 else
179 return FALSE;
180 }
182 int
183 is_nonnegative (char *number)
184 {
185 if (is_numeric (number) && atof (number) >= 0.0)
186 return TRUE;
187 else
188 return FALSE;
189 }
191 int
192 is_percentage (char *number)
193 {
194 int x;
195 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
196 return TRUE;
197 else
198 return FALSE;
199 }
201 int
202 is_integer (char *number)
203 {
204 long int n;
206 if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
207 return FALSE;
209 n = strtol (number, NULL, 10);
211 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
212 return TRUE;
213 else
214 return FALSE;
215 }
217 int
218 is_intpos (char *number)
219 {
220 if (is_integer (number) && atoi (number) > 0)
221 return TRUE;
222 else
223 return FALSE;
224 }
226 int
227 is_intneg (char *number)
228 {
229 if (is_integer (number) && atoi (number) < 0)
230 return TRUE;
231 else
232 return FALSE;
233 }
235 int
236 is_intnonneg (char *number)
237 {
238 if (is_integer (number) && atoi (number) >= 0)
239 return TRUE;
240 else
241 return FALSE;
242 }
244 int
245 is_intpercent (char *number)
246 {
247 int i;
248 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
249 return TRUE;
250 else
251 return FALSE;
252 }
254 int
255 is_option (char *str)
256 {
257 if (!str)
258 return FALSE;
259 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
260 return TRUE;
261 else
262 return FALSE;
263 }
267 #ifdef NEED_GETTIMEOFDAY
268 int
269 gettimeofday (struct timeval *tv, struct timezone *tz)
270 {
271 tv->tv_usec = 0;
272 tv->tv_sec = (long) time ((time_t) 0);
273 }
274 #endif
278 double
279 delta_time (struct timeval tv)
280 {
281 struct timeval now;
283 gettimeofday (&now, NULL);
284 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
285 }
289 long
290 deltime (struct timeval tv)
291 {
292 struct timeval now;
293 gettimeofday (&now, NULL);
294 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
295 }
300 void
301 strip (char *buffer)
302 {
303 size_t x;
304 int i;
306 for (x = strlen (buffer); x >= 1; x--) {
307 i = x - 1;
308 if (buffer[i] == ' ' ||
309 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
310 buffer[i] = '\0';
311 else
312 break;
313 }
314 return;
315 }
318 /******************************************************************************
319 *
320 * Copies one string to another. Any previously existing data in
321 * the destination string is lost.
322 *
323 * Example:
324 *
325 * char *str=NULL;
326 * str = strscpy("This is a line of text with no trailing newline");
327 *
328 *****************************************************************************/
330 char *
331 strscpy (char *dest, const char *src)
332 {
333 if (src == NULL)
334 return NULL;
336 asprintf (&dest, "%s", src);
338 return dest;
339 }
343 /******************************************************************************
344 *
345 * Returns a pointer to the next line of a multiline string buffer
346 *
347 * Given a pointer string, find the text following the next sequence
348 * of \r and \n characters. This has the effect of skipping blank
349 * lines as well
350 *
351 * Example:
352 *
353 * Given text as follows:
354 *
355 * ==============================
356 * This
357 * is
358 * a
359 *
360 * multiline string buffer
361 * ==============================
362 *
363 * int i=0;
364 * char *str=NULL;
365 * char *ptr=NULL;
366 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
367 * ptr = str;
368 * while (ptr) {
369 * printf("%d %s",i++,firstword(ptr));
370 * ptr = strnl(ptr);
371 * }
372 *
373 * Produces the following:
374 *
375 * 1 This
376 * 2 is
377 * 3 a
378 * 4 multiline
379 *
380 * NOTE: The 'firstword()' function is conceptual only and does not
381 * exist in this package.
382 *
383 * NOTE: Although the second 'ptr' variable is not strictly needed in
384 * this example, it is good practice with these utilities. Once
385 * the * pointer is advance in this manner, it may no longer be
386 * handled with * realloc(). So at the end of the code fragment
387 * above, * strscpy(str,"foo") work perfectly fine, but
388 * strscpy(ptr,"foo") will * cause the the program to crash with
389 * a segmentation fault.
390 *
391 *****************************************************************************/
393 char *
394 strnl (char *str)
395 {
396 size_t len;
397 if (str == NULL)
398 return NULL;
399 str = strpbrk (str, "\r\n");
400 if (str == NULL)
401 return NULL;
402 len = strspn (str, "\r\n");
403 if (str[len] == '\0')
404 return NULL;
405 str += len;
406 if (strlen (str) == 0)
407 return NULL;
408 return str;
409 }
412 /******************************************************************************
413 *
414 * Like strscpy, except only the portion of the source string up to
415 * the provided delimiter is copied.
416 *
417 * Example:
418 *
419 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
420 * printf("%s\n",str);
421 *
422 * Produces:
423 *
424 *This is a line of te
425 *
426 *****************************************************************************/
428 char *
429 strpcpy (char *dest, const char *src, const char *str)
430 {
431 size_t len;
433 if (src)
434 len = strcspn (src, str);
435 else
436 return NULL;
438 if (dest == NULL || strlen (dest) < len)
439 dest = realloc (dest, len + 1);
440 if (dest == NULL)
441 die (STATE_UNKNOWN, "failed realloc in strpcpy\n");
443 strncpy (dest, src, len);
444 dest[len] = '\0';
446 return dest;
447 }
451 /******************************************************************************
452 *
453 * Like strscat, except only the portion of the source string up to
454 * the provided delimiter is copied.
455 *
456 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
457 * str = strpcat(str,"This is a line of text with no trailing newline","x");
458 * printf("%s\n",str);
459 *
460 *This is a line of texThis is a line of tex
461 *
462 *****************************************************************************/
464 char *
465 strpcat (char *dest, const char *src, const char *str)
466 {
467 size_t len, l2;
469 if (dest)
470 len = strlen (dest);
471 else
472 len = 0;
474 if (src) {
475 l2 = strcspn (src, str);
476 }
477 else {
478 return dest;
479 }
481 dest = realloc (dest, len + l2 + 1);
482 if (dest == NULL)
483 die (STATE_UNKNOWN, "failed malloc in strscat\n");
485 strncpy (dest + len, src, l2);
486 dest[len + l2] = '\0';
488 return dest;
489 }
492 /******************************************************************************
493 *
494 * Print perfdata in a standard format
495 *
496 ******************************************************************************/
498 char *perfdata (const char *label,
499 long int val,
500 const char *uom,
501 int warnp,
502 long int warn,
503 int critp,
504 long int crit,
505 int minp,
506 long int minv,
507 int maxp,
508 long int maxv)
509 {
510 char *data = NULL;
512 if (strpbrk (label, "'= "))
513 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
514 else
515 asprintf (&data, "%s=%ld%s;", label, val, uom);
517 if (warnp)
518 asprintf (&data, "%s%ld;", data, warn);
519 else
520 asprintf (&data, "%s;", data);
522 if (critp)
523 asprintf (&data, "%s%ld;", data, crit);
524 else
525 asprintf (&data, "%s;", data);
527 if (minp)
528 asprintf (&data, "%s%ld", data, minv);
530 if (maxp)
531 asprintf (&data, "%s;%ld", data, maxv);
533 return data;
534 }
537 char *fperfdata (const char *label,
538 double val,
539 const char *uom,
540 int warnp,
541 double warn,
542 int critp,
543 double crit,
544 int minp,
545 double minv,
546 int maxp,
547 double maxv)
548 {
549 char *data = NULL;
551 if (strpbrk (label, "'= "))
552 asprintf (&data, "'%s'=", label);
553 else
554 asprintf (&data, "%s=", label);
556 asprintf (&data, "%s%f", data, val);
557 asprintf (&data, "%s%s;", data, uom);
559 if (warnp)
560 asprintf (&data, "%s%f", data, warn);
562 asprintf (&data, "%s;", data);
564 if (critp)
565 asprintf (&data, "%s%f", data, crit);
567 asprintf (&data, "%s;", data);
569 if (minp)
570 asprintf (&data, "%s%f", data, minv);
572 if (maxp) {
573 asprintf (&data, "%s;", data);
574 asprintf (&data, "%s%f", data, maxv);
575 }
577 return data;
578 }