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_ */ |