summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Weiss <hweiss@users.sourceforge.net>2009-04-22 00:28:53 +0200
committerHolger Weiss <hweiss@users.sourceforge.net>2009-04-22 00:47:29 +0200
commit92bb86c484c3d52c5ffdfa790f7a5acf68edcc36 (patch)
treee2195501bf3b67b373c9c3ddd0a5f0330d0209ed
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
-rw-r--r--configure.in38
-rw-r--r--lib/utils_base.c202
-rw-r--r--lib/utils_base.h19
-rw-r--r--plugins/utils.c17
-rw-r--r--plugins/utils.h2
5 files changed, 259 insertions, 19 deletions
diff --git a/configure.in b/configure.in
index 9067978a..474522d4 100644
--- a/configure.in
+++ b/configure.in
@@ -40,6 +40,39 @@ INSTALL="$INSTALL $extra_install_args"
40INSTALL_STRIP_PROGRAM="$INSTALL_STRIP_PROGRAM $extra_install_args" 40INSTALL_STRIP_PROGRAM="$INSTALL_STRIP_PROGRAM $extra_install_args"
41AC_SUBST(INSTALL) 41AC_SUBST(INSTALL)
42 42
43dnl Configure the plugin output format
44default_output_format="%s %x: %i\n"
45AC_ARG_WITH([standard_output_format],
46 [AS_HELP_STRING([--with-standard-output-format=FORMAT],
47 [specify the standard plugin output FORMAT; %p, %s, %x, and %m
48 will be replaced by the plugin name, the service name, the
49 status string, and the information message, respectively; tabs
50 or newlines can be inserted using \t or \n
51 @<:@default="%s %x: %m\n"@:>@])],
52 [standard_output_format=$withval],
53 [standard_output_format="yes"])
54AC_ARG_WITH([verbose_output_format],
55 [AS_HELP_STRING([--with-verbose-output-format=FORMAT],
56 [specify the verbose plugin output FORMAT; %p, %s, %x, and %m
57 will be replaced by the plugin name, the service name, the
58 status string, and the information message, respectively; tabs
59 or newlines can be inserted using \t or \n
60 @<:@default="%s %x: %m\n"@:>@])],
61 [verbose_output_format=$withval],
62 [verbose_output_format="yes"])
63AS_IF([test "$standard_output_format" = yes],
64 [standard_output_format=$default_output_format],
65 [test "$standard_output_format" = no],
66 [standard_output_format=""],
67 [test "$verbose_output_format" = yes],
68 [verbose_output_format=$default_output_format],
69 [test "$verbose_output_format" = no],
70 [verbose_output_format=""])
71AC_DEFINE_UNQUOTED([STANDARD_OUTPUT_FORMAT], ["$standard_output_format"],
72 [Define the standard plugin output format.])
73AC_DEFINE_UNQUOTED([VERBOSE_OUTPUT_FORMAT], ["$verbose_output_format"],
74 [Define the verbose plugin output format.])
75
43AC_PROG_CC 76AC_PROG_CC
44gl_EARLY 77gl_EARLY
45AC_PROG_GCC_TRADITIONAL 78AC_PROG_GCC_TRADITIONAL
@@ -147,6 +180,11 @@ AC_CHECK_LIB(socket,socket,SOCKETLIBS="$SOCKETLIBS -lsocket")
147AC_CHECK_LIB(resolv,main,SOCKETLIBS="$SOCKETLIBS -lresolv") 180AC_CHECK_LIB(resolv,main,SOCKETLIBS="$SOCKETLIBS -lresolv")
148AC_SUBST(SOCKETLIBS) 181AC_SUBST(SOCKETLIBS)
149 182
183dnl check for basename(3) which needs -lgen on some systems (e.g. IRIX)
184AC_CHECK_HEADERS([libgen.h])
185AC_SEARCH_LIBS([basename], [gen])
186AC_CHECK_FUNCS([basename])
187
150dnl 188dnl
151dnl check for math-related functions needing -lm 189dnl check for math-related functions needing -lm
152AC_CHECK_HEADERS(math.h) 190AC_CHECK_HEADERS(math.h)
diff --git a/lib/utils_base.c b/lib/utils_base.c
index fbed3607..7eada0cc 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}
diff --git a/lib/utils_base.h b/lib/utils_base.h
index bda76595..b6e8128b 100644
--- a/lib/utils_base.h
+++ b/lib/utils_base.h
@@ -37,6 +37,23 @@ int get_status(double, thresholds *);
37 37
38char *np_escaped_string (const char *); 38char *np_escaped_string (const char *);
39 39
40void np_set_output(const char *, const char *, int, int);
41int np_adjust_verbosity(int);
42void np_debug(int, const char *, ...)
43 __attribute__((format(printf, 2, 3)));
44void np_verbose(const char *, ...)
45 __attribute__((format(printf, 1, 2)));
46void np_die(int, const char *, ...)
47 __attribute__((noreturn, format(printf, 2, 3)));
48
49#define np_verbatim(s) np_verbose("%s", s)
50#define np_increase_verbosity(i) np_adjust_verbosity(i)
51#define np_decrease_verbosity(i) np_adjust_verbosity(-i)
52#define np_get_verbosity() np_adjust_verbosity(0)
53#define np_set_verbosity(v) np_set_output(NULL, NULL, v, 0)
54#define np_set_mynames(p, s) np_set_output(p, s, -2, 0)
55
56/* TODO: die() can be removed as soon as all plugins use np_die() instead. */
40void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3))); 57void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3)));
41 58
42/* Return codes for _set_thresholds */ 59/* Return codes for _set_thresholds */
@@ -50,4 +67,6 @@ int np_check_if_root(void);
50 * code from the above function, in case it's helpful for testing */ 67 * code from the above function, in case it's helpful for testing */
51int np_warn_if_not_root(void); 68int np_warn_if_not_root(void);
52 69
70const char *state_text(int);
71
53#endif /* _UTILS_BASE_ */ 72#endif /* _UTILS_BASE_ */
diff --git a/plugins/utils.c b/plugins/utils.c
index 0e79fbdb..5967647a 100644
--- a/plugins/utils.c
+++ b/plugins/utils.c
@@ -121,23 +121,6 @@ print_revision (const char *command_name, const char *revision_string)
121 command_name, clean_revstring(revision_string), PACKAGE, VERSION); 121 command_name, clean_revstring(revision_string), PACKAGE, VERSION);
122} 122}
123 123
124const char *
125state_text (int result)
126{
127 switch (result) {
128 case STATE_OK:
129 return "OK";
130 case STATE_WARNING:
131 return "WARNING";
132 case STATE_CRITICAL:
133 return "CRITICAL";
134 case STATE_DEPENDENT:
135 return "DEPENDENT";
136 default:
137 return "UNKNOWN";
138 }
139}
140
141void 124void
142timeout_alarm_handler (int signo) 125timeout_alarm_handler (int signo)
143{ 126{
diff --git a/plugins/utils.h b/plugins/utils.h
index f15a7b16..98d19d20 100644
--- a/plugins/utils.h
+++ b/plugins/utils.h
@@ -84,8 +84,6 @@ void usage4(const char *) __attribute__((noreturn));
84void usage5(void) __attribute__((noreturn)); 84void usage5(void) __attribute__((noreturn));
85void usage_va(const char *fmt, ...) __attribute__((noreturn)); 85void usage_va(const char *fmt, ...) __attribute__((noreturn));
86 86
87const char *state_text (int);
88
89#define max(a,b) (((a)>(b))?(a):(b)) 87#define max(a,b) (((a)>(b))?(a):(b))
90#define min(a,b) (((a)<(b))?(a):(b)) 88#define min(a,b) (((a)<(b))?(a):(b))
91 89