summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/extra_opts.c55
-rw-r--r--lib/maxfd.c6
-rw-r--r--lib/output.c119
-rw-r--r--lib/output.h31
-rw-r--r--lib/parse_ini.c239
-rw-r--r--lib/perfdata.c72
-rw-r--r--lib/perfdata.h48
-rw-r--r--lib/tests/test_base64.c271
-rw-r--r--lib/tests/test_cmd.c41
-rw-r--r--lib/tests/test_generic_output.c6
-rw-r--r--lib/tests/test_ini1.c54
-rw-r--r--lib/tests/test_opts1.c51
-rw-r--r--lib/tests/test_opts2.c86
-rw-r--r--lib/tests/test_tcp.c28
-rw-r--r--lib/tests/test_utils.c190
-rw-r--r--lib/thresholds.h4
-rw-r--r--lib/utils_base.c445
-rw-r--r--lib/utils_base.h29
-rw-r--r--lib/utils_cmd.c198
-rw-r--r--lib/utils_cmd.h10
-rw-r--r--lib/utils_tcp.c41
-rw-r--r--lib/utils_tcp.h3
23 files changed, 939 insertions, 1090 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a9f3ff40..27a08278 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -4,7 +4,7 @@ SUBDIRS = . tests
4 4
5noinst_LIBRARIES = libmonitoringplug.a 5noinst_LIBRARIES = libmonitoringplug.a
6 6
7AM_CPPFLAGS = -DNP_STATE_DIR_PREFIX=\"$(localstatedir)\" \ 7AM_CPPFLAGS = \
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_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c 10libmonitoringplug_a_SOURCES = utils_base.c utils_tcp.c utils_cmd.c maxfd.c output.c perfdata.c output.c thresholds.c vendor/cJSON/cJSON.c
diff --git a/lib/extra_opts.c b/lib/extra_opts.c
index 88787336..3fe69014 100644
--- a/lib/extra_opts.c
+++ b/lib/extra_opts.c
@@ -27,27 +27,32 @@
27 27
28/* FIXME: copied from utils.h; we should move a bunch of libs! */ 28/* FIXME: copied from utils.h; we should move a bunch of libs! */
29bool is_option2(char *str) { 29bool is_option2(char *str) {
30 if (!str) 30 if (!str) {
31 return false; 31 return false;
32 else if (strspn(str, "-") == 1 || strspn(str, "-") == 2) 32 }
33
34 if (strspn(str, "-") == 1 || strspn(str, "-") == 2) {
33 return true; 35 return true;
34 else 36 }
35 return false; 37
38 return false;
36} 39}
37 40
38/* this is the externally visible function used by plugins */ 41/* this is the externally visible function used by plugins */
39char **np_extra_opts(int *argc, char **argv, const char *plugin_name) { 42char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
40 np_arg_list *extra_args = NULL, *ea1 = NULL, *ea_tmp = NULL;
41 char **argv_new = NULL;
42 char *argptr = NULL;
43 int i, j, optfound, argc_new, ea_num = *argc;
44
45 if (*argc < 2) { 43 if (*argc < 2) {
46 /* No arguments provided */ 44 /* No arguments provided */
47 return argv; 45 return argv;
48 } 46 }
49 47
50 for (i = 1; i < *argc; i++) { 48 np_arg_list *extra_args = NULL;
49 np_arg_list *ea1 = NULL;
50 np_arg_list *ea_tmp = NULL;
51 char *argptr = NULL;
52 int optfound;
53 size_t ea_num = (size_t)*argc;
54
55 for (int i = 1; i < *argc; i++) {
51 argptr = NULL; 56 argptr = NULL;
52 optfound = 0; 57 optfound = 0;
53 58
@@ -56,8 +61,10 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
56 /* It is a single argument with value */ 61 /* It is a single argument with value */
57 argptr = argv[i] + 13; 62 argptr = argv[i] + 13;
58 /* Delete the extra opts argument */ 63 /* Delete the extra opts argument */
59 for (j = i; j < *argc; j++) 64 for (int j = i; j < *argc; j++) {
60 argv[j] = argv[j + 1]; 65 argv[j] = argv[j + 1];
66 }
67
61 i--; 68 i--;
62 *argc -= 1; 69 *argc -= 1;
63 } else if (strcmp(argv[i], "--extra-opts") == 0) { 70 } else if (strcmp(argv[i], "--extra-opts") == 0) {
@@ -65,8 +72,10 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
65 /* It is a argument with separate value */ 72 /* It is a argument with separate value */
66 argptr = argv[i + 1]; 73 argptr = argv[i + 1];
67 /* Delete the extra-opts argument/value */ 74 /* Delete the extra-opts argument/value */
68 for (j = i; j < *argc - 1; j++) 75 for (int j = i; j < *argc - 1; j++) {
69 argv[j] = argv[j + 2]; 76 argv[j] = argv[j + 2];
77 }
78
70 i -= 2; 79 i -= 2;
71 *argc -= 2; 80 *argc -= 2;
72 ea_num--; 81 ea_num--;
@@ -74,8 +83,10 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
74 /* It has no value */ 83 /* It has no value */
75 optfound = 1; 84 optfound = 1;
76 /* Delete the extra opts argument */ 85 /* Delete the extra opts argument */
77 for (j = i; j < *argc; j++) 86 for (int j = i; j < *argc; j++) {
78 argv[j] = argv[j + 1]; 87 argv[j] = argv[j + 1];
88 }
89
79 i--; 90 i--;
80 *argc -= 1; 91 *argc -= 1;
81 } 92 }
@@ -94,34 +105,37 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
94 /* append the list to extra_args */ 105 /* append the list to extra_args */
95 if (extra_args == NULL) { 106 if (extra_args == NULL) {
96 extra_args = ea1; 107 extra_args = ea1;
97 while ((ea1 = ea1->next)) 108 while ((ea1 = ea1->next)) {
98 ea_num++; 109 ea_num++;
110 }
99 } else { 111 } else {
100 ea_tmp = extra_args; 112 ea_tmp = extra_args;
101 while (ea_tmp->next) { 113 while (ea_tmp->next) {
102 ea_tmp = ea_tmp->next; 114 ea_tmp = ea_tmp->next;
103 } 115 }
104 ea_tmp->next = ea1; 116 ea_tmp->next = ea1;
105 while ((ea1 = ea1->next)) 117 while ((ea1 = ea1->next)) {
106 ea_num++; 118 ea_num++;
119 }
107 } 120 }
108 ea1 = ea_tmp = NULL; 121 ea1 = ea_tmp = NULL;
109 } 122 }
110 } /* lather, rince, repeat */ 123 } /* lather, rince, repeat */
111 124
112 if (ea_num == *argc && extra_args == NULL) { 125 if (ea_num == (size_t)*argc && extra_args == NULL) {
113 /* No extra-opts */ 126 /* No extra-opts */
114 return argv; 127 return argv;
115 } 128 }
116 129
117 /* done processing arguments. now create a new argv array... */ 130 /* done processing arguments. now create a new argv array... */
118 argv_new = (char **)malloc((ea_num + 1) * sizeof(char **)); 131 char **argv_new = (char **)malloc((ea_num + 1) * sizeof(char **));
119 if (argv_new == NULL) 132 if (argv_new == NULL) {
120 die(STATE_UNKNOWN, _("malloc() failed!\n")); 133 die(STATE_UNKNOWN, _("malloc() failed!\n"));
134 }
121 135
122 /* starting with program name */ 136 /* starting with program name */
123 argv_new[0] = argv[0]; 137 argv_new[0] = argv[0];
124 argc_new = 1; 138 int argc_new = 1;
125 /* then parsed ini opts (frying them up in the same run) */ 139 /* then parsed ini opts (frying them up in the same run) */
126 while (extra_args) { 140 while (extra_args) {
127 argv_new[argc_new++] = extra_args->arg; 141 argv_new[argc_new++] = extra_args->arg;
@@ -130,8 +144,9 @@ char **np_extra_opts(int *argc, char **argv, const char *plugin_name) {
130 free(ea1); 144 free(ea1);
131 } 145 }
132 /* finally the rest of the argv array */ 146 /* finally the rest of the argv array */
133 for (i = 1; i < *argc; i++) 147 for (int i = 1; i < *argc; i++) {
134 argv_new[argc_new++] = argv[i]; 148 argv_new[argc_new++] = argv[i];
149 }
135 *argc = argc_new; 150 *argc = argc_new;
136 /* and terminate. */ 151 /* and terminate. */
137 argv_new[argc_new] = NULL; 152 argv_new[argc_new] = NULL;
diff --git a/lib/maxfd.c b/lib/maxfd.c
index ca5b6e54..a0f79949 100644
--- a/lib/maxfd.c
+++ b/lib/maxfd.c
@@ -19,7 +19,6 @@
19 *****************************************************************************/ 19 *****************************************************************************/
20 20
21#include "./maxfd.h" 21#include "./maxfd.h"
22#include <errno.h>
23 22
24long mp_open_max(void) { 23long mp_open_max(void) {
25 long maxfd = 0L; 24 long maxfd = 0L;
@@ -31,10 +30,11 @@ long mp_open_max(void) {
31#ifdef _SC_OPEN_MAX 30#ifdef _SC_OPEN_MAX
32 errno = 0; 31 errno = 0;
33 if ((maxfd = sysconf(_SC_OPEN_MAX)) < 0) { 32 if ((maxfd = sysconf(_SC_OPEN_MAX)) < 0) {
34 if (errno == 0) 33 if (errno == 0) {
35 maxfd = DEFAULT_MAXFD; /* it's indeterminate */ 34 maxfd = DEFAULT_MAXFD; /* it's indeterminate */
36 else 35 } else {
37 die(STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n")); 36 die(STATE_UNKNOWN, _("sysconf error for _SC_OPEN_MAX\n"));
37 }
38 } 38 }
39#elif defined(OPEN_MAX) 39#elif defined(OPEN_MAX)
40 return OPEN_MAX 40 return OPEN_MAX
diff --git a/lib/output.c b/lib/output.c
index c408a2f5..f283969f 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -16,7 +16,8 @@ static mp_output_format output_format = MP_FORMAT_DEFAULT;
16static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; 16static mp_output_detail_level level_of_detail = MP_DETAIL_ALL;
17 17
18// == Prototypes == 18// == Prototypes ==
19static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); 19static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
20 unsigned int indentation);
20static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); 21static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
21 22
22// == Implementation == 23// == Implementation ==
@@ -58,7 +59,9 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
58 * It sets useful defaults 59 * It sets useful defaults
59 */ 60 */
60mp_check mp_check_init(void) { 61mp_check mp_check_init(void) {
61 mp_check check = {0}; 62 mp_check check = {
63 .evaluation_function = &mp_eval_check_default,
64 };
62 return check; 65 return check;
63} 66}
64 67
@@ -121,7 +124,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata
121 */ 124 */
122int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { 125int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) {
123 if (subcheck.output == NULL) { 126 if (subcheck.output == NULL) {
124 die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL"); 127 die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__,
128 "Sub check output is NULL");
125 } 129 }
126 130
127 mp_subcheck_list *tmp = NULL; 131 mp_subcheck_list *tmp = NULL;
@@ -194,18 +198,30 @@ char *get_subcheck_summary(mp_check check) {
194 return result; 198 return result;
195} 199}
196 200
201mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) {
202 if (subcheck.evaluation_function == NULL) {
203 return mp_eval_subcheck_default(subcheck);
204 }
205 return subcheck.evaluation_function(subcheck);
206}
207
197/* 208/*
198 * Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states 209 * Generate the result state of a mp_subcheck object based on its own state and its subchecks
210 * states
199 */ 211 */
200mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { 212mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) {
201 if (check.state_set_explicitly) { 213 if (subcheck.evaluation_function != NULL) {
202 return check.state; 214 return subcheck.evaluation_function(subcheck);
203 } 215 }
204 216
205 mp_subcheck_list *scl = check.subchecks; 217 if (subcheck.state_set_explicitly) {
218 return subcheck.state;
219 }
220
221 mp_subcheck_list *scl = subcheck.subchecks;
206 222
207 if (scl == NULL) { 223 if (scl == NULL) {
208 return check.default_state; 224 return subcheck.default_state;
209 } 225 }
210 226
211 mp_state_enum result = STATE_OK; 227 mp_state_enum result = STATE_OK;
@@ -218,10 +234,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
218 return result; 234 return result;
219} 235}
220 236
237mp_state_enum mp_compute_check_state(const mp_check check) {
238 // just a safety check
239 if (check.evaluation_function == NULL) {
240 return mp_eval_check_default(check);
241 }
242 return check.evaluation_function(check);
243}
244
221/* 245/*
222 * Generate the result state of a mp_check object based on it's own state and it's subchecks states 246 * Generate the result state of a mp_check object based on it's own state and it's subchecks states
223 */ 247 */
224mp_state_enum mp_compute_check_state(const mp_check check) { 248mp_state_enum mp_eval_check_default(const mp_check check) {
225 assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here 249 assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here
226 250
227 mp_subcheck_list *scl = check.subchecks; 251 mp_subcheck_list *scl = check.subchecks;
@@ -253,8 +277,10 @@ char *mp_fmt_output(mp_check check) {
253 mp_subcheck_list *subchecks = check.subchecks; 277 mp_subcheck_list *subchecks = check.subchecks;
254 278
255 while (subchecks != NULL) { 279 while (subchecks != NULL) {
256 if (level_of_detail == MP_DETAIL_ALL || mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) { 280 if (level_of_detail == MP_DETAIL_ALL ||
257 asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); 281 mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
282 asprintf(&result, "%s\n%s", result,
283 fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
258 } 284 }
259 subchecks = subchecks->next; 285 subchecks = subchecks->next;
260 } 286 }
@@ -266,7 +292,8 @@ char *mp_fmt_output(mp_check check) {
266 if (pd_string == NULL) { 292 if (pd_string == NULL) {
267 asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); 293 asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck));
268 } else { 294 } else {
269 asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck)); 295 asprintf(&pd_string, "%s %s", pd_string,
296 fmt_subcheck_perfdata(subchecks->subcheck));
270 } 297 }
271 298
272 subchecks = subchecks->next; 299 subchecks = subchecks->next;
@@ -335,22 +362,58 @@ static char *generate_indentation_string(unsigned int indentation) {
335/* 362/*
336 * Helper function to generate the output string of mp_subcheck 363 * Helper function to generate the output string of mp_subcheck
337 */ 364 */
338static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) { 365static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
366 unsigned int indentation) {
339 char *result = NULL; 367 char *result = NULL;
340 mp_subcheck_list *subchecks = NULL; 368 mp_subcheck_list *subchecks = NULL;
341 369
342 switch (output_format) { 370 switch (output_format) {
343 case MP_FORMAT_MULTI_LINE: 371 case MP_FORMAT_MULTI_LINE: {
344 asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), state_text(mp_compute_subcheck_state(check)), 372 char *tmp_string = NULL;
345 check.output); 373 if ((tmp_string = strchr(check.output, '\n')) != NULL) {
374 // This is a multiline string, put the correct indentation in before proceeding
375 char *intermediate_string = "";
376 bool have_residual_chars = false;
377
378 while (tmp_string != NULL) {
379 *tmp_string = '\0';
380 asprintf(&intermediate_string, "%s%s\n%s", intermediate_string, check.output,
381 generate_indentation_string(
382 indentation + 1)); // one more indentation to make it look better
383
384 if (*(tmp_string + 1) != '\0') {
385 check.output = tmp_string + 1;
386 have_residual_chars = true;
387 } else {
388 // Null after the \n, so this is the end
389 have_residual_chars = false;
390 break;
391 }
392
393 tmp_string = strchr(check.output, '\n');
394 }
395
396 // add the rest (if any)
397 if (have_residual_chars) {
398 char *tmp = check.output;
399 xasprintf(&check.output, "%s\n%s%s", intermediate_string,
400 generate_indentation_string(indentation + 1), tmp);
401 } else {
402 check.output = intermediate_string;
403 }
404 }
405 asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation),
406 state_text(mp_compute_subcheck_state(check)), check.output);
346 407
347 subchecks = check.subchecks; 408 subchecks = check.subchecks;
348 409
349 while (subchecks != NULL) { 410 while (subchecks != NULL) {
350 asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); 411 asprintf(&result, "%s\n%s", result,
412 fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
351 subchecks = subchecks->next; 413 subchecks = subchecks->next;
352 } 414 }
353 return result; 415 return result;
416 }
354 default: 417 default:
355 die(STATE_UNKNOWN, "Invalid format"); 418 die(STATE_UNKNOWN, "Invalid format");
356 } 419 }
@@ -551,3 +614,23 @@ mp_output_format mp_get_format(void) { return output_format; }
551void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } 614void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; }
552 615
553mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } 616mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; }
617
618mp_state_enum mp_eval_ok(mp_check overall) {
619 (void)overall;
620 return STATE_OK;
621}
622
623mp_state_enum mp_eval_warning(mp_check overall) {
624 (void)overall;
625 return STATE_WARNING;
626}
627
628mp_state_enum mp_eval_critical(mp_check overall) {
629 (void)overall;
630 return STATE_CRITICAL;
631}
632
633mp_state_enum mp_eval_unknown(mp_check overall) {
634 (void)overall;
635 return STATE_UNKNOWN;
636}
diff --git a/lib/output.h b/lib/output.h
index 3bd91f90..c63c8e3f 100644
--- a/lib/output.h
+++ b/lib/output.h
@@ -7,15 +7,21 @@
7/* 7/*
8 * A partial check result 8 * A partial check result
9 */ 9 */
10typedef struct { 10typedef struct mp_subcheck mp_subcheck;
11struct mp_subcheck {
11 mp_state_enum state; // OK, Warning, Critical ... set explicitly 12 mp_state_enum state; // OK, Warning, Critical ... set explicitly
12 mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly 13 mp_state_enum default_state; // OK, Warning, Critical .. if not set explicitly
13 bool state_set_explicitly; // was the state set explicitly (or should it be derived from subchecks) 14 bool state_set_explicitly; // was the state set explicitly (or should it be derived from
15 // subchecks)
14 16
15 char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP connection to..") 17 char *output; // Text output for humans ("Filesystem xyz is fine", "Could not create TCP
16 pd_list *perfdata; // Performance data for this check 18 // connection to..")
19 pd_list *perfdata; // Performance data for this check
17 struct subcheck_list *subchecks; // subchecks deeper in the hierarchy 20 struct subcheck_list *subchecks; // subchecks deeper in the hierarchy
18} mp_subcheck; 21
22 // the evaluation_functions computes the state of subcheck
23 mp_state_enum (*evaluation_function)(mp_subcheck);
24};
19 25
20/* 26/*
21 * A list of subchecks, used in subchecks and the main check 27 * A list of subchecks, used in subchecks and the main check
@@ -57,10 +63,14 @@ mp_output_detail_level mp_get_level_of_detail(void);
57 * The final result is always derived from the children and the "worst" state 63 * The final result is always derived from the children and the "worst" state
58 * in the first layer of subchecks 64 * in the first layer of subchecks
59 */ 65 */
60typedef struct { 66typedef struct mp_check mp_check;
67struct mp_check {
61 char *summary; // Overall summary, if not set a summary will be automatically generated 68 char *summary; // Overall summary, if not set a summary will be automatically generated
62 mp_subcheck_list *subchecks; 69 mp_subcheck_list *subchecks;
63} mp_check; 70
71 // the evaluation_functions computes the state of check
72 mp_state_enum (*evaluation_function)(mp_check);
73};
64 74
65mp_check mp_check_init(void); 75mp_check mp_check_init(void);
66mp_subcheck mp_subcheck_init(void); 76mp_subcheck mp_subcheck_init(void);
@@ -78,6 +88,13 @@ void mp_add_summary(mp_check check[static 1], char *summary);
78mp_state_enum mp_compute_check_state(mp_check); 88mp_state_enum mp_compute_check_state(mp_check);
79mp_state_enum mp_compute_subcheck_state(mp_subcheck); 89mp_state_enum mp_compute_subcheck_state(mp_subcheck);
80 90
91mp_state_enum mp_eval_ok(mp_check overall);
92mp_state_enum mp_eval_warning(mp_check overall);
93mp_state_enum mp_eval_critical(mp_check overall);
94mp_state_enum mp_eval_unknown(mp_check overall);
95mp_state_enum mp_eval_check_default(mp_check check);
96mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck);
97
81typedef struct { 98typedef struct {
82 bool parsing_success; 99 bool parsing_success;
83 mp_output_format output_format; 100 mp_output_format output_format;
diff --git a/lib/parse_ini.c b/lib/parse_ini.c
index 1289aae2..db337622 100644
--- a/lib/parse_ini.c
+++ b/lib/parse_ini.c
@@ -40,26 +40,29 @@ typedef struct {
40 char *stanza; 40 char *stanza;
41} np_ini_info; 41} np_ini_info;
42 42
43static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini", "nagios-plugins.ini", NULL}; 43static char *default_ini_file_names[] = {"monitoring-plugins.ini", "plugins.ini",
44 "nagios-plugins.ini", NULL};
44 45
45static char *default_ini_path_names[] = { 46static char *default_ini_path_names[] = {
46 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini", "/usr/local/etc/monitoring-plugins.ini", 47 "/usr/local/etc/monitoring-plugins/monitoring-plugins.ini",
47 "/etc/monitoring-plugins/monitoring-plugins.ini", "/etc/monitoring-plugins.ini", 48 "/usr/local/etc/monitoring-plugins.ini", "/etc/monitoring-plugins/monitoring-plugins.ini",
49 "/etc/monitoring-plugins.ini",
48 /* deprecated path names (for backward compatibility): */ 50 /* deprecated path names (for backward compatibility): */
49 "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini", "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini", 51 "/etc/nagios/plugins.ini", "/usr/local/nagios/etc/plugins.ini",
50 "/etc/nagios-plugins.ini", "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL}; 52 "/usr/local/etc/nagios/plugins.ini", "/etc/opt/nagios/plugins.ini", "/etc/nagios-plugins.ini",
53 "/usr/local/etc/nagios-plugins.ini", "/etc/opt/nagios-plugins.ini", NULL};
51 54
52/* eat all characters from a FILE pointer until n is encountered */ 55/* eat all characters from a FILE pointer until n is encountered */
53#define GOBBLE_TO(f, c, n) \ 56#define GOBBLE_TO(f, c, n) \
54 do { \ 57 do { \
55 (c) = fgetc((f)); \ 58 (c) = fgetc((f)); \
56 } while ((c) != EOF && (c) != (n)) 59 } while ((c) != EOF && (c) != (n))
57 60
58/* internal function that returns the constructed defaults options */ 61/* internal function that returns the constructed defaults options */
59static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts); 62static bool read_defaults(FILE *defaults_file, const char *stanza, np_arg_list **opts);
60 63
61/* internal function that converts a single line into options format */ 64/* internal function that converts a single line into options format */
62static int add_option(FILE *f, np_arg_list **optlst); 65static int add_option(FILE *filePointer, np_arg_list **optlst);
63 66
64/* internal functions to find default file */ 67/* internal functions to find default file */
65static char *default_file(void); 68static char *default_file(void);
@@ -71,7 +74,8 @@ static char *default_file_in_path(void);
71 * into its separate parts. 74 * into its separate parts.
72 */ 75 */
73static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) { 76static void parse_locator(const char *locator, const char *def_stanza, np_ini_info *i) {
74 size_t locator_len = 0, stanza_len = 0; 77 size_t locator_len = 0;
78 size_t stanza_len = 0;
75 79
76 /* if locator is NULL we'll use default values */ 80 /* if locator is NULL we'll use default values */
77 if (locator != NULL) { 81 if (locator != NULL) {
@@ -87,8 +91,9 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in
87 i->stanza = strdup(def_stanza); 91 i->stanza = strdup(def_stanza);
88 } 92 }
89 93
90 if (i->stanza == NULL) 94 if (i->stanza == NULL) {
91 die(STATE_UNKNOWN, _("malloc() failed!\n")); 95 die(STATE_UNKNOWN, _("malloc() failed!\n"));
96 }
92 97
93 /* check whether there's an @file part */ 98 /* check whether there's an @file part */
94 if (stanza_len == locator_len) { 99 if (stanza_len == locator_len) {
@@ -99,39 +104,46 @@ static void parse_locator(const char *locator, const char *def_stanza, np_ini_in
99 i->file_string_on_heap = true; 104 i->file_string_on_heap = true;
100 } 105 }
101 106
102 if (i->file == NULL || i->file[0] == '\0') 107 if (i->file == NULL || i->file[0] == '\0') {
103 die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n")); 108 die(STATE_UNKNOWN, _("Cannot find config file in any standard location.\n"));
109 }
104} 110}
105 111
106/* 112/*
107 * This is the externally visible function used by extra_opts. 113 * This is the externally visible function used by extra_opts.
108 */ 114 */
109np_arg_list *np_get_defaults(const char *locator, const char *default_section) { 115np_arg_list *np_get_defaults(const char *locator, const char *default_section) {
110 FILE *inifile = NULL;
111 np_arg_list *defaults = NULL;
112 np_ini_info i;
113 int is_suid_plugin = mp_suid(); 116 int is_suid_plugin = mp_suid();
114 117
115 if (is_suid_plugin && idpriv_temp_drop() == -1) 118 if (is_suid_plugin && idpriv_temp_drop() == -1) {
116 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno)); 119 die(STATE_UNKNOWN, _("Cannot drop privileges: %s\n"), strerror(errno));
120 }
117 121
118 parse_locator(locator, default_section, &i); 122 FILE *inifile = NULL;
119 inifile = strcmp(i.file, "-") == 0 ? stdin : fopen(i.file, "r"); 123 np_ini_info ini_info;
124 parse_locator(locator, default_section, &ini_info);
125 inifile = strcmp(ini_info.file, "-") == 0 ? stdin : fopen(ini_info.file, "r");
120 126
121 if (inifile == NULL) 127 if (inifile == NULL) {
122 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno)); 128 die(STATE_UNKNOWN, _("Can't read config file: %s\n"), strerror(errno));
123 if (!read_defaults(inifile, i.stanza, &defaults)) 129 }
124 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), i.stanza, i.file);
125 130
126 if (i.file_string_on_heap) { 131 np_arg_list *defaults = NULL;
127 free(i.file); 132 if (!read_defaults(inifile, ini_info.stanza, &defaults)) {
133 die(STATE_UNKNOWN, _("Invalid section '%s' in config file '%s'\n"), ini_info.stanza, ini_info.file);
134 }
135
136 if (ini_info.file_string_on_heap) {
137 free(ini_info.file);
128 } 138 }
129 139
130 if (inifile != stdin) 140 if (inifile != stdin) {
131 fclose(inifile); 141 fclose(inifile);
132 free(i.stanza); 142 }
133 if (is_suid_plugin && idpriv_temp_restore() == -1) 143 free(ini_info.stanza);
144 if (is_suid_plugin && idpriv_temp_restore() == -1) {
134 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno)); 145 die(STATE_UNKNOWN, _("Cannot restore privileges: %s\n"), strerror(errno));
146 }
135 147
136 return defaults; 148 return defaults;
137} 149}
@@ -143,54 +155,58 @@ np_arg_list *np_get_defaults(const char *locator, const char *default_section) {
143 * be extra careful about user-supplied input (i.e. avoiding possible 155 * be extra careful about user-supplied input (i.e. avoiding possible
144 * format string vulnerabilities, etc). 156 * format string vulnerabilities, etc).
145 */ 157 */
146static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) { 158static bool read_defaults(FILE *defaults_file, const char *stanza, np_arg_list **opts) {
147 int c = 0;
148 bool status = false; 159 bool status = false;
149 size_t i, stanza_len;
150 enum { 160 enum {
151 NOSTANZA, 161 NOSTANZA,
152 WRONGSTANZA, 162 WRONGSTANZA,
153 RIGHTSTANZA 163 RIGHTSTANZA
154 } stanzastate = NOSTANZA; 164 } stanzastate = NOSTANZA;
155 165
156 stanza_len = strlen(stanza); 166 size_t stanza_len = strlen(stanza);
157 167
158 /* our little stanza-parsing state machine */ 168 /* our little stanza-parsing state machine */
159 while ((c = fgetc(f)) != EOF) { 169 int current_char = 0;
170 while ((current_char = fgetc(defaults_file)) != EOF) {
160 /* gobble up leading whitespace */ 171 /* gobble up leading whitespace */
161 if (isspace(c)) 172 if (isspace(current_char)) {
162 continue; 173 continue;
163 switch (c) { 174 }
175 switch (current_char) {
164 /* globble up comment lines */ 176 /* globble up comment lines */
165 case ';': 177 case ';':
166 case '#': 178 case '#':
167 GOBBLE_TO(f, c, '\n'); 179 GOBBLE_TO(defaults_file, current_char, '\n');
168 break; 180 break;
169 /* start of a stanza, check to see if it matches */ 181 /* start of a stanza, check to see if it matches */
170 case '[': 182 case '[': {
171 stanzastate = WRONGSTANZA; 183 stanzastate = WRONGSTANZA;
184 size_t i;
172 for (i = 0; i < stanza_len; i++) { 185 for (i = 0; i < stanza_len; i++) {
173 c = fgetc(f); 186 current_char = fgetc(defaults_file);
174 /* strip leading whitespace */ 187 /* strip leading whitespace */
175 if (i == 0) 188 if (i == 0) {
176 for (; isspace(c); c = fgetc(f)) 189 for (; isspace(current_char); current_char = fgetc(defaults_file)) {
177 continue; 190 }
191 }
178 /* nope, read to the end of the line */ 192 /* nope, read to the end of the line */
179 if (c != stanza[i]) { 193 if (current_char != stanza[i]) {
180 GOBBLE_TO(f, c, '\n'); 194 GOBBLE_TO(defaults_file, current_char, '\n');
181 break; 195 break;
182 } 196 }
183 } 197 }
198
184 /* if it matched up to here and the next char is ']'... */ 199 /* if it matched up to here and the next char is ']'... */
185 if (i == stanza_len) { 200 if (i == stanza_len) {
186 c = fgetc(f); 201 current_char = fgetc(defaults_file);
187 /* strip trailing whitespace */ 202 /* strip trailing whitespace */
188 for (; isspace(c); c = fgetc(f)) 203 for (; isspace(current_char); current_char = fgetc(defaults_file)) {
189 continue; 204 }
190 if (c == ']') 205 if (current_char == ']') {
191 stanzastate = RIGHTSTANZA; 206 stanzastate = RIGHTSTANZA;
207 }
192 } 208 }
193 break; 209 } break;
194 /* otherwise, we're in the body of a stanza or a parse error */ 210 /* otherwise, we're in the body of a stanza or a parse error */
195 default: 211 default:
196 switch (stanzastate) { 212 switch (stanzastate) {
@@ -201,12 +217,12 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) {
201 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 217 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
202 /* we're in a stanza, but for a different plugin */ 218 /* we're in a stanza, but for a different plugin */
203 case WRONGSTANZA: 219 case WRONGSTANZA:
204 GOBBLE_TO(f, c, '\n'); 220 GOBBLE_TO(defaults_file, current_char, '\n');
205 break; 221 break;
206 /* okay, this is where we start taking the config */ 222 /* okay, this is where we start taking the config */
207 case RIGHTSTANZA: 223 case RIGHTSTANZA:
208 ungetc(c, f); 224 ungetc(current_char, defaults_file);
209 if (add_option(f, opts)) { 225 if (add_option(defaults_file, opts)) {
210 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 226 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
211 } 227 }
212 status = true; 228 status = true;
@@ -225,13 +241,12 @@ static int read_defaults(FILE *f, const char *stanza, np_arg_list **opts) {
225 * --option[=value] 241 * --option[=value]
226 * appending it to the linked list optbuf. 242 * appending it to the linked list optbuf.
227 */ 243 */
228static int add_option(FILE *f, np_arg_list **optlst) { 244static int add_option(FILE *filePointer, np_arg_list **optlst) {
229 np_arg_list *opttmp = *optlst, *optnew; 245 char *linebuf = NULL;
230 char *linebuf = NULL, *lineend = NULL, *optptr = NULL, *optend = NULL; 246 bool done_reading = false;
231 char *eqptr = NULL, *valptr = NULL, *valend = NULL; 247 const size_t read_sz = 8;
232 short done_reading = 0, equals = 0, value = 0; 248 size_t linebuf_sz = 0;
233 size_t cfg_len = 0, read_sz = 8, linebuf_sz = 0, read_pos = 0; 249 size_t read_pos = 0;
234 size_t opt_len = 0, val_len = 0;
235 250
236 /* read one line from the file */ 251 /* read one line from the file */
237 while (!done_reading) { 252 while (!done_reading) {
@@ -239,74 +254,101 @@ static int add_option(FILE *f, np_arg_list **optlst) {
239 if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) { 254 if (linebuf == NULL || read_pos + read_sz >= linebuf_sz) {
240 linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz; 255 linebuf_sz = linebuf_sz > 0 ? linebuf_sz << 1 : read_sz;
241 linebuf = realloc(linebuf, linebuf_sz); 256 linebuf = realloc(linebuf, linebuf_sz);
242 if (linebuf == NULL) 257 if (linebuf == NULL) {
243 die(STATE_UNKNOWN, _("malloc() failed!\n")); 258 die(STATE_UNKNOWN, _("malloc() failed!\n"));
259 }
244 } 260 }
245 if (fgets(&linebuf[read_pos], (int)read_sz, f) == NULL) 261
246 done_reading = 1; 262 if (fgets(&linebuf[read_pos], (int)read_sz, filePointer) == NULL) {
247 else { 263 done_reading = true;
264 } else {
248 read_pos = strlen(linebuf); 265 read_pos = strlen(linebuf);
249 if (linebuf[read_pos - 1] == '\n') { 266 if (linebuf[read_pos - 1] == '\n') {
250 linebuf[--read_pos] = '\0'; 267 linebuf[--read_pos] = '\0';
251 done_reading = 1; 268 done_reading = true;
252 } 269 }
253 } 270 }
254 } 271 }
255 lineend = &linebuf[read_pos]; 272
273 char *lineend = &linebuf[read_pos];
256 /* all that to read one line, isn't C fun? :) now comes the parsing :/ */ 274 /* all that to read one line, isn't C fun? :) now comes the parsing :/ */
257 275
258 /* skip leading whitespace */ 276 /* skip leading whitespace */
259 for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) 277 char *optptr = NULL;
260 continue; 278 for (optptr = linebuf; optptr < lineend && isspace(*optptr); optptr++) {
279 }
280
261 /* continue to '=' or EOL, watching for spaces that might precede it */ 281 /* continue to '=' or EOL, watching for spaces that might precede it */
282 char *eqptr = NULL;
283 char *optend = NULL;
262 for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) { 284 for (eqptr = optptr; eqptr < lineend && *eqptr != '='; eqptr++) {
263 if (isspace(*eqptr) && optend == NULL) 285 if (isspace(*eqptr) && optend == NULL) {
264 optend = eqptr; 286 optend = eqptr;
265 else 287 } else {
266 optend = NULL; 288 optend = NULL;
289 }
267 } 290 }
268 if (optend == NULL) 291
292 if (optend == NULL) {
269 optend = eqptr; 293 optend = eqptr;
294 }
295
270 --optend; 296 --optend;
297
271 /* ^[[:space:]]*=foo is a syntax error */ 298 /* ^[[:space:]]*=foo is a syntax error */
272 if (optptr == eqptr) 299 if (optptr == eqptr) {
273 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 300 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
301 }
302
274 /* continue from '=' to start of value or EOL */ 303 /* continue from '=' to start of value or EOL */
275 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) 304 char *valptr = NULL;
276 continue; 305 for (valptr = eqptr + 1; valptr < lineend && isspace(*valptr); valptr++) {
306 }
307
277 /* continue to the end of value */ 308 /* continue to the end of value */
278 for (valend = valptr; valend < lineend; valend++) 309 char *valend = NULL;
279 continue; 310 for (valend = valptr; valend < lineend; valend++) {
311 }
312
280 --valend; 313 --valend;
314
281 /* finally trim off trailing spaces */ 315 /* finally trim off trailing spaces */
282 for (; isspace(*valend); valend--) 316 for (; isspace(*valend); valend--) {
283 continue; 317 }
318
284 /* calculate the length of "--foo" */ 319 /* calculate the length of "--foo" */
285 opt_len = (size_t)(1 + optend - optptr); 320 size_t opt_len = (size_t)(1 + optend - optptr);
286 /* 1-character params needs only one dash */ 321 /* 1-character params needs only one dash */
287 if (opt_len == 1) 322 size_t cfg_len = 0;
323 if (opt_len == 1) {
288 cfg_len = 1 + (opt_len); 324 cfg_len = 1 + (opt_len);
289 else 325 } else {
290 cfg_len = 2 + (opt_len); 326 cfg_len = 2 + (opt_len);
327 }
328
329 size_t val_len = 0;
330 bool equals = false;
331 bool value = false;
291 /* if valptr<lineend then we have to also allocate space for "=bar" */ 332 /* if valptr<lineend then we have to also allocate space for "=bar" */
292 if (valptr < lineend) { 333 if (valptr < lineend) {
293 equals = value = 1; 334 equals = value = true;
294 val_len = (size_t)(1 + valend - valptr); 335 val_len = (size_t)(1 + valend - valptr);
295 cfg_len += 1 + val_len; 336 cfg_len += 1 + val_len;
296 } 337 } else if (valptr == lineend) {
297 /* if valptr==valend then we have "=" but no "bar" */ 338 /* if valptr==valend then we have "=" but no "bar" */
298 else if (valptr == lineend) { 339 equals = true;
299 equals = 1;
300 cfg_len += 1; 340 cfg_len += 1;
301 } 341 }
342
302 /* a line with no equal sign isn't valid */ 343 /* a line with no equal sign isn't valid */
303 if (equals == 0) 344 if (!equals) {
304 die(STATE_UNKNOWN, "%s\n", _("Config file error")); 345 die(STATE_UNKNOWN, "%s\n", _("Config file error"));
346 }
305 347
306 /* okay, now we have all the info we need, so we create a new np_arg_list 348 /* okay, now we have all the info we need, so we create a new np_arg_list
307 * element and set the argument... 349 * element and set the argument...
308 */ 350 */
309 optnew = malloc(sizeof(np_arg_list)); 351 np_arg_list *optnew = malloc(sizeof(np_arg_list));
310 optnew->next = NULL; 352 optnew->next = NULL;
311 353
312 read_pos = 0; 354 read_pos = 0;
@@ -329,11 +371,13 @@ static int add_option(FILE *f, np_arg_list **optlst) {
329 optnew->arg[read_pos] = '\0'; 371 optnew->arg[read_pos] = '\0';
330 372
331 /* ...and put that to the end of the list */ 373 /* ...and put that to the end of the list */
332 if (*optlst == NULL) 374 if (*optlst == NULL) {
333 *optlst = optnew; 375 *optlst = optnew;
334 else { 376 } else {
335 while (opttmp->next != NULL) 377 np_arg_list *opttmp = *optlst;
378 while (opttmp->next != NULL) {
336 opttmp = opttmp->next; 379 opttmp = opttmp->next;
380 }
337 opttmp->next = optnew; 381 opttmp->next = optnew;
338 } 382 }
339 383
@@ -344,7 +388,8 @@ static int add_option(FILE *f, np_arg_list **optlst) {
344static char *default_file(void) { 388static char *default_file(void) {
345 char *ini_file; 389 char *ini_file;
346 390
347 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL || (ini_file = default_file_in_path()) != NULL) { 391 if ((ini_file = getenv("MP_CONFIG_FILE")) != NULL ||
392 (ini_file = default_file_in_path()) != NULL) {
348 return ini_file; 393 return ini_file;
349 } 394 }
350 395
@@ -357,19 +402,25 @@ static char *default_file(void) {
357} 402}
358 403
359static char *default_file_in_path(void) { 404static char *default_file_in_path(void) {
360 char *config_path, **file; 405 char *config_path;
361 char *dir, *ini_file, *tokens; 406 char **file;
407 char *dir;
408 char *ini_file;
409 char *tokens;
362 410
363 if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) 411 if ((config_path = getenv("NAGIOS_CONFIG_PATH")) == NULL) {
364 return NULL; 412 return NULL;
413 }
365 /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */ 414 /* shall we spit out a warning that NAGIOS_CONFIG_PATH is deprecated? */
366 415
367 if ((tokens = strdup(config_path)) == NULL) 416 if ((tokens = strdup(config_path)) == NULL) {
368 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); 417 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
418 }
369 for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) { 419 for (dir = strtok(tokens, ":"); dir != NULL; dir = strtok(NULL, ":")) {
370 for (file = default_ini_file_names; *file != NULL; file++) { 420 for (file = default_ini_file_names; *file != NULL; file++) {
371 if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) 421 if ((asprintf(&ini_file, "%s/%s", dir, *file)) < 0) {
372 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory")); 422 die(STATE_UNKNOWN, "%s\n", _("Insufficient Memory"));
423 }
373 if (access(ini_file, F_OK) == 0) { 424 if (access(ini_file, F_OK) == 0) {
374 free(tokens); 425 free(tokens);
375 return ini_file; 426 return ini_file;
diff --git a/lib/perfdata.c b/lib/perfdata.c
index f425ffcf..2930a8bc 100644
--- a/lib/perfdata.c
+++ b/lib/perfdata.c
@@ -33,7 +33,18 @@ char *pd_value_to_string(const mp_perfdata_value pd) {
33char *pd_to_string(mp_perfdata pd) { 33char *pd_to_string(mp_perfdata pd) {
34 assert(pd.label != NULL); 34 assert(pd.label != NULL);
35 char *result = NULL; 35 char *result = NULL;
36 asprintf(&result, "'%s'=", pd.label); 36
37 if (strchr(pd.label, '\'') == NULL) {
38 asprintf(&result, "'%s'=", pd.label);
39 } else {
40 // we have a illegal single quote in the string
41 // replace it silently instead of complaining
42 for (char *ptr = pd.label; *ptr == '\0'; ptr++) {
43 if (*ptr == '\'') {
44 *ptr = '_';
45 }
46 }
47 }
37 48
38 asprintf(&result, "%s%s", result, pd_value_to_string(pd.value)); 49 asprintf(&result, "%s%s", result, pd_value_to_string(pd.value));
39 50
@@ -249,7 +260,9 @@ char *mp_range_to_string(const mp_range input) {
249 return result; 260 return result;
250} 261}
251 262
252mp_perfdata mp_set_pd_value_float(mp_perfdata pd, float value) { return mp_set_pd_value_double(pd, value); } 263mp_perfdata mp_set_pd_value_float(mp_perfdata pd, float value) {
264 return mp_set_pd_value_double(pd, value);
265}
253 266
254mp_perfdata mp_set_pd_value_double(mp_perfdata pd, double value) { 267mp_perfdata mp_set_pd_value_double(mp_perfdata pd, double value) {
255 pd.value.pd_double = value; 268 pd.value.pd_double = value;
@@ -257,11 +270,25 @@ mp_perfdata mp_set_pd_value_double(mp_perfdata pd, double value) {
257 return pd; 270 return pd;
258} 271}
259 272
260mp_perfdata mp_set_pd_value_int(mp_perfdata pd, int value) { return mp_set_pd_value_long_long(pd, (long long)value); } 273mp_perfdata mp_set_pd_value_char(mp_perfdata pd, char value) {
274 return mp_set_pd_value_long_long(pd, (long long)value);
275}
261 276
262mp_perfdata mp_set_pd_value_u_int(mp_perfdata pd, unsigned int value) { return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); } 277mp_perfdata mp_set_pd_value_u_char(mp_perfdata pd, unsigned char value) {
278 return mp_set_pd_value_u_long_long(pd, (unsigned long long)value);
279}
280
281mp_perfdata mp_set_pd_value_int(mp_perfdata pd, int value) {
282 return mp_set_pd_value_long_long(pd, (long long)value);
283}
263 284
264mp_perfdata mp_set_pd_value_long(mp_perfdata pd, long value) { return mp_set_pd_value_long_long(pd, (long long)value); } 285mp_perfdata mp_set_pd_value_u_int(mp_perfdata pd, unsigned int value) {
286 return mp_set_pd_value_u_long_long(pd, (unsigned long long)value);
287}
288
289mp_perfdata mp_set_pd_value_long(mp_perfdata pd, long value) {
290 return mp_set_pd_value_long_long(pd, (long long)value);
291}
265 292
266mp_perfdata mp_set_pd_value_u_long(mp_perfdata pd, unsigned long value) { 293mp_perfdata mp_set_pd_value_u_long(mp_perfdata pd, unsigned long value) {
267 return mp_set_pd_value_u_long_long(pd, (unsigned long long)value); 294 return mp_set_pd_value_u_long_long(pd, (unsigned long long)value);
@@ -286,15 +313,33 @@ mp_perfdata_value mp_create_pd_value_double(double value) {
286 return res; 313 return res;
287} 314}
288 315
289mp_perfdata_value mp_create_pd_value_float(float value) { return mp_create_pd_value_double((double)value); } 316mp_perfdata_value mp_create_pd_value_float(float value) {
317 return mp_create_pd_value_double((double)value);
318}
319
320mp_perfdata_value mp_create_pd_value_char(char value) {
321 return mp_create_pd_value_long_long((long long)value);
322}
290 323
291mp_perfdata_value mp_create_pd_value_int(int value) { return mp_create_pd_value_long_long((long long)value); } 324mp_perfdata_value mp_create_pd_value_u_char(unsigned char value) {
325 return mp_create_pd_value_u_long_long((unsigned long long)value);
326}
292 327
293mp_perfdata_value mp_create_pd_value_u_int(unsigned int value) { return mp_create_pd_value_u_long_long((unsigned long long)value); } 328mp_perfdata_value mp_create_pd_value_int(int value) {
329 return mp_create_pd_value_long_long((long long)value);
330}
331
332mp_perfdata_value mp_create_pd_value_u_int(unsigned int value) {
333 return mp_create_pd_value_u_long_long((unsigned long long)value);
334}
294 335
295mp_perfdata_value mp_create_pd_value_long(long value) { return mp_create_pd_value_long_long((long long)value); } 336mp_perfdata_value mp_create_pd_value_long(long value) {
337 return mp_create_pd_value_long_long((long long)value);
338}
296 339
297mp_perfdata_value mp_create_pd_value_u_long(unsigned long value) { return mp_create_pd_value_u_long_long((unsigned long long)value); } 340mp_perfdata_value mp_create_pd_value_u_long(unsigned long value) {
341 return mp_create_pd_value_u_long_long((unsigned long long)value);
342}
298 343
299mp_perfdata_value mp_create_pd_value_long_long(long long value) { 344mp_perfdata_value mp_create_pd_value_long_long(long long value) {
300 mp_perfdata_value res = {0}; 345 mp_perfdata_value res = {0};
@@ -360,6 +405,13 @@ mp_range_parsed mp_parse_range_string(const char *input) {
360 } 405 }
361 406
362 char *working_copy = strdup(input); 407 char *working_copy = strdup(input);
408 if (working_copy == NULL) {
409 // strdup error, probably
410 mp_range_parsed result = {
411 .error = MP_RANGE_PARSING_FAILURE,
412 };
413 return result;
414 }
363 input = working_copy; 415 input = working_copy;
364 416
365 char *separator = index(working_copy, ':'); 417 char *separator = index(working_copy, ':');
diff --git a/lib/perfdata.h b/lib/perfdata.h
index cb552678..e51ef5fd 100644
--- a/lib/perfdata.h
+++ b/lib/perfdata.h
@@ -28,7 +28,7 @@ typedef struct {
28/* 28/*
29 * New range type with generic numerical values 29 * New range type with generic numerical values
30 */ 30 */
31typedef struct mp_range_struct { 31typedef struct {
32 mp_perfdata_value start; 32 mp_perfdata_value start;
33 bool start_infinity; /* false (default) or true */ 33 bool start_infinity; /* false (default) or true */
34 34
@@ -41,11 +41,11 @@ typedef struct mp_range_struct {
41/* 41/*
42 * Old range type with floating point values 42 * Old range type with floating point values
43 */ 43 */
44typedef struct range_struct { 44typedef struct {
45 double start; 45 double start;
46 bool start_infinity; 46 bool start_infinity;
47 double end; 47 double end;
48 int end_infinity; 48 bool end_infinity;
49 int alert_on; /* OUTSIDE (default) or INSIDE */ 49 int alert_on; /* OUTSIDE (default) or INSIDE */
50 char *text; /* original unparsed text input */ 50 char *text; /* original unparsed text input */
51} range; 51} range;
@@ -53,7 +53,7 @@ typedef struct range_struct {
53/* 53/*
54 * Perfdata type for storing perfdata output 54 * Perfdata type for storing perfdata output
55 */ 55 */
56typedef struct perfdata_struct { 56typedef struct {
57 char *label; 57 char *label;
58 char *uom; 58 char *uom;
59 mp_perfdata_value value; 59 mp_perfdata_value value;
@@ -131,15 +131,15 @@ mp_range_parsed mp_parse_range_string(const char * /*input*/);
131 */ 131 */
132void pd_list_append(pd_list[1], mp_perfdata); 132void pd_list_append(pd_list[1], mp_perfdata);
133 133
134#define mp_set_pd_value(P, V) \ 134#define mp_set_pd_value(P, V) \
135 _Generic((V), \ 135 _Generic((V), \
136 float: mp_set_pd_value_float, \ 136 float: mp_set_pd_value_float, \
137 double: mp_set_pd_value_double, \ 137 double: mp_set_pd_value_double, \
138 int: mp_set_pd_value_int, \ 138 int: mp_set_pd_value_int, \
139 unsigned int: mp_set_pd_value_u_int, \ 139 unsigned int: mp_set_pd_value_u_int, \
140 long: mp_set_pd_value_long, \ 140 long: mp_set_pd_value_long, \
141 unsigned long: mp_set_pd_value_u_long, \ 141 unsigned long: mp_set_pd_value_u_long, \
142 long long: mp_set_pd_value_long_long, \ 142 long long: mp_set_pd_value_long_long, \
143 unsigned long long: mp_set_pd_value_u_long_long)(P, V) 143 unsigned long long: mp_set_pd_value_u_long_long)(P, V)
144 144
145mp_perfdata mp_set_pd_value_float(mp_perfdata, float); 145mp_perfdata mp_set_pd_value_float(mp_perfdata, float);
@@ -151,19 +151,23 @@ mp_perfdata mp_set_pd_value_u_long(mp_perfdata, unsigned long);
151mp_perfdata mp_set_pd_value_long_long(mp_perfdata, long long); 151mp_perfdata mp_set_pd_value_long_long(mp_perfdata, long long);
152mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long); 152mp_perfdata mp_set_pd_value_u_long_long(mp_perfdata, unsigned long long);
153 153
154#define mp_create_pd_value(V) \ 154#define mp_create_pd_value(V) \
155 _Generic((V), \ 155 _Generic((V), \
156 float: mp_create_pd_value_float, \ 156 float: mp_create_pd_value_float, \
157 double: mp_create_pd_value_double, \ 157 double: mp_create_pd_value_double, \
158 int: mp_create_pd_value_int, \ 158 char: mp_create_pd_value_char, \
159 unsigned int: mp_create_pd_value_u_int, \ 159 unsigned char: mp_create_pd_value_u_char, \
160 long: mp_create_pd_value_long, \ 160 int: mp_create_pd_value_int, \
161 unsigned long: mp_create_pd_value_u_long, \ 161 unsigned int: mp_create_pd_value_u_int, \
162 long long: mp_create_pd_value_long_long, \ 162 long: mp_create_pd_value_long, \
163 unsigned long: mp_create_pd_value_u_long, \
164 long long: mp_create_pd_value_long_long, \
163 unsigned long long: mp_create_pd_value_u_long_long)(V) 165 unsigned long long: mp_create_pd_value_u_long_long)(V)
164 166
165mp_perfdata_value mp_create_pd_value_float(float); 167mp_perfdata_value mp_create_pd_value_float(float);
166mp_perfdata_value mp_create_pd_value_double(double); 168mp_perfdata_value mp_create_pd_value_double(double);
169mp_perfdata_value mp_create_pd_value_char(char);
170mp_perfdata_value mp_create_pd_value_u_char(unsigned char);
167mp_perfdata_value mp_create_pd_value_int(int); 171mp_perfdata_value mp_create_pd_value_int(int);
168mp_perfdata_value mp_create_pd_value_u_int(unsigned int); 172mp_perfdata_value mp_create_pd_value_u_int(unsigned int);
169mp_perfdata_value mp_create_pd_value_long(long); 173mp_perfdata_value mp_create_pd_value_long(long);
diff --git a/lib/tests/test_base64.c b/lib/tests/test_base64.c
index 94cb5aa9..798244da 100644
--- a/lib/tests/test_base64.c
+++ b/lib/tests/test_base64.c
@@ -180,117 +180,168 @@ int main(int argc, char **argv) {
180#endif 180#endif
181 181
182 char random[1024] = { 182 char random[1024] = {
183 0x0b, 0x30, 0x44, 0x62, 0x7c, 0x22, 0x1f, 0x0d, 0x05, 0x67, 0x2c, 0x2a, 0x39, 0x21, 0x46, 0x08, 0x50, 0x66, 0x34, 0x37, 0x0b, 0x45, 183 0x0b, 0x30, 0x44, 0x62, 0x7c, 0x22, 0x1f, 0x0d, 0x05, 0x67, 0x2c, 0x2a, 0x39, 0x21, 0x46,
184 0x4b, 0x38, 0x32, 0x06, 0x7a, 0x3e, 0x7f, 0x0c, 0x40, 0x18, 0x6b, 0x2d, 0x60, 0x4c, 0x60, 0x0c, 0x23, 0x43, 0x3b, 0x3e, 0x1b, 0x16, 184 0x08, 0x50, 0x66, 0x34, 0x37, 0x0b, 0x45, 0x4b, 0x38, 0x32, 0x06, 0x7a, 0x3e, 0x7f, 0x0c,
185 0x04, 0x46, 0x58, 0x3f, 0x40, 0x6a, 0x11, 0x05, 0x63, 0x71, 0x14, 0x35, 0x47, 0x79, 0x13, 0x6f, 0x6b, 0x27, 0x18, 0x5b, 0x48, 0x27, 185 0x40, 0x18, 0x6b, 0x2d, 0x60, 0x4c, 0x60, 0x0c, 0x23, 0x43, 0x3b, 0x3e, 0x1b, 0x16, 0x04,
186 0x3e, 0x6f, 0x15, 0x33, 0x4f, 0x3e, 0x5e, 0x51, 0x73, 0x68, 0x25, 0x0f, 0x06, 0x5b, 0x7c, 0x72, 0x75, 0x3e, 0x3f, 0x1b, 0x5c, 0x6d, 186 0x46, 0x58, 0x3f, 0x40, 0x6a, 0x11, 0x05, 0x63, 0x71, 0x14, 0x35, 0x47, 0x79, 0x13, 0x6f,
187 0x6a, 0x39, 0x7c, 0x63, 0x63, 0x60, 0x6c, 0x7a, 0x33, 0x76, 0x52, 0x13, 0x25, 0x33, 0x7d, 0x65, 0x23, 0x27, 0x11, 0x06, 0x06, 0x47, 187 0x6b, 0x27, 0x18, 0x5b, 0x48, 0x27, 0x3e, 0x6f, 0x15, 0x33, 0x4f, 0x3e, 0x5e, 0x51, 0x73,
188 0x71, 0x1e, 0x14, 0x74, 0x63, 0x70, 0x2d, 0x15, 0x27, 0x18, 0x51, 0x06, 0x05, 0x33, 0x11, 0x2c, 0x6b, 0x00, 0x2d, 0x77, 0x20, 0x48, 188 0x68, 0x25, 0x0f, 0x06, 0x5b, 0x7c, 0x72, 0x75, 0x3e, 0x3f, 0x1b, 0x5c, 0x6d, 0x6a, 0x39,
189 0x0d, 0x73, 0x51, 0x45, 0x25, 0x7f, 0x7f, 0x35, 0x26, 0x2e, 0x26, 0x53, 0x24, 0x68, 0x1e, 0x0e, 0x58, 0x3a, 0x59, 0x50, 0x56, 0x37, 189 0x7c, 0x63, 0x63, 0x60, 0x6c, 0x7a, 0x33, 0x76, 0x52, 0x13, 0x25, 0x33, 0x7d, 0x65, 0x23,
190 0x5f, 0x66, 0x01, 0x4c, 0x5a, 0x64, 0x32, 0x50, 0x7b, 0x6a, 0x20, 0x72, 0x2b, 0x1d, 0x7e, 0x43, 0x7b, 0x61, 0x42, 0x0b, 0x61, 0x73, 190 0x27, 0x11, 0x06, 0x06, 0x47, 0x71, 0x1e, 0x14, 0x74, 0x63, 0x70, 0x2d, 0x15, 0x27, 0x18,
191 0x24, 0x79, 0x3a, 0x6b, 0x4a, 0x79, 0x6e, 0x09, 0x0f, 0x27, 0x2d, 0x0c, 0x5e, 0x32, 0x4b, 0x0d, 0x79, 0x46, 0x39, 0x21, 0x0a, 0x26, 191 0x51, 0x06, 0x05, 0x33, 0x11, 0x2c, 0x6b, 0x00, 0x2d, 0x77, 0x20, 0x48, 0x0d, 0x73, 0x51,
192 0x5f, 0x3a, 0x00, 0x26, 0x3f, 0x13, 0x2e, 0x7e, 0x50, 0x2b, 0x67, 0x46, 0x72, 0x3f, 0x3b, 0x01, 0x46, 0x1b, 0x0b, 0x35, 0x49, 0x39, 192 0x45, 0x25, 0x7f, 0x7f, 0x35, 0x26, 0x2e, 0x26, 0x53, 0x24, 0x68, 0x1e, 0x0e, 0x58, 0x3a,
193 0x19, 0x70, 0x3d, 0x02, 0x41, 0x0e, 0x38, 0x05, 0x76, 0x65, 0x4f, 0x31, 0x6c, 0x5e, 0x17, 0x04, 0x15, 0x36, 0x26, 0x64, 0x34, 0x14, 193 0x59, 0x50, 0x56, 0x37, 0x5f, 0x66, 0x01, 0x4c, 0x5a, 0x64, 0x32, 0x50, 0x7b, 0x6a, 0x20,
194 0x17, 0x7c, 0x0e, 0x0b, 0x5b, 0x55, 0x53, 0x6b, 0x00, 0x42, 0x41, 0x4f, 0x02, 0x5c, 0x13, 0x0a, 0x2c, 0x2c, 0x3e, 0x10, 0x14, 0x33, 194 0x72, 0x2b, 0x1d, 0x7e, 0x43, 0x7b, 0x61, 0x42, 0x0b, 0x61, 0x73, 0x24, 0x79, 0x3a, 0x6b,
195 0x45, 0x7c, 0x7a, 0x5a, 0x31, 0x61, 0x39, 0x08, 0x22, 0x6a, 0x1e, 0x0f, 0x6f, 0x1b, 0x6c, 0x13, 0x5e, 0x79, 0x20, 0x79, 0x50, 0x62, 195 0x4a, 0x79, 0x6e, 0x09, 0x0f, 0x27, 0x2d, 0x0c, 0x5e, 0x32, 0x4b, 0x0d, 0x79, 0x46, 0x39,
196 0x06, 0x2c, 0x76, 0x17, 0x04, 0x2b, 0x2a, 0x75, 0x1f, 0x0c, 0x37, 0x4e, 0x0f, 0x7b, 0x2d, 0x34, 0x75, 0x60, 0x31, 0x74, 0x2e, 0x0a, 196 0x21, 0x0a, 0x26, 0x5f, 0x3a, 0x00, 0x26, 0x3f, 0x13, 0x2e, 0x7e, 0x50, 0x2b, 0x67, 0x46,
197 0x4a, 0x11, 0x6c, 0x49, 0x25, 0x01, 0x3a, 0x3d, 0x22, 0x1e, 0x6d, 0x18, 0x51, 0x78, 0x2d, 0x62, 0x31, 0x4c, 0x50, 0x40, 0x17, 0x4b, 197 0x72, 0x3f, 0x3b, 0x01, 0x46, 0x1b, 0x0b, 0x35, 0x49, 0x39, 0x19, 0x70, 0x3d, 0x02, 0x41,
198 0x6f, 0x22, 0x00, 0x7f, 0x61, 0x2a, 0x34, 0x3e, 0x00, 0x5f, 0x2f, 0x5f, 0x2f, 0x14, 0x2a, 0x55, 0x27, 0x1f, 0x46, 0x1f, 0x12, 0x46, 198 0x0e, 0x38, 0x05, 0x76, 0x65, 0x4f, 0x31, 0x6c, 0x5e, 0x17, 0x04, 0x15, 0x36, 0x26, 0x64,
199 0x5e, 0x1e, 0x0c, 0x7c, 0x38, 0x01, 0x61, 0x64, 0x76, 0x22, 0x6e, 0x08, 0x20, 0x38, 0x4f, 0x73, 0x72, 0x55, 0x12, 0x42, 0x19, 0x50, 199 0x34, 0x14, 0x17, 0x7c, 0x0e, 0x0b, 0x5b, 0x55, 0x53, 0x6b, 0x00, 0x42, 0x41, 0x4f, 0x02,
200 0x61, 0x43, 0x77, 0x7d, 0x41, 0x2e, 0x35, 0x4f, 0x3d, 0x31, 0x28, 0x58, 0x67, 0x1b, 0x03, 0x51, 0x20, 0x32, 0x1c, 0x08, 0x6e, 0x37, 200 0x5c, 0x13, 0x0a, 0x2c, 0x2c, 0x3e, 0x10, 0x14, 0x33, 0x45, 0x7c, 0x7a, 0x5a, 0x31, 0x61,
201 0x75, 0x37, 0x44, 0x4f, 0x68, 0x19, 0x07, 0x64, 0x14, 0x28, 0x25, 0x2b, 0x69, 0x35, 0x18, 0x27, 0x26, 0x14, 0x13, 0x70, 0x42, 0x19, 201 0x39, 0x08, 0x22, 0x6a, 0x1e, 0x0f, 0x6f, 0x1b, 0x6c, 0x13, 0x5e, 0x79, 0x20, 0x79, 0x50,
202 0x12, 0x75, 0x3e, 0x02, 0x5d, 0x7c, 0x13, 0x1f, 0x16, 0x53, 0x3b, 0x74, 0x48, 0x3c, 0x5e, 0x39, 0x6c, 0x1c, 0x1c, 0x74, 0x39, 0x1f, 202 0x62, 0x06, 0x2c, 0x76, 0x17, 0x04, 0x2b, 0x2a, 0x75, 0x1f, 0x0c, 0x37, 0x4e, 0x0f, 0x7b,
203 0x00, 0x1b, 0x06, 0x0a, 0x68, 0x3b, 0x52, 0x4f, 0x1e, 0x6e, 0x3c, 0x35, 0x0c, 0x38, 0x0e, 0x0b, 0x3b, 0x1a, 0x76, 0x23, 0x29, 0x53, 203 0x2d, 0x34, 0x75, 0x60, 0x31, 0x74, 0x2e, 0x0a, 0x4a, 0x11, 0x6c, 0x49, 0x25, 0x01, 0x3a,
204 0x1e, 0x5f, 0x41, 0x0c, 0x4b, 0x0a, 0x65, 0x28, 0x78, 0x67, 0x48, 0x59, 0x26, 0x6d, 0x31, 0x76, 0x23, 0x70, 0x61, 0x64, 0x3b, 0x38, 204 0x3d, 0x22, 0x1e, 0x6d, 0x18, 0x51, 0x78, 0x2d, 0x62, 0x31, 0x4c, 0x50, 0x40, 0x17, 0x4b,
205 0x79, 0x66, 0x74, 0x53, 0x2c, 0x64, 0x64, 0x54, 0x03, 0x54, 0x65, 0x44, 0x4c, 0x18, 0x4f, 0x48, 0x20, 0x4f, 0x72, 0x10, 0x3f, 0x0c, 205 0x6f, 0x22, 0x00, 0x7f, 0x61, 0x2a, 0x34, 0x3e, 0x00, 0x5f, 0x2f, 0x5f, 0x2f, 0x14, 0x2a,
206 0x52, 0x2d, 0x03, 0x14, 0x03, 0x51, 0x42, 0x10, 0x77, 0x6a, 0x34, 0x06, 0x32, 0x03, 0x72, 0x14, 0x7c, 0x08, 0x5d, 0x52, 0x1a, 0x62, 206 0x55, 0x27, 0x1f, 0x46, 0x1f, 0x12, 0x46, 0x5e, 0x1e, 0x0c, 0x7c, 0x38, 0x01, 0x61, 0x64,
207 0x7c, 0x3e, 0x30, 0x7e, 0x5f, 0x7f, 0x54, 0x0f, 0x44, 0x49, 0x5d, 0x5e, 0x10, 0x6a, 0x06, 0x2b, 0x06, 0x53, 0x10, 0x39, 0x37, 0x32, 207 0x76, 0x22, 0x6e, 0x08, 0x20, 0x38, 0x4f, 0x73, 0x72, 0x55, 0x12, 0x42, 0x19, 0x50, 0x61,
208 0x4a, 0x4e, 0x3d, 0x2b, 0x65, 0x38, 0x39, 0x07, 0x72, 0x54, 0x64, 0x4d, 0x56, 0x6a, 0x03, 0x22, 0x70, 0x7b, 0x5f, 0x60, 0x0b, 0x2a, 208 0x43, 0x77, 0x7d, 0x41, 0x2e, 0x35, 0x4f, 0x3d, 0x31, 0x28, 0x58, 0x67, 0x1b, 0x03, 0x51,
209 0x0b, 0x6b, 0x10, 0x64, 0x14, 0x05, 0x22, 0x00, 0x73, 0x40, 0x23, 0x5b, 0x51, 0x1f, 0x2b, 0x1a, 0x5d, 0x69, 0x7a, 0x46, 0x0c, 0x5f, 209 0x20, 0x32, 0x1c, 0x08, 0x6e, 0x37, 0x75, 0x37, 0x44, 0x4f, 0x68, 0x19, 0x07, 0x64, 0x14,
210 0x32, 0x4b, 0x4a, 0x28, 0x52, 0x79, 0x5b, 0x12, 0x42, 0x18, 0x00, 0x5d, 0x27, 0x31, 0x53, 0x3c, 0x4c, 0x36, 0x4e, 0x38, 0x3f, 0x72, 210 0x28, 0x25, 0x2b, 0x69, 0x35, 0x18, 0x27, 0x26, 0x14, 0x13, 0x70, 0x42, 0x19, 0x12, 0x75,
211 0x03, 0x71, 0x02, 0x5b, 0x36, 0x59, 0x7f, 0x75, 0x6e, 0x08, 0x54, 0x0d, 0x34, 0x1c, 0x34, 0x57, 0x5d, 0x69, 0x48, 0x00, 0x3b, 0x05, 211 0x3e, 0x02, 0x5d, 0x7c, 0x13, 0x1f, 0x16, 0x53, 0x3b, 0x74, 0x48, 0x3c, 0x5e, 0x39, 0x6c,
212 0x07, 0x6e, 0x27, 0x65, 0x6e, 0x40, 0x3d, 0x3a, 0x4f, 0x72, 0x5d, 0x39, 0x16, 0x0f, 0x63, 0x12, 0x12, 0x15, 0x3a, 0x70, 0x0d, 0x57, 212 0x1c, 0x1c, 0x74, 0x39, 0x1f, 0x00, 0x1b, 0x06, 0x0a, 0x68, 0x3b, 0x52, 0x4f, 0x1e, 0x6e,
213 0x18, 0x0d, 0x5e, 0x3d, 0x22, 0x68, 0x68, 0x7c, 0x6d, 0x4f, 0x0c, 0x7b, 0x09, 0x2d, 0x4a, 0x73, 0x20, 0x47, 0x07, 0x57, 0x75, 0x5d, 213 0x3c, 0x35, 0x0c, 0x38, 0x0e, 0x0b, 0x3b, 0x1a, 0x76, 0x23, 0x29, 0x53, 0x1e, 0x5f, 0x41,
214 0x53, 0x70, 0x34, 0x21, 0x40, 0x57, 0x51, 0x5e, 0x49, 0x44, 0x00, 0x54, 0x27, 0x04, 0x68, 0x7e, 0x59, 0x56, 0x58, 0x74, 0x14, 0x3c, 214 0x0c, 0x4b, 0x0a, 0x65, 0x28, 0x78, 0x67, 0x48, 0x59, 0x26, 0x6d, 0x31, 0x76, 0x23, 0x70,
215 0x16, 0x33, 0x41, 0x16, 0x4b, 0x2f, 0x49, 0x37, 0x0a, 0x54, 0x08, 0x08, 0x1f, 0x39, 0x67, 0x76, 0x28, 0x28, 0x07, 0x1d, 0x61, 0x47, 215 0x61, 0x64, 0x3b, 0x38, 0x79, 0x66, 0x74, 0x53, 0x2c, 0x64, 0x64, 0x54, 0x03, 0x54, 0x65,
216 0x51, 0x4d, 0x75, 0x26, 0x52, 0x47, 0x47, 0x0c, 0x57, 0x58, 0x74, 0x3e, 0x62, 0x6c, 0x58, 0x3a, 0x44, 0x1e, 0x16, 0x2e, 0x21, 0x1c, 216 0x44, 0x4c, 0x18, 0x4f, 0x48, 0x20, 0x4f, 0x72, 0x10, 0x3f, 0x0c, 0x52, 0x2d, 0x03, 0x14,
217 0x73, 0x45, 0x67, 0x74, 0x4f, 0x33, 0x66, 0x0e, 0x74, 0x66, 0x26, 0x1f, 0x2e, 0x38, 0x44, 0x40, 0x7e, 0x2a, 0x50, 0x52, 0x5e, 0x43, 217 0x03, 0x51, 0x42, 0x10, 0x77, 0x6a, 0x34, 0x06, 0x32, 0x03, 0x72, 0x14, 0x7c, 0x08, 0x5d,
218 0x01, 0x7a, 0x38, 0x49, 0x3c, 0x55, 0x4d, 0x5a, 0x44, 0x08, 0x26, 0x59, 0x4d, 0x45, 0x0b, 0x48, 0x0a, 0x33, 0x5e, 0x4a, 0x4d, 0x75, 218 0x52, 0x1a, 0x62, 0x7c, 0x3e, 0x30, 0x7e, 0x5f, 0x7f, 0x54, 0x0f, 0x44, 0x49, 0x5d, 0x5e,
219 0x16, 0x17, 0x63, 0x46, 0x01, 0x2a, 0x55, 0x7b, 0x0f, 0x02, 0x73, 0x6a, 0x4b, 0x7f, 0x75, 0x65, 0x3c, 0x4c, 0x33, 0x39, 0x6c, 0x74, 219 0x10, 0x6a, 0x06, 0x2b, 0x06, 0x53, 0x10, 0x39, 0x37, 0x32, 0x4a, 0x4e, 0x3d, 0x2b, 0x65,
220 0x05, 0x60, 0x0f, 0x7f, 0x2d, 0x41, 0x4d, 0x4d, 0x46, 0x71, 0x09, 0x6f, 0x4f, 0x60, 0x15, 0x0f, 0x46, 0x73, 0x63, 0x4c, 0x5e, 0x74, 220 0x38, 0x39, 0x07, 0x72, 0x54, 0x64, 0x4d, 0x56, 0x6a, 0x03, 0x22, 0x70, 0x7b, 0x5f, 0x60,
221 0x30, 0x0d, 0x28, 0x43, 0x08, 0x72, 0x32, 0x04, 0x2e, 0x31, 0x29, 0x27, 0x44, 0x6d, 0x13, 0x17, 0x48, 0x0f, 0x49, 0x52, 0x10, 0x13, 221 0x0b, 0x2a, 0x0b, 0x6b, 0x10, 0x64, 0x14, 0x05, 0x22, 0x00, 0x73, 0x40, 0x23, 0x5b, 0x51,
222 0x7f, 0x17, 0x16, 0x62, 0x79, 0x35, 0x78, 0x3e, 0x01, 0x7c, 0x2e, 0x0f, 0x76, 0x3e, 0x5e, 0x53, 0x6c, 0x5b, 0x5f, 0x7c, 0x19, 0x41, 222 0x1f, 0x2b, 0x1a, 0x5d, 0x69, 0x7a, 0x46, 0x0c, 0x5f, 0x32, 0x4b, 0x4a, 0x28, 0x52, 0x79,
223 0x02, 0x2f, 0x17, 0x64, 0x41, 0x75, 0x10, 0x04, 0x47, 0x7c, 0x3d, 0x4b, 0x52, 0x00, 0x10, 0x5d, 0x51, 0x4e, 0x7a, 0x27, 0x25, 0x55, 223 0x5b, 0x12, 0x42, 0x18, 0x00, 0x5d, 0x27, 0x31, 0x53, 0x3c, 0x4c, 0x36, 0x4e, 0x38, 0x3f,
224 0x40, 0x12, 0x35, 0x60, 0x05, 0x1b, 0x34, 0x2d, 0x04, 0x7a, 0x6a, 0x69, 0x02, 0x79, 0x03, 0x3a, 0x2f, 0x06, 0x0a, 0x79, 0x7b, 0x12, 224 0x72, 0x03, 0x71, 0x02, 0x5b, 0x36, 0x59, 0x7f, 0x75, 0x6e, 0x08, 0x54, 0x0d, 0x34, 0x1c,
225 0x5d, 0x7c, 0x52, 0x29, 0x47, 0x58, 0x12, 0x73, 0x3f, 0x27, 0x56, 0x05, 0x0c, 0x48, 0x32, 0x58, 0x6b, 0x57, 0x5c, 0x03, 0x64, 0x56, 225 0x34, 0x57, 0x5d, 0x69, 0x48, 0x00, 0x3b, 0x05, 0x07, 0x6e, 0x27, 0x65, 0x6e, 0x40, 0x3d,
226 0x11, 0x52, 0x7a, 0x30, 0x36, 0x29, 0x17, 0x3b, 0x68, 0x7a, 0x7c, 0x05, 0x6b, 0x6b, 0x13, 0x6a, 0x24, 0x5c, 0x68, 0x42, 0x18, 0x32, 226 0x3a, 0x4f, 0x72, 0x5d, 0x39, 0x16, 0x0f, 0x63, 0x12, 0x12, 0x15, 0x3a, 0x70, 0x0d, 0x57,
227 0x03, 0x73, 0x6e, 0x04, 0x21, 0x2e, 0x01, 0x04, 0x63, 0x7d, 0x44, 0x41, 0x12, 0x31, 0x0b, 0x15, 0x1f, 0x70, 0x00, 0x2e, 0x66, 0x14, 227 0x18, 0x0d, 0x5e, 0x3d, 0x22, 0x68, 0x68, 0x7c, 0x6d, 0x4f, 0x0c, 0x7b, 0x09, 0x2d, 0x4a,
228 0x3c, 0x7f, 0x2b, 0x00, 0x1f, 0x0c, 0x28, 0x59, 0x0a, 0x16, 0x49, 0x5a, 0x5c, 0x64, 0x65, 0x4b, 0x11, 0x29, 0x15, 0x36, 0x5a, 0x65, 228 0x73, 0x20, 0x47, 0x07, 0x57, 0x75, 0x5d, 0x53, 0x70, 0x34, 0x21, 0x40, 0x57, 0x51, 0x5e,
229 0x19, 0x4f, 0x60, 0x23, 0x3a, 0x3a, 0x13, 0x25, 0x02, 0x78, 0x4c, 0x54}; 229 0x49, 0x44, 0x00, 0x54, 0x27, 0x04, 0x68, 0x7e, 0x59, 0x56, 0x58, 0x74, 0x14, 0x3c, 0x16,
230 0x33, 0x41, 0x16, 0x4b, 0x2f, 0x49, 0x37, 0x0a, 0x54, 0x08, 0x08, 0x1f, 0x39, 0x67, 0x76,
231 0x28, 0x28, 0x07, 0x1d, 0x61, 0x47, 0x51, 0x4d, 0x75, 0x26, 0x52, 0x47, 0x47, 0x0c, 0x57,
232 0x58, 0x74, 0x3e, 0x62, 0x6c, 0x58, 0x3a, 0x44, 0x1e, 0x16, 0x2e, 0x21, 0x1c, 0x73, 0x45,
233 0x67, 0x74, 0x4f, 0x33, 0x66, 0x0e, 0x74, 0x66, 0x26, 0x1f, 0x2e, 0x38, 0x44, 0x40, 0x7e,
234 0x2a, 0x50, 0x52, 0x5e, 0x43, 0x01, 0x7a, 0x38, 0x49, 0x3c, 0x55, 0x4d, 0x5a, 0x44, 0x08,
235 0x26, 0x59, 0x4d, 0x45, 0x0b, 0x48, 0x0a, 0x33, 0x5e, 0x4a, 0x4d, 0x75, 0x16, 0x17, 0x63,
236 0x46, 0x01, 0x2a, 0x55, 0x7b, 0x0f, 0x02, 0x73, 0x6a, 0x4b, 0x7f, 0x75, 0x65, 0x3c, 0x4c,
237 0x33, 0x39, 0x6c, 0x74, 0x05, 0x60, 0x0f, 0x7f, 0x2d, 0x41, 0x4d, 0x4d, 0x46, 0x71, 0x09,
238 0x6f, 0x4f, 0x60, 0x15, 0x0f, 0x46, 0x73, 0x63, 0x4c, 0x5e, 0x74, 0x30, 0x0d, 0x28, 0x43,
239 0x08, 0x72, 0x32, 0x04, 0x2e, 0x31, 0x29, 0x27, 0x44, 0x6d, 0x13, 0x17, 0x48, 0x0f, 0x49,
240 0x52, 0x10, 0x13, 0x7f, 0x17, 0x16, 0x62, 0x79, 0x35, 0x78, 0x3e, 0x01, 0x7c, 0x2e, 0x0f,
241 0x76, 0x3e, 0x5e, 0x53, 0x6c, 0x5b, 0x5f, 0x7c, 0x19, 0x41, 0x02, 0x2f, 0x17, 0x64, 0x41,
242 0x75, 0x10, 0x04, 0x47, 0x7c, 0x3d, 0x4b, 0x52, 0x00, 0x10, 0x5d, 0x51, 0x4e, 0x7a, 0x27,
243 0x25, 0x55, 0x40, 0x12, 0x35, 0x60, 0x05, 0x1b, 0x34, 0x2d, 0x04, 0x7a, 0x6a, 0x69, 0x02,
244 0x79, 0x03, 0x3a, 0x2f, 0x06, 0x0a, 0x79, 0x7b, 0x12, 0x5d, 0x7c, 0x52, 0x29, 0x47, 0x58,
245 0x12, 0x73, 0x3f, 0x27, 0x56, 0x05, 0x0c, 0x48, 0x32, 0x58, 0x6b, 0x57, 0x5c, 0x03, 0x64,
246 0x56, 0x11, 0x52, 0x7a, 0x30, 0x36, 0x29, 0x17, 0x3b, 0x68, 0x7a, 0x7c, 0x05, 0x6b, 0x6b,
247 0x13, 0x6a, 0x24, 0x5c, 0x68, 0x42, 0x18, 0x32, 0x03, 0x73, 0x6e, 0x04, 0x21, 0x2e, 0x01,
248 0x04, 0x63, 0x7d, 0x44, 0x41, 0x12, 0x31, 0x0b, 0x15, 0x1f, 0x70, 0x00, 0x2e, 0x66, 0x14,
249 0x3c, 0x7f, 0x2b, 0x00, 0x1f, 0x0c, 0x28, 0x59, 0x0a, 0x16, 0x49, 0x5a, 0x5c, 0x64, 0x65,
250 0x4b, 0x11, 0x29, 0x15, 0x36, 0x5a, 0x65, 0x19, 0x4f, 0x60, 0x23, 0x3a, 0x3a, 0x13, 0x25,
251 0x02, 0x78, 0x4c, 0x54};
230 char b64_known[1369] = { 252 char b64_known[1369] = {
231 0x43, 0x7a, 0x42, 0x45, 0x59, 0x6e, 0x77, 0x69, 0x48, 0x77, 0x30, 0x46, 0x5a, 0x79, 0x77, 0x71, 0x4f, 0x53, 0x46, 0x47, 0x43, 0x46, 253 0x43, 0x7a, 0x42, 0x45, 0x59, 0x6e, 0x77, 0x69, 0x48, 0x77, 0x30, 0x46, 0x5a, 0x79, 0x77,
232 0x42, 0x6d, 0x4e, 0x44, 0x63, 0x4c, 0x52, 0x55, 0x73, 0x34, 0x4d, 0x67, 0x5a, 0x36, 0x50, 0x6e, 0x38, 0x4d, 0x51, 0x42, 0x68, 0x72, 254 0x71, 0x4f, 0x53, 0x46, 0x47, 0x43, 0x46, 0x42, 0x6d, 0x4e, 0x44, 0x63, 0x4c, 0x52, 0x55,
233 0x4c, 0x57, 0x42, 0x4d, 0x59, 0x41, 0x77, 0x6a, 0x51, 0x7a, 0x73, 0x2b, 0x47, 0x78, 0x59, 0x45, 0x52, 0x6c, 0x67, 0x2f, 0x51, 0x47, 255 0x73, 0x34, 0x4d, 0x67, 0x5a, 0x36, 0x50, 0x6e, 0x38, 0x4d, 0x51, 0x42, 0x68, 0x72, 0x4c,
234 0x6f, 0x52, 0x42, 0x57, 0x4e, 0x78, 0x46, 0x44, 0x56, 0x48, 0x65, 0x52, 0x4e, 0x76, 0x61, 0x79, 0x63, 0x59, 0x57, 0x30, 0x67, 0x6e, 256 0x57, 0x42, 0x4d, 0x59, 0x41, 0x77, 0x6a, 0x51, 0x7a, 0x73, 0x2b, 0x47, 0x78, 0x59, 0x45,
235 0x50, 0x6d, 0x38, 0x56, 0x4d, 0x30, 0x38, 0x2b, 0x58, 0x6c, 0x46, 0x7a, 0x61, 0x43, 0x55, 0x50, 0x42, 0x6c, 0x74, 0x38, 0x63, 0x6e, 257 0x52, 0x6c, 0x67, 0x2f, 0x51, 0x47, 0x6f, 0x52, 0x42, 0x57, 0x4e, 0x78, 0x46, 0x44, 0x56,
236 0x55, 0x2b, 0x50, 0x78, 0x74, 0x63, 0x62, 0x57, 0x6f, 0x35, 0x66, 0x47, 0x4e, 0x6a, 0x59, 0x47, 0x78, 0x36, 0x4d, 0x33, 0x5a, 0x53, 258 0x48, 0x65, 0x52, 0x4e, 0x76, 0x61, 0x79, 0x63, 0x59, 0x57, 0x30, 0x67, 0x6e, 0x50, 0x6d,
237 0x45, 0x79, 0x55, 0x7a, 0x66, 0x57, 0x55, 0x6a, 0x4a, 0x78, 0x45, 0x47, 0x42, 0x6b, 0x64, 0x78, 0x48, 0x68, 0x52, 0x30, 0x59, 0x33, 259 0x38, 0x56, 0x4d, 0x30, 0x38, 0x2b, 0x58, 0x6c, 0x46, 0x7a, 0x61, 0x43, 0x55, 0x50, 0x42,
238 0x41, 0x74, 0x46, 0x53, 0x63, 0x59, 0x55, 0x51, 0x59, 0x46, 0x4d, 0x78, 0x45, 0x73, 0x61, 0x77, 0x41, 0x74, 0x64, 0x79, 0x42, 0x49, 260 0x6c, 0x74, 0x38, 0x63, 0x6e, 0x55, 0x2b, 0x50, 0x78, 0x74, 0x63, 0x62, 0x57, 0x6f, 0x35,
239 0x44, 0x58, 0x4e, 0x52, 0x52, 0x53, 0x56, 0x2f, 0x66, 0x7a, 0x55, 0x6d, 0x4c, 0x69, 0x5a, 0x54, 0x4a, 0x47, 0x67, 0x65, 0x44, 0x6c, 261 0x66, 0x47, 0x4e, 0x6a, 0x59, 0x47, 0x78, 0x36, 0x4d, 0x33, 0x5a, 0x53, 0x45, 0x79, 0x55,
240 0x67, 0x36, 0x57, 0x56, 0x42, 0x57, 0x4e, 0x31, 0x39, 0x6d, 0x41, 0x55, 0x78, 0x61, 0x5a, 0x44, 0x4a, 0x51, 0x65, 0x32, 0x6f, 0x67, 262 0x7a, 0x66, 0x57, 0x55, 0x6a, 0x4a, 0x78, 0x45, 0x47, 0x42, 0x6b, 0x64, 0x78, 0x48, 0x68,
241 0x63, 0x69, 0x73, 0x64, 0x66, 0x6b, 0x4e, 0x37, 0x59, 0x55, 0x49, 0x4c, 0x59, 0x58, 0x4d, 0x6b, 0x65, 0x54, 0x70, 0x72, 0x53, 0x6e, 263 0x52, 0x30, 0x59, 0x33, 0x41, 0x74, 0x46, 0x53, 0x63, 0x59, 0x55, 0x51, 0x59, 0x46, 0x4d,
242 0x6c, 0x75, 0x43, 0x51, 0x38, 0x6e, 0x4c, 0x51, 0x78, 0x65, 0x4d, 0x6b, 0x73, 0x4e, 0x65, 0x55, 0x59, 0x35, 0x49, 0x51, 0x6f, 0x6d, 264 0x78, 0x45, 0x73, 0x61, 0x77, 0x41, 0x74, 0x64, 0x79, 0x42, 0x49, 0x44, 0x58, 0x4e, 0x52,
243 0x58, 0x7a, 0x6f, 0x41, 0x4a, 0x6a, 0x38, 0x54, 0x4c, 0x6e, 0x35, 0x51, 0x4b, 0x32, 0x64, 0x47, 0x63, 0x6a, 0x38, 0x37, 0x41, 0x55, 265 0x52, 0x53, 0x56, 0x2f, 0x66, 0x7a, 0x55, 0x6d, 0x4c, 0x69, 0x5a, 0x54, 0x4a, 0x47, 0x67,
244 0x59, 0x62, 0x43, 0x7a, 0x56, 0x4a, 0x4f, 0x52, 0x6c, 0x77, 0x50, 0x51, 0x4a, 0x42, 0x44, 0x6a, 0x67, 0x46, 0x64, 0x6d, 0x56, 0x50, 266 0x65, 0x44, 0x6c, 0x67, 0x36, 0x57, 0x56, 0x42, 0x57, 0x4e, 0x31, 0x39, 0x6d, 0x41, 0x55,
245 0x4d, 0x57, 0x78, 0x65, 0x46, 0x77, 0x51, 0x56, 0x4e, 0x69, 0x5a, 0x6b, 0x4e, 0x42, 0x51, 0x58, 0x66, 0x41, 0x34, 0x4c, 0x57, 0x31, 267 0x78, 0x61, 0x5a, 0x44, 0x4a, 0x51, 0x65, 0x32, 0x6f, 0x67, 0x63, 0x69, 0x73, 0x64, 0x66,
246 0x56, 0x54, 0x61, 0x77, 0x42, 0x43, 0x51, 0x55, 0x38, 0x43, 0x58, 0x42, 0x4d, 0x4b, 0x4c, 0x43, 0x77, 0x2b, 0x45, 0x42, 0x51, 0x7a, 268 0x6b, 0x4e, 0x37, 0x59, 0x55, 0x49, 0x4c, 0x59, 0x58, 0x4d, 0x6b, 0x65, 0x54, 0x70, 0x72,
247 0x52, 0x58, 0x78, 0x36, 0x57, 0x6a, 0x46, 0x68, 0x4f, 0x51, 0x67, 0x69, 0x61, 0x68, 0x34, 0x50, 0x62, 0x78, 0x74, 0x73, 0x45, 0x31, 269 0x53, 0x6e, 0x6c, 0x75, 0x43, 0x51, 0x38, 0x6e, 0x4c, 0x51, 0x78, 0x65, 0x4d, 0x6b, 0x73,
248 0x35, 0x35, 0x49, 0x48, 0x6c, 0x51, 0x59, 0x67, 0x59, 0x73, 0x64, 0x68, 0x63, 0x45, 0x4b, 0x79, 0x70, 0x31, 0x48, 0x77, 0x77, 0x33, 270 0x4e, 0x65, 0x55, 0x59, 0x35, 0x49, 0x51, 0x6f, 0x6d, 0x58, 0x7a, 0x6f, 0x41, 0x4a, 0x6a,
249 0x54, 0x67, 0x39, 0x37, 0x4c, 0x54, 0x52, 0x31, 0x59, 0x44, 0x46, 0x30, 0x4c, 0x67, 0x70, 0x4b, 0x45, 0x57, 0x78, 0x4a, 0x4a, 0x51, 271 0x38, 0x54, 0x4c, 0x6e, 0x35, 0x51, 0x4b, 0x32, 0x64, 0x47, 0x63, 0x6a, 0x38, 0x37, 0x41,
250 0x45, 0x36, 0x50, 0x53, 0x49, 0x65, 0x62, 0x52, 0x68, 0x52, 0x65, 0x43, 0x31, 0x69, 0x4d, 0x55, 0x78, 0x51, 0x51, 0x42, 0x64, 0x4c, 272 0x55, 0x59, 0x62, 0x43, 0x7a, 0x56, 0x4a, 0x4f, 0x52, 0x6c, 0x77, 0x50, 0x51, 0x4a, 0x42,
251 0x62, 0x79, 0x49, 0x41, 0x66, 0x32, 0x45, 0x71, 0x4e, 0x44, 0x34, 0x41, 0x58, 0x79, 0x39, 0x66, 0x4c, 0x78, 0x51, 0x71, 0x56, 0x53, 273 0x44, 0x6a, 0x67, 0x46, 0x64, 0x6d, 0x56, 0x50, 0x4d, 0x57, 0x78, 0x65, 0x46, 0x77, 0x51,
252 0x63, 0x66, 0x52, 0x68, 0x38, 0x53, 0x52, 0x6c, 0x34, 0x65, 0x44, 0x48, 0x77, 0x34, 0x41, 0x57, 0x46, 0x6b, 0x64, 0x69, 0x4a, 0x75, 274 0x56, 0x4e, 0x69, 0x5a, 0x6b, 0x4e, 0x42, 0x51, 0x58, 0x66, 0x41, 0x34, 0x4c, 0x57, 0x31,
253 0x43, 0x43, 0x41, 0x34, 0x54, 0x33, 0x4e, 0x79, 0x56, 0x52, 0x4a, 0x43, 0x47, 0x56, 0x42, 0x68, 0x51, 0x33, 0x64, 0x39, 0x51, 0x53, 275 0x56, 0x54, 0x61, 0x77, 0x42, 0x43, 0x51, 0x55, 0x38, 0x43, 0x58, 0x42, 0x4d, 0x4b, 0x4c,
254 0x34, 0x31, 0x54, 0x7a, 0x30, 0x78, 0x4b, 0x46, 0x68, 0x6e, 0x47, 0x77, 0x4e, 0x52, 0x49, 0x44, 0x49, 0x63, 0x43, 0x47, 0x34, 0x33, 276 0x43, 0x77, 0x2b, 0x45, 0x42, 0x51, 0x7a, 0x52, 0x58, 0x78, 0x36, 0x57, 0x6a, 0x46, 0x68,
255 0x64, 0x54, 0x64, 0x45, 0x54, 0x32, 0x67, 0x5a, 0x42, 0x32, 0x51, 0x55, 0x4b, 0x43, 0x55, 0x72, 0x61, 0x54, 0x55, 0x59, 0x4a, 0x79, 277 0x4f, 0x51, 0x67, 0x69, 0x61, 0x68, 0x34, 0x50, 0x62, 0x78, 0x74, 0x73, 0x45, 0x31, 0x35,
256 0x59, 0x55, 0x45, 0x33, 0x42, 0x43, 0x47, 0x52, 0x4a, 0x31, 0x50, 0x67, 0x4a, 0x64, 0x66, 0x42, 0x4d, 0x66, 0x46, 0x6c, 0x4d, 0x37, 278 0x35, 0x49, 0x48, 0x6c, 0x51, 0x59, 0x67, 0x59, 0x73, 0x64, 0x68, 0x63, 0x45, 0x4b, 0x79,
257 0x64, 0x45, 0x67, 0x38, 0x58, 0x6a, 0x6c, 0x73, 0x48, 0x42, 0x78, 0x30, 0x4f, 0x52, 0x38, 0x41, 0x47, 0x77, 0x59, 0x4b, 0x61, 0x44, 279 0x70, 0x31, 0x48, 0x77, 0x77, 0x33, 0x54, 0x67, 0x39, 0x37, 0x4c, 0x54, 0x52, 0x31, 0x59,
258 0x74, 0x53, 0x54, 0x78, 0x35, 0x75, 0x50, 0x44, 0x55, 0x4d, 0x4f, 0x41, 0x34, 0x4c, 0x4f, 0x78, 0x70, 0x32, 0x49, 0x79, 0x6c, 0x54, 280 0x44, 0x46, 0x30, 0x4c, 0x67, 0x70, 0x4b, 0x45, 0x57, 0x78, 0x4a, 0x4a, 0x51, 0x45, 0x36,
259 0x48, 0x6c, 0x39, 0x42, 0x44, 0x45, 0x73, 0x4b, 0x5a, 0x53, 0x68, 0x34, 0x5a, 0x30, 0x68, 0x5a, 0x4a, 0x6d, 0x30, 0x78, 0x64, 0x69, 281 0x50, 0x53, 0x49, 0x65, 0x62, 0x52, 0x68, 0x52, 0x65, 0x43, 0x31, 0x69, 0x4d, 0x55, 0x78,
260 0x4e, 0x77, 0x59, 0x57, 0x51, 0x37, 0x4f, 0x48, 0x6c, 0x6d, 0x64, 0x46, 0x4d, 0x73, 0x5a, 0x47, 0x52, 0x55, 0x41, 0x31, 0x52, 0x6c, 282 0x51, 0x51, 0x42, 0x64, 0x4c, 0x62, 0x79, 0x49, 0x41, 0x66, 0x32, 0x45, 0x71, 0x4e, 0x44,
261 0x52, 0x45, 0x77, 0x59, 0x54, 0x30, 0x67, 0x67, 0x54, 0x33, 0x49, 0x51, 0x50, 0x77, 0x78, 0x53, 0x4c, 0x51, 0x4d, 0x55, 0x41, 0x31, 283 0x34, 0x41, 0x58, 0x79, 0x39, 0x66, 0x4c, 0x78, 0x51, 0x71, 0x56, 0x53, 0x63, 0x66, 0x52,
262 0x46, 0x43, 0x45, 0x48, 0x64, 0x71, 0x4e, 0x41, 0x59, 0x79, 0x41, 0x33, 0x49, 0x55, 0x66, 0x41, 0x68, 0x64, 0x55, 0x68, 0x70, 0x69, 284 0x68, 0x38, 0x53, 0x52, 0x6c, 0x34, 0x65, 0x44, 0x48, 0x77, 0x34, 0x41, 0x57, 0x46, 0x6b,
263 0x66, 0x44, 0x34, 0x77, 0x66, 0x6c, 0x39, 0x2f, 0x56, 0x41, 0x39, 0x45, 0x53, 0x56, 0x31, 0x65, 0x45, 0x47, 0x6f, 0x47, 0x4b, 0x77, 285 0x64, 0x69, 0x4a, 0x75, 0x43, 0x43, 0x41, 0x34, 0x54, 0x33, 0x4e, 0x79, 0x56, 0x52, 0x4a,
264 0x5a, 0x54, 0x45, 0x44, 0x6b, 0x33, 0x4d, 0x6b, 0x70, 0x4f, 0x50, 0x53, 0x74, 0x6c, 0x4f, 0x44, 0x6b, 0x48, 0x63, 0x6c, 0x52, 0x6b, 286 0x43, 0x47, 0x56, 0x42, 0x68, 0x51, 0x33, 0x64, 0x39, 0x51, 0x53, 0x34, 0x31, 0x54, 0x7a,
265 0x54, 0x56, 0x5a, 0x71, 0x41, 0x79, 0x4a, 0x77, 0x65, 0x31, 0x39, 0x67, 0x43, 0x79, 0x6f, 0x4c, 0x61, 0x78, 0x42, 0x6b, 0x46, 0x41, 287 0x30, 0x78, 0x4b, 0x46, 0x68, 0x6e, 0x47, 0x77, 0x4e, 0x52, 0x49, 0x44, 0x49, 0x63, 0x43,
266 0x55, 0x69, 0x41, 0x48, 0x4e, 0x41, 0x49, 0x31, 0x74, 0x52, 0x48, 0x79, 0x73, 0x61, 0x58, 0x57, 0x6c, 0x36, 0x52, 0x67, 0x78, 0x66, 288 0x47, 0x34, 0x33, 0x64, 0x54, 0x64, 0x45, 0x54, 0x32, 0x67, 0x5a, 0x42, 0x32, 0x51, 0x55,
267 0x4d, 0x6b, 0x74, 0x4b, 0x4b, 0x46, 0x4a, 0x35, 0x57, 0x78, 0x4a, 0x43, 0x47, 0x41, 0x42, 0x64, 0x4a, 0x7a, 0x46, 0x54, 0x50, 0x45, 289 0x4b, 0x43, 0x55, 0x72, 0x61, 0x54, 0x55, 0x59, 0x4a, 0x79, 0x59, 0x55, 0x45, 0x33, 0x42,
268 0x77, 0x32, 0x54, 0x6a, 0x67, 0x2f, 0x63, 0x67, 0x4e, 0x78, 0x41, 0x6c, 0x73, 0x32, 0x57, 0x58, 0x39, 0x31, 0x62, 0x67, 0x68, 0x55, 290 0x43, 0x47, 0x52, 0x4a, 0x31, 0x50, 0x67, 0x4a, 0x64, 0x66, 0x42, 0x4d, 0x66, 0x46, 0x6c,
269 0x44, 0x54, 0x51, 0x63, 0x4e, 0x46, 0x64, 0x64, 0x61, 0x55, 0x67, 0x41, 0x4f, 0x77, 0x55, 0x48, 0x62, 0x69, 0x64, 0x6c, 0x62, 0x6b, 291 0x4d, 0x37, 0x64, 0x45, 0x67, 0x38, 0x58, 0x6a, 0x6c, 0x73, 0x48, 0x42, 0x78, 0x30, 0x4f,
270 0x41, 0x39, 0x4f, 0x6b, 0x39, 0x79, 0x58, 0x54, 0x6b, 0x57, 0x44, 0x32, 0x4d, 0x53, 0x45, 0x68, 0x55, 0x36, 0x63, 0x41, 0x31, 0x58, 292 0x52, 0x38, 0x41, 0x47, 0x77, 0x59, 0x4b, 0x61, 0x44, 0x74, 0x53, 0x54, 0x78, 0x35, 0x75,
271 0x47, 0x41, 0x31, 0x65, 0x50, 0x53, 0x4a, 0x6f, 0x61, 0x48, 0x78, 0x74, 0x54, 0x77, 0x78, 0x37, 0x43, 0x53, 0x31, 0x4b, 0x63, 0x79, 293 0x50, 0x44, 0x55, 0x4d, 0x4f, 0x41, 0x34, 0x4c, 0x4f, 0x78, 0x70, 0x32, 0x49, 0x79, 0x6c,
272 0x42, 0x48, 0x42, 0x31, 0x64, 0x31, 0x58, 0x56, 0x4e, 0x77, 0x4e, 0x43, 0x46, 0x41, 0x56, 0x31, 0x46, 0x65, 0x53, 0x55, 0x51, 0x41, 294 0x54, 0x48, 0x6c, 0x39, 0x42, 0x44, 0x45, 0x73, 0x4b, 0x5a, 0x53, 0x68, 0x34, 0x5a, 0x30,
273 0x56, 0x43, 0x63, 0x45, 0x61, 0x48, 0x35, 0x5a, 0x56, 0x6c, 0x68, 0x30, 0x46, 0x44, 0x77, 0x57, 0x4d, 0x30, 0x45, 0x57, 0x53, 0x79, 295 0x68, 0x5a, 0x4a, 0x6d, 0x30, 0x78, 0x64, 0x69, 0x4e, 0x77, 0x59, 0x57, 0x51, 0x37, 0x4f,
274 0x39, 0x4a, 0x4e, 0x77, 0x70, 0x55, 0x43, 0x41, 0x67, 0x66, 0x4f, 0x57, 0x64, 0x32, 0x4b, 0x43, 0x67, 0x48, 0x48, 0x57, 0x46, 0x48, 296 0x48, 0x6c, 0x6d, 0x64, 0x46, 0x4d, 0x73, 0x5a, 0x47, 0x52, 0x55, 0x41, 0x31, 0x52, 0x6c,
275 0x55, 0x55, 0x31, 0x31, 0x4a, 0x6c, 0x4a, 0x48, 0x52, 0x77, 0x78, 0x58, 0x57, 0x48, 0x51, 0x2b, 0x59, 0x6d, 0x78, 0x59, 0x4f, 0x6b, 297 0x52, 0x45, 0x77, 0x59, 0x54, 0x30, 0x67, 0x67, 0x54, 0x33, 0x49, 0x51, 0x50, 0x77, 0x78,
276 0x51, 0x65, 0x46, 0x69, 0x34, 0x68, 0x48, 0x48, 0x4e, 0x46, 0x5a, 0x33, 0x52, 0x50, 0x4d, 0x32, 0x59, 0x4f, 0x64, 0x47, 0x59, 0x6d, 298 0x53, 0x4c, 0x51, 0x4d, 0x55, 0x41, 0x31, 0x46, 0x43, 0x45, 0x48, 0x64, 0x71, 0x4e, 0x41,
277 0x48, 0x79, 0x34, 0x34, 0x52, 0x45, 0x42, 0x2b, 0x4b, 0x6c, 0x42, 0x53, 0x58, 0x6b, 0x4d, 0x42, 0x65, 0x6a, 0x68, 0x4a, 0x50, 0x46, 299 0x59, 0x79, 0x41, 0x33, 0x49, 0x55, 0x66, 0x41, 0x68, 0x64, 0x55, 0x68, 0x70, 0x69, 0x66,
278 0x56, 0x4e, 0x57, 0x6b, 0x51, 0x49, 0x4a, 0x6c, 0x6c, 0x4e, 0x52, 0x51, 0x74, 0x49, 0x43, 0x6a, 0x4e, 0x65, 0x53, 0x6b, 0x31, 0x31, 300 0x44, 0x34, 0x77, 0x66, 0x6c, 0x39, 0x2f, 0x56, 0x41, 0x39, 0x45, 0x53, 0x56, 0x31, 0x65,
279 0x46, 0x68, 0x64, 0x6a, 0x52, 0x67, 0x45, 0x71, 0x56, 0x58, 0x73, 0x50, 0x41, 0x6e, 0x4e, 0x71, 0x53, 0x33, 0x39, 0x31, 0x5a, 0x54, 301 0x45, 0x47, 0x6f, 0x47, 0x4b, 0x77, 0x5a, 0x54, 0x45, 0x44, 0x6b, 0x33, 0x4d, 0x6b, 0x70,
280 0x78, 0x4d, 0x4d, 0x7a, 0x6c, 0x73, 0x64, 0x41, 0x56, 0x67, 0x44, 0x33, 0x38, 0x74, 0x51, 0x55, 0x31, 0x4e, 0x52, 0x6e, 0x45, 0x4a, 302 0x4f, 0x50, 0x53, 0x74, 0x6c, 0x4f, 0x44, 0x6b, 0x48, 0x63, 0x6c, 0x52, 0x6b, 0x54, 0x56,
281 0x62, 0x30, 0x39, 0x67, 0x46, 0x51, 0x39, 0x47, 0x63, 0x32, 0x4e, 0x4d, 0x58, 0x6e, 0x51, 0x77, 0x44, 0x53, 0x68, 0x44, 0x43, 0x48, 303 0x5a, 0x71, 0x41, 0x79, 0x4a, 0x77, 0x65, 0x31, 0x39, 0x67, 0x43, 0x79, 0x6f, 0x4c, 0x61,
282 0x49, 0x79, 0x42, 0x43, 0x34, 0x78, 0x4b, 0x53, 0x64, 0x45, 0x62, 0x52, 0x4d, 0x58, 0x53, 0x41, 0x39, 0x4a, 0x55, 0x68, 0x41, 0x54, 304 0x78, 0x42, 0x6b, 0x46, 0x41, 0x55, 0x69, 0x41, 0x48, 0x4e, 0x41, 0x49, 0x31, 0x74, 0x52,
283 0x66, 0x78, 0x63, 0x57, 0x59, 0x6e, 0x6b, 0x31, 0x65, 0x44, 0x34, 0x42, 0x66, 0x43, 0x34, 0x50, 0x64, 0x6a, 0x35, 0x65, 0x55, 0x32, 305 0x48, 0x79, 0x73, 0x61, 0x58, 0x57, 0x6c, 0x36, 0x52, 0x67, 0x78, 0x66, 0x4d, 0x6b, 0x74,
284 0x78, 0x62, 0x58, 0x33, 0x77, 0x5a, 0x51, 0x51, 0x49, 0x76, 0x46, 0x32, 0x52, 0x42, 0x64, 0x52, 0x41, 0x45, 0x52, 0x33, 0x77, 0x39, 306 0x4b, 0x4b, 0x46, 0x4a, 0x35, 0x57, 0x78, 0x4a, 0x43, 0x47, 0x41, 0x42, 0x64, 0x4a, 0x7a,
285 0x53, 0x31, 0x49, 0x41, 0x45, 0x46, 0x31, 0x52, 0x54, 0x6e, 0x6f, 0x6e, 0x4a, 0x56, 0x56, 0x41, 0x45, 0x6a, 0x56, 0x67, 0x42, 0x52, 307 0x46, 0x54, 0x50, 0x45, 0x77, 0x32, 0x54, 0x6a, 0x67, 0x2f, 0x63, 0x67, 0x4e, 0x78, 0x41,
286 0x73, 0x30, 0x4c, 0x51, 0x52, 0x36, 0x61, 0x6d, 0x6b, 0x43, 0x65, 0x51, 0x4d, 0x36, 0x4c, 0x77, 0x59, 0x4b, 0x65, 0x58, 0x73, 0x53, 308 0x6c, 0x73, 0x32, 0x57, 0x58, 0x39, 0x31, 0x62, 0x67, 0x68, 0x55, 0x44, 0x54, 0x51, 0x63,
287 0x58, 0x58, 0x78, 0x53, 0x4b, 0x55, 0x64, 0x59, 0x45, 0x6e, 0x4d, 0x2f, 0x4a, 0x31, 0x59, 0x46, 0x44, 0x45, 0x67, 0x79, 0x57, 0x47, 309 0x4e, 0x46, 0x64, 0x64, 0x61, 0x55, 0x67, 0x41, 0x4f, 0x77, 0x55, 0x48, 0x62, 0x69, 0x64,
288 0x74, 0x58, 0x58, 0x41, 0x4e, 0x6b, 0x56, 0x68, 0x46, 0x53, 0x65, 0x6a, 0x41, 0x32, 0x4b, 0x52, 0x63, 0x37, 0x61, 0x48, 0x70, 0x38, 310 0x6c, 0x62, 0x6b, 0x41, 0x39, 0x4f, 0x6b, 0x39, 0x79, 0x58, 0x54, 0x6b, 0x57, 0x44, 0x32,
289 0x42, 0x57, 0x74, 0x72, 0x45, 0x32, 0x6f, 0x6b, 0x58, 0x47, 0x68, 0x43, 0x47, 0x44, 0x49, 0x44, 0x63, 0x32, 0x34, 0x45, 0x49, 0x53, 311 0x4d, 0x53, 0x45, 0x68, 0x55, 0x36, 0x63, 0x41, 0x31, 0x58, 0x47, 0x41, 0x31, 0x65, 0x50,
290 0x34, 0x42, 0x42, 0x47, 0x4e, 0x39, 0x52, 0x45, 0x45, 0x53, 0x4d, 0x51, 0x73, 0x56, 0x48, 0x33, 0x41, 0x41, 0x4c, 0x6d, 0x59, 0x55, 312 0x53, 0x4a, 0x6f, 0x61, 0x48, 0x78, 0x74, 0x54, 0x77, 0x78, 0x37, 0x43, 0x53, 0x31, 0x4b,
291 0x50, 0x48, 0x38, 0x72, 0x41, 0x42, 0x38, 0x4d, 0x4b, 0x46, 0x6b, 0x4b, 0x46, 0x6b, 0x6c, 0x61, 0x58, 0x47, 0x52, 0x6c, 0x53, 0x78, 313 0x63, 0x79, 0x42, 0x48, 0x42, 0x31, 0x64, 0x31, 0x58, 0x56, 0x4e, 0x77, 0x4e, 0x43, 0x46,
292 0x45, 0x70, 0x46, 0x54, 0x5a, 0x61, 0x5a, 0x52, 0x6c, 0x50, 0x59, 0x43, 0x4d, 0x36, 0x4f, 0x68, 0x4d, 0x6c, 0x41, 0x6e, 0x68, 0x4d, 314 0x41, 0x56, 0x31, 0x46, 0x65, 0x53, 0x55, 0x51, 0x41, 0x56, 0x43, 0x63, 0x45, 0x61, 0x48,
293 0x56, 0x41, 0x3d, 0x3d, 0x00}; 315 0x35, 0x5a, 0x56, 0x6c, 0x68, 0x30, 0x46, 0x44, 0x77, 0x57, 0x4d, 0x30, 0x45, 0x57, 0x53,
316 0x79, 0x39, 0x4a, 0x4e, 0x77, 0x70, 0x55, 0x43, 0x41, 0x67, 0x66, 0x4f, 0x57, 0x64, 0x32,
317 0x4b, 0x43, 0x67, 0x48, 0x48, 0x57, 0x46, 0x48, 0x55, 0x55, 0x31, 0x31, 0x4a, 0x6c, 0x4a,
318 0x48, 0x52, 0x77, 0x78, 0x58, 0x57, 0x48, 0x51, 0x2b, 0x59, 0x6d, 0x78, 0x59, 0x4f, 0x6b,
319 0x51, 0x65, 0x46, 0x69, 0x34, 0x68, 0x48, 0x48, 0x4e, 0x46, 0x5a, 0x33, 0x52, 0x50, 0x4d,
320 0x32, 0x59, 0x4f, 0x64, 0x47, 0x59, 0x6d, 0x48, 0x79, 0x34, 0x34, 0x52, 0x45, 0x42, 0x2b,
321 0x4b, 0x6c, 0x42, 0x53, 0x58, 0x6b, 0x4d, 0x42, 0x65, 0x6a, 0x68, 0x4a, 0x50, 0x46, 0x56,
322 0x4e, 0x57, 0x6b, 0x51, 0x49, 0x4a, 0x6c, 0x6c, 0x4e, 0x52, 0x51, 0x74, 0x49, 0x43, 0x6a,
323 0x4e, 0x65, 0x53, 0x6b, 0x31, 0x31, 0x46, 0x68, 0x64, 0x6a, 0x52, 0x67, 0x45, 0x71, 0x56,
324 0x58, 0x73, 0x50, 0x41, 0x6e, 0x4e, 0x71, 0x53, 0x33, 0x39, 0x31, 0x5a, 0x54, 0x78, 0x4d,
325 0x4d, 0x7a, 0x6c, 0x73, 0x64, 0x41, 0x56, 0x67, 0x44, 0x33, 0x38, 0x74, 0x51, 0x55, 0x31,
326 0x4e, 0x52, 0x6e, 0x45, 0x4a, 0x62, 0x30, 0x39, 0x67, 0x46, 0x51, 0x39, 0x47, 0x63, 0x32,
327 0x4e, 0x4d, 0x58, 0x6e, 0x51, 0x77, 0x44, 0x53, 0x68, 0x44, 0x43, 0x48, 0x49, 0x79, 0x42,
328 0x43, 0x34, 0x78, 0x4b, 0x53, 0x64, 0x45, 0x62, 0x52, 0x4d, 0x58, 0x53, 0x41, 0x39, 0x4a,
329 0x55, 0x68, 0x41, 0x54, 0x66, 0x78, 0x63, 0x57, 0x59, 0x6e, 0x6b, 0x31, 0x65, 0x44, 0x34,
330 0x42, 0x66, 0x43, 0x34, 0x50, 0x64, 0x6a, 0x35, 0x65, 0x55, 0x32, 0x78, 0x62, 0x58, 0x33,
331 0x77, 0x5a, 0x51, 0x51, 0x49, 0x76, 0x46, 0x32, 0x52, 0x42, 0x64, 0x52, 0x41, 0x45, 0x52,
332 0x33, 0x77, 0x39, 0x53, 0x31, 0x49, 0x41, 0x45, 0x46, 0x31, 0x52, 0x54, 0x6e, 0x6f, 0x6e,
333 0x4a, 0x56, 0x56, 0x41, 0x45, 0x6a, 0x56, 0x67, 0x42, 0x52, 0x73, 0x30, 0x4c, 0x51, 0x52,
334 0x36, 0x61, 0x6d, 0x6b, 0x43, 0x65, 0x51, 0x4d, 0x36, 0x4c, 0x77, 0x59, 0x4b, 0x65, 0x58,
335 0x73, 0x53, 0x58, 0x58, 0x78, 0x53, 0x4b, 0x55, 0x64, 0x59, 0x45, 0x6e, 0x4d, 0x2f, 0x4a,
336 0x31, 0x59, 0x46, 0x44, 0x45, 0x67, 0x79, 0x57, 0x47, 0x74, 0x58, 0x58, 0x41, 0x4e, 0x6b,
337 0x56, 0x68, 0x46, 0x53, 0x65, 0x6a, 0x41, 0x32, 0x4b, 0x52, 0x63, 0x37, 0x61, 0x48, 0x70,
338 0x38, 0x42, 0x57, 0x74, 0x72, 0x45, 0x32, 0x6f, 0x6b, 0x58, 0x47, 0x68, 0x43, 0x47, 0x44,
339 0x49, 0x44, 0x63, 0x32, 0x34, 0x45, 0x49, 0x53, 0x34, 0x42, 0x42, 0x47, 0x4e, 0x39, 0x52,
340 0x45, 0x45, 0x53, 0x4d, 0x51, 0x73, 0x56, 0x48, 0x33, 0x41, 0x41, 0x4c, 0x6d, 0x59, 0x55,
341 0x50, 0x48, 0x38, 0x72, 0x41, 0x42, 0x38, 0x4d, 0x4b, 0x46, 0x6b, 0x4b, 0x46, 0x6b, 0x6c,
342 0x61, 0x58, 0x47, 0x52, 0x6c, 0x53, 0x78, 0x45, 0x70, 0x46, 0x54, 0x5a, 0x61, 0x5a, 0x52,
343 0x6c, 0x50, 0x59, 0x43, 0x4d, 0x36, 0x4f, 0x68, 0x4d, 0x6c, 0x41, 0x6e, 0x68, 0x4d, 0x56,
344 0x41, 0x3d, 0x3d, 0x00};
294 char *b64_test; 345 char *b64_test;
295 346
296 plan_tests(1); 347 plan_tests(1);
diff --git a/lib/tests/test_cmd.c b/lib/tests/test_cmd.c
index c8867dfb..d51016cc 100644
--- a/lib/tests/test_cmd.c
+++ b/lib/tests/test_cmd.c
@@ -38,36 +38,35 @@ char *get_command(char *const *line) {
38} 38}
39 39
40int main(int argc, char **argv) { 40int main(int argc, char **argv) {
41 char **command_line = malloc(sizeof(char *) * COMMAND_LINE);
42 char *command = NULL;
43 char *perl;
44 output chld_out, chld_err;
45 int c;
46 int result = UNSET;
47
48 plan_tests(51); 41 plan_tests(51);
49 42
50 diag("Running plain echo command, set one"); 43 diag("Running plain echo command, set one");
51 44
52 /* ensure everything is empty before we begin */ 45 /* ensure everything is empty before we begin */
46
47 output chld_out;
53 memset(&chld_out, 0, sizeof(output)); 48 memset(&chld_out, 0, sizeof(output));
49 output chld_err;
54 memset(&chld_err, 0, sizeof(output)); 50 memset(&chld_err, 0, sizeof(output));
55 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset"); 51 ok(chld_out.lines == 0, "(initialised) Checking stdout is reset");
56 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset"); 52 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
53 int result = UNSET;
57 ok(result == UNSET, "(initialised) Checking exit code is reset"); 54 ok(result == UNSET, "(initialised) Checking exit code is reset");
58 55
56 char **command_line = malloc(sizeof(char *) * COMMAND_LINE);
59 command_line[0] = strdup("/bin/echo"); 57 command_line[0] = strdup("/bin/echo");
60 command_line[1] = strdup("this"); 58 command_line[1] = strdup("this");
61 command_line[2] = strdup("is"); 59 command_line[2] = strdup("is");
62 command_line[3] = strdup("test"); 60 command_line[3] = strdup("test");
63 command_line[4] = strdup("one"); 61 command_line[4] = strdup("one");
64 62
65 command = get_command(command_line); 63 char *command = get_command(command_line);
66 64
67 result = cmd_run_array(command_line, &chld_out, &chld_err, 0); 65 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
68 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines"); 66 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines");
69 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); 67 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
70 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(array) Check for expected stdout output"); 68 ok(strcmp(chld_out.line[0], "this is test one") == 0,
69 "(array) Check for expected stdout output");
71 ok(result == 0, "(array) Checking exit code"); 70 ok(result == 0, "(array) Checking exit code");
72 71
73 /* ensure everything is empty again */ 72 /* ensure everything is empty again */
@@ -82,7 +81,8 @@ int main(int argc, char **argv) {
82 81
83 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines"); 82 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines");
84 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines"); 83 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines");
85 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output"); 84 ok(strcmp(chld_out.line[0], "this is test one") == 0,
85 "(string) Check for expected stdout output");
86 ok(result == 0, "(string) Checking exit code"); 86 ok(result == 0, "(string) Checking exit code");
87 87
88 diag("Running plain echo command, set two"); 88 diag("Running plain echo command, set two");
@@ -104,7 +104,8 @@ int main(int argc, char **argv) {
104 result = cmd_run_array(command_line, &chld_out, &chld_err, 0); 104 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
105 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines"); 105 ok(chld_out.lines == 1, "(array) Check for expected number of stdout lines");
106 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); 106 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
107 ok(strcmp(chld_out.line[0], "this is test two") == 0, "(array) Check for expected stdout output"); 107 ok(strcmp(chld_out.line[0], "this is test two") == 0,
108 "(array) Check for expected stdout output");
108 ok(result == 0, "(array) Checking exit code"); 109 ok(result == 0, "(array) Checking exit code");
109 110
110 /* ensure everything is empty again */ 111 /* ensure everything is empty again */
@@ -119,7 +120,8 @@ int main(int argc, char **argv) {
119 120
120 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines"); 121 ok(chld_out.lines == 1, "(string) Check for expected number of stdout lines");
121 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines"); 122 ok(chld_err.lines == 0, "(string) Check for expected number of stderr lines");
122 ok(strcmp(chld_out.line[0], "this is test one") == 0, "(string) Check for expected stdout output"); 123 ok(strcmp(chld_out.line[0], "this is test one") == 0,
124 "(string) Check for expected stdout output");
123 ok(result == 0, "(string) Checking exit code"); 125 ok(result == 0, "(string) Checking exit code");
124 126
125 /* ensure everything is empty again */ 127 /* ensure everything is empty again */
@@ -130,7 +132,8 @@ int main(int argc, char **argv) {
130 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset"); 132 ok(chld_err.lines == 0, "(initialised) Checking stderr is reset");
131 ok(result == UNSET, "(initialised) Checking exit code is reset"); 133 ok(result == UNSET, "(initialised) Checking exit code is reset");
132 134
133 /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line output */ 135 /* Pass linefeeds via parameters through - those should be evaluated by echo to give multi line
136 * output */
134 command_line[0] = strdup("/bin/echo"); 137 command_line[0] = strdup("/bin/echo");
135 command_line[1] = strdup("this is a test via echo\nline two\nit's line 3"); 138 command_line[1] = strdup("this is a test via echo\nline two\nit's line 3");
136 command_line[2] = strdup("and (note space between '3' and 'and') $$ will not get evaluated"); 139 command_line[2] = strdup("and (note space between '3' and 'and') $$ will not get evaluated");
@@ -138,9 +141,12 @@ int main(int argc, char **argv) {
138 result = cmd_run_array(command_line, &chld_out, &chld_err, 0); 141 result = cmd_run_array(command_line, &chld_out, &chld_err, 0);
139 ok(chld_out.lines == 3, "(array) Check for expected number of stdout lines"); 142 ok(chld_out.lines == 3, "(array) Check for expected number of stdout lines");
140 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines"); 143 ok(chld_err.lines == 0, "(array) Check for expected number of stderr lines");
141 ok(strcmp(chld_out.line[0], "this is a test via echo") == 0, "(array) Check line 1 for expected stdout output"); 144 ok(strcmp(chld_out.line[0], "this is a test via echo") == 0,
142 ok(strcmp(chld_out.line[1], "line two") == 0, "(array) Check line 2 for expected stdout output"); 145 "(array) Check line 1 for expected stdout output");
143 ok(strcmp(chld_out.line[2], "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0, 146 ok(strcmp(chld_out.line[1], "line two") == 0,
147 "(array) Check line 2 for expected stdout output");
148 ok(strcmp(chld_out.line[2],
149 "it's line 3 and (note space between '3' and 'and') $$ will not get evaluated") == 0,
144 "(array) Check line 3 for expected stdout output"); 150 "(array) Check line 3 for expected stdout output");
145 ok(result == 0, "(array) Checking exit code"); 151 ok(result == 0, "(array) Checking exit code");
146 152
@@ -171,7 +177,8 @@ int main(int argc, char **argv) {
171 177
172 ok(chld_out.lines == 0, "/bin/sh returns no stdout when file is missing..."); 178 ok(chld_out.lines == 0, "/bin/sh returns no stdout when file is missing...");
173 ok(chld_err.lines == 1, "...but does give an error line"); 179 ok(chld_err.lines == 1, "...but does give an error line");
174 ok(strstr(chld_err.line[0], "non-existent-file") != NULL, "And missing filename is in error message"); 180 ok(strstr(chld_err.line[0], "non-existent-file") != NULL,
181 "And missing filename is in error message");
175 ok(result != 0, "Get non-zero return code from /bin/sh"); 182 ok(result != 0, "Get non-zero return code from /bin/sh");
176 183
177 /* ensure everything is empty again */ 184 /* ensure everything is empty again */
diff --git a/lib/tests/test_generic_output.c b/lib/tests/test_generic_output.c
index e67aefc9..e4a78bcd 100644
--- a/lib/tests/test_generic_output.c
+++ b/lib/tests/test_generic_output.c
@@ -110,7 +110,8 @@ void test_two_subchecks(void) {
110 sc1.output = "foobar"; 110 sc1.output = "foobar";
111 sc1 = mp_set_subcheck_state(sc1, STATE_WARNING); 111 sc1 = mp_set_subcheck_state(sc1, STATE_WARNING);
112 112
113 ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, "Test subcheck state directly after setting it"); 113 ok(mp_compute_subcheck_state(sc1) == STATE_WARNING,
114 "Test subcheck state directly after setting it");
114 115
115 mp_perfdata pd1 = perfdata_init(); 116 mp_perfdata pd1 = perfdata_init();
116 117
@@ -129,7 +130,8 @@ void test_two_subchecks(void) {
129 130
130 mp_add_subcheck_to_subcheck(&sc1, sc2); 131 mp_add_subcheck_to_subcheck(&sc1, sc2);
131 132
132 ok(mp_compute_subcheck_state(sc1) == STATE_WARNING, "Test subcheck state after adding a subcheck"); 133 ok(mp_compute_subcheck_state(sc1) == STATE_WARNING,
134 "Test subcheck state after adding a subcheck");
133 135
134 mp_check check = mp_check_init(); 136 mp_check check = mp_check_init();
135 mp_add_subcheck_to_check(&check, sc1); 137 mp_add_subcheck_to_check(&check, sc1);
diff --git a/lib/tests/test_ini1.c b/lib/tests/test_ini1.c
index 246c1250..de983764 100644
--- a/lib/tests/test_ini1.c
+++ b/lib/tests/test_ini1.c
@@ -42,27 +42,30 @@ char *list2str(np_arg_list *optlst) {
42 free(optltmp); 42 free(optltmp);
43 } 43 }
44 /* Strip last whitespace */ 44 /* Strip last whitespace */
45 if (strlen(optstr) > 1) 45 if (strlen(optstr) > 1) {
46 optstr[strlen(optstr) - 1] = '\0'; 46 optstr[strlen(optstr) - 1] = '\0';
47 }
47 48
48 return optstr; 49 return optstr;
49} 50}
50 51
51int main(int argc, char **argv) { 52int main(int argc, char **argv) {
52 char *optstr = NULL;
53 53
54 plan_tests(12); 54 plan_tests(12);
55 55
56 optstr = list2str(np_get_defaults("section@./config-tiny.ini", "check_disk")); 56 char *optstr = list2str(np_get_defaults("section@./config-tiny.ini", "check_disk"));
57 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "config-tiny.ini's section as expected"); 57 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"),
58 "config-tiny.ini's section as expected");
58 my_free(optstr); 59 my_free(optstr);
59 60
60 optstr = list2str(np_get_defaults("@./config-tiny.ini", "section")); 61 optstr = list2str(np_get_defaults("@./config-tiny.ini", "section"));
61 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"), "Used default section name, without specific"); 62 ok(!strcmp(optstr, "--one=two --Foo=Bar --this=Your Mother! --blank"),
63 "Used default section name, without specific");
62 my_free(optstr); 64 my_free(optstr);
63 65
64 optstr = list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk")); 66 optstr = list2str(np_get_defaults("Section Two@./config-tiny.ini", "check_disk"));
65 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-tiny.ini's Section Two as expected"); 67 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"),
68 "config-tiny.ini's Section Two as expected");
66 my_free(optstr); 69 my_free(optstr);
67 70
68 optstr = list2str(np_get_defaults("/path/to/file.txt@./config-tiny.ini", "check_disk")); 71 optstr = list2str(np_get_defaults("/path/to/file.txt@./config-tiny.ini", "check_disk"));
@@ -70,15 +73,18 @@ int main(int argc, char **argv) {
70 my_free(optstr); 73 my_free(optstr);
71 74
72 optstr = list2str(np_get_defaults("section2@./config-tiny.ini", "check_disk")); 75 optstr = list2str(np_get_defaults("section2@./config-tiny.ini", "check_disk"));
73 ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section2 with whitespace before section name"); 76 ok(!strcmp(optstr, "--this=that"),
77 "config-tiny.ini's section2 with whitespace before section name");
74 my_free(optstr); 78 my_free(optstr);
75 79
76 optstr = list2str(np_get_defaults("section3@./config-tiny.ini", "check_disk")); 80 optstr = list2str(np_get_defaults("section3@./config-tiny.ini", "check_disk"));
77 ok(!strcmp(optstr, "--this=that"), "config-tiny.ini's section3 with whitespace after section name"); 81 ok(!strcmp(optstr, "--this=that"),
82 "config-tiny.ini's section3 with whitespace after section name");
78 my_free(optstr); 83 my_free(optstr);
79 84
80 optstr = list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk")); 85 optstr = list2str(np_get_defaults("check_mysql@./plugin.ini", "check_disk"));
81 ok(!strcmp(optstr, "--username=operator --password=secret"), "plugin.ini's check_mysql as expected"); 86 ok(!strcmp(optstr, "--username=operator --password=secret"),
87 "plugin.ini's check_mysql as expected");
82 my_free(optstr); 88 my_free(optstr);
83 89
84 optstr = list2str(np_get_defaults("check_mysql2@./plugin.ini", "check_disk")); 90 optstr = list2str(np_get_defaults("check_mysql2@./plugin.ini", "check_disk"));
@@ -90,29 +96,39 @@ int main(int argc, char **argv) {
90 my_free(optstr); 96 my_free(optstr);
91 97
92 optstr = list2str(np_get_defaults("Section Two@./config-dos.ini", "check_disk")); 98 optstr = list2str(np_get_defaults("Section Two@./config-dos.ini", "check_disk"));
93 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"), "config-dos.ini's Section Two as expected"); 99 ok(!strcmp(optstr, "--something else=blah --remove=whitespace"),
100 "config-dos.ini's Section Two as expected");
94 my_free(optstr); 101 my_free(optstr);
95 102
96 optstr = list2str(np_get_defaults("section_twice@./plugin.ini", "check_disk")); 103 optstr = list2str(np_get_defaults("section_twice@./plugin.ini", "check_disk"));
97 ok(!strcmp(optstr, "--foo=bar --bar=foo"), "plugin.ini's section_twice defined twice in the file"); 104 ok(!strcmp(optstr, "--foo=bar --bar=foo"),
105 "plugin.ini's section_twice defined twice in the file");
98 my_free(optstr); 106 my_free(optstr);
99 107
100 optstr = list2str(np_get_defaults("tcp_long_lines@plugins.ini", "check_tcp")); 108 optstr = list2str(np_get_defaults("tcp_long_lines@plugins.ini", "check_tcp"));
101 ok(!strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar " 109 ok(!strcmp(optstr, "--escape --send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
110 "yadda Foo bar BAZ yadda yadda yadda Foo bar "
102 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 111 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
103 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " 112 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar "
113 "BAZ yadda yadda yadda Foo bar BAZ yadda "
104 "yadda yadda Foo bar BAZ yadda yadda yadda Foo " 114 "yadda yadda Foo bar BAZ yadda yadda yadda Foo "
105 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 115 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
116 "yadda yadda Foo bar BAZ yadda yadda "
106 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " 117 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
107 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda --expect=Foo bar BAZ yadda yadda " 118 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
119 "yadda --expect=Foo bar BAZ yadda yadda "
108 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " 120 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
109 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo " 121 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
122 "yadda Foo bar BAZ yadda yadda yadda Foo "
110 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 123 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
111 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " 124 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar "
125 "BAZ yadda yadda yadda Foo bar BAZ yadda "
112 "yadda yadda Foo bar BAZ yadda yadda yadda Foo " 126 "yadda yadda Foo bar BAZ yadda yadda yadda Foo "
113 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 127 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
128 "yadda yadda Foo bar BAZ yadda yadda "
114 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " 129 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
115 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo " 130 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
131 "yadda Foo bar BAZ yadda yadda yadda Foo "
116 "bar BAZ yadda yadda yadda --jail"), 132 "bar BAZ yadda yadda yadda --jail"),
117 "Long options"); 133 "Long options");
118 my_free(optstr); 134 my_free(optstr);
diff --git a/lib/tests/test_opts1.c b/lib/tests/test_opts1.c
index 984183d3..fa95c4d4 100644
--- a/lib/tests/test_opts1.c
+++ b/lib/tests/test_opts1.c
@@ -40,37 +40,40 @@ void my_free(int *argc, char **newargv, char **argv) {
40#else 40#else
41void my_free(int *argc, char **newargv, char **argv) { 41void my_free(int *argc, char **newargv, char **argv) {
42 /* Free stuff (and print while we're at it) */ 42 /* Free stuff (and print while we're at it) */
43 int i, freeflag = 1; 43 bool freeflag = true;
44 printf(" Arg(%i): ", *argc + 1); 44 printf(" Arg(%i): ", *argc + 1);
45 printf("'%s' ", newargv[0]); 45 printf("'%s' ", newargv[0]);
46 for (i = 1; i < *argc; i++) { 46
47 for (int i = 1; i < *argc; i++) {
47 printf("'%s' ", newargv[i]); 48 printf("'%s' ", newargv[i]);
48 /* Stop freeing when we get to the start of the original array */ 49 /* Stop freeing when we get to the start of the original array */
49 if (freeflag) { 50 if (freeflag) {
50 if (newargv[i] == argv[1]) 51 if (newargv[i] == argv[1]) {
51 freeflag = 0; 52 freeflag = false;
52 else 53 } else {
53 free(newargv[i]); 54 free(newargv[i]);
55 }
54 } 56 }
55 } 57 }
56 printf("\n"); 58 printf("\n");
57 /* Free only if it's a different array */ 59 /* Free only if it's a different array */
58 if (newargv != argv) 60 if (newargv != argv) {
59 free(newargv); 61 free(newargv);
62 }
60 *argc = 0; 63 *argc = 0;
61} 64}
62#endif 65#endif
63 66
64int array_diff(int i1, char **a1, int i2, char **a2) { 67int array_diff(int i1, char **a1, int i2, char **a2) {
65 int i;
66
67 if (i1 != i2) { 68 if (i1 != i2) {
68 printf(" Argument count doesn't match!\n"); 69 printf(" Argument count doesn't match!\n");
69 return 0; 70 return 0;
70 } 71 }
71 for (i = 0; i <= i1; i++) { 72
72 if (a1[i] == NULL && a2[i] == NULL) 73 for (int i = 0; i <= i1; i++) {
74 if (a1[i] == NULL && a2[i] == NULL) {
73 continue; 75 continue;
76 }
74 if (a1[i] == NULL || a2[i] == NULL) { 77 if (a1[i] == NULL || a2[i] == NULL) {
75 printf(" Argument # %i null in one array!\n", i); 78 printf(" Argument # %i null in one array!\n", i);
76 return 0; 79 return 0;
@@ -84,11 +87,10 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
84} 87}
85 88
86int main(int argc, char **argv) { 89int main(int argc, char **argv) {
87 char **argv_new = NULL;
88 int i, argc_test;
89
90 plan_tests(5); 90 plan_tests(5);
91 91
92 char **argv_new = NULL;
93 int argc_test;
92 { 94 {
93 char *argv_test[] = {"prog_name", (char *)NULL}; 95 char *argv_test[] = {"prog_name", (char *)NULL};
94 argc_test = 1; 96 argc_test = 1;
@@ -110,27 +112,36 @@ int main(int argc, char **argv) {
110 { 112 {
111 char *argv_test[] = {"prog_name", "--extra-opts=@./config-opts.ini", (char *)NULL}; 113 char *argv_test[] = {"prog_name", "--extra-opts=@./config-opts.ini", (char *)NULL};
112 argc_test = 2; 114 argc_test = 2;
113 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", (char *)NULL}; 115 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank",
116 (char *)NULL};
114 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); 117 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
115 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts using default section"); 118 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts using default section");
116 my_free(&argc_test, argv_new, argv_test); 119 my_free(&argc_test, argv_new, argv_test);
117 } 120 }
118 121
119 { 122 {
120 char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts", "sect2@./config-opts.ini", (char *)NULL}; 123 char *argv_test[] = {"prog_name", "--extra-opts=sect1@./config-opts.ini", "--extra-opts",
124 "sect2@./config-opts.ini", (char *)NULL};
121 argc_test = 4; 125 argc_test = 4;
122 char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that", (char *)NULL}; 126 char *argv_known[] = {"prog_name", "--one=two", "--something else=oops", "--this=that",
127 (char *)NULL};
123 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); 128 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
124 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts specified twice"); 129 ok(array_diff(argc_test, argv_new, 4, argv_known), "Only extra opts specified twice");
125 my_free(&argc_test, argv_new, argv_test); 130 my_free(&argc_test, argv_new, argv_test);
126 } 131 }
127 132
128 { 133 {
129 char *argv_test[] = {"prog_name", "--arg1=val1", "--extra-opts=@./config-opts.ini", "--extra-opts", "sect1@./config-opts.ini", 134 char *argv_test[] = {"prog_name",
130 "--arg2", (char *)NULL}; 135 "--arg1=val1",
136 "--extra-opts=@./config-opts.ini",
137 "--extra-opts",
138 "sect1@./config-opts.ini",
139 "--arg2",
140 (char *)NULL};
131 argc_test = 6; 141 argc_test = 6;
132 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!", "--blank", "--one=two", 142 char *argv_known[] = {"prog_name", "--foo=Bar", "--this=Your Mother!",
133 "--arg1=val1", "--arg2", (char *)NULL}; 143 "--blank", "--one=two", "--arg1=val1",
144 "--arg2", (char *)NULL};
134 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); 145 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
135 ok(array_diff(argc_test, argv_new, 7, argv_known), "twice extra opts using two sections"); 146 ok(array_diff(argc_test, argv_new, 7, argv_known), "twice extra opts using two sections");
136 my_free(&argc_test, argv_new, argv_test); 147 my_free(&argc_test, argv_new, argv_test);
diff --git a/lib/tests/test_opts2.c b/lib/tests/test_opts2.c
index 23496617..3dd1b039 100644
--- a/lib/tests/test_opts2.c
+++ b/lib/tests/test_opts2.c
@@ -23,36 +23,39 @@
23 23
24void my_free(int *argc, char **newargv, char **argv) { 24void my_free(int *argc, char **newargv, char **argv) {
25 /* Free stuff (and print while we're at it) */ 25 /* Free stuff (and print while we're at it) */
26 int i, freeflag = 1; 26 bool freeflag = true;
27
27 printf(" Arg(%i): ", *argc + 1); 28 printf(" Arg(%i): ", *argc + 1);
28 printf("'%s' ", newargv[0]); 29 printf("'%s' ", newargv[0]);
29 for (i = 1; i < *argc; i++) { 30 for (int i = 1; i < *argc; i++) {
30 printf("'%s' ", newargv[i]); 31 printf("'%s' ", newargv[i]);
31 /* Stop freeing when we get to the start of the original array */ 32 /* Stop freeing when we get to the start of the original array */
32 if (freeflag) { 33 if (freeflag) {
33 if (newargv[i] == argv[1]) 34 if (newargv[i] == argv[1]) {
34 freeflag = 0; 35 freeflag = false;
35 else 36 } else {
36 free(newargv[i]); 37 free(newargv[i]);
38 }
37 } 39 }
38 } 40 }
39 printf("\n"); 41 printf("\n");
40 /* Free only if it's a different array */ 42 /* Free only if it's a different array */
41 if (newargv != argv) 43 if (newargv != argv) {
42 free(newargv); 44 free(newargv);
45 }
43 *argc = 0; 46 *argc = 0;
44} 47}
45 48
46int array_diff(int i1, char **a1, int i2, char **a2) { 49int array_diff(int i1, char **a1, int i2, char **a2) {
47 int i;
48
49 if (i1 != i2) { 50 if (i1 != i2) {
50 printf(" Argument count doesn't match!\n"); 51 printf(" Argument count doesn't match!\n");
51 return 0; 52 return 0;
52 } 53 }
53 for (i = 0; i <= i1; i++) { 54
54 if (a1[i] == NULL && a2[i] == NULL) 55 for (int i = 0; i <= i1; i++) {
56 if (a1[i] == NULL && a2[i] == NULL) {
55 continue; 57 continue;
58 }
56 if (a1[i] == NULL || a2[i] == NULL) { 59 if (a1[i] == NULL || a2[i] == NULL) {
57 printf(" Argument # %i null in one array!\n", i); 60 printf(" Argument # %i null in one array!\n", i);
58 return 0; 61 return 0;
@@ -66,11 +69,10 @@ int array_diff(int i1, char **a1, int i2, char **a2) {
66} 69}
67 70
68int main(int argc, char **argv) { 71int main(int argc, char **argv) {
69 char **argv_new = NULL;
70 int i, argc_test;
71
72 plan_tests(5); 72 plan_tests(5);
73 73
74 char **argv_new = NULL;
75 int argc_test;
74 { 76 {
75 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "--arg3", "val2", (char *)NULL}; 77 char *argv_test[] = {"prog_name", "arg1", "--extra-opts", "--arg3", "val2", (char *)NULL};
76 argc_test = 5; 78 argc_test = 5;
@@ -90,7 +92,8 @@ int main(int argc, char **argv) {
90 } 92 }
91 93
92 { 94 {
93 char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1", "--arg3", "val2", (char *)NULL}; 95 char *argv_test[] = {"prog_name", "arg1", "--extra-opts=section1",
96 "--arg3", "val2", (char *)NULL};
94 argc_test = 5; 97 argc_test = 5;
95 char *argv_known[] = {"prog_name", "--foobar=baz", "arg1", "--arg3", "val2", (char *)NULL}; 98 char *argv_known[] = {"prog_name", "--foobar=baz", "arg1", "--arg3", "val2", (char *)NULL};
96 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk"); 99 argv_new = np_extra_opts(&argc_test, argv_test, "check_disk");
@@ -108,30 +111,39 @@ int main(int argc, char **argv) {
108 } 111 }
109 112
110 { 113 {
111 char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines", (char *)NULL}; 114 char *argv_test[] = {"check_tcp", "--extra-opts", "--extra-opts=tcp_long_lines",
115 (char *)NULL};
112 argc_test = 3; 116 argc_test = 3;
113 char *argv_known[] = { 117 char *argv_known[] = {"check_tcp",
114 "check_tcp", 118 "--timeout=10",
115 "--timeout=10", 119 "--escape",
116 "--escape", 120 "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda "
117 "--send=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 121 "Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
118 "yadda Foo bar BAZ yadda " 122 "yadda Foo bar BAZ yadda "
119 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 123 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
120 "yadda Foo bar BAZ " 124 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
121 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " 125 "yadda Foo bar BAZ "
122 "yadda yadda Foo bar " 126 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
123 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", 127 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
124 "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 128 "yadda yadda Foo bar "
125 "yadda Foo bar BAZ yadda " 129 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
126 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda " 130 "yadda yadda yadda Foo bar BAZ yadda yadda yadda",
127 "yadda Foo bar BAZ " 131 "--expect=Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
128 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda " 132 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
129 "yadda yadda Foo bar " 133 "yadda Foo bar BAZ yadda "
130 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ " 134 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
131 "yadda yadda yadda Foo " 135 "yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda "
132 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda", 136 "yadda Foo bar BAZ "
133 "--jail", 137 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
134 (char *)NULL}; 138 "yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ yadda "
139 "yadda yadda Foo bar "
140 "BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
141 "yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
142 "yadda yadda yadda Foo "
143 "bar BAZ yadda yadda yadda Foo bar BAZ yadda yadda yadda Foo bar BAZ "
144 "yadda yadda yadda Foo bar BAZ yadda yadda yadda",
145 "--jail",
146 (char *)NULL};
135 argv_new = np_extra_opts(&argc_test, argv_test, "check_tcp"); 147 argv_new = np_extra_opts(&argc_test, argv_test, "check_tcp");
136 ok(array_diff(argc_test, argv_new, 6, argv_known), "Long lines test"); 148 ok(array_diff(argc_test, argv_new, 6, argv_known), "Long lines test");
137 my_free(&argc_test, argv_new, argv_test); 149 my_free(&argc_test, argv_new, argv_test);
diff --git a/lib/tests/test_tcp.c b/lib/tests/test_tcp.c
index 1b3003e9..37c818c9 100644
--- a/lib/tests/test_tcp.c
+++ b/lib/tests/test_tcp.c
@@ -21,30 +21,38 @@
21#include "tap.h" 21#include "tap.h"
22 22
23int main(void) { 23int main(void) {
24 char **server_expect;
25 int server_expect_count = 3;
26
27 plan_tests(9); 24 plan_tests(9);
28 25
26 char **server_expect;
27 const int server_expect_count = 3;
29 server_expect = malloc(sizeof(char *) * server_expect_count); 28 server_expect = malloc(sizeof(char *) * server_expect_count);
30 29
31 server_expect[0] = strdup("AA"); 30 server_expect[0] = strdup("AA");
32 server_expect[1] = strdup("bb"); 31 server_expect[1] = strdup("bb");
33 server_expect[2] = strdup("CC"); 32 server_expect[2] = strdup("CC");
34 33
35 ok(np_expect_match("AA bb CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_SUCCESS, 34 ok(np_expect_match("AA bb CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) ==
35 NP_MATCH_SUCCESS,
36 "Test matching any string at the beginning (first expect string)"); 36 "Test matching any string at the beginning (first expect string)");
37 ok(np_expect_match("bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_SUCCESS, 37 ok(np_expect_match("bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) ==
38 NP_MATCH_SUCCESS,
38 "Test matching any string at the beginning (second expect string)"); 39 "Test matching any string at the beginning (second expect string)");
39 ok(np_expect_match("b", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_RETRY, 40 ok(np_expect_match("b", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_RETRY,
40 "Test matching any string at the beginning (substring match)"); 41 "Test matching any string at the beginning (substring match)");
41 ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, 42 ok(np_expect_match("XX bb AA CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) ==
43 NP_MATCH_FAILURE,
42 "Test with strings not matching at the beginning"); 44 "Test with strings not matching at the beginning");
43 ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) == NP_MATCH_FAILURE, "Test matching any string"); 45 ok(np_expect_match("XX CC XX", server_expect, server_expect_count, NP_MATCH_EXACT) ==
44 ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY, "Test not matching any string"); 46 NP_MATCH_FAILURE,
45 ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_SUCCESS, 47 "Test matching any string");
48 ok(np_expect_match("XX", server_expect, server_expect_count, 0) == NP_MATCH_RETRY,
49 "Test not matching any string");
50 ok(np_expect_match("XX AA bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) ==
51 NP_MATCH_SUCCESS,
46 "Test matching all strings"); 52 "Test matching all strings");
47 ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, "Test not matching all strings"); 53 ok(np_expect_match("XX bb CC XX", server_expect, server_expect_count, NP_MATCH_ALL) ==
54 NP_MATCH_RETRY,
55 "Test not matching all strings");
48 ok(np_expect_match("XX XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY, 56 ok(np_expect_match("XX XX", server_expect, server_expect_count, NP_MATCH_ALL) == NP_MATCH_RETRY,
49 "Test not matching any string (testing all)"); 57 "Test not matching any string (testing all)");
50 58
diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c
index c3150f00..8040dec8 100644
--- a/lib/tests/test_utils.c
+++ b/lib/tests/test_utils.c
@@ -28,17 +28,7 @@
28#include "utils_base.c" 28#include "utils_base.c"
29 29
30int main(int argc, char **argv) { 30int main(int argc, char **argv) {
31 char state_path[1024]; 31 plan_tests(155);
32 range *range;
33 double temp;
34 thresholds *thresholds = NULL;
35 int i, rc;
36 char *temp_string;
37 state_key *temp_state_key = NULL;
38 state_data *temp_state_data;
39 time_t current_time;
40
41 plan_tests(185);
42 32
43 ok(this_monitoring_plugin == NULL, "monitoring_plugin not initialised"); 33 ok(this_monitoring_plugin == NULL, "monitoring_plugin not initialised");
44 34
@@ -57,7 +47,7 @@ int main(int argc, char **argv) {
57 47
58 np_set_args(argc, argv); 48 np_set_args(argc, argv);
59 49
60 range = parse_range_string("6"); 50 range *range = parse_range_string("6");
61 ok(range != NULL, "'6' is valid range"); 51 ok(range != NULL, "'6' is valid range");
62 ok(range->start == 0, "Start correct"); 52 ok(range->start == 0, "Start correct");
63 ok(range->start_infinity == false, "Not using negative infinity"); 53 ok(range->start_infinity == false, "Not using negative infinity");
@@ -97,7 +87,7 @@ int main(int argc, char **argv) {
97 free(range); 87 free(range);
98 88
99 range = parse_range_string("12345678901234567890:"); 89 range = parse_range_string("12345678901234567890:");
100 temp = atof("12345678901234567890"); /* Can't just use this because number too large */ 90 double temp = atof("12345678901234567890"); /* Can't just use this because number too large */
101 ok(range != NULL, "'12345678901234567890:' is valid range"); 91 ok(range != NULL, "'12345678901234567890:' is valid range");
102 ok(range->start == temp, "Start correct"); 92 ok(range->start == temp, "Start correct");
103 ok(range->start_infinity == false, "Not using negative infinity"); 93 ok(range->start_infinity == false, "Not using negative infinity");
@@ -158,32 +148,34 @@ int main(int argc, char **argv) {
158 range = parse_range_string("2:1"); 148 range = parse_range_string("2:1");
159 ok(range == NULL, "'2:1' rejected"); 149 ok(range == NULL, "'2:1' rejected");
160 150
161 rc = _set_thresholds(&thresholds, NULL, NULL); 151 thresholds *thresholds = NULL;
162 ok(rc == 0, "Thresholds (NULL, NULL) set"); 152 int returnCode;
153 returnCode = _set_thresholds(&thresholds, NULL, NULL);
154 ok(returnCode == 0, "Thresholds (NULL, NULL) set");
163 ok(thresholds->warning == NULL, "Warning not set"); 155 ok(thresholds->warning == NULL, "Warning not set");
164 ok(thresholds->critical == NULL, "Critical not set"); 156 ok(thresholds->critical == NULL, "Critical not set");
165 157
166 rc = _set_thresholds(&thresholds, NULL, "80"); 158 returnCode = _set_thresholds(&thresholds, NULL, "80");
167 ok(rc == 0, "Thresholds (NULL, '80') set"); 159 ok(returnCode == 0, "Thresholds (NULL, '80') set");
168 ok(thresholds->warning == NULL, "Warning not set"); 160 ok(thresholds->warning == NULL, "Warning not set");
169 ok(thresholds->critical->end == 80, "Critical set correctly"); 161 ok(thresholds->critical->end == 80, "Critical set correctly");
170 162
171 rc = _set_thresholds(&thresholds, "5:33", NULL); 163 returnCode = _set_thresholds(&thresholds, "5:33", NULL);
172 ok(rc == 0, "Thresholds ('5:33', NULL) set"); 164 ok(returnCode == 0, "Thresholds ('5:33', NULL) set");
173 ok(thresholds->warning->start == 5, "Warning start set"); 165 ok(thresholds->warning->start == 5, "Warning start set");
174 ok(thresholds->warning->end == 33, "Warning end set"); 166 ok(thresholds->warning->end == 33, "Warning end set");
175 ok(thresholds->critical == NULL, "Critical not set"); 167 ok(thresholds->critical == NULL, "Critical not set");
176 168
177 rc = _set_thresholds(&thresholds, "30", "60"); 169 returnCode = _set_thresholds(&thresholds, "30", "60");
178 ok(rc == 0, "Thresholds ('30', '60') set"); 170 ok(returnCode == 0, "Thresholds ('30', '60') set");
179 ok(thresholds->warning->end == 30, "Warning set correctly"); 171 ok(thresholds->warning->end == 30, "Warning set correctly");
180 ok(thresholds->critical->end == 60, "Critical set correctly"); 172 ok(thresholds->critical->end == 60, "Critical set correctly");
181 ok(get_status(15.3, thresholds) == STATE_OK, "15.3 - ok"); 173 ok(get_status(15.3, thresholds) == STATE_OK, "15.3 - ok");
182 ok(get_status(30.0001, thresholds) == STATE_WARNING, "30.0001 - warning"); 174 ok(get_status(30.0001, thresholds) == STATE_WARNING, "30.0001 - warning");
183 ok(get_status(69, thresholds) == STATE_CRITICAL, "69 - critical"); 175 ok(get_status(69, thresholds) == STATE_CRITICAL, "69 - critical");
184 176
185 rc = _set_thresholds(&thresholds, "-10:-2", "-30:20"); 177 returnCode = _set_thresholds(&thresholds, "-10:-2", "-30:20");
186 ok(rc == 0, "Thresholds ('-30:20', '-10:-2') set"); 178 ok(returnCode == 0, "Thresholds ('-30:20', '-10:-2') set");
187 ok(thresholds->warning->start == -10, "Warning start set correctly"); 179 ok(thresholds->warning->start == -10, "Warning start set correctly");
188 ok(thresholds->warning->end == -2, "Warning end set correctly"); 180 ok(thresholds->warning->end == -2, "Warning end set correctly");
189 ok(thresholds->critical->start == -30, "Critical start set correctly"); 181 ok(thresholds->critical->start == -30, "Critical start set correctly");
@@ -304,164 +296,28 @@ int main(int argc, char **argv) {
304 test = np_extract_ntpvar("", "foo"); 296 test = np_extract_ntpvar("", "foo");
305 ok(!test, "Empty string return NULL"); 297 ok(!test, "Empty string return NULL");
306 298
307 /* This is the result of running ./test_utils */
308 temp_string = (char *)_np_state_generate_key();
309 ok(!strcmp(temp_string, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got hash with exe and no parameters") ||
310 diag("You are probably running in wrong directory. Must run as ./test_utils");
311
312 this_monitoring_plugin->argc = 4;
313 this_monitoring_plugin->argv[0] = "./test_utils";
314 this_monitoring_plugin->argv[1] = "here";
315 this_monitoring_plugin->argv[2] = "--and";
316 this_monitoring_plugin->argv[3] = "now";
317 temp_string = (char *)_np_state_generate_key();
318 ok(!strcmp(temp_string, "bd72da9f78ff1419fad921ea5e43ce56508aef6c"), "Got based on expected argv");
319
320 unsetenv("MP_STATE_PATH");
321 temp_string = (char *)_np_state_calculate_location_prefix();
322 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory");
323
324 setenv("MP_STATE_PATH", "", 1);
325 temp_string = (char *)_np_state_calculate_location_prefix();
326 ok(!strcmp(temp_string, NP_STATE_DIR_PREFIX), "Got default directory even with empty string");
327
328 setenv("MP_STATE_PATH", "/usr/local/nagios/var", 1);
329 temp_string = (char *)_np_state_calculate_location_prefix();
330 ok(!strcmp(temp_string, "/usr/local/nagios/var"), "Got default directory");
331
332 ok(temp_state_key == NULL, "temp_state_key initially empty");
333
334 this_monitoring_plugin->argc = 1;
335 this_monitoring_plugin->argv[0] = "./test_utils";
336 np_enable_state(NULL, 51);
337 temp_state_key = this_monitoring_plugin->state;
338 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
339 ok(!strcmp(temp_state_key->name, "e2d17f995fd4c020411b85e3e3d0ff7306d4147e"), "Got generated filename");
340
341 np_enable_state("allowedchars_in_keyname", 77);
342 temp_state_key = this_monitoring_plugin->state;
343 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/allowedchars_in_keyname", (unsigned long)geteuid());
344 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
345 ok(!strcmp(temp_state_key->name, "allowedchars_in_keyname"), "Got key name with valid chars");
346 ok(!strcmp(temp_state_key->_filename, state_path), "Got internal filename");
347
348 /* Don't do this test just yet. Will die */
349 /*
350 np_enable_state("bad^chars$in@here", 77);
351 temp_state_key = this_monitoring_plugin->state;
352 ok( !strcmp(temp_state_key->name, "bad_chars_in_here"), "Got key name with bad chars replaced" );
353 */
354
355 np_enable_state("funnykeyname", 54);
356 temp_state_key = this_monitoring_plugin->state;
357 sprintf(state_path, "/usr/local/nagios/var/%lu/check_test/funnykeyname", (unsigned long)geteuid());
358 ok(!strcmp(temp_state_key->plugin_name, "check_test"), "Got plugin name");
359 ok(!strcmp(temp_state_key->name, "funnykeyname"), "Got key name");
360
361 ok(!strcmp(temp_state_key->_filename, state_path), "Got internal filename");
362 ok(temp_state_key->data_version == 54, "Version set");
363
364 temp_state_data = np_state_read();
365 ok(temp_state_data == NULL, "Got no state data as file does not exist");
366
367 /*
368 temp_fp = fopen("var/statefile", "r");
369 if (temp_fp==NULL)
370 printf("Error opening. errno=%d\n", errno);
371 printf("temp_fp=%s\n", temp_fp);
372 ok( _np_state_read_file(temp_fp) == true, "Can read state file" );
373 fclose(temp_fp);
374 */
375
376 temp_state_key->_filename = "var/statefile";
377 temp_state_data = np_state_read();
378 ok(this_monitoring_plugin->state->state_data != NULL, "Got state data now") ||
379 diag("Are you running in right directory? Will get coredump next if not");
380 ok(this_monitoring_plugin->state->state_data->time == 1234567890, "Got time");
381 ok(!strcmp((char *)this_monitoring_plugin->state->state_data->data, "String to read"), "Data as expected");
382
383 temp_state_key->data_version = 53;
384 temp_state_data = np_state_read();
385 ok(temp_state_data == NULL, "Older data version gives NULL");
386 temp_state_key->data_version = 54;
387
388 temp_state_key->_filename = "var/nonexistent";
389 temp_state_data = np_state_read();
390 ok(temp_state_data == NULL, "Missing file gives NULL");
391 ok(this_monitoring_plugin->state->state_data == NULL, "No state information");
392
393 temp_state_key->_filename = "var/oldformat";
394 temp_state_data = np_state_read();
395 ok(temp_state_data == NULL, "Old file format gives NULL");
396
397 temp_state_key->_filename = "var/baddate";
398 temp_state_data = np_state_read();
399 ok(temp_state_data == NULL, "Bad date gives NULL");
400
401 temp_state_key->_filename = "var/missingdataline";
402 temp_state_data = np_state_read();
403 ok(temp_state_data == NULL, "Missing data line gives NULL");
404
405 unlink("var/generated");
406 temp_state_key->_filename = "var/generated";
407 current_time = 1234567890;
408 np_state_write_string(current_time, "String to read");
409 ok(system("cmp var/generated var/statefile") == 0, "Generated file same as expected");
410
411 unlink("var/generated_directory/statefile");
412 unlink("var/generated_directory");
413 temp_state_key->_filename = "var/generated_directory/statefile";
414 current_time = 1234567890;
415 np_state_write_string(current_time, "String to read");
416 ok(system("cmp var/generated_directory/statefile var/statefile") == 0, "Have created directory");
417
418 /* This test to check cannot write to dir - can't automate yet */
419 /*
420 unlink("var/generated_bad_dir");
421 mkdir("var/generated_bad_dir", S_IRUSR);
422 np_state_write_string(current_time, "String to read");
423 */
424
425 temp_state_key->_filename = "var/generated";
426 time(&current_time);
427 np_state_write_string(0, "String to read");
428 temp_state_data = np_state_read();
429 /* Check time is set to current_time */
430 ok(system("cmp var/generated var/statefile > /dev/null") != 0, "Generated file should be different this time");
431 ok(this_monitoring_plugin->state->state_data->time - current_time <= 1, "Has time generated from current time");
432
433 /* Don't know how to automatically test this. Need to be able to redefine die and catch the error */
434 /*
435 temp_state_key->_filename="/dev/do/not/expect/to/be/able/to/write";
436 np_state_write_string(0, "Bad file");
437 */
438
439 np_cleanup();
440
441 ok(this_monitoring_plugin == NULL, "Free'd this_monitoring_plugin");
442
443 ok(mp_suid() == false, "Test aren't suid"); 299 ok(mp_suid() == false, "Test aren't suid");
444 300
445 /* base states with random case */ 301 /* base states with random case */
446 char *states[] = {"Ok", "wArnINg", "cRiTIcaL", "UnKNoWN", NULL}; 302 char *states[] = {"Ok", "wArnINg", "cRiTIcaL", "UnKNoWN", NULL};
447 303
448 for (i = 0; states[i] != NULL; i++) { 304 for (int i = 0; states[i] != NULL; i++) {
449 /* out of the random case states, create the lower and upper versions + numeric string one */ 305 /* out of the random case states, create the lower and upper versions + numeric string one
306 */
450 char *statelower = strdup(states[i]); 307 char *statelower = strdup(states[i]);
451 char *stateupper = strdup(states[i]); 308 char *stateupper = strdup(states[i]);
452 char statenum[2]; 309 char statenum[2];
453 char *temp_ptr; 310 for (char *temp_ptr = statelower; *temp_ptr; temp_ptr++) {
454 for (temp_ptr = statelower; *temp_ptr; temp_ptr++) { 311 *temp_ptr = (char)tolower(*temp_ptr);
455 *temp_ptr = tolower(*temp_ptr);
456 } 312 }
457 for (temp_ptr = stateupper; *temp_ptr; temp_ptr++) { 313 for (char *temp_ptr = stateupper; *temp_ptr; temp_ptr++) {
458 *temp_ptr = toupper(*temp_ptr); 314 *temp_ptr = (char)toupper(*temp_ptr);
459 } 315 }
460 snprintf(statenum, 2, "%i", i); 316 snprintf(statenum, 2, "%i", i);
461 317
462 /* Base test names, we'll append the state string */ 318 /* Base test names, we'll append the state string */
463 char testname[64] = "Translate state string: "; 319 char testname[64] = "Translate state string: ";
464 int tlen = strlen(testname); 320 size_t tlen = strlen(testname);
465 321
466 strcpy(testname + tlen, states[i]); 322 strcpy(testname + tlen, states[i]);
467 ok(i == mp_translate_state(states[i]), testname); 323 ok(i == mp_translate_state(states[i]), testname);
diff --git a/lib/thresholds.h b/lib/thresholds.h
index 5f9f9247..f8647681 100644
--- a/lib/thresholds.h
+++ b/lib/thresholds.h
@@ -6,12 +6,12 @@
6/* 6/*
7 * Old threshold type using the old range type 7 * Old threshold type using the old range type
8 */ 8 */
9typedef struct thresholds_struct { 9typedef struct {
10 range *warning; 10 range *warning;
11 range *critical; 11 range *critical;
12} thresholds; 12} thresholds;
13 13
14typedef struct mp_thresholds_struct { 14typedef struct {
15 bool warning_is_set; 15 bool warning_is_set;
16 mp_range warning; 16 mp_range warning;
17 bool critical_is_set; 17 bool critical_is_set;
diff --git a/lib/utils_base.c b/lib/utils_base.c
index c49a473f..28e6dc47 100644
--- a/lib/utils_base.c
+++ b/lib/utils_base.c
@@ -25,6 +25,7 @@
25 *****************************************************************************/ 25 *****************************************************************************/
26 26
27#include "../plugins/common.h" 27#include "../plugins/common.h"
28#include "states.h"
28#include <stdarg.h> 29#include <stdarg.h>
29#include "utils_base.h" 30#include "utils_base.h"
30#include <ctype.h> 31#include <ctype.h>
@@ -33,20 +34,20 @@
33#include <unistd.h> 34#include <unistd.h>
34#include <sys/types.h> 35#include <sys/types.h>
35 36
36#define np_free(ptr) \ 37#define np_free(ptr) \
37 { \ 38 { \
38 if (ptr) { \ 39 if (ptr) { \
39 free(ptr); \ 40 free(ptr); \
40 ptr = NULL; \ 41 ptr = NULL; \
41 } \ 42 } \
42 } 43 }
43 44
44monitoring_plugin *this_monitoring_plugin = NULL; 45monitoring_plugin *this_monitoring_plugin = NULL;
45 46
46int timeout_state = STATE_CRITICAL; 47mp_state_enum timeout_state = STATE_CRITICAL;
47unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT; 48unsigned int timeout_interval = DEFAULT_SOCKET_TIMEOUT;
48 49
49bool _np_state_read_file(FILE *); 50bool _np_state_read_file(FILE *state_file);
50 51
51void np_init(char *plugin_name, int argc, char **argv) { 52void np_init(char *plugin_name, int argc, char **argv) {
52 if (this_monitoring_plugin == NULL) { 53 if (this_monitoring_plugin == NULL) {
@@ -74,14 +75,6 @@ void np_set_args(int argc, char **argv) {
74 75
75void np_cleanup(void) { 76void np_cleanup(void) {
76 if (this_monitoring_plugin != NULL) { 77 if (this_monitoring_plugin != NULL) {
77 if (this_monitoring_plugin->state != NULL) {
78 if (this_monitoring_plugin->state->state_data) {
79 np_free(this_monitoring_plugin->state->state_data->data);
80 np_free(this_monitoring_plugin->state->state_data);
81 }
82 np_free(this_monitoring_plugin->state->name);
83 np_free(this_monitoring_plugin->state);
84 }
85 np_free(this_monitoring_plugin->plugin_name); 78 np_free(this_monitoring_plugin->plugin_name);
86 np_free(this_monitoring_plugin); 79 np_free(this_monitoring_plugin);
87 } 80 }
@@ -153,7 +146,8 @@ range *parse_range_string(char *str) {
153 set_range_end(temp_range, end); 146 set_range_end(temp_range, end);
154 } 147 }
155 148
156 if (temp_range->start_infinity == true || temp_range->end_infinity == true || temp_range->start <= temp_range->end) { 149 if (temp_range->start_infinity || temp_range->end_infinity ||
150 temp_range->start <= temp_range->end) {
157 return temp_range; 151 return temp_range;
158 } 152 }
159 free(temp_range); 153 free(temp_range);
@@ -205,12 +199,14 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
205 printf("Threshold not set"); 199 printf("Threshold not set");
206 } else { 200 } else {
207 if (my_threshold->warning) { 201 if (my_threshold->warning) {
208 printf("Warning: start=%g end=%g; ", my_threshold->warning->start, my_threshold->warning->end); 202 printf("Warning: start=%g end=%g; ", my_threshold->warning->start,
203 my_threshold->warning->end);
209 } else { 204 } else {
210 printf("Warning not set; "); 205 printf("Warning not set; ");
211 } 206 }
212 if (my_threshold->critical) { 207 if (my_threshold->critical) {
213 printf("Critical: start=%g end=%g", my_threshold->critical->start, my_threshold->critical->end); 208 printf("Critical: start=%g end=%g", my_threshold->critical->start,
209 my_threshold->critical->end);
214 } else { 210 } else {
215 printf("Critical not set"); 211 printf("Critical not set");
216 } 212 }
@@ -222,15 +218,16 @@ void print_thresholds(const char *threshold_name, thresholds *my_threshold) {
222bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) { 218bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
223 bool is_inside = false; 219 bool is_inside = false;
224 220
225 if (my_range.end_infinity == false && my_range.start_infinity == false) { 221 if (!my_range.end_infinity && !my_range.start_infinity) {
226 // range: .........|---inside---|........... 222 // range: .........|---inside---|...........
227 // value 223 // value
228 is_inside = ((cmp_perfdata_value(my_range.start, value) < 1) && (cmp_perfdata_value(value, my_range.end) <= 0)); 224 is_inside = ((cmp_perfdata_value(value, my_range.start) >= 0) &&
229 } else if (my_range.start_infinity == false && my_range.end_infinity == true) { 225 (cmp_perfdata_value(value, my_range.end) <= 0));
226 } else if (!my_range.start_infinity && my_range.end_infinity) {
230 // range: .........|---inside--------- 227 // range: .........|---inside---------
231 // value 228 // value
232 is_inside = (cmp_perfdata_value(my_range.start, value) < 0); 229 is_inside = (cmp_perfdata_value(value, my_range.start) >= 0);
233 } else if (my_range.start_infinity == true && my_range.end_infinity == false) { 230 } else if (my_range.start_infinity && !my_range.end_infinity) {
234 // range: -inside--------|.................... 231 // range: -inside--------|....................
235 // value 232 // value
236 is_inside = (cmp_perfdata_value(value, my_range.end) == -1); 233 is_inside = (cmp_perfdata_value(value, my_range.end) == -1);
@@ -239,7 +236,8 @@ bool mp_check_range(const mp_perfdata_value value, const mp_range my_range) {
239 is_inside = true; 236 is_inside = true;
240 } 237 }
241 238
242 if ((is_inside && my_range.alert_on_inside_range == INSIDE) || (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) { 239 if ((is_inside && my_range.alert_on_inside_range == INSIDE) ||
240 (!is_inside && my_range.alert_on_inside_range == OUTSIDE)) {
243 return true; 241 return true;
244 } 242 }
245 243
@@ -256,21 +254,21 @@ bool check_range(double value, range *my_range) {
256 yes = false; 254 yes = false;
257 } 255 }
258 256
259 if (my_range->end_infinity == false && my_range->start_infinity == false) { 257 if (!my_range->end_infinity && !my_range->start_infinity) {
260 if ((my_range->start <= value) && (value <= my_range->end)) { 258 if ((my_range->start <= value) && (value <= my_range->end)) {
261 return no; 259 return no;
262 } 260 }
263 return yes; 261 return yes;
264 } 262 }
265 263
266 if (my_range->start_infinity == false && my_range->end_infinity == true) { 264 if (!my_range->start_infinity && my_range->end_infinity) {
267 if (my_range->start <= value) { 265 if (my_range->start <= value) {
268 return no; 266 return no;
269 } 267 }
270 return yes; 268 return yes;
271 } 269 }
272 270
273 if (my_range->start_infinity == true && my_range->end_infinity == false) { 271 if (my_range->start_infinity && !my_range->end_infinity) {
274 if (value <= my_range->end) { 272 if (value <= my_range->end) {
275 return no; 273 return no;
276 } 274 }
@@ -280,14 +278,14 @@ bool check_range(double value, range *my_range) {
280} 278}
281 279
282/* Returns status */ 280/* Returns status */
283int get_status(double value, thresholds *my_thresholds) { 281mp_state_enum get_status(double value, thresholds *my_thresholds) {
284 if (my_thresholds->critical != NULL) { 282 if (my_thresholds->critical != NULL) {
285 if (check_range(value, my_thresholds->critical) == true) { 283 if (check_range(value, my_thresholds->critical)) {
286 return STATE_CRITICAL; 284 return STATE_CRITICAL;
287 } 285 }
288 } 286 }
289 if (my_thresholds->warning != NULL) { 287 if (my_thresholds->warning != NULL) {
290 if (check_range(value, my_thresholds->warning) == true) { 288 if (check_range(value, my_thresholds->warning)) {
291 return STATE_WARNING; 289 return STATE_WARNING;
292 } 290 }
293 } 291 }
@@ -296,32 +294,31 @@ int get_status(double value, thresholds *my_thresholds) {
296 294
297char *np_escaped_string(const char *string) { 295char *np_escaped_string(const char *string) {
298 char *data; 296 char *data;
299 int i; 297 int write_index = 0;
300 int j = 0;
301 data = strdup(string); 298 data = strdup(string);
302 for (i = 0; data[i]; i++) { 299 for (int i = 0; data[i]; i++) {
303 if (data[i] == '\\') { 300 if (data[i] == '\\') {
304 switch (data[++i]) { 301 switch (data[++i]) {
305 case 'n': 302 case 'n':
306 data[j++] = '\n'; 303 data[write_index++] = '\n';
307 break; 304 break;
308 case 'r': 305 case 'r':
309 data[j++] = '\r'; 306 data[write_index++] = '\r';
310 break; 307 break;
311 case 't': 308 case 't':
312 data[j++] = '\t'; 309 data[write_index++] = '\t';
313 break; 310 break;
314 case '\\': 311 case '\\':
315 data[j++] = '\\'; 312 data[write_index++] = '\\';
316 break; 313 break;
317 default: 314 default:
318 data[j++] = data[i]; 315 data[write_index++] = data[i];
319 } 316 }
320 } else { 317 } else {
321 data[j++] = data[i]; 318 data[write_index++] = data[i];
322 } 319 }
323 } 320 }
324 data[j] = '\0'; 321 data[write_index] = '\0';
325 return data; 322 return data;
326} 323}
327 324
@@ -336,33 +333,35 @@ int np_check_if_root(void) { return (geteuid() == 0); }
336char *np_extract_value(const char *varlist, const char *name, char sep) { 333char *np_extract_value(const char *varlist, const char *name, char sep) {
337 char *tmp = NULL; 334 char *tmp = NULL;
338 char *value = NULL; 335 char *value = NULL;
339 int i;
340 336
341 while (1) { 337 while (true) {
342 /* Strip any leading space */ 338 /* Strip any leading space */
343 for (; isspace(varlist[0]); varlist++) 339 for (; isspace(varlist[0]); varlist++) {
344 ; 340 ;
341 }
345 342
346 if (strncmp(name, varlist, strlen(name)) == 0) { 343 if (strncmp(name, varlist, strlen(name)) == 0) {
347 varlist += strlen(name); 344 varlist += strlen(name);
348 /* strip trailing spaces */ 345 /* strip trailing spaces */
349 for (; isspace(varlist[0]); varlist++) 346 for (; isspace(varlist[0]); varlist++) {
350 ; 347 ;
348 }
351 349
352 if (varlist[0] == '=') { 350 if (varlist[0] == '=') {
353 /* We matched the key, go past the = sign */ 351 /* We matched the key, go past the = sign */
354 varlist++; 352 varlist++;
355 /* strip leading spaces */ 353 /* strip leading spaces */
356 for (; isspace(varlist[0]); varlist++) 354 for (; isspace(varlist[0]); varlist++) {
357 ; 355 ;
356 }
358 357
359 if ((tmp = index(varlist, sep))) { 358 if ((tmp = index(varlist, sep))) {
360 /* Value is delimited by a comma */ 359 /* Value is delimited by a comma */
361 if (tmp - varlist == 0) { 360 if (tmp - varlist == 0) {
362 continue; 361 continue;
363 } 362 }
364 value = (char *)calloc(1, tmp - varlist + 1); 363 value = (char *)calloc(1, (unsigned long)(tmp - varlist + 1));
365 strncpy(value, varlist, tmp - varlist); 364 strncpy(value, varlist, (unsigned long)(tmp - varlist));
366 value[tmp - varlist] = '\0'; 365 value[tmp - varlist] = '\0';
367 } else { 366 } else {
368 /* Value is delimited by a \0 */ 367 /* Value is delimited by a \0 */
@@ -387,7 +386,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
387 386
388 /* Clean-up trailing spaces/newlines */ 387 /* Clean-up trailing spaces/newlines */
389 if (value) { 388 if (value) {
390 for (i = strlen(value) - 1; isspace(value[i]); i--) { 389 for (unsigned long i = strlen(value) - 1; isspace(value[i]); i--) {
391 value[i] = '\0'; 390 value[i] = '\0';
392 } 391 }
393 } 392 }
@@ -395,7 +394,7 @@ char *np_extract_value(const char *varlist, const char *name, char sep) {
395 return value; 394 return value;
396} 395}
397 396
398const char *state_text(int result) { 397const char *state_text(mp_state_enum result) {
399 switch (result) { 398 switch (result) {
400 case STATE_OK: 399 case STATE_OK:
401 return "OK"; 400 return "OK";
@@ -429,349 +428,3 @@ int mp_translate_state(char *state_text) {
429 } 428 }
430 return ERROR; 429 return ERROR;
431} 430}
432
433/*
434 * Returns a string to use as a keyname, based on an md5 hash of argv, thus
435 * hopefully a unique key per service/plugin invocation. Use the extra-opts
436 * parse of argv, so that uniqueness in parameters are reflected there.
437 */
438char *_np_state_generate_key(void) {
439 int i;
440 char **argv = this_monitoring_plugin->argv;
441 char keyname[41];
442 char *p = NULL;
443
444 unsigned char result[256];
445
446#ifdef USE_OPENSSL
447 /*
448 * This code path is chosen if openssl is available (which should be the most common
449 * scenario). Alternatively, the gnulib implementation/
450 *
451 */
452 EVP_MD_CTX *ctx = EVP_MD_CTX_new();
453
454 EVP_DigestInit(ctx, EVP_sha256());
455
456 for (i = 0; i < this_monitoring_plugin->argc; i++) {
457 EVP_DigestUpdate(ctx, argv[i], strlen(argv[i]));
458 }
459
460 EVP_DigestFinal(ctx, result, NULL);
461#else
462
463 struct sha256_ctx ctx;
464
465 for (i = 0; i < this_monitoring_plugin->argc; i++) {
466 sha256_process_bytes(argv[i], strlen(argv[i]), &ctx);
467 }
468
469 sha256_finish_ctx(&ctx, result);
470#endif // FOUNDOPENSSL
471
472 for (i = 0; i < 20; ++i) {
473 sprintf(&keyname[2 * i], "%02x", result[i]);
474 }
475
476 keyname[40] = '\0';
477
478 p = strdup(keyname);
479 if (p == NULL) {
480 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
481 }
482 return p;
483}
484
485void _cleanup_state_data(void) {
486 if (this_monitoring_plugin->state->state_data != NULL) {
487 np_free(this_monitoring_plugin->state->state_data->data);
488 np_free(this_monitoring_plugin->state->state_data);
489 }
490}
491
492/*
493 * Internal function. Returns either:
494 * envvar NAGIOS_PLUGIN_STATE_DIRECTORY
495 * statically compiled shared state directory
496 */
497char *_np_state_calculate_location_prefix(void) {
498 char *env_dir;
499
500 /* Do not allow passing MP_STATE_PATH in setuid plugins
501 * for security reasons */
502 if (!mp_suid()) {
503 env_dir = getenv("MP_STATE_PATH");
504 if (env_dir && env_dir[0] != '\0') {
505 return env_dir;
506 }
507 /* This is the former ENV, for backward-compatibility */
508 env_dir = getenv("NAGIOS_PLUGIN_STATE_DIRECTORY");
509 if (env_dir && env_dir[0] != '\0') {
510 return env_dir;
511 }
512 }
513
514 return NP_STATE_DIR_PREFIX;
515}
516
517/*
518 * Initiatializer for state routines.
519 * Sets variables. Generates filename. Returns np_state_key. die with
520 * UNKNOWN if exception
521 */
522void np_enable_state(char *keyname, int expected_data_version) {
523 state_key *this_state = NULL;
524 char *temp_filename = NULL;
525 char *temp_keyname = NULL;
526 char *p = NULL;
527 int ret;
528
529 if (this_monitoring_plugin == NULL) {
530 die(STATE_UNKNOWN, _("This requires np_init to be called"));
531 }
532
533 this_state = (state_key *)calloc(1, sizeof(state_key));
534 if (this_state == NULL) {
535 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
536 }
537
538 if (keyname == NULL) {
539 temp_keyname = _np_state_generate_key();
540 } else {
541 temp_keyname = strdup(keyname);
542 if (temp_keyname == NULL) {
543 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
544 }
545 }
546 /* Die if invalid characters used for keyname */
547 p = temp_keyname;
548 while (*p != '\0') {
549 if (!(isalnum(*p) || *p == '_')) {
550 die(STATE_UNKNOWN, _("Invalid character for keyname - only alphanumerics or '_'"));
551 }
552 p++;
553 }
554 this_state->name = temp_keyname;
555 this_state->plugin_name = this_monitoring_plugin->plugin_name;
556 this_state->data_version = expected_data_version;
557 this_state->state_data = NULL;
558
559 /* Calculate filename */
560 ret = asprintf(&temp_filename, "%s/%lu/%s/%s", _np_state_calculate_location_prefix(), (unsigned long)geteuid(),
561 this_monitoring_plugin->plugin_name, this_state->name);
562 if (ret < 0) {
563 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
564 }
565
566 this_state->_filename = temp_filename;
567
568 this_monitoring_plugin->state = this_state;
569}
570
571/*
572 * Will return NULL if no data is available (first run). If key currently
573 * exists, read data. If state file format version is not expected, return
574 * as if no data. Get state data version number and compares to expected.
575 * If numerically lower, then return as no previous state. die with UNKNOWN
576 * if exceptional error.
577 */
578state_data *np_state_read(void) {
579 state_data *this_state_data = NULL;
580 FILE *statefile;
581 bool rc = false;
582
583 if (this_monitoring_plugin == NULL) {
584 die(STATE_UNKNOWN, _("This requires np_init to be called"));
585 }
586
587 /* Open file. If this fails, no previous state found */
588 statefile = fopen(this_monitoring_plugin->state->_filename, "r");
589 if (statefile != NULL) {
590
591 this_state_data = (state_data *)calloc(1, sizeof(state_data));
592 if (this_state_data == NULL) {
593 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
594 }
595
596 this_state_data->data = NULL;
597 this_monitoring_plugin->state->state_data = this_state_data;
598
599 rc = _np_state_read_file(statefile);
600
601 fclose(statefile);
602 }
603
604 if (!rc) {
605 _cleanup_state_data();
606 }
607
608 return this_monitoring_plugin->state->state_data;
609}
610
611/*
612 * Read the state file
613 */
614bool _np_state_read_file(FILE *f) {
615 bool status = false;
616 size_t pos;
617 char *line;
618 int i;
619 int failure = 0;
620 time_t current_time, data_time;
621 enum {
622 STATE_FILE_VERSION,
623 STATE_DATA_VERSION,
624 STATE_DATA_TIME,
625 STATE_DATA_TEXT,
626 STATE_DATA_END
627 } expected = STATE_FILE_VERSION;
628
629 time(&current_time);
630
631 /* Note: This introduces a limit of 1024 bytes in the string data */
632 line = (char *)calloc(1, 1024);
633 if (line == NULL) {
634 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
635 }
636
637 while (!failure && (fgets(line, 1024, f)) != NULL) {
638 pos = strlen(line);
639 if (line[pos - 1] == '\n') {
640 line[pos - 1] = '\0';
641 }
642
643 if (line[0] == '#') {
644 continue;
645 }
646
647 switch (expected) {
648 case STATE_FILE_VERSION:
649 i = atoi(line);
650 if (i != NP_STATE_FORMAT_VERSION) {
651 failure++;
652 } else {
653 expected = STATE_DATA_VERSION;
654 }
655 break;
656 case STATE_DATA_VERSION:
657 i = atoi(line);
658 if (i != this_monitoring_plugin->state->data_version) {
659 failure++;
660 } else {
661 expected = STATE_DATA_TIME;
662 }
663 break;
664 case STATE_DATA_TIME:
665 /* If time > now, error */
666 data_time = strtoul(line, NULL, 10);
667 if (data_time > current_time) {
668 failure++;
669 } else {
670 this_monitoring_plugin->state->state_data->time = data_time;
671 expected = STATE_DATA_TEXT;
672 }
673 break;
674 case STATE_DATA_TEXT:
675 this_monitoring_plugin->state->state_data->data = strdup(line);
676 if (this_monitoring_plugin->state->state_data->data == NULL) {
677 die(STATE_UNKNOWN, _("Cannot execute strdup: %s"), strerror(errno));
678 }
679 expected = STATE_DATA_END;
680 status = true;
681 break;
682 case STATE_DATA_END:;
683 }
684 }
685
686 np_free(line);
687 return status;
688}
689
690/*
691 * If time=NULL, use current time. Create state file, with state format
692 * version, default text. Writes version, time, and data. Avoid locking
693 * problems - use mv to write and then swap. Possible loss of state data if
694 * two things writing to same key at same time.
695 * Will die with UNKNOWN if errors
696 */
697void np_state_write_string(time_t data_time, char *data_string) {
698 FILE *fp;
699 char *temp_file = NULL;
700 int fd = 0, result = 0;
701 time_t current_time;
702 char *directories = NULL;
703 char *p = NULL;
704
705 if (data_time == 0) {
706 time(&current_time);
707 } else {
708 current_time = data_time;
709 }
710
711 /* If file doesn't currently exist, create directories */
712 if (access(this_monitoring_plugin->state->_filename, F_OK) != 0) {
713 result = asprintf(&directories, "%s", this_monitoring_plugin->state->_filename);
714 if (result < 0) {
715 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
716 }
717
718 for (p = directories + 1; *p; p++) {
719 if (*p == '/') {
720 *p = '\0';
721 if ((access(directories, F_OK) != 0) && (mkdir(directories, S_IRWXU) != 0)) {
722 /* Can't free this! Otherwise error message is wrong! */
723 /* np_free(directories); */
724 die(STATE_UNKNOWN, _("Cannot create directory: %s"), directories);
725 }
726 *p = '/';
727 }
728 }
729 np_free(directories);
730 }
731
732 result = asprintf(&temp_file, "%s.XXXXXX", this_monitoring_plugin->state->_filename);
733 if (result < 0) {
734 die(STATE_UNKNOWN, _("Cannot allocate memory: %s"), strerror(errno));
735 }
736
737 if ((fd = mkstemp(temp_file)) == -1) {
738 np_free(temp_file);
739 die(STATE_UNKNOWN, _("Cannot create temporary filename"));
740 }
741
742 fp = (FILE *)fdopen(fd, "w");
743 if (fp == NULL) {
744 close(fd);
745 unlink(temp_file);
746 np_free(temp_file);
747 die(STATE_UNKNOWN, _("Unable to open temporary state file"));
748 }
749
750 fprintf(fp, "# NP State file\n");
751 fprintf(fp, "%d\n", NP_STATE_FORMAT_VERSION);
752 fprintf(fp, "%d\n", this_monitoring_plugin->state->data_version);
753 fprintf(fp, "%lu\n", current_time);
754 fprintf(fp, "%s\n", data_string);
755
756 fchmod(fd, S_IRUSR | S_IWUSR | S_IRGRP);
757
758 fflush(fp);
759
760 result = fclose(fp);
761
762 fsync(fd);
763
764 if (result != 0) {
765 unlink(temp_file);
766 np_free(temp_file);
767 die(STATE_UNKNOWN, _("Error writing temp file"));
768 }
769
770 if (rename(temp_file, this_monitoring_plugin->state->_filename) != 0) {
771 unlink(temp_file);
772 np_free(temp_file);
773 die(STATE_UNKNOWN, _("Cannot rename state temp file"));
774 }
775
776 np_free(temp_file);
777}
diff --git a/lib/utils_base.h b/lib/utils_base.h
index 123066f8..27884bf0 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -7,7 +7,7 @@
7 7
8#include "./perfdata.h" 8#include "./perfdata.h"
9#include "./thresholds.h" 9#include "./thresholds.h"
10 10#include "states.h"
11 11
12#ifndef USE_OPENSSL 12#ifndef USE_OPENSSL
13# include "sha256.h" 13# include "sha256.h"
@@ -26,25 +26,8 @@
26#define OUTSIDE 0 26#define OUTSIDE 0
27#define INSIDE 1 27#define INSIDE 1
28 28
29#define NP_STATE_FORMAT_VERSION 1
30
31typedef struct state_data_struct {
32 time_t time;
33 void *data;
34 int length; /* Of binary data */
35} state_data;
36
37typedef struct state_key_struct {
38 char *name;
39 char *plugin_name;
40 int data_version;
41 char *_filename;
42 state_data *state_data;
43} state_key;
44
45typedef struct np_struct { 29typedef struct np_struct {
46 char *plugin_name; 30 char *plugin_name;
47 state_key *state;
48 int argc; 31 int argc;
49 char **argv; 32 char **argv;
50} monitoring_plugin; 33} monitoring_plugin;
@@ -55,10 +38,10 @@ void set_thresholds(thresholds **, char *, char *);
55void print_thresholds(const char *, thresholds *); 38void print_thresholds(const char *, thresholds *);
56bool check_range(double, range *); 39bool check_range(double, range *);
57bool mp_check_range(mp_perfdata_value, mp_range); 40bool mp_check_range(mp_perfdata_value, mp_range);
58int get_status(double, thresholds *); 41mp_state_enum get_status(double, thresholds *);
59 42
60/* Handle timeouts */ 43/* Handle timeouts */
61extern int timeout_state; 44extern mp_state_enum timeout_state;
62extern unsigned int timeout_interval; 45extern unsigned int timeout_interval;
63 46
64/* All possible characters in a threshold range */ 47/* All possible characters in a threshold range */
@@ -100,13 +83,9 @@ char *np_extract_value(const char *, const char *, char);
100 */ 83 */
101int mp_translate_state(char *); 84int mp_translate_state(char *);
102 85
103void np_enable_state(char *, int);
104state_data *np_state_read(void);
105void np_state_write_string(time_t, char *);
106
107void np_init(char *, int argc, char **argv); 86void np_init(char *, int argc, char **argv);
108void np_set_args(int argc, char **argv); 87void np_set_args(int argc, char **argv);
109void np_cleanup(void); 88void np_cleanup(void);
110const char *state_text(int); 89const char *state_text(mp_state_enum);
111 90
112#endif /* _UTILS_BASE_ */ 91#endif /* _UTILS_BASE_ */
diff --git a/lib/utils_cmd.c b/lib/utils_cmd.c
index 18350ac0..35b83297 100644
--- a/lib/utils_cmd.c
+++ b/lib/utils_cmd.c
@@ -40,7 +40,6 @@
40 40
41/** includes **/ 41/** includes **/
42#include "common.h" 42#include "common.h"
43#include "utils.h"
44#include "utils_cmd.h" 43#include "utils_cmd.h"
45/* This variable must be global, since there's no way the caller 44/* This variable must be global, since there's no way the caller
46 * can forcibly slay a dead or ungainly running program otherwise. 45 * can forcibly slay a dead or ungainly running program otherwise.
@@ -62,16 +61,13 @@ static pid_t *_cmd_pids = NULL;
62# include <sys/wait.h> 61# include <sys/wait.h>
63#endif 62#endif
64 63
65/* used in _cmd_open to pass the environment to commands */
66extern char **environ;
67
68/** macros **/ 64/** macros **/
69#ifndef WEXITSTATUS 65#ifndef WEXITSTATUS
70# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8) 66# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
71#endif 67#endif
72 68
73#ifndef WIFEXITED 69#ifndef WIFEXITED
74# define WIFEXITED(stat_val) (((stat_val)&255) == 0) 70# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
75#endif 71#endif
76 72
77/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 73/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
@@ -80,14 +76,12 @@ extern char **environ;
80#endif 76#endif
81 77
82/** prototypes **/ 78/** prototypes **/
83static int _cmd_open(char *const *, int *, int *) __attribute__((__nonnull__(1, 2, 3))); 79static int _cmd_open(char *const *argv, int *pfd, int *pfderr)
84 80 __attribute__((__nonnull__(1, 2, 3)));
85static int _cmd_fetch_output(int, output *, int) __attribute__((__nonnull__(2)));
86 81
87static int _cmd_close(int); 82static int _cmd_fetch_output(int fileDescriptor, output *cmd_output, int flags) __attribute__((__nonnull__(2)));
88 83
89/* prototype imported from utils.h */ 84static int _cmd_close(int fileDescriptor);
90extern void die(int, const char *, ...) __attribute__((__noreturn__, __format__(__printf__, 2, 3)));
91 85
92/* this function is NOT async-safe. It is exported so multithreaded 86/* this function is NOT async-safe. It is exported so multithreaded
93 * plugins (or other apps) can call it prior to running any commands 87 * plugins (or other apps) can call it prior to running any commands
@@ -103,26 +97,29 @@ void cmd_init(void) {
103 maxfd = MAXFD_LIMIT; 97 maxfd = MAXFD_LIMIT;
104 } 98 }
105 99
106 if (!_cmd_pids) 100 if (!_cmd_pids) {
107 _cmd_pids = calloc(maxfd, sizeof(pid_t)); 101 _cmd_pids = calloc(maxfd, sizeof(pid_t));
102 }
108} 103}
109 104
110/* Start running a command, array style */ 105/* Start running a command, array style */
111static int _cmd_open(char *const *argv, int *pfd, int *pfderr) { 106static int _cmd_open(char *const *argv, int *pfd, int *pfderr) {
112 pid_t pid;
113#ifdef RLIMIT_CORE 107#ifdef RLIMIT_CORE
114 struct rlimit limit; 108 struct rlimit limit;
115#endif 109#endif
116 110
117 int i = 0; 111 int i = 0;
118 112
119 if (!_cmd_pids) 113 if (!_cmd_pids) {
120 CMD_INIT; 114 CMD_INIT;
115 }
121 116
122 setenv("LC_ALL", "C", 1); 117 setenv("LC_ALL", "C", 1);
123 118
124 if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) 119 pid_t pid;
120 if (pipe(pfd) < 0 || pipe(pfderr) < 0 || (pid = fork()) < 0) {
125 return -1; /* errno set by the failing function */ 121 return -1; /* errno set by the failing function */
122 }
126 123
127 /* child runs exceve() and _exit. */ 124 /* child runs exceve() and _exit. */
128 if (pid == 0) { 125 if (pid == 0) {
@@ -147,9 +144,11 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) {
147 * This is executed in a separate address space (pure child), 144 * This is executed in a separate address space (pure child),
148 * so we don't have to worry about async safety */ 145 * so we don't have to worry about async safety */
149 long maxfd = mp_open_max(); 146 long maxfd = mp_open_max();
150 for (i = 0; i < maxfd; i++) 147 for (i = 0; i < maxfd; i++) {
151 if (_cmd_pids[i] > 0) 148 if (_cmd_pids[i] > 0) {
152 close(i); 149 close(i);
150 }
151 }
153 152
154 execve(argv[0], argv, environ); 153 execve(argv[0], argv, environ);
155 _exit(STATE_UNKNOWN); 154 _exit(STATE_UNKNOWN);
@@ -166,87 +165,94 @@ static int _cmd_open(char *const *argv, int *pfd, int *pfderr) {
166 return pfd[0]; 165 return pfd[0];
167} 166}
168 167
169static int _cmd_close(int fd) { 168static int _cmd_close(int fileDescriptor) {
170 int status;
171 pid_t pid; 169 pid_t pid;
172 170
173 /* make sure the provided fd was opened */ 171 /* make sure the provided fd was opened */
174 long maxfd = mp_open_max(); 172 long maxfd = mp_open_max();
175 if (fd < 0 || fd > maxfd || !_cmd_pids || (pid = _cmd_pids[fd]) == 0) 173 if (fileDescriptor < 0 || fileDescriptor > maxfd || !_cmd_pids ||
174 (pid = _cmd_pids[fileDescriptor]) == 0) {
176 return -1; 175 return -1;
176 }
177 177
178 _cmd_pids[fd] = 0; 178 _cmd_pids[fileDescriptor] = 0;
179 if (close(fd) == -1) 179 if (close(fileDescriptor) == -1) {
180 return -1; 180 return -1;
181 }
181 182
182 /* EINTR is ok (sort of), everything else is bad */ 183 /* EINTR is ok (sort of), everything else is bad */
183 while (waitpid(pid, &status, 0) < 0) 184 int status;
184 if (errno != EINTR) 185 while (waitpid(pid, &status, 0) < 0) {
186 if (errno != EINTR) {
185 return -1; 187 return -1;
188 }
189 }
186 190
187 /* return child's termination status */ 191 /* return child's termination status */
188 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1; 192 return (WIFEXITED(status)) ? WEXITSTATUS(status) : -1;
189} 193}
190 194
191static int _cmd_fetch_output(int fd, output *op, int flags) { 195static int _cmd_fetch_output(int fileDescriptor, output *cmd_output, int flags) {
192 size_t len = 0, i = 0, lineno = 0;
193 size_t rsf = 6, ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */
194 char *buf = NULL;
195 int ret;
196 char tmpbuf[4096]; 196 char tmpbuf[4096];
197 197 cmd_output->buf = NULL;
198 op->buf = NULL; 198 cmd_output->buflen = 0;
199 op->buflen = 0; 199 ssize_t ret;
200 while ((ret = read(fd, tmpbuf, sizeof(tmpbuf))) > 0) { 200 while ((ret = read(fileDescriptor, tmpbuf, sizeof(tmpbuf))) > 0) {
201 len = (size_t)ret; 201 size_t len = (size_t)ret;
202 op->buf = realloc(op->buf, op->buflen + len + 1); 202 cmd_output->buf = realloc(cmd_output->buf, cmd_output->buflen + len + 1);
203 memcpy(op->buf + op->buflen, tmpbuf, len); 203 memcpy(cmd_output->buf + cmd_output->buflen, tmpbuf, len);
204 op->buflen += len; 204 cmd_output->buflen += len;
205 i++;
206 } 205 }
207 206
208 if (ret < 0) { 207 if (ret < 0) {
209 printf("read() returned %d: %s\n", ret, strerror(errno)); 208 printf("read() returned %zd: %s\n", ret, strerror(errno));
210 return ret; 209 return ret;
211 } 210 }
212 211
213 /* some plugins may want to keep output unbroken, and some commands 212 /* some plugins may want to keep output unbroken, and some commands
214 * will yield no output, so return here for those */ 213 * will yield no output, so return here for those */
215 if (flags & CMD_NO_ARRAYS || !op->buf || !op->buflen) 214 if (flags & CMD_NO_ARRAYS || !cmd_output->buf || !cmd_output->buflen) {
216 return op->buflen; 215 return cmd_output->buflen;
216 }
217 217
218 /* and some may want both */ 218 /* and some may want both */
219 char *buf = NULL;
219 if (flags & CMD_NO_ASSOC) { 220 if (flags & CMD_NO_ASSOC) {
220 buf = malloc(op->buflen); 221 buf = malloc(cmd_output->buflen);
221 memcpy(buf, op->buf, op->buflen); 222 memcpy(buf, cmd_output->buf, cmd_output->buflen);
222 } else 223 } else {
223 buf = op->buf; 224 buf = cmd_output->buf;
224 225 }
225 op->line = NULL; 226
226 op->lens = NULL; 227 cmd_output->line = NULL;
227 i = 0; 228 cmd_output->lens = NULL;
228 while (i < op->buflen) { 229 size_t i = 0;
230 size_t ary_size = 0; /* rsf = right shift factor, dec'ed uncond once */
231 size_t rsf = 6;
232 size_t lineno = 0;
233 while (i < cmd_output->buflen) {
229 /* make sure we have enough memory */ 234 /* make sure we have enough memory */
230 if (lineno >= ary_size) { 235 if (lineno >= ary_size) {
231 /* ary_size must never be zero */ 236 /* ary_size must never be zero */
232 do { 237 do {
233 ary_size = op->buflen >> --rsf; 238 ary_size = cmd_output->buflen >> --rsf;
234 } while (!ary_size); 239 } while (!ary_size);
235 240
236 op->line = realloc(op->line, ary_size * sizeof(char *)); 241 cmd_output->line = realloc(cmd_output->line, ary_size * sizeof(char *));
237 op->lens = realloc(op->lens, ary_size * sizeof(size_t)); 242 cmd_output->lens = realloc(cmd_output->lens, ary_size * sizeof(size_t));
238 } 243 }
239 244
240 /* set the pointer to the string */ 245 /* set the pointer to the string */
241 op->line[lineno] = &buf[i]; 246 cmd_output->line[lineno] = &buf[i];
242 247
243 /* hop to next newline or end of buffer */ 248 /* hop to next newline or end of buffer */
244 while (buf[i] != '\n' && i < op->buflen) 249 while (buf[i] != '\n' && i < cmd_output->buflen) {
245 i++; 250 i++;
251 }
246 buf[i] = '\0'; 252 buf[i] = '\0';
247 253
248 /* calculate the string length using pointer difference */ 254 /* calculate the string length using pointer difference */
249 op->lens[lineno] = (size_t)&buf[i] - (size_t)op->line[lineno]; 255 cmd_output->lens[lineno] = (size_t)&buf[i] - (size_t)cmd_output->line[lineno];
250 256
251 lineno++; 257 lineno++;
252 i++; 258 i++;
@@ -256,41 +262,42 @@ static int _cmd_fetch_output(int fd, output *op, int flags) {
256} 262}
257 263
258int cmd_run(const char *cmdstring, output *out, output *err, int flags) { 264int cmd_run(const char *cmdstring, output *out, output *err, int flags) {
259 int i = 0, argc; 265 if (cmdstring == NULL) {
260 size_t cmdlen;
261 char **argv = NULL;
262 char *cmd = NULL;
263 char *str = NULL;
264
265 if (cmdstring == NULL)
266 return -1; 266 return -1;
267 }
267 268
268 /* initialize the structs */ 269 /* initialize the structs */
269 if (out) 270 if (out) {
270 memset(out, 0, sizeof(output)); 271 memset(out, 0, sizeof(output));
271 if (err) 272 }
273 if (err) {
272 memset(err, 0, sizeof(output)); 274 memset(err, 0, sizeof(output));
275 }
273 276
274 /* make copy of command string so strtok() doesn't silently modify it */ 277 /* make copy of command string so strtok() doesn't silently modify it */
275 /* (the calling program may want to access it later) */ 278 /* (the calling program may want to access it later) */
276 cmdlen = strlen(cmdstring); 279 size_t cmdlen = strlen(cmdstring);
277 if ((cmd = malloc(cmdlen + 1)) == NULL) 280 char *cmd = NULL;
281 if ((cmd = malloc(cmdlen + 1)) == NULL) {
278 return -1; 282 return -1;
283 }
279 memcpy(cmd, cmdstring, cmdlen); 284 memcpy(cmd, cmdstring, cmdlen);
280 cmd[cmdlen] = '\0'; 285 cmd[cmdlen] = '\0';
281 286
282 /* This is not a shell, so we don't handle "???" */ 287 /* This is not a shell, so we don't handle "???" */
283 if (strstr(cmdstring, "\"")) 288 if (strstr(cmdstring, "\"")) {
284 return -1; 289 return -1;
290 }
285 291
286 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 292 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
287 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) 293 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) {
288 return -1; 294 return -1;
295 }
289 296
290 /* each arg must be whitespace-separated, so args can be a maximum 297 /* each arg must be whitespace-separated, so args can be a maximum
291 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */ 298 * of (len / 2) + 1. We add 1 extra to the mix for NULL termination */
292 argc = (cmdlen >> 1) + 2; 299 int argc = (cmdlen >> 1) + 2;
293 argv = calloc((size_t)argc, sizeof(char *)); 300 char **argv = calloc((size_t)argc, sizeof(char *));
294 301
295 if (argv == NULL) { 302 if (argv == NULL) {
296 printf("%s\n", _("Could not malloc argv array in popen()")); 303 printf("%s\n", _("Could not malloc argv array in popen()"));
@@ -298,14 +305,16 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) {
298 } 305 }
299 306
300 /* get command arguments (stupidly, but fairly quickly) */ 307 /* get command arguments (stupidly, but fairly quickly) */
308 int i = 0;
301 while (cmd) { 309 while (cmd) {
302 str = cmd; 310 char *str = cmd;
303 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */ 311 str += strspn(str, " \t\r\n"); /* trim any leading whitespace */
304 312
305 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */ 313 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
306 str++; 314 str++;
307 if (!strstr(str, "'")) 315 if (!strstr(str, "'")) {
308 return -1; /* balanced? */ 316 return -1; /* balanced? */
317 }
309 cmd = 1 + strstr(str, "'"); 318 cmd = 1 + strstr(str, "'");
310 str[strcspn(str, "'")] = 0; 319 str[strcspn(str, "'")] = 0;
311 } else { 320 } else {
@@ -317,8 +326,9 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) {
317 } 326 }
318 } 327 }
319 328
320 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) 329 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) {
321 cmd = NULL; 330 cmd = NULL;
331 }
322 332
323 argv[i++] = str; 333 argv[i++] = str;
324 } 334 }
@@ -327,53 +337,65 @@ int cmd_run(const char *cmdstring, output *out, output *err, int flags) {
327} 337}
328 338
329int cmd_run_array(char *const *argv, output *out, output *err, int flags) { 339int cmd_run_array(char *const *argv, output *out, output *err, int flags) {
330 int fd, pfd_out[2], pfd_err[2];
331
332 /* initialize the structs */ 340 /* initialize the structs */
333 if (out) 341 if (out) {
334 memset(out, 0, sizeof(output)); 342 memset(out, 0, sizeof(output));
335 if (err) 343 }
344 if (err) {
336 memset(err, 0, sizeof(output)); 345 memset(err, 0, sizeof(output));
346 }
337 347
338 if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) 348 int fd;
349 int pfd_out[2];
350 int pfd_err[2];
351 if ((fd = _cmd_open(argv, pfd_out, pfd_err)) == -1) {
339 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]); 352 die(STATE_UNKNOWN, _("Could not open pipe: %s\n"), argv[0]);
353 }
340 354
341 if (out) 355 if (out) {
342 out->lines = _cmd_fetch_output(pfd_out[0], out, flags); 356 out->lines = _cmd_fetch_output(pfd_out[0], out, flags);
343 if (err) 357 }
358 if (err) {
344 err->lines = _cmd_fetch_output(pfd_err[0], err, flags); 359 err->lines = _cmd_fetch_output(pfd_err[0], err, flags);
360 }
345 361
346 return _cmd_close(fd); 362 return _cmd_close(fd);
347} 363}
348 364
349int cmd_file_read(char *filename, output *out, int flags) { 365int cmd_file_read(const char *filename, output *out, int flags) {
350 int fd; 366 int fd;
351 if (out) 367 if (out) {
352 memset(out, 0, sizeof(output)); 368 memset(out, 0, sizeof(output));
369 }
353 370
354 if ((fd = open(filename, O_RDONLY)) == -1) { 371 if ((fd = open(filename, O_RDONLY)) == -1) {
355 die(STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno)); 372 die(STATE_UNKNOWN, _("Error opening %s: %s"), filename, strerror(errno));
356 } 373 }
357 374
358 if (out) 375 if (out) {
359 out->lines = _cmd_fetch_output(fd, out, flags); 376 out->lines = _cmd_fetch_output(fd, out, flags);
377 }
360 378
361 if (close(fd) == -1) 379 if (close(fd) == -1) {
362 die(STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno)); 380 die(STATE_UNKNOWN, _("Error closing %s: %s"), filename, strerror(errno));
381 }
363 382
364 return 0; 383 return 0;
365} 384}
366 385
367void timeout_alarm_handler(int signo) { 386void timeout_alarm_handler(int signo) {
368 if (signo == SIGALRM) { 387 if (signo == SIGALRM) {
369 printf(_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state), timeout_interval); 388 printf(_("%s - Plugin timed out after %d seconds\n"), state_text(timeout_state),
389 timeout_interval);
370 390
371 long maxfd = mp_open_max(); 391 long maxfd = mp_open_max();
372 if (_cmd_pids) 392 if (_cmd_pids) {
373 for (long int i = 0; i < maxfd; i++) { 393 for (long int i = 0; i < maxfd; i++) {
374 if (_cmd_pids[i] != 0) 394 if (_cmd_pids[i] != 0) {
375 kill(_cmd_pids[i], SIGKILL); 395 kill(_cmd_pids[i], SIGKILL);
396 }
376 } 397 }
398 }
377 399
378 exit(timeout_state); 400 exit(timeout_state);
379 } 401 }
diff --git a/lib/utils_cmd.h b/lib/utils_cmd.h
index d00069c9..3672cdc9 100644
--- a/lib/utils_cmd.h
+++ b/lib/utils_cmd.h
@@ -5,22 +5,22 @@
5 * Header file for Monitoring Plugins utils_cmd.c 5 * Header file for Monitoring Plugins utils_cmd.c
6 * 6 *
7 */ 7 */
8#include "../config.h"
9#include <stddef.h>
8 10
9/** types **/ 11/** types **/
10struct output { 12typedef struct {
11 char *buf; /* output buffer */ 13 char *buf; /* output buffer */
12 size_t buflen; /* output buffer content length */ 14 size_t buflen; /* output buffer content length */
13 char **line; /* array of lines (points to buf) */ 15 char **line; /* array of lines (points to buf) */
14 size_t *lens; /* string lengths */ 16 size_t *lens; /* string lengths */
15 size_t lines; /* lines of output */ 17 size_t lines; /* lines of output */
16}; 18} output;
17
18typedef struct output output;
19 19
20/** prototypes **/ 20/** prototypes **/
21int cmd_run(const char *, output *, output *, int); 21int cmd_run(const char *, output *, output *, int);
22int cmd_run_array(char *const *, output *, output *, int); 22int cmd_run_array(char *const *, output *, output *, int);
23int cmd_file_read(char *, output *, int); 23int cmd_file_read(const char *, output *, int);
24 24
25/* only multi-threaded plugins need to bother with this */ 25/* only multi-threaded plugins need to bother with this */
26void cmd_init(void); 26void cmd_init(void);
diff --git a/lib/utils_tcp.c b/lib/utils_tcp.c
index daae1d54..a82d5a3f 100644
--- a/lib/utils_tcp.c
+++ b/lib/utils_tcp.c
@@ -26,28 +26,35 @@
26 * 26 *
27 *****************************************************************************/ 27 *****************************************************************************/
28 28
29#include "common.h" 29#include "../config.h"
30#include "utils_tcp.h" 30#include "utils_tcp.h"
31#include <stdio.h>
32#include <string.h>
31 33
32#define VERBOSE(message) \ 34#define VERBOSE(message) \
33 do { \ 35 do { \
34 if (flags & NP_MATCH_VERBOSE) \ 36 if (flags & NP_MATCH_VERBOSE) \
35 puts(message); \ 37 puts(message); \
36 } while (0) 38 } while (0)
37 39
38enum np_match_result np_expect_match(char *status, char **server_expect, int expect_count, int flags) { 40enum np_match_result np_expect_match(char *status, char **server_expect, int expect_count,
39 int i, match = 0, partial = 0; 41 int flags) {
40 42 int match = 0;
41 for (i = 0; i < expect_count; i++) { 43 int partial = 0;
42 if (flags & NP_MATCH_VERBOSE) 44 for (int i = 0; i < expect_count; i++) {
43 printf("looking for [%s] %s [%s]\n", server_expect[i], (flags & NP_MATCH_EXACT) ? "in beginning of" : "anywhere in", status); 45 if (flags & NP_MATCH_VERBOSE) {
46 printf("looking for [%s] %s [%s]\n", server_expect[i],
47 (flags & NP_MATCH_EXACT) ? "in beginning of" : "anywhere in", status);
48 }
44 49
45 if (flags & NP_MATCH_EXACT) { 50 if (flags & NP_MATCH_EXACT) {
46 if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) { 51 if (strncmp(status, server_expect[i], strlen(server_expect[i])) == 0) {
47 VERBOSE("found it"); 52 VERBOSE("found it");
48 match++; 53 match++;
49 continue; 54 continue;
50 } else if (strncmp(status, server_expect[i], strlen(status)) == 0) { 55 }
56
57 if (strncmp(status, server_expect[i], strlen(status)) == 0) {
51 VERBOSE("found a substring"); 58 VERBOSE("found a substring");
52 partial++; 59 partial++;
53 continue; 60 continue;
@@ -60,10 +67,12 @@ enum np_match_result np_expect_match(char *status, char **server_expect, int exp
60 VERBOSE("couldn't find it"); 67 VERBOSE("couldn't find it");
61 } 68 }
62 69
63 if ((flags & NP_MATCH_ALL && match == expect_count) || (!(flags & NP_MATCH_ALL) && match >= 1)) 70 if ((flags & NP_MATCH_ALL && match == expect_count) ||
71 (!(flags & NP_MATCH_ALL) && match >= 1)) {
64 return NP_MATCH_SUCCESS; 72 return NP_MATCH_SUCCESS;
65 else if (partial > 0 || !(flags & NP_MATCH_EXACT)) 73 }
74 if (partial > 0 || !(flags & NP_MATCH_EXACT)) {
66 return NP_MATCH_RETRY; 75 return NP_MATCH_RETRY;
67 else 76 }
68 return NP_MATCH_FAILURE; 77 return NP_MATCH_FAILURE;
69} 78}
diff --git a/lib/utils_tcp.h b/lib/utils_tcp.h
index a7d83c59..e5cdbb82 100644
--- a/lib/utils_tcp.h
+++ b/lib/utils_tcp.h
@@ -17,4 +17,5 @@ enum np_match_result {
17 NP_MATCH_RETRY 17 NP_MATCH_RETRY
18}; 18};
19 19
20enum np_match_result np_expect_match(char *status, char **server_expect, int server_expect_count, int flags); 20enum np_match_result np_expect_match(char *status, char **server_expect, int server_expect_count,
21 int flags);