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.c205
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
43static char *insert_syserr(const char *);
44
45extern int errno;
46static int verbosity_level = -2;
47static const char *program_name = NULL;
48static 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 */
56void
57np_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
90int
91np_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
105void
106np_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
114void
115np_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
125void
126np_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. */
31void 172void
32die (int result, const char *fmt, ...) 173die (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 */
458static char *
459insert_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 */
500const char *
501state_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}