Code

standardize localization string
[nagiosplug.git] / plugins / check_nagios.c
1 /******************************************************************************
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.
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.
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.
17  $Id$
18  
19 ******************************************************************************/
21 const char *progname = "check_nagios";
22 const char *revision = "$Revision$";
23 const char *copyright = "1999-2003";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "popen.h"
28 #include "utils.h"
30 int process_arguments (int, char **);
31 void print_help (void);
32 void print_usage (void);
34 char *status_log = NULL;
35 char *process_string = NULL;
36 int expire_minutes = 0;
38 int verbose = 0;
40 int
41 main (int argc, char **argv)
42 {
43         int result = STATE_UNKNOWN;
44         char input_buffer[MAX_INPUT_BUFFER];
45         unsigned long latest_entry_time = 0L;
46         unsigned long temp_entry_time = 0L;
47         int proc_entries = 0;
48         time_t current_time;
49         char *temp_ptr;
50         FILE *fp;
51         int procuid = 0;
52         int procppid = 0;
53         int procvsz = 0;
54         int procrss = 0;
55         float procpcpu = 0;
56         char procstat[8];
57         char procprog[MAX_INPUT_BUFFER];
58         char *procargs;
59         int pos, cols;
60         int expected_cols = PS_COLS - 1;
61         const char *zombie = "Z";
62         char *temp_string;
64         setlocale (LC_ALL, "");
65         bindtextdomain (PACKAGE, LOCALEDIR);
66         textdomain (PACKAGE);
68         if (process_arguments (argc, argv) == ERROR)
69                 usage (_("check_nagios: could not parse arguments\n"));
71         /* Set signal handling and alarm */
72         if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
73                 printf (_("Cannot catch SIGALRM"));
74                 return STATE_UNKNOWN;
75         }
77         /* handle timeouts gracefully... */
78         alarm (timeout_interval);
80         /* open the status log */
81         fp = fopen (status_log, "r");
82         if (fp == NULL) {
83                 printf (_("ERROR - Cannot open status log for reading!\n"));
84                 return STATE_CRITICAL;
85         }
87         /* get the date/time of the last item updated in the log */
88         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
89                 temp_ptr = strtok (input_buffer, "]");
90                 temp_entry_time =
91                         (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
92                 if (temp_entry_time > latest_entry_time)
93                         latest_entry_time = temp_entry_time;
94         }
95         fclose (fp);
97         if (verbose >= 2)
98                 printf("command: %s\n", PS_COMMAND);
100         /* run the command to check for the Nagios process.. */
101         child_process = spopen (PS_COMMAND);
102         if (child_process == NULL) {
103                 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
104                 return STATE_UNKNOWN;
105         }
107         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
108         if (child_stderr == NULL) {
109                 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
110         }
112         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
114         /* count the number of matching Nagios processes... */
115         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
116                 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
117                 /* Zombie processes do not give a procprog command */
118                 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
119                         cols = expected_cols;
120                         /* Set some value for procargs for the strip command further below
121                         Seen to be a problem on some Solaris 7 and 8 systems */
122                         input_buffer[pos] = '\n';
123                         input_buffer[pos+1] = 0x0;
124                 }
125                 if ( cols >= expected_cols ) {
126                         asprintf (&procargs, "%s", input_buffer + pos);
127                         strip (procargs);
128                         
129                         /* Some ps return full pathname for command. This removes path */
130                         temp_string = strtok ((char *)procprog, "/");
131                         while (temp_string) {
132                                 strcpy(procprog, temp_string);
133                                 temp_string = strtok (NULL, "/");
134                         }
136                         /* May get empty procargs */
137                         if (!strstr(procargs, argv[0]) && strstr(procprog, process_string) && strcmp(procargs,"")) {
138                                 proc_entries++;
139                                 if (verbose >= 2) {
140                                         printf (_("Found process: %s %s\n"), procprog, procargs);
141                                 }
142                         }
143                 }
144         }
146         /* If we get anything on stderr, at least set warning */
147         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
148                 result = max_state (result, STATE_WARNING);
150         /* close stderr */
151         (void) fclose (child_stderr);
153         /* close the pipe */
154         if (spclose (child_process))
155                 result = max_state (result, STATE_WARNING);
157         /* reset the alarm handler */
158         alarm (0);
160         if (proc_entries == 0) {
161                 printf (_("Could not locate a running Nagios process!\n"));
162                 return STATE_CRITICAL;
163         }
165         result = STATE_OK;
167         time (&current_time);
168         if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
169                 result = STATE_WARNING;
171         printf
172                 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
173                  (result == STATE_OK) ? "ok" : "problem", proc_entries,
174                  (proc_entries == 1) ? "" : "es",
175                  (int) (current_time - latest_entry_time),
176                  ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
178         return result;
183 /* process command-line arguments */
184 int
185 process_arguments (int argc, char **argv)
187         int c;
189         int option = 0;
190         static struct option longopts[] = {
191                 {"filename", required_argument, 0, 'F'},
192                 {"expires", required_argument, 0, 'e'},
193                 {"command", required_argument, 0, 'C'},
194                 {"version", no_argument, 0, 'V'},
195                 {"help", no_argument, 0, 'h'},
196                 {"verbose", no_argument, 0, 'v'},
197                 {0, 0, 0, 0}
198         };
200         if (argc < 2)
201                 return ERROR;
203         if (!is_option (argv[1])) {
204                 status_log = argv[1];
205                 if (is_intnonneg (argv[2]))
206                         expire_minutes = atoi (argv[2]);
207                 else
208                         die (STATE_UNKNOWN,
209                                                                  _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
210                                                                  progname);
211                 process_string = argv[3];
212                 return OK;
213         }
215         while (1) {
216                 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
218                 if (c == -1 || c == EOF || c == 1)
219                         break;
221                 switch (c) {
222                 case '?':                                                                       /* print short usage statement if args not parsable */
223                         printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
224                         print_usage ();
225                         exit (STATE_UNKNOWN);
226                 case 'h':                                                                       /* help */
227                         print_help ();
228                         exit (STATE_OK);
229                 case 'V':                                                                       /* version */
230                         print_revision (progname, "$Revision$");
231                         exit (STATE_OK);
232                 case 'F':                                                                       /* status log */
233                         status_log = optarg;
234                         break;
235                 case 'C':                                                                       /* command */
236                         process_string = optarg;
237                         break;
238                 case 'e':                                                                       /* expiry time */
239                         if (is_intnonneg (optarg))
240                                 expire_minutes = atoi (optarg);
241                         else
242                                 die (STATE_UNKNOWN,
243                                      _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
244                                      progname);
245                         break;
246                 case 'v':
247                         verbose++;
248                         break;
249                 }
250         }
253         if (status_log == NULL)
254                 die (STATE_UNKNOWN,
255                      _("You must provide the status_log\nType '%s -h' for additional help\n"),
256                      progname);
257         else if (process_string == NULL)
258                 die (STATE_UNKNOWN,
259                                                          _("You must provide a process string\nType '%s -h' for additional help\n"),
260                                                          progname);
262         return OK;
267 void
268 print_help (void)
270         print_revision (progname, revision);
272         printf (_(COPYRIGHT), copyright, email);
274         printf (_("\
275 This plugin attempts to check the status of the Nagios process on the local\n\
276 machine. The plugin will check to make sure the Nagios status log is no older\n\
277 than the number of minutes specified by the <expire_minutes> option.  It also\n\
278 uses the /bin/ps command to check for a process matching whatever you specify\n\
279 by the <process_string> argument.\n"));
281         print_usage ();
283         printf (_(UT_HELP_VRSN));
285         printf (_("\
286 -F, --filename=FILE\n\
287    Name of the log file to check\n\
288 -e, --expires=INTEGER\n\
289    Seconds aging afterwhich logfile is condsidered stale\n\
290 -C, --command=STRING\n\
291    Command to search for in process table\n"));
293         printf (_("\
294 Example:\n\
295    ./check_nagios -e 5 \\\
296    -F /usr/local/nagios/var/status.log \\\
297    -C /usr/local/nagios/bin/nagios\n"));
302 void
303 print_usage (void)
305         printf (_("\
306 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
307                 progname);