Back to index

nagios-plugins  1.4.16
check_procs.c
Go to the documentation of this file.
00001 /*****************************************************************************
00002 * 
00003 * Nagios check_procs plugin
00004 * 
00005 * License: GPL
00006 * Copyright (c) 2000-2008 Nagios Plugins Development Team
00007 * 
00008 * Description:
00009 * 
00010 * This file contains the check_procs plugin
00011 * 
00012 * Checks all processes and generates WARNING or CRITICAL states if the
00013 * specified metric is outside the required threshold ranges. The metric
00014 * defaults to number of processes.  Search filters can be applied to limit
00015 * the processes to check.
00016 * 
00017 * 
00018 * This program is free software: you can redistribute it and/or modify
00019 * it under the terms of the GNU General Public License as published by
00020 * the Free Software Foundation, either version 3 of the License, or
00021 * (at your option) any later version.
00022 * 
00023 * This program is distributed in the hope that it will be useful,
00024 * but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 * GNU General Public License for more details.
00027 * 
00028 * You should have received a copy of the GNU General Public License
00029 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00030 * 
00031 * 
00032 *****************************************************************************/
00033 
00034 const char *progname = "check_procs";
00035 const char *program_name = "check_procs";  /* Required for coreutils libs */
00036 const char *copyright = "2000-2008";
00037 const char *email = "nagiosplug-devel@lists.sourceforge.net";
00038 
00039 #include "common.h"
00040 #include "utils.h"
00041 #include "utils_cmd.h"
00042 #include "regex.h"
00043 
00044 #include <pwd.h>
00045 
00046 int process_arguments (int, char **);
00047 int validate_arguments (void);
00048 int check_thresholds (int);
00049 int convert_to_seconds (char *); 
00050 void print_help (void);
00051 void print_usage (void);
00052 
00053 int wmax = -1;
00054 int cmax = -1;
00055 int wmin = -1;
00056 int cmin = -1;
00057 
00058 int options = 0; /* bitmask of filter criteria to test against */
00059 #define ALL 1
00060 #define STAT 2
00061 #define PPID 4
00062 #define USER 8
00063 #define PROG 16
00064 #define ARGS 32
00065 #define VSZ  64
00066 #define RSS  128
00067 #define PCPU 256
00068 #define ELAPSED 512
00069 #define EREG_ARGS 1024
00070 /* Different metrics */
00071 char *metric_name;
00072 enum metric {
00073        METRIC_PROCS,
00074        METRIC_VSZ,
00075        METRIC_RSS,
00076        METRIC_CPU,
00077        METRIC_ELAPSED
00078 };
00079 enum metric metric = METRIC_PROCS;
00080 
00081 int verbose = 0;
00082 int uid;
00083 pid_t ppid;
00084 int vsz;
00085 int rss;
00086 float pcpu;
00087 char *statopts;
00088 char *prog;
00089 char *args;
00090 char *input_filename = NULL;
00091 regex_t re_args;
00092 char *fmt;
00093 char *fails;
00094 char tmp[MAX_INPUT_BUFFER];
00095 
00096 FILE *ps_input = NULL;
00097 
00098 
00099 int
00100 main (int argc, char **argv)
00101 {
00102        char *input_buffer;
00103        char *input_line;
00104        char *procprog;
00105 
00106        pid_t mypid = 0;
00107        int procuid = 0;
00108        pid_t procpid = 0;
00109        pid_t procppid = 0;
00110        int procvsz = 0;
00111        int procrss = 0;
00112        int procseconds = 0;
00113        float procpcpu = 0;
00114        char procstat[8];
00115        char procetime[MAX_INPUT_BUFFER] = { '\0' };
00116        char *procargs;
00117 
00118        const char *zombie = "Z";
00119 
00120        int resultsum = 0; /* bitmask of the filter criteria met by a process */
00121        int found = 0; /* counter for number of lines returned in `ps` output */
00122        int procs = 0; /* counter for number of processes meeting filter criteria */
00123        int pos; /* number of spaces before 'args' in `ps` output */
00124        int cols; /* number of columns in ps output */
00125        int expected_cols = PS_COLS - 1;
00126        int warn = 0; /* number of processes in warn state */
00127        int crit = 0; /* number of processes in crit state */
00128        int i = 0, j = 0;
00129        int result = STATE_UNKNOWN;
00130        output chld_out, chld_err;
00131 
00132        setlocale (LC_ALL, "");
00133        bindtextdomain (PACKAGE, LOCALEDIR);
00134        textdomain (PACKAGE);
00135        setlocale(LC_NUMERIC, "POSIX");
00136 
00137        input_buffer = malloc (MAX_INPUT_BUFFER);
00138        procprog = malloc (MAX_INPUT_BUFFER);
00139 
00140        asprintf (&metric_name, "PROCS");
00141        metric = METRIC_PROCS;
00142 
00143        /* Parse extra opts if any */
00144        argv=np_extra_opts (&argc, argv, progname);
00145 
00146        if (process_arguments (argc, argv) == ERROR)
00147               usage4 (_("Could not parse arguments"));
00148 
00149        /* get our pid */
00150        mypid = getpid();
00151 
00152        /* Set signal handling and alarm timeout */
00153        if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
00154               die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
00155        }
00156        (void) alarm ((unsigned) timeout_interval);
00157 
00158        if (verbose >= 2)
00159               printf (_("CMD: %s\n"), PS_COMMAND);
00160 
00161        if (input_filename == NULL) {
00162               result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
00163               if (chld_err.lines > 0) {
00164                      printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
00165                      exit(STATE_WARNING);
00166               }
00167        } else {
00168               result = cmd_file_read( input_filename, &chld_out, 0);
00169        }
00170 
00171        /* flush first line: j starts at 1 */
00172        for (j = 1; j < chld_out.lines; j++) {
00173               input_line = chld_out.line[j];
00174 
00175               if (verbose >= 3)
00176                      printf ("%s", input_line);
00177 
00178               strcpy (procprog, "");
00179               asprintf (&procargs, "%s", "");
00180 
00181               cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
00182 
00183               /* Zombie processes do not give a procprog command */
00184               if ( cols < expected_cols && strstr(procstat, zombie) ) {
00185                      cols = expected_cols;
00186               }
00187               if ( cols >= expected_cols ) {
00188                      resultsum = 0;
00189                      asprintf (&procargs, "%s", input_line + pos);
00190                      strip (procargs);
00191 
00192                      /* Some ps return full pathname for command. This removes path */
00193                      strcpy(procprog, base_name(procprog));
00194 
00195                      /* we need to convert the elapsed time to seconds */
00196                      procseconds = convert_to_seconds(procetime);
00197 
00198                      if (verbose >= 3)
00199                             printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
00200                                    procs, procuid, procvsz, procrss,
00201                                    procpid, procppid, procpcpu, procstat, 
00202                                    procetime, procprog, procargs);
00203 
00204                      /* Ignore self */
00205                      if (mypid == procpid) continue;
00206 
00207                      if ((options & STAT) && (strstr (statopts, procstat)))
00208                             resultsum |= STAT;
00209                      if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
00210                             resultsum |= ARGS;
00211                      if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
00212                             resultsum |= EREG_ARGS;
00213                      if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
00214                             resultsum |= PROG;
00215                      if ((options & PPID) && (procppid == ppid))
00216                             resultsum |= PPID;
00217                      if ((options & USER) && (procuid == uid))
00218                             resultsum |= USER;
00219                      if ((options & VSZ)  && (procvsz >= vsz))
00220                             resultsum |= VSZ;
00221                      if ((options & RSS)  && (procrss >= rss))
00222                             resultsum |= RSS;
00223                      if ((options & PCPU)  && (procpcpu >= pcpu))
00224                             resultsum |= PCPU;
00225 
00226                      found++;
00227 
00228                      /* Next line if filters not matched */
00229                      if (!(options == resultsum || options == ALL))
00230                             continue;
00231 
00232                      procs++;
00233                      if (verbose >= 2) {
00234                             printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
00235                                    procuid, procvsz, procrss,
00236                                    procpid, procppid, procpcpu, procstat, 
00237                                    procetime, procprog, procargs);
00238                      }
00239 
00240                      if (metric == METRIC_VSZ)
00241                             i = check_thresholds (procvsz);
00242                      else if (metric == METRIC_RSS)
00243                             i = check_thresholds (procrss);
00244                      /* TODO? float thresholds for --metric=CPU */
00245                      else if (metric == METRIC_CPU)
00246                             i = check_thresholds ((int)procpcpu); 
00247                      else if (metric == METRIC_ELAPSED)
00248                             i = check_thresholds (procseconds);
00249 
00250                      if (metric != METRIC_PROCS) {
00251                             if (i == STATE_WARNING) {
00252                                    warn++;
00253                                    asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
00254                                    result = max_state (result, i);
00255                             }
00256                             if (i == STATE_CRITICAL) {
00257                                    crit++;
00258                                    asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
00259                                    result = max_state (result, i);
00260                             }
00261                      }
00262               } 
00263               /* This should not happen */
00264               else if (verbose) {
00265                      printf(_("Not parseable: %s"), input_buffer);
00266               }
00267        }
00268 
00269        if (found == 0) {                                              /* no process lines parsed so return STATE_UNKNOWN */
00270               printf (_("Unable to read output\n"));
00271               return STATE_UNKNOWN;
00272        }
00273 
00274        if ( result == STATE_UNKNOWN ) 
00275               result = STATE_OK;
00276 
00277        /* Needed if procs found, but none match filter */
00278        if ( metric == METRIC_PROCS ) {
00279               result = max_state (result, check_thresholds (procs) );
00280        }
00281 
00282        if ( result == STATE_OK ) {
00283               printf ("%s %s: ", metric_name, _("OK"));
00284        } else if (result == STATE_WARNING) {
00285               printf ("%s %s: ", metric_name, _("WARNING"));
00286               if ( metric != METRIC_PROCS ) {
00287                      printf (_("%d warn out of "), warn);
00288               }
00289        } else if (result == STATE_CRITICAL) {
00290               printf ("%s %s: ", metric_name, _("CRITICAL"));
00291               if (metric != METRIC_PROCS) {
00292                      printf (_("%d crit, %d warn out of "), crit, warn);
00293               }
00294        } 
00295        printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
00296        
00297        if (strcmp(fmt,"") != 0) {
00298               printf (_(" with %s"), fmt);
00299        }
00300 
00301        if ( verbose >= 1 && strcmp(fails,"") )
00302               printf (" [%s]", fails);
00303 
00304        printf ("\n");
00305        return result;
00306 }
00307 
00308 
00309 
00310 /* process command-line arguments */
00311 int
00312 process_arguments (int argc, char **argv)
00313 {
00314        int c = 1;
00315        char *user;
00316        struct passwd *pw;
00317        int option = 0;
00318        int err;
00319        int cflags = REG_NOSUB | REG_EXTENDED;
00320        char errbuf[MAX_INPUT_BUFFER];
00321        char *temp_string;
00322        int i=0;
00323        static struct option longopts[] = {
00324               {"warning", required_argument, 0, 'w'},
00325               {"critical", required_argument, 0, 'c'},
00326               {"metric", required_argument, 0, 'm'},
00327               {"timeout", required_argument, 0, 't'},
00328               {"status", required_argument, 0, 's'},
00329               {"ppid", required_argument, 0, 'p'},
00330               {"command", required_argument, 0, 'C'},
00331               {"vsz", required_argument, 0, 'z'},
00332               {"rss", required_argument, 0, 'r'},
00333               {"pcpu", required_argument, 0, 'P'},
00334               {"elapsed", required_argument, 0, 'e'},
00335               {"argument-array", required_argument, 0, 'a'},
00336               {"help", no_argument, 0, 'h'},
00337               {"version", no_argument, 0, 'V'},
00338               {"verbose", no_argument, 0, 'v'},
00339               {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
00340               {"input-file", required_argument, 0, CHAR_MAX+2},
00341               {0, 0, 0, 0}
00342        };
00343 
00344        for (c = 1; c < argc; c++)
00345               if (strcmp ("-to", argv[c]) == 0)
00346                      strcpy (argv[c], "-t");
00347 
00348        while (1) {
00349               c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", 
00350                      longopts, &option);
00351 
00352               if (c == -1 || c == EOF)
00353                      break;
00354 
00355               switch (c) {
00356               case '?':                                                             /* help */
00357                      usage5 ();
00358               case 'h':                                                             /* help */
00359                      print_help ();
00360                      exit (STATE_OK);
00361               case 'V':                                                             /* version */
00362                      print_revision (progname, NP_VERSION);
00363                      exit (STATE_OK);
00364               case 't':                                                             /* timeout period */
00365                      if (!is_integer (optarg))
00366                             usage2 (_("Timeout interval must be a positive integer"), optarg);
00367                      else
00368                             timeout_interval = atoi (optarg);
00369                      break;
00370               case 'c':                                                             /* critical threshold */
00371                      if (is_integer (optarg))
00372                             cmax = atoi (optarg);
00373                      else if (sscanf (optarg, ":%d", &cmax) == 1)
00374                             break;
00375                      else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
00376                             break;
00377                      else if (sscanf (optarg, "%d:", &cmin) == 1)
00378                             break;
00379                      else
00380                             usage4 (_("Critical Process Count must be an integer!"));
00381                      break;                                            
00382               case 'w':                                                             /* warning threshold */
00383                      if (is_integer (optarg))
00384                             wmax = atoi (optarg);
00385                      else if (sscanf (optarg, ":%d", &wmax) == 1)
00386                             break;
00387                      else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
00388                             break;
00389                      else if (sscanf (optarg, "%d:", &wmin) == 1)
00390                             break;
00391                      else
00392                             usage4 (_("Warning Process Count must be an integer!"));
00393                      break;
00394               case 'p':                                                             /* process id */
00395                      if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
00396                             asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
00397                             options |= PPID;
00398                             break;
00399                      }
00400                      usage4 (_("Parent Process ID must be an integer!"));
00401               case 's':                                                             /* status */
00402                      if (statopts)
00403                             break;
00404                      else
00405                             statopts = optarg;
00406                      asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
00407                      options |= STAT;
00408                      break;
00409               case 'u':                                                             /* user or user id */
00410                      if (is_integer (optarg)) {
00411                             uid = atoi (optarg);
00412                             pw = getpwuid ((uid_t) uid);
00413                             /*  check to be sure user exists */
00414                             if (pw == NULL)
00415                                    usage2 (_("UID was not found"), optarg);
00416                      }
00417                      else {
00418                             pw = getpwnam (optarg);
00419                             /*  check to be sure user exists */
00420                             if (pw == NULL)
00421                                    usage2 (_("User name was not found"), optarg);
00422                             /*  then get uid */
00423                             uid = pw->pw_uid;
00424                      }
00425                      user = pw->pw_name;
00426                      asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
00427                                uid, user);
00428                      options |= USER;
00429                      break;
00430               case 'C':                                                             /* command */
00431                      /* TODO: allow this to be passed in with --metric */
00432                      if (prog)
00433                             break;
00434                      else
00435                             prog = optarg;
00436                      asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
00437                                prog);
00438                      options |= PROG;
00439                      break;
00440               case 'a':                                                             /* args (full path name with args) */
00441                      /* TODO: allow this to be passed in with --metric */
00442                      if (args)
00443                             break;
00444                      else
00445                             args = optarg;
00446                      asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
00447                      options |= ARGS;
00448                      break;
00449               case CHAR_MAX+1:
00450                      err = regcomp(&re_args, optarg, cflags);
00451                      if (err != 0) {
00452                             regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
00453                             die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
00454                      }
00455                      /* Strip off any | within the regex optarg */
00456                      temp_string = strdup(optarg);
00457                      while(temp_string[i]!='\0'){
00458                             if(temp_string[i]=='|')
00459                                    temp_string[i]=',';
00460                             i++;
00461                      }
00462                      asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
00463                      options |= EREG_ARGS;
00464                      break;
00465               case 'r':                                 /* RSS */
00466                      if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
00467                             asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
00468                             options |= RSS;
00469                             break;
00470                      }
00471                      usage4 (_("RSS must be an integer!"));
00472               case 'z':                                 /* VSZ */
00473                      if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
00474                             asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
00475                             options |= VSZ;
00476                             break;
00477                      }
00478                      usage4 (_("VSZ must be an integer!"));
00479               case 'P':                                 /* PCPU */
00480                      /* TODO: -P 1.5.5 is accepted */
00481                      if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
00482                             asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
00483                             options |= PCPU;
00484                             break;
00485                      }
00486                      usage4 (_("PCPU must be a float!"));
00487               case 'm':
00488                      asprintf (&metric_name, "%s", optarg);
00489                      if ( strcmp(optarg, "PROCS") == 0) {
00490                             metric = METRIC_PROCS;
00491                             break;
00492                      } 
00493                      else if ( strcmp(optarg, "VSZ") == 0) {
00494                             metric = METRIC_VSZ;
00495                             break;
00496                      } 
00497                      else if ( strcmp(optarg, "RSS") == 0 ) {
00498                             metric = METRIC_RSS;
00499                             break;
00500                      }
00501                      else if ( strcmp(optarg, "CPU") == 0 ) {
00502                             metric = METRIC_CPU;
00503                             break;
00504                      }
00505                      else if ( strcmp(optarg, "ELAPSED") == 0) {
00506                             metric = METRIC_ELAPSED;
00507                             break;
00508                      }
00509                             
00510                      usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
00511               case 'v':                                                             /* command */
00512                      verbose++;
00513                      break;
00514               case CHAR_MAX+2:
00515                      input_filename = optarg;
00516                      break;
00517               }
00518        }
00519 
00520        c = optind;
00521        if (wmax == -1 && argv[c])
00522               wmax = atoi (argv[c++]);
00523        if (cmax == -1 && argv[c])
00524               cmax = atoi (argv[c++]);
00525        if (statopts == NULL && argv[c]) {
00526               asprintf (&statopts, "%s", argv[c++]);
00527               asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
00528               options |= STAT;
00529        }
00530 
00531        return validate_arguments ();
00532 }
00533 
00534 
00535 
00536 int
00537 validate_arguments ()
00538 {
00539 
00540        if (wmax >= 0 && wmin == -1)
00541               wmin = 0;
00542        if (cmax >= 0 && cmin == -1)
00543               cmin = 0;
00544        if (wmax >= wmin && cmax >= cmin) {       /* standard ranges */
00545               if (wmax > cmax && cmax != -1) {
00546                      printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
00547                      return ERROR;
00548               }
00549               if (cmin > wmin && wmin != -1) {
00550                      printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
00551                      return ERROR;
00552               }
00553        }
00554 
00555 /*     if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
00556 /*            printf ("At least one threshold must be set\n"); */
00557 /*            return ERROR; */
00558 /*     } */
00559 
00560        if (options == 0)
00561               options = ALL;
00562 
00563        if (statopts==NULL)
00564               statopts = strdup("");
00565 
00566        if (prog==NULL)
00567               prog = strdup("");
00568 
00569        if (args==NULL)
00570               args = strdup("");
00571 
00572        if (fmt==NULL)
00573               fmt = strdup("");
00574 
00575        if (fails==NULL)
00576               fails = strdup("");
00577 
00578        return options;
00579 }
00580 
00581 
00582 
00583 /* Check thresholds against value */
00584 int
00585 check_thresholds (int value)
00586 {
00587        if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
00588               return OK;
00589        }
00590        else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
00591               if (value > cmax && value < cmin)
00592                      return STATE_CRITICAL;
00593        }
00594        else if (cmax >= 0 && value > cmax) {
00595               return STATE_CRITICAL;
00596        }
00597        else if (cmin >= 0 && value < cmin) {
00598               return STATE_CRITICAL;
00599        }
00600 
00601        if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
00602               if (value > wmax && value < wmin) {
00603                      return STATE_WARNING;
00604               }
00605        }
00606        else if (wmax >= 0 && value > wmax) {
00607               return STATE_WARNING;
00608        }
00609        else if (wmin >= 0 && value < wmin) {
00610               return STATE_WARNING;
00611        }
00612        return STATE_OK;
00613 }
00614 
00615 
00616 /* convert the elapsed time to seconds */
00617 int
00618 convert_to_seconds(char *etime) {
00619 
00620        char *ptr;
00621        int total;
00622 
00623        int hyphcnt;
00624        int coloncnt;
00625        int days;
00626        int hours;
00627        int minutes;
00628        int seconds;
00629 
00630        hyphcnt = 0;
00631        coloncnt = 0;
00632        days = 0;
00633        hours = 0;
00634        minutes = 0;
00635        seconds = 0;
00636 
00637        for (ptr = etime; *ptr != '\0'; ptr++) {
00638        
00639               if (*ptr == '-') {
00640                      hyphcnt++;
00641                      continue;
00642               }
00643               if (*ptr == ':') {
00644                      coloncnt++;
00645                      continue;
00646               }
00647        }
00648 
00649        if (hyphcnt > 0) {
00650               sscanf(etime, "%d-%d:%d:%d",
00651                             &days, &hours, &minutes, &seconds);
00652               /* linux 2.6.5/2.6.6 reporting some processes with infinite
00653                * elapsed times for some reason */
00654               if (days == 49710) {
00655                      return 0;
00656               }
00657        } else {
00658               if (coloncnt == 2) {
00659                      sscanf(etime, "%d:%d:%d",
00660                             &hours, &minutes, &seconds);
00661               } else if (coloncnt == 1) {
00662                      sscanf(etime, "%d:%d",
00663                             &minutes, &seconds);
00664               }
00665        }
00666 
00667        total = (days * 86400) +
00668               (hours * 3600) +
00669               (minutes * 60) +
00670               seconds;
00671 
00672        if (verbose >= 3 && metric == METRIC_ELAPSED) {
00673                      printf("seconds: %d\n", total);
00674        }
00675        return total;
00676 }
00677 
00678 
00679 void
00680 print_help (void)
00681 {
00682        print_revision (progname, NP_VERSION);
00683 
00684        printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
00685        printf (COPYRIGHT, copyright, email);
00686 
00687        printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
00688   printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
00689   printf ("%s\n", _("of processes.  Search filters can be applied to limit the processes to check."));
00690 
00691   printf ("\n\n");
00692 
00693        print_usage ();
00694 
00695   printf (UT_HELP_VRSN);
00696   printf (UT_EXTRA_OPTS);
00697   printf (" %s\n", "-w, --warning=RANGE");
00698   printf ("   %s\n", _("Generate warning state if metric is outside this range"));
00699   printf (" %s\n", "-c, --critical=RANGE");
00700   printf ("   %s\n", _("Generate critical state if metric is outside this range"));
00701   printf (" %s\n", "-m, --metric=TYPE");
00702   printf ("  %s\n", _("Check thresholds against metric. Valid types:"));
00703   printf ("  %s\n", _("PROCS   - number of processes (default)"));
00704   printf ("  %s\n", _("VSZ     - virtual memory size"));
00705   printf ("  %s\n", _("RSS     - resident set memory size"));
00706   printf ("  %s\n", _("CPU     - percentage CPU"));
00707 /* only linux etime is support currently */
00708 #if defined( __linux__ )
00709        printf ("  %s\n", _("ELAPSED - time elapsed in seconds"));
00710 #endif /* defined(__linux__) */
00711        printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
00712 
00713        printf (" %s\n", "-v, --verbose");
00714   printf ("    %s\n", _("Extra information. Up to 3 verbosity levels"));
00715 
00716   printf ("\n");
00717        printf ("%s\n", "Filters:");
00718   printf (" %s\n", "-s, --state=STATUSFLAGS");
00719   printf ("   %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
00720   printf ("   %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
00721   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
00722   printf (" %s\n", "-p, --ppid=PPID");
00723   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
00724   printf (" %s\n", "-z, --vsz=VSZ");
00725   printf ("   %s\n", _("Only scan for processes with VSZ higher than indicated."));
00726   printf (" %s\n", "-r, --rss=RSS");
00727   printf ("   %s\n", _("Only scan for processes with RSS higher than indicated."));
00728        printf (" %s\n", "-P, --pcpu=PCPU");
00729   printf ("   %s\n", _("Only scan for processes with PCPU higher than indicated."));
00730   printf (" %s\n", "-u, --user=USER");
00731   printf ("   %s\n", _("Only scan for processes with user name or ID indicated."));
00732   printf (" %s\n", "-a, --argument-array=STRING");
00733   printf ("   %s\n", _("Only scan for processes with args that contain STRING."));
00734   printf (" %s\n", "--ereg-argument-array=STRING");
00735   printf ("   %s\n", _("Only scan for processes with args that contain the regex STRING."));
00736   printf (" %s\n", "-C, --command=COMMAND");
00737   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
00738 
00739        printf(_("\n\
00740 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
00741 specified 'max:min', a warning status will be generated if the\n\
00742 count is inside the specified range\n\n"));
00743 
00744        printf(_("\
00745 This plugin checks the number of currently running processes and\n\
00746 generates WARNING or CRITICAL states if the process count is outside\n\
00747 the specified threshold ranges. The process count can be filtered by\n\
00748 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
00749 be the total number of running processes\n\n"));
00750 
00751        printf ("%s\n", _("Examples:"));
00752   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
00753   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
00754   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
00755   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
00756   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
00757   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
00758   printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
00759   printf ("  %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
00760   printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
00761   printf ("  %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
00762 
00763        printf (UT_SUPPORT);
00764 }
00765 
00766 void
00767 print_usage (void)
00768 {
00769   printf ("%s\n", _("Usage:"));
00770        printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
00771   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
00772   printf (" [-C command] [-t timeout] [-v]\n");
00773 }