1 /******************************************************************************
2 *
3 * Program: Inverting plugin wrapper for Nagios
4 * License: GPL
5 *
6 * License Information:
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * $Id$
23 *
24 *****************************************************************************/
26 const char *progname = "negate";
27 #define REVISION "$Revision$"
28 #define COPYRIGHT "2002"
29 #define AUTHOR "Karl DeBisschop"
30 #define EMAIL "kdebisschop@users.sourceforge.net"
31 #define SUMMARY "Negates the status of a plugin (returns OK for CRITICAL, and vice-versa).\n"
33 #define OPTIONS "\
34 [-t timeout] <definition of wrapped plugin>"
36 #define LONGOPTIONS "\
37 -t, --timeout=INTEGER\n\
38 Terminate test if timeout limit is exceeded (default: %d)\n\
39 [keep this less than the plugin timeout to retain CRITICAL status]\n"
41 #define EXAMPLES "\
42 negate \"/usr/local/nagios/libexec/check_ping -H host\"\n\
43 Run check_ping and invert result. Must use full path to plugin\n\
44 negate \"/usr/local/nagios/libexec/check_procs -a 'vi negate.c'\"\n\
45 Use single quotes if you need to retain spaces\n"
47 #define DESCRIPTION "\
48 This plugin is a wrapper to take the output of another plugin and invert it.\n\
49 If the wrapped plugin returns STATE_OK, the wrapper will return STATE_CRITICAL.\n\
50 If the wrapped plugin returns STATE_CRITICAL, the wrapper will return STATE_OK.\n\
51 Otherwise, the output state of the wrapped plugin is unchanged.\n"
53 #define DEFAULT_TIMEOUT 9
55 #include "common.h"
56 #include "utils.h"
57 #include "popen.h"
59 char *command_line;
61 int process_arguments (int, char **);
62 int validate_arguments (void);
63 void print_usage (void);
64 void print_help (void);
65 \f
66 /******************************************************************************
68 The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
69 tags in the comments. With in the tags, the XML is assembled sequentially.
70 You can define entities in tags. You also have all the #defines available as
71 entities.
73 Please note that all tags must be lowercase to use the DocBook XML DTD.
75 @@-<article>
77 <sect1>
78 <title>Quick Reference</title>
79 <!-- The refentry forms a manpage -->
80 <refentry>
81 <refmeta>
82 <manvolnum>5<manvolnum>
83 </refmeta>
84 <refnamdiv>
85 <refname>&progname;</refname>
86 <refpurpose>&SUMMARY;</refpurpose>
87 </refnamdiv>
88 </refentry>
89 </sect1>
91 <sect1>
92 <title>FAQ</title>
93 </sect1>
95 <sect1>
96 <title>Theory, Installation, and Operation</title>
98 <sect2>
99 <title>General Description</title>
100 <para>
101 &DESCRIPTION;
102 </para>
103 </sect2>
105 <sect2>
106 <title>Future Enhancements</title>
107 <para>ToDo List</para>
108 <itemizedlist>
109 <listitem>Add option to do regex substitution in output text</listitem>
110 </itemizedlist>
111 </sect2>
114 <sect2>
115 <title>Functions</title>
116 -@@
117 ******************************************************************************/
119 int
120 main (int argc, char **argv)
121 {
122 int found = 0, result = STATE_UNKNOWN;
123 char input_buffer[MAX_INPUT_BUFFER];
125 if (process_arguments (argc, argv) == ERROR)
126 usage ("Could not parse arguments\n");
128 /* Set signal handling and alarm */
129 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR)
130 terminate (STATE_UNKNOWN, "Cannot catch SIGALRM");
132 (void) alarm ((unsigned) timeout_interval);
134 child_process = spopen (command_line);
135 if (child_process == NULL)
136 terminate (STATE_UNKNOWN, "Could not open pipe: %s\n", command_line);
138 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
139 if (child_stderr == NULL) {
140 printf ("Could not open stderr for %s\n", command_line);
141 }
143 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
144 found++;
145 if (strchr (input_buffer, '\n')) {
146 input_buffer[strcspn (input_buffer, "\n")] = 0;
147 printf ("%s\n", input_buffer);
148 }
149 else {
150 printf ("%s\n", input_buffer);
151 }
152 }
154 if (!found)
155 terminate (STATE_UNKNOWN,\
156 "%s problem - No data recieved from host\nCMD: %s\n",\
157 argv[0], command_line);
159 /* close the pipe */
160 result = spclose (child_process);
162 /* WARNING if output found on stderr */
163 if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
164 result = max_state (result, STATE_WARNING);
166 /* close stderr */
167 (void) fclose (child_stderr);
169 if (result == STATE_OK)
170 exit (STATE_CRITICAL);
171 else if (result == STATE_CRITICAL)
172 exit (EXIT_SUCCESS);
173 else
174 exit (result);
175 }
176 \f
180 void
181 print_help (void)
182 {
183 print_revision (progname, REVISION);
184 printf
185 ("Copyright (c) %s %s <%s>\n\n%s\n",
186 COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
187 print_usage ();
188 printf
189 ("\nOptions:\n" LONGOPTIONS "\n" "Examples:\n" EXAMPLES "\n"
190 DESCRIPTION "\n", DEFAULT_TIMEOUT);
191 support ();
192 }
194 void
195 print_usage (void)
196 {
197 printf ("Usage:\n" " %s %s\n"
198 " %s (-h | --help) for detailed help\n"
199 " %s (-V | --version) for version information\n",
200 progname, OPTIONS, progname, progname);
201 }
202 \f
205 /******************************************************************************
206 @@-
207 <sect3>
208 <title>process_arguments</title>
210 <para>This function parses the command line into the needed
211 variables.</para>
213 <para>Aside from the standard 'help' and 'version' options, there
214 is a only a 'timeout' option.No validation is currently done.</para>
216 </sect3>
217 -@@
218 ******************************************************************************/
220 /* process command-line arguments */
221 int
222 process_arguments (int argc, char **argv)
223 {
224 int c;
226 int option_index = 0;
227 static struct option long_options[] = {
228 {"help", no_argument, 0, 'h'},
229 {"version", no_argument, 0, 'V'},
230 {"timeout", required_argument, 0, 't'},
231 {0, 0, 0, 0}
232 };
234 while (1) {
235 c = getopt_long (argc, argv, "+hVt:",
236 long_options, &option_index);
238 if (c == -1 || c == EOF)
239 break;
241 switch (c) {
242 case '?': /* help */
243 usage3 ("Unknown argument", optopt);
244 case 'h': /* help */
245 print_help ();
246 exit (EXIT_SUCCESS);
247 case 'V': /* version */
248 print_revision (progname, REVISION);
249 exit (EXIT_SUCCESS);
250 case 't': /* timeout period */
251 if (!is_integer (optarg))
252 usage2 ("Timeout Interval must be an integer", optarg);
253 timeout_interval = atoi (optarg);
254 break;
255 }
256 }
258 asprintf (&command_line, "%s", argv[optind]);
259 for (c = optind+1; c < argc; c++) {
260 asprintf (&command_line, "%s %s", command_line, argv[c]);
261 }
263 return validate_arguments ();
264 }
267 /******************************************************************************
268 @@-
269 <sect3>
270 <title>validate_arguments</title>
272 <para>No validation is currently done.</para>
274 </sect3>
275 -@@
276 ******************************************************************************/
278 int
279 validate_arguments ()
280 {
281 if (command_line == NULL)
282 return ERROR;
283 return STATE_OK;
284 }
285 \f
287 /******************************************************************************
288 @@-
289 </sect2>
290 </sect1>
291 </article>
292 -@@
293 ******************************************************************************/