Code

bf6af8851c29d617dc1c1a873c36b6d29c9e5cc3
[nagiosplug.git] / plugins / utils.c
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, 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) {
85                 
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         }
96                 
98 }
100 char *
101 my_basename (char *path)
103         if (!strstr (path, "/"))
104                 return path;
105         else
106                 return 1 + strrchr (path, '/');
110 void
111 support (void)
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");
120 char *
121 clean_revstring (const char *revstring)
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");
130 void
131 print_revision (char *command_name, const char *revision_string)
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");
147 void
148 terminate (int result, const char *fmt, ...)
150         va_list ap;
151         va_start (ap, fmt);
152         vprintf (fmt, ap);
153         va_end (ap);
154         exit (result);
157 void
158 timeout_alarm_handler (int signo)
160         if (signo == SIGALRM) {
161                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
162                                                 timeout_interval);
163                 exit (STATE_CRITICAL);
164         }
167 int
168 is_host (char *address)
170         if (is_dotted_quad (address) || is_hostname (address))
171                 return (TRUE);
172         return (FALSE);
175 int
176 is_dotted_quad (char *address)
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;
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)
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;
219 int
220 is_numeric (char *number)
222         char tmp[1];
223         float x;
224         if (sscanf (number, "%f%c", &x, tmp) == 1)
225                 return (TRUE);
226         return (FALSE);
229 int
230 is_positive (char *number)
232         if (is_numeric (number) && atof (number) > 0.0)
233                 return (TRUE);
234         return (FALSE);
237 int
238 is_negative (char *number)
240         if (is_numeric (number) && atof (number) < 0.0)
241                 return (TRUE);
242         return (FALSE);
245 int
246 is_nonnegative (char *number)
248         if (is_numeric (number) && atof (number) >= 0.0)
249                 return (TRUE);
250         return (FALSE);
253 int
254 is_percentage (char *number)
256         int x;
257         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
258                 return (TRUE);
259         return (FALSE);
262 int
263 is_integer (char *number)
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);
276 int
277 is_intpos (char *number)
279         if (is_integer (number) && atoi (number) > 0)
280                 return (TRUE);
281         return (FALSE);
284 int
285 is_intneg (char *number)
287         if (is_integer (number) && atoi (number) < 0)
288                 return (TRUE);
289         return (FALSE);
292 int
293 is_intnonneg (char *number)
295         if (is_integer (number) && atoi (number) >= 0)
296                 return (TRUE);
297         return (FALSE);
300 int
301 is_intpercent (char *number)
303         int i;
304         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
305                 return (TRUE);
306         return (FALSE);
309 int
310 is_option (char *str)
312         if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
313                 return TRUE;
314         return FALSE;
319 #ifndef HAVE_GETTIMEOFDAY
320 int
321 gettimeofday (struct timeval *tv, struct timezone *tz)
323         tv->tv_usec = 0;
324         tv->tv_sec = (long) time ((time_t) 0);
326 #endif
330 double
331 delta_time (struct timeval tv)
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);
342 void
343 strip (char *buffer)
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;
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)
378         if (src == NULL)
379                 return NULL;
381         asprintf (&dest, "%s", src);
383         return dest;
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, char *src)
412         if (dest == NULL)
413                 return src;
414         if (src != NULL)
415                 asprintf (&dest, "%s%s", dest, src);
417         return dest;
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)
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;
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)
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;
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)
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;