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\n", msg);
57 print_usage ();
58 exit (STATE_UNKNOWN);
59 }
61 void usage_va (const char *fmt, ...)
62 {
63 va_list ap;
64 printf("%s: ", progname);
65 va_start(ap, fmt);
66 vprintf(fmt, ap);
67 va_end(ap);
68 printf("\n");
69 exit (STATE_UNKNOWN);
70 }
72 void usage2(const char *msg, const char *arg)
73 {
74 printf ("%s: %s - %s\n",progname,msg,arg);
75 print_usage ();
76 exit (STATE_UNKNOWN);
77 }
79 void
80 usage3 (const char *msg, int arg)
81 {
82 printf ("%s: %s - %c\n", progname, msg, arg);
83 print_usage();
84 exit (STATE_UNKNOWN);
85 }
87 void
88 usage4 (const char *msg)
89 {
90 printf ("%s: %s\n", progname, msg);
91 print_usage();
92 exit (STATE_UNKNOWN);
93 }
95 char *
96 clean_revstring (const char *revstring)
97 {
98 char plugin_revision[STRLEN];
99 if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
100 return strscpy (NULL, plugin_revision);
101 else
102 return strscpy (NULL, "N/A");
103 }
105 void
106 print_revision (const char *command_name, const char *revision_string)
107 {
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);
114 }
116 const char *
117 state_text (int result)
118 {
119 switch (result) {
120 case STATE_OK:
121 return "OK";
122 case STATE_WARNING:
123 return "WARNING";
124 case STATE_CRITICAL:
125 return "CRITICAL";
126 case STATE_DEPENDENT:
127 return "DEPENDENT";
128 default:
129 return "UNKNOWN";
130 }
131 }
133 void
134 die (int result, const char *fmt, ...)
135 {
136 va_list ap;
137 va_start (ap, fmt);
138 vprintf (fmt, ap);
139 va_end (ap);
140 exit (result);
141 }
143 void
144 timeout_alarm_handler (int signo)
145 {
146 if (signo == SIGALRM) {
147 printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
148 timeout_interval);
149 exit (STATE_CRITICAL);
150 }
151 }
153 int
154 is_numeric (char *number)
155 {
156 char tmp[1];
157 float x;
159 if (!number)
160 return FALSE;
161 else if (sscanf (number, "%f%c", &x, tmp) == 1)
162 return TRUE;
163 else
164 return FALSE;
165 }
167 int
168 is_positive (char *number)
169 {
170 if (is_numeric (number) && atof (number) > 0.0)
171 return TRUE;
172 else
173 return FALSE;
174 }
176 int
177 is_negative (char *number)
178 {
179 if (is_numeric (number) && atof (number) < 0.0)
180 return TRUE;
181 else
182 return FALSE;
183 }
185 int
186 is_nonnegative (char *number)
187 {
188 if (is_numeric (number) && atof (number) >= 0.0)
189 return TRUE;
190 else
191 return FALSE;
192 }
194 int
195 is_percentage (char *number)
196 {
197 int x;
198 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
199 return TRUE;
200 else
201 return FALSE;
202 }
204 int
205 is_integer (char *number)
206 {
207 long int n;
209 if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
210 return FALSE;
212 n = strtol (number, NULL, 10);
214 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
215 return TRUE;
216 else
217 return FALSE;
218 }
220 int
221 is_intpos (char *number)
222 {
223 if (is_integer (number) && atoi (number) > 0)
224 return TRUE;
225 else
226 return FALSE;
227 }
229 int
230 is_intneg (char *number)
231 {
232 if (is_integer (number) && atoi (number) < 0)
233 return TRUE;
234 else
235 return FALSE;
236 }
238 int
239 is_intnonneg (char *number)
240 {
241 if (is_integer (number) && atoi (number) >= 0)
242 return TRUE;
243 else
244 return FALSE;
245 }
247 int
248 is_intpercent (char *number)
249 {
250 int i;
251 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
252 return TRUE;
253 else
254 return FALSE;
255 }
257 int
258 is_option (char *str)
259 {
260 if (!str)
261 return FALSE;
262 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
263 return TRUE;
264 else
265 return FALSE;
266 }
270 #ifdef NEED_GETTIMEOFDAY
271 int
272 gettimeofday (struct timeval *tv, struct timezone *tz)
273 {
274 tv->tv_usec = 0;
275 tv->tv_sec = (long) time ((time_t) 0);
276 }
277 #endif
281 double
282 delta_time (struct timeval tv)
283 {
284 struct timeval now;
286 gettimeofday (&now, NULL);
287 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
288 }
292 long
293 deltime (struct timeval tv)
294 {
295 struct timeval now;
296 gettimeofday (&now, NULL);
297 return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
298 }
303 void
304 strip (char *buffer)
305 {
306 size_t x;
307 int i;
309 for (x = strlen (buffer); x >= 1; x--) {
310 i = x - 1;
311 if (buffer[i] == ' ' ||
312 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
313 buffer[i] = '\0';
314 else
315 break;
316 }
317 return;
318 }
321 /******************************************************************************
322 *
323 * Copies one string to another. Any previously existing data in
324 * the destination string is lost.
325 *
326 * Example:
327 *
328 * char *str=NULL;
329 * str = strscpy("This is a line of text with no trailing newline");
330 *
331 *****************************************************************************/
333 char *
334 strscpy (char *dest, const char *src)
335 {
336 if (src == NULL)
337 return NULL;
339 asprintf (&dest, "%s", src);
341 return dest;
342 }
346 /******************************************************************************
347 *
348 * Returns a pointer to the next line of a multiline string buffer
349 *
350 * Given a pointer string, find the text following the next sequence
351 * of \r and \n characters. This has the effect of skipping blank
352 * lines as well
353 *
354 * Example:
355 *
356 * Given text as follows:
357 *
358 * ==============================
359 * This
360 * is
361 * a
362 *
363 * multiline string buffer
364 * ==============================
365 *
366 * int i=0;
367 * char *str=NULL;
368 * char *ptr=NULL;
369 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
370 * ptr = str;
371 * while (ptr) {
372 * printf("%d %s",i++,firstword(ptr));
373 * ptr = strnl(ptr);
374 * }
375 *
376 * Produces the following:
377 *
378 * 1 This
379 * 2 is
380 * 3 a
381 * 4 multiline
382 *
383 * NOTE: The 'firstword()' function is conceptual only and does not
384 * exist in this package.
385 *
386 * NOTE: Although the second 'ptr' variable is not strictly needed in
387 * this example, it is good practice with these utilities. Once
388 * the * pointer is advance in this manner, it may no longer be
389 * handled with * realloc(). So at the end of the code fragment
390 * above, * strscpy(str,"foo") work perfectly fine, but
391 * strscpy(ptr,"foo") will * cause the the program to crash with
392 * a segmentation fault.
393 *
394 *****************************************************************************/
396 char *
397 strnl (char *str)
398 {
399 size_t len;
400 if (str == NULL)
401 return NULL;
402 str = strpbrk (str, "\r\n");
403 if (str == NULL)
404 return NULL;
405 len = strspn (str, "\r\n");
406 if (str[len] == '\0')
407 return NULL;
408 str += len;
409 if (strlen (str) == 0)
410 return NULL;
411 return str;
412 }
415 /******************************************************************************
416 *
417 * Like strscpy, except only the portion of the source string up to
418 * the provided delimiter is copied.
419 *
420 * Example:
421 *
422 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
423 * printf("%s\n",str);
424 *
425 * Produces:
426 *
427 *This is a line of te
428 *
429 *****************************************************************************/
431 char *
432 strpcpy (char *dest, const char *src, const char *str)
433 {
434 size_t len;
436 if (src)
437 len = strcspn (src, str);
438 else
439 return NULL;
441 if (dest == NULL || strlen (dest) < len)
442 dest = realloc (dest, len + 1);
443 if (dest == NULL)
444 die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
446 strncpy (dest, src, len);
447 dest[len] = '\0';
449 return dest;
450 }
454 /******************************************************************************
455 *
456 * Like strscat, except only the portion of the source string up to
457 * the provided delimiter is copied.
458 *
459 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
460 * str = strpcat(str,"This is a line of text with no trailing newline","x");
461 * printf("%s\n",str);
462 *
463 *This is a line of texThis is a line of tex
464 *
465 *****************************************************************************/
467 char *
468 strpcat (char *dest, const char *src, const char *str)
469 {
470 size_t len, l2;
472 if (dest)
473 len = strlen (dest);
474 else
475 len = 0;
477 if (src) {
478 l2 = strcspn (src, str);
479 }
480 else {
481 return dest;
482 }
484 dest = realloc (dest, len + l2 + 1);
485 if (dest == NULL)
486 die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
488 strncpy (dest + len, src, l2);
489 dest[len + l2] = '\0';
491 return dest;
492 }
495 /******************************************************************************
496 *
497 * Print perfdata in a standard format
498 *
499 ******************************************************************************/
501 char *perfdata (const char *label,
502 long int val,
503 const char *uom,
504 int warnp,
505 long int warn,
506 int critp,
507 long int crit,
508 int minp,
509 long int minv,
510 int maxp,
511 long int maxv)
512 {
513 char *data = NULL;
515 if (strpbrk (label, "'= "))
516 asprintf (&data, "'%s'=%ld%s;", label, val, uom);
517 else
518 asprintf (&data, "%s=%ld%s;", label, val, uom);
520 if (warnp)
521 asprintf (&data, "%s%ld;", data, warn);
522 else
523 asprintf (&data, "%s;", data);
525 if (critp)
526 asprintf (&data, "%s%ld;", data, crit);
527 else
528 asprintf (&data, "%s;", data);
530 if (minp)
531 asprintf (&data, "%s%ld", data, minv);
533 if (maxp)
534 asprintf (&data, "%s;%ld", data, maxv);
536 return data;
537 }
540 char *fperfdata (const char *label,
541 double val,
542 const char *uom,
543 int warnp,
544 double warn,
545 int critp,
546 double crit,
547 int minp,
548 double minv,
549 int maxp,
550 double maxv)
551 {
552 char *data = NULL;
554 if (strpbrk (label, "'= "))
555 asprintf (&data, "'%s'=", label);
556 else
557 asprintf (&data, "%s=", label);
559 asprintf (&data, "%s%f", data, val);
560 asprintf (&data, "%s%s;", data, uom);
562 if (warnp)
563 asprintf (&data, "%s%f", data, warn);
565 asprintf (&data, "%s;", data);
567 if (critp)
568 asprintf (&data, "%s%f", data, crit);
570 asprintf (&data, "%s;", data);
572 if (minp)
573 asprintf (&data, "%s%f", data, minv);
575 if (maxp) {
576 asprintf (&data, "%s;", data);
577 asprintf (&data, "%s%f", data, maxv);
578 }
580 return data;
581 }