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 ******************************************************************************/
19 const char *progname = "check_nagios";
20 const char *revision = "$Revision$";
21 const char *copyright = "1999-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 void print_help (void);
30 void print_usage (void);
32 char *status_log = NULL;
33 char *process_string = NULL;
34 int expire_minutes = 0;
36 int verbose = 0;
38 int
39 main (int argc, char **argv)
40 {
41 int result = STATE_UNKNOWN;
42 char input_buffer[MAX_INPUT_BUFFER];
43 unsigned long latest_entry_time = 0L;
44 unsigned long temp_entry_time = 0L;
45 int proc_entries = 0;
46 time_t current_time;
47 char *temp_ptr;
48 FILE *fp;
49 int procuid = 0;
50 int procppid = 0;
51 int procvsz = 0;
52 int procrss = 0;
53 float procpcpu = 0;
54 char procstat[8];
55 char procprog[MAX_INPUT_BUFFER];
56 char *procargs;
57 int pos, cols;
59 setlocale (LC_ALL, "");
60 bindtextdomain (PACKAGE, LOCALEDIR);
61 textdomain (PACKAGE);
63 if (process_arguments (argc, argv) == ERROR)
64 usage (_("Could not parse arguments\n"));
66 /* Set signal handling and alarm */
67 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
68 printf (_("Cannot catch SIGALRM"));
69 return STATE_UNKNOWN;
70 }
72 /* handle timeouts gracefully... */
73 alarm (timeout_interval);
75 /* open the status log */
76 fp = fopen (status_log, "r");
77 if (fp == NULL) {
78 printf (_("Error: Cannot open status log for reading!\n"));
79 return STATE_CRITICAL;
80 }
82 /* get the date/time of the last item updated in the log */
83 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
84 temp_ptr = strtok (input_buffer, "]");
85 temp_entry_time =
86 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
87 if (temp_entry_time > latest_entry_time)
88 latest_entry_time = temp_entry_time;
89 }
90 fclose (fp);
92 /* run the command to check for the Nagios process.. */
93 child_process = spopen (PS_COMMAND);
94 if (child_process == NULL) {
95 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
96 return STATE_UNKNOWN;
97 }
99 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
100 if (child_stderr == NULL) {
101 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
102 }
104 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
106 /* count the number of matching Nagios processes... */
107 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
108 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
109 if ( cols >= 6 ) {
110 asprintf (&procargs, "%s", input_buffer + pos);
111 strip (procargs);
113 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string)) {
114 proc_entries++;
115 if (verbose)
116 printf (_("Found process: %s\n"), procargs);
117 }
118 }
119 }
121 /* If we get anything on stderr, at least set warning */
122 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
123 result = max_state (result, STATE_WARNING);
125 /* close stderr */
126 (void) fclose (child_stderr);
128 /* close the pipe */
129 if (spclose (child_process))
130 result = max_state (result, STATE_WARNING);
132 /* reset the alarm handler */
133 alarm (0);
135 if (proc_entries == 0) {
136 printf (_("Could not locate a running Nagios process!\n"));
137 return STATE_CRITICAL;
138 }
140 result = STATE_OK;
142 time (¤t_time);
143 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
144 result = STATE_WARNING;
146 printf
147 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
148 (result == STATE_OK) ? "ok" : "problem", proc_entries,
149 (proc_entries == 1) ? "" : "es",
150 (int) (current_time - latest_entry_time),
151 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
153 return result;
154 }
160 /* process command-line arguments */
161 int
162 process_arguments (int argc, char **argv)
163 {
164 int c;
166 int option = 0;
167 static struct option longopts[] = {
168 {"filename", required_argument, 0, 'F'},
169 {"expires", required_argument, 0, 'e'},
170 {"command", required_argument, 0, 'C'},
171 {"version", no_argument, 0, 'V'},
172 {"help", no_argument, 0, 'h'},
173 {"verbose", no_argument, 0, 'v'},
174 {0, 0, 0, 0}
175 };
177 if (argc < 2)
178 return ERROR;
180 if (!is_option (argv[1])) {
181 status_log = argv[1];
182 if (is_intnonneg (argv[2]))
183 expire_minutes = atoi (argv[2]);
184 else
185 die (STATE_UNKNOWN,
186 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
187 progname);
188 process_string = argv[3];
189 return OK;
190 }
192 while (1) {
193 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
195 if (c == -1 || c == EOF || c == 1)
196 break;
198 switch (c) {
199 case '?': /* print short usage statement if args not parsable */
200 printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
201 print_usage ();
202 exit (STATE_UNKNOWN);
203 case 'h': /* help */
204 print_help ();
205 exit (STATE_OK);
206 case 'V': /* version */
207 print_revision (progname, "$Revision$");
208 exit (STATE_OK);
209 case 'F': /* status log */
210 status_log = optarg;
211 break;
212 case 'C': /* command */
213 process_string = optarg;
214 break;
215 case 'e': /* expiry time */
216 if (is_intnonneg (optarg))
217 expire_minutes = atoi (optarg);
218 else
219 die (STATE_UNKNOWN,
220 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
221 progname);
222 break;
223 case 'v':
224 verbose++;
225 break;
226 }
227 }
230 if (status_log == NULL)
231 die (STATE_UNKNOWN,
232 _("You must provide the status_log\nType '%s -h' for additional help\n"),
233 progname);
234 else if (process_string == NULL)
235 die (STATE_UNKNOWN,
236 _("You must provide a process string\nType '%s -h' for additional help\n"),
237 progname);
239 return OK;
240 }
246 \f
247 void
248 print_help (void)
249 {
250 print_revision (progname, revision);
252 printf (_(COPYRIGHT), copyright, email);
254 printf (_("\
255 This plugin attempts to check the status of the Nagios process on the local\n\
256 machine. The plugin will check to make sure the Nagios status log is no older\n\
257 than the number of minutes specified by the <expire_minutes> option. It also\n\
258 uses the /bin/ps command to check for a process matching whatever you specify\n\
259 by the <process_string> argument.\n"));
261 print_usage ();
263 printf (_(UT_HELP_VRSN));
265 printf (_("\
266 -F, --filename=FILE\n\
267 Name of the log file to check\n\
268 -e, --expires=INTEGER\n\
269 Seconds aging afterwhich logfile is condsidered stale\n\
270 -C, --command=STRING\n\
271 Command to search for in process table\n"));
273 printf (_("\
274 Example:\n\
275 ./check_nagios -e 5 \\\
276 -F /usr/local/nagios/var/status.log \\\
277 -C /usr/local/nagios/bin/nagios\n"));
278 }
283 void
284 print_usage (void)
285 {
286 printf (_("\
287 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
288 progname);
289 }