summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/maxfd.c26
-rw-r--r--lib/maxfd.h9
-rw-r--r--lib/parse_ini.c4
-rw-r--r--lib/tests/Makefile.am2
-rw-r--r--lib/tests/test_cmd.c14
-rw-r--r--lib/tests/test_disk.c4
-rwxr-xr-xlib/tests/test_ini3.t2
-rwxr-xr-xlib/tests/test_opts3.t2
-rw-r--r--lib/tests/test_utils.c8
-rw-r--r--lib/utils_base.c75
-rw-r--r--lib/utils_base.h10
-rw-r--r--lib/utils_cmd.c73
-rw-r--r--lib/utils_cmd.h4
-rw-r--r--lib/utils_disk.c36
-rw-r--r--lib/utils_disk.h6
16 files changed, 194 insertions, 83 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 01d73a6..1a47395 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -7,7 +7,7 @@ noinst_LIBRARIES = libmonitoringplug.a
7AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \ 7AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \
8 -I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins 8 -I$(srcdir) -I$(top_srcdir)/gl -I$(top_srcdir)/intl -I$(top_srcdir)/plugins
9 9
10libmonitoringplug_a_SOURCES = utils_base.c utils_disk.c utils_tcp.c utils_cmd.c 10libmonitoringplug_a_SOURCES = utils_base.c utils_disk.c utils_tcp.c utils_cmd.c maxfd.c
11EXTRA_DIST = utils_base.h utils_disk.h utils_tcp.h utils_cmd.h parse_ini.h extra_opts.h 11EXTRA_DIST = utils_base.h utils_disk.h utils_tcp.h utils_cmd.h parse_ini.h extra_opts.h
12 12
13if USE_PARSE_INI 13if USE_PARSE_INI
diff --git a/lib/maxfd.c b/lib/maxfd.c
new file mode 100644
index 0000000..529b356
--- /dev/null
+++ b/lib/maxfd.c
@@ -0,0 +1,26 @@
1#include "./maxfd.h"
2#include <errno.h>
3
4long mp_open_max (void) {
5 long maxfd = 0L;
6 /* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
7 * If that fails and the macro isn't defined, we fall back to an educated
8 * guess. There's no guarantee that our guess is adequate and the program
9 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
10
11#ifdef _SC_OPEN_MAX
12 errno = 0;
13 if ((maxfd = sysconf (_SC_OPEN_MAX)) < 0) {
14 if (errno == 0)
15 maxfd = DEFAULT_MAXFD; /* it's indeterminate */
16 else
17 die (STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n"));
18 }
19#elif defined(OPEN_MAX)
20 return OPEN_MAX
21#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
22 return DEFAULT_MAXFD;
23#endif
24
25 return(maxfd);
26}
diff --git a/lib/maxfd.h b/lib/maxfd.h
new file mode 100644
index 0000000..45218d0
--- /dev/null
+++ b/lib/maxfd.h
@@ -0,0 +1,9 @@
1#ifndef _MAXFD_
2#define _MAXFD_
3
4#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
5#define MAXFD_LIMIT 8192 /* upper limit of open files */
6
7long mp_open_max (void);
8
9#endif // _MAXFD_
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 25abc89..547af43 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -78,7 +78,7 @@ static char *default_file_in_path(void);
78/* 78/*
79 * Parse_locator decomposes a string of the form 79 * Parse_locator decomposes a string of the form
80 * [stanza][@filename] 80 * [stanza][@filename]
81 * into its seperate parts. 81 * into its separate parts.
82 */ 82 */
83static void 83static void
84parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) 84parse_locator(const char *locator, const char *def_stanza, np_ini_info *i)
@@ -169,7 +169,7 @@ read_defaults(FILE *f, const char *stanza, np_arg_list **opts)
169 if (isspace(c)) 169 if (isspace(c))
170 continue; 170 continue;
171 switch (c) { 171 switch (c) {
172 /* globble up coment lines */ 172 /* globble up comment lines */
173 case ';': 173 case ';':
174 case '#': 174 case '#':
175 GOBBLE_TO(f, c, '\n'); 175 GOBBLE_TO(f, c, '\n');
diff --git a/lib/tests/Makefile.am b/lib/tests/Makefile.am
index a8d7ade..31d79df 100644
--- a/lib/tests/Makefile.am
+++ b/lib/tests/Makefile.am
@@ -27,7 +27,7 @@ endif
27 27
28AM_CFLAGS = -g -I$(top_srcdir)/lib -I$(top_srcdir)/gl $(tap_cflags) 28AM_CFLAGS = -g -I$(top_srcdir)/lib -I$(top_srcdir)/gl $(tap_cflags)
29AM_LDFLAGS = $(tap_ldflags) -ltap 29AM_LDFLAGS = $(tap_ldflags) -ltap
30LDADD = $(top_srcdir)/lib/libmonitoringplug.a $(top_srcdir)/gl/libgnu.a 30LDADD = $(top_srcdir)/lib/libmonitoringplug.a $(top_srcdir)/gl/libgnu.a $(LIB_CRYPTO)
31 31
32SOURCES = test_utils.c test_disk.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c 32SOURCES = test_utils.c test_disk.c test_tcp.c test_cmd.c test_base64.c test_ini1.c test_ini3.c test_opts1.c test_opts2.c test_opts3.c
33 33
diff --git a/lib/tests/test_cmd.c b/lib/tests/test_cmd.c
index 29ca42a..4bb60aa 100644
--- a/lib/tests/test_cmd.c
+++ b/lib/tests/test_cmd.c
@@ -176,14 +176,14 @@ main (int argc, char **argv)
176 ok (result == UNSET, "(initialised) Checking exit code is reset"); 176 ok (result == UNSET, "(initialised) Checking exit code is reset");
177 177
178 command = (char *)malloc(COMMAND_LINE); 178 command = (char *)malloc(COMMAND_LINE);
179 strcpy(command, "/bin/echo3456 non-existant command"); 179 strcpy(command, "/bin/echo3456 non-existent command");
180 result = cmd_run (command, &chld_out, &chld_err, 0); 180 result = cmd_run (command, &chld_out, &chld_err, 0);
181 181
182 ok (chld_out.lines == 0, 182 ok (chld_out.lines == 0,
183 "Non existant command, so no output"); 183 "Non existent command, so no output");
184 ok (chld_err.lines == 0, 184 ok (chld_err.lines == 0,
185 "No stderr either"); 185 "No stderr either");
186 ok (result == 3, "Get return code 3 (?) for non-existant command"); 186 ok (result == 3, "Get return code 3 (?) for non-existent command");
187 187
188 188
189 /* ensure everything is empty again */ 189 /* ensure everything is empty again */
@@ -192,14 +192,14 @@ main (int argc, char **argv)
192 result = UNSET; 192 result = UNSET;
193 193
194 command = (char *)malloc(COMMAND_LINE); 194 command = (char *)malloc(COMMAND_LINE);
195 strcpy(command, "/bin/sh non-existant-file"); 195 strcpy(command, "/bin/sh non-existent-file");
196 result = cmd_run (command, &chld_out, &chld_err, 0); 196 result = cmd_run (command, &chld_out, &chld_err, 0);
197 197
198 ok (chld_out.lines == 0, 198 ok (chld_out.lines == 0,
199 "/bin/sh returns no stdout when file is missing..."); 199 "/bin/sh returns no stdout when file is missing...");
200 ok (chld_err.lines == 1, 200 ok (chld_err.lines == 1,
201 "...but does give an error line"); 201 "...but does give an error line");
202 ok (strstr(chld_err.line[0],"non-existant-file") != NULL, "And missing filename is in error message"); 202 ok (strstr(chld_err.line[0],"non-existent-file") != NULL, "And missing filename is in error message");
203 ok (result != 0, "Get non-zero return code from /bin/sh"); 203 ok (result != 0, "Get non-zero return code from /bin/sh");
204 204
205 205
@@ -219,11 +219,11 @@ main (int argc, char **argv)
219 result = UNSET; 219 result = UNSET;
220 220
221 command = (char *)malloc(COMMAND_LINE); 221 command = (char *)malloc(COMMAND_LINE);
222 strcpy(command, "/bin/non-existant-command"); 222 strcpy(command, "/bin/non-existent-command");
223 result = cmd_run (command, &chld_out, &chld_err, 0); 223 result = cmd_run (command, &chld_out, &chld_err, 0);
224 224
225 ok (chld_out.lines == 0, 225 ok (chld_out.lines == 0,
226 "/bin/non-existant-command returns no stdout..."); 226 "/bin/non-existent-command returns no stdout...");
227 ok (chld_err.lines == 0, 227 ok (chld_err.lines == 0,
228 "...and no stderr output either"); 228 "...and no stderr output either");
229 ok (result == 3, "Get return code 3 = UNKNOWN when command does not exist"); 229 ok (result == 3, "Get return code 3 = UNKNOWN when command does not exist");
diff --git a/lib/tests/test_disk.c b/lib/tests/test_disk.c
index f6477ac..9bd68c7 100644
--- a/lib/tests/test_disk.c
+++ b/lib/tests/test_disk.c
@@ -88,10 +88,10 @@ main (int argc, char **argv)
88 cflags, 3,strdup("regex on dev names:")); 88 cflags, 3,strdup("regex on dev names:"));
89 np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"), 89 np_test_mount_entry_regex(dummy_mount_list, strdup("/foo"),
90 cflags, 0, 90 cflags, 0,
91 strdup("regex on non existant dev/path:")); 91 strdup("regex on non existent dev/path:"));
92 np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"), 92 np_test_mount_entry_regex(dummy_mount_list, strdup("/Foo"),
93 cflags | REG_ICASE,0, 93 cflags | REG_ICASE,0,
94 strdup("regi on non existant dev/path:")); 94 strdup("regi on non existent dev/path:"));
95 np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"), 95 np_test_mount_entry_regex(dummy_mount_list, strdup("/c.t0"),
96 cflags, 3, 96 cflags, 3,
97 strdup("partial devname regex match:")); 97 strdup("partial devname regex match:"));
diff --git a/lib/tests/test_ini3.t b/lib/tests/test_ini3.t
index a2ca94a..41169db 100755
--- a/lib/tests/test_ini3.t
+++ b/lib/tests/test_ini3.t
@@ -10,7 +10,7 @@ if (! -e "./test_ini3") {
10# array of argument arrays 10# array of argument arrays
11# - First value is the expected return code 11# - First value is the expected return code
12# - 2nd value is the NAGIOS_CONFIG_PATH 12# - 2nd value is the NAGIOS_CONFIG_PATH
13# TODO: looks like we look in default path after looking trough this variable - shall we? 13# TODO: looks like we look in default path after looking through this variable - shall we?
14# - 3rd value is the plugin name 14# - 3rd value is the plugin name
15# - 4th is the ini locator 15# - 4th is the ini locator
16my @TESTS = ( 16my @TESTS = (
diff --git a/lib/tests/test_opts3.t b/lib/tests/test_opts3.t
index 8d974ca..d77a35c 100755
--- a/lib/tests/test_opts3.t
+++ b/lib/tests/test_opts3.t
@@ -10,7 +10,7 @@ if (! -e "./test_opts3") {
10# array of argument arrays 10# array of argument arrays
11# - First value is the expected return code 11# - First value is the expected return code
12# - 2nd value is the NAGIOS_CONFIG_PATH 12# - 2nd value is the NAGIOS_CONFIG_PATH
13# TODO: looks like we look in default path after looking trough this variable - shall we? 13# TODO: looks like we look in default path after looking through this variable - shall we?
14# - 3rd value is the plugin name 14# - 3rd value is the plugin name
15# - 4th and up are arguments 15# - 4th and up are arguments
16my @TESTS = ( 16my @TESTS = (
diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c
index f35b7e2..7b10494 100644
--- a/lib/tests/test_utils.c
+++ b/lib/tests/test_utils.c
@@ -309,7 +309,7 @@ main (int argc, char **argv)
309 309
310 /* This is the result of running ./test_utils */ 310 /* This is the result of running ./test_utils */
311 temp_string = (char *) _np_state_generate_key(); 311 temp_string = (char *) _np_state_generate_key();
312 ok(!strcmp(temp_string, "83d877b6cdfefb5d6f06101fd6fe76762f21792c"), "Got hash with exe and no parameters" ) || 312 ok(!strcmp(temp_string, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got hash with exe and no parameters" ) ||
313 diag( "You are probably running in wrong directory. Must run as ./test_utils" ); 313 diag( "You are probably running in wrong directory. Must run as ./test_utils" );
314 314
315 315
@@ -319,7 +319,7 @@ main (int argc, char **argv)
319 this_monitoring_plugin->argv[2] = "--and"; 319 this_monitoring_plugin->argv[2] = "--and";
320 this_monitoring_plugin->argv[3] = "now"; 320 this_monitoring_plugin->argv[3] = "now";
321 temp_string = (char *) _np_state_generate_key(); 321 temp_string = (char *) _np_state_generate_key();
322 ok(!strcmp(temp_string, "94b5e17bf5abf51cb15aff5f69b96f2f8dac5ecd"), "Got based on expected argv" ); 322 ok(!strcmp(temp_string, "bd72da9f78ff1419fad921ea5e43ce56508aef6c"), "Got based on expected argv" );
323 323
324 unsetenv("MP_STATE_PATH"); 324 unsetenv("MP_STATE_PATH");
325 temp_string = (char *) _np_state_calculate_location_prefix(); 325 temp_string = (char *) _np_state_calculate_location_prefix();
@@ -342,7 +342,7 @@ main (int argc, char **argv)
342 np_enable_state(NULL, 51); 342 np_enable_state(NULL, 51);
343 temp_state_key = this_monitoring_plugin->state; 343 temp_state_key = this_monitoring_plugin->state;
344 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" ); 344 ok( !strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name" );
345 ok( !strcmp(temp_state_key->name, "83d877b6cdfefb5d6f06101fd6fe76762f21792c"), "Got generated filename" ); 345 ok( !strcmp(temp_state_key->name, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got generated filename" );
346 346
347 347
348 np_enable_state("allowedchars_in_keyname", 77); 348 np_enable_state("allowedchars_in_keyname", 77);
@@ -395,7 +395,7 @@ main (int argc, char **argv)
395 ok( temp_state_data==NULL, "Older data version gives NULL" ); 395 ok( temp_state_data==NULL, "Older data version gives NULL" );
396 temp_state_key->data_version=54; 396 temp_state_key->data_version=54;
397 397
398 temp_state_key->_filename="var/nonexistant"; 398 temp_state_key->_filename="var/nonexistent";
399 temp_state_data = np_state_read(); 399 temp_state_data = np_state_read();
400 ok( temp_state_data==NULL, "Missing file gives NULL" ); 400 ok( temp_state_data==NULL, "Missing file gives NULL" );
401 ok( this_monitoring_plugin->state->state_data==NULL, "No state information" ); 401 ok( this_monitoring_plugin->state->state_data==NULL, "No state information" );
diff --git a/lib/utils_base.c b/lib/utils_base.c
index 3822bcf..0f52126 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -24,7 +24,7 @@
24* 24*
25*****************************************************************************/ 25*****************************************************************************/
26 26
27#include "common.h" 27#include "../plugins/common.h"
28#include <stdarg.h> 28#include <stdarg.h>
29#include "utils_base.h" 29#include "utils_base.h"
30#include <ctype.h> 30#include <ctype.h>
@@ -37,6 +37,9 @@
37 37
38monitoring_plugin *this_monitoring_plugin=NULL; 38monitoring_plugin *this_monitoring_plugin=NULL;
39 39
40unsigned int timeout_state = STATE_CRITICAL;
41unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
42
40int _np_state_read_file(FILE *); 43int _np_state_read_file(FILE *);
41 44
42void np_init( char *plugin_name, int argc, char **argv ) { 45void np_init( char *plugin_name, int argc, char **argv ) {
@@ -87,10 +90,13 @@ void _get_monitoring_plugin( monitoring_plugin **pointer ){
87void 90void
88die (int result, const char *fmt, ...) 91die (int result, const char *fmt, ...)
89{ 92{
90 va_list ap; 93 if(fmt!=NULL) {
91 va_start (ap, fmt); 94 va_list ap;
92 vprintf (fmt, ap); 95 va_start (ap, fmt);
93 va_end (ap); 96 vprintf (fmt, ap);
97 va_end (ap);
98 }
99
94 if(this_monitoring_plugin!=NULL) { 100 if(this_monitoring_plugin!=NULL) {
95 np_cleanup(); 101 np_cleanup();
96 } 102 }
@@ -122,6 +128,7 @@ range
122 temp_range->end = 0; 128 temp_range->end = 0;
123 temp_range->end_infinity = TRUE; 129 temp_range->end_infinity = TRUE;
124 temp_range->alert_on = OUTSIDE; 130 temp_range->alert_on = OUTSIDE;
131 temp_range->text = strdup(str);
125 132
126 if (str[0] == '@') { 133 if (str[0] == '@') {
127 temp_range->alert_on = INSIDE; 134 temp_range->alert_on = INSIDE;
@@ -312,18 +319,18 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
312 319
313 while (1) { 320 while (1) {
314 /* Strip any leading space */ 321 /* Strip any leading space */
315 for (varlist; isspace(varlist[0]); varlist++); 322 for (; isspace(varlist[0]); varlist++);
316 323
317 if (strncmp(name, varlist, strlen(name)) == 0) { 324 if (strncmp(name, varlist, strlen(name)) == 0) {
318 varlist += strlen(name); 325 varlist += strlen(name);
319 /* strip trailing spaces */ 326 /* strip trailing spaces */
320 for (varlist; isspace(varlist[0]); varlist++); 327 for (; isspace(varlist[0]); varlist++);
321 328
322 if (varlist[0] == '=') { 329 if (varlist[0] == '=') {
323 /* We matched the key, go past the = sign */ 330 /* We matched the key, go past the = sign */
324 varlist++; 331 varlist++;
325 /* strip leading spaces */ 332 /* strip leading spaces */
326 for (varlist; isspace(varlist[0]); varlist++); 333 for (; isspace(varlist[0]); varlist++);
327 334
328 if (tmp = index(varlist, sep)) { 335 if (tmp = index(varlist, sep)) {
329 /* Value is delimited by a comma */ 336 /* Value is delimited by a comma */
@@ -356,6 +363,22 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
356 return value; 363 return value;
357} 364}
358 365
366const char *
367state_text (int result)
368{
369 switch (result) {
370 case STATE_OK:
371 return "OK";
372 case STATE_WARNING:
373 return "WARNING";
374 case STATE_CRITICAL:
375 return "CRITICAL";
376 case STATE_DEPENDENT:
377 return "DEPENDENT";
378 default:
379 return "UNKNOWN";
380 }
381}
359 382
360/* 383/*
361 * Read a string representing a state (ok, warning... or numeric: 0, 1) and 384 * Read a string representing a state (ok, warning... or numeric: 0, 1) and
@@ -379,26 +402,45 @@ int mp_translate_state (char *state_text) {
379 * parse of argv, so that uniqueness in parameters are reflected there. 402 * parse of argv, so that uniqueness in parameters are reflected there.
380 */ 403 */
381char *_np_state_generate_key() { 404char *_np_state_generate_key() {
382 struct sha1_ctx ctx;
383 int i; 405 int i;
384 char **argv = this_monitoring_plugin->argv; 406 char **argv = this_monitoring_plugin->argv;
385 unsigned char result[20];
386 char keyname[41]; 407 char keyname[41];
387 char *p=NULL; 408 char *p=NULL;
388 409
389 sha1_init_ctx(&ctx); 410 unsigned char result[256];
390 411
412#ifdef USE_OPENSSL
413 /*
414 * This code path is chosen if openssl is available (which should be the most common
415 * scenario). Alternatively, the gnulib implementation/
416 *
417 */
418 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
419
420 EVP_DigestInit(ctx, EVP_sha256());
421
391 for(i=0; i<this_monitoring_plugin->argc; i++) { 422 for(i=0; i<this_monitoring_plugin->argc; i++) {
392 sha1_process_bytes(argv[i], strlen(argv[i]), &ctx); 423 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
393 } 424 }
394 425
395 sha1_finish_ctx(&ctx, &result); 426 EVP_DigestFinal(ctx, result, NULL);
396 427#else
428
429 struct sha256_ctx ctx;
430
431 for(i=0; i<this_monitoring_plugin->argc; i++) {
432 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
433 }
434
435 sha256_finish_ctx(&ctx, result);
436#endif // FOUNDOPENSSL
437
397 for (i=0; i<20; ++i) { 438 for (i=0; i<20; ++i) {
398 sprintf(&keyname[2*i], "%02x", result[i]); 439 sprintf(&keyname[2*i], "%02x", result[i]);
399 } 440 }
441
400 keyname[40]='\0'; 442 keyname[40]='\0';
401 443
402 p = strdup(keyname); 444 p = strdup(keyname);
403 if(p==NULL) { 445 if(p==NULL) {
404 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno)); 446 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
@@ -684,4 +726,3 @@ void np_state_write_string(time_t data_time, char *data_string) {
684 726
685 np_free(temp_file); 727 np_free(temp_file);
686} 728}
687
diff --git a/lib/utils_base.h b/lib/utils_base.h
index 42ae0c0..9cb4276 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -2,7 +2,9 @@
2#define _UTILS_BASE_ 2#define _UTILS_BASE_
3/* Header file for Monitoring Plugins utils_base.c */ 3/* Header file for Monitoring Plugins utils_base.c */
4 4
5#include "sha1.h" 5#ifndef USE_OPENSSL
6# include "sha256.h"
7#endif
6 8
7/* This file holds header information for thresholds - use this in preference to 9/* This file holds header information for thresholds - use this in preference to
8 individual plugin logic */ 10 individual plugin logic */
@@ -23,6 +25,7 @@ typedef struct range_struct {
23 double end; 25 double end;
24 int end_infinity; 26 int end_infinity;
25 int alert_on; /* OUTSIDE (default) or INSIDE */ 27 int alert_on; /* OUTSIDE (default) or INSIDE */
28 char* text; /* original unparsed text input */
26 } range; 29 } range;
27 30
28typedef struct thresholds_struct { 31typedef struct thresholds_struct {
@@ -61,6 +64,10 @@ void print_thresholds(const char *, thresholds *);
61int check_range(double, range *); 64int check_range(double, range *);
62int get_status(double, thresholds *); 65int get_status(double, thresholds *);
63 66
67/* Handle timeouts */
68extern unsigned int timeout_state;
69extern unsigned int timeout_interval;
70
64/* All possible characters in a threshold range */ 71/* All possible characters in a threshold range */
65#define NP_THRESHOLDS_CHARS "-0123456789.:@~" 72#define NP_THRESHOLDS_CHARS "-0123456789.:@~"
66 73
@@ -107,5 +114,6 @@ void np_state_write_string(time_t, char *);
107void np_init(char *, int argc, char **argv); 114void np_init(char *, int argc, char **argv);
108void np_set_args(int argc, char **argv); 115void np_set_args(int argc, char **argv);
109void np_cleanup(); 116void np_cleanup();
117const char *state_text (int);
110 118
111#endif /* _UTILS_BASE_ */ 119#endif /* _UTILS_BASE_ */
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 7eb9a3a..f66fd57 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -40,8 +40,22 @@
40 40
41/** includes **/ 41/** includes **/
42#include "common.h" 42#include "common.h"
43#include "utils.h"
43#include "utils_cmd.h" 44#include "utils_cmd.h"
45/* This variable must be global, since there's no way the caller
46 * can forcibly slay a dead or ungainly running program otherwise.
47 * Multithreading apps and plugins can initialize it (via CMD_INIT)
48 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
49 * for the first time.
50 *
51 * The check for initialized values is atomic and can
52 * occur in any number of threads simultaneously. */
53static pid_t *_cmd_pids = NULL;
54
44#include "utils_base.h" 55#include "utils_base.h"
56
57#include "./maxfd.h"
58
45#include <fcntl.h> 59#include <fcntl.h>
46 60
47#ifdef HAVE_SYS_WAIT_H 61#ifdef HAVE_SYS_WAIT_H
@@ -65,31 +79,6 @@ extern char **environ;
65# define SIG_ERR ((Sigfunc *)-1) 79# define SIG_ERR ((Sigfunc *)-1)
66#endif 80#endif
67 81
68/* This variable must be global, since there's no way the caller
69 * can forcibly slay a dead or ungainly running program otherwise.
70 * Multithreading apps and plugins can initialize it (via CMD_INIT)
71 * in an async safe manner PRIOR to calling cmd_run() or cmd_run_array()
72 * for the first time.
73 *
74 * The check for initialized values is atomic and can
75 * occur in any number of threads simultaneously. */
76static pid_t *_cmd_pids = NULL;
77
78/* Try sysconf(_SC_OPEN_MAX) first, as it can be higher than OPEN_MAX.
79 * If that fails and the macro isn't defined, we fall back to an educated
80 * guess. There's no guarantee that our guess is adequate and the program
81 * will die with SIGSEGV if it isn't and the upper boundary is breached. */
82#define DEFAULT_MAXFD 256 /* fallback value if no max open files value is set */
83#define MAXFD_LIMIT 8192 /* upper limit of open files */
84#ifdef _SC_OPEN_MAX
85static long maxfd = 0;
86#elif defined(OPEN_MAX)
87# define maxfd OPEN_MAX
88#else /* sysconf macro unavailable, so guess (may be wildly inaccurate) */
89# define maxfd DEFAULT_MAXFD
90#endif
91
92
93/** prototypes **/ 82/** prototypes **/
94static int _cmd_open (char *const *, int *, int *) 83static int _cmd_open (char *const *, int *, int *)
95 __attribute__ ((__nonnull__ (1, 2, 3))); 84 __attribute__ ((__nonnull__ (1, 2, 3)));
@@ -110,13 +99,7 @@ extern void die (int, const char *, ...)
110void 99void
111cmd_init (void) 100cmd_init (void)
112{ 101{
113#ifndef maxfd 102 long maxfd = mp_open_max();
114 if (!maxfd && (maxfd = sysconf (_SC_OPEN_MAX)) < 0) {
115 /* possibly log or emit a warning here, since there's no
116 * guarantee that our guess at maxfd will be adequate */
117 maxfd = DEFAULT_MAXFD;
118 }
119#endif
120 103
121 /* if maxfd is unnaturally high, we force it to a lower value 104 /* if maxfd is unnaturally high, we force it to a lower value
122 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause 105 * ( e.g. on SunOS, when ulimit is set to unlimited: 2147483647 this would cause
@@ -142,10 +125,6 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
142 125
143 int i = 0; 126 int i = 0;
144 127
145 /* if no command was passed, return with no error */
146 if (argv == NULL)
147 return -1;
148
149 if (!_cmd_pids) 128 if (!_cmd_pids)
150 CMD_INIT; 129 CMD_INIT;
151 130
@@ -176,6 +155,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
176 /* close all descriptors in _cmd_pids[] 155 /* close all descriptors in _cmd_pids[]
177 * This is executed in a separate address space (pure child), 156 * This is executed in a separate address space (pure child),
178 * so we don't have to worry about async safety */ 157 * so we don't have to worry about async safety */
158 long maxfd = mp_open_max();
179 for (i = 0; i < maxfd; i++) 159 for (i = 0; i < maxfd; i++)
180 if (_cmd_pids[i] > 0) 160 if (_cmd_pids[i] > 0)
181 close (i); 161 close (i);
@@ -185,7 +165,7 @@ _cmd_open (char *const *argv, int *pfd, int *pfderr)
185 } 165 }
186 166
187 /* parent picks up execution here */ 167 /* parent picks up execution here */
188 /* close childs descriptors in our address space */ 168 /* close children descriptors in our address space */
189 close (pfd[1]); 169 close (pfd[1]);
190 close (pfderr[1]); 170 close (pfderr[1]);
191 171
@@ -202,6 +182,7 @@ _cmd_close (int fd)
202 pid_t pid; 182 pid_t pid;
203 183
204 /* make sure the provided fd was opened */ 184 /* make sure the provided fd was opened */
185 long maxfd = mp_open_max();
205 if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) 186 if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0)
206 return -1; 187 return -1;
207 188
@@ -293,7 +274,6 @@ _cmd_fetch_output (int fd, output * op, int flags)
293int 274int
294cmd_run (const char *cmdstring, output * out, output * err, int flags) 275cmd_run (const char *cmdstring, output * out, output * err, int flags)
295{ 276{
296 int fd, pfd_out[2], pfd_err[2];
297 int i = 0, argc; 277 int i = 0, argc;
298 size_t cmdlen; 278 size_t cmdlen;
299 char **argv = NULL; 279 char **argv = NULL;
@@ -406,3 +386,20 @@ cmd_file_read ( char *filename, output *out, int flags)
406 386
407 return 0; 387 return 0;
408} 388}
389
390void
391timeout_alarm_handler (int signo)
392{
393 size_t i;
394 if (signo == SIGALRM) {
395 printf (_("%s - Plugin timed out after %d seconds\n"),
396 state_text(timeout_state), timeout_interval);
397
398 long maxfd = mp_open_max();
399 if(_cmd_pids) for(i = 0; i < maxfd; i++) {
400 if(_cmd_pids[i] != 0) kill(_cmd_pids[i], SIGKILL);
401 }
402
403 exit (timeout_state);
404 }
405}
diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h
index ebaf15b..1fc2968 100644
--- a/lib/utils_cmd.h
+++ b/lib/utils_cmd.h
@@ -32,4 +32,8 @@ void cmd_init (void);
32#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */ 32#define CMD_NO_ARRAYS 0x01 /* don't populate arrays at all */
33#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */ 33#define CMD_NO_ASSOC 0x02 /* output.line won't point to buf */
34 34
35
36RETSIGTYPE timeout_alarm_handler (int);
37
38
35#endif /* _UTILS_CMD_ */ 39#endif /* _UTILS_CMD_ */
diff --git a/lib/utils_disk.c b/lib/utils_disk.c
index efe35fc..582d3ea 100644
--- a/lib/utils_disk.c
+++ b/lib/utils_disk.c
@@ -28,6 +28,7 @@
28 28
29#include "common.h" 29#include "common.h"
30#include "utils_disk.h" 30#include "utils_disk.h"
31#include "gl/fsusage.h"
31 32
32void 33void
33np_add_name (struct name_list **list, const char *name) 34np_add_name (struct name_list **list, const char *name)
@@ -46,9 +47,10 @@ np_add_parameter(struct parameter_list **list, const char *name)
46 struct parameter_list *current = *list; 47 struct parameter_list *current = *list;
47 struct parameter_list *new_path; 48 struct parameter_list *new_path;
48 new_path = (struct parameter_list *) malloc (sizeof *new_path); 49 new_path = (struct parameter_list *) malloc (sizeof *new_path);
49 new_path->name = (char *) name; 50 new_path->name = (char *) malloc(strlen(name) + 1);
50 new_path->best_match = NULL; 51 new_path->best_match = NULL;
51 new_path->name_next = NULL; 52 new_path->name_next = NULL;
53 new_path->name_prev = NULL;
52 new_path->freespace_bytes = NULL; 54 new_path->freespace_bytes = NULL;
53 new_path->freespace_units = NULL; 55 new_path->freespace_units = NULL;
54 new_path->freespace_percent = NULL; 56 new_path->freespace_percent = NULL;
@@ -69,16 +71,22 @@ np_add_parameter(struct parameter_list **list, const char *name)
69 new_path->dtotal_units = 0; 71 new_path->dtotal_units = 0;
70 new_path->inodes_total = 0; 72 new_path->inodes_total = 0;
71 new_path->inodes_free = 0; 73 new_path->inodes_free = 0;
74 new_path->inodes_free_to_root = 0;
75 new_path->inodes_used = 0;
72 new_path->dused_inodes_percent = 0; 76 new_path->dused_inodes_percent = 0;
73 new_path->dfree_inodes_percent = 0; 77 new_path->dfree_inodes_percent = 0;
74 78
79 strcpy(new_path->name, name);
80
75 if (current == NULL) { 81 if (current == NULL) {
76 *list = new_path; 82 *list = new_path;
83 new_path->name_prev = NULL;
77 } else { 84 } else {
78 while (current->name_next) { 85 while (current->name_next) {
79 current = current->name_next; 86 current = current->name_next;
80 } 87 }
81 current->name_next = new_path; 88 current->name_next = new_path;
89 new_path->name_prev = current;
82 } 90 }
83 return new_path; 91 return new_path;
84} 92}
@@ -87,6 +95,9 @@ np_add_parameter(struct parameter_list **list, const char *name)
87struct parameter_list * 95struct parameter_list *
88np_del_parameter(struct parameter_list *item, struct parameter_list *prev) 96np_del_parameter(struct parameter_list *item, struct parameter_list *prev)
89{ 97{
98 if (item == NULL) {
99 return NULL;
100 }
90 struct parameter_list *next; 101 struct parameter_list *next;
91 102
92 if (item->name_next) 103 if (item->name_next)
@@ -94,10 +105,17 @@ np_del_parameter(struct parameter_list *item, struct parameter_list *prev)
94 else 105 else
95 next = NULL; 106 next = NULL;
96 107
97 free(item); 108 if (next)
109 next->name_prev = prev;
110
98 if (prev) 111 if (prev)
99 prev->name_next = next; 112 prev->name_next = next;
100 113
114 if (item->name) {
115 free(item->name);
116 }
117 free(item);
118
101 return next; 119 return next;
102} 120}
103 121
@@ -125,11 +143,15 @@ np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list
125 size_t name_len = strlen(d->name); 143 size_t name_len = strlen(d->name);
126 size_t best_match_len = 0; 144 size_t best_match_len = 0;
127 struct mount_entry *best_match = NULL; 145 struct mount_entry *best_match = NULL;
146 struct fs_usage fsp;
128 147
129 /* set best match if path name exactly matches a mounted device name */ 148 /* set best match if path name exactly matches a mounted device name */
130 for (me = mount_list; me; me = me->me_next) { 149 for (me = mount_list; me; me = me->me_next) {
131 if (strcmp(me->me_devname, d->name)==0) 150 if (strcmp(me->me_devname, d->name)==0) {
132 best_match = me; 151 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
152 best_match = me;
153 }
154 }
133 } 155 }
134 156
135 /* set best match by directory name if no match was found by devname */ 157 /* set best match by directory name if no match was found by devname */
@@ -140,8 +162,10 @@ np_set_best_match(struct parameter_list *desired, struct mount_entry *mount_list
140 (len == 1 || strncmp (me->me_mountdir, d->name, len) == 0))) 162 (len == 1 || strncmp (me->me_mountdir, d->name, len) == 0)))
141 || (exact == TRUE && strcmp(me->me_mountdir, d->name)==0)) 163 || (exact == TRUE && strcmp(me->me_mountdir, d->name)==0))
142 { 164 {
143 best_match = me; 165 if (get_fs_usage(me->me_mountdir, me->me_devname, &fsp) >= 0) {
144 best_match_len = len; 166 best_match = me;
167 best_match_len = len;
168 }
145 } 169 }
146 } 170 }
147 } 171 }
diff --git a/lib/utils_disk.h b/lib/utils_disk.h
index 83a3763..3b5a45f 100644
--- a/lib/utils_disk.h
+++ b/lib/utils_disk.h
@@ -24,9 +24,11 @@ struct parameter_list
24 char *group; 24 char *group;
25 struct mount_entry *best_match; 25 struct mount_entry *best_match;
26 struct parameter_list *name_next; 26 struct parameter_list *name_next;
27 uintmax_t total, available, available_to_root, used, inodes_free, inodes_total; 27 struct parameter_list *name_prev;
28 uintmax_t total, available, available_to_root, used,
29 inodes_free, inodes_free_to_root, inodes_used, inodes_total;
28 double dfree_pct, dused_pct; 30 double dfree_pct, dused_pct;
29 double dused_units, dfree_units, dtotal_units; 31 uint64_t dused_units, dfree_units, dtotal_units;
30 double dused_inodes_percent, dfree_inodes_percent; 32 double dused_inodes_percent, dfree_inodes_percent;
31}; 33};
32 34