1 /******************************************************************************
2 *
3 * CHECK_SWAP.C
4 *
5 * Program: Process plugin for Nagios
6 * License: GPL
7 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
8 *
9 * $Id$
10 *
11 ******************************************************************************/
13 #include "common.h"
14 #include "popen.h"
15 #include "utils.h"
17 #define PROGNAME "check_swap"
19 int process_arguments (int argc, char **argv);
20 int call_getopt (int argc, char **argv);
21 int validate_arguments (void);
22 void print_usage (void);
23 void print_help (void);
25 int warn_percent = 200, crit_percent = 200, warn_size = -1, crit_size = -1;
27 int
28 main (int argc, char **argv)
29 {
30 int total_swap, used_swap, free_swap, percent_used;
31 int result = STATE_OK;
32 char input_buffer[MAX_INPUT_BUFFER];
33 #ifdef HAVE_SWAP
34 char *temp_buffer;
35 #endif
36 #ifdef HAVE_PROC_MEMINFO
37 FILE *fp;
38 #endif
39 char str[32];
40 char *status = NULL;
42 if (process_arguments (argc, argv) != OK)
43 usage ("Invalid command arguments supplied\n");
45 #ifdef HAVE_PROC_MEMINFO
46 fp = fopen (PROC_MEMINFO, "r");
47 asprintf (&status, "%s", "Swap used:");
48 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
49 sscanf (input_buffer, " %s %d %d %d", str, &total_swap, &used_swap,
50 &free_swap);
51 if (strstr (str, "Swap")) {
52 percent_used = 100 * (((float) used_swap) / ((float) total_swap));
53 asprintf (&status, "%s %2d%% (%d bytes out of %d)",
54 status, percent_used, used_swap, total_swap);
55 if (percent_used >= crit_percent || free_swap <= crit_size)
56 result = STATE_CRITICAL;
57 else if (percent_used >= warn_percent || free_swap <= warn_size)
58 result = STATE_WARNING;
59 break;
60 }
61 }
62 fclose (fp);
63 #else
64 #ifdef HAVE_SWAP
65 child_process = spopen (SWAP_COMMAND);
66 if (child_process == NULL) {
67 printf ("Could not open pipe: %s\n", SWAP_COMMAND);
68 return STATE_UNKNOWN;
69 }
71 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
72 if (child_stderr == NULL)
73 printf ("Could not open stderr for %s\n", SWAP_COMMAND);
75 sprintf (str, "%s", "");
76 /* read 1st line */
77 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
78 if (strcmp (SWAP_FORMAT, "") == 0) {
79 temp_buffer = strtok (input_buffer, " \n");
80 while (temp_buffer) {
81 if (strstr (temp_buffer, "blocks"))
82 sprintf (str, "%s %s", str, "%f");
83 else if (strstr (temp_buffer, "free"))
84 sprintf (str, "%s %s", str, "%f");
85 else
86 sprintf (str, "%s %s", str, "%*s");
87 temp_buffer = strtok (NULL, " \n");
88 }
89 }
91 asprintf (&status, "%s", "Swap used:");
92 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
93 sscanf (input_buffer, SWAP_FORMAT, &total_swap, &free_swap);
94 used_swap = total_swap - free_swap;
95 percent_used = 100 * ((float) used_swap) / ((float) total_swap);
96 asprintf (&status, "%s %2d%% (%d bytes out of %d)",
97 status, percent_used, used_swap, total_swap);
98 if (percent_used >= crit_percent || free_swap <= crit_size)
99 result = STATE_CRITICAL;
100 else if (percent_used >= warn_percent || free_swap <= warn_size)
101 result = STATE_WARNING;
102 }
104 /* If we get anything on STDERR, at least set warning */
105 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
106 result = max (result, STATE_WARNING);
108 /* close stderr */
109 (void) fclose (child_stderr);
111 /* close the pipe */
112 if (spclose (child_process))
113 result = max (result, STATE_WARNING);
114 #endif
115 #endif
117 #ifndef SWAP_COMMAND
118 #ifndef SWAP_FILE
119 #ifndef HAVE_PROC_MEMINFO
120 return STATE_UNKNOWN;
121 #endif
122 #endif
123 #endif
125 if (result == STATE_OK)
126 printf ("Swap ok - %s\n", status);
127 else if (result == STATE_CRITICAL)
128 printf ("CRITICAL - %s\n", status);
129 else if (result == STATE_WARNING)
130 printf ("WARNING - %s\n", status);
131 else if (result == STATE_UNKNOWN)
132 printf ("Unable to read output\n");
133 else {
134 result = STATE_UNKNOWN;
135 printf ("UNKNOWN - %s\n", status);
136 }
138 return result;
139 }
145 /* process command-line arguments */
146 int
147 process_arguments (int argc, char **argv)
148 {
149 int c, i = 0;
151 #ifdef HAVE_GETOPT_H
152 int option_index = 0;
153 static struct option long_options[] = {
154 {"warning", required_argument, 0, 'w'},
155 {"critical", required_argument, 0, 'c'},
156 {"verbose", no_argument, 0, 'v'},
157 {"version", no_argument, 0, 'V'},
158 {"help", no_argument, 0, 'h'},
159 {0, 0, 0, 0}
160 };
161 #endif
163 if (argc < 2)
164 return ERROR;
166 while (1) {
167 #ifdef HAVE_GETOPT_H
168 c = getopt_long (argc, argv, "+?Vhc:w:", long_options, &option_index);
169 #else
170 c = getopt (argc, argv, "+?Vhc:w:");
171 #endif
173 if (c == -1 || c == EOF)
174 break;
176 switch (c) {
177 case 'w': /* warning time threshold */
178 if (is_intnonneg (optarg)) {
179 warn_size = atoi (optarg);
180 break;
181 }
182 else if (strstr (optarg, ",") &&
183 strstr (optarg, "%") &&
184 sscanf (optarg, "%d,%d%%", &warn_size, &warn_percent) == 2) {
185 break;
186 }
187 else if (strstr (optarg, "%") &&
188 sscanf (optarg, "%d%%", &warn_percent) == 1) {
189 break;
190 }
191 else {
192 usage ("Warning threshold must be integer or percentage!\n");
193 }
194 case 'c': /* critical time threshold */
195 if (is_intnonneg (optarg)) {
196 crit_size = atoi (optarg);
197 break;
198 }
199 else if (strstr (optarg, ",") &&
200 strstr (optarg, "%") &&
201 sscanf (optarg, "%d,%d%%", &crit_size, &crit_percent) == 2) {
202 break;
203 }
204 else if (strstr (optarg, "%") &&
205 sscanf (optarg, "%d%%", &crit_percent) == 1) {
206 break;
207 }
208 else {
209 usage ("Critical threshold must be integer or percentage!\n");
210 }
211 case 'V': /* version */
212 print_revision (my_basename (argv[0]), "$Revision$");
213 exit (STATE_OK);
214 case 'h': /* help */
215 print_help ();
216 exit (STATE_OK);
217 case '?': /* help */
218 usage ("Invalid argument\n");
219 }
220 }
222 c = optind;
223 if (c == argc)
224 return validate_arguments ();
225 if (warn_percent > 100 && is_intnonneg (argv[c]))
226 warn_percent = atoi (argv[c++]);
228 if (c == argc)
229 return validate_arguments ();
230 if (crit_percent > 100 && is_intnonneg (argv[c]))
231 crit_percent = atoi (argv[c++]);
233 if (c == argc)
234 return validate_arguments ();
235 if (warn_size < 0 && is_intnonneg (argv[c]))
236 warn_size = atoi (argv[c++]);
238 if (c == argc)
239 return validate_arguments ();
240 if (crit_size < 0 && is_intnonneg (argv[c]))
241 crit_size = atoi (argv[c++]);
243 return validate_arguments ();
244 }
250 int
251 validate_arguments (void)
252 {
253 if (warn_percent > 100 && crit_percent > 100 && warn_size < 0
254 && crit_size < 0) {
255 return ERROR;
256 }
257 else if (warn_percent > crit_percent) {
258 usage
259 ("Warning percentage should not be less than critical percentage\n");
260 }
261 else if (warn_size < crit_size) {
262 usage
263 ("Warning free space should not be more than critical free space\n");
264 }
265 return OK;
266 }
272 void
273 print_usage (void)
274 {
275 printf
276 ("Usage: check_swap -w <used_percentage>%% -c <used_percentage>%%\n"
277 " check_swap -w <bytes_free> -c <bytes_free>\n"
278 " check_swap (-V|--version)\n" " check_swap (-h|--help)\n");
279 }
285 void
286 print_help (void)
287 {
288 print_revision (PROGNAME, "$Revision$");
289 printf
290 ("Copyright (c) 2000 Karl DeBisschop\n\n"
291 "This plugin will check all of the swap partitions and return an\n"
292 "error if the the avalable swap space is less than specified.\n\n");
293 print_usage ();
294 printf
295 ("\nOptions:\n"
296 " -w, --warning=INTEGER\n"
297 " Exit with WARNING status if less than INTEGER bytes of swap space are free\n"
298 " -w, --warning=PERCENT%%\n"
299 " Exit with WARNING status if more than PERCENT of swap space has been used\n"
300 " -c, --critical=INTEGER\n"
301 " Exit with CRITICAL status if less than INTEGER bytes of swap space are free\n"
302 " -c, --critical=PERCENT%%\n"
303 " Exit with CRITCAL status if more than PERCENT of swap space has been used\n"
304 " -h, --help\n"
305 " Print detailed help screen\n"
306 " -V, --version\n" " Print version information\n\n");
307 support ();
308 }