summaryrefslogtreecommitdiffstats
path: root/lib/utils_base.c
diff options
context:
space:
mode:
authorHolger Weiss <hweiss@users.sourceforge.net>2009-04-21 22:28:53 (GMT)
committerHolger Weiss <hweiss@users.sourceforge.net>2009-05-10 11:37:35 (GMT)
commit006597a12d28d9cd752b3eeb56dff3bc97049f4c (patch)
tree26e322d4b996b901e0d928e11bba46658646b30f /lib/utils_base.c
parentdd52d7e5e7acfd42243bc1ce173a0bf5d62fe347 (diff)
downloadmonitoring-plugins-006597a12d28d9cd752b3eeb56dff3bc97049f4c.tar.gz
Make C plugin output format configurablehw/output/functions
The development guidelines¹ currently state that the plugin output should be in the format "SERVICE STATUS: Information text". However, the SERVICE and STATUS information is redundant, as the plugin caller (e.g., Nagios) should know which SERVICE is checked and the STATUS is returned via the plugin's exit code. After discussing² this issue on the development list, we decided to make the plugin output configurable at compile time (separately for "normal" and "verbose" output). ¹ http://nagiosplug.sf.net/developer-guidelines.html ² http://thread.gmane.org/gmane.network.nagios.plugins.devel/5155 Signed-off-by: Holger Weiss <hweiss@users.sourceforge.net>
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 77700f5..ba4f83b 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}