Code

fixes for using POSIX return codes
[nagiosplug.git] / plugins / check_vsz.c
1 /******************************************************************************
2  *
3  * CHECK_VSZ.C
4  *
5  * Program: Process plugin for Nagios
6  * License: GPL
7  * Copyright (c) 1999,2000 Karl DeBisschop <kdebiss@alum.mit.edu>
8  *
9  * Last Modified: $Date$
10  *
11  * Description:
12  *
13  * This plugin will check for processes whose total image size exceeds
14  * the warning or critical thresholds given on the command line.   With
15  * no command_name, everything that shows up on ps is evaluated.
16  * Otherwise, only jobs with the command_name given are examined.
17  * This program is particularly useful if you have to run a piece of
18  * commercial software that has a memory leak.  With it you can shut
19  * down and restart the processes whenever the program threatens to
20  * take over your system.
21  *
22  * Modifications:
23  *
24  * 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
25  *            change to getopt, use print_help
26  * 08-18-1999 Ethan Galstad (nagios@nagios.org)
27  *            Changed code to use common include file
28  *            Changed fclose() to pclose()
29  * 09-09-1999 Ethan Galstad (nagios@nagios.org)
30  *            Changed popen()/pclose() to spopen()/spclose()
31  * 11-18-1999 Karl DeBisschop (kdebiss@alum.mit.edu)
32  *            set STATE_WARNING of stderr written or nonzero status returned
33  *
34  *****************************************************************************/
36 #include "common.h"
37 #include "popen.h"
38 #include "utils.h"
40 int process_arguments (int argc, char **argv);
41 int call_getopt (int argc, char **argv);
42 void print_help (char *cmd);
43 void print_usage (char *cmd);
45 int warn = -1;
46 int crit = -1;
47 char *proc = NULL;
49 int
50 main (int argc, char **argv)
51 {
52         int len;
53         int result = STATE_OK;
54         int line = 0;
55         int proc_size = -1;
56         char input_buffer[MAX_INPUT_BUFFER];
57         char proc_name[MAX_INPUT_BUFFER];
58         char *message = NULL;
60         if (!process_arguments (argc, argv)) {
61                 printf ("%s: failure parsing arguments\n", my_basename (argv[0]));
62                 print_help (my_basename (argv[0]));
63                 return STATE_UNKNOWN;
64         }
66         /* run the command */
67         child_process = spopen (VSZ_COMMAND);
68         if (child_process == NULL) {
69                 printf ("Unable to open pipe: %s\n", VSZ_COMMAND);
70                 return STATE_UNKNOWN;
71         }
73         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
74         if (child_stderr == NULL)
75                 printf ("Could not open stderr for %s\n", VSZ_COMMAND);
77         message = malloc ((size_t) 1);
78         message[0] = 0;
79         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
81                 line++;
83                 /* skip the first line */
84                 if (line == 1)
85                         continue;
87                 if (sscanf (input_buffer, VSZ_FORMAT, &proc_size, proc_name) == 2) {
88                         if (proc == NULL) {
89                                 if (proc_size > warn) {
90                                         len = strlen (message) + strlen (proc_name) + 23;
91                                         message = realloc (message, len);
92                                         if (message == NULL)
93                                                 terminate (STATE_UNKNOWN,
94                                                                                          "check_vsz: could not malloc message (1)");
95                                         sprintf (message, "%s %s(%d)", message, proc_name, proc_size);
96                                         result = max (result, STATE_WARNING);
97                                 }
98                                 if (proc_size > crit) {
99                                         result = STATE_CRITICAL;
100                                 }
101                         }
102                         else if (strstr (proc_name, proc)) {
103                                 len = strlen (message) + 21;
104                                 message = realloc (message, len);
105                                 if (message == NULL)
106                                         terminate (STATE_UNKNOWN,
107                                                                                  "check_vsz: could not malloc message (2)");
108                                 sprintf (message, "%s %d", message, proc_size);
109                                 if (proc_size > warn) {
110                                         result = max (result, STATE_WARNING);
111                                 }
112                                 if (proc_size > crit) {
113                                         result = STATE_CRITICAL;
114                                 }
115                         }
116                 }
117         }
119         /* If we get anything on STDERR, at least set warning */
120         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
121                 result = max (result, STATE_WARNING);
123         (void) fclose (child_stderr);
125         /* close the pipe */
126         if (spclose (child_process))
127                 result = max (result, STATE_WARNING);
129         if (result == STATE_OK)
130                 printf ("ok (all VSZ<%d): %s\n", warn, message);
131         else if (result == STATE_UNKNOWN)
132                 printf ("Unable to read output\n");
133         else if (result == STATE_WARNING)
134                 printf ("WARNING (VSZ>%d):%s\n", warn, message);
135         else
136                 printf ("CRITICAL (VSZ>%d):%s\n", crit, message);
138         return result;
144 int
145 process_arguments (int argc, char **argv)
147         int c;
149         if (argc < 2)
150                 return ERROR;
152         c = 0;
153         while (c += (call_getopt (argc - c, &argv[c]))) {
154                 if (argc <= c)
155                         break;
156                 if (warn == -1) {
157                         if (!is_intnonneg (argv[c])) {
158                                 printf ("%s: critical threshold must be an integer: %s\n",
159                                                                 my_basename (argv[0]), argv[c]);
160                                 print_usage (my_basename (argv[0]));
161                                 exit (STATE_UNKNOWN);
162                         }
163                         warn = atoi (argv[c]);
164                 }
165                 else if (crit == -1) {
166                         if (!is_intnonneg (argv[c])) {
167                                 printf ("%s: critical threshold must be an integer: %s\n",
168                                                                 my_basename (argv[0]), argv[c]);
169                                 print_usage (my_basename (argv[0]));
170                                 exit (STATE_UNKNOWN);
171                         }
172                         crit = atoi (argv[c]);
173                 }
174                 else if (proc == NULL) {
175                         proc = malloc (strlen (argv[c]) + 1);
176                         if (proc == NULL)
177                                 terminate (STATE_UNKNOWN,
178                                                                          "check_vsz: failed malloc of proc in process_arguments");
179                         strcpy (proc, argv[c]);
180                 }
181         }
182         return c;
185 int
186 call_getopt (int argc, char **argv)
188         int c, i = 1;
190 #ifdef HAVE_GETOPT_H
191         int option_index = 0;
192         static struct option long_options[] = {
193                 {"help", no_argument, 0, 'h'},
194                 {"version", no_argument, 0, 'V'},
195                 {"critical", required_argument, 0, 'c'},
196                 {"warning", required_argument, 0, 'w'},
197                 {"command", required_argument, 0, 'C'},
198                 {0, 0, 0, 0}
199         };
200 #endif
202         while (1) {
203 #ifdef HAVE_GETOPT_H
204                 c = getopt_long (argc, argv, "+hVc:w:C:", long_options, &option_index);
205 #else
206                 c = getopt (argc, argv, "+hVc:w:C:");
207 #endif
208                 if (c == EOF)
209                         break;
211                 i++;
212                 switch (c) {
213                 case 'c':
214                 case 'w':
215                 case 'C':
216                         i++;
217                 }
219                 switch (c) {
220                 case '?':                                                                       /* help */
221                         printf ("%s: Unknown argument: %s\n\n", my_basename (argv[0]), optarg);
222                         print_usage (my_basename (argv[0]));
223                         exit (STATE_UNKNOWN);
224                 case 'h':                                                                       /* help */
225                         print_help (my_basename (argv[0]));
226                         exit (STATE_OK);
227                 case 'V':                                                                       /* version */
228                         print_revision (my_basename (argv[0]), "$Revision$");
229                         exit (STATE_OK);
230                 case 'c':                                                                       /* critical threshold */
231                         if (!is_intnonneg (optarg)) {
232                                 printf ("%s: critical threshold must be an integer: %s\n",
233                                                                 my_basename (argv[0]), optarg);
234                                 print_usage (my_basename (argv[0]));
235                                 exit (STATE_UNKNOWN);
236                         }
237                         crit = atoi (optarg);
238                         break;
239                 case 'w':                                                                       /* warning threshold */
240                         if (!is_intnonneg (optarg)) {
241                                 printf ("%s: warning threshold must be an integer: %s\n",
242                                                                 my_basename (argv[0]), optarg);
243                                 print_usage (my_basename (argv[0]));
244                                 exit (STATE_UNKNOWN);
245                         }
246                         warn = atoi (optarg);
247                         break;
248                 case 'C':                                                                       /* command name */
249                         proc = malloc (strlen (optarg) + 1);
250                         if (proc == NULL)
251                                 terminate (STATE_UNKNOWN,
252                                                                          "check_vsz: failed malloc of proc in process_arguments");
253                         strcpy (proc, optarg);
254                         break;
255                 }
256         }
257         return i;
260 void
261 print_usage (char *cmd)
263         printf ("Usage: %s -w <wsize> -c <csize> [-C command]\n"
264                                         "       %s --help\n" "       %s --version\n", cmd, cmd, cmd);
267 void
268 print_help (char *cmd)
270         print_revision ("check_vsz", "$Revision$");
271         printf
272                 ("Copyright (c) 2000 Karl DeBisschop <kdebiss@alum.mit.edu>\n\n"
273                  "This plugin checks the image size of a running program and returns an\n"
274                  "error if the number is above either of the thresholds given.\n\n");
275         print_usage (cmd);
276         printf
277                 ("\nOptions:\n"
278                  " -h, --help\n"
279                  "    Print detailed help\n"
280                  " -V, --version\n"
281                  "    Print version numbers and license information\n"
282                  " -w, --warning=INTEGER\n"
283                  "    Program image size necessary to cause a WARNING state\n"
284                  " -c, --critical=INTEGER\n"
285                  "    Program image size necessary to cause a CRITICAL state\n"
286                  " -C, --command=STRING\n" "    Program to search for [optional]\n");