5dc6cfdbc5502dc4a6e8f31bb0e0feea20e4f51b
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 #include "config.h"
15 #include "common.h"
16 #include "version.h"
17 #include <stdarg.h>
18 #include <limits.h>
20 extern int timeout_interval;
22 char *my_basename (char *);
23 void support (void);
24 char *clean_revstring (const char *);
25 void print_revision (char *, const char *);
26 void terminate (int, const char *fmt, ...);
27 RETSIGTYPE timeout_alarm_handler (int);
29 int is_host (char *);
30 int is_dotted_quad (char *);
31 int is_hostname (char *);
33 int is_integer (char *);
34 int is_intpos (char *);
35 int is_intneg (char *);
36 int is_intnonneg (char *);
37 int is_intpercent (char *);
39 int is_numeric (char *);
40 int is_positive (char *);
41 int is_negative (char *);
42 int is_nonnegative (char *);
43 int is_percentage (char *);
45 int is_option (char *str);
47 double delta_time (struct timeval tv);
49 void strip (char *);
50 char *strscpy (char *dest, const char *src);
51 char *strscat (char *dest, const char *src);
52 char *strnl (char *str);
53 char *strpcpy (char *dest, const char *src, const char *str);
54 char *strpcat (char *dest, const char *src, const char *str);
56 #define LABELLEN 63
57 #define STRLEN 64
58 #define TXTBLK 128
60 #define max(a,b) ((a)>(b))?(a):(b)
62 /* **************************************************************************
63 * max_state(result, STATE_x)
64 * compares STATE_x to result and returns result if STATE_x is less than a based on the following
65 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
66 *
67 * Note that numerically the above does not hold
68 ****************************************************************************/
70 int
71 max_state(int a, int b)
72 {
73 if(a == STATE_CRITICAL){
74 return a;
75 }
76 else if (a == STATE_WARNING) {
78 if (b == STATE_CRITICAL){
79 return b;
80 }else {
81 return a;
82 }
83 }
84 else if (a == STATE_OK) {
86 if ( b== STATE_CRITICAL || b == STATE_WARNING) {
87 return b;
88 }else{
89 return a;
90 }
91 }
92 else {
93 /* a == UNKNOWN */
94 return b;
95 }
98 }
100 char *
101 my_basename (char *path)
102 {
103 if (!strstr (path, "/"))
104 return path;
105 else
106 return 1 + strrchr (path, '/');
107 }
110 void
111 support (void)
112 {
113 printf
114 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
115 "regarding use of this software. To submit patches or suggest improvements,\n"
116 "send email to nagiosplug-devel@lists.sourceforge.net\n");
117 }
120 char *
121 clean_revstring (const char *revstring)
122 {
123 char plugin_revision[STRLEN];
124 if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
125 return strscpy (NULL, plugin_revision);
126 else
127 return strscpy (NULL, "N/A");
128 }
130 void
131 print_revision (char *command_name, const char *revision_string)
132 {
133 char plugin_revision[STRLEN];
135 if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
136 strncpy (plugin_revision, "N/A", STRLEN);
137 printf ("%s (nagios-plugins %s) %s\n",
138 my_basename (command_name), VERSION, plugin_revision);
139 printf
140 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
141 "copies of the plugins under the terms of the GNU General Public License.\n"
142 "For more information about these matters, see the file named COPYING.\n");
144 }
147 void
148 terminate (int result, const char *fmt, ...)
149 {
150 va_list ap;
151 va_start (ap, fmt);
152 vprintf (fmt, ap);
153 va_end (ap);
154 exit (result);
155 }
157 void
158 timeout_alarm_handler (int signo)
159 {
160 if (signo == SIGALRM) {
161 printf ("CRITICAL - Plugin timed out after %d seconds\n",
162 timeout_interval);
163 exit (STATE_CRITICAL);
164 }
165 }
167 int
168 is_host (char *address)
169 {
170 if (is_dotted_quad (address) || is_hostname (address))
171 return (TRUE);
172 return (FALSE);
173 }
175 int
176 is_dotted_quad (char *address)
177 {
178 int o1, o2, o3, o4;
179 char c[1];
181 if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4)
182 return FALSE;
183 else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255)
184 return FALSE;
185 else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0)
186 return FALSE;
187 else
188 return TRUE;
189 }
191 /* from RFC-1035
192 *
193 * The labels must follow the rules for ARPANET host names. They must
194 * start with a letter, end with a letter or digit, and have as interior
195 * characters only letters, digits, and hyphen. There are also some
196 * restrictions on the length. Labels must be 63 characters or less. */
198 int
199 is_hostname (char *s1)
200 {
201 if (strlen (s1) > 63)
202 return FALSE;
203 if (strcspn
204 (s1,
205 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") !=
206 0) return FALSE;
207 if (strspn (s1, "0123456789-.") == 1)
208 return FALSE;
209 while ((s1 = index (s1, '.'))) {
210 s1++;
211 if (strspn (s1, "0123456789-.") == 1) {
212 printf ("%s\n", s1);
213 return FALSE;
214 }
215 }
216 return TRUE;
217 }
219 int
220 is_numeric (char *number)
221 {
222 char tmp[1];
223 float x;
224 if (sscanf (number, "%f%c", &x, tmp) == 1)
225 return (TRUE);
226 return (FALSE);
227 }
229 int
230 is_positive (char *number)
231 {
232 if (is_numeric (number) && atof (number) > 0.0)
233 return (TRUE);
234 return (FALSE);
235 }
237 int
238 is_negative (char *number)
239 {
240 if (is_numeric (number) && atof (number) < 0.0)
241 return (TRUE);
242 return (FALSE);
243 }
245 int
246 is_nonnegative (char *number)
247 {
248 if (is_numeric (number) && atof (number) >= 0.0)
249 return (TRUE);
250 return (FALSE);
251 }
253 int
254 is_percentage (char *number)
255 {
256 int x;
257 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
258 return (TRUE);
259 return (FALSE);
260 }
262 int
263 is_integer (char *number)
264 {
265 long int n;
267 if (strspn (number, "-0123456789 ") != strlen (number))
268 return (FALSE);
270 n = strtol (number, NULL, 10);
271 if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
272 return (TRUE);
273 return (FALSE);
274 }
276 int
277 is_intpos (char *number)
278 {
279 if (is_integer (number) && atoi (number) > 0)
280 return (TRUE);
281 return (FALSE);
282 }
284 int
285 is_intneg (char *number)
286 {
287 if (is_integer (number) && atoi (number) < 0)
288 return (TRUE);
289 return (FALSE);
290 }
292 int
293 is_intnonneg (char *number)
294 {
295 if (is_integer (number) && atoi (number) >= 0)
296 return (TRUE);
297 return (FALSE);
298 }
300 int
301 is_intpercent (char *number)
302 {
303 int i;
304 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
305 return (TRUE);
306 return (FALSE);
307 }
309 int
310 is_option (char *str)
311 {
312 if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
313 return TRUE;
314 return FALSE;
315 }
319 #ifndef HAVE_GETTIMEOFDAY
320 int
321 gettimeofday (struct timeval *tv, struct timezone *tz)
322 {
323 tv->tv_usec = 0;
324 tv->tv_sec = (long) time ((time_t) 0);
325 }
326 #endif
330 double
331 delta_time (struct timeval tv)
332 {
333 struct timeval now;
335 gettimeofday (&now, NULL);
336 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
337 }
342 void
343 strip (char *buffer)
344 {
345 size_t x;
346 int i;
348 for (x = strlen (buffer); x >= 1; x--) {
349 i = x - 1;
350 if (buffer[i] == ' ' ||
351 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
352 buffer[i] = '\0';
353 else
354 break;
355 }
356 return;
357 }
363 /******************************************************************************
364 *
365 * Copies one string to another. Any previously existing data in
366 * the destination string is lost.
367 *
368 * Example:
369 *
370 * char *str=NULL;
371 * str = strscpy("This is a line of text with no trailing newline");
372 *
373 *****************************************************************************/
375 char *
376 strscpy (char *dest, const char *src)
377 {
378 if (src == NULL)
379 return NULL;
381 asprintf (&dest, "%s", src);
383 return dest;
384 }
390 /******************************************************************************
391 *
392 * Concatenates one string to the end of another
393 *
394 * Given a pointer destination string, which may or may not already
395 * hold some text, and a source string with additional text (possibly
396 * NULL or empty), returns a pointer to a string that is the first
397 * string with the second concatenated to it. Uses realloc to free
398 * memory held by the dest argument if new storage space is required.
399 *
400 * Example:
401 *
402 * char *str=NULL;
403 * str = strscpy("This is a line of text with no trailing newline");
404 * str = strscat(str,"\n");
405 *
406 *****************************************************************************/
408 char *
409 strscat (char *dest, const char *src)
410 {
412 if (dest == NULL)
413 return src;
414 if (src != NULL)
415 asprintf (&dest, "%s%s", dest, src);
417 return dest;
418 }
424 /******************************************************************************
425 *
426 * Returns a pointer to the next line of a multiline string buffer
427 *
428 * Given a pointer string, find the text following the next sequence
429 * of \r and \n characters. This has the effect of skipping blank
430 * lines as well
431 *
432 * Example:
433 *
434 * Given text as follows:
435 *
436 * ==============================
437 * This
438 * is
439 * a
440 *
441 * multiline string buffer
442 * ==============================
443 *
444 * int i=0;
445 * char *str=NULL;
446 * char *ptr=NULL;
447 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
448 * ptr = str;
449 * while (ptr) {
450 * printf("%d %s",i++,firstword(ptr));
451 * ptr = strnl(ptr);
452 * }
453 *
454 * Produces the following:
455 *
456 * 1 This
457 * 2 is
458 * 3 a
459 * 4 multiline
460 *
461 * NOTE: The 'firstword()' function is conceptual only and does not
462 * exist in this package.
463 *
464 * NOTE: Although the second 'ptr' variable is not strictly needed in
465 * this example, it is good practice with these utilities. Once
466 * the * pointer is advance in this manner, it may no longer be
467 * handled with * realloc(). So at the end of the code fragment
468 * above, * strscpy(str,"foo") work perfectly fine, but
469 * strscpy(ptr,"foo") will * cause the the program to crash with
470 * a segmentation fault.
471 *
472 *****************************************************************************/
474 char *
475 strnl (char *str)
476 {
477 size_t len;
478 if (str == NULL)
479 return NULL;
480 str = strpbrk (str, "\r\n");
481 if (str == NULL)
482 return NULL;
483 len = strspn (str, "\r\n");
484 if (str[len] == '\0')
485 return NULL;
486 str += len;
487 if (strlen (str) == 0)
488 return NULL;
489 return str;
490 }
496 /******************************************************************************
497 *
498 * Like strscpy, except only the portion of the source string up to
499 * the provided delimiter is copied.
500 *
501 * Example:
502 *
503 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
504 * printf("%s\n",str);
505 *
506 * Produces:
507 *
508 *This is a line of te
509 *
510 *****************************************************************************/
512 char *
513 strpcpy (char *dest, const char *src, const char *str)
514 {
515 size_t len;
517 if (src)
518 len = strcspn (src, str);
519 else
520 return NULL;
522 if (dest == NULL || strlen (dest) < len)
523 dest = realloc (dest, len + 1);
524 if (dest == NULL)
525 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
527 strncpy (dest, src, len);
528 dest[len] = '\0';
530 return dest;
531 }
537 /******************************************************************************
538 *
539 * Like strscat, except only the portion of the source string up to
540 * the provided delimiter is copied.
541 *
542 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
543 * str = strpcat(str,"This is a line of text with no trailing newline","x");
544 * printf("%s\n",str);
545 *
546 *This is a line of texThis is a line of tex
547 *
548 *****************************************************************************/
550 char *
551 strpcat (char *dest, const char *src, const char *str)
552 {
553 size_t len, l2;
555 if (dest)
556 len = strlen (dest);
557 else
558 len = 0;
560 if (src) {
561 l2 = strcspn (src, str);
562 }
563 else {
564 return dest;
565 }
567 dest = realloc (dest, len + l2 + 1);
568 if (dest == NULL)
569 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
571 strncpy (dest + len, src, l2);
572 dest[len + l2] = '\0';
574 return dest;
575 }