Code

starttls support for check_smtp #1041576
[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-2004";
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 procetime[MAX_INPUT_BUFFER];
58         char procprog[MAX_INPUT_BUFFER];
59         char *procargs;
60         int pos, cols;
61         int expected_cols = PS_COLS - 1;
62         const char *zombie = "Z";
63         char *temp_string;
65         setlocale (LC_ALL, "");
66         bindtextdomain (PACKAGE, LOCALEDIR);
67         textdomain (PACKAGE);
69         if (process_arguments (argc, argv) == ERROR)
70                 usage4 (_("Could not parse arguments"));
72         /* Set signal handling and alarm timeout */
73         if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
74                 usage4 (_("Cannot catch SIGALRM"));
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 (_("CRITICAL - 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(procargs, 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)\n"));
210                 process_string = argv[3];
211                 return OK;
212         }
214         while (1) {
215                 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
217                 if (c == -1 || c == EOF || c == 1)
218                         break;
220                 switch (c) {
221                 case '?':                                                                       /* print short usage statement if args not parsable */
222                         usage2 (_("Unknown argument"), optarg);
223                 case 'h':                                                                       /* help */
224                         print_help ();
225                         exit (STATE_OK);
226                 case 'V':                                                                       /* version */
227                         print_revision (progname, revision);
228                         exit (STATE_OK);
229                 case 'F':                                                                       /* status log */
230                         status_log = optarg;
231                         break;
232                 case 'C':                                                                       /* command */
233                         process_string = optarg;
234                         break;
235                 case 'e':                                                                       /* expiry time */
236                         if (is_intnonneg (optarg))
237                                 expire_minutes = atoi (optarg);
238                         else
239                                 die (STATE_UNKNOWN,
240                                      _("Expiration time must be an integer (seconds)\n"));
241                         break;
242                 case 'v':
243                         verbose++;
244                         break;
245                 }
246         }
249         if (status_log == NULL)
250                 die (STATE_UNKNOWN,
251                      _("You must provide the status_log\n"));
252         else if (process_string == NULL)
253                 die (STATE_UNKNOWN,
254                                                          _("You must provide a process string\n"));
256         return OK;
261 void
262 print_help (void)
264         print_revision (progname, revision);
266         printf (_(COPYRIGHT), copyright, email);
268         printf (_("\
269 This plugin checks the status of the Nagios process on the local\n\
270 machine. The plugin will check to make sure the Nagios status log is no older\n\
271 than the number of minutes specified by the expires option. It also\n\
272 checks the process table for a process matching the command argument.\n\n"));
274         print_usage ();
276         printf (_(UT_HELP_VRSN));
278         printf (_("\
279  -F, --filename=FILE\n\
280    Name of the log file to check\n\
281  -e, --expires=INTEGER\n\
282    Minutes aging after which logfile is considered stale\n\
283  -C, --command=STRING\n\
284    Substring to search for in process arguments\n"));
286         printf (_("\
287 Example:\n\
288    ./check_nagios -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios\n"));
293 void
294 print_usage (void)
296         printf ("\
297 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n", progname);