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)
100 {
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"));
112 }
114 char *
115 state_text (int result)
116 {
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 }
129 }
131 void
132 die (int result, const char *fmt, ...)
133 {
134 va_list ap;
135 va_start (ap, fmt);
136 vprintf (fmt, ap);
137 va_end (ap);
138 exit (result);
139 }
141 void
142 timeout_alarm_handler (int signo)
143 {
144 if (signo == SIGALRM) {
145 printf ("CRITICAL - Plugin timed out after %d seconds\n",
146 timeout_interval);
147 exit (STATE_CRITICAL);
148 }
149 }
151 int
152 is_numeric (char *number)
153 {
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;
163 }
165 int
166 is_positive (char *number)
167 {
168 if (is_numeric (number) && atof (number) > 0.0)
169 return TRUE;
170 else
171 return FALSE;
172 }
174 int
175 is_negative (char *number)
176 {
177 if (is_numeric (number) && atof (number) < 0.0)
178 return TRUE;
179 else
180 return FALSE;
181 }
183 int
184 is_nonnegative (char *number)
185 {
186 if (is_numeric (number) && atof (number) >= 0.0)
187 return TRUE;
188 else
189 return FALSE;
190 }
192 int
193 is_percentage (char *number)
194 {
195 int x;
196 if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
197 return TRUE;
198 else
199 return FALSE;
200 }
202 int
203 is_integer (char *number)
204 {
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;
216 }
218 int
219 is_intpos (char *number)
220 {
221 if (is_integer (number) && atoi (number) > 0)
222 return TRUE;
223 else
224 return FALSE;
225 }
227 int
228 is_intneg (char *number)
229 {
230 if (is_integer (number) && atoi (number) < 0)
231 return TRUE;
232 else
233 return FALSE;
234 }
236 int
237 is_intnonneg (char *number)
238 {
239 if (is_integer (number) && atoi (number) >= 0)
240 return TRUE;
241 else
242 return FALSE;
243 }
245 int
246 is_intpercent (char *number)
247 {
248 int i;
249 if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
250 return TRUE;
251 else
252 return FALSE;
253 }
255 int
256 is_option (char *str)
257 {
258 if (!str)
259 return FALSE;
260 else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
261 return TRUE;
262 else
263 return FALSE;
264 }
268 #ifdef NEED_GETTIMEOFDAY
269 int
270 gettimeofday (struct timeval *tv, struct timezone *tz)
271 {
272 tv->tv_usec = 0;
273 tv->tv_sec = (long) time ((time_t) 0);
274 }
275 #endif
279 double
280 delta_time (struct timeval tv)
281 {
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);
286 }
291 void
292 strip (char *buffer)
293 {
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;
306 }
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)
326 {
327 if (src == NULL)
328 return NULL;
330 asprintf (&dest, "%s", src);
332 return dest;
333 }
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)
359 {
361 if (dest == NULL)
362 return src;
363 if (src != NULL)
364 asprintf (&dest, "%s%s", dest, src);
366 return dest;
367 }
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)
425 {
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;
439 }
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)
463 {
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;
480 }
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)
501 {
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;
524 }