diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/utils_base.c | 202 | ||||
| -rw-r--r-- | lib/utils_base.h | 19 |
2 files changed, 221 insertions, 0 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c index fbed3607..7eada0cc 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c | |||
| @@ -12,10 +12,150 @@ | |||
| 12 | * $Date$ | 12 | * $Date$ |
| 13 | ****************************************************************************/ | 13 | ****************************************************************************/ |
| 14 | 14 | ||
| 15 | #if HAVE_LIBGEN_H | ||
| 16 | #include <libgen.h> /* basename(3) */ | ||
| 17 | #endif | ||
| 15 | #include <stdarg.h> | 18 | #include <stdarg.h> |
| 16 | #include "common.h" | 19 | #include "common.h" |
| 17 | #include "utils_base.h" | 20 | #include "utils_base.h" |
| 18 | 21 | ||
| 22 | #define PRINT_OUTPUT(fmt, ap) \ | ||
| 23 | do { \ | ||
| 24 | fmt = insert_syserr(fmt); \ | ||
| 25 | va_start(ap, fmt); \ | ||
| 26 | vprintf(fmt, ap); \ | ||
| 27 | va_end(ap); \ | ||
| 28 | } while (/* CONSTCOND */ 0) | ||
| 29 | |||
| 30 | static char *insert_syserr(const char *); | ||
| 31 | |||
| 32 | extern int errno; | ||
| 33 | static int verbosity_level = -2; | ||
| 34 | static const char *program_name = NULL; | ||
| 35 | static const char *service_name = NULL; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * Set static variables for use in output functions. Usually, argv[0] may be | ||
| 39 | * used as progname, since we call basename(3) ourselves. If a verbosity value | ||
| 40 | * of -2 is specified, the verbosity_level won't be set. Currently, no flags | ||
| 41 | * are implemented. | ||
| 42 | */ | ||
| 43 | void | ||
| 44 | np_set_output(const char *progname, const char *servname, int verbosity, | ||
| 45 | int flags __attribute__((unused))) | ||
| 46 | { | ||
| 47 | static char pathbuf[128], progbuf[128], servbuf[32]; | ||
| 48 | |||
| 49 | if (progname != NULL) { | ||
| 50 | #if HAVE_BASENAME | ||
| 51 | /* | ||
| 52 | * Copy the progname into a temporary buffer in order to cope | ||
| 53 | * with basename(3) implementations which modify their argument. | ||
| 54 | * TODO: Maybe we should implement an np_basename()? Gnulib's | ||
| 55 | * base_name() dies on error, writing a message to stderr, which | ||
| 56 | * is probably not what we want. Once we have some replacement, | ||
| 57 | * the libgen-/basename(3)-related checks can be removed from | ||
| 58 | * configure.in. | ||
| 59 | */ | ||
| 60 | strncpy(pathbuf, progname, sizeof(pathbuf) - 1); | ||
| 61 | pathbuf[sizeof(pathbuf) - 1] = '\0'; | ||
| 62 | progname = basename(pathbuf); | ||
| 63 | #endif | ||
| 64 | strncpy(progbuf, progname, sizeof(progbuf) - 1); | ||
| 65 | progbuf[sizeof(progbuf) - 1] = '\0'; | ||
| 66 | program_name = progbuf; | ||
| 67 | } | ||
| 68 | if (servname != NULL) { | ||
| 69 | strncpy(servbuf, servname, sizeof(servbuf) - 1); | ||
| 70 | servbuf[sizeof(servbuf) - 1] = '\0'; | ||
| 71 | service_name = servbuf; | ||
| 72 | } | ||
| 73 | if (verbosity != -2) | ||
| 74 | verbosity_level = verbosity; | ||
| 75 | } | ||
| 76 | |||
| 77 | int | ||
| 78 | np_adjust_verbosity(int by) | ||
| 79 | { | ||
| 80 | if (verbosity_level == -2) | ||
| 81 | verbosity_level = by; | ||
| 82 | else | ||
| 83 | verbosity_level += by; | ||
| 84 | |||
| 85 | /* We don't support verbosity levels < -1. */ | ||
| 86 | if (verbosity_level < -1) | ||
| 87 | verbosity_level = -1; | ||
| 88 | |||
| 89 | return verbosity_level; | ||
| 90 | } | ||
| 91 | |||
| 92 | void | ||
| 93 | np_debug(int verbosity, const char *fmt, ...) | ||
| 94 | { | ||
| 95 | va_list ap; | ||
| 96 | |||
| 97 | if (verbosity_level != -1 && verbosity >= verbosity_level) | ||
| 98 | PRINT_OUTPUT(fmt, ap); | ||
| 99 | } | ||
| 100 | |||
| 101 | void | ||
| 102 | np_verbose(const char *fmt, ...) | ||
| 103 | { | ||
| 104 | va_list ap; | ||
| 105 | |||
| 106 | if (verbosity_level >= 1) { | ||
| 107 | PRINT_OUTPUT(fmt, ap); | ||
| 108 | putchar('\n'); | ||
| 109 | } | ||
| 110 | } | ||
| 111 | |||
| 112 | void | ||
| 113 | np_die(int status, const char *fmt, ...) | ||
| 114 | { | ||
| 115 | va_list ap; | ||
| 116 | const char *p; | ||
| 117 | |||
| 118 | if (program_name == NULL || service_name == NULL) | ||
| 119 | PRINT_OUTPUT(fmt, ap); | ||
| 120 | |||
| 121 | for (p = (verbosity_level > 0) ? | ||
| 122 | VERBOSE_OUTPUT_FORMAT : STANDARD_OUTPUT_FORMAT; | ||
| 123 | *p != '\0'; p++) { | ||
| 124 | if (*p == '%') { | ||
| 125 | if (*++p == '\0') | ||
| 126 | break; | ||
| 127 | switch (*p) { | ||
| 128 | case 'm': | ||
| 129 | PRINT_OUTPUT(fmt, ap); | ||
| 130 | continue; | ||
| 131 | case 'p': | ||
| 132 | fputs(program_name, stdout); | ||
| 133 | continue; | ||
| 134 | case 's': | ||
| 135 | fputs(service_name, stdout); | ||
| 136 | continue; | ||
| 137 | case 'x': | ||
| 138 | fputs(state_text(status), stdout); | ||
| 139 | continue; | ||
| 140 | } | ||
| 141 | } else if (*p == '\\') { | ||
| 142 | if (*++p == '\0') | ||
| 143 | break; | ||
| 144 | switch (*p) { | ||
| 145 | case 'n': | ||
| 146 | putchar('\n'); | ||
| 147 | continue; | ||
| 148 | case 't': | ||
| 149 | putchar('\t'); | ||
| 150 | continue; | ||
| 151 | } | ||
| 152 | } | ||
| 153 | putchar(*p); | ||
| 154 | } | ||
| 155 | exit(status); | ||
| 156 | } | ||
| 157 | |||
| 158 | /* TODO: die() can be removed as soon as all plugins use np_die() instead. */ | ||
| 19 | void | 159 | void |
| 20 | die (int result, const char *fmt, ...) | 160 | die (int result, const char *fmt, ...) |
| 21 | { | 161 | { |
| @@ -243,3 +383,65 @@ int np_warn_if_not_root(void) { | |||
| 243 | } | 383 | } |
| 244 | return status; | 384 | return status; |
| 245 | } | 385 | } |
| 386 | |||
| 387 | const char * | ||
| 388 | state_text(int result) | ||
| 389 | { | ||
| 390 | switch (result) { | ||
| 391 | case STATE_OK: | ||
| 392 | return "OK"; | ||
| 393 | case STATE_WARNING: | ||
| 394 | return "WARNING"; | ||
| 395 | case STATE_CRITICAL: | ||
| 396 | return "CRITICAL"; | ||
| 397 | case STATE_DEPENDENT: | ||
| 398 | return "DEPENDENT"; | ||
| 399 | default: | ||
| 400 | return "UNKNOWN"; | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 404 | /* | ||
| 405 | * Replace occurrences of "%m" by strerror(errno). Other printf(3)-style | ||
| 406 | * conversion specifications will be copied verbatim, including "%%", even if | ||
| 407 | * followed by an "m". Returns a static buffer in order to not fail on memory | ||
| 408 | * allocation error. | ||
| 409 | */ | ||
| 410 | static char * | ||
| 411 | insert_syserr(const char *buf) | ||
| 412 | { | ||
| 413 | static char newbuf[8192]; | ||
| 414 | char *errstr = strerror(errno); | ||
| 415 | size_t errlen = strlen(errstr); | ||
| 416 | size_t copylen; | ||
| 417 | unsigned i, j; | ||
| 418 | |||
| 419 | for (i = 0, j = 0; buf[i] != '\0' && j < sizeof(newbuf) - 2; i++, j++) { | ||
| 420 | if (buf[i] == '%') { | ||
| 421 | if (buf[++i] == 'm') { | ||
| 422 | copylen = (errlen > sizeof(newbuf) - j - 1) ? | ||
| 423 | sizeof(newbuf) - j - 1 : errlen; | ||
| 424 | memcpy(newbuf + j, errstr, copylen); | ||
| 425 | /* | ||
| 426 | * As we'll increment j by 1 after the iteration | ||
| 427 | * anyway, we only increment j by the number of | ||
| 428 | * copied bytes - 1. | ||
| 429 | */ | ||
| 430 | j += copylen - 1; | ||
| 431 | continue; | ||
| 432 | } else { | ||
| 433 | /* | ||
| 434 | * The possibility to run into this block is the | ||
| 435 | * reason we checked for j < sizeof(newbuf) - 2 | ||
| 436 | * instead of j < sizeof(newbuf) - 1. | ||
| 437 | */ | ||
| 438 | newbuf[j++] = '%'; | ||
| 439 | if (buf[i] == '\0') | ||
| 440 | break; | ||
| 441 | } | ||
| 442 | } | ||
| 443 | newbuf[j] = buf[i]; | ||
| 444 | } | ||
| 445 | newbuf[j] = '\0'; | ||
| 446 | return newbuf; | ||
| 447 | } | ||
diff --git a/lib/utils_base.h b/lib/utils_base.h index bda76595..b6e8128b 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 */ |
| @@ -50,4 +67,6 @@ int np_check_if_root(void); | |||
| 50 | * code from the above function, in case it's helpful for testing */ | 67 | * code from the above function, in case it's helpful for testing */ |
| 51 | int np_warn_if_not_root(void); | 68 | int np_warn_if_not_root(void); |
| 52 | 69 | ||
| 70 | const char *state_text(int); | ||
| 71 | |||
| 53 | #endif /* _UTILS_BASE_ */ | 72 | #endif /* _UTILS_BASE_ */ |
