Code

replace "terminate" with "die" for shorter name and better readability
[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         va_start (ap, fmt);
136         vprintf (fmt, ap);
137         va_end (ap);
138         exit (result);
141 void
142 timeout_alarm_handler (int signo)
144         if (signo == SIGALRM) {
145                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
146                                                 timeout_interval);
147                 exit (STATE_CRITICAL);
148         }
151 int
152 is_numeric (char *number)
154         char tmp[1];
155         float x;
157         if (!number)
158                 return FALSE;
159         else if (sscanf (number, "%f%c", &x, tmp) == 1)
160                 return TRUE;
161         else
162                 return FALSE;
165 int
166 is_positive (char *number)
168         if (is_numeric (number) && atof (number) > 0.0)
169                 return TRUE;
170         else
171                 return FALSE;
174 int
175 is_negative (char *number)
177         if (is_numeric (number) && atof (number) < 0.0)
178                 return TRUE;
179         else
180                 return FALSE;
183 int
184 is_nonnegative (char *number)
186         if (is_numeric (number) && atof (number) >= 0.0)
187                 return TRUE;
188         else
189                 return FALSE;
192 int
193 is_percentage (char *number)
195         int x;
196         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
197                 return TRUE;
198         else
199                 return FALSE;
202 int
203 is_integer (char *number)
205         long int n;
207         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
208                 return FALSE;
210         n = strtol (number, NULL, 10);
212         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
213                 return TRUE;
214         else
215                 return FALSE;
218 int
219 is_intpos (char *number)
221         if (is_integer (number) && atoi (number) > 0)
222                 return TRUE;
223         else
224                 return FALSE;
227 int
228 is_intneg (char *number)
230         if (is_integer (number) && atoi (number) < 0)
231                 return TRUE;
232         else
233                 return FALSE;
236 int
237 is_intnonneg (char *number)
239         if (is_integer (number) && atoi (number) >= 0)
240                 return TRUE;
241         else
242                 return FALSE;
245 int
246 is_intpercent (char *number)
248         int i;
249         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
250                 return TRUE;
251         else
252                 return FALSE;
255 int
256 is_option (char *str)
258         if (!str)
259                 return FALSE;
260         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
261                 return TRUE;
262         else
263                 return FALSE;
268 #ifdef NEED_GETTIMEOFDAY
269 int
270 gettimeofday (struct timeval *tv, struct timezone *tz)
272         tv->tv_usec = 0;
273         tv->tv_sec = (long) time ((time_t) 0);
275 #endif
279 double
280 delta_time (struct timeval tv)
282         struct timeval now;
284         gettimeofday (&now, NULL);
285         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
291 void
292 strip (char *buffer)
294         size_t x;
295         int i;
297         for (x = strlen (buffer); x >= 1; x--) {
298                 i = x - 1;
299                 if (buffer[i] == ' ' ||
300                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
301                         buffer[i] = '\0';
302                 else
303                         break;
304         }
305         return;
312 /******************************************************************************
313  *
314  * Copies one string to another. Any previously existing data in
315  * the destination string is lost.
316  *
317  * Example:
318  *
319  * char *str=NULL;
320  * str = strscpy("This is a line of text with no trailing newline");
321  *
322  *****************************************************************************/
324 char *
325 strscpy (char *dest, const char *src)
327         if (src == NULL)
328                 return NULL;
330         asprintf (&dest, "%s", src);
332         return dest;
339 /******************************************************************************
340  *
341  * Concatenates one string to the end of another
342  *
343  * Given a pointer destination string, which may or may not already
344  * hold some text, and a source string with additional text (possibly
345  * NULL or empty), returns a pointer to a string that is the first
346  * string with the second concatenated to it. Uses realloc to free 
347  * memory held by the dest argument if new storage space is required.
348  *
349  * Example:
350  *
351  * char *str=NULL;
352  * str = strscpy("This is a line of text with no trailing newline");
353  * str = strscat(str,"\n");
354  *
355  *****************************************************************************/
357 char *
358 strscat (char *dest, const char *src)
361         if (dest == NULL)
362                 return src;
363         if (src != NULL)
364                 asprintf (&dest, "%s%s", dest, src);
366         return dest;
373 /******************************************************************************
374  *
375  * Returns a pointer to the next line of a multiline string buffer
376  *
377  * Given a pointer string, find the text following the next sequence
378  * of \r and \n characters. This has the effect of skipping blank
379  * lines as well
380  *
381  * Example:
382  *
383  * Given text as follows:
384  *
385  * ==============================
386  * This
387  * is
388  * a
389  * 
390  * multiline string buffer
391  * ==============================
392  *
393  * int i=0;
394  * char *str=NULL;
395  * char *ptr=NULL;
396  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
397  * ptr = str;
398  * while (ptr) {
399  *   printf("%d %s",i++,firstword(ptr));
400  *   ptr = strnl(ptr);
401  * }
402  * 
403  * Produces the following:
404  *
405  * 1 This
406  * 2 is
407  * 3 a
408  * 4 multiline
409  *
410  * NOTE: The 'firstword()' function is conceptual only and does not
411  *       exist in this package.
412  *
413  * NOTE: Although the second 'ptr' variable is not strictly needed in
414  *       this example, it is good practice with these utilities. Once
415  *       the * pointer is advance in this manner, it may no longer be
416  *       handled with * realloc(). So at the end of the code fragment
417  *       above, * strscpy(str,"foo") work perfectly fine, but
418  *       strscpy(ptr,"foo") will * cause the the program to crash with
419  *       a segmentation fault.
420  *
421  *****************************************************************************/
423 char *
424 strnl (char *str)
426         size_t len;
427         if (str == NULL)
428                 return NULL;
429         str = strpbrk (str, "\r\n");
430         if (str == NULL)
431                 return NULL;
432         len = strspn (str, "\r\n");
433         if (str[len] == '\0')
434                 return NULL;
435         str += len;
436         if (strlen (str) == 0)
437                 return NULL;
438         return str;
445 /******************************************************************************
446  *
447  * Like strscpy, except only the portion of the source string up to
448  * the provided delimiter is copied.
449  *
450  * Example:
451  *
452  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
453  * printf("%s\n",str);
454  *
455  * Produces:
456  *
457  *This is a line of te
458  *
459  *****************************************************************************/
461 char *
462 strpcpy (char *dest, const char *src, const char *str)
464         size_t len;
466         if (src)
467                 len = strcspn (src, str);
468         else
469                 return NULL;
471         if (dest == NULL || strlen (dest) < len)
472                 dest = realloc (dest, len + 1);
473         if (dest == NULL)
474                 die (STATE_UNKNOWN, "failed realloc in strpcpy\n");
476         strncpy (dest, src, len);
477         dest[len] = '\0';
479         return dest;
486 /******************************************************************************
487  *
488  * Like strscat, except only the portion of the source string up to
489  * the provided delimiter is copied.
490  *
491  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
492  * str = strpcat(str,"This is a line of text with no trailing newline","x");
493  * printf("%s\n",str);
494  * 
495  *This is a line of texThis is a line of tex
496  *
497  *****************************************************************************/
499 char *
500 strpcat (char *dest, const char *src, const char *str)
502         size_t len, l2;
504         if (dest)
505                 len = strlen (dest);
506         else
507                 len = 0;
509         if (src) {
510                 l2 = strcspn (src, str);
511         }
512         else {
513                 return dest;
514         }
516         dest = realloc (dest, len + l2 + 1);
517         if (dest == NULL)
518                 die (STATE_UNKNOWN, "failed malloc in strscat\n");
520         strncpy (dest + len, src, l2);
521         dest[len + l2] = '\0';
523         return dest;