summaryrefslogtreecommitdiffstats
path: root/plugins
diff options
context:
space:
mode:
Diffstat (limited to 'plugins')
-rw-r--r--plugins/Makefile.am1
-rw-r--r--plugins/check_fping.c114
-rw-r--r--plugins/check_fping.d/config.h24
-rw-r--r--plugins/check_procs.c1135
-rw-r--r--plugins/check_procs.d/config.h75
-rw-r--r--plugins/utils.h2
6 files changed, 750 insertions, 601 deletions
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 04fb7ed2..20a62fb2 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -72,6 +72,7 @@ EXTRA_DIST = t \
72 check_ntp_peer.d \ 72 check_ntp_peer.d \
73 check_apt.d \ 73 check_apt.d \
74 check_pgsql.d \ 74 check_pgsql.d \
75 check_procs.d \
75 check_ping.d \ 76 check_ping.d \
76 check_by_ssh.d \ 77 check_by_ssh.d \
77 check_smtp.d \ 78 check_smtp.d \
diff --git a/plugins/check_fping.c b/plugins/check_fping.c
index ec7abb67..8018e06d 100644
--- a/plugins/check_fping.c
+++ b/plugins/check_fping.c
@@ -79,6 +79,24 @@ int main(int argc, char **argv) {
79 server = strscpy(server, config.server_name); 79 server = strscpy(server, config.server_name);
80 80
81 char *option_string = ""; 81 char *option_string = "";
82 char *fping_prog = NULL;
83
84 /* First determine if the target is dualstack or ipv6 only. */
85 bool server_is_inet6_addr = is_inet6_addr(server);
86
87 /*
88 * If the user requested -6 OR the user made no assertion and the address is v6 or dualstack
89 * -> we use ipv6
90 * If the user requested -4 OR the user made no assertion and the address is v4 ONLY
91 * -> we use ipv4
92 */
93 if (address_family == AF_INET6 || (address_family == AF_UNSPEC && server_is_inet6_addr)) {
94 xasprintf(&option_string, "%s-6 ", option_string);
95 } else {
96 xasprintf(&option_string, "%s-4 ", option_string);
97 }
98 fping_prog = strdup(PATH_TO_FPING);
99
82 /* compose the command */ 100 /* compose the command */
83 if (config.target_timeout) { 101 if (config.target_timeout) {
84 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout); 102 xasprintf(&option_string, "%s-t %d ", option_string, config.target_timeout);
@@ -99,19 +117,26 @@ int main(int argc, char **argv) {
99 xasprintf(&option_string, "%s-R ", option_string); 117 xasprintf(&option_string, "%s-R ", option_string);
100 } 118 }
101 119
102 char *fping_prog = NULL; 120 if (config.fwmark_set) {
103#ifdef PATH_TO_FPING6 121 xasprintf(&option_string, "%s--fwmark %u ", option_string, config.fwmark);
104 if (address_family != AF_INET && is_inet6_addr(server)) { 122 }
105 fping_prog = strdup(PATH_TO_FPING6); 123
106 } else { 124 if (config.icmp_timestamp) {
107 fping_prog = strdup(PATH_TO_FPING); 125 xasprintf(&option_string, "%s--icmp-timestamp ", option_string);
126 }
127
128 if (config.check_source) {
129 xasprintf(&option_string, "%s--check-source ", option_string);
108 } 130 }
109#else
110 fping_prog = strdup(PATH_TO_FPING);
111#endif
112 131
113 char *command_line = NULL; 132 char *command_line = NULL;
114 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server); 133
134 if (config.icmp_timestamp) {
135 // no packet size settable for ICMP timestamp
136 xasprintf(&command_line, "%s %s -c %d %s", fping_prog, option_string, config.packet_count, server);
137 } else {
138 xasprintf(&command_line, "%s %s-b %d -c %d %s", fping_prog, option_string, config.packet_size, config.packet_count, server);
139 }
115 140
116 if (verbose) { 141 if (verbose) {
117 printf("%s\n", command_line); 142 printf("%s\n", command_line);
@@ -268,13 +293,38 @@ mp_state_enum textscan(char *buf, const char *server_name, bool crta_p, double c
268 293
269/* process command-line arguments */ 294/* process command-line arguments */
270check_fping_config_wrapper process_arguments(int argc, char **argv) { 295check_fping_config_wrapper process_arguments(int argc, char **argv) {
271 static struct option longopts[] = { 296 enum {
272 {"hostname", required_argument, 0, 'H'}, {"sourceip", required_argument, 0, 'S'}, {"sourceif", required_argument, 0, 'I'}, 297 FWMARK_OPT = CHAR_MAX + 1,
273 {"critical", required_argument, 0, 'c'}, {"warning", required_argument, 0, 'w'}, {"alive", no_argument, 0, 'a'}, 298 ICMP_TIMESTAMP_OPT,
274 {"bytes", required_argument, 0, 'b'}, {"number", required_argument, 0, 'n'}, {"target-timeout", required_argument, 0, 'T'}, 299 CHECK_SOURCE_OPT,
275 {"interval", required_argument, 0, 'i'}, {"verbose", no_argument, 0, 'v'}, {"version", no_argument, 0, 'V'}, 300 };
276 {"help", no_argument, 0, 'h'}, {"use-ipv4", no_argument, 0, '4'}, {"use-ipv6", no_argument, 0, '6'}, 301 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
277 {"dontfrag", no_argument, 0, 'M'}, {"random", no_argument, 0, 'R'}, {0, 0, 0, 0}}; 302 {"sourceip", required_argument, 0, 'S'},
303 {"sourceif", required_argument, 0, 'I'},
304 {"critical", required_argument, 0, 'c'},
305 {"warning", required_argument, 0, 'w'},
306 {"alive", no_argument, 0, 'a'},
307 {"bytes", required_argument, 0, 'b'},
308 {"number", required_argument, 0, 'n'},
309 {"target-timeout", required_argument, 0, 'T'},
310 {"interval", required_argument, 0, 'i'},
311 {"verbose", no_argument, 0, 'v'},
312 {"version", no_argument, 0, 'V'},
313 {"help", no_argument, 0, 'h'},
314 {"use-ipv4", no_argument, 0, '4'},
315 {"use-ipv6", no_argument, 0, '6'},
316 {"dontfrag", no_argument, 0, 'M'},
317 {"random", no_argument, 0, 'R'},
318#ifdef FPING_VERSION_5_2_OR_HIGHER
319 // only available with fping version >= 5.2
320 {"fwmark", required_argument, NULL, FWMARK_OPT},
321# ifdef FPING_VERSION_5_3_OR_HIGHER
322 // only available with fping version >= 5.3
323 {"icmp-timestamp", no_argument, NULL, ICMP_TIMESTAMP_OPT},
324 {"check-source", no_argument, NULL, CHECK_SOURCE_OPT},
325# endif
326#endif
327 {0, 0, 0, 0}};
278 328
279 char *rv[2]; 329 char *rv[2];
280 rv[PL] = NULL; 330 rv[PL] = NULL;
@@ -299,7 +349,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
299 argc--; 349 argc--;
300 } 350 }
301 351
302 while (1) { 352 while (true) {
303 int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option); 353 int option_index = getopt_long(argc, argv, "+hVvaH:S:c:w:b:n:T:i:I:M:R:46", longopts, &option);
304 354
305 if (option_index == -1 || option_index == EOF || option_index == 1) { 355 if (option_index == -1 || option_index == EOF || option_index == 1) {
@@ -340,11 +390,7 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
340 address_family = AF_INET; 390 address_family = AF_INET;
341 break; 391 break;
342 case '6': /* IPv6 only */ 392 case '6': /* IPv6 only */
343#ifdef USE_IPV6
344 address_family = AF_INET6; 393 address_family = AF_INET6;
345#else
346 usage(_("IPv6 support not available\n"));
347#endif
348 break; 394 break;
349 case 'c': 395 case 'c':
350 get_threshold(optarg, rv); 396 get_threshold(optarg, rv);
@@ -406,6 +452,20 @@ check_fping_config_wrapper process_arguments(int argc, char **argv) {
406 case 'M': 452 case 'M':
407 result.config.dontfrag = true; 453 result.config.dontfrag = true;
408 break; 454 break;
455 case FWMARK_OPT:
456 if (is_intpos(optarg)) {
457 result.config.fwmark = (unsigned int)atol(optarg);
458 result.config.fwmark_set = true;
459 } else {
460 usage(_("fwmark must be a positive integer"));
461 }
462 break;
463 case ICMP_TIMESTAMP_OPT:
464 result.config.icmp_timestamp = true;
465 break;
466 case CHECK_SOURCE_OPT:
467 result.config.check_source = true;
468 break;
409 } 469 }
410 } 470 }
411 471
@@ -493,6 +553,16 @@ void print_help(void) {
493 printf(" %s\n", _("set the Don't Fragment flag")); 553 printf(" %s\n", _("set the Don't Fragment flag"));
494 printf(" %s\n", "-R, --random"); 554 printf(" %s\n", "-R, --random");
495 printf(" %s\n", _("random packet data (to foil link data compression)")); 555 printf(" %s\n", _("random packet data (to foil link data compression)"));
556#ifdef FPING_VERSION_5_2_OR_HIGHER
557 printf(" %s\n", "--fwmark=INTEGER");
558 printf(" %s\n", _("set the routing mark to INTEGER (fping option)"));
559# ifdef FPING_VERSION_5_3_OR_HIGHER
560 printf(" %s\n", "--icmp-timestamp");
561 printf(" %s\n", _("use ICMP Timestamp instead of ICMP Echo (fping option)"));
562 printf(" %s\n", "--check-source");
563 printf(" %s\n", _("discard replies not from target address (fping option)"));
564# endif
565#endif
496 printf(UT_VERBOSE); 566 printf(UT_VERBOSE);
497 printf("\n"); 567 printf("\n");
498 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)")); 568 printf(" %s\n", _("THRESHOLD is <rta>,<pl>%% where <rta> is the round trip average travel time (ms)"));
diff --git a/plugins/check_fping.d/config.h b/plugins/check_fping.d/config.h
index a0697bf3..d95e9ded 100644
--- a/plugins/check_fping.d/config.h
+++ b/plugins/check_fping.d/config.h
@@ -29,6 +29,21 @@ typedef struct {
29 bool cpl_p; 29 bool cpl_p;
30 int wpl; 30 int wpl;
31 bool wpl_p; 31 bool wpl_p;
32
33 // only available with fping version >= 5.2
34 // for a given uint _fwmark_ fping sets _fwmark_ as a firewall mark
35 // in the packets
36 unsigned int fwmark;
37 bool fwmark_set;
38
39
40 // only available with fping version >= 5.3
41 // Setting icmp_timestamp tells fping to use ICMP Timestamp (ICMP type 13) instead
42 // of ICMP Echo
43 bool icmp_timestamp;
44
45 // Setting check_source lets fping discard replies which are not from the target address
46 bool check_source;
32} check_fping_config; 47} check_fping_config;
33 48
34check_fping_config check_fping_config_init() { 49check_fping_config check_fping_config_init() {
@@ -53,6 +68,15 @@ check_fping_config check_fping_config_init() {
53 .cpl_p = false, 68 .cpl_p = false,
54 .wpl = 0, 69 .wpl = 0,
55 .wpl_p = false, 70 .wpl_p = false,
71
72 // only available with fping version >= 5.2
73 .fwmark = 0,
74 .fwmark_set = false, // just to be deterministic
75
76 // only available with fping version >= 5.3
77 .icmp_timestamp = false,
78 .check_source = false,
79
56 }; 80 };
57 return tmp; 81 return tmp;
58} 82}
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 1d78ccee..83e6864e 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -1,41 +1,41 @@
1/***************************************************************************** 1/*****************************************************************************
2* 2 *
3* Monitoring check_procs plugin 3 * Monitoring check_procs plugin
4* 4 *
5* License: GPL 5 * License: GPL
6* Copyright (c) 2000-2024 Monitoring Plugins Development Team 6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
7* 7 *
8* Description: 8 * Description:
9* 9 *
10* This file contains the check_procs plugin 10 * This file contains the check_procs plugin
11* 11 *
12* Checks all processes and generates WARNING or CRITICAL states if the 12 * Checks all processes and generates WARNING or CRITICAL states if the
13* specified metric is outside the required threshold ranges. The metric 13 * specified metric is outside the required threshold ranges. The metric
14* defaults to number of processes. Search filters can be applied to limit 14 * defaults to number of processes. Search filters can be applied to limit
15* the processes to check. 15 * the processes to check.
16* 16 *
17* The parent process, check_procs itself and any child process of 17 * The parent process, check_procs itself and any child process of
18* check_procs (ps) are excluded from any checks to prevent false positives. 18 * check_procs (ps) are excluded from any checks to prevent false positives.
19* 19 *
20* 20 *
21* This program is free software: you can redistribute it and/or modify 21 * This program is free software: you can redistribute it and/or modify
22* it under the terms of the GNU General Public License as published by 22 * it under the terms of the GNU General Public License as published by
23* the Free Software Foundation, either version 3 of the License, or 23 * the Free Software Foundation, either version 3 of the License, or
24* (at your option) any later version. 24 * (at your option) any later version.
25* 25 *
26* This program is distributed in the hope that it will be useful, 26 * This program is distributed in the hope that it will be useful,
27* but WITHOUT ANY WARRANTY; without even the implied warranty of 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29* GNU General Public License for more details. 29 * GNU General Public License for more details.
30* 30 *
31* You should have received a copy of the GNU General Public License 31 * You should have received a copy of the GNU General Public License
32* along with this program. If not, see <http://www.gnu.org/licenses/>. 32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33* 33 *
34* 34 *
35*****************************************************************************/ 35 *****************************************************************************/
36 36
37const char *progname = "check_procs"; 37const char *progname = "check_procs";
38const char *program_name = "check_procs"; /* Required for coreutils libs */ 38const char *program_name = "check_procs"; /* Required for coreutils libs */
39const char *copyright = "2000-2024"; 39const char *copyright = "2000-2024";
40const char *email = "devel@monitoring-plugins.org"; 40const char *email = "devel@monitoring-plugins.org";
41 41
@@ -43,313 +43,288 @@ const char *email = "devel@monitoring-plugins.org";
43#include "utils.h" 43#include "utils.h"
44#include "utils_cmd.h" 44#include "utils_cmd.h"
45#include "regex.h" 45#include "regex.h"
46#include "states.h"
47#include "check_procs.d/config.h"
46 48
47#include <pwd.h> 49#include <pwd.h>
48#include <errno.h> 50#include <errno.h>
49 51
50#ifdef HAVE_SYS_STAT_H 52#ifdef HAVE_SYS_STAT_H
51#include <sys/stat.h> 53# include <sys/stat.h>
52#endif 54#endif
53 55
54static int process_arguments (int /*argc*/, char ** /*argv*/); 56typedef struct {
55static int validate_arguments (void); 57 int errorcode;
56static int convert_to_seconds (char * /*etime*/); 58 check_procs_config config;
57static void print_help (void); 59} check_procs_config_wrapper;
58void print_usage (void); 60static check_procs_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
59 61static check_procs_config_wrapper validate_arguments(check_procs_config_wrapper /*config_wrapper*/);
60static char *warning_range = NULL; 62
61static char *critical_range = NULL; 63static int convert_to_seconds(char * /*etime*/, enum metric /*metric*/);
62static thresholds *procs_thresholds = NULL; 64static void print_help(void);
63 65void print_usage(void);
64static int options = 0; /* bitmask of filter criteria to test against */ 66
65#define ALL 1 67#define ALL 1
66#define STAT 2 68#define STAT 2
67#define PPID 4 69#define PPID 4
68#define USER 8 70#define USER 8
69#define PROG 16 71#define PROG 16
70#define ARGS 32 72#define ARGS 32
71#define VSZ 64 73#define VSZ 64
72#define RSS 128 74#define RSS 128
73#define PCPU 256 75#define PCPU 256
74#define ELAPSED 512 76#define ELAPSED 512
75#define EREG_ARGS 1024 77#define EREG_ARGS 1024
76#define EXCLUDE_PROGS 2048 78#define EXCLUDE_PROGS 2048
77 79
78#define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads: 80#define KTHREAD_PARENT \
79 ppid of procs are compared to pid of this proc*/ 81 "kthreadd" /* the parent process of kernel threads: \
80 82 ppid of procs are compared to pid of this proc*/
81/* Different metrics */
82char *metric_name;
83enum metric {
84 METRIC_PROCS,
85 METRIC_VSZ,
86 METRIC_RSS,
87 METRIC_CPU,
88 METRIC_ELAPSED
89};
90enum metric metric = METRIC_PROCS;
91 83
92static int verbose = 0; 84static int verbose = 0;
93static int uid; 85
94static pid_t ppid; 86static int stat_exe(const pid_t pid, struct stat *buf) {
95static int vsz;
96static int rss;
97static float pcpu;
98static char *statopts;
99static char *prog;
100static char *exclude_progs;
101static char **exclude_progs_arr = NULL;
102static char exclude_progs_counter = 0;
103static char *args;
104static char *input_filename = NULL;
105static regex_t re_args;
106static char *fmt;
107static char *fails;
108static char tmp[MAX_INPUT_BUFFER];
109static int kthread_filter = 0;
110static int usepid = 0; /* whether to test for pid or /proc/pid/exe */
111
112static int
113stat_exe (const pid_t pid, struct stat *buf) {
114 char *path; 87 char *path;
115 int ret;
116 xasprintf(&path, "/proc/%d/exe", pid); 88 xasprintf(&path, "/proc/%d/exe", pid);
117 ret = stat(path, buf); 89 int ret = stat(path, buf);
118 free(path); 90 free(path);
119 return ret; 91 return ret;
120} 92}
121 93
122 94int main(int argc, char **argv) {
123int 95 setlocale(LC_ALL, "");
124main (int argc, char **argv)
125{
126 char *input_buffer;
127 char *input_line;
128 char *procprog;
129
130 pid_t mypid = 0;
131 pid_t myppid = 0;
132 struct stat statbuf;
133 dev_t mydev = 0;
134 ino_t myino = 0;
135 int procuid = 0;
136 pid_t procpid = 0;
137 pid_t procppid = 0;
138 pid_t kthread_ppid = 0;
139 int procvsz = 0;
140 int procrss = 0;
141 int procseconds = 0;
142 float procpcpu = 0;
143 char procstat[8];
144 char procetime[MAX_INPUT_BUFFER] = { '\0' };
145 char *procargs;
146
147 const char *zombie = "Z";
148
149 int resultsum = 0; /* bitmask of the filter criteria met by a process */
150 int found = 0; /* counter for number of lines returned in `ps` output */
151 int procs = 0; /* counter for number of processes meeting filter criteria */
152 int pos; /* number of spaces before 'args' in `ps` output */
153 int cols; /* number of columns in ps output */
154 int expected_cols = PS_COLS - 1;
155 int warn = 0; /* number of processes in warn state */
156 int crit = 0; /* number of processes in crit state */
157 int i = 0;
158 int result = STATE_UNKNOWN;
159 int ret = 0;
160 output chld_out, chld_err;
161
162 setlocale (LC_ALL, "");
163 bindtextdomain (PACKAGE, LOCALEDIR);
164 textdomain (PACKAGE);
165 setlocale(LC_NUMERIC, "POSIX"); 96 setlocale(LC_NUMERIC, "POSIX");
166 97 bindtextdomain(PACKAGE, LOCALEDIR);
167 input_buffer = malloc (MAX_INPUT_BUFFER); 98 textdomain(PACKAGE);
168 procprog = malloc (MAX_INPUT_BUFFER);
169
170 xasprintf (&metric_name, "PROCS");
171 metric = METRIC_PROCS;
172 99
173 /* Parse extra opts if any */ 100 /* Parse extra opts if any */
174 argv=np_extra_opts (&argc, argv, progname); 101 argv = np_extra_opts(&argc, argv, progname);
102
103 check_procs_config_wrapper tmp_config = process_arguments(argc, argv);
104 if (tmp_config.errorcode == ERROR) {
105 usage4(_("Could not parse arguments"));
106 }
175 107
176 if (process_arguments (argc, argv) == ERROR) 108 check_procs_config config = tmp_config.config;
177 usage4 (_("Could not parse arguments"));
178 109
179 /* find ourself */ 110 /* find ourself */
180 mypid = getpid(); 111 pid_t mypid = getpid();
181 myppid = getppid(); 112 pid_t myppid = getppid();
182 if (usepid || stat_exe(mypid, &statbuf) == -1) { 113 dev_t mydev = 0;
114 ino_t myino = 0;
115 struct stat statbuf;
116 if (config.usepid || stat_exe(mypid, &statbuf) == -1) {
183 /* usepid might have been set by -T */ 117 /* usepid might have been set by -T */
184 usepid = 1; 118 config.usepid = true;
185 } else { 119 } else {
186 usepid = 0; 120 config.usepid = false;
187 mydev = statbuf.st_dev; 121 mydev = statbuf.st_dev;
188 myino = statbuf.st_ino; 122 myino = statbuf.st_ino;
189 } 123 }
190 124
191 /* Set signal handling and alarm timeout */ 125 /* Set signal handling and alarm timeout */
192 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { 126 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
193 die (STATE_UNKNOWN, _("Cannot catch SIGALRM")); 127 die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
194 } 128 }
195 (void) alarm ((unsigned) timeout_interval); 129 (void)alarm(timeout_interval);
196 130
197 if (verbose >= 2) 131 if (verbose >= 2) {
198 printf (_("CMD: %s\n"), PS_COMMAND); 132 printf(_("CMD: %s\n"), PS_COMMAND);
133 }
199 134
200 if (input_filename == NULL) { 135 output chld_out;
201 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0); 136 output chld_err;
137 mp_state_enum result = STATE_UNKNOWN;
138 if (config.input_filename == NULL) {
139 result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
202 if (chld_err.lines > 0) { 140 if (chld_err.lines > 0) {
203 printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]); 141 printf("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
204 exit(STATE_WARNING); 142 exit(STATE_WARNING);
205 } 143 }
206 } else { 144 } else {
207 result = cmd_file_read( input_filename, &chld_out, 0); 145 result = cmd_file_read(config.input_filename, &chld_out, 0);
208 } 146 }
209 147
148 int pos; /* number of spaces before 'args' in `ps` output */
149 uid_t procuid = 0;
150 pid_t procpid = 0;
151 pid_t procppid = 0;
152 pid_t kthread_ppid = 0;
153 int warn = 0; /* number of processes in warn state */
154 int crit = 0; /* number of processes in crit state */
155 int procvsz = 0;
156 int procrss = 0;
157 int procseconds = 0;
158 float procpcpu = 0;
159 char procstat[8];
160 char procetime[MAX_INPUT_BUFFER] = {'\0'};
161 int resultsum = 0; /* bitmask of the filter criteria met by a process */
162 int found = 0; /* counter for number of lines returned in `ps` output */
163 int procs = 0; /* counter for number of processes meeting filter criteria */
164 char *input_buffer = malloc(MAX_INPUT_BUFFER);
165 char *procprog = malloc(MAX_INPUT_BUFFER);
166 const int expected_cols = PS_COLS - 1;
167
210 /* flush first line: j starts at 1 */ 168 /* flush first line: j starts at 1 */
211 for (size_t j = 1; j < chld_out.lines; j++) { 169 for (size_t j = 1; j < chld_out.lines; j++) {
212 input_line = chld_out.line[j]; 170 char *input_line = chld_out.line[j];
213 171
214 if (verbose >= 3) 172 if (verbose >= 3) {
215 printf ("%s", input_line); 173 printf("%s", input_line);
174 }
216 175
217 strcpy (procprog, ""); 176 strcpy(procprog, "");
218 xasprintf (&procargs, "%s", ""); 177 char *procargs;
178 xasprintf(&procargs, "%s", "");
219 179
220 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST); 180 /* number of columns in ps output */
181 int cols = sscanf(input_line, PS_FORMAT, PS_VARLIST);
221 182
222 /* Zombie processes do not give a procprog command */ 183 /* Zombie processes do not give a procprog command */
223 if ( cols < expected_cols && strstr(procstat, zombie) ) { 184 const char *zombie = "Z";
185 if (cols < expected_cols && strstr(procstat, zombie)) {
224 cols = expected_cols; 186 cols = expected_cols;
225 } 187 }
226 if ( cols >= expected_cols ) { 188 if (cols >= expected_cols) {
227 resultsum = 0; 189 resultsum = 0;
228 xasprintf (&procargs, "%s", input_line + pos); 190 xasprintf(&procargs, "%s", input_line + pos);
229 strip (procargs); 191 strip(procargs);
230 192
231 /* Some ps return full pathname for command. This removes path */ 193 /* Some ps return full pathname for command. This removes path */
232 strcpy(procprog, base_name(procprog)); 194 strcpy(procprog, base_name(procprog));
233 195
234 /* we need to convert the elapsed time to seconds */ 196 /* we need to convert the elapsed time to seconds */
235 procseconds = convert_to_seconds(procetime); 197 procseconds = convert_to_seconds(procetime, config.metric);
236 198
237 if (verbose >= 3) 199 if (verbose >= 3) {
238 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 200 printf("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procs, procuid, procvsz,
239 procs, procuid, procvsz, procrss, 201 procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs);
240 procpid, procppid, procpcpu, procstat, 202 }
241 procetime, procprog, procargs);
242 203
243 /* Ignore self */ 204 /* Ignore self */
244 if ((usepid && mypid == procpid) || 205 int ret = 0;
245 ( ((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) || 206 if ((config.usepid && mypid == procpid) ||
246 (ret == -1 && errno == ENOENT)) 207 (((!config.usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
247 ) { 208 (ret == -1 && errno == ENOENT))) {
248 if (verbose >= 3) 209 if (verbose >= 3) {
249 printf("not considering - is myself or gone\n"); 210 printf("not considering - is myself or gone\n");
211 }
250 continue; 212 continue;
251 } 213 }
252 /* Ignore parent*/ 214 /* Ignore parent*/
253 else if (myppid == procpid) { 215 if (myppid == procpid) {
254 if (verbose >= 3) 216 if (verbose >= 3) {
255 printf("not considering - is parent\n"); 217 printf("not considering - is parent\n");
218 }
256 continue; 219 continue;
257 } 220 }
258 221
259 /* Ignore our own children */ 222 /* Ignore our own children */
260 if (procppid == mypid) { 223 if (procppid == mypid) {
261 if (verbose >= 3) 224 if (verbose >= 3) {
262 printf("not considering - is our child\n"); 225 printf("not considering - is our child\n");
226 }
263 continue; 227 continue;
264 } 228 }
265 229
266 /* Ignore excluded processes by name */ 230 /* Ignore excluded processes by name */
267 if(options & EXCLUDE_PROGS) { 231 if (config.options & EXCLUDE_PROGS) {
268 int found = 0; 232 bool found = false;
269 int i = 0; 233 for (int i = 0; i < (config.exclude_progs_counter); i++) {
270 234 if (!strcmp(procprog, config.exclude_progs_arr[i])) {
271 for(i=0; i < (exclude_progs_counter); i++) { 235 found = true;
272 if(!strcmp(procprog, exclude_progs_arr[i])) { 236 }
273 found = 1; 237 }
274 } 238 if (!found) {
275 } 239 resultsum |= EXCLUDE_PROGS;
276 if(found == 0) { 240 } else {
277 resultsum |= EXCLUDE_PROGS; 241 if (verbose >= 3) {
278 } else 242 printf("excluding - by ignorelist\n");
279 { 243 }
280 if(verbose >= 3) 244 }
281 printf("excluding - by ignorelist\n");
282 }
283 } 245 }
284 246
285 /* filter kernel threads (children of KTHREAD_PARENT)*/ 247 /* filter kernel threads (children of KTHREAD_PARENT)*/
286 /* TODO adapt for other OSes than GNU/Linux 248 /* TODO adapt for other OSes than GNU/Linux
287 sorry for not doing that, but I've no other OSes to test :-( */ 249 sorry for not doing that, but I've no other OSes to test :-( */
288 if (kthread_filter == 1) { 250 if (config.kthread_filter) {
289 /* get pid KTHREAD_PARENT */ 251 /* get pid KTHREAD_PARENT */
290 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT) ) 252 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
291 kthread_ppid = procpid; 253 kthread_ppid = procpid;
254 }
292 255
293 if (kthread_ppid == procppid) { 256 if (kthread_ppid == procppid) {
294 if (verbose >= 2) 257 if (verbose >= 2) {
295 printf ("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs); 258 printf("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs);
259 }
296 continue; 260 continue;
297 } 261 }
298 } 262 }
299 263
300 if ((options & STAT) && (strstr (procstat, statopts))) 264 if ((config.options & STAT) && (strstr(procstat, config.statopts))) {
301 resultsum |= STAT; 265 resultsum |= STAT;
302 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL)) 266 }
267 if ((config.options & ARGS) && procargs && (strstr(procargs, config.args) != NULL)) {
303 resultsum |= ARGS; 268 resultsum |= ARGS;
304 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0)) 269 }
270 if ((config.options & EREG_ARGS) && procargs && (regexec(&config.re_args, procargs, (size_t)0, NULL, 0) == 0)) {
305 resultsum |= EREG_ARGS; 271 resultsum |= EREG_ARGS;
306 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0)) 272 }
273 if ((config.options & PROG) && procprog && (strcmp(config.prog, procprog) == 0)) {
307 resultsum |= PROG; 274 resultsum |= PROG;
308 if ((options & PPID) && (procppid == ppid)) 275 }
276 if ((config.options & PPID) && (procppid == config.ppid)) {
309 resultsum |= PPID; 277 resultsum |= PPID;
310 if ((options & USER) && (procuid == uid)) 278 }
279 if ((config.options & USER) && (procuid == config.uid)) {
311 resultsum |= USER; 280 resultsum |= USER;
312 if ((options & VSZ) && (procvsz >= vsz)) 281 }
282 if ((config.options & VSZ) && (procvsz >= config.vsz)) {
313 resultsum |= VSZ; 283 resultsum |= VSZ;
314 if ((options & RSS) && (procrss >= rss)) 284 }
285 if ((config.options & RSS) && (procrss >= config.rss)) {
315 resultsum |= RSS; 286 resultsum |= RSS;
316 if ((options & PCPU) && (procpcpu >= pcpu)) 287 }
288 if ((config.options & PCPU) && (procpcpu >= config.pcpu)) {
317 resultsum |= PCPU; 289 resultsum |= PCPU;
290 }
318 291
319 found++; 292 found++;
320 293
321 /* Next line if filters not matched */ 294 /* Next line if filters not matched */
322 if (!(options == resultsum || options == ALL)) 295 if (!(config.options == resultsum || config.options == ALL)) {
323 continue; 296 continue;
297 }
324 298
325 procs++; 299 procs++;
326 if (verbose >= 2) { 300 if (verbose >= 2) {
327 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 301 printf("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procuid, procvsz,
328 procuid, procvsz, procrss, 302 procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs);
329 procpid, procppid, procpcpu, procstat,
330 procetime, procprog, procargs);
331 } 303 }
332 304
333 if (metric == METRIC_VSZ) 305 mp_state_enum temporary_result = STATE_OK;
334 i = get_status ((double)procvsz, procs_thresholds); 306 if (config.metric == METRIC_VSZ) {
335 else if (metric == METRIC_RSS) 307 temporary_result = get_status((double)procvsz, config.procs_thresholds);
336 i = get_status ((double)procrss, procs_thresholds); 308 } else if (config.metric == METRIC_RSS) {
309 temporary_result = get_status((double)procrss, config.procs_thresholds);
310 }
337 /* TODO? float thresholds for --metric=CPU */ 311 /* TODO? float thresholds for --metric=CPU */
338 else if (metric == METRIC_CPU) 312 else if (config.metric == METRIC_CPU) {
339 i = get_status (procpcpu, procs_thresholds); 313 temporary_result = get_status(procpcpu, config.procs_thresholds);
340 else if (metric == METRIC_ELAPSED) 314 } else if (config.metric == METRIC_ELAPSED) {
341 i = get_status ((double)procseconds, procs_thresholds); 315 temporary_result = get_status((double)procseconds, config.procs_thresholds);
316 }
342 317
343 if (metric != METRIC_PROCS) { 318 if (config.metric != METRIC_PROCS) {
344 if (i == STATE_WARNING) { 319 if (temporary_result == STATE_WARNING) {
345 warn++; 320 warn++;
346 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog); 321 xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
347 result = max_state (result, i); 322 result = max_state(result, temporary_result);
348 } 323 }
349 if (i == STATE_CRITICAL) { 324 if (temporary_result == STATE_CRITICAL) {
350 crit++; 325 crit++;
351 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog); 326 xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
352 result = max_state (result, i); 327 result = max_state(result, temporary_result);
353 } 328 }
354 } 329 }
355 } 330 }
@@ -359,339 +334,350 @@ main (int argc, char **argv)
359 } 334 }
360 } 335 }
361 336
362 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */ 337 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
363 printf (_("Unable to read output\n")); 338 printf(_("Unable to read output\n"));
364 return STATE_UNKNOWN; 339 return STATE_UNKNOWN;
365 } 340 }
366 341
367 if ( result == STATE_UNKNOWN ) 342 if (result == STATE_UNKNOWN) {
368 result = STATE_OK; 343 result = STATE_OK;
344 }
369 345
370 /* Needed if procs found, but none match filter */ 346 /* Needed if procs found, but none match filter */
371 if ( metric == METRIC_PROCS ) { 347 if (config.metric == METRIC_PROCS) {
372 result = max_state (result, get_status ((double)procs, procs_thresholds) ); 348 result = max_state(result, get_status((double)procs, config.procs_thresholds));
373 } 349 }
374 350
375 if ( result == STATE_OK ) { 351 if (result == STATE_OK) {
376 printf ("%s %s: ", metric_name, _("OK")); 352 printf("%s %s: ", config.metric_name, _("OK"));
377 } else if (result == STATE_WARNING) { 353 } else if (result == STATE_WARNING) {
378 printf ("%s %s: ", metric_name, _("WARNING")); 354 printf("%s %s: ", config.metric_name, _("WARNING"));
379 if ( metric != METRIC_PROCS ) { 355 if (config.metric != METRIC_PROCS) {
380 printf (_("%d warn out of "), warn); 356 printf(_("%d warn out of "), warn);
381 } 357 }
382 } else if (result == STATE_CRITICAL) { 358 } else if (result == STATE_CRITICAL) {
383 printf ("%s %s: ", metric_name, _("CRITICAL")); 359 printf("%s %s: ", config.metric_name, _("CRITICAL"));
384 if (metric != METRIC_PROCS) { 360 if (config.metric != METRIC_PROCS) {
385 printf (_("%d crit, %d warn out of "), crit, warn); 361 printf(_("%d crit, %d warn out of "), crit, warn);
386 } 362 }
387 } 363 }
388 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs); 364 printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs);
389 365
390 if (strcmp(fmt,"") != 0) { 366 if (strcmp(config.fmt, "") != 0) {
391 printf (_(" with %s"), fmt); 367 printf(_(" with %s"), config.fmt);
392 } 368 }
393 369
394 if ( verbose >= 1 && strcmp(fails,"") ) 370 if (verbose >= 1 && strcmp(config.fails, "")) {
395 printf (" [%s]", fails); 371 printf(" [%s]", config.fails);
372 }
396 373
397 if (metric == METRIC_PROCS) 374 if (config.metric == METRIC_PROCS) {
398 printf (" | procs=%d;%s;%s;0;", procs, 375 printf(" | procs=%d;%s;%s;0;", procs, config.warning_range ? config.warning_range : "",
399 warning_range ? warning_range : "", 376 config.critical_range ? config.critical_range : "");
400 critical_range ? critical_range : ""); 377 } else {
401 else 378 printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
402 printf (" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit); 379 }
403 380
404 printf ("\n"); 381 printf("\n");
405 return result; 382 exit(result);
406} 383}
407 384
408
409
410/* process command-line arguments */ 385/* process command-line arguments */
411int 386check_procs_config_wrapper process_arguments(int argc, char **argv) {
412process_arguments (int argc, char **argv) 387 static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
413{ 388 {"critical", required_argument, 0, 'c'},
414 int c = 1; 389 {"metric", required_argument, 0, 'm'},
415 char *user; 390 {"timeout", required_argument, 0, 't'},
416 struct passwd *pw; 391 {"status", required_argument, 0, 's'},
417 int option = 0; 392 {"ppid", required_argument, 0, 'p'},
418 int err; 393 {"user", required_argument, 0, 'u'},
419 int cflags = REG_NOSUB | REG_EXTENDED; 394 {"command", required_argument, 0, 'C'},
420 char errbuf[MAX_INPUT_BUFFER]; 395 {"vsz", required_argument, 0, 'z'},
421 char *temp_string; 396 {"rss", required_argument, 0, 'r'},
422 int i=0; 397 {"pcpu", required_argument, 0, 'P'},
423 static struct option longopts[] = { 398 {"elapsed", required_argument, 0, 'e'},
424 {"warning", required_argument, 0, 'w'}, 399 {"argument-array", required_argument, 0, 'a'},
425 {"critical", required_argument, 0, 'c'}, 400 {"help", no_argument, 0, 'h'},
426 {"metric", required_argument, 0, 'm'}, 401 {"version", no_argument, 0, 'V'},
427 {"timeout", required_argument, 0, 't'}, 402 {"verbose", no_argument, 0, 'v'},
428 {"status", required_argument, 0, 's'}, 403 {"ereg-argument-array", required_argument, 0, CHAR_MAX + 1},
429 {"ppid", required_argument, 0, 'p'}, 404 {"input-file", required_argument, 0, CHAR_MAX + 2},
430 {"user", required_argument, 0, 'u'}, 405 {"no-kthreads", required_argument, 0, 'k'},
431 {"command", required_argument, 0, 'C'}, 406 {"traditional-filter", no_argument, 0, 'T'},
432 {"vsz", required_argument, 0, 'z'}, 407 {"exclude-process", required_argument, 0, 'X'},
433 {"rss", required_argument, 0, 'r'}, 408 {0, 0, 0, 0}};
434 {"pcpu", required_argument, 0, 'P'}, 409
435 {"elapsed", required_argument, 0, 'e'}, 410 for (int index = 1; index < argc; index++) {
436 {"argument-array", required_argument, 0, 'a'}, 411 if (strcmp("-to", argv[index]) == 0) {
437 {"help", no_argument, 0, 'h'}, 412 strcpy(argv[index], "-t");
438 {"version", no_argument, 0, 'V'}, 413 }
439 {"verbose", no_argument, 0, 'v'}, 414 }
440 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
441 {"input-file", required_argument, 0, CHAR_MAX+2},
442 {"no-kthreads", required_argument, 0, 'k'},
443 {"traditional-filter", no_argument, 0, 'T'},
444 {"exclude-process", required_argument, 0, 'X'},
445 {0, 0, 0, 0}
446 };
447 415
448 for (c = 1; c < argc; c++) 416 check_procs_config_wrapper result = {
449 if (strcmp ("-to", argv[c]) == 0) 417 .errorcode = OK,
450 strcpy (argv[c], "-t"); 418 .config = check_procs_config_init(),
419 };
451 420
452 while (1) { 421 while (true) {
453 c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", 422 int option = 0;
454 longopts, &option); 423 int option_index = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", longopts, &option);
455 424
456 if (c == -1 || c == EOF) 425 if (option_index == -1 || option_index == EOF) {
457 break; 426 break;
427 }
458 428
459 switch (c) { 429 switch (option_index) {
460 case '?': /* help */ 430 case '?': /* help */
461 usage5 (); 431 usage5();
462 case 'h': /* help */ 432 case 'h': /* help */
463 print_help (); 433 print_help();
464 exit (STATE_UNKNOWN); 434 exit(STATE_UNKNOWN);
465 case 'V': /* version */ 435 case 'V': /* version */
466 print_revision (progname, NP_VERSION); 436 print_revision(progname, NP_VERSION);
467 exit (STATE_UNKNOWN); 437 exit(STATE_UNKNOWN);
468 case 't': /* timeout period */ 438 case 't': /* timeout period */
469 if (!is_integer (optarg)) 439 if (!is_integer(optarg)) {
470 usage2 (_("Timeout interval must be a positive integer"), optarg); 440 usage2(_("Timeout interval must be a positive integer"), optarg);
471 else 441 } else {
472 timeout_interval = atoi (optarg); 442 timeout_interval = atoi(optarg);
443 }
473 break; 444 break;
474 case 'c': /* critical threshold */ 445 case 'c': /* critical threshold */
475 critical_range = optarg; 446 result.config.critical_range = optarg;
476 break; 447 break;
477 case 'w': /* warning threshold */ 448 case 'w': /* warning threshold */
478 warning_range = optarg; 449 result.config.warning_range = optarg;
479 break; 450 break;
480 case 'p': /* process id */ 451 case 'p': { /* process id */
481 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) { 452 static char tmp[MAX_INPUT_BUFFER];
482 xasprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid); 453 if (sscanf(optarg, "%d%[^0-9]", &result.config.ppid, tmp) == 1) {
483 options |= PPID; 454 xasprintf(&result.config.fmt, "%s%sPPID = %d", (result.config.fmt ? result.config.fmt : ""),
455 (result.config.options ? ", " : ""), result.config.ppid);
456 result.config.options |= PPID;
484 break; 457 break;
485 } 458 }
486 usage4 (_("Parent Process ID must be an integer!")); 459 usage4(_("Parent Process ID must be an integer!"));
487 case 's': /* status */ 460 }
488 if (statopts) 461 case 's': /* status */
462 if (result.config.statopts) {
489 break; 463 break;
490 else 464 } else {
491 statopts = optarg; 465 result.config.statopts = optarg;
492 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); 466 }
493 options |= STAT; 467 xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
468 (result.config.options ? ", " : ""), result.config.statopts);
469 result.config.options |= STAT;
494 break; 470 break;
495 case 'u': /* user or user id */ 471 case 'u': /* user or user id */ {
496 if (is_integer (optarg)) { 472 struct passwd *pw;
497 uid = atoi (optarg); 473 if (is_integer(optarg)) {
498 pw = getpwuid ((uid_t) uid); 474 result.config.uid = atoi(optarg);
475 pw = getpwuid(result.config.uid);
499 /* check to be sure user exists */ 476 /* check to be sure user exists */
500 if (pw == NULL) 477 if (pw == NULL) {
501 usage2 (_("UID was not found"), optarg); 478 usage2(_("UID was not found"), optarg);
502 } 479 }
503 else { 480 } else {
504 pw = getpwnam (optarg); 481 pw = getpwnam(optarg);
505 /* check to be sure user exists */ 482 /* check to be sure user exists */
506 if (pw == NULL) 483 if (pw == NULL) {
507 usage2 (_("User name was not found"), optarg); 484 usage2(_("User name was not found"), optarg);
485 }
508 /* then get uid */ 486 /* then get uid */
509 uid = pw->pw_uid; 487 result.config.uid = pw->pw_uid;
510 } 488 }
511 user = pw->pw_name; 489
512 xasprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), 490 char *user = pw->pw_name;
513 uid, user); 491 xasprintf(&result.config.fmt, "%s%sUID = %d (%s)", (result.config.fmt ? result.config.fmt : ""),
514 options |= USER; 492 (result.config.options ? ", " : ""), result.config.uid, user);
515 break; 493 result.config.options |= USER;
516 case 'C': /* command */ 494 } break;
495 case 'C': /* command */
517 /* TODO: allow this to be passed in with --metric */ 496 /* TODO: allow this to be passed in with --metric */
518 if (prog) 497 if (result.config.prog) {
519 break; 498 break;
520 else 499 } else {
521 prog = optarg; 500 result.config.prog = optarg;
522 xasprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), 501 }
523 prog); 502 xasprintf(&result.config.fmt, _("%s%scommand name '%s'"), (result.config.fmt ? result.config.fmt : ""),
524 options |= PROG; 503 (result.config.options ? ", " : ""), result.config.prog);
504 result.config.options |= PROG;
525 break; 505 break;
526 case 'X': 506 case 'X':
527 if(exclude_progs) 507 if (result.config.exclude_progs) {
528 break; 508 break;
529 else 509 } else {
530 exclude_progs = optarg; 510 result.config.exclude_progs = optarg;
531 xasprintf (&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), 511 }
532 exclude_progs); 512 xasprintf(&result.config.fmt, _("%s%sexclude progs '%s'"), (result.config.fmt ? result.config.fmt : ""),
533 char *p = strtok(exclude_progs, ","); 513 (result.config.options ? ", " : ""), result.config.exclude_progs);
534 514 char *tmp_pointer = strtok(result.config.exclude_progs, ",");
535 while(p){ 515
536 exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char*) * ++exclude_progs_counter); 516 while (tmp_pointer) {
537 exclude_progs_arr[exclude_progs_counter-1] = p; 517 result.config.exclude_progs_arr =
538 p = strtok(NULL, ","); 518 realloc(result.config.exclude_progs_arr, sizeof(char *) * ++result.config.exclude_progs_counter);
519 result.config.exclude_progs_arr[result.config.exclude_progs_counter - 1] = tmp_pointer;
520 tmp_pointer = strtok(NULL, ",");
539 } 521 }
540 522
541 options |= EXCLUDE_PROGS; 523 result.config.options |= EXCLUDE_PROGS;
542 break; 524 break;
543 case 'a': /* args (full path name with args) */ 525 case 'a': /* args (full path name with args) */
544 /* TODO: allow this to be passed in with --metric */ 526 /* TODO: allow this to be passed in with --metric */
545 if (args) 527 if (result.config.args) {
546 break; 528 break;
547 else 529 } else {
548 args = optarg; 530 result.config.args = optarg;
549 xasprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args); 531 }
550 options |= ARGS; 532 xasprintf(&result.config.fmt, "%s%sargs '%s'", (result.config.fmt ? result.config.fmt : ""),
533 (result.config.options ? ", " : ""), result.config.args);
534 result.config.options |= ARGS;
551 break; 535 break;
552 case CHAR_MAX+1: 536 case CHAR_MAX + 1: {
553 err = regcomp(&re_args, optarg, cflags); 537 int cflags = REG_NOSUB | REG_EXTENDED;
538 int err = regcomp(&result.config.re_args, optarg, cflags);
554 if (err != 0) { 539 if (err != 0) {
555 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER); 540 char errbuf[MAX_INPUT_BUFFER];
556 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); 541 regerror(err, &result.config.re_args, errbuf, MAX_INPUT_BUFFER);
542 die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
557 } 543 }
558 /* Strip off any | within the regex optarg */ 544 /* Strip off any | within the regex optarg */
559 temp_string = strdup(optarg); 545 char *temp_string = strdup(optarg);
560 while(temp_string[i]!='\0'){ 546 int index = 0;
561 if(temp_string[i]=='|') 547 while (temp_string[index] != '\0') {
562 temp_string[i]=','; 548 if (temp_string[index] == '|') {
563 i++; 549 temp_string[index] = ',';
564 } 550 }
565 xasprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string); 551 index++;
566 options |= EREG_ARGS; 552 }
567 break; 553 xasprintf(&result.config.fmt, "%s%sregex args '%s'", (result.config.fmt ? result.config.fmt : ""),
568 case 'r': /* RSS */ 554 (result.config.options ? ", " : ""), temp_string);
569 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) { 555 result.config.options |= EREG_ARGS;
570 xasprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss); 556 } break;
571 options |= RSS; 557 case 'r': { /* RSS */
558 static char tmp[MAX_INPUT_BUFFER];
559 if (sscanf(optarg, "%d%[^0-9]", &result.config.rss, tmp) == 1) {
560 xasprintf(&result.config.fmt, "%s%sRSS >= %d", (result.config.fmt ? result.config.fmt : ""),
561 (result.config.options ? ", " : ""), result.config.rss);
562 result.config.options |= RSS;
572 break; 563 break;
573 } 564 }
574 usage4 (_("RSS must be an integer!")); 565 usage4(_("RSS must be an integer!"));
575 case 'z': /* VSZ */ 566 }
576 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) { 567 case 'z': { /* VSZ */
577 xasprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz); 568 static char tmp[MAX_INPUT_BUFFER];
578 options |= VSZ; 569 if (sscanf(optarg, "%d%[^0-9]", &result.config.vsz, tmp) == 1) {
570 xasprintf(&result.config.fmt, "%s%sVSZ >= %d", (result.config.fmt ? result.config.fmt : ""),
571 (result.config.options ? ", " : ""), result.config.vsz);
572 result.config.options |= VSZ;
579 break; 573 break;
580 } 574 }
581 usage4 (_("VSZ must be an integer!")); 575 usage4(_("VSZ must be an integer!"));
582 case 'P': /* PCPU */ 576 }
577 case 'P': { /* PCPU */
583 /* TODO: -P 1.5.5 is accepted */ 578 /* TODO: -P 1.5.5 is accepted */
584 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) { 579 static char tmp[MAX_INPUT_BUFFER];
585 xasprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu); 580 if (sscanf(optarg, "%f%[^0-9.]", &result.config.pcpu, tmp) == 1) {
586 options |= PCPU; 581 xasprintf(&result.config.fmt, "%s%sPCPU >= %.2f", (result.config.fmt ? result.config.fmt : ""),
582 (result.config.options ? ", " : ""), result.config.pcpu);
583 result.config.options |= PCPU;
587 break; 584 break;
588 } 585 }
589 usage4 (_("PCPU must be a float!")); 586 usage4(_("PCPU must be a float!"));
587 }
590 case 'm': 588 case 'm':
591 xasprintf (&metric_name, "%s", optarg); 589 xasprintf(&result.config.metric_name, "%s", optarg);
592 if ( strcmp(optarg, "PROCS") == 0) { 590 if (strcmp(optarg, "PROCS") == 0) {
593 metric = METRIC_PROCS; 591 result.config.metric = METRIC_PROCS;
594 break; 592 break;
595 } 593 }
596 else if ( strcmp(optarg, "VSZ") == 0) { 594 if (strcmp(optarg, "VSZ") == 0) {
597 metric = METRIC_VSZ; 595 result.config.metric = METRIC_VSZ;
598 break; 596 break;
599 } 597 }
600 else if ( strcmp(optarg, "RSS") == 0 ) { 598 if (strcmp(optarg, "RSS") == 0) {
601 metric = METRIC_RSS; 599 result.config.metric = METRIC_RSS;
602 break; 600 break;
603 } 601 }
604 else if ( strcmp(optarg, "CPU") == 0 ) { 602 if (strcmp(optarg, "CPU") == 0) {
605 metric = METRIC_CPU; 603 result.config.metric = METRIC_CPU;
606 break; 604 break;
607 } 605 }
608 else if ( strcmp(optarg, "ELAPSED") == 0) { 606 if (strcmp(optarg, "ELAPSED") == 0) {
609 metric = METRIC_ELAPSED; 607 result.config.metric = METRIC_ELAPSED;
610 break; 608 break;
611 } 609 }
612 610
613 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!")); 611 usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
614 case 'k': /* linux kernel thread filter */ 612 case 'k': /* linux kernel thread filter */
615 kthread_filter = 1; 613 result.config.kthread_filter = true;
616 break; 614 break;
617 case 'v': /* command */ 615 case 'v': /* command */
618 verbose++; 616 verbose++;
619 break; 617 break;
620 case 'T': 618 case 'T':
621 usepid = 1; 619 result.config.usepid = true;
622 break; 620 break;
623 case CHAR_MAX+2: 621 case CHAR_MAX + 2:
624 input_filename = optarg; 622 result.config.input_filename = optarg;
625 break; 623 break;
626 } 624 }
627 } 625 }
628 626
629 c = optind; 627 int index = optind;
630 if ((! warning_range) && argv[c]) 628 if ((!result.config.warning_range) && argv[index]) {
631 warning_range = argv[c++]; 629 result.config.warning_range = argv[index++];
632 if ((! critical_range) && argv[c]) 630 }
633 critical_range = argv[c++]; 631 if ((!result.config.critical_range) && argv[index]) {
634 if (statopts == NULL && argv[c]) { 632 result.config.critical_range = argv[index++];
635 xasprintf (&statopts, "%s", argv[c++]); 633 }
636 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); 634 if (result.config.statopts == NULL && argv[index]) {
637 options |= STAT; 635 xasprintf(&result.config.statopts, "%s", argv[index++]);
636 xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
637 (result.config.options ? ", " : ""), result.config.statopts);
638 result.config.options |= STAT;
638 } 639 }
639 640
640 /* this will abort in case of invalid ranges */ 641 /* this will abort in case of invalid ranges */
641 set_thresholds (&procs_thresholds, warning_range, critical_range); 642 set_thresholds(&result.config.procs_thresholds, result.config.warning_range, result.config.critical_range);
642 643
643 return validate_arguments (); 644 return validate_arguments(result);
644} 645}
645 646
647check_procs_config_wrapper validate_arguments(check_procs_config_wrapper config_wrapper) {
648 if (config_wrapper.config.options == 0) {
649 config_wrapper.config.options = ALL;
650 }
646 651
652 if (config_wrapper.config.statopts == NULL) {
653 config_wrapper.config.statopts = strdup("");
654 }
647 655
648int 656 if (config_wrapper.config.prog == NULL) {
649validate_arguments () 657 config_wrapper.config.prog = strdup("");
650{ 658 }
651 if (options == 0)
652 options = ALL;
653
654 if (statopts==NULL)
655 statopts = strdup("");
656
657 if (prog==NULL)
658 prog = strdup("");
659 659
660 if (args==NULL) 660 if (config_wrapper.config.args == NULL) {
661 args = strdup(""); 661 config_wrapper.config.args = strdup("");
662 }
662 663
663 if (fmt==NULL) 664 if (config_wrapper.config.fmt == NULL) {
664 fmt = strdup(""); 665 config_wrapper.config.fmt = strdup("");
666 }
665 667
666 if (fails==NULL) 668 if (config_wrapper.config.fails == NULL) {
667 fails = strdup(""); 669 config_wrapper.config.fails = strdup("");
670 }
668 671
669 return options; 672 // return options;
673 return config_wrapper;
670} 674}
671 675
672
673/* convert the elapsed time to seconds */ 676/* convert the elapsed time to seconds */
674int 677int convert_to_seconds(char *etime, enum metric metric) {
675convert_to_seconds(char *etime) { 678 int hyphcnt = 0;
676 679 int coloncnt = 0;
677 char *ptr; 680 for (char *ptr = etime; *ptr != '\0'; ptr++) {
678 int total;
679
680 int hyphcnt;
681 int coloncnt;
682 int days;
683 int hours;
684 int minutes;
685 int seconds;
686
687 hyphcnt = 0;
688 coloncnt = 0;
689 days = 0;
690 hours = 0;
691 minutes = 0;
692 seconds = 0;
693
694 for (ptr = etime; *ptr != '\0'; ptr++) {
695 681
696 if (*ptr == '-') { 682 if (*ptr == '-') {
697 hyphcnt++; 683 hyphcnt++;
@@ -703,9 +689,12 @@ convert_to_seconds(char *etime) {
703 } 689 }
704 } 690 }
705 691
692 int days = 0;
693 int hours = 0;
694 int minutes = 0;
695 int seconds = 0;
706 if (hyphcnt > 0) { 696 if (hyphcnt > 0) {
707 sscanf(etime, "%d-%d:%d:%d", 697 sscanf(etime, "%d-%d:%d:%d", &days, &hours, &minutes, &seconds);
708 &days, &hours, &minutes, &seconds);
709 /* linux 2.6.5/2.6.6 reporting some processes with infinite 698 /* linux 2.6.5/2.6.6 reporting some processes with infinite
710 * elapsed times for some reason */ 699 * elapsed times for some reason */
711 if (days == 49710) { 700 if (days == 49710) {
@@ -713,135 +702,125 @@ convert_to_seconds(char *etime) {
713 } 702 }
714 } else { 703 } else {
715 if (coloncnt == 2) { 704 if (coloncnt == 2) {
716 sscanf(etime, "%d:%d:%d", 705 sscanf(etime, "%d:%d:%d", &hours, &minutes, &seconds);
717 &hours, &minutes, &seconds);
718 } else if (coloncnt == 1) { 706 } else if (coloncnt == 1) {
719 sscanf(etime, "%d:%d", 707 sscanf(etime, "%d:%d", &minutes, &seconds);
720 &minutes, &seconds);
721 } 708 }
722 } 709 }
723 710
724 total = (days * 86400) + 711 int total = (days * 86400) + (hours * 3600) + (minutes * 60) + seconds;
725 (hours * 3600) +
726 (minutes * 60) +
727 seconds;
728 712
729 if (verbose >= 3 && metric == METRIC_ELAPSED) { 713 if (verbose >= 3 && metric == METRIC_ELAPSED) {
730 printf("seconds: %d\n", total); 714 printf("seconds: %d\n", total);
731 } 715 }
732 return total; 716 return total;
733} 717}
734 718
719void print_help(void) {
720 print_revision(progname, NP_VERSION);
735 721
736void 722 printf("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
737print_help (void) 723 printf(COPYRIGHT, copyright, email);
738{
739 print_revision (progname, NP_VERSION);
740
741 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
742 printf (COPYRIGHT, copyright, email);
743 724
744 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified")); 725 printf("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
745 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number")); 726 printf("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
746 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check.")); 727 printf("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
747 728
748 printf ("\n\n"); 729 printf("\n\n");
749 730
750 printf ("%s\n", _("The parent process, check_procs itself and any child process of check_procs (ps)")); 731 printf("%s\n", _("The parent process, check_procs itself and any child process of check_procs (ps)"));
751 printf ("%s\n", _("are excluded from any checks to prevent false positives.")); 732 printf("%s\n", _("are excluded from any checks to prevent false positives."));
752 733
753 printf ("\n\n"); 734 printf("\n\n");
754 735
755 print_usage (); 736 print_usage();
756 737
757 printf (UT_HELP_VRSN); 738 printf(UT_HELP_VRSN);
758 printf (UT_EXTRA_OPTS); 739 printf(UT_EXTRA_OPTS);
759 printf (" %s\n", "-w, --warning=RANGE"); 740 printf(" %s\n", "-w, --warning=RANGE");
760 printf (" %s\n", _("Generate warning state if metric is outside this range")); 741 printf(" %s\n", _("Generate warning state if metric is outside this range"));
761 printf (" %s\n", "-c, --critical=RANGE"); 742 printf(" %s\n", "-c, --critical=RANGE");
762 printf (" %s\n", _("Generate critical state if metric is outside this range")); 743 printf(" %s\n", _("Generate critical state if metric is outside this range"));
763 printf (" %s\n", "-m, --metric=TYPE"); 744 printf(" %s\n", "-m, --metric=TYPE");
764 printf (" %s\n", _("Check thresholds against metric. Valid types:")); 745 printf(" %s\n", _("Check thresholds against metric. Valid types:"));
765 printf (" %s\n", _("PROCS - number of processes (default)")); 746 printf(" %s\n", _("PROCS - number of processes (default)"));
766 printf (" %s\n", _("VSZ - virtual memory size")); 747 printf(" %s\n", _("VSZ - virtual memory size"));
767 printf (" %s\n", _("RSS - resident set memory size")); 748 printf(" %s\n", _("RSS - resident set memory size"));
768 printf (" %s\n", _("CPU - percentage CPU")); 749 printf(" %s\n", _("CPU - percentage CPU"));
769/* only linux etime is support currently */ 750/* only linux etime is support currently */
770#if defined( __linux__ ) 751#if defined(__linux__)
771 printf (" %s\n", _("ELAPSED - time elapsed in seconds")); 752 printf(" %s\n", _("ELAPSED - time elapsed in seconds"));
772#endif /* defined(__linux__) */ 753#endif /* defined(__linux__) */
773 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); 754 printf(UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
774 755
775 printf (" %s\n", "-v, --verbose"); 756 printf(" %s\n", "-v, --verbose");
776 printf (" %s\n", _("Extra information. Up to 3 verbosity levels")); 757 printf(" %s\n", _("Extra information. Up to 3 verbosity levels"));
777 758
778 printf (" %s\n", "-T, --traditional"); 759 printf(" %s\n", "-T, --traditional");
779 printf (" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe")); 760 printf(" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe"));
780 761
781 printf ("\n"); 762 printf("\n");
782 printf ("%s\n", "Filters:"); 763 printf("%s\n", "Filters:");
783 printf (" %s\n", "-s, --state=STATUSFLAGS"); 764 printf(" %s\n", "-s, --state=STATUSFLAGS");
784 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or")); 765 printf(" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
785 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,")); 766 printf(" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
786 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command).")); 767 printf(" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
787 printf (" %s\n", "-p, --ppid=PPID"); 768 printf(" %s\n", "-p, --ppid=PPID");
788 printf (" %s\n", _("Only scan for children of the parent process ID indicated.")); 769 printf(" %s\n", _("Only scan for children of the parent process ID indicated."));
789 printf (" %s\n", "-z, --vsz=VSZ"); 770 printf(" %s\n", "-z, --vsz=VSZ");
790 printf (" %s\n", _("Only scan for processes with VSZ higher than indicated.")); 771 printf(" %s\n", _("Only scan for processes with VSZ higher than indicated."));
791 printf (" %s\n", "-r, --rss=RSS"); 772 printf(" %s\n", "-r, --rss=RSS");
792 printf (" %s\n", _("Only scan for processes with RSS higher than indicated.")); 773 printf(" %s\n", _("Only scan for processes with RSS higher than indicated."));
793 printf (" %s\n", "-P, --pcpu=PCPU"); 774 printf(" %s\n", "-P, --pcpu=PCPU");
794 printf (" %s\n", _("Only scan for processes with PCPU higher than indicated.")); 775 printf(" %s\n", _("Only scan for processes with PCPU higher than indicated."));
795 printf (" %s\n", "-u, --user=USER"); 776 printf(" %s\n", "-u, --user=USER");
796 printf (" %s\n", _("Only scan for processes with user name or ID indicated.")); 777 printf(" %s\n", _("Only scan for processes with user name or ID indicated."));
797 printf (" %s\n", "-a, --argument-array=STRING"); 778 printf(" %s\n", "-a, --argument-array=STRING");
798 printf (" %s\n", _("Only scan for processes with args that contain STRING.")); 779 printf(" %s\n", _("Only scan for processes with args that contain STRING."));
799 printf (" %s\n", "--ereg-argument-array=STRING"); 780 printf(" %s\n", "--ereg-argument-array=STRING");
800 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING.")); 781 printf(" %s\n", _("Only scan for processes with args that contain the regex STRING."));
801 printf (" %s\n", "-C, --command=COMMAND"); 782 printf(" %s\n", "-C, --command=COMMAND");
802 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path).")); 783 printf(" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
803 printf (" %s\n", "-X, --exclude-process"); 784 printf(" %s\n", "-X, --exclude-process");
804 printf (" %s\n", _("Exclude processes which match this comma separated list")); 785 printf(" %s\n", _("Exclude processes which match this comma separated list"));
805 printf (" %s\n", "-k, --no-kthreads"); 786 printf(" %s\n", "-k, --no-kthreads");
806 printf (" %s\n", _("Only scan for non kernel threads (works on Linux only).")); 787 printf(" %s\n", _("Only scan for non kernel threads (works on Linux only)."));
807 788
808 printf(_("\n\ 789 printf(_("\n\
809RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\ 790RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
810specified 'max:min', a warning status will be generated if the\n\ 791specified 'max:min', a warning status will be generated if the\n\
811count is inside the specified range\n\n")); 792count is inside the specified range\n\n"));
812 793
813 printf(_("\ 794 printf(_("\
814This plugin checks the number of currently running processes and\n\ 795This plugin checks the number of currently running processes and\n\
815generates WARNING or CRITICAL states if the process count is outside\n\ 796generates WARNING or CRITICAL states if the process count is outside\n\
816the specified threshold ranges. The process count can be filtered by\n\ 797the specified threshold ranges. The process count can be filtered by\n\
817process owner, parent process PID, current state (e.g., 'Z'), or may\n\ 798process owner, parent process PID, current state (e.g., 'Z'), or may\n\
818be the total number of running processes\n\n")); 799be the total number of running processes\n\n"));
819 800
820 printf ("%s\n", _("Examples:")); 801 printf("%s\n", _("Examples:"));
821 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry"); 802 printf(" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
822 printf (" %s\n", _("Warning if not two processes with command name portsentry.")); 803 printf(" %s\n", _("Warning if not two processes with command name portsentry."));
823 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes")); 804 printf(" %s\n\n", _("Critical if < 2 or > 1024 processes"));
824 printf (" %s\n", "check_procs -c 1: -C sshd"); 805 printf(" %s\n", "check_procs -c 1: -C sshd");
825 printf (" %s\n", _("Critical if not at least 1 process with command sshd")); 806 printf(" %s\n", _("Critical if not at least 1 process with command sshd"));
826 printf (" %s\n", "check_procs -w 1024 -c 1: -C sshd"); 807 printf(" %s\n", "check_procs -w 1024 -c 1: -C sshd");
827 printf (" %s\n", _("Warning if > 1024 processes with command name sshd.")); 808 printf(" %s\n", _("Warning if > 1024 processes with command name sshd."));
828 printf (" %s\n\n", _("Critical if < 1 processes with command name sshd.")); 809 printf(" %s\n\n", _("Critical if < 1 processes with command name sshd."));
829 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root"); 810 printf(" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
830 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing")); 811 printf(" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
831 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root")); 812 printf(" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
832 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ"); 813 printf(" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
833 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K")); 814 printf(" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
834 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU"); 815 printf(" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
835 printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%")); 816 printf(" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
836 817
837 printf (UT_SUPPORT); 818 printf(UT_SUPPORT);
838} 819}
839 820
840void 821void print_usage(void) {
841print_usage (void) 822 printf("%s\n", _("Usage:"));
842{ 823 printf("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
843 printf ("%s\n", _("Usage:")); 824 printf(" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
844 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname); 825 printf(" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");
845 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
846 printf (" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");
847} 826}
diff --git a/plugins/check_procs.d/config.h b/plugins/check_procs.d/config.h
new file mode 100644
index 00000000..e32ca066
--- /dev/null
+++ b/plugins/check_procs.d/config.h
@@ -0,0 +1,75 @@
1#pragma once
2
3#include "../../config.h"
4#include "regex.h"
5#include "thresholds.h"
6#include <stddef.h>
7#include <string.h>
8#include <sys/types.h>
9
10enum metric {
11 METRIC_PROCS,
12 METRIC_VSZ,
13 METRIC_RSS,
14 METRIC_CPU,
15 METRIC_ELAPSED
16};
17
18typedef struct {
19 int options; /* bitmask of filter criteria to test against */
20 enum metric metric;
21 char *metric_name;
22 char *input_filename;
23 char *prog;
24 char *args;
25 char *fmt;
26 char *fails;
27 char *exclude_progs;
28 char **exclude_progs_arr;
29 char exclude_progs_counter;
30 regex_t re_args;
31
32 bool kthread_filter;
33 bool usepid; /* whether to test for pid or /proc/pid/exe */
34 uid_t uid;
35 pid_t ppid;
36 int vsz;
37 int rss;
38 float pcpu;
39 char *statopts;
40
41 char *warning_range;
42 char *critical_range;
43 thresholds *procs_thresholds;
44} check_procs_config;
45
46check_procs_config check_procs_config_init() {
47 check_procs_config tmp = {
48 .options = 0,
49 .metric = METRIC_PROCS,
50 .metric_name = strdup("PROCS"),
51 .input_filename = NULL,
52 .prog = NULL,
53 .args = NULL,
54 .fmt = NULL,
55 .fails = NULL,
56 .exclude_progs = NULL,
57 .exclude_progs_arr = NULL,
58 .exclude_progs_counter = 0,
59 .re_args = {0},
60
61 .kthread_filter = false,
62 .usepid = false,
63 .uid = 0,
64 .ppid = 0,
65 .vsz = 0,
66 .rss = 0,
67 .pcpu = 0,
68 .statopts = NULL,
69
70 .warning_range = NULL,
71 .critical_range = NULL,
72 .procs_thresholds = NULL,
73 };
74 return tmp;
75}
diff --git a/plugins/utils.h b/plugins/utils.h
index 92a6c115..1d3c153c 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -76,7 +76,7 @@ char *strnl(char *);
76char *strpcpy(char *, const char *, const char *); 76char *strpcpy(char *, const char *, const char *);
77char *strpcat(char *, const char *, const char *); 77char *strpcat(char *, const char *, const char *);
78int xvasprintf(char **strp, const char *fmt, va_list ap); 78int xvasprintf(char **strp, const char *fmt, va_list ap);
79int xasprintf(char **strp, const char *fmt, ...); 79int xasprintf(char **strp, const char *fmt, ...)__attribute__ ((format (printf, 2, 3)));
80 80
81void usage(const char *) __attribute__((noreturn)); 81void usage(const char *) __attribute__((noreturn));
82void usage2(const char *, const char *) __attribute__((noreturn)); 82void usage2(const char *, const char *) __attribute__((noreturn));