Code

return of process_arguments() is TRUE not OK !
[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 * $Id$
18 *****************************************************************************/
20 const char *progname = "check_game";
21 const char *revision = "$Revision$";
22 const char *copyright = "2002-2003";
23 const char *email = "nagiosplug-devel@lists.sourceforge.net";
25 #include "common.h"
26 #include "popen.h"
27 #include "utils.h"
29 int process_arguments (int, char **);
30 int validate_arguments (void);
31 void print_help (void);
32 void print_usage (void);
34 #define QSTAT_DATA_DELIMITER    ","
36 #define QSTAT_HOST_ERROR        "ERROR"
37 #define QSTAT_HOST_DOWN         "DOWN"
38 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
39 #define QSTAT_MAX_RETURN_ARGS   12
41 char *server_ip;
42 char *game_type;
43 int port = 0;
45 int verbose;
47 int qstat_game_players_max = -1;
48 int qstat_game_players = -1;
49 int qstat_game_field = -1;
50 int qstat_map_field = -1;
51 int qstat_ping_field = -1;
54 int
55 main (int argc, char **argv)
56 {
57         char *command_line;
58         int result;
59         FILE *fp;
60         char input_buffer[MAX_INPUT_BUFFER];
61         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
62         int i;
64         setlocale (LC_ALL, "");
65         bindtextdomain (PACKAGE, LOCALEDIR);
66         textdomain (PACKAGE);
68 //      result = process_arguments (argc, argv);
69         
70         if (process_arguments (argc, argv) != TRUE)
71                 usage (_("check_game: could not parse arguments\n"));
73 /*      if (result != OK) {
74                 printf (_("Incorrect arguments supplied\n"));
75                 printf ("\n");
76                 print_revision (progname, revision);
77                 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
78                 printf (_("License: GPL\n"));
79                 printf ("\n");
80                 return STATE_UNKNOWN;
81         }
82 */
84         result = STATE_OK;
86         /* create the command line to execute */
87         asprintf (&command_line, "%s -raw %s -%s %s",
88                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
89         
90         if (port)
91                 asprintf (&command_line, "%s:%-d", command_line, port);
93         if (verbose > 0)
94                 printf ("%s\n", command_line);
96         /* run the command */
97         fp = spopen (command_line);
98         if (fp == NULL) {
99                 printf (_("Could not open pipe: %s\n"), command_line);
100                 return STATE_UNKNOWN;
101         }
103         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
105         /* strip the newline character from the end of the input */
106         input_buffer[strlen (input_buffer) - 1] = 0;
108         /* sanity check */
109         /* was thinking about running qstat without any options, capturing the
110            -default line, parsing it & making an array of all know server types
111            but thought this would be too much hassle considering this is a tool
112            for intelligent sysadmins (ha). Could put a static array of known 
113            server types in a header file but then we'd be limiting ourselves
115            In the end, I figured I'd simply let an error occur & then trap it
116          */
118         if (!strncmp (input_buffer, "unknown option", 14)) {
119                 printf (_("CRITICAL - Host type parameter incorrect!\n"));
120                 result = STATE_CRITICAL;
121                 return result;
122         }
124         /* initialize the returned data buffer */
125         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
126                 ret[i] = strdup("");
128         i = 0;
129         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
130         while (p != NULL) {
131                 ret[i] = p;
132                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
133                 i++;
134                 if (i >= QSTAT_MAX_RETURN_ARGS)
135                         break;
136         }
138         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
139                 printf ("CRITICAL - Host not found\n");
140                 result = STATE_CRITICAL;
141         }
142         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
143                 printf ("CRITICAL - Game server down or unavailable\n");
144                 result = STATE_CRITICAL;
145         }
146         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
147                 printf ("CRITICAL - Game server timeout\n");
148                 result = STATE_CRITICAL;
149         }
150         else {
151                 printf ("OK: %s/%s %s (%s), Ping: %s ms|%s %s\n", 
152                         ret[qstat_game_players],
153                         ret[qstat_game_players_max],
154                         ret[qstat_game_field], 
155                         ret[qstat_map_field],
156                         ret[qstat_ping_field],
157                                                 perfdata ("players", atol(ret[qstat_game_players]), "",
158                                   FALSE, 0, FALSE, 0,
159                                   TRUE, 0, TRUE, atol(ret[qstat_game_players_max])),
160                                                 fperfdata ("ping", strtod(ret[qstat_ping_field], NULL), "",
161                                   FALSE, 0, FALSE, 0,
162                                   TRUE, 0, FALSE, 0));
163         }
165         /* close the pipe */
166         spclose (fp);
168         return result;
173 int
174 process_arguments (int argc, char **argv)
176         int c;
178         int opt_index = 0;
179         static struct option long_opts[] = {
180                 {"help", no_argument, 0, 'h'},
181                 {"version", no_argument, 0, 'V'},
182                 {"verbose", no_argument, 0, 'v'},
183                 {"timeout", required_argument, 0, 't'},
184                 {"hostname", required_argument, 0, 'H'},
185                 {"port", required_argument, 0, 'P'},
186                 {"game-type", required_argument, 0, 'G'},
187                 {"map-field", required_argument, 0, 'm'},
188                 {"ping-field", required_argument, 0, 'p'},
189                 {"game-field", required_argument, 0, 'g'},
190                 {"players-field", required_argument, 0, 129},
191                 {"max-players-field", required_argument, 0, 130},
192                 {0, 0, 0, 0}
193         };
195         if (argc < 2)
196                 return ERROR;
198         for (c = 1; c < argc; c++) {
199                 if (strcmp ("-mf", argv[c]) == 0)
200                         strcpy (argv[c], "-m");
201                 else if (strcmp ("-pf", argv[c]) == 0)
202                         strcpy (argv[c], "-p");
203                 else if (strcmp ("-gf", argv[c]) == 0)
204                         strcpy (argv[c], "-g");
205         }
207         while (1) {
208                 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
210                 if (c == -1 || c == EOF)
211                         break;
213                 switch (c) {
214                 case '?': /* args not parsable */
215                         printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
216                         print_usage ();
217                         exit (STATE_UNKNOWN);
218                 case 'h': /* help */
219                         print_help ();
220                         exit (STATE_OK);
221                 case 'V': /* version */
222                         print_revision (progname, revision);
223                         exit (STATE_OK);
224                 case 'v': /* version */
225                         verbose = TRUE;
226                         break;
227                 case 't': /* timeout period */
228                         timeout_interval = atoi (optarg);
229                         break;
230                 case 'H': /* hostname */
231                         if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH)
232                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
233                         server_ip = optarg;
234                         break;
235                 case 'P': /* port */
236                         port = atoi (optarg);
237                         break;
238                 case 'G': /* hostname */
239                         if (strlen (optarg) >= MAX_INPUT_BUFFER)
240                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
241                         game_type = optarg;
242                         break;
243                 case 'p': /* index of ping field */
244                         qstat_ping_field = atoi (optarg);
245                         if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
246                                 return ERROR;
247                         break;
248                 case 'm': /* index on map field */
249                         qstat_map_field = atoi (optarg);
250                         if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
251                                 return ERROR;
252                         break;
253                 case 'g': /* index of game field */
254                         qstat_game_field = atoi (optarg);
255                         if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
256                                 return ERROR;
257                         break;
258                 case 129: /* index of player count field */
259                         qstat_game_players = atoi (optarg);
260                         if (qstat_game_players_max == 0)
261                                 qstat_game_players_max = qstat_game_players - 1;
262                         if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
263                                 return ERROR;
264                         break;
265                 case 130: /* index of max players field */
266                         qstat_game_players_max = atoi (optarg);
267                         if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
268                                 return ERROR;
269                         break;
270                 }
271         }
273         c = optind;
274         /* first option is the game type */
275         if (!game_type && c<argc)
276                 game_type = strdup (argv[c++]);
278         /* Second option is the server name */
279         if (!server_ip && c<argc)
280                 server_ip = strdup (argv[c++]);
282         return validate_arguments ();
285 int
286 validate_arguments (void)
288         if (qstat_game_players_max < 0)
289                 qstat_game_players_max = 4;
291         if (qstat_game_players < 0)
292                 qstat_game_players = 5;
294         if (qstat_game_field < 0)
295                 qstat_game_field = 2;
297         if (qstat_map_field < 0)
298                 qstat_map_field = 3;
300         if (qstat_ping_field < 0)
301                 qstat_ping_field = 5;
303         return OK;
310 void
311 print_help (void)
313         print_revision (progname, revision);
315         printf (_(COPYRIGHT), copyright, email);
317         printf (_("This plugin tests %s connections with the specified host."), progname);
319         print_usage ();
321         printf (_(UT_HELP_VRSN));
323         printf (_("\
324 <game>        = Game type that is recognised by qstat (without the leading dash)\n\
325 <ip_address>  = The IP address of the device you wish to query\n\
326  [port]        = Optional port of which to connect\n\
327  [game_field]  = Field number in raw qstat output that contains game name\n\
328  [map_field]   = Field number in raw qstat output that contains map name\n\
329  [ping_field]  = Field number in raw qstat output that contains ping time\n"));
331         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
333         printf (_("\n\
334 Notes:\n\
335 - This plugin uses the 'qstat' command, the popular game server status query tool .\n\
336   If you don't have the package installed, you will need to download it from\n\
337   http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n"));
339         printf (_(UT_SUPPORT));
345 void
346 print_usage (void)
348         printf (_("\
349 Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field]\n\
350   [-pf ping_field]\n"), progname);
351         printf (_(UT_HLP_VRS), progname, progname);
354 /******************************************************************************
355  *
356  * Test Cases:
357  *
358  * ./check_game --players 7 -p 8 --map 5 qs 67.20.190.61 26000
359  * 
360  * qstat -raw , -qs 67.20.190.61
361  *  ==> QS,67.20.190.61,Nightmare.fintek.ca,67.20.190.61:26000,3,e2m1,6,0,83,0
362  *
363  * qstat -qs 67.20.190.61
364  *  ==> ADDRESS           PLAYERS      MAP   RESPONSE TIME    NAME
365  *  ==> 67.20.190.61            0/ 6     e2m1     79 / 0   Nightmare.fintek.ca
366  *
367  ******************************************************************************/