summaryrefslogtreecommitdiffstats
path: root/lib/output.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/output.c')
-rw-r--r--lib/output.c161
1 files changed, 140 insertions, 21 deletions
diff --git a/lib/output.c b/lib/output.c
index 61fbf832..3c04d63d 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -13,9 +13,11 @@
13 13
14// == Global variables 14// == Global variables
15static mp_output_format output_format = MP_FORMAT_DEFAULT; 15static mp_output_format output_format = MP_FORMAT_DEFAULT;
16static mp_output_detail_level level_of_detail = MP_DETAIL_ALL;
16 17
17// == Prototypes == 18// == Prototypes ==
18static 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);
19static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); 21static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck);
20 22
21// == Implementation == 23// == Implementation ==
@@ -40,7 +42,7 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
40 42
41 while (subchecks != NULL) { 43 while (subchecks != NULL) {
42 if (added > 0) { 44 if (added > 0) {
43 added = asprintf(&result, "%s%s", result, fmt_subcheck_perfdata(subchecks->subcheck)); 45 added = asprintf(&result, "%s %s", result, fmt_subcheck_perfdata(subchecks->subcheck));
44 } else { 46 } else {
45 // TODO free previous result here? 47 // TODO free previous result here?
46 added = asprintf(&result, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); 48 added = asprintf(&result, "%s", fmt_subcheck_perfdata(subchecks->subcheck));
@@ -57,7 +59,11 @@ static inline char *fmt_subcheck_perfdata(mp_subcheck check) {
57 * It sets useful defaults 59 * It sets useful defaults
58 */ 60 */
59mp_check mp_check_init(void) { 61mp_check mp_check_init(void) {
60 mp_check check = {0}; 62 mp_check check = {
63 .evaluation_function = &mp_eval_check_default,
64 .default_output_override = NULL,
65 .default_output_override_content = NULL,
66 };
61 return check; 67 return check;
62} 68}
63 69
@@ -120,7 +126,8 @@ void mp_add_perfdata_to_subcheck(mp_subcheck check[static 1], const mp_perfdata
120 */ 126 */
121int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { 127int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) {
122 if (subcheck.output == NULL) { 128 if (subcheck.output == NULL) {
123 die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__, "Sub check output is NULL"); 129 die(STATE_UNKNOWN, "%s - %s #%d: %s", __FILE__, __func__, __LINE__,
130 "Sub check output is NULL");
124 } 131 }
125 132
126 mp_subcheck_list *tmp = NULL; 133 mp_subcheck_list *tmp = NULL;
@@ -160,7 +167,7 @@ int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subchec
160void mp_add_summary(mp_check check[static 1], char *summary) { check->summary = summary; } 167void mp_add_summary(mp_check check[static 1], char *summary) { check->summary = summary; }
161 168
162/* 169/*
163 * Generate the summary string of a mp_check object based on it's subchecks 170 * Generate the summary string of a mp_check object based on its subchecks
164 */ 171 */
165char *get_subcheck_summary(mp_check check) { 172char *get_subcheck_summary(mp_check check) {
166 mp_subcheck_list *subchecks = check.subchecks; 173 mp_subcheck_list *subchecks = check.subchecks;
@@ -170,7 +177,7 @@ char *get_subcheck_summary(mp_check check) {
170 unsigned int critical = 0; 177 unsigned int critical = 0;
171 unsigned int unknown = 0; 178 unsigned int unknown = 0;
172 while (subchecks != NULL) { 179 while (subchecks != NULL) {
173 switch (subchecks->subcheck.state) { 180 switch (mp_compute_subcheck_state(subchecks->subcheck)) {
174 case STATE_OK: 181 case STATE_OK:
175 ok++; 182 ok++;
176 break; 183 break;
@@ -193,16 +200,33 @@ char *get_subcheck_summary(mp_check check) {
193 return result; 200 return result;
194} 201}
195 202
203mp_state_enum mp_compute_subcheck_state(const mp_subcheck subcheck) {
204 if (subcheck.evaluation_function == NULL) {
205 return mp_eval_subcheck_default(subcheck);
206 }
207 return subcheck.evaluation_function(subcheck);
208}
209
196/* 210/*
197 * Generate the result state of a mp_subcheck object based on it's own state and it's subchecks states 211 * Generate the result state of a mp_subcheck object based on its own state and its subchecks
212 * states
198 */ 213 */
199mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { 214mp_state_enum mp_eval_subcheck_default(mp_subcheck subcheck) {
200 if (check.state_set_explicitly) { 215 if (subcheck.evaluation_function != NULL) {
201 return check.state; 216 return subcheck.evaluation_function(subcheck);
202 } 217 }
203 218
204 mp_subcheck_list *scl = check.subchecks; 219 if (subcheck.state_set_explicitly) {
205 mp_state_enum result = check.default_state; 220 return subcheck.state;
221 }
222
223 mp_subcheck_list *scl = subcheck.subchecks;
224
225 if (scl == NULL) {
226 return subcheck.default_state;
227 }
228
229 mp_state_enum result = STATE_OK;
206 230
207 while (scl != NULL) { 231 while (scl != NULL) {
208 result = max_state_alt(result, mp_compute_subcheck_state(scl->subcheck)); 232 result = max_state_alt(result, mp_compute_subcheck_state(scl->subcheck));
@@ -212,10 +236,18 @@ mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) {
212 return result; 236 return result;
213} 237}
214 238
239mp_state_enum mp_compute_check_state(const mp_check check) {
240 // just a safety check
241 if (check.evaluation_function == NULL) {
242 return mp_eval_check_default(check);
243 }
244 return check.evaluation_function(check);
245}
246
215/* 247/*
216 * Generate the result state of a mp_check object based on it's own state and it's subchecks states 248 * Generate the result state of a mp_check object based on its own state and its subchecks states
217 */ 249 */
218mp_state_enum mp_compute_check_state(const mp_check check) { 250mp_state_enum mp_eval_check_default(const mp_check check) {
219 assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here 251 assert(check.subchecks != NULL); // a mp_check without subchecks is invalid, die here
220 252
221 mp_subcheck_list *scl = check.subchecks; 253 mp_subcheck_list *scl = check.subchecks;
@@ -229,6 +261,21 @@ mp_state_enum mp_compute_check_state(const mp_check check) {
229 return result; 261 return result;
230} 262}
231 263
264// Remove troublesome symbols from plugin output
265char *sanitize_output_insitu(char *input) {
266 if (input == NULL) {
267 return input;
268 }
269
270 for (char *walker = input; *walker != '\0'; walker++) {
271 if (*walker == '|') {
272 *walker = ' ';
273 }
274 }
275
276 return input;
277}
278
232/* 279/*
233 * Generate output string for a mp_check object 280 * Generate output string for a mp_check object
234 * Non static to be available for testing functions 281 * Non static to be available for testing functions
@@ -238,6 +285,11 @@ char *mp_fmt_output(mp_check check) {
238 285
239 switch (output_format) { 286 switch (output_format) {
240 case MP_FORMAT_MULTI_LINE: { 287 case MP_FORMAT_MULTI_LINE: {
288 if (check.default_output_override != NULL) {
289 result = check.default_output_override(check.default_output_override_content);
290 break;
291 }
292
241 if (check.summary == NULL) { 293 if (check.summary == NULL) {
242 check.summary = get_subcheck_summary(check); 294 check.summary = get_subcheck_summary(check);
243 } 295 }
@@ -247,7 +299,11 @@ char *mp_fmt_output(mp_check check) {
247 mp_subcheck_list *subchecks = check.subchecks; 299 mp_subcheck_list *subchecks = check.subchecks;
248 300
249 while (subchecks != NULL) { 301 while (subchecks != NULL) {
250 asprintf(&result, "%s\n%s", result, fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1)); 302 if (level_of_detail == MP_DETAIL_ALL ||
303 mp_compute_subcheck_state(subchecks->subcheck) != STATE_OK) {
304 asprintf(&result, "%s\n%s", result,
305 fmt_subcheck_output(MP_FORMAT_MULTI_LINE, subchecks->subcheck, 1));
306 }
251 subchecks = subchecks->next; 307 subchecks = subchecks->next;
252 } 308 }
253 309
@@ -258,12 +314,15 @@ char *mp_fmt_output(mp_check check) {
258 if (pd_string == NULL) { 314 if (pd_string == NULL) {
259 asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck)); 315 asprintf(&pd_string, "%s", fmt_subcheck_perfdata(subchecks->subcheck));
260 } else { 316 } else {
261 asprintf(&pd_string, "%s %s", pd_string, fmt_subcheck_perfdata(subchecks->subcheck)); 317 asprintf(&pd_string, "%s %s", pd_string,
318 fmt_subcheck_perfdata(subchecks->subcheck));
262 } 319 }
263 320
264 subchecks = subchecks->next; 321 subchecks = subchecks->next;
265 } 322 }
266 323
324 result = sanitize_output_insitu(result);
325
267 if (pd_string != NULL && strlen(pd_string) > 0) { 326 if (pd_string != NULL && strlen(pd_string) > 0) {
268 asprintf(&result, "%s|%s", result, pd_string); 327 asprintf(&result, "%s|%s", result, pd_string);
269 } 328 }
@@ -327,22 +386,58 @@ static char *generate_indentation_string(unsigned int indentation) {
327/* 386/*
328 * Helper function to generate the output string of mp_subcheck 387 * Helper function to generate the output string of mp_subcheck
329 */ 388 */
330static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) { 389static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check,
390 unsigned int indentation) {
331 char *result = NULL; 391 char *result = NULL;
332 mp_subcheck_list *subchecks = NULL; 392 mp_subcheck_list *subchecks = NULL;
333 393
334 switch (output_format) { 394 switch (output_format) {
335 case MP_FORMAT_MULTI_LINE: 395 case MP_FORMAT_MULTI_LINE: {
336 asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation), state_text(mp_compute_subcheck_state(check)), 396 char *tmp_string = NULL;
337 check.output); 397 if ((tmp_string = strchr(check.output, '\n')) != NULL) {
398 // This is a multiline string, put the correct indentation in before proceeding
399 char *intermediate_string = "";
400 bool have_residual_chars = false;
401
402 while (tmp_string != NULL) {
403 *tmp_string = '\0';
404 asprintf(&intermediate_string, "%s%s\n%s", intermediate_string, check.output,
405 generate_indentation_string(
406 indentation + 1)); // one more indentation to make it look better
407
408 if (*(tmp_string + 1) != '\0') {
409 check.output = tmp_string + 1;
410 have_residual_chars = true;
411 } else {
412 // Null after the \n, so this is the end
413 have_residual_chars = false;
414 break;
415 }
416
417 tmp_string = strchr(check.output, '\n');
418 }
419
420 // add the rest (if any)
421 if (have_residual_chars) {
422 char *tmp = check.output;
423 xasprintf(&check.output, "%s%s%s", intermediate_string,
424 generate_indentation_string(indentation + 1), tmp);
425 } else {
426 check.output = intermediate_string;
427 }
428 }
429 asprintf(&result, "%s\\_[%s] - %s", generate_indentation_string(indentation),
430 state_text(mp_compute_subcheck_state(check)), check.output);
338 431
339 subchecks = check.subchecks; 432 subchecks = check.subchecks;
340 433
341 while (subchecks != NULL) { 434 while (subchecks != NULL) {
342 asprintf(&result, "%s\n%s", result, fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1)); 435 asprintf(&result, "%s\n%s", result,
436 fmt_subcheck_output(output_format, subchecks->subcheck, indentation + 1));
343 subchecks = subchecks->next; 437 subchecks = subchecks->next;
344 } 438 }
345 return result; 439 return result;
440 }
346 default: 441 default:
347 die(STATE_UNKNOWN, "Invalid format"); 442 die(STATE_UNKNOWN, "Invalid format");
348 } 443 }
@@ -539,3 +634,27 @@ parsed_output_format mp_parse_output_format(char *format_string) {
539void mp_set_format(mp_output_format format) { output_format = format; } 634void mp_set_format(mp_output_format format) { output_format = format; }
540 635
541mp_output_format mp_get_format(void) { return output_format; } 636mp_output_format mp_get_format(void) { return output_format; }
637
638void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; }
639
640mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; }
641
642mp_state_enum mp_eval_ok(mp_check overall) {
643 (void)overall;
644 return STATE_OK;
645}
646
647mp_state_enum mp_eval_warning(mp_check overall) {
648 (void)overall;
649 return STATE_WARNING;
650}
651
652mp_state_enum mp_eval_critical(mp_check overall) {
653 (void)overall;
654 return STATE_CRITICAL;
655}
656
657mp_state_enum mp_eval_unknown(mp_check overall) {
658 (void)overall;
659 return STATE_UNKNOWN;
660}