From 9f8a485744ba8de13c01cc48a4db0d8d73189c97 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Fri, 7 Mar 2025 15:58:30 +0100 Subject: Refactor check_game --- plugins/check_game.c | 211 ++++++++++++++++++++++-------------------- plugins/check_game.d/config.h | 30 ++++++ 2 files changed, 139 insertions(+), 102 deletions(-) create mode 100644 plugins/check_game.d/config.h 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@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 + +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; +} -- cgit v1.2.3-74-g34f1