Code

Added autogen.sh script that rebuilds using autotools and runs configure
[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 #include <arpa/inet.h>
22 extern int timeout_interval;
23 extern const char *progname;
25 void support (void);
26 char *clean_revstring (const char *);
27 void print_revision (const char *, const char *);
28 void terminate (int, const char *fmt, ...);
29 RETSIGTYPE timeout_alarm_handler (int);
31 int is_host (char *);
32 int is_addr (char *);
33 int resolve_host_or_addr (char *, int);
34 int is_inet_addr (char *);
35 #ifdef USE_IPV6
36 int is_inet6_addr (char *);
37 #endif
38 int is_hostname (char *);
40 int is_integer (char *);
41 int is_intpos (char *);
42 int is_intneg (char *);
43 int is_intnonneg (char *);
44 int is_intpercent (char *);
46 int is_numeric (char *);
47 int is_positive (char *);
48 int is_negative (char *);
49 int is_nonnegative (char *);
50 int is_percentage (char *);
52 int is_option (char *str);
54 double delta_time (struct timeval tv);
56 void strip (char *);
57 char *strscpy (char *dest, const char *src);
58 char *strscat (char *dest, char *src);
59 char *strnl (char *str);
60 char *strpcpy (char *dest, const char *src, const char *str);
61 char *strpcat (char *dest, const char *src, const char *str);
63 #define LABELLEN 63
64 #define STRLEN 64
65 #define TXTBLK 128
67 /* **************************************************************************
68  /* max_state(STATE_x, STATE_y)
69  * compares STATE_x to  STATE_y and returns result based on the following
70  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
71  *
72  * Note that numerically the above does not hold
73  ****************************************************************************/
75 #define max(a,b) (((a)>(b))?(a):(b))
77 int
78 max_state (int a, int b)
79 {
80         if (a == STATE_CRITICAL || b == STATE_CRITICAL)
81                 return STATE_CRITICAL;
82         else if (a == STATE_WARNING || b == STATE_WARNING)
83                 return STATE_WARNING;
84         else if (a == STATE_OK || b == STATE_OK)
85                 return STATE_OK;
86         else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
87                 return STATE_UNKNOWN;
88         else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
89                 return STATE_DEPENDENT;
90         else
91                 return max (a, b);
92 }
94 void usage (char *msg)
95 {
96         printf (msg);
97         print_usage ();
98         exit (STATE_UNKNOWN);
99 }
101 void usage2(char *msg, char *arg)
103         printf ("%s: %s - %s\n",progname,msg,arg);
104         print_usage ();
105         exit (STATE_UNKNOWN);
108 void
109 usage3 (char *msg, char arg)
111         printf ("%s: %s - %c\n", progname, msg, arg);
112         print_usage();
113         exit (STATE_UNKNOWN);
117 void
118 support (void)
120         printf
121                 ("Send email to nagios-users@lists.sourceforge.net if you have questions\n"
122                  "regarding use of this software. To submit patches or suggest improvements,\n"
123                  "send email to nagiosplug-devel@lists.sourceforge.net\n");
127 char *
128 clean_revstring (const char *revstring)
130         char plugin_revision[STRLEN];
131         if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1)
132                 return strscpy (NULL, plugin_revision);
133         else
134           return strscpy (NULL, "N/A");
137 void
138 print_revision (const char *command_name, const char *revision_string)
140         char plugin_revision[STRLEN];
142         if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1)
143                 strncpy (plugin_revision, "N/A", STRLEN);
144         printf ("%s (nagios-plugins %s) %s\n",
145                                         progname, VERSION, plugin_revision);
146         printf
147                 ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n"
148                  "copies of the plugins under the terms of the GNU General Public License.\n"
149                  "For more information about these matters, see the file named COPYING.\n");
154 void
155 terminate (int result, const char *fmt, ...)
157         va_list ap;
158         va_start (ap, fmt);
159         vprintf (fmt, ap);
160         va_end (ap);
161         exit (result);
164 void
165 timeout_alarm_handler (int signo)
167         if (signo == SIGALRM) {
168                 printf ("CRITICAL - Plugin timed out after %d seconds\n",
169                                                 timeout_interval);
170                 exit (STATE_CRITICAL);
171         }
174 int
175 is_host (char *address)
177         if (is_addr (address) || is_hostname (address))
178                 return (TRUE);
180         return (FALSE);
183 int
184 is_addr (char *address)
186 #ifdef USE_IPV6
187         if (is_inet_addr (address) || is_inet6_addr (address))
188 #else
189         if (is_inet_addr (address))
190 #endif
191                 return (TRUE);
193         return (FALSE);
196 int
197 resolve_host_or_addr (char *address, int family)
199         struct addrinfo hints;
200         struct addrinfo *res;
201         int retval;
203         memset (&hints, 0, sizeof (hints));
204         hints.ai_family = family;
205         retval = getaddrinfo (address, NULL, &hints, &res);
207         if (retval != 0)
208                 return FALSE;
209         else {
210                 freeaddrinfo (res);
211                 return TRUE;
212         }
215 int
216 is_inet_addr (char *address)
218         return resolve_host_or_addr (address, AF_INET);
221 #ifdef USE_IPV6
222 int
223 is_inet6_addr (char *address)
225         return resolve_host_or_addr (address, AF_INET6);
227 #endif
229 /* from RFC-1035
230  * 
231  * The labels must follow the rules for ARPANET host names.  They must
232  * start with a letter, end with a letter or digit, and have as interior
233  * characters only letters, digits, and hyphen.  There are also some
234  * restrictions on the length.  Labels must be 63 characters or less. */
236 int
237 is_hostname (char *s1)
239 #ifdef USE_IPV6
240         return resolve_host_or_addr (s1, AF_UNSPEC);
241 #else
242         return resolve_host_or_addr (s1, AF_INET);
243 #endif
246 int
247 is_numeric (char *number)
249         char tmp[1];
250         float x;
252         if (!number)
253                 return FALSE;
254         else if (sscanf (number, "%f%c", &x, tmp) == 1)
255                 return TRUE;
256         else
257                 return FALSE;
260 int
261 is_positive (char *number)
263         if (is_numeric (number) && atof (number) > 0.0)
264                 return TRUE;
265         else
266                 return FALSE;
269 int
270 is_negative (char *number)
272         if (is_numeric (number) && atof (number) < 0.0)
273                 return TRUE;
274         else
275                 return FALSE;
278 int
279 is_nonnegative (char *number)
281         if (is_numeric (number) && atof (number) >= 0.0)
282                 return TRUE;
283         else
284                 return FALSE;
287 int
288 is_percentage (char *number)
290         int x;
291         if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
292                 return TRUE;
293         else
294                 return FALSE;
297 int
298 is_integer (char *number)
300         long int n;
302         if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
303                 return FALSE;
305         n = strtol (number, NULL, 10);
307         if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
308                 return TRUE;
309         else
310                 return FALSE;
313 int
314 is_intpos (char *number)
316         if (is_integer (number) && atoi (number) > 0)
317                 return TRUE;
318         else
319                 return FALSE;
322 int
323 is_intneg (char *number)
325         if (is_integer (number) && atoi (number) < 0)
326                 return TRUE;
327         else
328                 return FALSE;
331 int
332 is_intnonneg (char *number)
334         if (is_integer (number) && atoi (number) >= 0)
335                 return TRUE;
336         else
337                 return FALSE;
340 int
341 is_intpercent (char *number)
343         int i;
344         if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
345                 return TRUE;
346         else
347                 return FALSE;
350 int
351 is_option (char *str)
353         if (!str)
354                 return FALSE;
355         else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
356                 return TRUE;
357         else
358                 return FALSE;
363 #ifdef NEED_GETTIMEOFDAY
364 int
365 gettimeofday (struct timeval *tv, struct timezone *tz)
367         tv->tv_usec = 0;
368         tv->tv_sec = (long) time ((time_t) 0);
370 #endif
374 double
375 delta_time (struct timeval tv)
377         struct timeval now;
379         gettimeofday (&now, NULL);
380         return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
386 void
387 strip (char *buffer)
389         size_t x;
390         int i;
392         for (x = strlen (buffer); x >= 1; x--) {
393                 i = x - 1;
394                 if (buffer[i] == ' ' ||
395                                 buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
396                         buffer[i] = '\0';
397                 else
398                         break;
399         }
400         return;
407 /******************************************************************************
408  *
409  * Copies one string to another. Any previously existing data in
410  * the destination string is lost.
411  *
412  * Example:
413  *
414  * char *str=NULL;
415  * str = strscpy("This is a line of text with no trailing newline");
416  *
417  *****************************************************************************/
419 char *
420 strscpy (char *dest, const char *src)
422         if (src == NULL)
423                 return NULL;
425         asprintf (&dest, "%s", src);
427         return dest;
434 /******************************************************************************
435  *
436  * Concatenates one string to the end of another
437  *
438  * Given a pointer destination string, which may or may not already
439  * hold some text, and a source string with additional text (possibly
440  * NULL or empty), returns a pointer to a string that is the first
441  * string with the second concatenated to it. Uses realloc to free 
442  * memory held by the dest argument if new storage space is required.
443  *
444  * Example:
445  *
446  * char *str=NULL;
447  * str = strscpy("This is a line of text with no trailing newline");
448  * str = strscat(str,"\n");
449  *
450  *****************************************************************************/
452 char *
453 strscat (char *dest, char *src)
456         if (dest == NULL)
457                 return src;
458         if (src != NULL)
459                 asprintf (&dest, "%s%s", dest, src);
461         return dest;
468 /******************************************************************************
469  *
470  * Returns a pointer to the next line of a multiline string buffer
471  *
472  * Given a pointer string, find the text following the next sequence
473  * of \r and \n characters. This has the effect of skipping blank
474  * lines as well
475  *
476  * Example:
477  *
478  * Given text as follows:
479  *
480  * ==============================
481  * This
482  * is
483  * a
484  * 
485  * multiline string buffer
486  * ==============================
487  *
488  * int i=0;
489  * char *str=NULL;
490  * char *ptr=NULL;
491  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
492  * ptr = str;
493  * while (ptr) {
494  *   printf("%d %s",i++,firstword(ptr));
495  *   ptr = strnl(ptr);
496  * }
497  * 
498  * Produces the following:
499  *
500  * 1 This
501  * 2 is
502  * 3 a
503  * 4 multiline
504  *
505  * NOTE: The 'firstword()' function is conceptual only and does not
506  *       exist in this package.
507  *
508  * NOTE: Although the second 'ptr' variable is not strictly needed in
509  *       this example, it is good practice with these utilities. Once
510  *       the * pointer is advance in this manner, it may no longer be
511  *       handled with * realloc(). So at the end of the code fragment
512  *       above, * strscpy(str,"foo") work perfectly fine, but
513  *       strscpy(ptr,"foo") will * cause the the program to crash with
514  *       a segmentation fault.
515  *
516  *****************************************************************************/
518 char *
519 strnl (char *str)
521         size_t len;
522         if (str == NULL)
523                 return NULL;
524         str = strpbrk (str, "\r\n");
525         if (str == NULL)
526                 return NULL;
527         len = strspn (str, "\r\n");
528         if (str[len] == '\0')
529                 return NULL;
530         str += len;
531         if (strlen (str) == 0)
532                 return NULL;
533         return str;
540 /******************************************************************************
541  *
542  * Like strscpy, except only the portion of the source string up to
543  * the provided delimiter is copied.
544  *
545  * Example:
546  *
547  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
548  * printf("%s\n",str);
549  *
550  * Produces:
551  *
552  *This is a line of te
553  *
554  *****************************************************************************/
556 char *
557 strpcpy (char *dest, const char *src, const char *str)
559         size_t len;
561         if (src)
562                 len = strcspn (src, str);
563         else
564                 return NULL;
566         if (dest == NULL || strlen (dest) < len)
567                 dest = realloc (dest, len + 1);
568         if (dest == NULL)
569                 terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n");
571         strncpy (dest, src, len);
572         dest[len] = '\0';
574         return dest;
581 /******************************************************************************
582  *
583  * Like strscat, except only the portion of the source string up to
584  * the provided delimiter is copied.
585  *
586  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
587  * str = strpcat(str,"This is a line of text with no trailing newline","x");
588  * printf("%s\n",str);
589  * 
590  *This is a line of texThis is a line of tex
591  *
592  *****************************************************************************/
594 char *
595 strpcat (char *dest, const char *src, const char *str)
597         size_t len, l2;
599         if (dest)
600                 len = strlen (dest);
601         else
602                 len = 0;
604         if (src) {
605                 l2 = strcspn (src, str);
606         }
607         else {
608                 return dest;
609         }
611         dest = realloc (dest, len + l2 + 1);
612         if (dest == NULL)
613                 terminate (STATE_UNKNOWN, "failed malloc in strscat\n");
615         strncpy (dest + len, src, l2);
616         dest[len + l2] = '\0';
618         return dest;