[monitoring-plugins] Refactor check_procs

Lorenz Kästle git at monitoring-plugins.org
Sun Jun 29 11:20:12 CEST 2025


 Module: monitoring-plugins
 Branch: master
 Commit: a14b2b35776c7550123ce58af571913eb9d7819f
 Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
   Date: Wed Mar 12 15:29:36 2025 +0100
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=a14b2b35

Refactor check_procs

---

 plugins/Makefile.am            |   1 +
 plugins/check_procs.c          | 335 ++++++++++++++++++++---------------------
 plugins/check_procs.d/config.h |  75 +++++++++
 3 files changed, 243 insertions(+), 168 deletions(-)

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 6c582a15..0920adce 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -63,6 +63,7 @@ EXTRA_DIST = t \
 			 check_mrtg.d \
 			 check_apt.d \
 			 check_pgsql.d \
+			 check_procs.d \
 			 check_by_ssh.d \
 			 check_smtp.d \
 			 check_mysql.d \
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 at monitoring-plugins.org";
 #include "utils_cmd.h"
 #include "regex.h"
 #include "states.h"
+#include "check_procs.d/config.h"
 
 #include <pwd.h>
 #include <errno.h>
@@ -52,17 +53,17 @@ const char *email = "devel at monitoring-plugins.org";
 #	include <sys/stat.h>
 #endif
 
-static int process_arguments(int /*argc*/, char ** /*argv*/);
-static int validate_arguments(void);
-static int convert_to_seconds(char * /*etime*/);
+typedef struct {
+	int errorcode;
+	check_procs_config config;
+} check_procs_config_wrapper;
+static check_procs_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
+static check_procs_config_wrapper validate_arguments(check_procs_config_wrapper /*config_wrapper*/);
+
+static int convert_to_seconds(char * /*etime*/, enum metric /*metric*/);
 static void print_help(void);
 void print_usage(void);
 
-static char *warning_range = NULL;
-static char *critical_range = NULL;
-static thresholds *procs_thresholds = NULL;
-
-static int options = 0; /* bitmask of filter criteria to test against */
 #define ALL           1
 #define STAT          2
 #define PPID          4
@@ -80,36 +81,7 @@ static int options = 0; /* bitmask of filter criteria to test against */
 	"kthreadd" /* the parent process of kernel threads:                                                                                    \
 		 ppid of procs are compared to pid of this proc*/
 
-/* Different metrics */
-char *metric_name;
-enum metric {
-	METRIC_PROCS,
-	METRIC_VSZ,
-	METRIC_RSS,
-	METRIC_CPU,
-	METRIC_ELAPSED
-};
-enum metric metric = METRIC_PROCS;
-
 static int verbose = 0;
-static uid_t uid;
-static pid_t ppid;
-static int vsz;
-static int rss;
-static float pcpu;
-static char *statopts;
-static char *prog;
-static char *exclude_progs;
-static char **exclude_progs_arr = NULL;
-static char exclude_progs_counter = 0;
-static char *args;
-static char *input_filename = NULL;
-static regex_t re_args;
-static char *fmt;
-static char *fails;
-static char tmp[MAX_INPUT_BUFFER];
-static bool kthread_filter = false;
-static bool usepid = false; /* whether to test for pid or /proc/pid/exe */
 
 static int stat_exe(const pid_t pid, struct stat *buf) {
 	char *path;
@@ -125,27 +97,27 @@ int main(int argc, char **argv) {
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
 
-	xasprintf(&metric_name, "PROCS");
-	metric = METRIC_PROCS;
-
 	/* Parse extra opts if any */
 	argv = np_extra_opts(&argc, argv, progname);
 
-	if (process_arguments(argc, argv) == ERROR) {
+	check_procs_config_wrapper tmp_config = process_arguments(argc, argv);
+	if (tmp_config.errorcode == ERROR) {
 		usage4(_("Could not parse arguments"));
 	}
 
+	check_procs_config config = tmp_config.config;
+
 	/* find ourself */
 	pid_t mypid = getpid();
 	pid_t myppid = getppid();
 	dev_t mydev = 0;
 	ino_t myino = 0;
 	struct stat statbuf;
-	if (usepid || stat_exe(mypid, &statbuf) == -1) {
+	if (config.usepid || stat_exe(mypid, &statbuf) == -1) {
 		/* usepid might have been set by -T */
-		usepid = true;
+		config.usepid = true;
 	} else {
-		usepid = false;
+		config.usepid = false;
 		mydev = statbuf.st_dev;
 		myino = statbuf.st_ino;
 	}
@@ -163,14 +135,14 @@ int main(int argc, char **argv) {
 	output chld_out;
 	output chld_err;
 	mp_state_enum result = STATE_UNKNOWN;
-	if (input_filename == NULL) {
+	if (config.input_filename == NULL) {
 		result = cmd_run(PS_COMMAND, &chld_out, &chld_err, 0);
 		if (chld_err.lines > 0) {
 			printf("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
 			exit(STATE_WARNING);
 		}
 	} else {
-		result = cmd_file_read(input_filename, &chld_out, 0);
+		result = cmd_file_read(config.input_filename, &chld_out, 0);
 	}
 
 	int pos; /* number of spaces before 'args' in `ps` output */
@@ -222,7 +194,7 @@ int main(int argc, char **argv) {
 			strcpy(procprog, base_name(procprog));
 
 			/* we need to convert the elapsed time to seconds */
-			procseconds = convert_to_seconds(procetime);
+			procseconds = convert_to_seconds(procetime, config.metric);
 
 			if (verbose >= 3) {
 				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) {
 
 			/* Ignore self */
 			int ret = 0;
-			if ((usepid && mypid == procpid) ||
-				(((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
+			if ((config.usepid && mypid == procpid) ||
+				(((!config.usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
 				 (ret == -1 && errno == ENOENT))) {
 				if (verbose >= 3) {
 					printf("not considering - is myself or gone\n");
@@ -256,10 +228,10 @@ int main(int argc, char **argv) {
 			}
 
 			/* Ignore excluded processes by name */
-			if (options & EXCLUDE_PROGS) {
+			if (config.options & EXCLUDE_PROGS) {
 				bool found = false;
-				for (int i = 0; i < (exclude_progs_counter); i++) {
-					if (!strcmp(procprog, exclude_progs_arr[i])) {
+				for (int i = 0; i < (config.exclude_progs_counter); i++) {
+					if (!strcmp(procprog, config.exclude_progs_arr[i])) {
 						found = true;
 					}
 				}
@@ -275,7 +247,7 @@ int main(int argc, char **argv) {
 			/* filter kernel threads (children of KTHREAD_PARENT)*/
 			/* TODO adapt for other OSes than GNU/Linux
 					sorry for not doing that, but I've no other OSes to test :-( */
-			if (kthread_filter) {
+			if (config.kthread_filter) {
 				/* get pid KTHREAD_PARENT */
 				if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT)) {
 					kthread_ppid = procpid;
@@ -289,38 +261,38 @@ int main(int argc, char **argv) {
 				}
 			}
 
-			if ((options & STAT) && (strstr(procstat, statopts))) {
+			if ((config.options & STAT) && (strstr(procstat, config.statopts))) {
 				resultsum |= STAT;
 			}
-			if ((options & ARGS) && procargs && (strstr(procargs, args) != NULL)) {
+			if ((config.options & ARGS) && procargs && (strstr(procargs, config.args) != NULL)) {
 				resultsum |= ARGS;
 			}
-			if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t)0, NULL, 0) == 0)) {
+			if ((config.options & EREG_ARGS) && procargs && (regexec(&config.re_args, procargs, (size_t)0, NULL, 0) == 0)) {
 				resultsum |= EREG_ARGS;
 			}
-			if ((options & PROG) && procprog && (strcmp(prog, procprog) == 0)) {
+			if ((config.options & PROG) && procprog && (strcmp(config.prog, procprog) == 0)) {
 				resultsum |= PROG;
 			}
-			if ((options & PPID) && (procppid == ppid)) {
+			if ((config.options & PPID) && (procppid == config.ppid)) {
 				resultsum |= PPID;
 			}
-			if ((options & USER) && (procuid == uid)) {
+			if ((config.options & USER) && (procuid == config.uid)) {
 				resultsum |= USER;
 			}
-			if ((options & VSZ) && (procvsz >= vsz)) {
+			if ((config.options & VSZ) && (procvsz >= config.vsz)) {
 				resultsum |= VSZ;
 			}
-			if ((options & RSS) && (procrss >= rss)) {
+			if ((config.options & RSS) && (procrss >= config.rss)) {
 				resultsum |= RSS;
 			}
-			if ((options & PCPU) && (procpcpu >= pcpu)) {
+			if ((config.options & PCPU) && (procpcpu >= config.pcpu)) {
 				resultsum |= PCPU;
 			}
 
 			found++;
 
 			/* Next line if filters not matched */
-			if (!(options == resultsum || options == ALL)) {
+			if (!(config.options == resultsum || config.options == ALL)) {
 				continue;
 			}
 
@@ -331,27 +303,27 @@ int main(int argc, char **argv) {
 			}
 
 			mp_state_enum temporary_result = STATE_OK;
-			if (metric == METRIC_VSZ) {
-				temporary_result = get_status((double)procvsz, procs_thresholds);
-			} else if (metric == METRIC_RSS) {
-				temporary_result = get_status((double)procrss, procs_thresholds);
+			if (config.metric == METRIC_VSZ) {
+				temporary_result = get_status((double)procvsz, config.procs_thresholds);
+			} else if (config.metric == METRIC_RSS) {
+				temporary_result = get_status((double)procrss, config.procs_thresholds);
 			}
 			/* TODO? float thresholds for --metric=CPU */
-			else if (metric == METRIC_CPU) {
-				temporary_result = get_status(procpcpu, procs_thresholds);
-			} else if (metric == METRIC_ELAPSED) {
-				temporary_result = get_status((double)procseconds, procs_thresholds);
+			else if (config.metric == METRIC_CPU) {
+				temporary_result = get_status(procpcpu, config.procs_thresholds);
+			} else if (config.metric == METRIC_ELAPSED) {
+				temporary_result = get_status((double)procseconds, config.procs_thresholds);
 			}
 
-			if (metric != METRIC_PROCS) {
+			if (config.metric != METRIC_PROCS) {
 				if (temporary_result == STATE_WARNING) {
 					warn++;
-					xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+					xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
 					result = max_state(result, temporary_result);
 				}
 				if (temporary_result == STATE_CRITICAL) {
 					crit++;
-					xasprintf(&fails, "%s%s%s", fails, (strcmp(fails, "") ? ", " : ""), procprog);
+					xasprintf(&config.fails, "%s%s%s", config.fails, (strcmp(config.fails, "") ? ", " : ""), procprog);
 					result = max_state(result, temporary_result);
 				}
 			}
@@ -372,35 +344,36 @@ int main(int argc, char **argv) {
 	}
 
 	/* Needed if procs found, but none match filter */
-	if (metric == METRIC_PROCS) {
-		result = max_state(result, get_status((double)procs, procs_thresholds));
+	if (config.metric == METRIC_PROCS) {
+		result = max_state(result, get_status((double)procs, config.procs_thresholds));
 	}
 
 	if (result == STATE_OK) {
-		printf("%s %s: ", metric_name, _("OK"));
+		printf("%s %s: ", config.metric_name, _("OK"));
 	} else if (result == STATE_WARNING) {
-		printf("%s %s: ", metric_name, _("WARNING"));
-		if (metric != METRIC_PROCS) {
+		printf("%s %s: ", config.metric_name, _("WARNING"));
+		if (config.metric != METRIC_PROCS) {
 			printf(_("%d warn out of "), warn);
 		}
 	} else if (result == STATE_CRITICAL) {
-		printf("%s %s: ", metric_name, _("CRITICAL"));
-		if (metric != METRIC_PROCS) {
+		printf("%s %s: ", config.metric_name, _("CRITICAL"));
+		if (config.metric != METRIC_PROCS) {
 			printf(_("%d crit, %d warn out of "), crit, warn);
 		}
 	}
 	printf(ngettext("%d process", "%d processes", (unsigned long)procs), procs);
 
-	if (strcmp(fmt, "") != 0) {
-		printf(_(" with %s"), fmt);
+	if (strcmp(config.fmt, "") != 0) {
+		printf(_(" with %s"), config.fmt);
 	}
 
-	if (verbose >= 1 && strcmp(fails, "")) {
-		printf(" [%s]", fails);
+	if (verbose >= 1 && strcmp(config.fails, "")) {
+		printf(" [%s]", config.fails);
 	}
 
-	if (metric == METRIC_PROCS) {
-		printf(" | procs=%d;%s;%s;0;", procs, warning_range ? warning_range : "", critical_range ? critical_range : "");
+	if (config.metric == METRIC_PROCS) {
+		printf(" | procs=%d;%s;%s;0;", procs, config.warning_range ? config.warning_range : "",
+			   config.critical_range ? config.critical_range : "");
 	} else {
 		printf(" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
 	}
@@ -410,7 +383,7 @@ int main(int argc, char **argv) {
 }
 
 /* process command-line arguments */
-int process_arguments(int argc, char **argv) {
+check_procs_config_wrapper process_arguments(int argc, char **argv) {
 	static struct option longopts[] = {{"warning", required_argument, 0, 'w'},
 									   {"critical", required_argument, 0, 'c'},
 									   {"metric", required_argument, 0, 'm'},
@@ -440,6 +413,11 @@ int process_arguments(int argc, char **argv) {
 		}
 	}
 
+	check_procs_config_wrapper result = {
+		.errorcode = OK,
+		.config = check_procs_config_init(),
+	};
+
 	while (true) {
 		int option = 0;
 		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) {
 			}
 			break;
 		case 'c': /* critical threshold */
-			critical_range = optarg;
+			result.config.critical_range = optarg;
 			break;
 		case 'w': /* warning threshold */
-			warning_range = optarg;
+			result.config.warning_range = optarg;
 			break;
-		case 'p': /* process id */
-			if (sscanf(optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
-				xasprintf(&fmt, "%s%sPPID = %d", (fmt ? fmt : ""), (options ? ", " : ""), ppid);
-				options |= PPID;
+		case 'p': { /* process id */
+			static char tmp[MAX_INPUT_BUFFER];
+			if (sscanf(optarg, "%d%[^0-9]", &result.config.ppid, tmp) == 1) {
+				xasprintf(&result.config.fmt, "%s%sPPID = %d", (result.config.fmt ? result.config.fmt : ""),
+						  (result.config.options ? ", " : ""), result.config.ppid);
+				result.config.options |= PPID;
 				break;
 			}
 			usage4(_("Parent Process ID must be an integer!"));
+		}
 		case 's': /* status */
-			if (statopts) {
+			if (result.config.statopts) {
 				break;
 			} else {
-				statopts = optarg;
+				result.config.statopts = optarg;
 			}
-			xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
-			options |= STAT;
+			xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), result.config.statopts);
+			result.config.options |= STAT;
 			break;
 		case 'u': /* user or user id */ {
 			struct passwd *pw;
 			if (is_integer(optarg)) {
-				uid = atoi(optarg);
-				pw = getpwuid(uid);
+				result.config.uid = atoi(optarg);
+				pw = getpwuid(result.config.uid);
 				/*  check to be sure user exists */
 				if (pw == NULL) {
 					usage2(_("UID was not found"), optarg);
@@ -502,56 +484,61 @@ int process_arguments(int argc, char **argv) {
 					usage2(_("User name was not found"), optarg);
 				}
 				/*  then get uid */
-				uid = pw->pw_uid;
+				result.config.uid = pw->pw_uid;
 			}
 
 			char *user = pw->pw_name;
-			xasprintf(&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""), uid, user);
-			options |= USER;
+			xasprintf(&result.config.fmt, "%s%sUID = %d (%s)", (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), result.config.uid, user);
+			result.config.options |= USER;
 		} break;
 		case 'C': /* command */
 			/* TODO: allow this to be passed in with --metric */
-			if (prog) {
+			if (result.config.prog) {
 				break;
 			} else {
-				prog = optarg;
+				result.config.prog = optarg;
 			}
-			xasprintf(&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), prog);
-			options |= PROG;
+			xasprintf(&result.config.fmt, _("%s%scommand name '%s'"), (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), result.config.prog);
+			result.config.options |= PROG;
 			break;
 		case 'X':
-			if (exclude_progs) {
+			if (result.config.exclude_progs) {
 				break;
 			} else {
-				exclude_progs = optarg;
+				result.config.exclude_progs = optarg;
 			}
-			xasprintf(&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""), exclude_progs);
-			char *tmp_pointer = strtok(exclude_progs, ",");
+			xasprintf(&result.config.fmt, _("%s%sexclude progs '%s'"), (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), result.config.exclude_progs);
+			char *tmp_pointer = strtok(result.config.exclude_progs, ",");
 
 			while (tmp_pointer) {
-				exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char *) * ++exclude_progs_counter);
-				exclude_progs_arr[exclude_progs_counter - 1] = tmp_pointer;
+				result.config.exclude_progs_arr =
+					realloc(result.config.exclude_progs_arr, sizeof(char *) * ++result.config.exclude_progs_counter);
+				result.config.exclude_progs_arr[result.config.exclude_progs_counter - 1] = tmp_pointer;
 				tmp_pointer = strtok(NULL, ",");
 			}
 
-			options |= EXCLUDE_PROGS;
+			result.config.options |= EXCLUDE_PROGS;
 			break;
 		case 'a': /* args (full path name with args) */
 			/* TODO: allow this to be passed in with --metric */
-			if (args) {
+			if (result.config.args) {
 				break;
 			} else {
-				args = optarg;
+				result.config.args = optarg;
 			}
-			xasprintf(&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
-			options |= ARGS;
+			xasprintf(&result.config.fmt, "%s%sargs '%s'", (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), result.config.args);
+			result.config.options |= ARGS;
 			break;
 		case CHAR_MAX + 1: {
 			int cflags = REG_NOSUB | REG_EXTENDED;
-			int err = regcomp(&re_args, optarg, cflags);
+			int err = regcomp(&result.config.re_args, optarg, cflags);
 			if (err != 0) {
 				char errbuf[MAX_INPUT_BUFFER];
-				regerror(err, &re_args, errbuf, MAX_INPUT_BUFFER);
+				regerror(err, &result.config.re_args, errbuf, MAX_INPUT_BUFFER);
 				die(STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
 			}
 			/* Strip off any | within the regex optarg */
@@ -563,119 +550,131 @@ int process_arguments(int argc, char **argv) {
 				}
 				index++;
 			}
-			xasprintf(&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
-			options |= EREG_ARGS;
+			xasprintf(&result.config.fmt, "%s%sregex args '%s'", (result.config.fmt ? result.config.fmt : ""),
+					  (result.config.options ? ", " : ""), temp_string);
+			result.config.options |= EREG_ARGS;
 		} break;
-		case 'r': /* RSS */
-			if (sscanf(optarg, "%d%[^0-9]", &rss, tmp) == 1) {
-				xasprintf(&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
-				options |= RSS;
+		case 'r': { /* RSS */
+			static char tmp[MAX_INPUT_BUFFER];
+			if (sscanf(optarg, "%d%[^0-9]", &result.config.rss, tmp) == 1) {
+				xasprintf(&result.config.fmt, "%s%sRSS >= %d", (result.config.fmt ? result.config.fmt : ""),
+						  (result.config.options ? ", " : ""), result.config.rss);
+				result.config.options |= RSS;
 				break;
 			}
 			usage4(_("RSS must be an integer!"));
-		case 'z': /* VSZ */
-			if (sscanf(optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
-				xasprintf(&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
-				options |= VSZ;
+		}
+		case 'z': { /* VSZ */
+			static char tmp[MAX_INPUT_BUFFER];
+			if (sscanf(optarg, "%d%[^0-9]", &result.config.vsz, tmp) == 1) {
+				xasprintf(&result.config.fmt, "%s%sVSZ >= %d", (result.config.fmt ? result.config.fmt : ""),
+						  (result.config.options ? ", " : ""), result.config.vsz);
+				result.config.options |= VSZ;
 				break;
 			}
 			usage4(_("VSZ must be an integer!"));
-		case 'P': /* PCPU */
+		}
+		case 'P': { /* PCPU */
 			/* TODO: -P 1.5.5 is accepted */
-			if (sscanf(optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
-				xasprintf(&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
-				options |= PCPU;
+			static char tmp[MAX_INPUT_BUFFER];
+			if (sscanf(optarg, "%f%[^0-9.]", &result.config.pcpu, tmp) == 1) {
+				xasprintf(&result.config.fmt, "%s%sPCPU >= %.2f", (result.config.fmt ? result.config.fmt : ""),
+						  (result.config.options ? ", " : ""), result.config.pcpu);
+				result.config.options |= PCPU;
 				break;
 			}
 			usage4(_("PCPU must be a float!"));
+		}
 		case 'm':
-			xasprintf(&metric_name, "%s", optarg);
+			xasprintf(&result.config.metric_name, "%s", optarg);
 			if (strcmp(optarg, "PROCS") == 0) {
-				metric = METRIC_PROCS;
+				result.config.metric = METRIC_PROCS;
 				break;
 			}
 			if (strcmp(optarg, "VSZ") == 0) {
-				metric = METRIC_VSZ;
+				result.config.metric = METRIC_VSZ;
 				break;
 			}
 			if (strcmp(optarg, "RSS") == 0) {
-				metric = METRIC_RSS;
+				result.config.metric = METRIC_RSS;
 				break;
 			}
 			if (strcmp(optarg, "CPU") == 0) {
-				metric = METRIC_CPU;
+				result.config.metric = METRIC_CPU;
 				break;
 			}
 			if (strcmp(optarg, "ELAPSED") == 0) {
-				metric = METRIC_ELAPSED;
+				result.config.metric = METRIC_ELAPSED;
 				break;
 			}
 
 			usage4(_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
 		case 'k': /* linux kernel thread filter */
-			kthread_filter = true;
+			result.config.kthread_filter = true;
 			break;
 		case 'v': /* command */
 			verbose++;
 			break;
 		case 'T':
-			usepid = true;
+			result.config.usepid = true;
 			break;
 		case CHAR_MAX + 2:
-			input_filename = optarg;
+			result.config.input_filename = optarg;
 			break;
 		}
 	}
 
 	int index = optind;
-	if ((!warning_range) && argv[index]) {
-		warning_range = argv[index++];
+	if ((!result.config.warning_range) && argv[index]) {
+		result.config.warning_range = argv[index++];
 	}
-	if ((!critical_range) && argv[index]) {
-		critical_range = argv[index++];
+	if ((!result.config.critical_range) && argv[index]) {
+		result.config.critical_range = argv[index++];
 	}
-	if (statopts == NULL && argv[index]) {
-		xasprintf(&statopts, "%s", argv[index++]);
-		xasprintf(&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
-		options |= STAT;
+	if (result.config.statopts == NULL && argv[index]) {
+		xasprintf(&result.config.statopts, "%s", argv[index++]);
+		xasprintf(&result.config.fmt, _("%s%sSTATE = %s"), (result.config.fmt ? result.config.fmt : ""),
+				  (result.config.options ? ", " : ""), result.config.statopts);
+		result.config.options |= STAT;
 	}
 
 	/* this will abort in case of invalid ranges */
-	set_thresholds(&procs_thresholds, warning_range, critical_range);
+	set_thresholds(&result.config.procs_thresholds, result.config.warning_range, result.config.critical_range);
 
-	return validate_arguments();
+	return validate_arguments(result);
 }
 
-int validate_arguments() {
-	if (options == 0) {
-		options = ALL;
+check_procs_config_wrapper validate_arguments(check_procs_config_wrapper config_wrapper) {
+	if (config_wrapper.config.options == 0) {
+		config_wrapper.config.options = ALL;
 	}
 
-	if (statopts == NULL) {
-		statopts = strdup("");
+	if (config_wrapper.config.statopts == NULL) {
+		config_wrapper.config.statopts = strdup("");
 	}
 
-	if (prog == NULL) {
-		prog = strdup("");
+	if (config_wrapper.config.prog == NULL) {
+		config_wrapper.config.prog = strdup("");
 	}
 
-	if (args == NULL) {
-		args = strdup("");
+	if (config_wrapper.config.args == NULL) {
+		config_wrapper.config.args = strdup("");
 	}
 
-	if (fmt == NULL) {
-		fmt = strdup("");
+	if (config_wrapper.config.fmt == NULL) {
+		config_wrapper.config.fmt = strdup("");
 	}
 
-	if (fails == NULL) {
-		fails = strdup("");
+	if (config_wrapper.config.fails == NULL) {
+		config_wrapper.config.fails = strdup("");
 	}
 
-	return options;
+	// return options;
+	return config_wrapper;
 }
 
 /* convert the elapsed time to seconds */
-int convert_to_seconds(char *etime) {
+int convert_to_seconds(char *etime, enum metric metric) {
 	int hyphcnt = 0;
 	int coloncnt = 0;
 	for (char *ptr = etime; *ptr != '\0'; ptr++) {
diff --git a/plugins/check_procs.d/config.h b/plugins/check_procs.d/config.h
new file mode 100644
index 00000000..815809d4
--- /dev/null
+++ b/plugins/check_procs.d/config.h
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "../../config.h"
+#include "regex.h"
+#include "thresholds.h"
+#include <stddef.h>
+#include <string.h>
+#include <sys/types.h>
+
+enum metric {
+	METRIC_PROCS,
+	METRIC_VSZ,
+	METRIC_RSS,
+	METRIC_CPU,
+	METRIC_ELAPSED
+};
+
+typedef struct {
+	int options; /* bitmask of filter criteria to test against */
+	enum metric metric;
+	char *metric_name;
+	char *input_filename;
+	char *prog;
+	char *args;
+	char *fmt;
+	char *fails;
+	char *exclude_progs;
+	char **exclude_progs_arr;
+	char exclude_progs_counter;
+	regex_t re_args;
+
+	bool kthread_filter;
+	bool usepid; /* whether to test for pid or /proc/pid/exe */
+	uid_t uid;
+	pid_t ppid;
+	int vsz;
+	int rss;
+	float pcpu;
+	char *statopts;
+
+	char *warning_range;
+	char *critical_range;
+	thresholds *procs_thresholds;
+} check_procs_config;
+
+check_procs_config check_procs_config_init() {
+	check_procs_config tmp = {
+		.options = 0,
+		.metric = METRIC_PROCS,
+		.metric_name = strdup("PROCS"),
+		.input_filename = NULL,
+		.prog = NULL,
+		.args = NULL,
+		.fmt = NULL,
+		.fails = NULL,
+		.exclude_progs = NULL,
+		.exclude_progs_arr = NULL,
+		.exclude_progs_counter = 0,
+		.re_args = {},
+
+		.kthread_filter = false,
+		.usepid = false,
+		.uid = {},
+		.ppid = {},
+		.vsz = 0,
+		.rss = 0,
+		.pcpu = 0,
+		.statopts = NULL,
+
+		.warning_range = NULL,
+		.critical_range = NULL,
+		.procs_thresholds = NULL,
+	};
+	return tmp;
+}



More information about the Commits mailing list