summaryrefslogtreecommitdiffstats
path: root/plugins/negate.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/negate.c')
-rw-r--r--plugins/negate.c142
1 files changed, 88 insertions, 54 deletions
diff --git a/plugins/negate.c b/plugins/negate.c
index 7e52fe67..a42a6c59 100644
--- a/plugins/negate.c
+++ b/plugins/negate.c
@@ -38,21 +38,18 @@ const char *email = "devel@monitoring-plugins.org";
38#include "common.h" 38#include "common.h"
39#include "utils.h" 39#include "utils.h"
40#include "utils_cmd.h" 40#include "utils_cmd.h"
41#include "negate.d/config.h"
42#include "../lib/states.h"
41 43
42#include <ctype.h> 44typedef struct {
45 int errorcode;
46 negate_config config;
47} negate_config_wrapper;
48static negate_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
49static negate_config_wrapper validate_arguments(negate_config_wrapper /*config_wrapper*/);
43 50
44static const char **process_arguments(int /*argc*/, char ** /*argv*/);
45static void validate_arguments(char ** /*command_line*/);
46static void print_help(void); 51static void print_help(void);
47void print_usage(void); 52void print_usage(void);
48static bool subst_text = false;
49
50static int state[4] = {
51 STATE_OK,
52 STATE_WARNING,
53 STATE_CRITICAL,
54 STATE_UNKNOWN,
55};
56 53
57int main(int argc, char **argv) { 54int main(int argc, char **argv) {
58 setlocale(LC_ALL, ""); 55 setlocale(LC_ALL, "");
@@ -61,15 +58,24 @@ int main(int argc, char **argv) {
61 58
62 timeout_interval = DEFAULT_TIMEOUT; 59 timeout_interval = DEFAULT_TIMEOUT;
63 60
64 char **command_line = (char **)process_arguments(argc, argv); 61 negate_config_wrapper tmp_config = process_arguments(argc, argv);
62
63 if (tmp_config.errorcode == ERROR) {
64 die(STATE_UNKNOWN, _("negate: Failed to parse input"));
65 }
66
67 negate_config config = tmp_config.config;
68
69 char **command_line = config.command_line;
65 70
66 /* Set signal handling and alarm */ 71 /* Set signal handling and alarm */
67 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) 72 if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
68 die(STATE_UNKNOWN, _("Cannot catch SIGALRM")); 73 die(STATE_UNKNOWN, _("Cannot catch SIGALRM"));
74 }
69 75
70 (void)alarm((unsigned)timeout_interval); 76 (void)alarm(timeout_interval);
71 77
72 int result = STATE_UNKNOWN; 78 mp_state_enum result = STATE_UNKNOWN;
73 output chld_out; 79 output chld_out;
74 output chld_err; 80 output chld_err;
75 81
@@ -86,46 +92,54 @@ int main(int argc, char **argv) {
86 } 92 }
87 93
88 /* Return UNKNOWN or worse if no output is returned */ 94 /* Return UNKNOWN or worse if no output is returned */
89 if (chld_out.lines == 0) 95 if (chld_out.lines == 0) {
90 die(max_state_alt(result, STATE_UNKNOWN), _("No data returned from command\n")); 96 die(max_state_alt(result, STATE_UNKNOWN), _("No data returned from command\n"));
97 }
91 98
92 char *sub; 99 char *sub;
93 for (size_t i = 0; i < chld_out.lines; i++) { 100 for (size_t i = 0; i < chld_out.lines; i++) {
94 if (subst_text && result >= 0 && result <= 4 && result != state[result]) { 101 if (config.subst_text && result >= 0 && result <= 4 && result != config.state[result]) {
95 /* Loop over each match found */ 102 /* Loop over each match found */
96 while ((sub = strstr(chld_out.line[i], state_text(result)))) { 103 while ((sub = strstr(chld_out.line[i], state_text(result)))) {
97 /* Terminate the first part and skip over the string we'll substitute */ 104 /* Terminate the first part and skip over the string we'll substitute */
98 *sub = '\0'; 105 *sub = '\0';
99 sub += strlen(state_text(result)); 106 sub += strlen(state_text(result));
100 /* then put everything back together */ 107 /* then put everything back together */
101 xasprintf(&chld_out.line[i], "%s%s%s", chld_out.line[i], state_text(state[result]), sub); 108 xasprintf(&chld_out.line[i], "%s%s%s", chld_out.line[i],
109 state_text(config.state[result]), sub);
102 } 110 }
103 } 111 }
104 printf("%s\n", chld_out.line[i]); 112 printf("%s\n", chld_out.line[i]);
105 } 113 }
106 114
107 if (result >= 0 && result <= 4) { 115 if (result >= 0 && result <= 4) {
108 exit(state[result]); 116 exit(config.state[result]);
109 } else { 117 } else {
110 exit(result); 118 exit(result);
111 } 119 }
112} 120}
113 121
114/* process command-line arguments */ 122/* process command-line arguments */
115static const char **process_arguments(int argc, char **argv) { 123static negate_config_wrapper process_arguments(int argc, char **argv) {
116 static struct option longopts[] = {{"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'}, 124 static struct option longopts[] = {
117 {"timeout", required_argument, 0, 't'}, {"timeout-result", required_argument, 0, 'T'}, 125 {"help", no_argument, 0, 'h'}, {"version", no_argument, 0, 'V'},
118 {"ok", required_argument, 0, 'o'}, {"warning", required_argument, 0, 'w'}, 126 {"timeout", required_argument, 0, 't'}, {"timeout-result", required_argument, 0, 'T'},
119 {"critical", required_argument, 0, 'c'}, {"unknown", required_argument, 0, 'u'}, 127 {"ok", required_argument, 0, 'o'}, {"warning", required_argument, 0, 'w'},
120 {"substitute", no_argument, 0, 's'}, {0, 0, 0, 0}}; 128 {"critical", required_argument, 0, 'c'}, {"unknown", required_argument, 0, 'u'},
121 129 {"substitute", no_argument, 0, 's'}, {0, 0, 0, 0}};
130
131 negate_config_wrapper result = {
132 .errorcode = OK,
133 .config = negate_config_init(),
134 };
122 bool permute = true; 135 bool permute = true;
123 while (true) { 136 while (true) {
124 int option = 0; 137 int option = 0;
125 int option_char = getopt_long(argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option); 138 int option_char = getopt_long(argc, argv, "+hVt:T:o:w:c:u:s", longopts, &option);
126 139
127 if (option_char == -1 || option_char == EOF) 140 if (option_char == -1 || option_char == EOF) {
128 break; 141 break;
142 }
129 143
130 switch (option_char) { 144 switch (option_char) {
131 case '?': /* help */ 145 case '?': /* help */
@@ -133,64 +147,80 @@ static const char **process_arguments(int argc, char **argv) {
133 break; 147 break;
134 case 'h': /* help */ 148 case 'h': /* help */
135 print_help(); 149 print_help();
136 exit(EXIT_SUCCESS); 150 exit(STATE_UNKNOWN);
137 break; 151 break;
138 case 'V': /* version */ 152 case 'V': /* version */
139 print_revision(progname, NP_VERSION); 153 print_revision(progname, NP_VERSION);
140 exit(EXIT_SUCCESS); 154 exit(STATE_UNKNOWN);
141 case 't': /* timeout period */ 155 case 't': /* timeout period */
142 if (!is_integer(optarg)) 156 if (!is_integer(optarg)) {
143 usage2(_("Timeout interval must be a positive integer"), optarg); 157 usage2(_("Timeout interval must be a positive integer"), optarg);
144 else 158 } else {
145 timeout_interval = atoi(optarg); 159 timeout_interval = atoi(optarg);
160 }
146 break; 161 break;
147 case 'T': /* Result to return on timeouts */ 162 case 'T': /* Result to return on timeouts */
148 if ((timeout_state = mp_translate_state(optarg)) == ERROR) 163 if ((timeout_state = mp_translate_state(optarg)) == ERROR) {
149 usage4(_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 164 usage4(_("Timeout result must be a valid state name (OK, WARNING, CRITICAL, "
165 "UNKNOWN) or integer (0-3)."));
166 }
150 break; 167 break;
151 case 'o': /* replacement for OK */ 168 case 'o': /* replacement for OK */
152 if ((state[STATE_OK] = mp_translate_state(optarg)) == ERROR) 169 if ((result.config.state[STATE_OK] = mp_translate_state(optarg)) == ERROR) {
153 usage4(_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 170 usage4(_("Ok must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or "
171 "integer (0-3)."));
172 }
154 permute = false; 173 permute = false;
155 break; 174 break;
156 175
157 case 'w': /* replacement for WARNING */ 176 case 'w': /* replacement for WARNING */
158 if ((state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR) 177 if ((result.config.state[STATE_WARNING] = mp_translate_state(optarg)) == ERROR) {
159 usage4(_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 178 usage4(_("Warning must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or "
179 "integer (0-3)."));
180 }
160 permute = false; 181 permute = false;
161 break; 182 break;
162 case 'c': /* replacement for CRITICAL */ 183 case 'c': /* replacement for CRITICAL */
163 if ((state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR) 184 if ((result.config.state[STATE_CRITICAL] = mp_translate_state(optarg)) == ERROR) {
164 usage4(_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 185 usage4(_("Critical must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or "
186 "integer (0-3)."));
187 }
165 permute = false; 188 permute = false;
166 break; 189 break;
167 case 'u': /* replacement for UNKNOWN */ 190 case 'u': /* replacement for UNKNOWN */
168 if ((state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR) 191 if ((result.config.state[STATE_UNKNOWN] = mp_translate_state(optarg)) == ERROR) {
169 usage4(_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or integer (0-3).")); 192 usage4(_("Unknown must be a valid state name (OK, WARNING, CRITICAL, UNKNOWN) or "
193 "integer (0-3)."));
194 }
170 permute = false; 195 permute = false;
171 break; 196 break;
172 case 's': /* Substitute status text */ 197 case 's': /* Substitute status text */
173 subst_text = true; 198 result.config.subst_text = true;
174 break; 199 break;
175 } 200 }
176 } 201 }
177 202
178 validate_arguments(&argv[optind]);
179
180 if (permute) { /* No [owcu] switch specified, default to this */ 203 if (permute) { /* No [owcu] switch specified, default to this */
181 state[STATE_OK] = STATE_CRITICAL; 204 result.config.state[STATE_OK] = STATE_CRITICAL;
182 state[STATE_CRITICAL] = STATE_OK; 205 result.config.state[STATE_CRITICAL] = STATE_OK;
183 } 206 }
184 207
185 return (const char **)&argv[optind]; 208 result.config.command_line = &argv[optind];
209
210 return validate_arguments(result);
186} 211}
187 212
188void validate_arguments(char **command_line) { 213negate_config_wrapper validate_arguments(negate_config_wrapper config_wrapper) {
189 if (command_line[0] == NULL) 214 if (config_wrapper.config.command_line[0] == NULL) {
190 usage4(_("Could not parse arguments")); 215 usage4(_("Could not parse arguments"));
216 }
191 217
192 if (strncmp(command_line[0], "/", 1) != 0 && strncmp(command_line[0], "./", 2) != 0) 218 if (strncmp(config_wrapper.config.command_line[0], "/", 1) != 0 &&
219 strncmp(config_wrapper.config.command_line[0], "./", 2) != 0) {
193 usage4(_("Require path to command")); 220 usage4(_("Require path to command"));
221 }
222
223 return config_wrapper;
194} 224}
195 225
196void print_help(void) { 226void print_help(void) {
@@ -198,7 +228,8 @@ void print_help(void) {
198 228
199 printf(COPYRIGHT, copyright, email); 229 printf(COPYRIGHT, copyright, email);
200 230
201 printf("%s\n", _("Negates only the return code of a plugin (returns OK for CRITICAL and vice-versa) by default.")); 231 printf("%s\n", _("Negates only the return code of a plugin (returns OK for CRITICAL and "
232 "vice-versa) by default."));
202 printf("%s\n", _("Additional switches can be used to control:\n")); 233 printf("%s\n", _("Additional switches can be used to control:\n"));
203 printf("\t - which state becomes what\n"); 234 printf("\t - which state becomes what\n");
204 printf("\t - changing the plugin output text to match the return code"); 235 printf("\t - changing the plugin output text to match the return code");
@@ -228,17 +259,20 @@ void print_help(void) {
228 printf("%s\n", _("Examples:")); 259 printf("%s\n", _("Examples:"));
229 printf(" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host"); 260 printf(" %s\n", "negate /usr/local/nagios/libexec/check_ping -H host");
230 printf(" %s\n", _("Run check_ping and invert result. Must use full path to plugin")); 261 printf(" %s\n", _("Run check_ping and invert result. Must use full path to plugin"));
231 printf(" %s\n", "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'"); 262 printf(" %s\n",
263 "negate -w OK -c UNKNOWN /usr/local/nagios/libexec/check_procs -a 'vi negate.c'");
232 printf(" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL")); 264 printf(" %s\n", _("This will return OK instead of WARNING and UNKNOWN instead of CRITICAL"));
233 printf("\n"); 265 printf("\n");
234 printf("%s\n", _("Notes:")); 266 printf("%s\n", _("Notes:"));
235 printf(" %s\n", _("This plugin is a wrapper to take the output of another plugin and invert it.")); 267 printf(" %s\n",
268 _("This plugin is a wrapper to take the output of another plugin and invert it."));
236 printf(" %s\n", _("The full path of the plugin must be provided.")); 269 printf(" %s\n", _("The full path of the plugin must be provided."));
237 printf(" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL.")); 270 printf(" %s\n", _("If the wrapped plugin returns OK, the wrapper will return CRITICAL."));
238 printf(" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK.")); 271 printf(" %s\n", _("If the wrapped plugin returns CRITICAL, the wrapper will return OK."));
239 printf(" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged.")); 272 printf(" %s\n", _("Otherwise, the output state of the wrapped plugin is unchanged."));
240 printf("\n"); 273 printf("\n");
241 printf(" %s\n", _("Using timeout-result, it is possible to override the timeout behaviour or a")); 274 printf(" %s\n",
275 _("Using timeout-result, it is possible to override the timeout behaviour or a"));
242 printf(" %s\n", _("plugin by setting the negate timeout a bit lower.")); 276 printf(" %s\n", _("plugin by setting the negate timeout a bit lower."));
243 277
244 printf(UT_SUPPORT); 278 printf(UT_SUPPORT);