[monitoring-plugins] Refactor check_game

Lorenz Kästle git at monitoring-plugins.org
Sun Mar 9 23:50:11 CET 2025


 Module: monitoring-plugins
 Branch: master
 Commit: 9f8a485744ba8de13c01cc48a4db0d8d73189c97
 Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
   Date: Fri Mar  7 15:58:30 2025 +0100
    URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=9f8a4857

Refactor check_game

---

 plugins/check_game.c          | 211 ++++++++++++++++++++++--------------------
 plugins/check_game.d/config.h |  30 ++++++
 2 files changed, 139 insertions(+), 102 deletions(-)

diff --git a/plugins/check_game.c b/plugins/check_game.c
index 619277e7..58014c3e 100644
--- a/plugins/check_game.c
+++ b/plugins/check_game.c
@@ -36,9 +36,15 @@ const char *email = "devel at monitoring-plugins.org";
 #include "common.h"
 #include "utils.h"
 #include "runcmd.h"
+#include "check_game.d/config.h"
+#include "../lib/monitoringplug.h"
 
-static int process_arguments(int /*argc*/, char ** /*argv*/);
-static int validate_arguments(void);
+typedef struct {
+	int errorcode;
+	check_game_config config;
+} check_game_config_wrapper;
+
+static check_game_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
 static void print_help(void);
 void print_usage(void);
 
@@ -49,26 +55,9 @@ void print_usage(void);
 #define QSTAT_HOST_TIMEOUT    "TIMEOUT"
 #define QSTAT_MAX_RETURN_ARGS 12
 
-static char *server_ip;
-static char *game_type;
-static int port = 0;
-
 static bool verbose = false;
 
-static int qstat_game_players_max = -1;
-static int qstat_game_players = -1;
-static int qstat_game_field = -1;
-static int qstat_map_field = -1;
-static int qstat_ping_field = -1;
-
 int main(int argc, char **argv) {
-	char *command_line;
-	int result = STATE_UNKNOWN;
-	char *p;
-	char *ret[QSTAT_MAX_RETURN_ARGS];
-	size_t i = 0;
-	output chld_out;
-
 	setlocale(LC_ALL, "");
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	textdomain(PACKAGE);
@@ -76,22 +65,31 @@ 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_game_config_wrapper tmp = process_arguments(argc, argv);
+
+	if (tmp.errorcode == ERROR) {
 		usage_va(_("Could not parse arguments"));
+	}
 
-	result = STATE_OK;
+	check_game_config config = tmp.config;
+
+	mp_state_enum result = STATE_OK;
 
 	/* create the command line to execute */
-	xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
+	char *command_line = NULL;
+	xasprintf(&command_line, "%s -raw %s -%s %s", PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, config.game_type, config.server_ip);
 
-	if (port)
-		xasprintf(&command_line, "%s:%-d", command_line, port);
+	if (config.port) {
+		xasprintf(&command_line, "%s:%-d", command_line, config.port);
+	}
 
-	if (verbose)
+	if (verbose) {
 		printf("%s\n", command_line);
+	}
 
 	/* run the command. historically, this plugin ignores output on stderr,
 	 * as well as return status of the qstat program */
+	output chld_out = {};
 	(void)np_runcmd(command_line, &chld_out, NULL, 0);
 
 	/* sanity check */
@@ -104,19 +102,22 @@ int main(int argc, char **argv) {
 	   In the end, I figured I'd simply let an error occur & then trap it
 	 */
 
-	if (!strncmp(chld_out.line[0], "unknown option", 14)) {
+	if (!strncmp(chld_out.line[0], "unknown option", strlen("unknown option"))) {
 		printf(_("CRITICAL - Host type parameter incorrect!\n"));
 		result = STATE_CRITICAL;
-		return result;
+		exit(result);
 	}
 
-	p = (char *)strtok(chld_out.line[0], QSTAT_DATA_DELIMITER);
-	while (p != NULL) {
-		ret[i] = p;
-		p = (char *)strtok(NULL, QSTAT_DATA_DELIMITER);
+	char *ret[QSTAT_MAX_RETURN_ARGS];
+	size_t i = 0;
+	char *sequence = strtok(chld_out.line[0], QSTAT_DATA_DELIMITER);
+	while (sequence != NULL) {
+		ret[i] = sequence;
+		sequence = strtok(NULL, QSTAT_DATA_DELIMITER);
 		i++;
-		if (i >= QSTAT_MAX_RETURN_ARGS)
+		if (i >= QSTAT_MAX_RETURN_ARGS) {
 			break;
+		}
 	}
 
 	if (strstr(ret[2], QSTAT_HOST_ERROR)) {
@@ -129,18 +130,19 @@ int main(int argc, char **argv) {
 		printf(_("CRITICAL - Game server timeout\n"));
 		result = STATE_CRITICAL;
 	} else {
-		printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[qstat_game_players], ret[qstat_game_players_max], ret[qstat_game_field],
-			   ret[qstat_map_field], ret[qstat_ping_field],
-			   perfdata("players", atol(ret[qstat_game_players]), "", false, 0, false, 0, true, 0, true, atol(ret[qstat_game_players_max])),
-			   fperfdata("ping", strtod(ret[qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0));
+		printf("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", ret[config.qstat_game_players], ret[config.qstat_game_players_max], ret[config.qstat_game_field],
+			   ret[config.qstat_map_field], ret[config.qstat_ping_field],
+			   perfdata("players", atol(ret[config.qstat_game_players]), "", false, 0, false, 0, true, 0, true, atol(ret[config.qstat_game_players_max])),
+			   fperfdata("ping", strtod(ret[config.qstat_ping_field], NULL), "", false, 0, false, 0, true, 0, false, 0));
 	}
 
-	return result;
+	exit(result);
 }
 
-int process_arguments(int argc, char **argv) {
-	int c;
+#define players_field_index 129
+#define max_players_field_index 130
 
+check_game_config_wrapper process_arguments(int argc, char **argv) {
 	int opt_index = 0;
 	static struct option long_opts[] = {{"help", no_argument, 0, 'h'},
 										{"version", no_argument, 0, 'V'},
@@ -152,29 +154,38 @@ int process_arguments(int argc, char **argv) {
 										{"map-field", required_argument, 0, 'm'},
 										{"ping-field", required_argument, 0, 'p'},
 										{"game-field", required_argument, 0, 'g'},
-										{"players-field", required_argument, 0, 129},
-										{"max-players-field", required_argument, 0, 130},
+										{"players-field", required_argument, 0, players_field_index},
+										{"max-players-field", required_argument, 0, max_players_field_index},
 										{0, 0, 0, 0}};
 
-	if (argc < 2)
-		return ERROR;
+	check_game_config_wrapper result = {
+		.config = check_game_config_init(),
+		.errorcode = OK,
+	};
 
-	for (c = 1; c < argc; c++) {
-		if (strcmp("-mf", argv[c]) == 0)
-			strcpy(argv[c], "-m");
-		else if (strcmp("-pf", argv[c]) == 0)
-			strcpy(argv[c], "-p");
-		else if (strcmp("-gf", argv[c]) == 0)
-			strcpy(argv[c], "-g");
+	if (argc < 2) {
+		result.errorcode = ERROR;
+		return result;
+	}
+
+	for (int option_counter = 1; option_counter < argc; option_counter++) {
+		if (strcmp("-mf", argv[option_counter]) == 0) {
+			strcpy(argv[option_counter], "-m");
+		} else if (strcmp("-pf", argv[option_counter]) == 0) {
+			strcpy(argv[option_counter], "-p");
+		} else if (strcmp("-gf", argv[option_counter]) == 0) {
+			strcpy(argv[option_counter], "-g");
+		}
 	}
 
 	while (1) {
-		c = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
+		int option_index = getopt_long(argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
 
-		if (c == -1 || c == EOF)
+		if (option_index == -1 || option_index == EOF) {
 			break;
+		}
 
-		switch (c) {
+		switch (option_index) {
 		case 'h': /* help */
 			print_help();
 			exit(STATE_UNKNOWN);
@@ -188,79 +199,75 @@ int process_arguments(int argc, char **argv) {
 			timeout_interval = atoi(optarg);
 			break;
 		case 'H': /* hostname */
-			if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH)
+			if (strlen(optarg) >= MAX_HOST_ADDRESS_LENGTH) {
 				die(STATE_UNKNOWN, _("Input buffer overflow\n"));
-			server_ip = optarg;
+			}
+			result.config.server_ip = optarg;
 			break;
 		case 'P': /* port */
-			port = atoi(optarg);
+			result.config.port = atoi(optarg);
 			break;
 		case 'G': /* hostname */
-			if (strlen(optarg) >= MAX_INPUT_BUFFER)
+			if (strlen(optarg) >= MAX_INPUT_BUFFER) {
 				die(STATE_UNKNOWN, _("Input buffer overflow\n"));
-			game_type = optarg;
+			}
+			result.config.game_type = optarg;
 			break;
 		case 'p': /* index of ping field */
-			qstat_ping_field = atoi(optarg);
-			if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
-				return ERROR;
+			result.config.qstat_ping_field = atoi(optarg);
+			if (result.config.qstat_ping_field < 0 || result.config.qstat_ping_field > QSTAT_MAX_RETURN_ARGS) {
+				result.errorcode = ERROR;
+				return result;
+			}
 			break;
 		case 'm': /* index on map field */
-			qstat_map_field = atoi(optarg);
-			if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
-				return ERROR;
+			result.config.qstat_map_field = atoi(optarg);
+			if (result.config.qstat_map_field < 0 || result.config.qstat_map_field > QSTAT_MAX_RETURN_ARGS) {
+				result.errorcode = ERROR;
+				return result;
+			}
 			break;
 		case 'g': /* index of game field */
-			qstat_game_field = atoi(optarg);
-			if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
-				return ERROR;
+			result.config.qstat_game_field = atoi(optarg);
+			if (result.config.qstat_game_field < 0 || result.config.qstat_game_field > QSTAT_MAX_RETURN_ARGS) {
+				result.errorcode = ERROR;
+				return result;
+			}
 			break;
-		case 129: /* index of player count field */
-			qstat_game_players = atoi(optarg);
-			if (qstat_game_players_max == 0)
-				qstat_game_players_max = qstat_game_players - 1;
-			if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
-				return ERROR;
+		case players_field_index: /* index of player count field */
+			result.config.qstat_game_players = atoi(optarg);
+			if (result.config.qstat_game_players_max == 0) {
+				result.config.qstat_game_players_max = result.config.qstat_game_players - 1;
+			}
+			if (result.config.qstat_game_players < 0 || result.config.qstat_game_players > QSTAT_MAX_RETURN_ARGS) {
+				result.errorcode = ERROR;
+				return result;
+			}
 			break;
-		case 130: /* index of max players field */
-			qstat_game_players_max = atoi(optarg);
-			if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
-				return ERROR;
+		case max_players_field_index: /* index of max players field */
+			result.config.qstat_game_players_max = atoi(optarg);
+			if (result.config.qstat_game_players_max < 0 || result.config.qstat_game_players_max > QSTAT_MAX_RETURN_ARGS) {
+				result.errorcode = ERROR;
+				return result;
+			}
 			break;
 		default: /* args not parsable */
 			usage5();
 		}
 	}
 
-	c = optind;
+	int option_counter = optind;
 	/* first option is the game type */
-	if (!game_type && c < argc)
-		game_type = strdup(argv[c++]);
+	if (!result.config.game_type && option_counter < argc) {
+		result.config.game_type = strdup(argv[option_counter++]);
+	}
 
 	/* Second option is the server name */
-	if (!server_ip && c < argc)
-		server_ip = strdup(argv[c++]);
-
-	return validate_arguments();
-}
-
-int validate_arguments(void) {
-	if (qstat_game_players_max < 0)
-		qstat_game_players_max = 4;
-
-	if (qstat_game_players < 0)
-		qstat_game_players = 5;
-
-	if (qstat_game_field < 0)
-		qstat_game_field = 2;
-
-	if (qstat_map_field < 0)
-		qstat_map_field = 3;
-
-	if (qstat_ping_field < 0)
-		qstat_ping_field = 5;
+	if (!result.config.server_ip && option_counter < argc) {
+		result.config.server_ip = strdup(argv[option_counter++]);
+	}
 
-	return OK;
+	return result;
 }
 
 void print_help(void) {
diff --git a/plugins/check_game.d/config.h b/plugins/check_game.d/config.h
new file mode 100644
index 00000000..c95a1ced
--- /dev/null
+++ b/plugins/check_game.d/config.h
@@ -0,0 +1,30 @@
+#pragma once
+#include "../../config.h"
+#include <stddef.h>
+
+typedef struct {
+	char *server_ip;
+	char *game_type;
+	int port;
+
+	int qstat_game_players_max;
+	int qstat_game_players;
+	int qstat_game_field;
+	int qstat_map_field;
+	int qstat_ping_field;
+} check_game_config;
+
+check_game_config check_game_config_init() {
+	check_game_config tmp = {
+		.server_ip = NULL,
+		.game_type = NULL,
+		.port = 0,
+
+		.qstat_game_players_max = 4,
+		.qstat_game_players = 5,
+		.qstat_map_field = 3,
+		.qstat_game_field = 2,
+		.qstat_ping_field = 5,
+	};
+	return tmp;
+}



More information about the Commits mailing list