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-04-21 22:47:29 (GMT)
commit92bb86c484c3d52c5ffdfa790f7a5acf68edcc36 (patch)
treee2195501bf3b67b373c9c3ddd0a5f0330d0209ed /lib/utils_base.c
parent05a980ba4bd3de0540771000955bd3235ad17acd (diff)
downloadmonitoring-plugins-92bb86c484c3d52c5ffdfa790f7a5acf68edcc36.tar.gz
Make C plugin output format configurable
*** THIS COMMIT WILL BE MODIFIED IN THE FUTURE! *** The development guidelines¹ currently state that the plugin output should be in the format "SERVICE STATUS: Information text". However, when a plugin is called via Nagios in order to perform a service check, adding SERVICE and STATUS to the output is redundant. And when a plugin is called on the command line for testing, there is no use in printing out the SERVICE string, either. However, for debugging, it does make sense to print out the STATUS so that the user won't have to check and interpret the exit code manually. But it should suffice to print such debug output only when called with "--verbose", not in production. Space for plugin output is sometimes scarce, so that we should try to keep the output "short and to the point" (as the guide states) and not waste space with redundant information. Therefore, we decided² to make the ("normal" and "verbose") plugin output configurable at compile time. ¹ http://nagiosplug.sf.net/developer-guidelines.html ² http://thread.gmane.org/gmane.network.nagios.plugins.devel/5155
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}