Code

8cf1bf4290ab9e469dc1152150afef5ba73184e2
[nagiosplug.git] / plugins / check_game.c
1 /******************************************************************************
2  *
3  * CHECK_GAME.C
4  *
5  * Program: GAME plugin for Nagios
6  * License: GPL
7  * Copyright (c) 1999 Ian Cass (ian@knowledge.com)
8  *
9  * Last Modified: $Date$
10  *
11  * Mod History
12  *
13  * 25-8-99 Ethan Galstad <nagios@nagios.org>
14  *         Integrated with common plugin code, minor cleanup stuff
15  *
16  * 17-8-99 version 1.1b
17  *
18  * 17-8-99 make port a separate argument so we can use something like
19  *         check_game q2s!27910 with the probe set up as
20  *         check_game $ARG1$ $HOSTADDRESS$ $ARG2$
21  *
22  * 17-8-99 Put in sanity check for ppl who enter the wrong server type
23  *
24  * 17-8-99 Release version 1.0b
25  *
26  * Command line: CHECK_GAME <server type> <ip_address> [port]
27  *
28  * server type = a server type that qstat understands (type qstat & look at the -default line)
29  * ip_address  = either a dotted address or a FQD name
30  * port        = defaults game default port
31  *                        
32  *
33  * Description:
34  * 
35  * Needed to explore writing my own probes for nagios. It looked
36  * pretty simple so I thought I'd write one for monitoring the status
37  * of game servers. It uses qstat to do the actual monitoring and
38  * analyses the result. Doing it this way means I can support all the
39  * servers that qstat does and will do in the future.
40  *
41  *
42  * Dependencies:
43  *
44  * This plugin uses the 'qstat' command If you don't
45  * have the package installed you will need to download it from 
46  * http://www.activesw.com/people/steve/qstat.html or any popular files archive
47  * before you can use this plugin.
48  *
49  * License Information:
50  *
51  * This program is free software; you can redistribute it and/or modify
52  * it under the terms of the GNU General Public License as published by
53  * the Free Software Foundation; either version 2 of the License, or
54  * (at your option) any later version.
55  *
56  * This program is distributed in the hope that it will be useful,
57  * but WITHOUT ANY WARRANTY; without even the implied warranty of
58  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
59  * GNU General Public License for more details.
60  *
61  * You should have received a copy of the GNU General Public License
62  * along with this program; if not, write to the Free Software
63  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
64  *
65  *****************************************************************************/
67 #include "config.h"
68 #include "common.h"
69 #include "utils.h"
71 int process_arguments (int, char **);
72 const char *progname = "check_game";
74 #define QSTAT_DATA_DELIMITER    ","
76 #define QSTAT_HOST_ERROR        "ERROR"
77 #define QSTAT_HOST_DOWN         "DOWN"
78 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
79 #define QSTAT_MAX_RETURN_ARGS   12
81 char server_ip[MAX_HOST_ADDRESS_LENGTH];
82 char game_type[MAX_INPUT_BUFFER];
83 char port[MAX_INPUT_BUFFER];
85 int qstat_game_players_max = 4;
86 int qstat_game_players = 5;
87 int qstat_game_field = 2;
88 int qstat_map_field = 3;
89 int qstat_ping_field = 5;
92 int
93 main (int argc, char **argv)
94 {
95         char command_line[MAX_INPUT_BUFFER];
96         int result;
97         FILE *fp;
98         char input_buffer[MAX_INPUT_BUFFER];
99         char response[MAX_INPUT_BUFFER];
100         char *temp_ptr;
101         int found;
102         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
103         int i;
105         result = process_arguments (argc, argv);
107         if (result != OK) {
108                 printf ("Incorrect arguments supplied\n");
109                 printf ("\n");
110                 print_revision (argv[0], "$Revision$");
111                 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
112                 printf ("License: GPL\n");
113                 printf ("\n");
114                 printf
115                         ("Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field] [-pf ping_field]\n",
116                          argv[0]);
117                 printf ("\n");
118                 printf ("Options:\n");
119                 printf
120                         (" <game>        = Game type that is recognised by qstat (without the leading dash)\n");
121                 printf
122                         (" <ip_address>  = The IP address of the device you wish to query\n");
123                 printf (" [port]        = Optional port of which to connect\n");
124                 printf
125                         (" [game_field]  = Field number in raw qstat output that contains game name\n");
126                 printf
127                         (" [map_field]   = Field number in raw qstat output that contains map name\n");
128                 printf
129                         (" [ping_field]  = Field number in raw qstat output that contains ping time\n");
130                 printf ("\n");
131                 printf ("Notes:\n");
132                 printf
133                         ("- This plugin uses the 'qstat' command, the popular game server status query tool .\n");
134                 printf
135                         ("  If you don't have the package installed, you will need to download it from\n");
136                 printf
137                         ("  http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n");
138                 printf ("\n");
139                 return STATE_UNKNOWN;
140         }
142         result = STATE_OK;
144         /* create the command line to execute */
145         snprintf (command_line, sizeof (command_line) - 1, "%s -raw %s -%s %s%s",
146                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip, port);
147         command_line[sizeof (command_line) - 1] = 0;
149         /* run the command */
150         fp = popen (command_line, "r");
151         if (fp == NULL) {
152                 printf ("Error - Could not open pipe: %s\n", command_line);
153                 return STATE_UNKNOWN;
154         }
156         found = 0;
157         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
159         /* strip the newline character from the end of the input */
160         input_buffer[strlen (input_buffer) - 1] = 0;
162         /* sanity check */
163         /* was thinking about running qstat without any options, capturing the
164            -default line, parsing it & making an array of all know server types
165            but thought this would be too much hassle considering this is a tool
166            for intelligent sysadmins (ha). Could put a static array of known 
167            server types in a header file but then we'd be limiting ourselves
169            In the end, I figured I'd simply let an error occur & then trap it
170          */
172         if (!strncmp (input_buffer, "unknown option", 14)) {
173                 printf ("ERROR: Host type parameter incorrect!\n");
174                 result = STATE_CRITICAL;
175                 return result;
176         }
178         /* initialize the returned data buffer */
179         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
180                 ret[i] = "";
182         i = 0;
183         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
184         while (p != NULL) {
185                 ret[i] = p;
186                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
187                 i++;
188                 if (i >= QSTAT_MAX_RETURN_ARGS)
189                         break;
190         }
192         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
193                 printf ("ERROR: Host not found\n");
194                 result = STATE_CRITICAL;
195         }
196         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
197                 printf ("ERROR: Game server down or unavailable\n");
198                 result = STATE_CRITICAL;
199         }
200         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
201                 printf ("ERROR: Game server timeout\n");
202                 result = STATE_CRITICAL;
203         }
204         else {
205                 printf ("OK: %s/%s %s (%s), Ping: %s ms\n", 
206                 ret[qstat_game_players_max],
207                 ret[qstat_game_players],
208                 ret[qstat_game_field], 
209                 ret[qstat_map_field],
210                 ret[qstat_ping_field]);
211         }
213         /* close the pipe */
214         pclose (fp);
216         return result;
221 int
222 process_arguments (int argc, char **argv)
224         int x;
226         /* not enough options were supplied */
227         if (argc < 3)
228                 return ERROR;
230         /* first option is always the game type */
231         strncpy (game_type, argv[1], sizeof (game_type) - 1);
232         game_type[sizeof (game_type) - 1] = 0;
234         /* Second option is always the server name */
235         strncpy (server_ip, argv[2], sizeof (server_ip) - 1);
236         server_ip[sizeof (server_ip) - 1] = 0;
238         /* process all remaining arguments */
239         for (x = 4; x <= argc; x++) {
241                 /* we got the port number to connect to */
242                 if (!strcmp (argv[x - 1], "-p")) {
243                         if (x < argc) {
244                                 snprintf (port, sizeof (port) - 2, ":%s", argv[x]);
245                                 port[sizeof (port) - 1] = 0;
246                                 x++;
247                         }
248                         else
249                                 return ERROR;
250                 }
252                 /* we got the game field */
253                 else if (!strcmp (argv[x - 1], "-gf")) {
254                         if (x < argc) {
255                                 qstat_game_field = atoi (argv[x]);
256                                 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
257                                         return ERROR;
258                                 x++;
259                         }
260                         else
261                                 return ERROR;
262                 }
264                 /* we got the map field */
265                 else if (!strcmp (argv[x - 1], "-mf")) {
266                         if (x < argc) {
267                                 qstat_map_field = atoi (argv[x]);
268                                 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
269                                         return ERROR;
270                                 x++;
271                         }
272                         else
273                                 return ERROR;
274                 }
276                 /* we got the ping field */
277                 else if (!strcmp (argv[x - 1], "-pf")) {
278                         if (x < argc) {
279                                 qstat_ping_field = atoi (argv[x]);
280                                 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
281                                         return ERROR;
282                                 x++;
283                         }
284                         else
285                                 return ERROR;
286                 }
288                 /* else we got something else... */
289                 else
290                         return ERROR;
291         }
293         return OK;
296 void print_usage (void)
298         return STATE_OK;