Code

convert PROGANE from a define to a const char
[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;
21 extern const char *progname;
23 void support (void);
24 char *clean_revstring (const char *);
25 void print_revision (const 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 /* **************************************************************************
61  * max_state(STATE_x, STATE_y)
62  * compares STATE_x to  STATE_y and returns result based on the following
63  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
64  *
65  * Note that numerically the above does not hold
66  ****************************************************************************/
68 int
69 max_state (int a, int b)
70 {
71         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
72                 return STATE_CRITICAL;
73         else if (a == STATE_WARNING || b == STATE_WARNING)
74                 return STATE_WARNING;
75         else if (a == STATE_OK || b == STATE_OK)
76                 return STATE_OK;
77         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
78                 return STATE_UNKNOWN;
79         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
80                 return STATE_DEPENDENT;
81         else
82                 return max (a, b);
83 }
85 void usage (char *msg)
86 {
87         printf (msg);
88         print_usage ();
89         exit (STATE_UNKNOWN);
90 }
92 void usage2(char *msg, char *arg)
93 {
94         printf ("%s: %s - %s\n",progname,msg,arg);
95         print_usage ();
96         exit (STATE_UNKNOWN);
97 }
99 void
100 usage3 (char *msg, char arg)
102         printf ("%s: %s - %c\n", progname, msg, arg);
103         print_usage();
104         exit (STATE_UNKNOWN);
108 void
109 support (void)
111         printf
112                 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
113                  "regarding use of this software. To submit patches or suggest improvements,\n"
114                  "send email to nagiosplug-devel@lists.sourceforge.net\n");
118 char *
119 clean_revstring (const char *revstring)
121         char plugin_revision[STRLEN];
122         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
123                 return strscpy (NULL, plugin_revision);
124         else
125           return strscpy (NULL, "N/A");
128 void
129 print_revision (const char *command_name, const char *revision_string)
131         char plugin_revision[STRLEN];
133         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
134                 strncpy (plugin_revision, "N/A", STRLEN);
135         printf ("%s (nagios-plugins %s) %s\n",
136                                         progname, VERSION, plugin_revision);
137         printf
138                 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
139                  "copies of the plugins under the terms of the GNU General Public License.\n"
140                  "For more information about these matters, see the file named COPYING.\n");
145 void
146 terminate (int result, const char *fmt, ...)
148         va_list ap;
149         va_start (ap, fmt);
150         vprintf (fmt, ap);
151         va_end (ap);
152         exit (result);
155 void
156 timeout_alarm_handler (int signo)
158         if (signo == SIGALRM) {
159                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
160                                                 timeout_interval);
161                 exit (STATE_CRITICAL);
162         }
165 int
166 is_host (char *address)
168         if (is_dotted_quad (address) || is_hostname (address))
169                 return (TRUE);
170         return (FALSE);
173 int
174 is_dotted_quad (char *address)
176         int o1, o2, o3, o4;
177         char c[1];
179         if (!address)
180                 return FALSE;
182         if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4)
183                 return FALSE;
184         else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255)
185                 return FALSE;
186         else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0)
187                 return FALSE;
188         else
189                 return TRUE;
192 /* from RFC-1035
193  * 
194  * The labels must follow the rules for ARPANET host names.  They must
195  * start with a letter, end with a letter or digit, and have as interior
196  * characters only letters, digits, and hyphen.  There are also some
197  * restrictions on the length.  Labels must be 63 characters or less. */
199 int
200 is_hostname (char *s1)
202         if (!s1 || strlen (s1) > 63) {
203                 return FALSE;
204         }
205         if (strcspn (s1, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") != 0) {
206                 return FALSE;
207         }
208         if (strspn (s1, "0123456789-.") == 1) {
209                 return FALSE;
210         }
211         while ((s1 = index (s1, '.'))) {
212                 s1++;
213                 if (strspn (s1, "0123456789-.") == 1) {
214                         return FALSE;
215                 }
216         }
217         return TRUE;
220 int
221 is_numeric (char *number)
223         char tmp[1];
224         float x;
226         if (!number)
227                 return FALSE;
228         else if (sscanf (number, "%f%c", &x, tmp) == 1)
229                 return TRUE;
230         else
231                 return FALSE;
234 int
235 is_positive (char *number)
237         if (is_numeric (number) && atof (number) > 0.0)
238                 return TRUE;
239         else
240                 return FALSE;
243 int
244 is_negative (char *number)
246         if (is_numeric (number) && atof (number) < 0.0)
247                 return TRUE;
248         else
249                 return FALSE;
252 int
253 is_nonnegative (char *number)
255         if (is_numeric (number) && atof (number) >= 0.0)
256                 return TRUE;
257         else
258                 return FALSE;
261 int
262 is_percentage (char *number)
264         int x;
265         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
266                 return TRUE;
267         else
268                 return FALSE;
271 int
272 is_integer (char *number)
274         long int n;
276         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
277                 return FALSE;
279         n = strtol (number, NULL, 10);
281         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
282                 return TRUE;
283         else
284                 return FALSE;
287 int
288 is_intpos (char *number)
290         if (is_integer (number) && atoi (number) > 0)
291                 return TRUE;
292         else
293                 return FALSE;
296 int
297 is_intneg (char *number)
299         if (is_integer (number) && atoi (number) < 0)
300                 return TRUE;
301         else
302                 return FALSE;
305 int
306 is_intnonneg (char *number)
308         if (is_integer (number) && atoi (number) >= 0)
309                 return TRUE;
310         else
311                 return FALSE;
314 int
315 is_intpercent (char *number)
317         int i;
318         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
319                 return TRUE;
320         else
321                 return FALSE;
324 int
325 is_option (char *str)
327         if (!str)
328                 return FALSE;
329         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
330                 return TRUE;
331         else
332                 return FALSE;
337 #ifdef NEED_GETTIMEOFDAY
338 int
339 gettimeofday (struct timeval *tv, struct timezone *tz)
341         tv->tv_usec = 0;
342         tv->tv_sec = (long) time ((time_t) 0);
344 #endif
348 double
349 delta_time (struct timeval tv)
351         struct timeval now;
353         gettimeofday (&now, NULL);
354         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
360 void
361 strip (char *buffer)
363         size_t x;
364         int i;
366         for (x = strlen (buffer); x >= 1; x--) {
367                 i = x - 1;
368                 if (buffer[i] == ' ' ||
369                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
370                         buffer[i] = '\0';
371                 else
372                         break;
373         }
374         return;
381 /******************************************************************************
382  *
383  * Copies one string to another. Any previously existing data in
384  * the destination string is lost.
385  *
386  * Example:
387  *
388  * char *str=NULL;
389  * str = strscpy("This is a line of text with no trailing newline");
390  *
391  *****************************************************************************/
393 char *
394 strscpy (char *dest, const char *src)
396         if (src == NULL)
397                 return NULL;
399         asprintf (&dest, "%s", src);
401         return dest;
408 /******************************************************************************
409  *
410  * Concatenates one string to the end of another
411  *
412  * Given a pointer destination string, which may or may not already
413  * hold some text, and a source string with additional text (possibly
414  * NULL or empty), returns a pointer to a string that is the first
415  * string with the second concatenated to it. Uses realloc to free 
416  * memory held by the dest argument if new storage space is required.
417  *
418  * Example:
419  *
420  * char *str=NULL;
421  * str = strscpy("This is a line of text with no trailing newline");
422  * str = strscat(str,"\n");
423  *
424  *****************************************************************************/
426 char *
427 strscat (char *dest, char *src)
430         if (dest == NULL)
431                 return src;
432         if (src != NULL)
433                 asprintf (&dest, "%s%s", dest, src);
435         return dest;
442 /******************************************************************************
443  *
444  * Returns a pointer to the next line of a multiline string buffer
445  *
446  * Given a pointer string, find the text following the next sequence
447  * of \r and \n characters. This has the effect of skipping blank
448  * lines as well
449  *
450  * Example:
451  *
452  * Given text as follows:
453  *
454  * ==============================
455  * This
456  * is
457  * a
458  * 
459  * multiline string buffer
460  * ==============================
461  *
462  * int i=0;
463  * char *str=NULL;
464  * char *ptr=NULL;
465  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
466  * ptr = str;
467  * while (ptr) {
468  *   printf("%d %s",i++,firstword(ptr));
469  *   ptr = strnl(ptr);
470  * }
471  * 
472  * Produces the following:
473  *
474  * 1 This
475  * 2 is
476  * 3 a
477  * 4 multiline
478  *
479  * NOTE: The 'firstword()' function is conceptual only and does not
480  *       exist in this package.
481  *
482  * NOTE: Although the second 'ptr' variable is not strictly needed in
483  *       this example, it is good practice with these utilities. Once
484  *       the * pointer is advance in this manner, it may no longer be
485  *       handled with * realloc(). So at the end of the code fragment
486  *       above, * strscpy(str,"foo") work perfectly fine, but
487  *       strscpy(ptr,"foo") will * cause the the program to crash with
488  *       a segmentation fault.
489  *
490  *****************************************************************************/
492 char *
493 strnl (char *str)
495         size_t len;
496         if (str == NULL)
497                 return NULL;
498         str = strpbrk (str, "\r\n");
499         if (str == NULL)
500                 return NULL;
501         len = strspn (str, "\r\n");
502         if (str[len] == '\0')
503                 return NULL;
504         str += len;
505         if (strlen (str) == 0)
506                 return NULL;
507         return str;
514 /******************************************************************************
515  *
516  * Like strscpy, except only the portion of the source string up to
517  * the provided delimiter is copied.
518  *
519  * Example:
520  *
521  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
522  * printf("%s\n",str);
523  *
524  * Produces:
525  *
526  *This is a line of te
527  *
528  *****************************************************************************/
530 char *
531 strpcpy (char *dest, const char *src, const char *str)
533         size_t len;
535         if (src)
536                 len = strcspn (src, str);
537         else
538                 return NULL;
540         if (dest == NULL || strlen (dest) < len)
541                 dest = realloc (dest, len + 1);
542         if (dest == NULL)
543                 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
545         strncpy (dest, src, len);
546         dest[len] = '\0';
548         return dest;
555 /******************************************************************************
556  *
557  * Like strscat, except only the portion of the source string up to
558  * the provided delimiter is copied.
559  *
560  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
561  * str = strpcat(str,"This is a line of text with no trailing newline","x");
562  * printf("%s\n",str);
563  * 
564  *This is a line of texThis is a line of tex
565  *
566  *****************************************************************************/
568 char *
569 strpcat (char *dest, const char *src, const char *str)
571         size_t len, l2;
573         if (dest)
574                 len = strlen (dest);
575         else
576                 len = 0;
578         if (src) {
579                 l2 = strcspn (src, str);
580         }
581         else {
582                 return dest;
583         }
585         dest = realloc (dest, len + l2 + 1);
586         if (dest == NULL)
587                 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
589         strncpy (dest + len, src, l2);
590         dest[len + l2] = '\0';
592         return dest;