Code

semicolon needed where praogname define was replced
[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 **);
73 #define QSTAT_DATA_DELIMITER    ","
75 #define QSTAT_HOST_ERROR        "ERROR"
76 #define QSTAT_HOST_DOWN         "DOWN"
77 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
78 #define QSTAT_MAX_RETURN_ARGS   12
80 char server_ip[MAX_HOST_ADDRESS_LENGTH];
81 char game_type[MAX_INPUT_BUFFER];
82 char port[MAX_INPUT_BUFFER];
84 int qstat_game_players_max = 4;
85 int qstat_game_players = 5;
86 int qstat_game_field = 2;
87 int qstat_map_field = 3;
88 int qstat_ping_field = 5;
91 int
92 main (int argc, char **argv)
93 {
94         char command_line[MAX_INPUT_BUFFER];
95         int result;
96         FILE *fp;
97         char input_buffer[MAX_INPUT_BUFFER];
98         char response[MAX_INPUT_BUFFER];
99         char *temp_ptr;
100         int found;
101         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
102         int i;
104         result = process_arguments (argc, argv);
106         if (result != OK) {
107                 printf ("Incorrect arguments supplied\n");
108                 printf ("\n");
109                 print_revision (argv[0], "$Revision$");
110                 printf ("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n");
111                 printf ("License: GPL\n");
112                 printf ("\n");
113                 printf
114                         ("Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field] [-pf ping_field]\n",
115                          argv[0]);
116                 printf ("\n");
117                 printf ("Options:\n");
118                 printf
119                         (" <game>        = Game type that is recognised by qstat (without the leading dash)\n");
120                 printf
121                         (" <ip_address>  = The IP address of the device you wish to query\n");
122                 printf (" [port]        = Optional port of which to connect\n");
123                 printf
124                         (" [game_field]  = Field number in raw qstat output that contains game name\n");
125                 printf
126                         (" [map_field]   = Field number in raw qstat output that contains map name\n");
127                 printf
128                         (" [ping_field]  = Field number in raw qstat output that contains ping time\n");
129                 printf ("\n");
130                 printf ("Notes:\n");
131                 printf
132                         ("- This plugin uses the 'qstat' command, the popular game server status query tool .\n");
133                 printf
134                         ("  If you don't have the package installed, you will need to download it from\n");
135                 printf
136                         ("  http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n");
137                 printf ("\n");
138                 return STATE_UNKNOWN;
139         }
141         result = STATE_OK;
143         /* create the command line to execute */
144         snprintf (command_line, sizeof (command_line) - 1, "%s -raw %s -%s %s%s",
145                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip, port);
146         command_line[sizeof (command_line) - 1] = 0;
148         /* run the command */
149         fp = popen (command_line, "r");
150         if (fp == NULL) {
151                 printf ("Error - Could not open pipe: %s\n", command_line);
152                 return STATE_UNKNOWN;
153         }
155         found = 0;
156         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
158         /* strip the newline character from the end of the input */
159         input_buffer[strlen (input_buffer) - 1] = 0;
161         /* sanity check */
162         /* was thinking about running qstat without any options, capturing the
163            -default line, parsing it & making an array of all know server types
164            but thought this would be too much hassle considering this is a tool
165            for intelligent sysadmins (ha). Could put a static array of known 
166            server types in a header file but then we'd be limiting ourselves
168            In the end, I figured I'd simply let an error occur & then trap it
169          */
171         if (!strncmp (input_buffer, "unknown option", 14)) {
172                 printf ("ERROR: Host type parameter incorrect!\n");
173                 result = STATE_CRITICAL;
174                 return result;
175         }
177         /* initialize the returned data buffer */
178         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
179                 ret[i] = "";
181         i = 0;
182         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
183         while (p != NULL) {
184                 ret[i] = p;
185                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
186                 i++;
187                 if (i >= QSTAT_MAX_RETURN_ARGS)
188                         break;
189         }
191         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
192                 printf ("ERROR: Host not found\n");
193                 result = STATE_CRITICAL;
194         }
195         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
196                 printf ("ERROR: Game server down or unavailable\n");
197                 result = STATE_CRITICAL;
198         }
199         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
200                 printf ("ERROR: Game server timeout\n");
201                 result = STATE_CRITICAL;
202         }
203         else {
204                 printf ("OK: %s/%s %s (%s), Ping: %s ms\n", 
205                 ret[qstat_game_players_max],
206                 ret[qstat_game_players],
207                 ret[qstat_game_field], 
208                 ret[qstat_map_field],
209                 ret[qstat_ping_field]);
210         }
212         /* close the pipe */
213         pclose (fp);
215         return result;
220 int
221 process_arguments (int argc, char **argv)
223         int x;
225         /* not enough options were supplied */
226         if (argc < 3)
227                 return ERROR;
229         /* first option is always the game type */
230         strncpy (game_type, argv[1], sizeof (game_type) - 1);
231         game_type[sizeof (game_type) - 1] = 0;
233         /* Second option is always the server name */
234         strncpy (server_ip, argv[2], sizeof (server_ip) - 1);
235         server_ip[sizeof (server_ip) - 1] = 0;
237         /* process all remaining arguments */
238         for (x = 4; x <= argc; x++) {
240                 /* we got the port number to connect to */
241                 if (!strcmp (argv[x - 1], "-p")) {
242                         if (x < argc) {
243                                 snprintf (port, sizeof (port) - 2, ":%s", argv[x]);
244                                 port[sizeof (port) - 1] = 0;
245                                 x++;
246                         }
247                         else
248                                 return ERROR;
249                 }
251                 /* we got the game field */
252                 else if (!strcmp (argv[x - 1], "-gf")) {
253                         if (x < argc) {
254                                 qstat_game_field = atoi (argv[x]);
255                                 if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
256                                         return ERROR;
257                                 x++;
258                         }
259                         else
260                                 return ERROR;
261                 }
263                 /* we got the map field */
264                 else if (!strcmp (argv[x - 1], "-mf")) {
265                         if (x < argc) {
266                                 qstat_map_field = atoi (argv[x]);
267                                 if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
268                                         return ERROR;
269                                 x++;
270                         }
271                         else
272                                 return ERROR;
273                 }
275                 /* we got the ping field */
276                 else if (!strcmp (argv[x - 1], "-pf")) {
277                         if (x < argc) {
278                                 qstat_ping_field = atoi (argv[x]);
279                                 if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
280                                         return ERROR;
281                                 x++;
282                         }
283                         else
284                                 return ERROR;
285                 }
287                 /* else we got something else... */
288                 else
289                         return ERROR;
290         }
292         return OK;