diff options
Diffstat (limited to 'plugins/utils.c')
-rw-r--r-- | plugins/utils.c | 806 |
1 files changed, 806 insertions, 0 deletions
diff --git a/plugins/utils.c b/plugins/utils.c new file mode 100644 index 0000000..71c0bdd --- /dev/null +++ b/plugins/utils.c @@ -0,0 +1,806 @@ +/***************************************************************************** +* +* Library of useful functions for plugins +* +* License: GPL +* Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net) +* Copyright (c) 2002-2007 Monitoring Plugins Development Team +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see <http://www.gnu.org/licenses/>. +* +* +*****************************************************************************/ + +#include "common.h" +#include "utils.h" +#include "utils_base.h" +#include <stdarg.h> +#include <limits.h> +#include <string.h> +#include <errno.h> + +#include <arpa/inet.h> + +extern void print_usage (void); +extern const char *progname; + +#define STRLEN 64 +#define TXTBLK 128 + +time_t start_time, end_time; + +/* ************************************************************************** + * max_state(STATE_x, STATE_y) + * compares STATE_x to STATE_y and returns result based on the following + * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL + * + * Note that numerically the above does not hold + ****************************************************************************/ + +int +max_state (int a, int b) +{ + if (a == STATE_CRITICAL || b == STATE_CRITICAL) + return STATE_CRITICAL; + else if (a == STATE_WARNING || b == STATE_WARNING) + return STATE_WARNING; + else if (a == STATE_OK || b == STATE_OK) + return STATE_OK; + else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN) + return STATE_UNKNOWN; + else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT) + return STATE_DEPENDENT; + else + return max (a, b); +} + +/* ************************************************************************** + * max_state_alt(STATE_x, STATE_y) + * compares STATE_x to STATE_y and returns result based on the following + * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL + * + * The main difference between max_state_alt and max_state it that it doesn't + * allow setting a default to UNKNOWN. It will instead prioritixe any valid + * non-OK state. + ****************************************************************************/ + +int +max_state_alt (int a, int b) +{ + if (a == STATE_CRITICAL || b == STATE_CRITICAL) + return STATE_CRITICAL; + else if (a == STATE_WARNING || b == STATE_WARNING) + return STATE_WARNING; + else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN) + return STATE_UNKNOWN; + else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT) + return STATE_DEPENDENT; + else if (a == STATE_OK || b == STATE_OK) + return STATE_OK; + else + return max (a, b); +} + +void usage (const char *msg) +{ + printf ("%s\n", msg); + print_usage (); + exit (STATE_UNKNOWN); +} + +void usage_va (const char *fmt, ...) +{ + va_list ap; + printf("%s: ", progname); + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + printf("\n"); + exit (STATE_UNKNOWN); +} + +void usage2(const char *msg, const char *arg) +{ + printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" ); + print_usage (); + exit (STATE_UNKNOWN); +} + +void +usage3 (const char *msg, int arg) +{ + printf ("%s: %s - %c\n", progname, msg, arg); + print_usage(); + exit (STATE_UNKNOWN); +} + +void +usage4 (const char *msg) +{ + printf ("%s: %s\n", progname, msg); + print_usage(); + exit (STATE_UNKNOWN); +} + +void +usage5 (void) +{ + print_usage(); + exit (STATE_UNKNOWN); +} + +void +print_revision (const char *command_name, const char *revision) +{ + printf ("%s v%s (%s %s)\n", + command_name, revision, PACKAGE, VERSION); +} + +int +is_numeric (char *number) +{ + char tmp[1]; + float x; + + if (!number) + return FALSE; + else if (sscanf (number, "%f%c", &x, tmp) == 1) + return TRUE; + else + return FALSE; +} + +int +is_positive (char *number) +{ + if (is_numeric (number) && atof (number) > 0.0) + return TRUE; + else + return FALSE; +} + +int +is_negative (char *number) +{ + if (is_numeric (number) && atof (number) < 0.0) + return TRUE; + else + return FALSE; +} + +int +is_nonnegative (char *number) +{ + if (is_numeric (number) && atof (number) >= 0.0) + return TRUE; + else + return FALSE; +} + +int +is_percentage (char *number) +{ + int x; + if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100) + return TRUE; + else + return FALSE; +} + +int +is_integer (char *number) +{ + long int n; + + if (!number || (strspn (number, "-0123456789 ") != strlen (number))) + return FALSE; + + n = strtol (number, NULL, 10); + + if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX) + return TRUE; + else + return FALSE; +} + +int +is_intpos (char *number) +{ + if (is_integer (number) && atoi (number) > 0) + return TRUE; + else + return FALSE; +} + +int +is_intneg (char *number) +{ + if (is_integer (number) && atoi (number) < 0) + return TRUE; + else + return FALSE; +} + +int +is_intnonneg (char *number) +{ + if (is_integer (number) && atoi (number) >= 0) + return TRUE; + else + return FALSE; +} + +/* + * Checks whether the number in the string _number_ can be put inside a int64_t + * On success the number will be written to the _target_ address, if _target_ is not set + * to NULL. + */ +int is_int64(char *number, int64_t *target) { + errno = 0; + uint64_t tmp = strtoll(number, NULL, 10); + if (errno != 0) { + return 0; + } + if (tmp < INT64_MIN || tmp > INT64_MAX) { + return 0; + } + if (target != NULL) { + *target = tmp; + } + return 1; +} + +/* + * Checks whether the number in the string _number_ can be put inside a uint64_t + * On success the number will be written to the _target_ address, if _target_ is not set + * to NULL. + */ +int is_uint64(char *number, uint64_t *target) { + errno = 0; + uint64_t tmp = strtoll(number, NULL, 10); + if (errno != 0) { + return 0; + } + if (tmp < 0 || tmp > UINT64_MAX) { + return 0; + } + if (target != NULL) { + *target = tmp; + } + return 1; +} + +int +is_intpercent (char *number) +{ + int i; + if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100) + return TRUE; + else + return FALSE; +} + +int +is_option (char *str) +{ + if (!str) + return FALSE; + else if (strspn (str, "-") == 1 || strspn (str, "-") == 2) + return TRUE; + else + return FALSE; +} + +#ifdef NEED_GETTIMEOFDAY +int +gettimeofday (struct timeval *tv, struct timezone *tz) +{ + tv->tv_usec = 0; + tv->tv_sec = (long) time ((time_t) 0); +} +#endif + + + +double +delta_time (struct timeval tv) +{ + struct timeval now; + + gettimeofday (&now, NULL); + return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000); +} + + + +long +deltime (struct timeval tv) +{ + struct timeval now; + gettimeofday (&now, NULL); + return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec; +} + + + + +void +strip (char *buffer) +{ + size_t x; + int i; + + for (x = strlen (buffer); x >= 1; x--) { + i = x - 1; + if (buffer[i] == ' ' || + buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t') + buffer[i] = '\0'; + else + break; + } + return; +} + + +/****************************************************************************** + * + * Copies one string to another. Any previously existing data in + * the destination string is lost. + * + * Example: + * + * char *str=NULL; + * str = strscpy("This is a line of text with no trailing newline"); + * + *****************************************************************************/ + +char * +strscpy (char *dest, const char *src) +{ + if (src == NULL) + return NULL; + + xasprintf (&dest, "%s", src); + + return dest; +} + + + +/****************************************************************************** + * + * Returns a pointer to the next line of a multiline string buffer + * + * Given a pointer string, find the text following the next sequence + * of \r and \n characters. This has the effect of skipping blank + * lines as well + * + * Example: + * + * Given text as follows: + * + * ============================== + * This + * is + * a + * + * multiline string buffer + * ============================== + * + * int i=0; + * char *str=NULL; + * char *ptr=NULL; + * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n"); + * ptr = str; + * while (ptr) { + * printf("%d %s",i++,firstword(ptr)); + * ptr = strnl(ptr); + * } + * + * Produces the following: + * + * 1 This + * 2 is + * 3 a + * 4 multiline + * + * NOTE: The 'firstword()' function is conceptual only and does not + * exist in this package. + * + * NOTE: Although the second 'ptr' variable is not strictly needed in + * this example, it is good practice with these utilities. Once + * the * pointer is advance in this manner, it may no longer be + * handled with * realloc(). So at the end of the code fragment + * above, * strscpy(str,"foo") work perfectly fine, but + * strscpy(ptr,"foo") will * cause the the program to crash with + * a segmentation fault. + * + *****************************************************************************/ + +char * +strnl (char *str) +{ + size_t len; + if (str == NULL) + return NULL; + str = strpbrk (str, "\r\n"); + if (str == NULL) + return NULL; + len = strspn (str, "\r\n"); + if (str[len] == '\0') + return NULL; + str += len; + if (strlen (str) == 0) + return NULL; + return str; +} + + +/****************************************************************************** + * + * Like strscpy, except only the portion of the source string up to + * the provided delimiter is copied. + * + * Example: + * + * str = strpcpy(str,"This is a line of text with no trailing newline","x"); + * printf("%s\n",str); + * + * Produces: + * + *This is a line of te + * + *****************************************************************************/ + +char * +strpcpy (char *dest, const char *src, const char *str) +{ + size_t len; + + if (src) + len = strcspn (src, str); + else + return NULL; + + if (dest == NULL || strlen (dest) < len) + dest = realloc (dest, len + 1); + if (dest == NULL) + die (STATE_UNKNOWN, _("failed realloc in strpcpy\n")); + + strncpy (dest, src, len); + dest[len] = '\0'; + + return dest; +} + + + +/****************************************************************************** + * + * Like strscat, except only the portion of the source string up to + * the provided delimiter is copied. + * + * str = strpcpy(str,"This is a line of text with no trailing newline","x"); + * str = strpcat(str,"This is a line of text with no trailing newline","x"); + * printf("%s\n",str); + * + *This is a line of texThis is a line of tex + * + *****************************************************************************/ + +char * +strpcat (char *dest, const char *src, const char *str) +{ + size_t len, l2; + + if (dest) + len = strlen (dest); + else + len = 0; + + if (src) { + l2 = strcspn (src, str); + } + else { + return dest; + } + + dest = realloc (dest, len + l2 + 1); + if (dest == NULL) + die (STATE_UNKNOWN, _("failed malloc in strscat\n")); + + strncpy (dest + len, src, l2); + dest[len + l2] = '\0'; + + return dest; +} + + +/****************************************************************************** + * + * asprintf, but die on failure + * + ******************************************************************************/ + +int +xvasprintf (char **strp, const char *fmt, va_list ap) +{ + int result = vasprintf (strp, fmt, ap); + if (result == -1 || *strp == NULL) + die (STATE_UNKNOWN, _("failed malloc in xvasprintf\n")); + return result; +} + +int +xasprintf (char **strp, const char *fmt, ...) +{ + va_list ap; + int result; + va_start (ap, fmt); + result = xvasprintf (strp, fmt, ap); + va_end (ap); + return result; +} + +/****************************************************************************** + * + * Print perfdata in a standard format + * + ******************************************************************************/ + +char *perfdata (const char *label, + long int val, + const char *uom, + int warnp, + long int warn, + int critp, + long int crit, + int minp, + long int minv, + int maxp, + long int maxv) +{ + char *data = NULL; + + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=%ld%s;", label, val, uom); + else + xasprintf (&data, "%s=%ld%s;", label, val, uom); + + if (warnp) + xasprintf (&data, "%s%ld;", data, warn); + else + xasprintf (&data, "%s;", data); + + if (critp) + xasprintf (&data, "%s%ld;", data, crit); + else + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%ld;", data, minv); + else + xasprintf (&data, "%s;", data); + + if (maxp) + xasprintf (&data, "%s%ld", data, maxv); + + return data; +} + + +char *perfdata_uint64 (const char *label, + uint64_t val, + const char *uom, + int warnp, /* Warning present */ + uint64_t warn, + int critp, /* Critical present */ + uint64_t crit, + int minp, /* Minimum present */ + uint64_t minv, + int maxp, /* Maximum present */ + uint64_t maxv) +{ + char *data = NULL; + + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=%" PRIu64 "%s;", label, val, uom); + else + xasprintf (&data, "%s=%" PRIu64 "%s;", label, val, uom); + + if (warnp) + xasprintf (&data, "%s%" PRIu64 ";", data, warn); + else + xasprintf (&data, "%s;", data); + + if (critp) + xasprintf (&data, "%s%" PRIu64 ";", data, crit); + else + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%" PRIu64 ";", data, minv); + else + xasprintf (&data, "%s;", data); + + if (maxp) + xasprintf (&data, "%s%" PRIu64, data, maxv); + + return data; +} + + +char *perfdata_int64 (const char *label, + int64_t val, + const char *uom, + int warnp, /* Warning present */ + int64_t warn, + int critp, /* Critical present */ + int64_t crit, + int minp, /* Minimum present */ + int64_t minv, + int maxp, /* Maximum present */ + int64_t maxv) +{ + char *data = NULL; + + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=%" PRId64 "%s;", label, val, uom); + else + xasprintf (&data, "%s=%" PRId64 "%s;", label, val, uom); + + if (warnp) + xasprintf (&data, "%s%" PRId64 ";", data, warn); + else + xasprintf (&data, "%s;", data); + + if (critp) + xasprintf (&data, "%s%" PRId64 ";", data, crit); + else + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%" PRId64 ";", data, minv); + else + xasprintf (&data, "%s;", data); + + if (maxp) + xasprintf (&data, "%s%" PRId64, data, maxv); + + return data; +} + + +char *fperfdata (const char *label, + double val, + const char *uom, + int warnp, + double warn, + int critp, + double crit, + int minp, + double minv, + int maxp, + double maxv) +{ + char *data = NULL; + + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=", label); + else + xasprintf (&data, "%s=", label); + + xasprintf (&data, "%s%f", data, val); + xasprintf (&data, "%s%s;", data, uom); + + if (warnp) + xasprintf (&data, "%s%f", data, warn); + + xasprintf (&data, "%s;", data); + + if (critp) + xasprintf (&data, "%s%f", data, crit); + + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%f", data, minv); + + if (maxp) { + xasprintf (&data, "%s;", data); + xasprintf (&data, "%s%f", data, maxv); + } + + return data; +} + +char *sperfdata (const char *label, + double val, + const char *uom, + char *warn, + char *crit, + int minp, + double minv, + int maxp, + double maxv) +{ + char *data = NULL; + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=", label); + else + xasprintf (&data, "%s=", label); + + xasprintf (&data, "%s%f", data, val); + xasprintf (&data, "%s%s;", data, uom); + + if (warn!=NULL) + xasprintf (&data, "%s%s", data, warn); + + xasprintf (&data, "%s;", data); + + if (crit!=NULL) + xasprintf (&data, "%s%s", data, crit); + + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%f", data, minv); + + if (maxp) { + xasprintf (&data, "%s;", data); + xasprintf (&data, "%s%f", data, maxv); + } + + return data; +} + +char *sperfdata_int (const char *label, + int val, + const char *uom, + char *warn, + char *crit, + int minp, + int minv, + int maxp, + int maxv) +{ + char *data = NULL; + if (strpbrk (label, "'= ")) + xasprintf (&data, "'%s'=", label); + else + xasprintf (&data, "%s=", label); + + xasprintf (&data, "%s%d", data, val); + xasprintf (&data, "%s%s;", data, uom); + + if (warn!=NULL) + xasprintf (&data, "%s%s", data, warn); + + xasprintf (&data, "%s;", data); + + if (crit!=NULL) + xasprintf (&data, "%s%s", data, crit); + + xasprintf (&data, "%s;", data); + + if (minp) + xasprintf (&data, "%s%d", data, minv); + + if (maxp) { + xasprintf (&data, "%s;", data); + xasprintf (&data, "%s%d", data, maxv); + } + + return data; +} |