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 if (process_arguments (argc, argv) == ERROR)
60 usage (_("Could not parse arguments\n"));
62 /* Set signal handling and alarm */
63 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
64 printf (_("Cannot catch SIGALRM"));
65 return STATE_UNKNOWN;
66 }
68 /* handle timeouts gracefully... */
69 alarm (timeout_interval);
71 /* open the status log */
72 fp = fopen (status_log, "r");
73 if (fp == NULL) {
74 printf (_("Error: Cannot open status log for reading!\n"));
75 return STATE_CRITICAL;
76 }
78 /* get the date/time of the last item updated in the log */
79 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
80 temp_ptr = strtok (input_buffer, "]");
81 temp_entry_time =
82 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
83 if (temp_entry_time > latest_entry_time)
84 latest_entry_time = temp_entry_time;
85 }
86 fclose (fp);
88 /* run the command to check for the Nagios process.. */
89 child_process = spopen (PS_COMMAND);
90 if (child_process == NULL) {
91 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
92 return STATE_UNKNOWN;
93 }
95 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
96 if (child_stderr == NULL) {
97 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
98 }
100 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
102 /* count the number of matching Nagios processes... */
103 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
104 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
105 if ( cols >= 6 ) {
106 asprintf (&procargs, "%s", input_buffer + pos);
107 strip (procargs);
109 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string)) {
110 proc_entries++;
111 if (verbose)
112 printf (_("Found process: %s\n"), procargs);
113 }
114 }
115 }
117 /* If we get anything on stderr, at least set warning */
118 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
119 result = max_state (result, STATE_WARNING);
121 /* close stderr */
122 (void) fclose (child_stderr);
124 /* close the pipe */
125 if (spclose (child_process))
126 result = max_state (result, STATE_WARNING);
128 /* reset the alarm handler */
129 alarm (0);
131 if (proc_entries == 0) {
132 printf (_("Could not locate a running Nagios process!\n"));
133 return STATE_CRITICAL;
134 }
136 result = STATE_OK;
138 time (¤t_time);
139 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
140 result = STATE_WARNING;
142 printf
143 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
144 (result == STATE_OK) ? "ok" : "problem", proc_entries,
145 (proc_entries == 1) ? "" : "es",
146 (int) (current_time - latest_entry_time),
147 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
149 return result;
150 }
156 /* process command-line arguments */
157 int
158 process_arguments (int argc, char **argv)
159 {
160 int c;
162 int option = 0;
163 static struct option longopts[] = {
164 {"filename", required_argument, 0, 'F'},
165 {"expires", required_argument, 0, 'e'},
166 {"command", required_argument, 0, 'C'},
167 {"version", no_argument, 0, 'V'},
168 {"help", no_argument, 0, 'h'},
169 {"verbose", no_argument, 0, 'v'},
170 {0, 0, 0, 0}
171 };
173 if (argc < 2)
174 return ERROR;
176 if (!is_option (argv[1])) {
177 status_log = argv[1];
178 if (is_intnonneg (argv[2]))
179 expire_minutes = atoi (argv[2]);
180 else
181 die (STATE_UNKNOWN,
182 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
183 progname);
184 process_string = argv[3];
185 return OK;
186 }
188 while (1) {
189 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
191 if (c == -1 || c == EOF || c == 1)
192 break;
194 switch (c) {
195 case '?': /* print short usage statement if args not parsable */
196 printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
197 print_usage ();
198 exit (STATE_UNKNOWN);
199 case 'h': /* help */
200 print_help ();
201 exit (STATE_OK);
202 case 'V': /* version */
203 print_revision (progname, "$Revision$");
204 exit (STATE_OK);
205 case 'F': /* status log */
206 status_log = optarg;
207 break;
208 case 'C': /* command */
209 process_string = optarg;
210 break;
211 case 'e': /* expiry time */
212 if (is_intnonneg (optarg))
213 expire_minutes = atoi (optarg);
214 else
215 die (STATE_UNKNOWN,
216 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
217 progname);
218 break;
219 case 'v':
220 verbose++;
221 break;
222 }
223 }
226 if (status_log == NULL)
227 die (STATE_UNKNOWN,
228 _("You must provide the status_log\nType '%s -h' for additional help\n"),
229 progname);
230 else if (process_string == NULL)
231 die (STATE_UNKNOWN,
232 _("You must provide a process string\nType '%s -h' for additional help\n"),
233 progname);
235 return OK;
236 }
242 \f
243 void
244 print_help (void)
245 {
246 print_revision (progname, revision);
248 printf (_(COPYRIGHT), copyright, email);
250 printf (_("\
251 This plugin attempts to check the status of the Nagios process on the local\n\
252 machine. The plugin will check to make sure the Nagios status log is no older\n\
253 than the number of minutes specified by the <expire_minutes> option. It also\n\
254 uses the /bin/ps command to check for a process matching whatever you specify\n\
255 by the <process_string> argument.\n"));
257 print_usage ();
259 printf (_(UT_HELP_VRSN));
261 printf (_("\
262 -F, --filename=FILE\n\
263 Name of the log file to check\n\
264 -e, --expires=INTEGER\n\
265 Seconds aging afterwhich logfile is condsidered stale\n\
266 -C, --command=STRING\n\
267 Command to search for in process table\n"));
269 printf (_("\
270 Example:\n\
271 ./check_nagios -e 5 \\\
272 -F /usr/local/nagios/var/status.log \\\
273 -C /usr/local/nagios/bin/nagios\n"));
274 }
279 void
280 print_usage (void)
281 {
282 printf (_("\
283 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
284 progname);
285 }