diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/utils_base.c | 205 | ||||
| -rw-r--r-- | lib/utils_base.h | 20 |
2 files changed, 225 insertions, 0 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c index 77700f5b..ba4f83b8 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c | |||
| @@ -24,10 +24,151 @@ | |||
| 24 | * | 24 | * |
| 25 | *****************************************************************************/ | 25 | *****************************************************************************/ |
| 26 | 26 | ||
| 27 | #if HAVE_LIBGEN_H | ||
| 28 | #include <libgen.h> /* basename(3) */ | ||
| 29 | #endif | ||
| 30 | #include <stdarg.h> | ||
| 27 | #include "common.h" | 31 | #include "common.h" |
| 28 | #include <stdarg.h> | 32 | #include <stdarg.h> |
| 29 | #include "utils_base.h" | 33 | #include "utils_base.h" |
| 30 | 34 | ||
| 35 | #define PRINT_OUTPUT(fmt, ap) \ | ||
| 36 | do { \ | ||
| 37 | fmt = insert_syserr(fmt); \ | ||
| 38 | va_start(ap, fmt); \ | ||
| 39 | vprintf(fmt, ap); \ | ||
| 40 | va_end(ap); \ | ||
| 41 | } while (/* CONSTCOND */ 0) | ||
| 42 | |||
| 43 | static char *insert_syserr(const char *); | ||
| 44 | |||
| 45 | extern int errno; | ||
| 46 | static int verbosity_level = -2; | ||
| 47 | static const char *program_name = NULL; | ||
| 48 | static const char *service_name = NULL; | ||
| 49 | |||
| 50 | /* | ||
| 51 | * Set static variables for use in output functions. Usually, argv[0] may be | ||
| 52 | * used as progname, since we call basename(3) ourselves. If a verbosity value | ||
| 53 | * of -2 is specified, the verbosity_level won't be set. Currently, no flags | ||
| 54 | * are implemented. | ||
| 55 | */ | ||
| 56 | void | ||
| 57 | np_set_output(const char *progname, const char *servname, int verbosity, | ||
| 58 | int flags __attribute__((unused))) | ||
| 59 | { | ||
| 60 | static char pathbuf[128], progbuf[128], servbuf[32]; | ||
| 61 | |||
| 62 | if (progname != NULL) { | ||
| 63 | #if HAVE_BASENAME | ||
| 64 | /* | ||
| 65 | * Copy the progname into a temporary buffer in order to cope | ||
| 66 | * with basename(3) implementations which modify their argument. | ||
| 67 | * TODO: Maybe we should implement an np_basename()? Gnulib's | ||
| 68 | * base_name() dies on error, writing a message to stderr, which | ||
| 69 | * is probably not what we want. Once we have some replacement, | ||
| 70 | * the libgen-/basename(3)-related checks can be removed from | ||
| 71 | * configure.in. | ||
| 72 | */ | ||
| 73 | strncpy(pathbuf, progname, sizeof(pathbuf) - 1); | ||
| 74 | pathbuf[sizeof(pathbuf) - 1] = '\0'; | ||
| 75 | progname = basename(pathbuf); | ||
| 76 | #endif | ||
| 77 | strncpy(progbuf, progname, sizeof(progbuf) - 1); | ||
| 78 | progbuf[sizeof(progbuf) - 1] = '\0'; | ||
| 79 | program_name = progbuf; | ||
| 80 | } | ||
| 81 | if (servname != NULL) { | ||
| 82 | strncpy(servbuf, servname, sizeof(servbuf) - 1); | ||
| 83 | servbuf[sizeof(servbuf) - 1] = '\0'; | ||
| 84 | service_name = servbuf; | ||
| 85 | } | ||
| 86 | if (verbosity != -2) | ||
| 87 | verbosity_level = verbosity; | ||
| 88 | } | ||
| 89 | |||
| 90 | int | ||
| 91 | np_adjust_verbosity(int by) | ||
| 92 | { | ||
| 93 | if (verbosity_level == -2) | ||
| 94 | verbosity_level = by; | ||
| 95 | else | ||
| 96 | verbosity_level += by; | ||
| 97 | |||
| 98 | /* We don't support verbosity levels < -1. */ | ||
| 99 | if (verbosity_level < -1) | ||
| 100 | verbosity_level = -1; | ||
| 101 | |||
| 102 | return verbosity_level; | ||
| 103 | } | ||
| 104 | |||
| 105 | void | ||
| 106 | np_debug(int verbosity, const char *fmt, ...) | ||
| 107 | { | ||
| 108 | va_list ap; | ||
| 109 | |||
| 110 | if (verbosity_level != -1 && verbosity >= verbosity_level) | ||
| 111 | PRINT_OUTPUT(fmt, ap); | ||
| 112 | } | ||
| 113 | |||
| 114 | void | ||
| 115 | np_verbose(const char *fmt, ...) | ||
| 116 | { | ||
| 117 | va_list ap; | ||
| 118 | |||
| 119 | if (verbosity_level >= 1) { | ||
| 120 | PRINT_OUTPUT(fmt, ap); | ||
| 121 | putchar('\n'); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | |||
| 125 | void | ||
| 126 | np_die(int status, const char *fmt, ...) | ||
| 127 | { | ||
| 128 | va_list ap; | ||
| 129 | const char *p; | ||
| 130 | |||
| 131 | if (program_name == NULL || service_name == NULL) | ||
| 132 | PRINT_OUTPUT(fmt, ap); | ||
| 133 | |||
| 134 | for (p = (verbosity_level > 0) ? | ||
| 135 | VERBOSE_OUTPUT_FORMAT : STANDARD_OUTPUT_FORMAT; | ||
| 136 | *p != '\0'; p++) { | ||
| 137 | if (*p == '%') { | ||
| 138 | if (*++p == '\0') | ||
| 139 | break; | ||
| 140 | switch (*p) { | ||
| 141 | case 'm': | ||
| 142 | PRINT_OUTPUT(fmt, ap); | ||
| 143 | continue; | ||
| 144 | case 'p': | ||
| 145 | fputs(program_name, stdout); | ||
| 146 | continue; | ||
| 147 | case 's': | ||
| 148 | fputs(service_name, stdout); | ||
| 149 | continue; | ||
| 150 | case 'x': | ||
| 151 | fputs(state_text(status), stdout); | ||
| 152 | continue; | ||
| 153 | } | ||
| 154 | } else if (*p == '\\') { | ||
| 155 | if (*++p == '\0') | ||
| 156 | break; | ||
| 157 | switch (*p) { | ||
| 158 | case 'n': | ||
| 159 | putchar('\n'); | ||
| 160 | continue; | ||
| 161 | case 't': | ||
| 162 | putchar('\t'); | ||
| 163 | continue; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | putchar(*p); | ||
| 167 | } | ||
| 168 | exit(status); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* TODO: die() can be removed as soon as all plugins use np_die() instead. */ | ||
| 31 | void | 172 | void |
| 32 | die (int result, const char *fmt, ...) | 173 | die (int result, const char *fmt, ...) |
| 33 | { | 174 | { |
| @@ -308,3 +449,67 @@ char *np_extract_value(const char *varlist, const char *name, char sep) { | |||
| 308 | return value; | 449 | return value; |
| 309 | } | 450 | } |
| 310 | 451 | ||
| 452 | /* | ||
| 453 | * Replace occurrences of "%m" by strerror(errno). Other printf(3)-style | ||
| 454 | * conversion specifications will be copied verbatim, including "%%", even if | ||
| 455 | * followed by an "m". Returns a pointer to a static buffer in order to not | ||
| 456 | * fail on memory allocation error. | ||
| 457 | */ | ||
| 458 | static char * | ||
| 459 | insert_syserr(const char *buf) | ||
| 460 | { | ||
| 461 | static char newbuf[8192]; | ||
| 462 | char *errstr = strerror(errno); | ||
| 463 | size_t errlen = strlen(errstr); | ||
| 464 | size_t copylen; | ||
| 465 | unsigned i, j; | ||
| 466 | |||
| 467 | for (i = 0, j = 0; buf[i] != '\0' && j < sizeof(newbuf) - 2; i++, j++) { | ||
| 468 | if (buf[i] == '%') { | ||
| 469 | if (buf[++i] == 'm') { | ||
| 470 | copylen = (errlen > sizeof(newbuf) - j - 1) ? | ||
| 471 | sizeof(newbuf) - j - 1 : errlen; | ||
| 472 | memcpy(newbuf + j, errstr, copylen); | ||
| 473 | /* | ||
| 474 | * As we'll increment j by 1 after the iteration | ||
| 475 | * anyway, we only increment j by the number of | ||
| 476 | * copied bytes - 1. | ||
| 477 | */ | ||
| 478 | j += copylen - 1; | ||
| 479 | continue; | ||
| 480 | } else { | ||
| 481 | /* | ||
| 482 | * The possibility to run into this block is the | ||
| 483 | * reason we checked for j < sizeof(newbuf) - 2 | ||
| 484 | * instead of j < sizeof(newbuf) - 1. | ||
| 485 | */ | ||
| 486 | newbuf[j++] = '%'; | ||
| 487 | if (buf[i] == '\0') | ||
| 488 | break; | ||
| 489 | } | ||
| 490 | } | ||
| 491 | newbuf[j] = buf[i]; | ||
| 492 | } | ||
| 493 | newbuf[j] = '\0'; | ||
| 494 | return newbuf; | ||
| 495 | } | ||
| 496 | |||
| 497 | /* | ||
| 498 | * Given a numerical status, return a pointer to the according string. | ||
| 499 | */ | ||
| 500 | const char * | ||
| 501 | state_text(int result) | ||
| 502 | { | ||
| 503 | switch (result) { | ||
| 504 | case STATE_OK: | ||
| 505 | return "OK"; | ||
| 506 | case STATE_WARNING: | ||
| 507 | return "WARNING"; | ||
| 508 | case STATE_CRITICAL: | ||
| 509 | return "CRITICAL"; | ||
| 510 | case STATE_DEPENDENT: | ||
| 511 | return "DEPENDENT"; | ||
| 512 | default: | ||
| 513 | return "UNKNOWN"; | ||
| 514 | } | ||
| 515 | } | ||
diff --git a/lib/utils_base.h b/lib/utils_base.h index f40fdb0f..8d0b2124 100644 --- a/lib/utils_base.h +++ b/lib/utils_base.h | |||
| @@ -37,6 +37,23 @@ int get_status(double, thresholds *); | |||
| 37 | 37 | ||
| 38 | char *np_escaped_string (const char *); | 38 | char *np_escaped_string (const char *); |
| 39 | 39 | ||
| 40 | void np_set_output(const char *, const char *, int, int); | ||
| 41 | int np_adjust_verbosity(int); | ||
| 42 | void np_debug(int, const char *, ...) | ||
| 43 | __attribute__((format(printf, 2, 3))); | ||
| 44 | void np_verbose(const char *, ...) | ||
| 45 | __attribute__((format(printf, 1, 2))); | ||
| 46 | void np_die(int, const char *, ...) | ||
| 47 | __attribute__((noreturn, format(printf, 2, 3))); | ||
| 48 | |||
| 49 | #define np_verbatim(s) np_verbose("%s", s) | ||
| 50 | #define np_increase_verbosity(i) np_adjust_verbosity(i) | ||
| 51 | #define np_decrease_verbosity(i) np_adjust_verbosity(-i) | ||
| 52 | #define np_get_verbosity() np_adjust_verbosity(0) | ||
| 53 | #define np_set_verbosity(v) np_set_output(NULL, NULL, v, 0) | ||
| 54 | #define np_set_mynames(p, s) np_set_output(p, s, -2, 0) | ||
| 55 | |||
| 56 | /* TODO: die() can be removed as soon as all plugins use np_die() instead. */ | ||
| 40 | void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3))); | 57 | void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3))); |
| 41 | 58 | ||
| 42 | /* Return codes for _set_thresholds */ | 59 | /* Return codes for _set_thresholds */ |
| @@ -64,4 +81,7 @@ char *np_extract_value(const char*, const char*, char); | |||
| 64 | */ | 81 | */ |
| 65 | #define np_extract_ntpvar(l, n) np_extract_value(l, n, ',') | 82 | #define np_extract_ntpvar(l, n) np_extract_value(l, n, ',') |
| 66 | 83 | ||
| 84 | /* Given a numerical status, return a pointer to the according string. */ | ||
| 85 | const char *state_text(int); | ||
| 86 | |||
| 67 | #endif /* _UTILS_BASE_ */ | 87 | #endif /* _UTILS_BASE_ */ |
