Fix argument order of calloc on several occasions
[monitoring-plugins.git] / plugins / utils.c
blob6d366e3d8dcd7eea2d3bfc22d1ae120e079fdc40
1 /*****************************************************************************
3 * Library of useful functions for plugins
5 * License: GPL
6 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
7 * Copyright (c) 2002-2024 Monitoring Plugins Development Team
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************/
25 #include "common.h"
26 #include "./utils.h"
27 #include "utils_base.h"
28 #include <stdarg.h>
29 #include <limits.h>
30 #include <string.h>
31 #include <errno.h>
33 #include <stdbool.h>
35 #include <arpa/inet.h>
37 extern void print_usage(void);
38 extern const char *progname;
40 #define STRLEN 64
41 #define TXTBLK 128
43 time_t start_time, end_time;
45 /* **************************************************************************
46 * max_state(STATE_x, STATE_y)
47 * compares STATE_x to STATE_y and returns result based on the following
48 * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
50 * Note that numerically the above does not hold
51 ****************************************************************************/
53 int max_state(int a, int b) {
54 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
55 return STATE_CRITICAL;
56 else if (a == STATE_WARNING || b == STATE_WARNING)
57 return STATE_WARNING;
58 else if (a == STATE_OK || b == STATE_OK)
59 return STATE_OK;
60 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
61 return STATE_UNKNOWN;
62 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
63 return STATE_DEPENDENT;
64 else
65 return max(a, b);
68 /* **************************************************************************
69 * max_state_alt(STATE_x, STATE_y)
70 * compares STATE_x to STATE_y and returns result based on the following
71 * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
73 * The main difference between max_state_alt and max_state it that it doesn't
74 * allow setting a default to UNKNOWN. It will instead prioritixe any valid
75 * non-OK state.
76 ****************************************************************************/
78 int max_state_alt(int a, int b) {
79 if (a == STATE_CRITICAL || b == STATE_CRITICAL)
80 return STATE_CRITICAL;
81 else if (a == STATE_WARNING || b == STATE_WARNING)
82 return STATE_WARNING;
83 else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
84 return STATE_UNKNOWN;
85 else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
86 return STATE_DEPENDENT;
87 else if (a == STATE_OK || b == STATE_OK)
88 return STATE_OK;
89 else
90 return max(a, b);
93 void usage(const char *msg) {
94 printf("%s\n", msg);
95 print_usage();
96 exit(STATE_UNKNOWN);
99 void usage_va(const char *fmt, ...) {
100 va_list ap;
101 printf("%s: ", progname);
102 va_start(ap, fmt);
103 vprintf(fmt, ap);
104 va_end(ap);
105 printf("\n");
106 exit(STATE_UNKNOWN);
109 void usage2(const char *msg, const char *arg) {
110 printf("%s: %s - %s\n", progname, msg, arg ? arg : "(null)");
111 print_usage();
112 exit(STATE_UNKNOWN);
115 void usage3(const char *msg, int arg) {
116 printf("%s: %s - %c\n", progname, msg, arg);
117 print_usage();
118 exit(STATE_UNKNOWN);
121 void usage4(const char *msg) {
122 printf("%s: %s\n", progname, msg);
123 print_usage();
124 exit(STATE_UNKNOWN);
127 void usage5(void) {
128 print_usage();
129 exit(STATE_UNKNOWN);
132 void print_revision(const char *command_name, const char *revision) {
133 printf("%s v%s (%s %s)\n", command_name, revision, PACKAGE, VERSION);
136 bool is_numeric(char *number) {
137 char tmp[1];
138 float x;
140 if (!number)
141 return false;
142 else if (sscanf(number, "%f%c", &x, tmp) == 1)
143 return true;
144 else
145 return false;
148 bool is_positive(char *number) {
149 if (is_numeric(number) && atof(number) > 0.0)
150 return true;
151 else
152 return false;
155 bool is_negative(char *number) {
156 if (is_numeric(number) && atof(number) < 0.0)
157 return true;
158 else
159 return false;
162 bool is_nonnegative(char *number) {
163 if (is_numeric(number) && atof(number) >= 0.0)
164 return true;
165 else
166 return false;
169 bool is_percentage(char *number) {
170 int x;
171 if (is_numeric(number) && (x = atof(number)) >= 0 && x <= 100)
172 return true;
173 else
174 return false;
177 bool is_percentage_expression(const char str[]) {
178 if (!str) {
179 return false;
182 size_t len = strlen(str);
184 if (str[len - 1] != '%') {
185 return false;
188 char *foo = calloc(len + 1, sizeof(char));
190 if (!foo) {
191 die(STATE_UNKNOWN, _("calloc failed \n"));
194 strcpy(foo, str);
195 foo[len - 1] = '\0';
197 bool result = is_numeric(foo);
199 free(foo);
201 return result;
204 bool 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 bool is_intpos(char *number) {
219 if (is_integer(number) && atoi(number) > 0)
220 return true;
221 else
222 return false;
225 bool is_intneg(char *number) {
226 if (is_integer(number) && atoi(number) < 0)
227 return true;
228 else
229 return false;
232 bool is_intnonneg(char *number) {
233 if (is_integer(number) && atoi(number) >= 0)
234 return true;
235 else
236 return false;
240 * Checks whether the number in the string _number_ can be put inside a int64_t
241 * On success the number will be written to the _target_ address, if _target_ is not set
242 * to NULL.
244 bool is_int64(char *number, int64_t *target) {
245 errno = 0;
246 char *endptr = {0};
248 int64_t tmp = strtoll(number, &endptr, 10);
249 if (errno != 0) {
250 return false;
253 if (*endptr == '\0') {
254 return 0;
257 if (tmp < INT64_MIN || tmp > INT64_MAX) {
258 return false;
261 if (target != NULL) {
262 *target = tmp;
264 return true;
268 * Checks whether the number in the string _number_ can be put inside a uint64_t
269 * On success the number will be written to the _target_ address, if _target_ is not set
270 * to NULL.
272 bool is_uint64(char *number, uint64_t *target) {
273 errno = 0;
274 char *endptr = {0};
275 unsigned long long tmp = strtoull(number, &endptr, 10);
277 if (errno != 0) {
278 return false;
281 if (*endptr != '\0') {
282 return false;
285 if (tmp > UINT64_MAX) {
286 return false;
289 if (target != NULL) {
290 *target = (uint64_t)tmp;
293 return true;
296 bool is_intpercent(char *number) {
297 int i;
298 if (is_integer(number) && (i = atoi(number)) >= 0 && i <= 100)
299 return true;
300 else
301 return false;
304 bool is_option(char *str) {
305 if (!str)
306 return false;
307 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2)
308 return true;
309 else
310 return false;
313 #ifdef NEED_GETTIMEOFDAY
314 int gettimeofday(struct timeval *tv, struct timezone *tz) {
315 tv->tv_usec = 0;
316 tv->tv_sec = (long)time((time_t)0);
318 #endif
320 double delta_time(struct timeval tv) {
321 struct timeval now;
323 gettimeofday(&now, NULL);
324 return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
327 long deltime(struct timeval tv) {
328 struct timeval now;
329 gettimeofday(&now, NULL);
330 return (now.tv_sec - tv.tv_sec) * 1000000 + now.tv_usec - tv.tv_usec;
333 void strip(char *buffer) {
334 size_t x;
335 int i;
337 for (x = strlen(buffer); x >= 1; x--) {
338 i = x - 1;
339 if (buffer[i] == ' ' || buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
340 buffer[i] = '\0';
341 else
342 break;
344 return;
347 /******************************************************************************
349 * Copies one string to another. Any previously existing data in
350 * the destination string is lost.
352 * Example:
354 * char *str=NULL;
355 * str = strscpy("This is a line of text with no trailing newline");
357 *****************************************************************************/
359 char *strscpy(char *dest, const char *src) {
360 if (src == NULL)
361 return NULL;
363 xasprintf(&dest, "%s", src);
365 return dest;
368 /******************************************************************************
370 * Returns a pointer to the next line of a multiline string buffer
372 * Given a pointer string, find the text following the next sequence
373 * of \r and \n characters. This has the effect of skipping blank
374 * lines as well
376 * Example:
378 * Given text as follows:
380 * ==============================
381 * This
382 * is
385 * multiline string buffer
386 * ==============================
388 * int i=0;
389 * char *str=NULL;
390 * char *ptr=NULL;
391 * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
392 * ptr = str;
393 * while (ptr) {
394 * printf("%d %s",i++,firstword(ptr));
395 * ptr = strnl(ptr);
398 * Produces the following:
400 * 1 This
401 * 2 is
402 * 3 a
403 * 4 multiline
405 * NOTE: The 'firstword()' function is conceptual only and does not
406 * exist in this package.
408 * NOTE: Although the second 'ptr' variable is not strictly needed in
409 * this example, it is good practice with these utilities. Once
410 * the * pointer is advance in this manner, it may no longer be
411 * handled with * realloc(). So at the end of the code fragment
412 * above, * strscpy(str,"foo") work perfectly fine, but
413 * strscpy(ptr,"foo") will * cause the the program to crash with
414 * a segmentation fault.
416 *****************************************************************************/
418 char *strnl(char *str) {
419 size_t len;
420 if (str == NULL)
421 return NULL;
422 str = strpbrk(str, "\r\n");
423 if (str == NULL)
424 return NULL;
425 len = strspn(str, "\r\n");
426 if (str[len] == '\0')
427 return NULL;
428 str += len;
429 if (strlen(str) == 0)
430 return NULL;
431 return str;
434 /******************************************************************************
436 * Like strscpy, except only the portion of the source string up to
437 * the provided delimiter is copied.
439 * Example:
441 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
442 * printf("%s\n",str);
444 * Produces:
446 *This is a line of te
448 *****************************************************************************/
450 char *strpcpy(char *dest, const char *src, const char *str) {
451 size_t len;
453 if (src)
454 len = strcspn(src, str);
455 else
456 return NULL;
458 if (dest == NULL || strlen(dest) < len)
459 dest = realloc(dest, len + 1);
460 if (dest == NULL)
461 die(STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
463 strncpy(dest, src, len);
464 dest[len] = '\0';
466 return dest;
469 /******************************************************************************
471 * Like strscat, except only the portion of the source string up to
472 * the provided delimiter is copied.
474 * str = strpcpy(str,"This is a line of text with no trailing newline","x");
475 * str = strpcat(str,"This is a line of text with no trailing newline","x");
476 * printf("%s\n",str);
478 *This is a line of texThis is a line of tex
480 *****************************************************************************/
482 char *strpcat(char *dest, const char *src, const char *str) {
483 size_t len, l2;
485 if (dest)
486 len = strlen(dest);
487 else
488 len = 0;
490 if (src) {
491 l2 = strcspn(src, str);
492 } else {
493 return dest;
496 dest = realloc(dest, len + l2 + 1);
497 if (dest == NULL)
498 die(STATE_UNKNOWN, _("failed malloc in strscat\n"));
500 strncpy(dest + len, src, l2);
501 dest[len + l2] = '\0';
503 return dest;
506 /******************************************************************************
508 * asprintf, but die on failure
510 ******************************************************************************/
512 int xvasprintf(char **strp, const char *fmt, va_list ap) {
513 int result = vasprintf(strp, fmt, ap);
514 if (result == -1 || *strp == NULL)
515 die(STATE_UNKNOWN, _("failed malloc in xvasprintf\n"));
516 return result;
519 int xasprintf(char **strp, const char *fmt, ...) {
520 va_list ap;
521 int result;
522 va_start(ap, fmt);
523 result = xvasprintf(strp, fmt, ap);
524 va_end(ap);
525 return result;
528 /******************************************************************************
530 * Print perfdata in a standard format
532 ******************************************************************************/
534 char *perfdata(const char *label, long int val, const char *uom, int warnp, long int warn, int critp, long int crit, int minp,
535 long int minv, int maxp, long int maxv) {
536 char *data = NULL;
538 if (strpbrk(label, "'= "))
539 xasprintf(&data, "'%s'=%ld%s;", label, val, uom);
540 else
541 xasprintf(&data, "%s=%ld%s;", label, val, uom);
543 if (warnp)
544 xasprintf(&data, "%s%ld;", data, warn);
545 else
546 xasprintf(&data, "%s;", data);
548 if (critp)
549 xasprintf(&data, "%s%ld;", data, crit);
550 else
551 xasprintf(&data, "%s;", data);
553 if (minp)
554 xasprintf(&data, "%s%ld;", data, minv);
555 else
556 xasprintf(&data, "%s;", data);
558 if (maxp)
559 xasprintf(&data, "%s%ld", data, maxv);
561 return data;
564 char *perfdata_uint64(const char *label, uint64_t val, const char *uom, int warnp, /* Warning present */
565 uint64_t warn, int critp, /* Critical present */
566 uint64_t crit, int minp, /* Minimum present */
567 uint64_t minv, int maxp, /* Maximum present */
568 uint64_t maxv) {
569 char *data = NULL;
571 if (strpbrk(label, "'= "))
572 xasprintf(&data, "'%s'=%" PRIu64 "%s;", label, val, uom);
573 else
574 xasprintf(&data, "%s=%" PRIu64 "%s;", label, val, uom);
576 if (warnp)
577 xasprintf(&data, "%s%" PRIu64 ";", data, warn);
578 else
579 xasprintf(&data, "%s;", data);
581 if (critp)
582 xasprintf(&data, "%s%" PRIu64 ";", data, crit);
583 else
584 xasprintf(&data, "%s;", data);
586 if (minp)
587 xasprintf(&data, "%s%" PRIu64 ";", data, minv);
588 else
589 xasprintf(&data, "%s;", data);
591 if (maxp)
592 xasprintf(&data, "%s%" PRIu64, data, maxv);
594 return data;
597 char *perfdata_int64(const char *label, int64_t val, const char *uom, int warnp, /* Warning present */
598 int64_t warn, int critp, /* Critical present */
599 int64_t crit, int minp, /* Minimum present */
600 int64_t minv, int maxp, /* Maximum present */
601 int64_t maxv) {
602 char *data = NULL;
604 if (strpbrk(label, "'= "))
605 xasprintf(&data, "'%s'=%" PRId64 "%s;", label, val, uom);
606 else
607 xasprintf(&data, "%s=%" PRId64 "%s;", label, val, uom);
609 if (warnp)
610 xasprintf(&data, "%s%" PRId64 ";", data, warn);
611 else
612 xasprintf(&data, "%s;", data);
614 if (critp)
615 xasprintf(&data, "%s%" PRId64 ";", data, crit);
616 else
617 xasprintf(&data, "%s;", data);
619 if (minp)
620 xasprintf(&data, "%s%" PRId64 ";", data, minv);
621 else
622 xasprintf(&data, "%s;", data);
624 if (maxp)
625 xasprintf(&data, "%s%" PRId64, data, maxv);
627 return data;
630 char *fperfdata(const char *label, double val, const char *uom, int warnp, double warn, int critp, double crit, int minp, double minv,
631 int maxp, double maxv) {
632 char *data = NULL;
634 if (strpbrk(label, "'= "))
635 xasprintf(&data, "'%s'=", label);
636 else
637 xasprintf(&data, "%s=", label);
639 xasprintf(&data, "%s%f", data, val);
640 xasprintf(&data, "%s%s;", data, uom);
642 if (warnp)
643 xasprintf(&data, "%s%f", data, warn);
645 xasprintf(&data, "%s;", data);
647 if (critp)
648 xasprintf(&data, "%s%f", data, crit);
650 xasprintf(&data, "%s;", data);
652 if (minp)
653 xasprintf(&data, "%s%f", data, minv);
655 if (maxp) {
656 xasprintf(&data, "%s;", data);
657 xasprintf(&data, "%s%f", data, maxv);
660 return data;
663 char *sperfdata(const char *label, double val, const char *uom, char *warn, char *crit, int minp, double minv, int maxp, double maxv) {
664 char *data = NULL;
665 if (strpbrk(label, "'= "))
666 xasprintf(&data, "'%s'=", label);
667 else
668 xasprintf(&data, "%s=", label);
670 xasprintf(&data, "%s%f", data, val);
671 xasprintf(&data, "%s%s;", data, uom);
673 if (warn != NULL)
674 xasprintf(&data, "%s%s", data, warn);
676 xasprintf(&data, "%s;", data);
678 if (crit != NULL)
679 xasprintf(&data, "%s%s", data, crit);
681 xasprintf(&data, "%s;", data);
683 if (minp)
684 xasprintf(&data, "%s%f", data, minv);
686 if (maxp) {
687 xasprintf(&data, "%s;", data);
688 xasprintf(&data, "%s%f", data, maxv);
691 return data;
694 char *sperfdata_int(const char *label, int val, const char *uom, char *warn, char *crit, int minp, int minv, int maxp, int maxv) {
695 char *data = NULL;
696 if (strpbrk(label, "'= "))
697 xasprintf(&data, "'%s'=", label);
698 else
699 xasprintf(&data, "%s=", label);
701 xasprintf(&data, "%s%d", data, val);
702 xasprintf(&data, "%s%s;", data, uom);
704 if (warn != NULL)
705 xasprintf(&data, "%s%s", data, warn);
707 xasprintf(&data, "%s;", data);
709 if (crit != NULL)
710 xasprintf(&data, "%s%s", data, crit);
712 xasprintf(&data, "%s;", data);
714 if (minp)
715 xasprintf(&data, "%s%d", data, minv);
717 if (maxp) {
718 xasprintf(&data, "%s;", data);
719 xasprintf(&data, "%s%d", data, maxv);
722 return data;