Code

Fixed segfault in argument processing. Thanks to Christoph Schell (#1742066)
[nagiosplug.git] / plugins / check_procs.c
1 /******************************************************************************
2 *
3 * Nagios check_procs plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_procs plugin
13 *
14 *  Checks all processes and generates WARNING or CRITICAL states if the specified
15 *  metric is outside the required threshold ranges. The metric defaults to number
16 *  of processes.  Search filters can be applied to limit the processes to check.
17 *
18 * License Information:
19 *
20 * This program is free software; you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation; either version 2 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program; if not, write to the Free Software
32 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
33 *
34 * $Id$
35
36 ******************************************************************************/
38 const char *progname = "check_procs";
39 const char *program_name = "check_procs";  /* Required for coreutils libs */
40 const char *revision = "$Revision$";
41 const char *copyright = "2000-2006";
42 const char *email = "nagiosplug-devel@lists.sourceforge.net";
44 #include "common.h"
45 #include "popen.h"
46 #include "utils.h"
48 #include <pwd.h>
50 int process_arguments (int, char **);
51 int validate_arguments (void);
52 int check_thresholds (int);
53 int convert_to_seconds (char *); 
54 void print_help (void);
55 void print_usage (void);
57 int wmax = -1;
58 int cmax = -1;
59 int wmin = -1;
60 int cmin = -1;
62 int options = 0; /* bitmask of filter criteria to test against */
63 #define ALL 1
64 #define STAT 2
65 #define PPID 4
66 #define USER 8
67 #define PROG 16
68 #define ARGS 32
69 #define VSZ  64
70 #define RSS  128
71 #define PCPU 256
72 #define ELAPSED 512
73 /* Different metrics */
74 char *metric_name;
75 enum metric {
76         METRIC_PROCS,
77         METRIC_VSZ,
78         METRIC_RSS,
79         METRIC_CPU,
80         METRIC_ELAPSED
81 };
82 enum metric metric = METRIC_PROCS;
84 int verbose = 0;
85 int uid;
86 pid_t ppid;
87 int vsz;
88 int rss;
89 float pcpu;
90 char *statopts;
91 char *prog;
92 char *args;
93 char *fmt;
94 char *fails;
95 char tmp[MAX_INPUT_BUFFER];
99 int
100 main (int argc, char **argv)
102         char *input_buffer;
103         char *input_line;
104         char *procprog;
106         pid_t mypid = 0;
107         int procuid = 0;
108         pid_t procpid = 0;
109         pid_t procppid = 0;
110         int procvsz = 0;
111         int procrss = 0;
112         int procseconds = 0;
113         float procpcpu = 0;
114         char procstat[8];
115         char procetime[MAX_INPUT_BUFFER] = { '\0' };
116         char *procargs;
118         const char *zombie = "Z";
120         int resultsum = 0; /* bitmask of the filter criteria met by a process */
121         int found = 0; /* counter for number of lines returned in `ps` output */
122         int procs = 0; /* counter for number of processes meeting filter criteria */
123         int pos; /* number of spaces before 'args' in `ps` output */
124         int cols; /* number of columns in ps output */
125         int expected_cols = PS_COLS - 1;
126         int warn = 0; /* number of processes in warn state */
127         int crit = 0; /* number of processes in crit state */
128         int i = 0;
129         int result = STATE_UNKNOWN;
131         setlocale (LC_ALL, "");
132         bindtextdomain (PACKAGE, LOCALEDIR);
133         textdomain (PACKAGE);
134         setlocale(LC_NUMERIC, "POSIX");
136         input_buffer = malloc (MAX_INPUT_BUFFER);
137         procprog = malloc (MAX_INPUT_BUFFER);
139         asprintf (&metric_name, "PROCS");
140         metric = METRIC_PROCS;
142         if (process_arguments (argc, argv) == ERROR)
143                 usage4 (_("Could not parse arguments"));
145         /* get our pid */
146         mypid = getpid();
148         /* Set signal handling and alarm timeout */
149         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
150                 usage4 (_("Cannot catch SIGALRM"));
151         }
152         alarm (timeout_interval);
154         if (verbose >= 2)
155                 printf (_("CMD: %s\n"), PS_COMMAND);
157         child_process = spopen (PS_COMMAND);
158         if (child_process == NULL) {
159                 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
160                 return STATE_UNKNOWN;
161         }
163         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
164         if (child_stderr == NULL)
165                 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
167         /* flush first line */
168         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
169         while ( input_buffer[strlen(input_buffer)-1] != '\n' )
170                 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
172         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
173                 asprintf (&input_line, "%s", input_buffer);
174                 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
175                         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
176                         asprintf (&input_line, "%s%s", input_line, input_buffer);
177                 }
179                 if (verbose >= 3)
180                         printf ("%s", input_line);
182                 strcpy (procprog, "");
183                 asprintf (&procargs, "%s", "");
185                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
187                 /* Zombie processes do not give a procprog command */
188                 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
189                         cols = expected_cols;
190                 }
191                 if ( cols >= expected_cols ) {
192                         resultsum = 0;
193                         asprintf (&procargs, "%s", input_line + pos);
194                         strip (procargs);
196                         /* Some ps return full pathname for command. This removes path */
197                         strcpy(procprog, base_name(procprog));
199                         /* we need to convert the elapsed time to seconds */
200                         procseconds = convert_to_seconds(procetime);
202                         if (verbose >= 3)
203                                 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
204                                         procs, procuid, procvsz, procrss,
205                                         procpid, procppid, procpcpu, procstat, 
206                                         procetime, procprog, procargs);
208                         /* Ignore self */
209                         if (mypid == procpid) continue;
211                         if ((options & STAT) && (strstr (statopts, procstat)))
212                                 resultsum |= STAT;
213                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
214                                 resultsum |= ARGS;
215                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
216                                 resultsum |= PROG;
217                         if ((options & PPID) && (procppid == ppid))
218                                 resultsum |= PPID;
219                         if ((options & USER) && (procuid == uid))
220                                 resultsum |= USER;
221                         if ((options & VSZ)  && (procvsz >= vsz))
222                                 resultsum |= VSZ;
223                         if ((options & RSS)  && (procrss >= rss))
224                                 resultsum |= RSS;
225                         if ((options & PCPU)  && (procpcpu >= pcpu))
226                                 resultsum |= PCPU;
228                         found++;
230                         /* Next line if filters not matched */
231                         if (!(options == resultsum || options == ALL))
232                                 continue;
234                         procs++;
236                         if (metric == METRIC_VSZ)
237                                 i = check_thresholds (procvsz);
238                         else if (metric == METRIC_RSS)
239                                 i = check_thresholds (procrss);
240                         /* TODO? float thresholds for --metric=CPU */
241                         else if (metric == METRIC_CPU)
242                                 i = check_thresholds ((int)procpcpu); 
243                         else if (metric == METRIC_ELAPSED)
244                                 i = check_thresholds (procseconds);
246                         if (metric != METRIC_PROCS) {
247                                 if (i == STATE_WARNING) {
248                                         warn++;
249                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
250                                         result = max_state (result, i);
251                                 }
252                                 if (i == STATE_CRITICAL) {
253                                         crit++;
254                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
255                                         result = max_state (result, i);
256                                 }
257                         }
258                 } 
259                 /* This should not happen */
260                 else if (verbose) {
261                         printf(_("Not parseable: %s"), input_buffer);
262                 }
263         }
265         /* If we get anything on STDERR, at least set warning */
266         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
267                 if (verbose)
268                         printf ("STDERR: %s", input_buffer);
269                 result = max_state (result, STATE_WARNING);
270                 printf (_("System call sent warnings to stderr\n"));
271         }
272         
273         (void) fclose (child_stderr);
275         /* close the pipe */
276         if (spclose (child_process)) {
277                 printf (_("System call returned nonzero status\n"));
278                 result = max_state (result, STATE_WARNING);
279         }
281         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
282                 printf (_("Unable to read output\n"));
283                 return result;
284         }
286         if ( result == STATE_UNKNOWN ) 
287                 result = STATE_OK;
289         /* Needed if procs found, but none match filter */
290         if ( metric == METRIC_PROCS ) {
291                 result = max_state (result, check_thresholds (procs) );
292         }
294         if ( result == STATE_OK ) {
295                 printf ("%s %s: ", metric_name, _("OK"));
296         } else if (result == STATE_WARNING) {
297                 printf ("%s %s: ", metric_name, _("WARNING"));
298                 if ( metric != METRIC_PROCS ) {
299                         printf (_("%d warn out of "), warn);
300                 }
301         } else if (result == STATE_CRITICAL) {
302                 printf ("%s %s: ", metric_name, _("CRITICAL"));
303                 if (metric != METRIC_PROCS) {
304                         printf (_("%d crit, %d warn out of "), crit, warn);
305                 }
306         } 
307         printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
308         
309         if (strcmp(fmt,"") != 0) {
310                 printf (_(" with %s"), fmt);
311         }
313         if ( verbose >= 1 && strcmp(fails,"") )
314                 printf (" [%s]", fails);
316         printf ("\n");
317         return result;
322 /* process command-line arguments */
323 int
324 process_arguments (int argc, char **argv)
326         int c = 1;
327         char *user;
328         struct passwd *pw;
329         int option = 0;
330         static struct option longopts[] = {
331                 {"warning", required_argument, 0, 'w'},
332                 {"critical", required_argument, 0, 'c'},
333                 {"metric", required_argument, 0, 'm'},
334                 {"timeout", required_argument, 0, 't'},
335                 {"status", required_argument, 0, 's'},
336                 {"ppid", required_argument, 0, 'p'},
337                 {"command", required_argument, 0, 'C'},
338                 {"vsz", required_argument, 0, 'z'},
339                 {"rss", required_argument, 0, 'r'},
340                 {"pcpu", required_argument, 0, 'P'},
341                 {"elapsed", required_argument, 0, 'e'},
342                 {"argument-array", required_argument, 0, 'a'},
343                 {"help", no_argument, 0, 'h'},
344                 {"version", no_argument, 0, 'V'},
345                 {"verbose", no_argument, 0, 'v'},
346                 {0, 0, 0, 0}
347         };
349         for (c = 1; c < argc; c++)
350                 if (strcmp ("-to", argv[c]) == 0)
351                         strcpy (argv[c], "-t");
353         while (1) {
354                 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", 
355                         longopts, &option);
357                 if (c == -1 || c == EOF)
358                         break;
360                 switch (c) {
361                 case '?':                                                                       /* help */
362                         usage5 ();
363                 case 'h':                                                                       /* help */
364                         print_help ();
365                         exit (STATE_OK);
366                 case 'V':                                                                       /* version */
367                         print_revision (progname, revision);
368                         exit (STATE_OK);
369                 case 't':                                                                       /* timeout period */
370                         if (!is_integer (optarg))
371                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
372                         else
373                                 timeout_interval = atoi (optarg);
374                         break;
375                 case 'c':                                                                       /* critical threshold */
376                         if (is_integer (optarg))
377                                 cmax = atoi (optarg);
378                         else if (sscanf (optarg, ":%d", &cmax) == 1)
379                                 break;
380                         else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
381                                 break;
382                         else if (sscanf (optarg, "%d:", &cmin) == 1)
383                                 break;
384                         else
385                                 usage4 (_("Critical Process Count must be an integer!"));
386                         break;                                                   
387                 case 'w':                                                                       /* warning threshold */
388                         if (is_integer (optarg))
389                                 wmax = atoi (optarg);
390                         else if (sscanf (optarg, ":%d", &wmax) == 1)
391                                 break;
392                         else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
393                                 break;
394                         else if (sscanf (optarg, "%d:", &wmin) == 1)
395                                 break;
396                         else
397                                 usage4 (_("Warning Process Count must be an integer!"));
398                         break;
399                 case 'p':                                                                       /* process id */
400                         if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
401                                 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
402                                 options |= PPID;
403                                 break;
404                         }
405                         usage4 (_("Parent Process ID must be an integer!"));
406                 case 's':                                                                       /* status */
407                         if (statopts)
408                                 break;
409                         else
410                                 statopts = optarg;
411                         asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
412                         options |= STAT;
413                         break;
414                 case 'u':                                                                       /* user or user id */
415                         if (is_integer (optarg)) {
416                                 uid = atoi (optarg);
417                                 pw = getpwuid ((uid_t) uid);
418                                 /*  check to be sure user exists */
419                                 if (pw == NULL)
420                                         usage2 (_("UID %s was not found"), optarg);
421                         }
422                         else {
423                                 pw = getpwnam (optarg);
424                                 /*  check to be sure user exists */
425                                 if (pw == NULL)
426                                         usage2 (_("User name %s was not found"), optarg);
427                                 /*  then get uid */
428                                 uid = pw->pw_uid;
429                         }
430                         user = pw->pw_name;
431                         asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
432                                   uid, user);
433                         options |= USER;
434                         break;
435                 case 'C':                                                                       /* command */
436                         /* TODO: allow this to be passed in with --metric */
437                         if (prog)
438                                 break;
439                         else
440                                 prog = optarg;
441                         asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
442                                   prog);
443                         options |= PROG;
444                         break;
445                 case 'a':                                                                       /* args (full path name with args) */
446                         /* TODO: allow this to be passed in with --metric */
447                         if (args)
448                                 break;
449                         else
450                                 args = optarg;
451                         asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
452                         options |= ARGS;
453                         break;
454                 case 'r':                                       /* RSS */
455                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
456                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
457                                 options |= RSS;
458                                 break;
459                         }
460                         usage4 (_("RSS must be an integer!"));
461                 case 'z':                                       /* VSZ */
462                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
463                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
464                                 options |= VSZ;
465                                 break;
466                         }
467                         usage4 (_("VSZ must be an integer!"));
468                 case 'P':                                       /* PCPU */
469                         /* TODO: -P 1.5.5 is accepted */
470                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
471                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
472                                 options |= PCPU;
473                                 break;
474                         }
475                         usage4 (_("PCPU must be a float!"));
476                 case 'm':
477                         asprintf (&metric_name, "%s", optarg);
478                         if ( strcmp(optarg, "PROCS") == 0) {
479                                 metric = METRIC_PROCS;
480                                 break;
481                         } 
482                         else if ( strcmp(optarg, "VSZ") == 0) {
483                                 metric = METRIC_VSZ;
484                                 break;
485                         } 
486                         else if ( strcmp(optarg, "RSS") == 0 ) {
487                                 metric = METRIC_RSS;
488                                 break;
489                         }
490                         else if ( strcmp(optarg, "CPU") == 0 ) {
491                                 metric = METRIC_CPU;
492                                 break;
493                         }
494                         else if ( strcmp(optarg, "ELAPSED") == 0) {
495                                 metric = METRIC_ELAPSED;
496                                 break;
497                         }
498                                 
499                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
500                 case 'v':                                                                       /* command */
501                         verbose++;
502                         break;
503                 }
504         }
506         c = optind;
507         if (wmax == -1 && argv[c])
508                 wmax = atoi (argv[c++]);
509         if (cmax == -1 && argv[c])
510                 cmax = atoi (argv[c++]);
511         if (statopts == NULL && argv[c]) {
512                 asprintf (&statopts, "%s", argv[c++]);
513                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
514                 options |= STAT;
515         }
517         return validate_arguments ();
522 int
523 validate_arguments ()
526         if (wmax >= 0 && wmin == -1)
527                 wmin = 0;
528         if (cmax >= 0 && cmin == -1)
529                 cmin = 0;
530         if (wmax >= wmin && cmax >= cmin) {     /* standard ranges */
531                 if (wmax > cmax && cmax != -1) {
532                         printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
533                         return ERROR;
534                 }
535                 if (cmin > wmin && wmin != -1) {
536                         printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
537                         return ERROR;
538                 }
539         }
541 /*      if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
542 /*              printf ("At least one threshold must be set\n"); */
543 /*              return ERROR; */
544 /*      } */
546         if (options == 0)
547                 options = ALL;
549         if (statopts==NULL)
550                 statopts = strdup("");
552         if (prog==NULL)
553                 prog = strdup("");
555         if (args==NULL)
556                 args = strdup("");
558         if (fmt==NULL)
559                 fmt = strdup("");
561         if (fails==NULL)
562                 fails = strdup("");
564         return options;
569 /* Check thresholds against value */
570 int
571 check_thresholds (int value)
573         if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
574                 return OK;
575         }
576         else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
577                 if (value > cmax && value < cmin)
578                         return STATE_CRITICAL;
579         }
580         else if (cmax >= 0 && value > cmax) {
581                 return STATE_CRITICAL;
582         }
583         else if (cmin >= 0 && value < cmin) {
584                 return STATE_CRITICAL;
585         }
587         if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
588                 if (value > wmax && value < wmin) {
589                         return STATE_WARNING;
590                 }
591         }
592         else if (wmax >= 0 && value > wmax) {
593                 return STATE_WARNING;
594         }
595         else if (wmin >= 0 && value < wmin) {
596                 return STATE_WARNING;
597         }
598         return STATE_OK;
602 /* convert the elapsed time to seconds */
603 int
604 convert_to_seconds(char *etime) {
606         char *ptr;
607         int total;
609         int hyphcnt;
610         int coloncnt;
611         int days;
612         int hours;
613         int minutes;
614         int seconds;
616         hyphcnt = 0;
617         coloncnt = 0;
618         days = 0;
619         hours = 0;
620         minutes = 0;
621         seconds = 0;
623         for (ptr = etime; *ptr != '\0'; ptr++) {
624         
625                 if (*ptr == '-') {
626                         hyphcnt++;
627                         continue;
628                 }
629                 if (*ptr == ':') {
630                         coloncnt++;
631                         continue;
632                 }
633         }
635         if (hyphcnt > 0) {
636                 sscanf(etime, "%d-%d:%d:%d",
637                                 &days, &hours, &minutes, &seconds);
638                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
639                  * elapsed times for some reason */
640                 if (days == 49710) {
641                         return 0;
642                 }
643         } else {
644                 if (coloncnt == 2) {
645                         sscanf(etime, "%d:%d:%d",
646                                 &hours, &minutes, &seconds);
647                 } else if (coloncnt == 1) {
648                         sscanf(etime, "%d:%d",
649                                 &minutes, &seconds);
650                 }
651         }
653         total = (days * 86400) +
654                 (hours * 3600) +
655                 (minutes * 60) +
656                 seconds;
658         if (verbose >= 3 && metric == METRIC_ELAPSED) {
659                         printf("seconds: %d\n", total);
660         }
661         return total;
665 void
666 print_help (void)
668         print_revision (progname, revision);
670         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
671         printf (COPYRIGHT, copyright, email);
673         printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
674   printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
675   printf ("%s\n", _("of processes.  Search filters can be applied to limit the processes to check."));
677   printf ("\n\n");
678   
679         print_usage ();
681         printf ("%s\n", _("Required Arguments:"));
682   printf (" %s\n", "-w, --warning=RANGE");
683   printf ("   %s\n", _("Generate warning state if metric is outside this range"));
684   printf (" %s\n", "-c, --critical=RANGE");
685   printf ("   %s\n", _("Generate critical state if metric is outside this range"));
687         printf ("%s\n", _("Optional Arguments:"));
688   printf (" %s\n", "-m, --metric=TYPE");
689   printf ("  %s\n", _("Check thresholds against metric. Valid types:"));
690   printf ("  %s\n", _("PROCS   - number of processes (default)"));
691   printf ("  %s\n", _("VSZ     - virtual memory size"));
692   printf ("  %s\n", _("RSS     - resident set memory size"));
693   printf ("  %s\n", _("CPU     - percentage cpu"));
694 /* only linux etime is support currently */
695 #if defined( __linux__ )
696         printf ("  %s\n", _("ELAPSED - time elapsed in seconds"));
697 #endif /* defined(__linux__) */
698         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
700         printf (" %s\n", "-v, --verbose");
701   printf ("    %s\n", _("Extra information. Up to 3 verbosity levels"));
703         printf ("%s\n", "Optional Filters:");
704   printf (" %s\n", "-s, --state=STATUSFLAGS");
705   printf ("   %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
706   printf ("   %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
707   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
708   printf (" %s\n", "-p, --ppid=PPID");
709   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
710   printf (" %s\n", "-z, --vsz=VSZ");
711   printf ("   %s\n", _("Only scan for processes with vsz higher than indicated."));
712   printf (" %s\n", "-r, --rss=RSS");
713   printf ("   %s\n", _("Only scan for processes with rss higher than indicated."));
714         printf (" %s\n", "-P, --pcpu=PCPU");
715   printf ("   %s\n", _("Only scan for processes with pcpu higher than indicated."));
716   printf (" %s\n", "-u, --user=USER");
717   printf ("   %s\n", _("Only scan for processes with user name or ID indicated."));
718   printf (" %s\n", "-a, --argument-array=STRING");
719   printf ("   %s\n", _("Only scan for processes with args that contain STRING."));
720   printf (" %s\n", "-C, --command=COMMAND");
721   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
723         printf(_("\n\
724 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
725 specified 'max:min', a warning status will be generated if the\n\
726 count is inside the specified range\n\n"));
728         printf(_("\
729 This plugin checks the number of currently running processes and\n\
730 generates WARNING or CRITICAL states if the process count is outside\n\
731 the specified threshold ranges. The process count can be filtered by\n\
732 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
733 be the total number of running processes\n\n"));
735         printf ("%s\n", _("Examples:"));
736   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
737   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
738   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
739   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
740   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
741   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
742   printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
743   printf ("  %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
744   printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
745   printf ("  %s\n\n", _("Alert if cpu of any processes over 10%% or 20%%"));
747         printf (_(UT_SUPPORT));
750 void
751 print_usage (void)
753   printf (_("Usage:"));
754         printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
755   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
756   printf (" [-C command] [-t timeout] [-v]\n");