summaryrefslogtreecommitdiffstats
path: root/plugins/check_disk.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_disk.c')
-rw-r--r--plugins/check_disk.c353
1 files changed, 353 insertions, 0 deletions
diff --git a/plugins/check_disk.c b/plugins/check_disk.c
new file mode 100644
index 0000000..d7aad07
--- /dev/null
+++ b/plugins/check_disk.c
@@ -0,0 +1,353 @@
1/******************************************************************************
2 *
3 * CHECK_DISK.C
4 *
5 * Program: Disk space plugin for Nagios
6 * License: GPL
7 * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
8 * Copyright (c) 2000 Karl DeBisschop (kdebisschop@users.sourceforge.net)
9 *
10 * $Id$
11 *
12 * Description:
13 *
14 * This plugin will use the /bin/df command to check the free space on
15 * currently mounted filesystems. If the percent used disk space is
16 * above <c_dfp>, a STATE_CRITICAL is returned. If the percent used
17 * disk space is above <w_dfp>, a STATE_WARNING is returned. If the
18 * speicified filesystem cannot be read, a STATE_CRITICAL is returned,
19 * other errors with reading the output result in a STATE_UNKNOWN
20 * error.
21 *
22 * Notes:
23 * - IRIX support added by Charlie Cook 4-16-1999
24 * - Modifications by Karl DeBisschop 1999-11-24
25 * reformat code to 80 char screen width
26 * set STATE_WARNING if stderr is written or spclose status set
27 * set default result to STAT_UNKNOWN
28 * initailize usp to -1, eliminate 'found' variable
29 * accept any filename/filesystem
30 * use sscanf, drop while loop
31 *
32 *****************************************************************************/
33
34#include "common.h"
35#include "popen.h"
36#include "utils.h"
37#include <stdarg.h>
38
39#define PROGNAME "check_disk"
40
41int process_arguments (int, char **);
42int call_getopt (int, char **);
43int validate_arguments (void);
44int check_disk (int usp, int free_disk);
45void print_help (void);
46void print_usage (void);
47
48int w_df = -1;
49int c_df = -1;
50float w_dfp = -1.0;
51float c_dfp = -1.0;
52char *path = NULL;
53int verbose = FALSE;
54
55int
56main (int argc, char **argv)
57{
58 int len;
59 int usp = -1;
60 int total_disk = -1;
61 int used_disk = -1;
62 int free_disk = -1;
63 int result = STATE_UNKNOWN;
64 char *command_line = NULL;
65 char input_buffer[MAX_INPUT_BUFFER] = "";
66 char file_system[MAX_INPUT_BUFFER] = "";
67 char outbuf[MAX_INPUT_BUFFER] = "";
68 char *output = NULL;
69
70 if (process_arguments (argc, argv) != OK)
71 usage ("Could not parse arguments\n");
72
73 command_line = ssprintf (command_line, "%s %s", DF_COMMAND, path);
74
75 if (verbose)
76 printf ("%s ==> ", command_line);
77
78 child_process = spopen (command_line);
79 if (child_process == NULL) {
80 printf ("Could not open pipe: %s\n", command_line);
81 return STATE_UNKNOWN;
82 }
83
84 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
85 if (child_stderr == NULL) {
86 printf ("Could not open stderr for %s\n", command_line);
87 }
88
89 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
90
91 if (!index (input_buffer, '/'))
92 continue;
93
94 if (sscanf
95 (input_buffer, "%s %d %d %d %d%%", file_system, &total_disk,
96 &used_disk, &free_disk, &usp) == 5
97 || sscanf (input_buffer, "%s %*s %d %d %d %d%%", file_system,
98 &total_disk, &used_disk, &free_disk, &usp) == 5) {
99 result = max (result, check_disk (usp, free_disk));
100 len =
101 snprintf (outbuf, MAX_INPUT_BUFFER - 1,
102 " [%d kB (%d%%) free on %s]", free_disk, 100 - usp,
103 file_system);
104 outbuf[len] = 0;
105 output = strscat (output, outbuf);
106 }
107 else {
108 printf ("Unable to read output:\n%s\n%s\n", command_line, input_buffer);
109 return result;
110 }
111 }
112
113 /* If we get anything on stderr, at least set warning */
114 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
115 result = max (result, STATE_WARNING);
116
117 /* close stderr */
118 (void) fclose (child_stderr);
119
120 /* close the pipe */
121 if (spclose (child_process))
122 result = max (result, STATE_WARNING);
123
124 else if (usp < 0)
125 printf ("Disk %s not mounted or nonexistant\n", argv[3]);
126 else if (result == STATE_UNKNOWN)
127 printf ("Unable to read output\n%s\n%s\n", command_line, input_buffer);
128 else
129 printf ("DISK %s -%s\n", state_text (result), output);
130
131 return result;
132}
133
134/* process command-line arguments */
135int
136process_arguments (int argc, char **argv)
137{
138 int c;
139
140 if (argc < 2)
141 return ERROR;
142
143 for (c = 1; c < argc; c++) {
144 if (strcmp ("-to", argv[c]) == 0) {
145 strcpy (argv[c], "-t");
146 }
147 }
148
149 c = 0;
150 while ((c += (call_getopt (argc - c, &argv[c]))) < argc) {
151
152 if (w_dfp == -1 && is_intnonneg (argv[c]))
153 w_dfp = (100.0 - atof (argv[c]));
154 else if (c_dfp == -1 && is_intnonneg (argv[c]))
155 c_dfp = (100.0 - atof (argv[c]));
156 else if (path == NULL || path[0] == 0)
157 path = strscpy (path, argv[c]);
158 }
159
160 if (path == NULL) {
161 path = malloc (1);
162 if (path == NULL)
163 terminate (STATE_UNKNOWN, "Could not malloc empty path\n");
164 path[0] = 0;
165 }
166
167 return validate_arguments ();
168}
169
170int
171call_getopt (int argc, char **argv)
172{
173 int c, i = 0;
174
175#ifdef HAVE_GETOPT_H
176 int option_index = 0;
177 static struct option long_options[] = {
178 {"warning", required_argument, 0, 'w'},
179 {"critical", required_argument, 0, 'c'},
180 {"timeout", required_argument, 0, 't'},
181 {"path", required_argument, 0, 'p'},
182 {"partition", required_argument, 0, 'p'},
183 {"verbose", no_argument, 0, 'v'},
184 {"version", no_argument, 0, 'V'},
185 {"help", no_argument, 0, 'h'},
186 {0, 0, 0, 0}
187 };
188#endif
189
190 while (1) {
191#ifdef HAVE_GETOPT_H
192 c =
193 getopt_long (argc, argv, "+?Vhvt:c:w:p:", long_options, &option_index);
194#else
195 c = getopt (argc, argv, "+?Vhvt:c:w:p:");
196#endif
197
198 i++;
199
200 if (c == -1 || c == EOF || c == 1)
201 break;
202
203 switch (c) {
204 case 't':
205 case 'c':
206 case 'w':
207 case 'p':
208 i++;
209 }
210
211 switch (c) {
212 case 'w': /* warning time threshold */
213 if (is_intnonneg (optarg)) {
214 w_df = atoi (optarg);
215 break;
216 }
217 else if (strpbrk (optarg, ",:") &&
218 strstr (optarg, "%") &&
219 sscanf (optarg, "%d%*[:,]%f%%", &w_df, &w_dfp) == 2) {
220 break;
221 }
222 else if (strstr (optarg, "%") && sscanf (optarg, "%f%%", &w_dfp) == 1) {
223 break;
224 }
225 else {
226 usage ("Warning threshold must be integer or percentage!\n");
227 }
228 case 'c': /* critical time threshold */
229 if (is_intnonneg (optarg)) {
230 c_df = atoi (optarg);
231 break;
232 }
233 else if (strpbrk (optarg, ",:") &&
234 strstr (optarg, "%") &&
235 sscanf (optarg, "%d%*[,:]%f%%", &c_df, &c_dfp) == 2) {
236 break;
237 }
238 else if (strstr (optarg, "%") && sscanf (optarg, "%f%%", &c_dfp) == 1) {
239 break;
240 }
241 else {
242 usage ("Critical threshold must be integer or percentage!\n");
243 }
244 case 't': /* timeout period */
245 if (is_integer (optarg)) {
246 timeout_interval = atoi (optarg);
247 break;
248 }
249 else {
250 usage ("Timeout Interval must be an integer!\n");
251 }
252 case 'p': /* path or partition */
253 path = optarg;
254 break;
255 case 'v': /* verbose */
256 verbose = TRUE;
257 break;
258 case 'V': /* version */
259 print_revision (my_basename (argv[0]), "$Revision$");
260 exit (STATE_OK);
261 case 'h': /* help */
262 print_help ();
263 exit (STATE_OK);
264 case '?': /* help */
265 usage ("check_disk: unrecognized option\n");
266 break;
267 }
268 }
269 return i;
270}
271
272int
273validate_arguments ()
274{
275 if (w_df < 0 && c_df < 0 && w_dfp < 0 && c_dfp < 0) {
276 printf ("INPUT ERROR: Unable to parse command line\n");
277 return ERROR;
278 }
279 else if ((w_dfp >= 0 || c_dfp >= 0)
280 && (w_dfp < 0 || c_dfp < 0 || w_dfp > 100 || c_dfp > 100
281 || c_dfp > w_dfp)) {
282 printf
283 ("INPUT ERROR: C_DFP (%f) should be less than W_DFP (%f) and both should be between zero and 100 percent, inclusive\n",
284 c_dfp, w_dfp);
285 return ERROR;
286 }
287 else if ((w_df > 0 || c_df > 0) && (w_df < 0 || c_df < 0 || c_df > w_df)) {
288 printf
289 ("INPUT ERROR: C_DF (%d) should be less than W_DF (%d) and both should be greater than zero\n",
290 c_df, w_df);
291 return ERROR;
292 }
293 else {
294 return OK;
295 }
296}
297
298int
299check_disk (usp, free_disk)
300{
301 int result = STATE_UNKNOWN;
302 /* check the percent used space against thresholds */
303 if (usp >= 0 && usp >= (100.0 - c_dfp))
304 result = STATE_CRITICAL;
305 else if (c_df >= 0 && free_disk <= c_df)
306 result = STATE_CRITICAL;
307 else if (usp >= 0 && usp >= (100.0 - w_dfp))
308 result = STATE_WARNING;
309 else if (w_df >= 0 && free_disk <= w_df)
310 result = STATE_WARNING;
311 else if (usp >= 0.0)
312 result = STATE_OK;
313 return result;
314}
315
316void
317print_help (void)
318{
319 print_revision (PROGNAME, "$Revision$");
320 printf
321 ("Copyright (c) 2000 Ethan Galstad/Karl DeBisschop\n\n"
322 "This plugin will check the percent of used disk space on a mounted\n"
323 "file system and generate an alert if percentage is above one of the\n"
324 "threshold values.\n\n");
325 print_usage ();
326 printf
327 ("\nOptions:\n"
328 " -w, --warning=INTEGER\n"
329 " Exit with WARNING status if less than INTEGER kilobytes of disk are free\n"
330 " -w, --warning=PERCENT%%\n"
331 " Exit with WARNING status if more than PERCENT of disk space is free\n"
332 " -c, --critical=INTEGER\n"
333 " Exit with CRITICAL status if less than INTEGER kilobytes of disk are free\n"
334 " -c, --critical=PERCENT%%\n"
335 " Exit with CRITCAL status if more than PERCENT of disk space is free\n"
336 " -p, --path=PATH, --partition=PARTTION\n"
337 " Path or partition (checks all mounted partitions if unspecified)\n"
338 " -v, --verbose\n"
339 " Show details for command-line debugging (do not use with nagios server)\n"
340 " -h, --help\n"
341 " Print detailed help screen\n"
342 " -V, --version\n" " Print version information\n\n");
343 support ();
344}
345
346void
347print_usage (void)
348{
349 printf
350 ("Usage: %s -w limit -c limit [-p path] [-t timeout] [--verbose]\n"
351 " %s (-h|--help)\n"
352 " %s (-V|--version)\n", PROGNAME, PROGNAME, PROGNAME);
353}