Code

db28dfdfc9e81fd0e3cde87cc5e1b6b5c6640db1
[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 *authors = "Nagios Plugin Development Team";
23 const char *email = "nagiosplug-devel@lists.sourceforge.net";
25 const char *summary = "\
26 This plugin tests %s connections with the specified host.\n";
28 const char *option_summary = "\
29 %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field] [-pf ping_field]\n";
31 const char *options = "\
32 <game>        = Game type that is recognised by qstat (without the leading dash)\n\
33 <ip_address>  = The IP address of the device you wish to query\n\
34  [port]        = Optional port of which to connect\n\
35  [game_field]  = Field number in raw qstat output that contains game name\n\
36  [map_field]   = Field number in raw qstat output that contains map name\n\
37  [ping_field]  = Field number in raw qstat output that contains ping time\n\
38 \n\
39 Notes:\n\
40 - This plugin uses the 'qstat' command, the popular game server status query tool .\n\
41   If you don't have the package installed, you will need to download it from\n\
42   http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n";
44 #include "common.h"
45 #include "popen.h"
46 #include "utils.h"
48 void print_usage (void);
49 void print_help (void);
50 int process_arguments (int, char **);
51 int validate_arguments (void);
53 #define QSTAT_DATA_DELIMITER    ","
55 #define QSTAT_HOST_ERROR        "ERROR"
56 #define QSTAT_HOST_DOWN         "DOWN"
57 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
58 #define QSTAT_MAX_RETURN_ARGS   12
60 char *server_ip;
61 char *game_type;
62 int port = 0;
64 int verbose;
66 int qstat_game_players_max = 4;
67 int qstat_game_players = 5;
68 int qstat_game_field = 2;
69 int qstat_map_field = 3;
70 int qstat_ping_field = 5;
73 int
74 main (int argc, char **argv)
75 {
76         char *command_line;
77         int result;
78         FILE *fp;
79         char input_buffer[MAX_INPUT_BUFFER];
80         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
81         int i;
83         result = process_arguments (argc, argv);
85         if (result != OK) {
86                 printf ("Incorrect arguments supplied\n");
87                 printf ("\n");
88                 print_revision (argv[0], "$Revision$");
89                 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
90                 printf ("License: GPL\n");
91                 printf ("\n");
92                 return STATE_UNKNOWN;
93         }
95         result = STATE_OK;
97         /* create the command line to execute */
98         asprintf (&command_line, "%s -raw %s -%s %s",
99                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
100         
101         if (port)
102                 asprintf (&command_line, "%s:%-d", command_line, port);
104         if (verbose > 0)
105                 printf ("%s\n", command_line);
107         /* run the command */
108         fp = spopen (command_line);
109         if (fp == NULL) {
110                 printf ("Error - Could not open pipe: %s\n", command_line);
111                 return STATE_UNKNOWN;
112         }
114         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
116         /* strip the newline character from the end of the input */
117         input_buffer[strlen (input_buffer) - 1] = 0;
119         /* sanity check */
120         /* was thinking about running qstat without any options, capturing the
121            -default line, parsing it & making an array of all know server types
122            but thought this would be too much hassle considering this is a tool
123            for intelligent sysadmins (ha). Could put a static array of known 
124            server types in a header file but then we'd be limiting ourselves
126            In the end, I figured I'd simply let an error occur & then trap it
127          */
129         if (!strncmp (input_buffer, "unknown option", 14)) {
130                 printf ("ERROR: Host type parameter incorrect!\n");
131                 result = STATE_CRITICAL;
132                 return result;
133         }
135         /* initialize the returned data buffer */
136         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
137                 ret[i] = "";
139         i = 0;
140         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
141         while (p != NULL) {
142                 ret[i] = p;
143                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
144                 i++;
145                 if (i >= QSTAT_MAX_RETURN_ARGS)
146                         break;
147         }
149         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
150                 printf ("ERROR: Host not found\n");
151                 result = STATE_CRITICAL;
152         }
153         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
154                 printf ("ERROR: Game server down or unavailable\n");
155                 result = STATE_CRITICAL;
156         }
157         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
158                 printf ("ERROR: Game server timeout\n");
159                 result = STATE_CRITICAL;
160         }
161         else {
162                 printf ("OK: %s/%s %s (%s), Ping: %s ms\n", 
163                         ret[qstat_game_players],
164                         ret[qstat_game_players_max],
165                         ret[qstat_game_field], 
166                         ret[qstat_map_field],
167                         ret[qstat_ping_field]);
168         }
170         /* close the pipe */
171         spclose (fp);
173         return result;
178 int
179 process_arguments (int argc, char **argv)
181         int c;
183         int opt_index = 0;
184         static struct option long_opts[] = {
185                 {"help", no_argument, 0, 'h'},
186                 {"version", no_argument, 0, 'V'},
187                 {"verbose", no_argument, 0, 'v'},
188                 {"timeout", required_argument, 0, 't'},
189                 {"hostname", required_argument, 0, 'H'},
190                 {"port", required_argument, 0, 'P'},
191                 {"game-type", required_argument, 0, 'G'},
192                 {"map-field", required_argument, 0, 'm'},
193                 {"ping-field", required_argument, 0, 'p'},
194                 {"game-field", required_argument, 0, 'g'},
195                 {"players-field", required_argument, 0, 129},
196                 {"max-players-field", required_argument, 0, 130},
197                 {0, 0, 0, 0}
198         };
200         if (argc < 2)
201                 return ERROR;
203         for (c = 1; c < argc; c++) {
204                 if (strcmp ("-mf", argv[c]) == 0)
205                         strcpy (argv[c], "-m");
206                 else if (strcmp ("-pf", argv[c]) == 0)
207                         strcpy (argv[c], "-p");
208                 else if (strcmp ("-gf", argv[c]) == 0)
209                         strcpy (argv[c], "-g");
210         }
212         while (1) {
213                 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
215                 if (c == -1 || c == EOF)
216                         break;
218                 switch (c) {
219                 case '?': /* args not parsable */
220                         printf ("%s: Unknown argument: %s\n\n", progname, optarg);
221                         print_usage ();
222                         exit (STATE_UNKNOWN);
223                 case 'h': /* help */
224                         print_help ();
225                         exit (STATE_OK);
226                 case 'V': /* version */
227                         print_revision (progname, revision);
228                         exit (STATE_OK);
229                 case 'v': /* version */
230                         verbose = TRUE;
231                         break;
232                 case 't': /* timeout period */
233                         timeout_interval = atoi (optarg);
234                         break;
235                 case 'H': /* hostname */
236                         if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH)
237                                 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
238                         server_ip = strdup (optarg);
239                         break;
240                 case 'P': /* port */
241                         port = atoi (optarg);
242                         break;
243                 case 'G': /* hostname */
244                         if (strlen (optarg) >= MAX_INPUT_BUFFER)
245                                 terminate (STATE_UNKNOWN, "Input buffer overflow\n");
246                         game_type = strdup (optarg);
247                         break;
248                 case 'p': /* index of ping field */
249                         qstat_ping_field = atoi (optarg);
250                         if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
251                                 return ERROR;
252                         break;
253                 case 'm': /* index on map field */
254                         qstat_map_field = atoi (optarg);
255                         if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
256                                 return ERROR;
257                         break;
258                 case 'g': /* index of game field */
259                         qstat_game_field = atoi (optarg);
260                         if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
261                                 return ERROR;
262                         break;
263                 case 129: /* index of player count field */
264                         qstat_game_players = atoi (optarg);
265                         if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
266                                 return ERROR;
267                         break;
268                 case 130: /* index of max players field */
269                         qstat_game_players_max = atoi (optarg);
270                         if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
271                                 return ERROR;
272                         break;
273                 }
274         }
276         c = optind;
277         /* first option is the game type */
278         if (!game_type && c<argc)
279                 game_type = strdup (argv[c++]);
281         /* Second option is the server name */
282         if (!server_ip && c<argc)
283                 server_ip = strdup (argv[c++]);
285         return validate_arguments ();
288 int
289 validate_arguments (void)
291                 return OK;
295 void
296 print_help (void)
298         print_revision (progname, revision);
299         printf ("Copyright (c) %s %s\n\t<%s>\n\n",
300                  copyright, authors, email);
301         printf (summary, progname);
302         print_usage ();
303         printf ("\nOptions:\n");
304         printf (options, DEFAULT_SOCKET_TIMEOUT);
305         support ();
308 void
309 print_usage (void)
311         printf
312                 ("Usage: %s %s\n"
313                  "       %s (-h|--help)\n"
314                  "       %s (-V|--version)\n", progname, option_summary, progname, progname);