Back to index

nagios-plugins  1.4.16
utils.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Library of useful functions for plugins
00004 * 
00005 * License: GPL
00006 * Copyright (c) 2000 Karl DeBisschop (karl@debisschop.net)
00007 * Copyright (c) 2002-2007 Nagios Plugin Development Team
00008 * 
00009 * This program is free software: you can redistribute it and/or modify
00010 * it under the terms of the GNU General Public License as published by
00011 * the Free Software Foundation, either version 3 of the License, or
00012 * (at your option) any later version.
00013 * 
00014 * This program is distributed in the hope that it will be useful,
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 * GNU General Public License for more details.
00018 * 
00019 * You should have received a copy of the GNU General Public License
00020 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00021 * 
00022 * 
00023 *****************************************************************************/
00024 
00025 #define LOCAL_TIMEOUT_ALARM_HANDLER
00026 
00027 #include "common.h"
00028 #include "utils.h"
00029 #include "utils_base.h"
00030 #include <stdarg.h>
00031 #include <limits.h>
00032 
00033 #include <arpa/inet.h>
00034 
00035 extern void print_usage (void);
00036 extern const char *progname;
00037 
00038 #define STRLEN 64
00039 #define TXTBLK 128
00040 
00041 /* **************************************************************************
00042  * max_state(STATE_x, STATE_y)
00043  * compares STATE_x to  STATE_y and returns result based on the following
00044  * STATE_UNKNOWN < STATE_OK < STATE_WARNING < STATE_CRITICAL
00045  *
00046  * Note that numerically the above does not hold
00047  ****************************************************************************/
00048 
00049 int
00050 max_state (int a, int b)
00051 {
00052        if (a == STATE_CRITICAL || b == STATE_CRITICAL)
00053               return STATE_CRITICAL;
00054        else if (a == STATE_WARNING || b == STATE_WARNING)
00055               return STATE_WARNING;
00056        else if (a == STATE_OK || b == STATE_OK)
00057               return STATE_OK;
00058        else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
00059               return STATE_UNKNOWN;
00060        else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
00061               return STATE_DEPENDENT;
00062        else
00063               return max (a, b);
00064 }
00065 
00066 /* **************************************************************************
00067  * max_state_alt(STATE_x, STATE_y)
00068  * compares STATE_x to  STATE_y and returns result based on the following
00069  * STATE_OK < STATE_DEPENDENT < STATE_UNKNOWN < STATE_WARNING < STATE_CRITICAL
00070  *
00071  * The main difference between max_state_alt and max_state it that it doesn't
00072  * allow setting a default to UNKNOWN. It will instead prioritixe any valid
00073  * non-OK state.
00074  ****************************************************************************/
00075 
00076 int
00077 max_state_alt (int a, int b)
00078 {
00079        if (a == STATE_CRITICAL || b == STATE_CRITICAL)
00080               return STATE_CRITICAL;
00081        else if (a == STATE_WARNING || b == STATE_WARNING)
00082               return STATE_WARNING;
00083        else if (a == STATE_UNKNOWN || b == STATE_UNKNOWN)
00084               return STATE_UNKNOWN;
00085        else if (a == STATE_DEPENDENT || b == STATE_DEPENDENT)
00086               return STATE_DEPENDENT;
00087        else if (a == STATE_OK || b == STATE_OK)
00088               return STATE_OK;
00089        else
00090               return max (a, b);
00091 }
00092 
00093 void usage (const char *msg)
00094 {
00095        printf ("%s\n", msg);
00096        print_usage ();
00097        exit (STATE_UNKNOWN);
00098 }
00099 
00100 void usage_va (const char *fmt, ...)
00101 {
00102        va_list ap;
00103        printf("%s: ", progname);
00104        va_start(ap, fmt);
00105        vprintf(fmt, ap);
00106        va_end(ap);
00107        printf("\n");
00108        exit (STATE_UNKNOWN);
00109 }
00110 
00111 void usage2(const char *msg, const char *arg)
00112 {
00113        printf ("%s: %s - %s\n", progname, msg, arg?arg:"(null)" );
00114        print_usage ();
00115        exit (STATE_UNKNOWN);
00116 }
00117 
00118 void
00119 usage3 (const char *msg, int arg)
00120 {
00121        printf ("%s: %s - %c\n", progname, msg, arg);
00122        print_usage();
00123        exit (STATE_UNKNOWN);
00124 }
00125 
00126 void
00127 usage4 (const char *msg)
00128 {
00129        printf ("%s: %s\n", progname, msg);
00130        print_usage();
00131        exit (STATE_UNKNOWN);
00132 }
00133 
00134 void
00135 usage5 (void)
00136 {
00137        print_usage();
00138        exit (STATE_UNKNOWN);
00139 }
00140 
00141 void
00142 print_revision (const char *command_name, const char *revision)
00143 {
00144        char plugin_revision[STRLEN];
00145 
00146        printf ("%s v%s (%s %s)\n",
00147                 command_name, revision, PACKAGE, VERSION);
00148 }
00149 
00150 const char *
00151 state_text (int result)
00152 {
00153        switch (result) {
00154        case STATE_OK:
00155               return "OK";
00156        case STATE_WARNING:
00157               return "WARNING";
00158        case STATE_CRITICAL:
00159               return "CRITICAL";
00160        case STATE_DEPENDENT:
00161               return "DEPENDENT";
00162        default:
00163               return "UNKNOWN";
00164        }
00165 }
00166 
00167 void
00168 timeout_alarm_handler (int signo)
00169 {
00170        if (signo == SIGALRM) {
00171               printf (_("%s - Plugin timed out after %d seconds\n"),
00172                                           state_text(timeout_state), timeout_interval);
00173               exit (timeout_state);
00174        }
00175 }
00176 
00177 int
00178 is_numeric (char *number)
00179 {
00180        char tmp[1];
00181        float x;
00182 
00183        if (!number)
00184               return FALSE;
00185        else if (sscanf (number, "%f%c", &x, tmp) == 1)
00186               return TRUE;
00187        else
00188               return FALSE;
00189 }
00190 
00191 int
00192 is_positive (char *number)
00193 {
00194        if (is_numeric (number) && atof (number) > 0.0)
00195               return TRUE;
00196        else
00197               return FALSE;
00198 }
00199 
00200 int
00201 is_negative (char *number)
00202 {
00203        if (is_numeric (number) && atof (number) < 0.0)
00204               return TRUE;
00205        else
00206               return FALSE;
00207 }
00208 
00209 int
00210 is_nonnegative (char *number)
00211 {
00212        if (is_numeric (number) && atof (number) >= 0.0)
00213               return TRUE;
00214        else
00215               return FALSE;
00216 }
00217 
00218 int
00219 is_percentage (char *number)
00220 {
00221        int x;
00222        if (is_numeric (number) && (x = atof (number)) >= 0 && x <= 100)
00223               return TRUE;
00224        else
00225               return FALSE;
00226 }
00227 
00228 int
00229 is_integer (char *number)
00230 {
00231        long int n;
00232 
00233        if (!number || (strspn (number, "-0123456789 ") != strlen (number)))
00234               return FALSE;
00235 
00236        n = strtol (number, NULL, 10);
00237 
00238        if (errno != ERANGE && n >= INT_MIN && n <= INT_MAX)
00239               return TRUE;
00240        else
00241               return FALSE;
00242 }
00243 
00244 int
00245 is_intpos (char *number)
00246 {
00247        if (is_integer (number) && atoi (number) > 0)
00248               return TRUE;
00249        else
00250               return FALSE;
00251 }
00252 
00253 int
00254 is_intneg (char *number)
00255 {
00256        if (is_integer (number) && atoi (number) < 0)
00257               return TRUE;
00258        else
00259               return FALSE;
00260 }
00261 
00262 int
00263 is_intnonneg (char *number)
00264 {
00265        if (is_integer (number) && atoi (number) >= 0)
00266               return TRUE;
00267        else
00268               return FALSE;
00269 }
00270 
00271 int
00272 is_intpercent (char *number)
00273 {
00274        int i;
00275        if (is_integer (number) && (i = atoi (number)) >= 0 && i <= 100)
00276               return TRUE;
00277        else
00278               return FALSE;
00279 }
00280 
00281 int
00282 is_option (char *str)
00283 {
00284        if (!str)
00285               return FALSE;
00286        else if (strspn (str, "-") == 1 || strspn (str, "-") == 2)
00287               return TRUE;
00288        else
00289               return FALSE;
00290 }
00291 
00292 #ifdef NEED_GETTIMEOFDAY
00293 int
00294 gettimeofday (struct timeval *tv, struct timezone *tz)
00295 {
00296        tv->tv_usec = 0;
00297        tv->tv_sec = (long) time ((time_t) 0);
00298 }
00299 #endif
00300 
00301 
00302 
00303 double
00304 delta_time (struct timeval tv)
00305 {
00306        struct timeval now;
00307 
00308        gettimeofday (&now, NULL);
00309        return ((double)(now.tv_sec - tv.tv_sec) + (double)(now.tv_usec - tv.tv_usec) / (double)1000000);
00310 }
00311 
00312 
00313 
00314 long
00315 deltime (struct timeval tv)
00316 {
00317        struct timeval now;
00318        gettimeofday (&now, NULL);
00319        return (now.tv_sec - tv.tv_sec)*1000000 + now.tv_usec - tv.tv_usec;
00320 }
00321 
00322 
00323 
00324 
00325 void
00326 strip (char *buffer)
00327 {
00328        size_t x;
00329        int i;
00330 
00331        for (x = strlen (buffer); x >= 1; x--) {
00332               i = x - 1;
00333               if (buffer[i] == ' ' ||
00334                             buffer[i] == '\r' || buffer[i] == '\n' || buffer[i] == '\t')
00335                      buffer[i] = '\0';
00336               else
00337                      break;
00338        }
00339        return;
00340 }
00341 
00342 
00343 /******************************************************************************
00344  *
00345  * Copies one string to another. Any previously existing data in
00346  * the destination string is lost.
00347  *
00348  * Example:
00349  *
00350  * char *str=NULL;
00351  * str = strscpy("This is a line of text with no trailing newline");
00352  *
00353  *****************************************************************************/
00354 
00355 char *
00356 strscpy (char *dest, const char *src)
00357 {
00358        if (src == NULL)
00359               return NULL;
00360 
00361        asprintf (&dest, "%s", src);
00362 
00363        return dest;
00364 }
00365 
00366 
00367 
00368 /******************************************************************************
00369  *
00370  * Returns a pointer to the next line of a multiline string buffer
00371  *
00372  * Given a pointer string, find the text following the next sequence
00373  * of \r and \n characters. This has the effect of skipping blank
00374  * lines as well
00375  *
00376  * Example:
00377  *
00378  * Given text as follows:
00379  *
00380  * ==============================
00381  * This
00382  * is
00383  * a
00384  * 
00385  * multiline string buffer
00386  * ==============================
00387  *
00388  * int i=0;
00389  * char *str=NULL;
00390  * char *ptr=NULL;
00391  * str = strscpy(str,"This\nis\r\na\n\nmultiline string buffer\n");
00392  * ptr = str;
00393  * while (ptr) {
00394  *   printf("%d %s",i++,firstword(ptr));
00395  *   ptr = strnl(ptr);
00396  * }
00397  * 
00398  * Produces the following:
00399  *
00400  * 1 This
00401  * 2 is
00402  * 3 a
00403  * 4 multiline
00404  *
00405  * NOTE: The 'firstword()' function is conceptual only and does not
00406  *       exist in this package.
00407  *
00408  * NOTE: Although the second 'ptr' variable is not strictly needed in
00409  *       this example, it is good practice with these utilities. Once
00410  *       the * pointer is advance in this manner, it may no longer be
00411  *       handled with * realloc(). So at the end of the code fragment
00412  *       above, * strscpy(str,"foo") work perfectly fine, but
00413  *       strscpy(ptr,"foo") will * cause the the program to crash with
00414  *       a segmentation fault.
00415  *
00416  *****************************************************************************/
00417 
00418 char *
00419 strnl (char *str)
00420 {
00421        size_t len;
00422        if (str == NULL)
00423               return NULL;
00424        str = strpbrk (str, "\r\n");
00425        if (str == NULL)
00426               return NULL;
00427        len = strspn (str, "\r\n");
00428        if (str[len] == '\0')
00429               return NULL;
00430        str += len;
00431        if (strlen (str) == 0)
00432               return NULL;
00433        return str;
00434 }
00435 
00436 
00437 /******************************************************************************
00438  *
00439  * Like strscpy, except only the portion of the source string up to
00440  * the provided delimiter is copied.
00441  *
00442  * Example:
00443  *
00444  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
00445  * printf("%s\n",str);
00446  *
00447  * Produces:
00448  *
00449  *This is a line of te
00450  *
00451  *****************************************************************************/
00452 
00453 char *
00454 strpcpy (char *dest, const char *src, const char *str)
00455 {
00456        size_t len;
00457 
00458        if (src)
00459               len = strcspn (src, str);
00460        else
00461               return NULL;
00462 
00463        if (dest == NULL || strlen (dest) < len)
00464               dest = realloc (dest, len + 1);
00465        if (dest == NULL)
00466               die (STATE_UNKNOWN, _("failed realloc in strpcpy\n"));
00467 
00468        strncpy (dest, src, len);
00469        dest[len] = '\0';
00470 
00471        return dest;
00472 }
00473 
00474 
00475 
00476 /******************************************************************************
00477  *
00478  * Like strscat, except only the portion of the source string up to
00479  * the provided delimiter is copied.
00480  *
00481  * str = strpcpy(str,"This is a line of text with no trailing newline","x");
00482  * str = strpcat(str,"This is a line of text with no trailing newline","x");
00483  * printf("%s\n",str);
00484  * 
00485  *This is a line of texThis is a line of tex
00486  *
00487  *****************************************************************************/
00488 
00489 char *
00490 strpcat (char *dest, const char *src, const char *str)
00491 {
00492        size_t len, l2;
00493 
00494        if (dest)
00495               len = strlen (dest);
00496        else
00497               len = 0;
00498 
00499        if (src) {
00500               l2 = strcspn (src, str);
00501        }
00502        else {
00503               return dest;
00504        }
00505 
00506        dest = realloc (dest, len + l2 + 1);
00507        if (dest == NULL)
00508               die (STATE_UNKNOWN, _("failed malloc in strscat\n"));
00509 
00510        strncpy (dest + len, src, l2);
00511        dest[len + l2] = '\0';
00512 
00513        return dest;
00514 }
00515 
00516 /******************************************************************************
00517  *
00518  * Print perfdata in a standard format
00519  *
00520  ******************************************************************************/
00521 
00522 char *perfdata (const char *label,
00523  long int val,
00524  const char *uom,
00525  int warnp,
00526  long int warn,
00527  int critp,
00528  long int crit,
00529  int minp,
00530  long int minv,
00531  int maxp,
00532  long int maxv)
00533 {
00534        char *data = NULL;
00535 
00536        if (strpbrk (label, "'= "))
00537               asprintf (&data, "'%s'=%ld%s;", label, val, uom);
00538        else
00539               asprintf (&data, "%s=%ld%s;", label, val, uom);
00540 
00541        if (warnp)
00542               asprintf (&data, "%s%ld;", data, warn);
00543        else
00544               asprintf (&data, "%s;", data);
00545 
00546        if (critp)
00547               asprintf (&data, "%s%ld;", data, crit);
00548        else
00549               asprintf (&data, "%s;", data);
00550 
00551        if (minp)
00552               asprintf (&data, "%s%ld", data, minv);
00553 
00554        if (maxp)
00555               asprintf (&data, "%s;%ld", data, maxv);
00556 
00557        return data;
00558 }
00559 
00560 
00561 char *fperfdata (const char *label,
00562  double val,
00563  const char *uom,
00564  int warnp,
00565  double warn,
00566  int critp,
00567  double crit,
00568  int minp,
00569  double minv,
00570  int maxp,
00571  double maxv)
00572 {
00573        char *data = NULL;
00574 
00575        if (strpbrk (label, "'= "))
00576               asprintf (&data, "'%s'=", label);
00577        else
00578               asprintf (&data, "%s=", label);
00579 
00580        asprintf (&data, "%s%f", data, val);
00581        asprintf (&data, "%s%s;", data, uom);
00582 
00583        if (warnp)
00584               asprintf (&data, "%s%f", data, warn);
00585 
00586        asprintf (&data, "%s;", data);
00587 
00588        if (critp)
00589               asprintf (&data, "%s%f", data, crit);
00590 
00591        asprintf (&data, "%s;", data);
00592 
00593        if (minp)
00594               asprintf (&data, "%s%f", data, minv);
00595 
00596        if (maxp) {
00597               asprintf (&data, "%s;", data);
00598               asprintf (&data, "%s%f", data, maxv);
00599        }
00600 
00601        return data;
00602 }