[monitoring-plugins] Refactor check_nagios

Lorenz Kästle git at monitoring-plugins.org
Tue Mar 11 17:30:11 CET 2025


 Module: monitoring-plugins
 Branch: master
 Commit: b16360eede8d370698ba8836808a3b1dbd805edf
 Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
   Date: Tue Mar 11 16:18:03 2025 +0100
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=b16360ee

Refactor check_nagios

---

 plugins/Makefile.am             |   1 +
 plugins/check_nagios.c          | 134 +++++++++++++++++++++-------------------
 plugins/check_nagios.d/config.h |  19 ++++++
 3 files changed, 89 insertions(+), 65 deletions(-)

diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 1e4789ff..d27c9efd 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -53,6 +53,7 @@ EXTRA_DIST = t \
 			 check_ldap.d \
 			 check_hpjd.d \
 			 check_game.d \
+			 check_nagios.d \
 			 check_dbi.d \
 			 check_ssh.d \
 			 check_dns.d \
diff --git a/plugins/check_nagios.c b/plugins/check_nagios.c
index 72613f97..a46dc1ed 100644
--- a/plugins/check_nagios.c
+++ b/plugins/check_nagios.c
@@ -39,47 +39,20 @@ const char *email = "devel at monitoring-plugins.org";
 #include "common.h"
 #include "runcmd.h"
 #include "utils.h"
-
-static int process_arguments(int /*argc*/, char ** /*argv*/);
+#include "states.h"
+#include "check_nagios.d/config.h"
+
+typedef struct {
+	int errorcode;
+	check_nagios_config config;
+} check_nagios_config_wrapper;
+static check_nagios_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
 static void print_help(void);
 void print_usage(void);
 
-static char *status_log = NULL;
-static char *process_string = NULL;
-static int expire_minutes = 0;
-
 static int verbose = 0;
 
 int main(int argc, char **argv) {
-	int result = STATE_UNKNOWN;
-	char input_buffer[MAX_INPUT_BUFFER];
-	unsigned long latest_entry_time = 0L;
-	unsigned long temp_entry_time = 0L;
-	int proc_entries = 0;
-	time_t current_time;
-	char *temp_ptr;
-	FILE *fp;
-	int procuid = 0;
-	int procpid = 0;
-	int procppid = 0;
-	int procvsz = 0;
-	int procrss = 0;
-	float procpcpu = 0;
-	char procstat[8];
-#ifdef PS_USES_PROCETIME
-	char procetime[MAX_INPUT_BUFFER];
-#endif /* PS_USES_PROCETIME */
-	char procprog[MAX_INPUT_BUFFER];
-	char *procargs;
-	int pos;
-	int cols;
-	int expected_cols = PS_COLS - 1;
-	const char *zombie = "Z";
-	char *temp_string;
-	output chld_out;
-	output chld_err;
-	size_t i;
-
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
@@ -87,10 +60,14 @@ int main(int argc, char **argv) {
 	/* Parse extra opts if any */
 	argv = np_extra_opts(&argc, argv, progname);
 
-	if (process_arguments(argc, argv) == ERROR) {
+	check_nagios_config_wrapper tmp_config = process_arguments(argc, argv);
+
+	if (tmp_config.errorcode == ERROR) {
 		usage_va(_("Could not parse arguments"));
 	}
 
+	const check_nagios_config config = tmp_config.config;
+
 	/* Set signal handling and alarm timeout */
 	if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
 		usage_va(_("Cannot catch SIGALRM"));
@@ -100,13 +77,17 @@ int main(int argc, char **argv) {
 	alarm(timeout_interval);
 
 	/* open the status log */
-	fp = fopen(status_log, "r");
-	if (fp == NULL) {
+	FILE *log_file = fopen(config.status_log, "r");
+	if (log_file == NULL) {
 		die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
 	}
 
+	unsigned long latest_entry_time = 0L;
+	unsigned long temp_entry_time = 0L;
+	char input_buffer[MAX_INPUT_BUFFER];
+	char *temp_ptr;
 	/* get the date/time of the last item updated in the log */
-	while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
+	while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, log_file)) {
 		if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) {
 			temp_entry_time = strtoul(temp_ptr + 8, NULL, 10);
 			latest_entry_time = temp_entry_time;
@@ -119,20 +100,39 @@ int main(int argc, char **argv) {
 			}
 		}
 	}
-	fclose(fp);
+	fclose(log_file);
 
 	if (verbose >= 2) {
 		printf("command: %s\n", PS_COMMAND);
 	}
 
 	/* run the command to check for the Nagios process.. */
+	mp_state_enum result = STATE_UNKNOWN;
+	output chld_out;
+	output chld_err;
 	if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) {
 		result = STATE_WARNING;
 	}
 
+	int procuid = 0;
+	int procpid = 0;
+	int procppid = 0;
+	int procvsz = 0;
+	int procrss = 0;
+	int proc_entries = 0;
+	float procpcpu = 0;
+	char procstat[8];
+	char procprog[MAX_INPUT_BUFFER];
+	char *procargs;
+#ifdef PS_USES_PROCETIME
+	char procetime[MAX_INPUT_BUFFER];
+#endif /* PS_USES_PROCETIME */
+	int pos;
+	int expected_cols = PS_COLS - 1;
+	const char *zombie = "Z";
 	/* count the number of matching Nagios processes... */
-	for (i = 0; i < chld_out.lines; i++) {
-		cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
+	for (size_t i = 0; i < chld_out.lines; i++) {
+		int cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
 		/* Zombie processes do not give a procprog command */
 		if (cols == (expected_cols - 1) && strstr(procstat, zombie)) {
 			cols = expected_cols;
@@ -146,14 +146,14 @@ int main(int argc, char **argv) {
 			strip(procargs);
 
 			/* Some ps return full pathname for command. This removes path */
-			temp_string = strtok((char *)procprog, "/");
+			char *temp_string = strtok((char *)procprog, "/");
 			while (temp_string) {
 				strcpy(procprog, temp_string);
 				temp_string = strtok(NULL, "/");
 			}
 
 			/* May get empty procargs */
-			if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs, "")) {
+			if (!strstr(procargs, argv[0]) && strstr(procargs, config.process_string) && strcmp(procargs, "")) {
 				proc_entries++;
 				if (verbose >= 2) {
 					printf(_("Found process: %s %s\n"), procprog, procargs);
@@ -178,8 +178,9 @@ int main(int argc, char **argv) {
 		die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
 	}
 
+	time_t current_time;
 	time(&current_time);
-	if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
+	if ((int)(current_time - latest_entry_time) > (config.expire_minutes * 60)) {
 		result = STATE_WARNING;
 	} else {
 		result = STATE_OK;
@@ -192,42 +193,45 @@ int main(int argc, char **argv) {
 		   (int)(current_time - latest_entry_time));
 	printf("\n");
 
-	return result;
+	exit(result);
 }
 
 /* process command-line arguments */
-int process_arguments(int argc, char **argv) {
-	int c;
-
-	int option = 0;
+check_nagios_config_wrapper process_arguments(int argc, char **argv) {
 	static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'},
 									   {"command", required_argument, 0, 'C'},  {"timeout", optional_argument, 0, 't'},
 									   {"version", no_argument, 0, 'V'},        {"help", no_argument, 0, 'h'},
 									   {"verbose", no_argument, 0, 'v'},        {0, 0, 0, 0}};
 
+	check_nagios_config_wrapper result = {
+		.errorcode = OK,
+		.config = check_nagios_config_init(),
+	};
 	if (argc < 2) {
-		return ERROR;
+		result.errorcode = ERROR;
+		return result;
 	}
 
 	if (!is_option(argv[1])) {
-		status_log = argv[1];
+		result.config.status_log = argv[1];
 		if (is_intnonneg(argv[2])) {
-			expire_minutes = atoi(argv[2]);
+			result.config.expire_minutes = atoi(argv[2]);
 		} else {
 			die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
 		}
-		process_string = argv[3];
-		return OK;
+		result.config.process_string = argv[3];
+		return result;
 	}
 
-	while (1) {
-		c = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
+	int option = 0;
+	while (true) {
+		int option_index = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
 
-		if (c == -1 || c == EOF || c == 1) {
+		if (option_index == -1 || option_index == EOF || option_index == 1) {
 			break;
 		}
 
-		switch (c) {
+		switch (option_index) {
 		case 'h': /* help */
 			print_help();
 			exit(STATE_UNKNOWN);
@@ -235,14 +239,14 @@ int process_arguments(int argc, char **argv) {
 			print_revision(progname, NP_VERSION);
 			exit(STATE_UNKNOWN);
 		case 'F': /* status log */
-			status_log = optarg;
+			result.config.status_log = optarg;
 			break;
 		case 'C': /* command */
-			process_string = optarg;
+			result.config.process_string = optarg;
 			break;
 		case 'e': /* expiry time */
 			if (is_intnonneg(optarg)) {
-				expire_minutes = atoi(optarg);
+				result.config.expire_minutes = atoi(optarg);
 			} else {
 				die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
 			}
@@ -262,15 +266,15 @@ int process_arguments(int argc, char **argv) {
 		}
 	}
 
-	if (status_log == NULL) {
+	if (result.config.status_log == NULL) {
 		die(STATE_UNKNOWN, _("You must provide the status_log\n"));
 	}
 
-	if (process_string == NULL) {
+	if (result.config.process_string == NULL) {
 		die(STATE_UNKNOWN, _("You must provide a process string\n"));
 	}
 
-	return OK;
+	return result;
 }
 
 void print_help(void) {
diff --git a/plugins/check_nagios.d/config.h b/plugins/check_nagios.d/config.h
new file mode 100644
index 00000000..efe139f9
--- /dev/null
+++ b/plugins/check_nagios.d/config.h
@@ -0,0 +1,19 @@
+#pragma once
+
+#include "../../config.h"
+#include <stddef.h>
+
+typedef struct {
+	char *status_log;
+	char *process_string;
+	int expire_minutes;
+} check_nagios_config;
+
+check_nagios_config check_nagios_config_init() {
+	check_nagios_config tmp = {
+		.status_log = NULL,
+		.process_string = NULL,
+		.expire_minutes = 0,
+	};
+	return tmp;
+}



More information about the Commits mailing list