Back to index

nagios-plugins  1.4.16
negate.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Nagios negate plugin
00004 * 
00005 * License: GPL
00006 * Copyright (c) 2002-2008 Nagios Plugins Development Team
00007 * 
00008 * Description:
00009 * 
00010 * This file contains the negate plugin
00011 * 
00012 * Negates the status of a plugin (returns OK for CRITICAL, and vice-versa).
00013 * Can also perform custom state switching.
00014 * 
00015 * 
00016 * This program is free software: you can redistribute it and/or modify
00017 * it under the terms of the GNU General Public License as published by
00018 * the Free Software Foundation, either version 3 of the License, or
00019 * (at your option) any later version.
00020 * 
00021 * This program is distributed in the hope that it will be useful,
00022 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00024 * GNU General Public License for more details.
00025 * 
00026 * You should have received a copy of the GNU General Public License
00027 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00028 * 
00029 * 
00030 *****************************************************************************/
00031 
00032 const char *progname = "negate";
00033 const char *copyright = "2002-2008";
00034 const char *email = "nagiosplug-devel@lists.sourceforge.net";
00035 
00036 #define DEFAULT_TIMEOUT 11
00037 
00038 #include "common.h"
00039 #include "utils.h"
00040 #include "utils_cmd.h"
00041 
00042 /* char *command_line; */
00043 
00044 static const char **process_arguments (int, char **);
00045 int validate_arguments (char **);
00046 void print_help (void);
00047 void print_usage (void);
00048 int subst_text = FALSE;
00049 
00050 static int state[4] = {
00051        STATE_OK,
00052        STATE_WARNING,
00053        STATE_CRITICAL,
00054        STATE_UNKNOWN,
00055 };
00056 
00057 int
00058 main (int argc, char **argv)
00059 {
00060        int found = 0, result = STATE_UNKNOWN;
00061        char *buf, *sub;
00062        char **command_line;
00063        output chld_out, chld_err;
00064        int i;
00065 
00066        setlocale (LC_ALL, "");
00067        bindtextdomain (PACKAGE, LOCALEDIR);
00068        textdomain (PACKAGE);
00069 
00070        timeout_interval = DEFAULT_TIMEOUT;
00071 
00072        command_line = (char **) process_arguments (argc, argv);
00073 
00074        /* Set signal handling and alarm */
00075        if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR)
00076               die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
00077 
00078        (void) alarm ((unsigned) timeout_interval);
00079 
00080        /* catch when the command is quoted */
00081        if(command_line[1] == NULL) {
00082               result = cmd_run (command_line[0], &chld_out, &chld_err, 0);
00083        } else {
00084               result = cmd_run_array (command_line, &chld_out, &chld_err, 0);
00085        }
00086        if (chld_err.lines > 0) {
00087               printf ("Error output from command:\n");
00088               for (i = 0; i < chld_err.lines; i++) {
00089                      printf ("%s\n", chld_err.line[i]);
00090               }
00091               exit (STATE_WARNING);
00092        }
00093 
00094        /* Return UNKNOWN or worse if no output is returned */
00095        if (chld_out.lines == 0)
00096               die (max_state_alt (result, STATE_UNKNOWN), _("No data returned from command\n"));
00097 
00098        for (i = 0; i < chld_out.lines; i++) {
00099               if (subst_text && result != state[result] &&
00100                   result >= 0 && result <= 4) {
00101                      /* Loop over each match found */
00102                      while ((sub = strstr (chld_out.line[i], state_text (result)))) {
00103                             /* Terminate the first part and skip over the string we'll substitute */
00104                             *sub = '\0';
00105                             sub += strlen (state_text (result));
00106                             /* then put everything back together */
00107                             asprintf (&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text (state[result]), sub);
00108                      }
00109               }
00110               printf ("%s\n", chld_out.line[i]);
00111        }
00112 
00113        if (result >= 0 && result <= 4) {
00114               exit (state[result]);
00115        } else {
00116               exit (result);
00117        }
00118 }
00119 
00120 
00121 /* process command-line arguments */
00122 static const char **
00123 process_arguments (int argc, char **argv)
00124 {
00125        int c;
00126        int permute = TRUE;
00127 
00128        int option = 0;
00129        static struct option longopts[] = {
00130               {"help", no_argument, 0, 'h'},
00131               {"version", no_argument, 0, 'V'},
00132               {"timeout", required_argument, 0, 't'},
00133               {"timeout-result", required_argument, 0, 'T'},
00134               {"ok", required_argument, 0, 'o'},
00135               {"warning", required_argument, 0, 'w'},
00136               {"critical", required_argument, 0, 'c'},
00137               {"unknown", required_argument, 0, 'u'},
00138               {"substitute", no_argument, 0, 's'},
00139               {0, 0, 0, 0}
00140        };
00141 
00142        while (1) {
00143               c = getopt_long (argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
00144 
00145               if (c == -1 || c == EOF)
00146                      break;
00147 
00148               switch (c) {
00149               case '?':     /* help */
00150                      usage5 ();
00151                      break;
00152               case 'h':     /* help */
00153                      print_help ();
00154                      exit (EXIT_SUCCESS);
00155                      break;
00156               case 'V':     /* version */
00157                      print_revision (progname, NP_VERSION);
00158                      exit (EXIT_SUCCESS);
00159               case 't':     /* timeout period */
00160                      if (!is_integer (optarg))
00161                             usage2 (_("Timeout interval must be a positive integer"), optarg);
00162                      else
00163                             timeout_interval = atoi (optarg);
00164                      break;
00165               case 'T':     /* Result to return on timeouts */
00166                      if ((timeout_state = translate_state(optarg)) == ERROR)
00167                             usage4 (_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
00168                      break;
00169               case 'o':     /* replacement for OK */
00170                      if ((state[STATE_OK] = translate_state(optarg)) == ERROR)
00171                             usage4 (_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
00172                      permute = FALSE;
00173                      break;
00174 
00175               case 'w':     /* replacement for WARNING */
00176                      if ((state[STATE_WARNING] = translate_state(optarg)) == ERROR)
00177                             usage4 (_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
00178                      permute = FALSE;
00179                      break;
00180               case 'c':     /* replacement for CRITICAL */
00181                      if ((state[STATE_CRITICAL] = translate_state(optarg)) == ERROR)
00182                             usage4 (_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
00183                      permute = FALSE;
00184                      break;
00185               case 'u':     /* replacement for UNKNOWN */
00186                      if ((state[STATE_UNKNOWN] = translate_state(optarg)) == ERROR)
00187                             usage4 (_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3)."));
00188                      permute = FALSE;
00189                      break;
00190               case 's':     /* Substitute status text */
00191                      subst_text = TRUE;
00192                      break;
00193               }
00194        }
00195 
00196        validate_arguments (&argv[optind]);
00197 
00198        if (permute) { /* No [owcu] switch specified, default to this */
00199               state[STATE_OK] = STATE_CRITICAL;
00200               state[STATE_CRITICAL] = STATE_OK;
00201        }
00202 
00203        return (const char **) &argv[optind];
00204 }
00205 
00206 
00207 int
00208 validate_arguments (char **command_line)
00209 {
00210        if (command_line[0] == NULL)
00211               usage4 (_("Could not parse arguments"));
00212 
00213        if (strncmp(command_line[0],"/",1) != 0 && strncmp(command_line[0],"./",2) != 0)
00214               usage4 (_("Require path to command"));
00215 }
00216 
00217 
00218 int
00219 translate_state (char *state_text)
00220 {
00221        char *temp_ptr;
00222        for (temp_ptr = state_text; *temp_ptr; temp_ptr++) {
00223               *temp_ptr = toupper(*temp_ptr);
00224        }
00225        if (!strcmp(state_text,"OK") || !strcmp(state_text,"0"))
00226               return STATE_OK;
00227        if (!strcmp(state_text,"WARNING") || !strcmp(state_text,"1"))
00228               return STATE_WARNING;
00229        if (!strcmp(state_text,"CRITICAL") || !strcmp(state_text,"2"))
00230               return STATE_CRITICAL;
00231        if (!strcmp(state_text,"UNKNOWN") || !strcmp(state_text,"3"))
00232               return STATE_UNKNOWN;
00233        return ERROR;
00234 }
00235 
00236 void
00237 print_help (void)
00238 {
00239        print_revision (progname, NP_VERSION);
00240 
00241        printf (COPYRIGHT, copyright, email);
00242 
00243        printf ("%s\n", _("Negates the status of a plugin (returns OK for CRITICAL and vice-versa)."));
00244        printf ("%s\n", _("Additional switches can be used to control which state becomes what."));
00245 
00246        printf ("\n\n");
00247 
00248        print_usage ();
00249 
00250        printf (UT_HELP_VRSN);
00251 
00252        printf (UT_TIMEOUT, timeout_interval);
00253        printf ("    %s\n", _("Keep timeout longer than the plugin timeout to retain CRITICAL status."));
00254        printf (" -T, --timeout-result=STATUS\n");
00255        printf ("    %s\n", _("Custom result on Negate timeouts; see below for STATUS definition\n"));
00256 
00257        printf(" -o, --ok=STATUS\n");
00258        printf(" -w, --warning=STATUS\n");
00259        printf(" -c, --critical=STATUS\n");
00260        printf(" -u, --unknown=STATUS\n");
00261        printf(_("    STATUS can be 'OK', 'WARNING', 'CRITICAL' or 'UNKNOWN' without single\n"));
00262        printf(_("    quotes. Numeric values are accepted. If nothing is specified, permutes\n"));
00263        printf(_("    OK and CRITICAL.\n"));
00264        printf(" -s, --substitute\n");
00265        printf(_("    Substitute output text as well. Will only substitute text in CAPITALS\n"));
00266 
00267        printf ("\n");
00268        printf ("%s\n", _("Examples:"));
00269        printf (" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host");
00270        printf ("    %s\n", _("Run check_ping and invert result. Must use full path to plugin"));
00271        printf (" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'");
00272        printf ("    %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL"));
00273        printf ("\n");
00274        printf ("%s\n", _("Notes:"));
00275        printf (" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it."));
00276        printf (" %s\n", _("The full path of the plugin must be provided."));
00277        printf (" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL."));
00278        printf (" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK."));
00279        printf (" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged."));
00280        printf ("\n");
00281        printf (" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a"));
00282        printf (" %s\n", _("plugin by setting the negate timeout a bit lower."));
00283 
00284        printf (UT_SUPPORT);
00285 }
00286 
00287 
00288 
00289 void
00290 print_usage (void)
00291 {
00292        printf ("%s\n", _("Usage:"));
00293        printf ("%s [-t timeout] [-Towcu STATE] [-s] <definition of wrapped plugin>\n", progname);
00294 }