Code

first revised patch failed to trap the "break" in while()
[nagiosplug.git] / plugins / negate.c
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)
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);
176 \f
180 void
181 print_help (void)
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 ();
194 void
195 print_usage (void)
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);
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)
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 ();
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 ()
281         if (command_line == NULL)
282                 return ERROR;
283         return STATE_OK;
285 \f
287 /******************************************************************************
288 @@-
289 </sect2> 
290 </sect1>
291 </article>
292 -@@
293 ******************************************************************************/