summaryrefslogtreecommitdiffstats
path: root/plugins/check_procs.c
diff options
context:
space:
mode:
authorLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-12 15:29:36 +0100
committerLorenz Kästle <12514511+RincewindsHat@users.noreply.github.com>2025-03-12 15:29:36 +0100
commita14b2b35776c7550123ce58af571913eb9d7819f (patch)
treea05aaaea732402ec4d886935564108811ef67eee /plugins/check_procs.c
parent16c3e2499309af654bcf92a4cc516521122e8d66 (diff)
downloadmonitoring-plugins-a14b2b35776c7550123ce58af571913eb9d7819f.tar.gz
Refactor check_procs
Diffstat (limited to 'plugins/check_procs.c')
-rw-r--r--plugins/check_procs.c335
1 files changed, 167 insertions, 168 deletions
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index da2198a7..83e6864e 100644
--- a/plugins/check_procs.c
+++ b/plugins/check_procs.c
@@ -44,6 +44,7 @@ const char *email = "devel@monitoring-plugins.org";
44#include "utils_cmd.h" 44#include "utils_cmd.h"
45#include "regex.h" 45#include "regex.h"
46#include "states.h" 46#include "states.h"
47#include "check_procs.d/config.h"
47 48
48#include <pwd.h> 49#include <pwd.h>
49#include <errno.h> 50#include <errno.h>
@@ -52,17 +53,17 @@ const char *email = "devel@monitoring-plugins.org";
52# include <sys/stat.h> 53# include <sys/stat.h>
53#endif 54#endif
54 55
55static int process_arguments(int /*argc*/, char ** /*argv*/); 56typedef struct {
56static int validate_arguments(void); 57 int errorcode;
57static int convert_to_seconds(char * /*etime*/); 58 check_procs_config config;
59} check_procs_config_wrapper;
60static check_procs_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
61static check_procs_config_wrapper validate_arguments(check_procs_config_wrapper /*config_wrapper*/);
62
63static int convert_to_seconds(char * /*etime*/, enum metric /*metric*/);
58static void print_help(void); 64static void print_help(void);
59void print_usage(void); 65void print_usage(void);
60 66
61static char *warning_range = NULL;
62static char *critical_range = NULL;
63static thresholds *procs_thresholds = NULL;
64
65static int options = 0; /* bitmask of filter criteria to test against */
66#define ALL 1 67#define ALL 1
67#define STAT 2 68#define STAT 2
68#define PPID 4 69#define PPID 4
@@ -80,36 +81,7 @@ static int options = 0; /* bitmask of filter criteria to test against */
80 "kthreadd" /* the parent process of kernel threads: \ 81 "kthreadd" /* the parent process of kernel threads: \
81 ppid of procs are compared to pid of this proc*/ 82 ppid of procs are compared to pid of this proc*/
82 83
83/* Different metrics */
84char *metric_name;
85enum metric {
86 METRIC_PROCS,
87 METRIC_VSZ,
88 METRIC_RSS,
89 METRIC_CPU,
90 METRIC_ELAPSED
91};
92enum metric metric = METRIC_PROCS;
93
94static int verbose = 0; 84static int verbose = 0;
95static uid_t uid;
96static pid_t ppid;
97static int vsz;
98static int rss;
99static float pcpu;
100static char *statopts;
101static char *prog;
102static char *exclude_progs;
103static char **exclude_progs_arr = NULL;
104static char exclude_progs_counter = 0;
105static char *args;
106static char *input_filename = NULL;
107static regex_t re_args;
108static char *fmt;
109static char *fails;
110static char tmp[MAX_INPUT_BUFFER];
111static bool kthread_filter = false;
112static bool usepid = false; /* whether to test for pid or /proc/pid/exe */
113 85
114static int stat_exe(const pid_t pid, struct stat *buf) { 86static int stat_exe(const pid_t pid, struct stat *buf) {
115 char *path; 87 char *path;
@@ -125,27 +97,27 @@ int main(int argc, char **argv) {
125 bindtextdomain(PACKAGE, LOCALEDIR); 97 bindtextdomain(PACKAGE, LOCALEDIR);
126 textdomain(PACKAGE); 98 textdomain(PACKAGE);
127 99
128 xasprintf(&metric_name, "PROCS");
129 metric = METRIC_PROCS;
130
131 /* Parse extra opts if any */ 100 /* Parse extra opts if any */
132 argv = np_extra_opts(&argc, argv, progname); 101 argv = np_extra_opts(&argc, argv, progname);
133 102
134 if (process_arguments(argc, argv) == ERROR) { 103 check_procs_config_wrapper tmp_config = process_arguments(argc, argv);
104 if (tmp_config.errorcode == ERROR) {
135 usage4(_("Could not parse arguments")); 105 usage4(_("Could not parse arguments"));
136 } 106 }
137 107
108 check_procs_config config = tmp_config.config;
109
138 /* find ourself */ 110 /* find ourself */
139 pid_t mypid = getpid(); 111 pid_t mypid = getpid();
140 pid_t myppid = getppid(); 112 pid_t myppid = getppid();
141 dev_t mydev = 0; 113 dev_t mydev = 0;
142 ino_t myino = 0; 114 ino_t myino = 0;
143 struct stat statbuf; 115 struct stat statbuf;
144 if (usepid || stat_exe(mypid, &statbuf) == -1) { 116 if (config.usepid || stat_exe(mypid, &statbuf) == -1) {
145 /* usepid might have been set by -T */ 117 /* usepid might have been set by -T */
146 usepid = true; 118 config.usepid = true;
147 } else { 119 } else {
148 usepid = false; 120 config.usepid = false;
149 mydev = statbuf.st_dev; 121 mydev = statbuf.st_dev;
150 myino = statbuf.st_ino; 122 myino = statbuf.st_ino;
151 } 123 }
@@ -163,14 +135,14 @@ int main(int argc, char **argv) {
163 output chld_out; 135 output chld_out;
164 output chld_err; 136 output chld_err;
165 mp_state_enum result = STATE_UNKNOWN; 137 mp_state_enum result = STATE_UNKNOWN;
166 if (input_filename == NULL) { 138 if (config.input_filename == NULL) {
167 result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0); 139 result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
168 if (chld_err.lines > 0) { 140 if (chld_err.lines > 0) {
169 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]);
170 exit(STATE_WARNING); 142 exit(STATE_WARNING);
171 } 143 }
172 } else { 144 } else {
173 result = cmd_file_read(input_filename, &chld_out, 0); 145 result = cmd_file_read(config.input_filename, &chld_out, 0);
174 } 146 }
175 147
176 int pos; /* number of spaces before 'args' in `ps` output */ 148 int pos; /* number of spaces before 'args' in `ps` output */
@@ -222,7 +194,7 @@ int main(int argc, char **argv) {
222 strcpy(procprog, base_name(procprog)); 194 strcpy(procprog, base_name(procprog));
223 195
224 /* we need to convert the elapsed time to seconds */ 196 /* we need to convert the elapsed time to seconds */
225 procseconds = convert_to_seconds(procetime); 197 procseconds = convert_to_seconds(procetime, config.metric);
226 198
227 if (verbose >= 3) { 199 if (verbose >= 3) {
228 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, 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,
@@ -231,8 +203,8 @@ int main(int argc, char **argv) {
231 203
232 /* Ignore self */ 204 /* Ignore self */
233 int ret = 0; 205 int ret = 0;
234 if ((usepid && mypid == procpid) || 206 if ((config.usepid && mypid == procpid) ||
235 (((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) || 207 (((!config.usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
236 (ret == -1 && errno == ENOENT))) { 208 (ret == -1 && errno == ENOENT))) {
237 if (verbose >= 3) { 209 if (verbose >= 3) {
238 printf("not considering - is myself or gone\n"); 210 printf("not considering - is myself or gone\n");
@@ -256,10 +228,10 @@ int main(int argc, char **argv) {
256 } 228 }
257 229
258 /* Ignore excluded processes by name */ 230 /* Ignore excluded processes by name */
259 if (options & EXCLUDE_PROGS) { 231 if (config.options & EXCLUDE_PROGS) {
260 bool found = false; 232 bool found = false;
261 for (int i = 0; i < (exclude_progs_counter); i++) { 233 for (int i = 0; i < (config.exclude_progs_counter); i++) {
262 if (!strcmp(procprog, exclude_progs_arr[i])) { 234 if (!strcmp(procprog, config.exclude_progs_arr[i])) {
263 found = true; 235 found = true;
264 } 236 }
265 } 237 }
@@ -275,7 +247,7 @@ int main(int argc, char **argv) {
275 /* filter kernel threads (children of KTHREAD_PARENT)*/ 247 /* filter kernel threads (children of KTHREAD_PARENT)*/
276 /* TODO adapt for other OSes than GNU/Linux 248 /* TODO adapt for other OSes than GNU/Linux
277 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 :-( */
278 if (kthread_filter) { 250 if (config.kthread_filter) {
279 /* get pid KTHREAD_PARENT */ 251 /* get pid KTHREAD_PARENT */
280 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) { 252 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
281 kthread_ppid = procpid; 253 kthread_ppid = procpid;
@@ -289,38 +261,38 @@ int main(int argc, char **argv) {
289 } 261 }
290 } 262 }
291 263
292 if ((options & STAT) && (strstr(procstat, statopts))) { 264 if ((config.options & STAT) && (strstr(procstat, config.statopts))) {
293 resultsum |= STAT; 265 resultsum |= STAT;
294 } 266 }
295 if ((options & ARGS) && procargs && (strstr(procargs, args) != NULL)) { 267 if ((config.options & ARGS) && procargs && (strstr(procargs, config.args) != NULL)) {
296 resultsum |= ARGS; 268 resultsum |= ARGS;
297 } 269 }
298 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t)0, NULL, 0) == 0)) { 270 if ((config.options & EREG_ARGS) && procargs && (regexec(&config.re_args, procargs, (size_t)0, NULL, 0) == 0)) {
299 resultsum |= EREG_ARGS; 271 resultsum |= EREG_ARGS;
300 } 272 }
301 if ((options & PROG) && procprog && (strcmp(prog, procprog) == 0)) { 273 if ((config.options & PROG) && procprog && (strcmp(config.prog, procprog) == 0)) {
302 resultsum |= PROG; 274 resultsum |= PROG;
303 } 275 }
304 if ((options & PPID) && (procppid == ppid)) { 276 if ((config.options & PPID) && (procppid == config.ppid)) {
305 resultsum |= PPID; 277 resultsum |= PPID;
306 } 278 }
307 if ((options & USER) && (procuid == uid)) { 279 if ((config.options & USER) && (procuid == config.uid)) {
308 resultsum |= USER; 280 resultsum |= USER;
309 } 281 }
310 if ((options & VSZ) && (procvsz >= vsz)) { 282 if ((config.options & VSZ) && (procvsz >= config.vsz)) {
311 resultsum |= VSZ; 283 resultsum |= VSZ;
312 } 284 }
313 if ((options & RSS) && (procrss >= rss)) { 285 if ((config.options & RSS) && (procrss >= config.rss)) {
314 resultsum |= RSS; 286 resultsum |= RSS;
315 } 287 }
316 if ((options & PCPU) && (procpcpu >= pcpu)) { 288 if ((config.options & PCPU) && (procpcpu >= config.pcpu)) {
317 resultsum |= PCPU; 289 resultsum |= PCPU;
318 } 290 }
319 291
320 found++; 292 found++;
321 293
322 /* Next line if filters not matched */ 294 /* Next line if filters not matched */
323 if (!(options == resultsum || options == ALL)) { 295 if (!(config.options == resultsum || config.options == ALL)) {
324 continue; 296 continue;
325 } 297 }
326 298
@@ -331,27 +303,27 @@ int main(int argc, char **argv) {
331 } 303 }
332 304
333 mp_state_enum temporary_result = STATE_OK; 305 mp_state_enum temporary_result = STATE_OK;
334 if (metric == METRIC_VSZ) { 306 if (config.metric == METRIC_VSZ) {
335 temporary_result = get_status((double)procvsz, procs_thresholds); 307 temporary_result = get_status((double)procvsz, config.procs_thresholds);
336 } else if (metric == METRIC_RSS) { 308 } else if (config.metric == METRIC_RSS) {
337 temporary_result = get_status((double)procrss, procs_thresholds); 309 temporary_result = get_status((double)procrss, config.procs_thresholds);
338 } 310 }
339 /* TODO? float thresholds for --metric=CPU */ 311 /* TODO? float thresholds for --metric=CPU */
340 else if (metric == METRIC_CPU) { 312 else if (config.metric == METRIC_CPU) {
341 temporary_result = get_status(procpcpu, procs_thresholds); 313 temporary_result = get_status(procpcpu, config.procs_thresholds);
342 } else if (metric == METRIC_ELAPSED) { 314 } else if (config.metric == METRIC_ELAPSED) {
343 temporary_result = get_status((double)procseconds, procs_thresholds); 315 temporary_result = get_status((double)procseconds, config.procs_thresholds);
344 } 316 }
345 317
346 if (metric != METRIC_PROCS) { 318 if (config.metric != METRIC_PROCS) {
347 if (temporary_result == STATE_WARNING) { 319 if (temporary_result == STATE_WARNING) {
348 warn++; 320 warn++;
349 xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog); 321 xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
350 result = max_state(result, temporary_result); 322 result = max_state(result, temporary_result);
351 } 323 }
352 if (temporary_result == STATE_CRITICAL) { 324 if (temporary_result == STATE_CRITICAL) {
353 crit++; 325 crit++;
354 xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog); 326 xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
355 result = max_state(result, temporary_result); 327 result = max_state(result, temporary_result);
356 } 328 }
357 } 329 }
@@ -372,35 +344,36 @@ int main(int argc, char **argv) {
372 } 344 }
373 345
374 /* Needed if procs found, but none match filter */ 346 /* Needed if procs found, but none match filter */
375 if (metric == METRIC_PROCS) { 347 if (config.metric == METRIC_PROCS) {
376 result = max_state(result, get_status((double)procs, procs_thresholds)); 348 result = max_state(result, get_status((double)procs, config.procs_thresholds));
377 } 349 }
378 350
379 if (result == STATE_OK) { 351 if (result == STATE_OK) {
380 printf("%s %s: ", metric_name, _("OK")); 352 printf("%s %s: ", config.metric_name, _("OK"));
381 } else if (result == STATE_WARNING) { 353 } else if (result == STATE_WARNING) {
382 printf("%s %s: ", metric_name, _("WARNING")); 354 printf("%s %s: ", config.metric_name, _("WARNING"));
383 if (metric != METRIC_PROCS) { 355 if (config.metric != METRIC_PROCS) {
384 printf(_("%d warn out of "), warn); 356 printf(_("%d warn out of "), warn);
385 } 357 }
386 } else if (result == STATE_CRITICAL) { 358 } else if (result == STATE_CRITICAL) {
387 printf("%s %s: ", metric_name, _("CRITICAL")); 359 printf("%s %s: ", config.metric_name, _("CRITICAL"));
388 if (metric != METRIC_PROCS) { 360 if (config.metric != METRIC_PROCS) {
389 printf(_("%d crit, %d warn out of "), crit, warn); 361 printf(_("%d crit, %d warn out of "), crit, warn);
390 } 362 }
391 } 363 }
392 printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs); 364 printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs);
393 365
394 if (strcmp(fmt, "") != 0) { 366 if (strcmp(config.fmt, "") != 0) {
395 printf(_(" with %s"), fmt); 367 printf(_(" with %s"), config.fmt);
396 } 368 }
397 369
398 if (verbose >= 1 && strcmp(fails, "")) { 370 if (verbose >= 1 && strcmp(config.fails, "")) {
399 printf(" [%s]", fails); 371 printf(" [%s]", config.fails);
400 } 372 }
401 373
402 if (metric == METRIC_PROCS) { 374 if (config.metric == METRIC_PROCS) {
403 printf(" | procs=%d;%s;%s;0;", procs, warning_range ? warning_range : "", critical_range ? critical_range : ""); 375 printf(" | procs=%d;%s;%s;0;", procs, config.warning_range ? config.warning_range : "",
376 config.critical_range ? config.critical_range : "");
404 } else { 377 } else {
405 printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit); 378 printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
406 } 379 }
@@ -410,7 +383,7 @@ int main(int argc, char **argv) {
410} 383}
411 384
412/* process command-line arguments */ 385/* process command-line arguments */
413int process_arguments(int argc, char **argv) { 386check_procs_config_wrapper process_arguments(int argc, char **argv) {
414 static struct option longopts[] = {{"warning", required_argument, 0, 'w'}, 387 static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
415 {"critical", required_argument, 0, 'c'}, 388 {"critical", required_argument, 0, 'c'},
416 {"metric", required_argument, 0, 'm'}, 389 {"metric", required_argument, 0, 'm'},
@@ -440,6 +413,11 @@ int process_arguments(int argc, char **argv) {
440 } 413 }
441 } 414 }
442 415
416 check_procs_config_wrapper result = {
417 .errorcode = OK,
418 .config = check_procs_config_init(),
419 };
420
443 while (true) { 421 while (true) {
444 int option = 0; 422 int option = 0;
445 int option_index = getopt_long(argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:", 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);
@@ -465,32 +443,36 @@ int process_arguments(int argc, char **argv) {
465 } 443 }
466 break; 444 break;
467 case 'c': /* critical threshold */ 445 case 'c': /* critical threshold */
468 critical_range = optarg; 446 result.config.critical_range = optarg;
469 break; 447 break;
470 case 'w': /* warning threshold */ 448 case 'w': /* warning threshold */
471 warning_range = optarg; 449 result.config.warning_range = optarg;
472 break; 450 break;
473 case 'p': /* process id */ 451 case 'p': { /* process id */
474 if (sscanf(optarg, "%d%[^0-9]", &ppid, tmp) == 1) { 452 static char tmp[MAX_INPUT_BUFFER];
475 xasprintf(&fmt, "%s%sPPID = %d", (fmt ? fmt : ""), (options ? ", " : ""), ppid); 453 if (sscanf(optarg, "%d%[^0-9]", &result.config.ppid, tmp) == 1) {
476 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;
477 break; 457 break;
478 } 458 }
479 usage4(_("Parent Process ID must be an integer!")); 459 usage4(_("Parent Process ID must be an integer!"));
460 }
480 case 's': /* status */ 461 case 's': /* status */
481 if (statopts) { 462 if (result.config.statopts) {
482 break; 463 break;
483 } else { 464 } else {
484 statopts = optarg; 465 result.config.statopts = optarg;
485 } 466 }
486 xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); 467 xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
487 options |= STAT; 468 (result.config.options ? ", " : ""), result.config.statopts);
469 result.config.options |= STAT;
488 break; 470 break;
489 case 'u': /* user or user id */ { 471 case 'u': /* user or user id */ {
490 struct passwd *pw; 472 struct passwd *pw;
491 if (is_integer(optarg)) { 473 if (is_integer(optarg)) {
492 uid = atoi(optarg); 474 result.config.uid = atoi(optarg);
493 pw = getpwuid(uid); 475 pw = getpwuid(result.config.uid);
494 /* check to be sure user exists */ 476 /* check to be sure user exists */
495 if (pw == NULL) { 477 if (pw == NULL) {
496 usage2(_("UID was not found"), optarg); 478 usage2(_("UID was not found"), optarg);
@@ -502,56 +484,61 @@ int process_arguments(int argc, char **argv) {
502 usage2(_("User name was not found"), optarg); 484 usage2(_("User name was not found"), optarg);
503 } 485 }
504 /* then get uid */ 486 /* then get uid */
505 uid = pw->pw_uid; 487 result.config.uid = pw->pw_uid;
506 } 488 }
507 489
508 char *user = pw->pw_name; 490 char *user = pw->pw_name;
509 xasprintf(&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), uid, user); 491 xasprintf(&result.config.fmt, "%s%sUID = %d (%s)", (result.config.fmt ? result.config.fmt : ""),
510 options |= USER; 492 (result.config.options ? ", " : ""), result.config.uid, user);
493 result.config.options |= USER;
511 } break; 494 } break;
512 case 'C': /* command */ 495 case 'C': /* command */
513 /* TODO: allow this to be passed in with --metric */ 496 /* TODO: allow this to be passed in with --metric */
514 if (prog) { 497 if (result.config.prog) {
515 break; 498 break;
516 } else { 499 } else {
517 prog = optarg; 500 result.config.prog = optarg;
518 } 501 }
519 xasprintf(&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), prog); 502 xasprintf(&result.config.fmt, _("%s%scommand name '%s'"), (result.config.fmt ? result.config.fmt : ""),
520 options |= PROG; 503 (result.config.options ? ", " : ""), result.config.prog);
504 result.config.options |= PROG;
521 break; 505 break;
522 case 'X': 506 case 'X':
523 if (exclude_progs) { 507 if (result.config.exclude_progs) {
524 break; 508 break;
525 } else { 509 } else {
526 exclude_progs = optarg; 510 result.config.exclude_progs = optarg;
527 } 511 }
528 xasprintf(&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), exclude_progs); 512 xasprintf(&result.config.fmt, _("%s%sexclude progs '%s'"), (result.config.fmt ? result.config.fmt : ""),
529 char *tmp_pointer = strtok(exclude_progs, ","); 513 (result.config.options ? ", " : ""), result.config.exclude_progs);
514 char *tmp_pointer = strtok(result.config.exclude_progs, ",");
530 515
531 while (tmp_pointer) { 516 while (tmp_pointer) {
532 exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char *) * ++exclude_progs_counter); 517 result.config.exclude_progs_arr =
533 exclude_progs_arr[exclude_progs_counter - 1] = tmp_pointer; 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;
534 tmp_pointer = strtok(NULL, ","); 520 tmp_pointer = strtok(NULL, ",");
535 } 521 }
536 522
537 options |= EXCLUDE_PROGS; 523 result.config.options |= EXCLUDE_PROGS;
538 break; 524 break;
539 case 'a': /* args (full path name with args) */ 525 case 'a': /* args (full path name with args) */
540 /* TODO: allow this to be passed in with --metric */ 526 /* TODO: allow this to be passed in with --metric */
541 if (args) { 527 if (result.config.args) {
542 break; 528 break;
543 } else { 529 } else {
544 args = optarg; 530 result.config.args = optarg;
545 } 531 }
546 xasprintf(&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args); 532 xasprintf(&result.config.fmt, "%s%sargs '%s'", (result.config.fmt ? result.config.fmt : ""),
547 options |= ARGS; 533 (result.config.options ? ", " : ""), result.config.args);
534 result.config.options |= ARGS;
548 break; 535 break;
549 case CHAR_MAX + 1: { 536 case CHAR_MAX + 1: {
550 int cflags = REG_NOSUB | REG_EXTENDED; 537 int cflags = REG_NOSUB | REG_EXTENDED;
551 int err = regcomp(&re_args, optarg, cflags); 538 int err = regcomp(&result.config.re_args, optarg, cflags);
552 if (err != 0) { 539 if (err != 0) {
553 char errbuf[MAX_INPUT_BUFFER]; 540 char errbuf[MAX_INPUT_BUFFER];
554 regerror(err, &re_args, errbuf, MAX_INPUT_BUFFER); 541 regerror(err, &result.config.re_args, errbuf, MAX_INPUT_BUFFER);
555 die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf); 542 die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
556 } 543 }
557 /* Strip off any | within the regex optarg */ 544 /* Strip off any | within the regex optarg */
@@ -563,119 +550,131 @@ int process_arguments(int argc, char **argv) {
563 } 550 }
564 index++; 551 index++;
565 } 552 }
566 xasprintf(&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string); 553 xasprintf(&result.config.fmt, "%s%sregex args '%s'", (result.config.fmt ? result.config.fmt : ""),
567 options |= EREG_ARGS; 554 (result.config.options ? ", " : ""), temp_string);
555 result.config.options |= EREG_ARGS;
568 } break; 556 } break;
569 case 'r': /* RSS */ 557 case 'r': { /* RSS */
570 if (sscanf(optarg, "%d%[^0-9]", &rss, tmp) == 1) { 558 static char tmp[MAX_INPUT_BUFFER];
571 xasprintf(&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss); 559 if (sscanf(optarg, "%d%[^0-9]", &result.config.rss, tmp) == 1) {
572 options |= RSS; 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;
573 break; 563 break;
574 } 564 }
575 usage4(_("RSS must be an integer!")); 565 usage4(_("RSS must be an integer!"));
576 case 'z': /* VSZ */ 566 }
577 if (sscanf(optarg, "%d%[^0-9]", &vsz, tmp) == 1) { 567 case 'z': { /* VSZ */
578 xasprintf(&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz); 568 static char tmp[MAX_INPUT_BUFFER];
579 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;
580 break; 573 break;
581 } 574 }
582 usage4(_("VSZ must be an integer!")); 575 usage4(_("VSZ must be an integer!"));
583 case 'P': /* PCPU */ 576 }
577 case 'P': { /* PCPU */
584 /* TODO: -P 1.5.5 is accepted */ 578 /* TODO: -P 1.5.5 is accepted */
585 if (sscanf(optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) { 579 static char tmp[MAX_INPUT_BUFFER];
586 xasprintf(&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu); 580 if (sscanf(optarg, "%f%[^0-9.]", &result.config.pcpu, tmp) == 1) {
587 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;
588 break; 584 break;
589 } 585 }
590 usage4(_("PCPU must be a float!")); 586 usage4(_("PCPU must be a float!"));
587 }
591 case 'm': 588 case 'm':
592 xasprintf(&metric_name, "%s", optarg); 589 xasprintf(&result.config.metric_name, "%s", optarg);
593 if (strcmp(optarg, "PROCS") == 0) { 590 if (strcmp(optarg, "PROCS") == 0) {
594 metric = METRIC_PROCS; 591 result.config.metric = METRIC_PROCS;
595 break; 592 break;
596 } 593 }
597 if (strcmp(optarg, "VSZ") == 0) { 594 if (strcmp(optarg, "VSZ") == 0) {
598 metric = METRIC_VSZ; 595 result.config.metric = METRIC_VSZ;
599 break; 596 break;
600 } 597 }
601 if (strcmp(optarg, "RSS") == 0) { 598 if (strcmp(optarg, "RSS") == 0) {
602 metric = METRIC_RSS; 599 result.config.metric = METRIC_RSS;
603 break; 600 break;
604 } 601 }
605 if (strcmp(optarg, "CPU") == 0) { 602 if (strcmp(optarg, "CPU") == 0) {
606 metric = METRIC_CPU; 603 result.config.metric = METRIC_CPU;
607 break; 604 break;
608 } 605 }
609 if (strcmp(optarg, "ELAPSED") == 0) { 606 if (strcmp(optarg, "ELAPSED") == 0) {
610 metric = METRIC_ELAPSED; 607 result.config.metric = METRIC_ELAPSED;
611 break; 608 break;
612 } 609 }
613 610
614 usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!")); 611 usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
615 case 'k': /* linux kernel thread filter */ 612 case 'k': /* linux kernel thread filter */
616 kthread_filter = true; 613 result.config.kthread_filter = true;
617 break; 614 break;
618 case 'v': /* command */ 615 case 'v': /* command */
619 verbose++; 616 verbose++;
620 break; 617 break;
621 case 'T': 618 case 'T':
622 usepid = true; 619 result.config.usepid = true;
623 break; 620 break;
624 case CHAR_MAX + 2: 621 case CHAR_MAX + 2:
625 input_filename = optarg; 622 result.config.input_filename = optarg;
626 break; 623 break;
627 } 624 }
628 } 625 }
629 626
630 int index = optind; 627 int index = optind;
631 if ((!warning_range) && argv[index]) { 628 if ((!result.config.warning_range) && argv[index]) {
632 warning_range = argv[index++]; 629 result.config.warning_range = argv[index++];
633 } 630 }
634 if ((!critical_range) && argv[index]) { 631 if ((!result.config.critical_range) && argv[index]) {
635 critical_range = argv[index++]; 632 result.config.critical_range = argv[index++];
636 } 633 }
637 if (statopts == NULL && argv[index]) { 634 if (result.config.statopts == NULL && argv[index]) {
638 xasprintf(&statopts, "%s", argv[index++]); 635 xasprintf(&result.config.statopts, "%s", argv[index++]);
639 xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); 636 xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
640 options |= STAT; 637 (result.config.options ? ", " : ""), result.config.statopts);
638 result.config.options |= STAT;
641 } 639 }
642 640
643 /* this will abort in case of invalid ranges */ 641 /* this will abort in case of invalid ranges */
644 set_thresholds(&procs_thresholds, warning_range, critical_range); 642 set_thresholds(&result.config.procs_thresholds, result.config.warning_range, result.config.critical_range);
645 643
646 return validate_arguments(); 644 return validate_arguments(result);
647} 645}
648 646
649int validate_arguments() { 647check_procs_config_wrapper validate_arguments(check_procs_config_wrapper config_wrapper) {
650 if (options == 0) { 648 if (config_wrapper.config.options == 0) {
651 options = ALL; 649 config_wrapper.config.options = ALL;
652 } 650 }
653 651
654 if (statopts == NULL) { 652 if (config_wrapper.config.statopts == NULL) {
655 statopts = strdup(""); 653 config_wrapper.config.statopts = strdup("");
656 } 654 }
657 655
658 if (prog == NULL) { 656 if (config_wrapper.config.prog == NULL) {
659 prog = strdup(""); 657 config_wrapper.config.prog = strdup("");
660 } 658 }
661 659
662 if (args == NULL) { 660 if (config_wrapper.config.args == NULL) {
663 args = strdup(""); 661 config_wrapper.config.args = strdup("");
664 } 662 }
665 663
666 if (fmt == NULL) { 664 if (config_wrapper.config.fmt == NULL) {
667 fmt = strdup(""); 665 config_wrapper.config.fmt = strdup("");
668 } 666 }
669 667
670 if (fails == NULL) { 668 if (config_wrapper.config.fails == NULL) {
671 fails = strdup(""); 669 config_wrapper.config.fails = strdup("");
672 } 670 }
673 671
674 return options; 672 // return options;
673 return config_wrapper;
675} 674}
676 675
677/* convert the elapsed time to seconds */ 676/* convert the elapsed time to seconds */
678int convert_to_seconds(char *etime) { 677int convert_to_seconds(char *etime, enum metric metric) {
679 int hyphcnt = 0; 678 int hyphcnt = 0;
680 int coloncnt = 0; 679 int coloncnt = 0;
681 for (char *ptr = etime; *ptr != '\0'; ptr++) { 680 for (char *ptr = etime; *ptr != '\0'; ptr++) {