summaryrefslogtreecommitdiffstats
path: root/plugins/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/utils.c')
-rw-r--r--plugins/utils.c806
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;
+}