Code

replace "terminate" with "die" for shorter name and better readability
[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 void
29 print_usage (void)
30 {
31         printf (_("\
32 Usage: %s <game> <ip_address> [-p port] [-gf game_field] [-mf map_field]\n\
33   [-pf ping_field]\n"), progname);
34         printf (_(UT_HLP_VRS), progname, progname);
35 }
37 void
38 print_help (void)
39 {
40         print_revision (progname, revision);
42         printf (_(COPYRIGHT), copyright, email);
44         printf (_("This plugin tests %s connections with the specified host."), progname);
46         print_usage ();
48         printf (_(UT_HELP_VRSN));
50         printf (_("\
51 <game>        = Game type that is recognised by qstat (without the leading dash)\n\
52 <ip_address>  = The IP address of the device you wish to query\n\
53  [port]        = Optional port of which to connect\n\
54  [game_field]  = Field number in raw qstat output that contains game name\n\
55  [map_field]   = Field number in raw qstat output that contains map name\n\
56  [ping_field]  = Field number in raw qstat output that contains ping time\n"),
57                 DEFAULT_SOCKET_TIMEOUT);
59         printf (_("\n\
60 Notes:\n\
61 - This plugin uses the 'qstat' command, the popular game server status query tool .\n\
62   If you don't have the package installed, you will need to download it from\n\
63   http://www.activesw.com/people/steve/qstat.html before you can use this plugin.\n"));
65         printf (_(UT_SUPPORT));
66 }
67 \f
68 int process_arguments (int, char **);
69 int validate_arguments (void);
71 #define QSTAT_DATA_DELIMITER    ","
73 #define QSTAT_HOST_ERROR        "ERROR"
74 #define QSTAT_HOST_DOWN         "DOWN"
75 #define QSTAT_HOST_TIMEOUT      "TIMEOUT"
76 #define QSTAT_MAX_RETURN_ARGS   12
78 char *server_ip;
79 char *game_type;
80 int port = 0;
82 int verbose;
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;
95         int result;
96         FILE *fp;
97         char input_buffer[MAX_INPUT_BUFFER];
98         char *p, *ret[QSTAT_MAX_RETURN_ARGS];
99         int i;
101         result = process_arguments (argc, argv);
103         if (result != OK) {
104                 printf (_("Incorrect arguments supplied\n"));
105                 printf ("\n");
106                 print_revision (progname, revision);
107                 printf (_("Copyright (c) 1999 Ian Cass, Knowledge Matters Limited\n"));
108                 printf (_("License: GPL\n"));
109                 printf ("\n");
110                 return STATE_UNKNOWN;
111         }
113         result = STATE_OK;
115         /* create the command line to execute */
116         asprintf (&command_line, "%s -raw %s -%s %s",
117                                                 PATH_TO_QSTAT, QSTAT_DATA_DELIMITER, game_type, server_ip);
118         
119         if (port)
120                 asprintf (&command_line, "%s:%-d", command_line, port);
122         if (verbose > 0)
123                 printf ("%s\n", command_line);
125         /* run the command */
126         fp = spopen (command_line);
127         if (fp == NULL) {
128                 printf (_("Error - Could not open pipe: %s\n"), command_line);
129                 return STATE_UNKNOWN;
130         }
132         fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp); /* Only interested in the first line */
134         /* strip the newline character from the end of the input */
135         input_buffer[strlen (input_buffer) - 1] = 0;
137         /* sanity check */
138         /* was thinking about running qstat without any options, capturing the
139            -default line, parsing it & making an array of all know server types
140            but thought this would be too much hassle considering this is a tool
141            for intelligent sysadmins (ha). Could put a static array of known 
142            server types in a header file but then we'd be limiting ourselves
144            In the end, I figured I'd simply let an error occur & then trap it
145          */
147         if (!strncmp (input_buffer, "unknown option", 14)) {
148                 printf (_("ERROR: Host type parameter incorrect!\n"));
149                 result = STATE_CRITICAL;
150                 return result;
151         }
153         /* initialize the returned data buffer */
154         for (i = 0; i < QSTAT_MAX_RETURN_ARGS; i++)
155                 ret[i] = "";
157         i = 0;
158         p = (char *) strtok (input_buffer, QSTAT_DATA_DELIMITER);
159         while (p != NULL) {
160                 ret[i] = p;
161                 p = (char *) strtok (NULL, QSTAT_DATA_DELIMITER);
162                 i++;
163                 if (i >= QSTAT_MAX_RETURN_ARGS)
164                         break;
165         }
167         if (strstr (ret[2], QSTAT_HOST_ERROR)) {
168                 printf ("ERROR: Host not found\n");
169                 result = STATE_CRITICAL;
170         }
171         else if (strstr (ret[2], QSTAT_HOST_DOWN)) {
172                 printf ("ERROR: Game server down or unavailable\n");
173                 result = STATE_CRITICAL;
174         }
175         else if (strstr (ret[2], QSTAT_HOST_TIMEOUT)) {
176                 printf ("ERROR: Game server timeout\n");
177                 result = STATE_CRITICAL;
178         }
179         else {
180                 printf ("OK: %s/%s %s (%s), Ping: %s ms\n", 
181                         ret[qstat_game_players],
182                         ret[qstat_game_players_max],
183                         ret[qstat_game_field], 
184                         ret[qstat_map_field],
185                         ret[qstat_ping_field]);
186         }
188         /* close the pipe */
189         spclose (fp);
191         return result;
196 int
197 process_arguments (int argc, char **argv)
199         int c;
201         int opt_index = 0;
202         static struct option long_opts[] = {
203                 {"help", no_argument, 0, 'h'},
204                 {"version", no_argument, 0, 'V'},
205                 {"verbose", no_argument, 0, 'v'},
206                 {"timeout", required_argument, 0, 't'},
207                 {"hostname", required_argument, 0, 'H'},
208                 {"port", required_argument, 0, 'P'},
209                 {"game-type", required_argument, 0, 'G'},
210                 {"map-field", required_argument, 0, 'm'},
211                 {"ping-field", required_argument, 0, 'p'},
212                 {"game-field", required_argument, 0, 'g'},
213                 {"players-field", required_argument, 0, 129},
214                 {"max-players-field", required_argument, 0, 130},
215                 {0, 0, 0, 0}
216         };
218         if (argc < 2)
219                 return ERROR;
221         for (c = 1; c < argc; c++) {
222                 if (strcmp ("-mf", argv[c]) == 0)
223                         strcpy (argv[c], "-m");
224                 else if (strcmp ("-pf", argv[c]) == 0)
225                         strcpy (argv[c], "-p");
226                 else if (strcmp ("-gf", argv[c]) == 0)
227                         strcpy (argv[c], "-g");
228         }
230         while (1) {
231                 c = getopt_long (argc, argv, "hVvt:H:P:G:g:p:m:", long_opts, &opt_index);
233                 if (c == -1 || c == EOF)
234                         break;
236                 switch (c) {
237                 case '?': /* args not parsable */
238                         printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
239                         print_usage ();
240                         exit (STATE_UNKNOWN);
241                 case 'h': /* help */
242                         print_help ();
243                         exit (STATE_OK);
244                 case 'V': /* version */
245                         print_revision (progname, revision);
246                         exit (STATE_OK);
247                 case 'v': /* version */
248                         verbose = TRUE;
249                         break;
250                 case 't': /* timeout period */
251                         timeout_interval = atoi (optarg);
252                         break;
253                 case 'H': /* hostname */
254                         if (strlen (optarg) >= MAX_HOST_ADDRESS_LENGTH)
255                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
256                         server_ip = strdup (optarg);
257                         break;
258                 case 'P': /* port */
259                         port = atoi (optarg);
260                         break;
261                 case 'G': /* hostname */
262                         if (strlen (optarg) >= MAX_INPUT_BUFFER)
263                                 die (STATE_UNKNOWN, _("Input buffer overflow\n"));
264                         game_type = strdup (optarg);
265                         break;
266                 case 'p': /* index of ping field */
267                         qstat_ping_field = atoi (optarg);
268                         if (qstat_ping_field < 0 || qstat_ping_field > QSTAT_MAX_RETURN_ARGS)
269                                 return ERROR;
270                         break;
271                 case 'm': /* index on map field */
272                         qstat_map_field = atoi (optarg);
273                         if (qstat_map_field < 0 || qstat_map_field > QSTAT_MAX_RETURN_ARGS)
274                                 return ERROR;
275                         break;
276                 case 'g': /* index of game field */
277                         qstat_game_field = atoi (optarg);
278                         if (qstat_game_field < 0 || qstat_game_field > QSTAT_MAX_RETURN_ARGS)
279                                 return ERROR;
280                         break;
281                 case 129: /* index of player count field */
282                         qstat_game_players = atoi (optarg);
283                         if (qstat_game_players < 0 || qstat_game_players > QSTAT_MAX_RETURN_ARGS)
284                                 return ERROR;
285                         break;
286                 case 130: /* index of max players field */
287                         qstat_game_players_max = atoi (optarg);
288                         if (qstat_game_players_max < 0 || qstat_game_players_max > QSTAT_MAX_RETURN_ARGS)
289                                 return ERROR;
290                         break;
291                 }
292         }
294         c = optind;
295         /* first option is the game type */
296         if (!game_type && c<argc)
297                 game_type = strdup (argv[c++]);
299         /* Second option is the server name */
300         if (!server_ip && c<argc)
301                 server_ip = strdup (argv[c++]);
303         return validate_arguments ();
306 int
307 validate_arguments (void)
309                 return OK;