diff options
Diffstat (limited to 'lib/utils_base.c')
-rw-r--r-- | lib/utils_base.c | 205 |
1 files changed, 205 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 | } | ||