/***************************************************************************** * * 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 . * * *****************************************************************************/ #include "common.h" #include "utils.h" #include "utils_base.h" #include #include #include extern void print_usage (void); extern const char *progname; #define STRLEN 64 #define TXTBLK 128 unsigned int timeout_state = STATE_CRITICAL; unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; 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); } const char * state_text (int result) { switch (result) { case STATE_OK: return "OK"; case STATE_WARNING: return "WARNING"; case STATE_CRITICAL: return "CRITICAL"; case STATE_DEPENDENT: return "DEPENDENT"; default: return "UNKNOWN"; } } void timeout_alarm_handler (int signo) { if (signo == SIGALRM) { printf (_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state), timeout_interval); exit (timeout_state); } } 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; } 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); if (maxp) xasprintf (&data, "%s;%ld", 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; }