Code

the last round of pedantic compiler warnings
[nagiosplug.git] / plugins / check_game.c
1 /******************************************************************************
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 *****************************************************************************/
19 const char *progname = "check_game";
20 const char *revision = "$Revision$";
21 const char *copyright = "2002-2003";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "popen.h"
26 #include "utils.h"
28 int process_arguments (int, char **);
29 int validate_arguments (void);
30 void print_help (void);
31 void print_usage (void);
33 #define QSTAT_DATA_DELIMITER    ","
35 #define QSTAT_HOST_ERROR        "ERROR"
36 #define QSTAT_HOST_DOWN         "DOWN"
37 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
38 #define QSTAT_MAX_RETURN_ARGS   12
40 char *server_ip;
41 char *game_type;
42 int port = 0;
44 int verbose;
46 int qstat_game_players_max = 4;
47 int qstat_game_players = 5;
48 int qstat_game_field = 2;
49 int qstat_map_field = 3;
50 int qstat_ping_field = 5;
53 int
54 main (int argc, char **argv)
55 {
56         char *command_line;
57         int result;
58         FILE *fp;
59         char input_buffer[MAX_INPUT_BUFFER];
60         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
61         int i;
63         result = process_arguments (argc, argv);
65         if (result != OK) {
66                 printf (_("Incorrect arguments supplied\n"));
67                 printf ("\n");
68                 print_revision (progname, revision);
69                 printf (_("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n"));
70                 printf (_("License: GPL\n"));
71                 printf ("\n");
72                 return STATE_UNKNOWN;
73         }
75         result = STATE_OK;
77         /* create the command line to execute */
78         asprintf (&command_line, "%s -raw %s -%s %s",
79                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
80         
81         if (port)
82                 asprintf (&command_line, "%s:%-d", command_line, port);
84         if (verbose > 0)
85                 printf ("%s\n", command_line);
87         /* run the command */
88         fp = spopen (command_line);
89         if (fp == NULL) {
90                 printf (_("Error - Could not open pipe: %s\n"), command_line);
91                 return STATE_UNKNOWN;
92         }
94         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
96         /* strip the newline character from the end of the input */
97         input_buffer[strlen (input_buffer) - 1] = 0;
99         /* sanity check */
100         /* was thinking about running qstat without any options, capturing the
101            -default line, parsing it & making an array of all know server types
102            but thought this would be too much hassle considering this is a tool
103            for intelligent sysadmins (ha). Could put a static array of known 
104            server types in a header file but then we'd be limiting ourselves
106            In the end, I figured I'd simply let an error occur & then trap it
107          */
109         if (!strncmp (input_buffer, "unknown option", 14)) {
110                 printf (_("ERROR: Host type parameter incorrect!\n"));
111                 result = STATE_CRITICAL;
112                 return result;
113         }
115         /* initialize the returned data buffer */
116         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
117                 ret[i] = strdup("");
119         i = 0;
120         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
121         while (p != NULL) {
122                 ret[i] = p;
123                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
124                 i++;
125                 if (i >= QSTAT_MAX_RETURN_ARGS)
126                         break;
127         }
129         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
130                 printf ("ERROR: Host not found\n");
131                 result = STATE_CRITICAL;
132         }
133         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
134                 printf ("ERROR: Game server down or unavailable\n");
135                 result = STATE_CRITICAL;
136         }
137         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
138                 printf ("ERROR: Game server timeout\n");
139                 result = STATE_CRITICAL;
140         }
141         else {
142                 printf ("OK: %s/%s %s (%s), Ping: %s ms\n", 
143                         ret[qstat_game_players],
144                         ret[qstat_game_players_max],
145                         ret[qstat_game_field], 
146                         ret[qstat_map_field],
147                         ret[qstat_ping_field]);
148         }
150         /* close the pipe */
151         spclose (fp);
153         return result;
158 int
159 process_arguments (int argc, char **argv)
161         int c;
163         int opt_index = 0;
164         static struct option long_opts[] = {
165                 {"help", no_argument, 0, 'h'},
166                 {"version", no_argument, 0, 'V'},
167                 {"verbose", no_argument, 0, 'v'},
168                 {"timeout", required_argument, 0, 't'},
169                 {"hostname", required_argument, 0, 'H'},
170                 {"port", required_argument, 0, 'P'},
171                 {"game-type", required_argument, 0, 'G'},
172                 {"map-field", required_argument, 0, 'm'},
173                 {"ping-field", required_argument, 0, 'p'},
174                 {"game-field", required_argument, 0, 'g'},
175                 {"players-field", required_argument, 0, 129},
176                 {"max-players-field", required_argument, 0, 130},
177                 {0, 0, 0, 0}
178         };
180         if (argc < 2)
181                 return ERROR;
183         for (c = 1; c < argc; c++) {
184                 if (strcmp ("-mf", argv[c]) == 0)
185                         strcpy (argv[c], "-m");
186                 else if (strcmp ("-pf", argv[c]) == 0)
187                         strcpy (argv[c], "-p");
188                 else if (strcmp ("-gf", argv[c]) == 0)
189                         strcpy (argv[c], "-g");
190         }
192         while (1) {
193                 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
195                 if (c == -1 || c == EOF)
196                         break;
198                 switch (c) {
199                 case '?': /* args not parsable */
200                         printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
201                         print_usage ();
202                         exit (STATE_UNKNOWN);
203                 case 'h': /* help */
204                         print_help ();
205                         exit (STATE_OK);
206                 case 'V': /* version */
207                         print_revision (progname, revision);
208                         exit (STATE_OK);
209                 case 'v': /* version */
210                         verbose = TRUE;
211                         break;
212                 case 't': /* timeout period */
213                         timeout_interval = atoi (optarg);
214                         break;
215                 case 'H': /* hostname */
216                         if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH)
217                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
218                         server_ip = optarg;
219                         break;
220                 case 'P': /* port */
221                         port = atoi (optarg);
222                         break;
223                 case 'G': /* hostname */
224                         if (strlen (optarg) >= MAX_INPUT_BUFFER)
225                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
226                         game_type = optarg;
227                         break;
228                 case 'p': /* index of ping field */
229                         qstat_ping_field = atoi (optarg);
230                         if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
231                                 return ERROR;
232                         break;
233                 case 'm': /* index on map field */
234                         qstat_map_field = atoi (optarg);
235                         if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
236                                 return ERROR;
237                         break;
238                 case 'g': /* index of game field */
239                         qstat_game_field = atoi (optarg);
240                         if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
241                                 return ERROR;
242                         break;
243                 case 129: /* index of player count field */
244                         qstat_game_players = atoi (optarg);
245                         if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
246                                 return ERROR;
247                         break;
248                 case 130: /* index of max players field */
249                         qstat_game_players_max = atoi (optarg);
250                         if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
251                                 return ERROR;
252                         break;
253                 }
254         }
256         c = optind;
257         /* first option is the game type */
258         if (!game_type && c<argc)
259                 game_type = strdup (argv[c++]);
261         /* Second option is the server name */
262         if (!server_ip && c<argc)
263                 server_ip = strdup (argv[c++]);
265         return validate_arguments ();
268 int
269 validate_arguments (void)
271                 return OK;
278 \f
279 void
280 print_help (void)
282         print_revision (progname, revision);
284         printf (_(COPYRIGHT), copyright, email);
286         printf (_("This plugin tests %s connections with the specified host."), progname);
288         print_usage ();
290         printf (_(UT_HELP_VRSN));
292         printf (_("\
293 <game>        = Game type that is recognised by qstat (without the leading dash)\n\
294 <ip_address>  = The IP address of the device you wish to query\n\
295  [port]        = Optional port of which to connect\n\
296  [game_field]  = Field number in raw qstat output that contains game name\n\
297  [map_field]   = Field number in raw qstat output that contains map name\n\
298  [ping_field]  = Field number in raw qstat output that contains ping time\n"));
300         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
302         printf (_("\n\
303 Notes:\n\
304 - This plugin uses the 'qstat' command, the popular game server status query tool .\n\
305   If you don't have the package installed, you will need to download it from\n\
306   http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n"));
308         printf (_(UT_SUPPORT));
314 void
315 print_usage (void)
317         printf (_("\
318 Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field]\n\
319   [-pf ping_field]\n"), progname);
320         printf (_(UT_HLP_VRS), progname, progname);