Code

5f770a1f5a508c339238f45209bc829a36452131
[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 #define LOCAL_TIMEOUT_ALARM_HANDLER
16 #include "config.h"
17 #include "common.h"
18 #include "utils.h"
19 #include <stdarg.h>
20 #include <limits.h>
22 #include <arpa/inet.h>
24 extern void print_usage (void);
25 extern const char *progname;
27 #define STRLEN 64
28 #define TXTBLK 128
30 /* **************************************************************************
31  * max_state(STATE_x, STATE_y)
32  * compares STATE_x to  STATE_y and returns result based on the following
33  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
34  *
35  * Note that numerically the above does not hold
36  ****************************************************************************/
38 int
39 max_state (int a, int b)
40 {
41         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
42                 return STATE_CRITICAL;
43         else if (a == STATE_WARNING || b == STATE_WARNING)
44                 return STATE_WARNING;
45         else if (a == STATE_OK || b == STATE_OK)
46                 return STATE_OK;
47         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
48                 return STATE_UNKNOWN;
49         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
50                 return STATE_DEPENDENT;
51         else
52                 return max (a, b);
53 }
55 void usage (char *msg)
56 {
57         printf (msg);
58         print_usage ();
59         exit (STATE_UNKNOWN);
60 }
62 void usage2(char *msg, char *arg)
63 {
64         printf ("%s: %s - %s\n",progname,msg,arg);
65         print_usage ();
66         exit (STATE_UNKNOWN);
67 }
69 void
70 usage3 (char *msg, char arg)
71 {
72         printf ("%s: %s - %c\n", progname, msg, arg);
73         print_usage();
74         exit (STATE_UNKNOWN);
75 }
78 void
79 support (void)
80 {
81         printf (_("\n\
82 Send email to nagios-users@lists.sourceforge.net if you have questions\n\
83 regarding use of this software. To submit patches or suggest improvements,\n\
84 send email to nagiosplug-devel@lists.sourceforge.net\n"));
85 }
88 char *
89 clean_revstring (const char *revstring)
90 {
91         char plugin_revision[STRLEN];
92         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
93                 return strscpy (NULL, plugin_revision);
94         else
95           return strscpy (NULL, "N/A");
96 }
98 void
99 print_revision (const char *command_name, const char *revision_string)
101         char plugin_revision[STRLEN];
103         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
104                 strncpy (plugin_revision, "N/A", STRLEN);
105         printf ("%s (%s %s) %s\n",
106                                         command_name, PACKAGE, VERSION, plugin_revision);
107         printf (_("\
108 The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n\
109 copies of the plugins under the terms of the GNU General Public License.\n\
110 For more information about these matters, see the file named COPYING.\n"));
114 char *
115 state_text (int result)
117         switch (result) {
118         case STATE_OK:
119                 return "OK";
120         case STATE_WARNING:
121                 return "WARNING";
122         case STATE_CRITICAL:
123                 return "CRITICAL";
124         case STATE_DEPENDENT:
125                 return "DEPENDENT";
126         default:
127                 return "UNKNOWN";
128         }
131 void
132 die (int result, const char *fmt, ...)
134         va_list ap;
135         printf ("%s %s: ", sizeof (char) + index(progname, '_'), state_text(result));
136         va_start (ap, fmt);
137         vprintf (fmt, ap);
138         va_end (ap);
139         exit (result);
142 void
143 terminate (int result, const char *fmt, ...)
145         va_list ap;
146         va_start (ap, fmt);
147         vprintf (fmt, ap);
148         va_end (ap);
149         exit (result);
152 void
153 timeout_alarm_handler (int signo)
155         if (signo == SIGALRM) {
156                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
157                                                 timeout_interval);
158                 exit (STATE_CRITICAL);
159         }
162 int
163 is_numeric (char *number)
165         char tmp[1];
166         float x;
168         if (!number)
169                 return FALSE;
170         else if (sscanf (number, "%f%c", &x, tmp) == 1)
171                 return TRUE;
172         else
173                 return FALSE;
176 int
177 is_positive (char *number)
179         if (is_numeric (number) && atof (number) > 0.0)
180                 return TRUE;
181         else
182                 return FALSE;
185 int
186 is_negative (char *number)
188         if (is_numeric (number) && atof (number) < 0.0)
189                 return TRUE;
190         else
191                 return FALSE;
194 int
195 is_nonnegative (char *number)
197         if (is_numeric (number) && atof (number) >= 0.0)
198                 return TRUE;
199         else
200                 return FALSE;
203 int
204 is_percentage (char *number)
206         int x;
207         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
208                 return TRUE;
209         else
210                 return FALSE;
213 int
214 is_integer (char *number)
216         long int n;
218         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
219                 return FALSE;
221         n = strtol (number, NULL, 10);
223         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
224                 return TRUE;
225         else
226                 return FALSE;
229 int
230 is_intpos (char *number)
232         if (is_integer (number) && atoi (number) > 0)
233                 return TRUE;
234         else
235                 return FALSE;
238 int
239 is_intneg (char *number)
241         if (is_integer (number) && atoi (number) < 0)
242                 return TRUE;
243         else
244                 return FALSE;
247 int
248 is_intnonneg (char *number)
250         if (is_integer (number) && atoi (number) >= 0)
251                 return TRUE;
252         else
253                 return FALSE;
256 int
257 is_intpercent (char *number)
259         int i;
260         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
261                 return TRUE;
262         else
263                 return FALSE;
266 int
267 is_option (char *str)
269         if (!str)
270                 return FALSE;
271         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
272                 return TRUE;
273         else
274                 return FALSE;
279 #ifdef NEED_GETTIMEOFDAY
280 int
281 gettimeofday (struct timeval *tv, struct timezone *tz)
283         tv->tv_usec = 0;
284         tv->tv_sec = (long) time ((time_t) 0);
286 #endif
290 double
291 delta_time (struct timeval tv)
293         struct timeval now;
295         gettimeofday (&now, NULL);
296         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
302 void
303 strip (char *buffer)
305         size_t x;
306         int i;
308         for (x = strlen (buffer); x >= 1; x--) {
309                 i = x - 1;
310                 if (buffer[i] == ' ' ||
311                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
312                         buffer[i] = '\0';
313                 else
314                         break;
315         }
316         return;
323 /******************************************************************************
324  *
325  * Copies one string to another. Any previously existing data in
326  * the destination string is lost.
327  *
328  * Example:
329  *
330  * char *str=NULL;
331  * str = strscpy("This is a line of text with no trailing newline");
332  *
333  *****************************************************************************/
335 char *
336 strscpy (char *dest, const char *src)
338         if (src == NULL)
339                 return NULL;
341         asprintf (&dest, "%s", src);
343         return dest;
350 /******************************************************************************
351  *
352  * Concatenates one string to the end of another
353  *
354  * Given a pointer destination string, which may or may not already
355  * hold some text, and a source string with additional text (possibly
356  * NULL or empty), returns a pointer to a string that is the first
357  * string with the second concatenated to it. Uses realloc to free 
358  * memory held by the dest argument if new storage space is required.
359  *
360  * Example:
361  *
362  * char *str=NULL;
363  * str = strscpy("This is a line of text with no trailing newline");
364  * str = strscat(str,"\n");
365  *
366  *****************************************************************************/
368 char *
369 strscat (char *dest, const char *src)
372         if (dest == NULL)
373                 return src;
374         if (src != NULL)
375                 asprintf (&dest, "%s%s", dest, src);
377         return dest;
384 /******************************************************************************
385  *
386  * Returns a pointer to the next line of a multiline string buffer
387  *
388  * Given a pointer string, find the text following the next sequence
389  * of \r and \n characters. This has the effect of skipping blank
390  * lines as well
391  *
392  * Example:
393  *
394  * Given text as follows:
395  *
396  * ==============================
397  * This
398  * is
399  * a
400  * 
401  * multiline string buffer
402  * ==============================
403  *
404  * int i=0;
405  * char *str=NULL;
406  * char *ptr=NULL;
407  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
408  * ptr = str;
409  * while (ptr) {
410  *   printf("%d %s",i++,firstword(ptr));
411  *   ptr = strnl(ptr);
412  * }
413  * 
414  * Produces the following:
415  *
416  * 1 This
417  * 2 is
418  * 3 a
419  * 4 multiline
420  *
421  * NOTE: The 'firstword()' function is conceptual only and does not
422  *       exist in this package.
423  *
424  * NOTE: Although the second 'ptr' variable is not strictly needed in
425  *       this example, it is good practice with these utilities. Once
426  *       the * pointer is advance in this manner, it may no longer be
427  *       handled with * realloc(). So at the end of the code fragment
428  *       above, * strscpy(str,"foo") work perfectly fine, but
429  *       strscpy(ptr,"foo") will * cause the the program to crash with
430  *       a segmentation fault.
431  *
432  *****************************************************************************/
434 char *
435 strnl (char *str)
437         size_t len;
438         if (str == NULL)
439                 return NULL;
440         str = strpbrk (str, "\r\n");
441         if (str == NULL)
442                 return NULL;
443         len = strspn (str, "\r\n");
444         if (str[len] == '\0')
445                 return NULL;
446         str += len;
447         if (strlen (str) == 0)
448                 return NULL;
449         return str;
456 /******************************************************************************
457  *
458  * Like strscpy, except only the portion of the source string up to
459  * the provided delimiter is copied.
460  *
461  * Example:
462  *
463  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
464  * printf("%s\n",str);
465  *
466  * Produces:
467  *
468  *This is a line of te
469  *
470  *****************************************************************************/
472 char *
473 strpcpy (char *dest, const char *src, const char *str)
475         size_t len;
477         if (src)
478                 len = strcspn (src, str);
479         else
480                 return NULL;
482         if (dest == NULL || strlen (dest) < len)
483                 dest = realloc (dest, len + 1);
484         if (dest == NULL)
485                 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
487         strncpy (dest, src, len);
488         dest[len] = '\0';
490         return dest;
497 /******************************************************************************
498  *
499  * Like strscat, except only the portion of the source string up to
500  * the provided delimiter is copied.
501  *
502  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
503  * str = strpcat(str,"This is a line of text with no trailing newline","x");
504  * printf("%s\n",str);
505  * 
506  *This is a line of texThis is a line of tex
507  *
508  *****************************************************************************/
510 char *
511 strpcat (char *dest, const char *src, const char *str)
513         size_t len, l2;
515         if (dest)
516                 len = strlen (dest);
517         else
518                 len = 0;
520         if (src) {
521                 l2 = strcspn (src, str);
522         }
523         else {
524                 return dest;
525         }
527         dest = realloc (dest, len + l2 + 1);
528         if (dest == NULL)
529                 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
531         strncpy (dest + len, src, l2);
532         dest[len + l2] = '\0';
534         return dest;