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