diff options
Diffstat (limited to 'lib/output.c')
| -rw-r--r-- | lib/output.c | 161 |
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 |
| 15 | static mp_output_format output_format = MP_FORMAT_DEFAULT; | 15 | static mp_output_format output_format = MP_FORMAT_DEFAULT; |
| 16 | static mp_output_detail_level level_of_detail = MP_DETAIL_ALL; | ||
| 16 | 17 | ||
| 17 | // == Prototypes == | 18 | // == Prototypes == |
| 18 | static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation); | 19 | static char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, |
| 20 | unsigned int indentation); | ||
| 19 | static inline cJSON *json_serialize_subcheck(mp_subcheck subcheck); | 21 | static 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 | */ |
| 59 | mp_check mp_check_init(void) { | 61 | mp_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 | */ |
| 121 | int mp_add_subcheck_to_subcheck(mp_subcheck check[static 1], mp_subcheck subcheck) { | 127 | int 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 | |||
| 160 | void mp_add_summary(mp_check check[static 1], char *summary) { check->summary = summary; } | 167 | void 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 | */ |
| 165 | char *get_subcheck_summary(mp_check check) { | 172 | char *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 | ||
| 203 | mp_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 | */ |
| 199 | mp_state_enum mp_compute_subcheck_state(const mp_subcheck check) { | 214 | mp_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 | ||
| 239 | mp_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 | */ |
| 218 | mp_state_enum mp_compute_check_state(const mp_check check) { | 250 | mp_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 | ||
| 265 | char *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 | */ |
| 330 | static inline char *fmt_subcheck_output(mp_output_format output_format, mp_subcheck check, unsigned int indentation) { | 389 | static 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) { | |||
| 539 | void mp_set_format(mp_output_format format) { output_format = format; } | 634 | void mp_set_format(mp_output_format format) { output_format = format; } |
| 540 | 635 | ||
| 541 | mp_output_format mp_get_format(void) { return output_format; } | 636 | mp_output_format mp_get_format(void) { return output_format; } |
| 637 | |||
| 638 | void mp_set_level_of_detail(mp_output_detail_level level) { level_of_detail = level; } | ||
| 639 | |||
| 640 | mp_output_detail_level mp_get_level_of_detail(void) { return level_of_detail; } | ||
| 641 | |||
| 642 | mp_state_enum mp_eval_ok(mp_check overall) { | ||
| 643 | (void)overall; | ||
| 644 | return STATE_OK; | ||
| 645 | } | ||
| 646 | |||
| 647 | mp_state_enum mp_eval_warning(mp_check overall) { | ||
| 648 | (void)overall; | ||
| 649 | return STATE_WARNING; | ||
| 650 | } | ||
| 651 | |||
| 652 | mp_state_enum mp_eval_critical(mp_check overall) { | ||
| 653 | (void)overall; | ||
| 654 | return STATE_CRITICAL; | ||
| 655 | } | ||
| 656 | |||
| 657 | mp_state_enum mp_eval_unknown(mp_check overall) { | ||
| 658 | (void)overall; | ||
| 659 | return STATE_UNKNOWN; | ||
| 660 | } | ||
