Code

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