summaryrefslogtreecommitdiffstats
path: root/lib/utils_base.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/utils_base.c')
-rw-r--r--lib/utils_base.c202
1 files changed, 202 insertions, 0 deletions
diff --git a/lib/utils_base.c b/lib/utils_base.c
index fbed360..7eada0c 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
30static char *insert_syserr(const char *);
31
32extern int errno;
33static int verbosity_level = -2;
34static const char *program_name = NULL;
35static 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 */
43void
44np_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
77int
78np_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
92void
93np_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
101void
102np_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
112void
113np_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. */
19void 159void
20die (int result, const char *fmt, ...) 160die (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
387const char *
388state_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 */
410static char *
411insert_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}