diff options
Diffstat (limited to 'plugins/utils.c')
-rw-r--r-- | plugins/utils.c | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/plugins/utils.c b/plugins/utils.c new file mode 100644 index 00000000..49e4d3d7 --- /dev/null +++ b/plugins/utils.c | |||
@@ -0,0 +1,610 @@ | |||
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 | ****************************************************************************/ | ||
13 | |||
14 | #include "config.h" | ||
15 | #include "common.h" | ||
16 | #include "version.h" | ||
17 | #include <stdarg.h> | ||
18 | #include <limits.h> | ||
19 | |||
20 | extern int timeout_interval; | ||
21 | |||
22 | char *my_basename (char *); | ||
23 | void support (void); | ||
24 | char *clean_revstring (const char *); | ||
25 | void print_revision (char *, const char *); | ||
26 | void terminate (int, const char *fmt, ...); | ||
27 | RETSIGTYPE timeout_alarm_handler (int); | ||
28 | |||
29 | int is_host (char *); | ||
30 | int is_dotted_quad (char *); | ||
31 | int is_hostname (char *); | ||
32 | |||
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 *); | ||
38 | |||
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 *); | ||
44 | |||
45 | int is_option (char *str); | ||
46 | |||
47 | void strip (char *); | ||
48 | char *strscpy (char *dest, const char *src); | ||
49 | char *strscat (char *dest, const char *src); | ||
50 | char *strnl (char *str); | ||
51 | char *ssprintf (char *str, const char *fmt, ...); | ||
52 | char *strpcpy (char *dest, const char *src, const char *str); | ||
53 | char *strpcat (char *dest, const char *src, const char *str); | ||
54 | |||
55 | #define LABELLEN 63 | ||
56 | #define STRLEN 64 | ||
57 | #define TXTBLK 128 | ||
58 | |||
59 | #define max(a,b) ((a)>(b))?(a):(b) | ||
60 | |||
61 | char * | ||
62 | my_basename (char *path) | ||
63 | { | ||
64 | if (!strstr (path, "/")) | ||
65 | return path; | ||
66 | else | ||
67 | return 1 + strrchr (path, '/'); | ||
68 | } | ||
69 | |||
70 | |||
71 | void | ||
72 | support (void) | ||
73 | { | ||
74 | printf | ||
75 | ("Send email to nagios-users@lists.sourceforge.net if you have questions\n" | ||
76 | "regarding use of this software. To submit patches or suggest improvements,\n" | ||
77 | "send email to nagiosplug-devel@lists.sourceforge.net\n"); | ||
78 | } | ||
79 | |||
80 | |||
81 | char * | ||
82 | clean_revstring (const char *revstring) | ||
83 | { | ||
84 | char plugin_revision[STRLEN]; | ||
85 | if (sscanf (revstring,"$Revision: %[0-9.]",plugin_revision) == 1) | ||
86 | return strscpy (NULL, plugin_revision); | ||
87 | else | ||
88 | return strscpy (NULL, "N/A"); | ||
89 | } | ||
90 | |||
91 | void | ||
92 | print_revision (char *command_name, const char *revision_string) | ||
93 | { | ||
94 | char plugin_revision[STRLEN]; | ||
95 | |||
96 | if (sscanf (revision_string, "$Revision: %[0-9.]", plugin_revision) != 1) | ||
97 | strncpy (plugin_revision, "N/A", STRLEN); | ||
98 | printf ("%s (nagios-plugins %s) %s\n", | ||
99 | my_basename (command_name), VERSION, plugin_revision); | ||
100 | printf | ||
101 | ("The nagios plugins come with ABSOLUTELY NO WARRANTY. You may redistribute\n" | ||
102 | "copies of the plugins under the terms of the GNU General Public License.\n" | ||
103 | "For more information about these matters, see the file named COPYING.\n"); | ||
104 | |||
105 | } | ||
106 | |||
107 | |||
108 | void | ||
109 | terminate (int result, const char *fmt, ...) | ||
110 | { | ||
111 | va_list ap; | ||
112 | va_start (ap, fmt); | ||
113 | vprintf (fmt, ap); | ||
114 | va_end (ap); | ||
115 | exit (result); | ||
116 | } | ||
117 | |||
118 | void | ||
119 | timeout_alarm_handler (int signo) | ||
120 | { | ||
121 | if (signo == SIGALRM) { | ||
122 | printf ("CRITICAL - Plugin timed out after %d seconds\n", | ||
123 | timeout_interval); | ||
124 | exit (STATE_CRITICAL); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | int | ||
129 | is_host (char *address) | ||
130 | { | ||
131 | if (is_dotted_quad (address) || is_hostname (address)) | ||
132 | return (TRUE); | ||
133 | return (FALSE); | ||
134 | } | ||
135 | |||
136 | int | ||
137 | is_dotted_quad (char *address) | ||
138 | { | ||
139 | int o1, o2, o3, o4; | ||
140 | char c[1]; | ||
141 | |||
142 | if (sscanf (address, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, c) != 4) | ||
143 | return FALSE; | ||
144 | else if (o1 > 255 || o2 > 255 || o3 > 255 || o4 > 255) | ||
145 | return FALSE; | ||
146 | else if (o1 < 0 || o2 < 0 || o3 < 0 || o4 < 0) | ||
147 | return FALSE; | ||
148 | else | ||
149 | return TRUE; | ||
150 | } | ||
151 | |||
152 | /* from RFC-1035 | ||
153 | * | ||
154 | * The labels must follow the rules for ARPANET host names. They must | ||
155 | * start with a letter, end with a letter or digit, and have as interior | ||
156 | * characters only letters, digits, and hyphen. There are also some | ||
157 | * restrictions on the length. Labels must be 63 characters or less. */ | ||
158 | |||
159 | int | ||
160 | is_hostname (char *s1) | ||
161 | { | ||
162 | if (strlen (s1) > 63) | ||
163 | return FALSE; | ||
164 | if (strcspn | ||
165 | (s1, | ||
166 | "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUWVXYZ0123456789-.") != | ||
167 | 0) return FALSE; | ||
168 | if (strspn (s1, "0123456789-.") == 1) | ||
169 | return FALSE; | ||
170 | while ((s1 = index (s1, '.'))) { | ||
171 | s1++; | ||
172 | if (strspn (s1, "0123456789-.") == 1) { | ||
173 | printf ("%s\n", s1); | ||
174 | return FALSE; | ||
175 | } | ||
176 | } | ||
177 | return TRUE; | ||
178 | } | ||
179 | |||
180 | int | ||
181 | is_numeric (char *number) | ||
182 | { | ||
183 | char tmp[1]; | ||
184 | float x; | ||
185 | if (sscanf (number, "%f%c", &x, tmp) == 1) | ||
186 | return (TRUE); | ||
187 | return (FALSE); | ||
188 | } | ||
189 | |||
190 | int | ||
191 | is_positive (char *number) | ||
192 | { | ||
193 | if (is_numeric (number) && atof (number) > 0.0) | ||
194 | return (TRUE); | ||
195 | return (FALSE); | ||
196 | } | ||
197 | |||
198 | int | ||
199 | is_negative (char *number) | ||
200 | { | ||
201 | if (is_numeric (number) && atof (number) < 0.0) | ||
202 | return (TRUE); | ||
203 | return (FALSE); | ||
204 | } | ||
205 | |||
206 | int | ||
207 | is_nonnegative (char *number) | ||
208 | { | ||
209 | if (is_numeric (number) && atof (number) >= 0.0) | ||
210 | return (TRUE); | ||
211 | return (FALSE); | ||
212 | } | ||
213 | |||
214 | int | ||
215 | is_percentage (char *number) | ||
216 | { | ||
217 | int x; | ||
218 | if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100) | ||
219 | return (TRUE); | ||
220 | return (FALSE); | ||
221 | } | ||
222 | |||
223 | int | ||
224 | is_integer (char *number) | ||
225 | { | ||
226 | long int n; | ||
227 | |||
228 | if (strspn (number, "-0123456789 ") != strlen (number)) | ||
229 | return (FALSE); | ||
230 | |||
231 | n = strtol (number, NULL, 10); | ||
232 | if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) | ||
233 | return (TRUE); | ||
234 | return (FALSE); | ||
235 | } | ||
236 | |||
237 | int | ||
238 | is_intpos (char *number) | ||
239 | { | ||
240 | if (is_integer (number) && atoi (number) > 0) | ||
241 | return (TRUE); | ||
242 | return (FALSE); | ||
243 | } | ||
244 | |||
245 | int | ||
246 | is_intneg (char *number) | ||
247 | { | ||
248 | if (is_integer (number) && atoi (number) < 0) | ||
249 | return (TRUE); | ||
250 | return (FALSE); | ||
251 | } | ||
252 | |||
253 | int | ||
254 | is_intnonneg (char *number) | ||
255 | { | ||
256 | if (is_integer (number) && atoi (number) >= 0) | ||
257 | return (TRUE); | ||
258 | return (FALSE); | ||
259 | } | ||
260 | |||
261 | int | ||
262 | is_intpercent (char *number) | ||
263 | { | ||
264 | int i; | ||
265 | if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100) | ||
266 | return (TRUE); | ||
267 | return (FALSE); | ||
268 | } | ||
269 | |||
270 | int | ||
271 | is_option (char *str) | ||
272 | { | ||
273 | if (strspn (str, "-") == 1 || strspn (str, "-") == 2) | ||
274 | return TRUE; | ||
275 | return FALSE; | ||
276 | } | ||
277 | |||
278 | |||
279 | |||
280 | |||
281 | |||
282 | void | ||
283 | strip (char *buffer) | ||
284 | { | ||
285 | size_t x; | ||
286 | int i; | ||
287 | |||
288 | for (x = strlen (buffer); x >= 1; x--) { | ||
289 | i = x - 1; | ||
290 | if (buffer[i] == ' ' || | ||
291 | buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t') | ||
292 | buffer[i] = '\0'; | ||
293 | else | ||
294 | break; | ||
295 | } | ||
296 | return; | ||
297 | } | ||
298 | |||
299 | |||
300 | |||
301 | |||
302 | |||
303 | /****************************************************************************** | ||
304 | * | ||
305 | * Copies one string to another | ||
306 | * | ||
307 | * Given a pointer destination string, which may or may not already | ||
308 | * hold some text, and a source string with additional text (possibly | ||
309 | * NULL or empty), returns a pointer to a a copy of the source | ||
310 | * string. Uses realloc to free memory held by the dest argument if | ||
311 | * new storage space is required, and any previously existing data in | ||
312 | * the destination string is lost. | ||
313 | * | ||
314 | * Example: | ||
315 | * | ||
316 | * char *str=NULL; | ||
317 | * str = strscpy("This is a line of text with no trailing newline"); | ||
318 | * | ||
319 | *****************************************************************************/ | ||
320 | |||
321 | char * | ||
322 | strscpy (char *dest, const char *src) | ||
323 | { | ||
324 | size_t len; | ||
325 | |||
326 | if (src == NULL) | ||
327 | return dest; | ||
328 | |||
329 | len = strlen (src) + 1; | ||
330 | if (dest == NULL) | ||
331 | dest = malloc (len); | ||
332 | else if (strlen (dest) < len) | ||
333 | dest = realloc (dest, len); | ||
334 | if (dest == NULL) | ||
335 | terminate (STATE_UNKNOWN, "failed realloc in strscpy\n"); | ||
336 | |||
337 | strncpy (dest, src, len); | ||
338 | |||
339 | return dest; | ||
340 | } | ||
341 | |||
342 | |||
343 | |||
344 | |||
345 | |||
346 | /****************************************************************************** | ||
347 | * | ||
348 | * Concatenates one string to the end of another | ||
349 | * | ||
350 | * Given a pointer destination string, which may or may not already | ||
351 | * hold some text, and a source string with additional text (possibly | ||
352 | * NULL or empty), returns a pointer to a string that is the first | ||
353 | * string with the second concatenated to it. Uses realloc to free | ||
354 | * memory held by the dest argument if new storage space is required. | ||
355 | * | ||
356 | * Example: | ||
357 | * | ||
358 | * char *str=NULL; | ||
359 | * str = strscpy("This is a line of text with no trailing newline"); | ||
360 | * str = strscat(str,"\n"); | ||
361 | * | ||
362 | *****************************************************************************/ | ||
363 | |||
364 | char * | ||
365 | strscat (char *dest, const char *src) | ||
366 | { | ||
367 | size_t len, l2; | ||
368 | |||
369 | if (src) | ||
370 | l2 = strlen (src); | ||
371 | else | ||
372 | return dest; | ||
373 | |||
374 | if (dest) | ||
375 | len = strlen (dest); | ||
376 | else | ||
377 | len = 0; | ||
378 | |||
379 | dest = realloc (dest, len + l2 + 1); | ||
380 | if (dest == NULL) | ||
381 | terminate (STATE_UNKNOWN, "failed malloc in strscat\n"); | ||
382 | |||
383 | strncpy (dest + len, src, l2); | ||
384 | dest[len + l2] = '\0'; | ||
385 | |||
386 | return dest; | ||
387 | } | ||
388 | |||
389 | |||
390 | |||
391 | |||
392 | |||
393 | /****************************************************************************** | ||
394 | * | ||
395 | * Returns a pointer to the next line of a multiline string buffer | ||
396 | * | ||
397 | * Given a pointer string, find the text following the next sequence | ||
398 | * of \r and \n characters. This has the effect of skipping blank | ||
399 | * lines as well | ||
400 | * | ||
401 | * Example: | ||
402 | * | ||
403 | * Given text as follows: | ||
404 | * | ||
405 | * ============================== | ||
406 | * This | ||
407 | * is | ||
408 | * a | ||
409 | * | ||
410 | * multiline string buffer | ||
411 | * ============================== | ||
412 | * | ||
413 | * int i=0; | ||
414 | * char *str=NULL; | ||
415 | * char *ptr=NULL; | ||
416 | * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n"); | ||
417 | * ptr = str; | ||
418 | * while (ptr) { | ||
419 | * printf("%d %s",i++,firstword(ptr)); | ||
420 | * ptr = strnl(ptr); | ||
421 | * } | ||
422 | * | ||
423 | * Produces the following: | ||
424 | * | ||
425 | * 1 This | ||
426 | * 2 is | ||
427 | * 3 a | ||
428 | * 4 multiline | ||
429 | * | ||
430 | * NOTE: The 'firstword()' function is conceptual only and does not | ||
431 | * exist in this package. | ||
432 | * | ||
433 | * NOTE: Although the second 'ptr' variable is not strictly needed in | ||
434 | * this example, it is good practice with these utilities. Once | ||
435 | * the * pointer is advance in this manner, it may no longer be | ||
436 | * handled with * realloc(). So at the end of the code fragment | ||
437 | * above, * strscpy(str,"foo") work perfectly fine, but | ||
438 | * strscpy(ptr,"foo") will * cause the the program to crash with | ||
439 | * a segmentation fault. | ||
440 | * | ||
441 | *****************************************************************************/ | ||
442 | |||
443 | char * | ||
444 | strnl (char *str) | ||
445 | { | ||
446 | size_t len; | ||
447 | if (str == NULL) | ||
448 | return NULL; | ||
449 | str = strpbrk (str, "\r\n"); | ||
450 | if (str == NULL) | ||
451 | return NULL; | ||
452 | len = strspn (str, "\r\n"); | ||
453 | if (str[len] == '\0') | ||
454 | return NULL; | ||
455 | str += len; | ||
456 | if (strlen (str) == 0) | ||
457 | return NULL; | ||
458 | return str; | ||
459 | } | ||
460 | |||
461 | |||
462 | |||
463 | |||
464 | |||
465 | /****************************************************************************** | ||
466 | * | ||
467 | * Does a formatted print to a string variable | ||
468 | * | ||
469 | * Given a pointer destination string, which may or may not already | ||
470 | * hold some text, and a source string with additional text (possibly | ||
471 | * NULL or empty), returns a pointer to a string that cntains the | ||
472 | * results of the specified formatted print | ||
473 | * | ||
474 | * Example: | ||
475 | * | ||
476 | * char *str=NULL; | ||
477 | * str = ssprintf(str,"%d %s",1,"string"); | ||
478 | * | ||
479 | *****************************************************************************/ | ||
480 | |||
481 | char * | ||
482 | ssprintf (char *ptr, const char *fmt, ...) | ||
483 | { | ||
484 | va_list ap; | ||
485 | int nchars; | ||
486 | size_t size; | ||
487 | char *str = NULL; | ||
488 | |||
489 | if (str == NULL) { | ||
490 | str = malloc (TXTBLK); | ||
491 | if (str == NULL) | ||
492 | terminate (STATE_UNKNOWN, "malloc failed in ssprintf"); | ||
493 | size = TXTBLK; | ||
494 | } | ||
495 | else | ||
496 | size = max (strlen (str), TXTBLK); | ||
497 | |||
498 | va_start (ap, fmt); | ||
499 | |||
500 | while (1) { | ||
501 | |||
502 | nchars = vsnprintf (str, size, fmt, ap); | ||
503 | |||
504 | if (nchars > -1) | ||
505 | if (nchars < (int) size) { | ||
506 | va_end (ap); | ||
507 | str[nchars] = '\0'; | ||
508 | if (ptr) | ||
509 | free (ptr); | ||
510 | return str; | ||
511 | } | ||
512 | else { | ||
513 | size = (size_t) (nchars + 1); | ||
514 | } | ||
515 | |||
516 | else | ||
517 | size *= 2; | ||
518 | |||
519 | str = realloc (str, size); | ||
520 | |||
521 | if (str == NULL) | ||
522 | terminate (STATE_UNKNOWN, "realloc failed in ssprintf"); | ||
523 | } | ||
524 | |||
525 | } | ||
526 | |||
527 | |||
528 | |||
529 | |||
530 | |||
531 | /****************************************************************************** | ||
532 | * | ||
533 | * Like strscpy, except only the portion of the source string up to | ||
534 | * the provided delimiter is copied. | ||
535 | * | ||
536 | * Example: | ||
537 | * | ||
538 | * str = strpcpy(str,"This is a line of text with no trailing newline","x"); | ||
539 | * printf("%s\n",str); | ||
540 | * | ||
541 | * Produces: | ||
542 | * | ||
543 | *This is a line of te | ||
544 | * | ||
545 | *****************************************************************************/ | ||
546 | |||
547 | char * | ||
548 | strpcpy (char *dest, const char *src, const char *str) | ||
549 | { | ||
550 | size_t len; | ||
551 | |||
552 | if (src) | ||
553 | len = strcspn (src, str); | ||
554 | else | ||
555 | return NULL; | ||
556 | |||
557 | if (dest == NULL || strlen (dest) < len) | ||
558 | dest = realloc (dest, len + 1); | ||
559 | if (dest == NULL) | ||
560 | terminate (STATE_UNKNOWN, "failed realloc in strpcpy\n"); | ||
561 | |||
562 | strncpy (dest, src, len); | ||
563 | dest[len] = '\0'; | ||
564 | |||
565 | return dest; | ||
566 | } | ||
567 | |||
568 | |||
569 | |||
570 | |||
571 | |||
572 | /****************************************************************************** | ||
573 | * | ||
574 | * Like strscat, except only the portion of the source string up to | ||
575 | * the provided delimiter is copied. | ||
576 | * | ||
577 | * str = strpcpy(str,"This is a line of text with no trailing newline","x"); | ||
578 | * str = strpcat(str,"This is a line of text with no trailing newline","x"); | ||
579 | * printf("%s\n",str); | ||
580 | * | ||
581 | *This is a line of texThis is a line of tex | ||
582 | * | ||
583 | *****************************************************************************/ | ||
584 | |||
585 | char * | ||
586 | strpcat (char *dest, const char *src, const char *str) | ||
587 | { | ||
588 | size_t len, l2; | ||
589 | |||
590 | if (dest) | ||
591 | len = strlen (dest); | ||
592 | else | ||
593 | len = 0; | ||
594 | |||
595 | if (src) { | ||
596 | l2 = strcspn (src, str); | ||
597 | } | ||
598 | else { | ||
599 | return dest; | ||
600 | } | ||
601 | |||
602 | dest = realloc (dest, len + l2 + 1); | ||
603 | if (dest == NULL) | ||
604 | terminate (STATE_UNKNOWN, "failed malloc in strscat\n"); | ||
605 | |||
606 | strncpy (dest + len, src, l2); | ||
607 | dest[len + l2] = '\0'; | ||
608 | |||
609 | return dest; | ||
610 | } | ||