negate.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. *****************************************************************************/
  25. const char *progname = "negate";
  26. #define REVISION "$Revision$"
  27. #define COPYRIGHT "2002"
  28. #define AUTHOR "Karl DeBisschop"
  29. #define EMAIL "kdebisschop@users.sourceforge.net"
  30. #define SUMMARY "Negates the status of a plugin (returns OK for CRITICAL, and vice-versa).\n"
  31. #define OPTIONS "\
  32. [-t timeout] <definition of wrapped plugin>"
  33. #define LONGOPTIONS "\
  34. -t, --timeout=INTEGER\n\
  35. Terminate test if timeout limit is exceeded (default: %d)\n\
  36. [keep this less than the plugin timeout to retain CRITICAL status]\n"
  37. #define EXAMPLES "\
  38. negate \"/usr/local/nagios/libexec/check_ping -H host\"\n\
  39. Run check_ping and invert result. Must use full path to plugin\n\
  40. negate \"/usr/local/nagios/libexec/check_procs -a 'vi negate.c'\"\n\
  41. Use single quotes if you need to retain spaces\n"
  42. #define DESCRIPTION "\
  43. This plugin is a wrapper to take the output of another plugin and invert it.\n\
  44. If the wrapped plugin returns STATE_OK, the wrapper will return STATE_CRITICAL.\n\
  45. If the wrapped plugin returns STATE_CRITICAL, the wrapper will return STATE_OK.\n\
  46. Otherwise, the output state of the wrapped plugin is unchanged.\n"
  47. #define DEFAULT_TIMEOUT 9
  48. #include "common.h"
  49. #include "utils.h"
  50. #include "popen.h"
  51. char *command_line;
  52. int process_arguments (int, char **);
  53. int validate_arguments (void);
  54. void print_usage (void);
  55. void print_help (void);
  56. /******************************************************************************
  57. The (psuedo?)literate programming XML is contained within \@\@\- <XML> \-\@\@
  58. tags in the comments. With in the tags, the XML is assembled sequentially.
  59. You can define entities in tags. You also have all the #defines available as
  60. entities.
  61. Please note that all tags must be lowercase to use the DocBook XML DTD.
  62. @@-<article>
  63. <sect1>
  64. <title>Quick Reference</title>
  65. <!-- The refentry forms a manpage -->
  66. <refentry>
  67. <refmeta>
  68. <manvolnum>5<manvolnum>
  69. </refmeta>
  70. <refnamdiv>
  71. <refname>&progname;</refname>
  72. <refpurpose>&SUMMARY;</refpurpose>
  73. </refnamdiv>
  74. </refentry>
  75. </sect1>
  76. <sect1>
  77. <title>FAQ</title>
  78. </sect1>
  79. <sect1>
  80. <title>Theory, Installation, and Operation</title>
  81. <sect2>
  82. <title>General Description</title>
  83. <para>
  84. &DESCRIPTION;
  85. </para>
  86. </sect2>
  87. <sect2>
  88. <title>Future Enhancements</title>
  89. <para>ToDo List</para>
  90. <itemizedlist>
  91. <listitem>Add option to do regex substitution in output text</listitem>
  92. </itemizedlist>
  93. </sect2>
  94. <sect2>
  95. <title>Functions</title>
  96. -@@
  97. ******************************************************************************/
  98. int
  99. main (int argc, char **argv)
  100. {
  101. int found = 0, result = STATE_UNKNOWN;
  102. char input_buffer[MAX_INPUT_BUFFER];
  103. if (process_arguments (argc, argv) == ERROR)
  104. usage ("Could not parse arguments\n");
  105. /* Set signal handling and alarm */
  106. if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR)
  107. terminate (STATE_UNKNOWN, "Cannot catch SIGALRM");
  108. (void) alarm ((unsigned) timeout_interval);
  109. child_process = spopen (command_line);
  110. if (child_process == NULL)
  111. terminate (STATE_UNKNOWN, "Could not open pipe: %s\n", command_line);
  112. child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
  113. if (child_stderr == NULL) {
  114. printf ("Could not open stderr for %s\n", command_line);
  115. }
  116. while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
  117. found++;
  118. if (strchr (input_buffer, '\n')) {
  119. input_buffer[strcspn (input_buffer, "\n")] = 0;
  120. printf ("%s\n", input_buffer);
  121. }
  122. else {
  123. printf ("%s\n", input_buffer);
  124. }
  125. }
  126. if (!found)
  127. terminate (STATE_UNKNOWN,\
  128. "%s problem - No data recieved from host\nCMD: %s\n",\
  129. argv[0], command_line);
  130. /* close the pipe */
  131. result = spclose (child_process);
  132. /* WARNING if output found on stderr */
  133. if (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
  134. result = max_state (result, STATE_WARNING);
  135. /* close stderr */
  136. (void) fclose (child_stderr);
  137. if (result == STATE_OK)
  138. exit (STATE_CRITICAL);
  139. else if (result == STATE_CRITICAL)
  140. exit (EXIT_SUCCESS);
  141. else
  142. exit (result);
  143. }
  144. void
  145. print_help (void)
  146. {
  147. print_revision (progname, REVISION);
  148. printf
  149. ("Copyright (c) %s %s <%s>\n\n%s\n",
  150. COPYRIGHT, AUTHOR, EMAIL, SUMMARY);
  151. print_usage ();
  152. printf
  153. ("\nOptions:\n" LONGOPTIONS "\n" "Examples:\n" EXAMPLES "\n"
  154. DESCRIPTION "\n", DEFAULT_TIMEOUT);
  155. support ();
  156. }
  157. void
  158. print_usage (void)
  159. {
  160. printf ("Usage:\n" " %s %s\n"
  161. " %s (-h | --help) for detailed help\n"
  162. " %s (-V | --version) for version information\n",
  163. progname, OPTIONS, progname, progname);
  164. }
  165. /******************************************************************************
  166. @@-
  167. <sect3>
  168. <title>process_arguments</title>
  169. <para>This function parses the command line into the needed
  170. variables.</para>
  171. <para>Aside from the standard 'help' and 'version' options, there
  172. is a only a 'timeout' option.No validation is currently done.</para>
  173. </sect3>
  174. -@@
  175. ******************************************************************************/
  176. /* process command-line arguments */
  177. int
  178. process_arguments (int argc, char **argv)
  179. {
  180. int c;
  181. int option_index = 0;
  182. static struct option long_options[] = {
  183. {"help", no_argument, 0, 'h'},
  184. {"version", no_argument, 0, 'V'},
  185. {"timeout", required_argument, 0, 't'},
  186. {0, 0, 0, 0}
  187. };
  188. while (1) {
  189. c = getopt_long (argc, argv, "+hVt:",
  190. long_options, &option_index);
  191. if (c == -1 || c == EOF)
  192. break;
  193. switch (c) {
  194. case '?': /* help */
  195. usage3 ("Unknown argument", optopt);
  196. case 'h': /* help */
  197. print_help ();
  198. exit (EXIT_SUCCESS);
  199. case 'V': /* version */
  200. print_revision (progname, REVISION);
  201. exit (EXIT_SUCCESS);
  202. case 't': /* timeout period */
  203. if (!is_integer (optarg))
  204. usage2 ("Timeout Interval must be an integer", optarg);
  205. timeout_interval = atoi (optarg);
  206. break;
  207. }
  208. }
  209. asprintf (&command_line, "%s", argv[optind]);
  210. for (c = optind+1; c < argc; c++) {
  211. asprintf (&command_line, "%s %s", command_line, argv[c]);
  212. }
  213. return validate_arguments ();
  214. }
  215. /******************************************************************************
  216. @@-
  217. <sect3>
  218. <title>validate_arguments</title>
  219. <para>No validation is currently done.</para>
  220. </sect3>
  221. -@@
  222. ******************************************************************************/
  223. int
  224. validate_arguments ()
  225. {
  226. if (command_line == NULL)
  227. return ERROR;
  228. return STATE_OK;
  229. }
  230. /******************************************************************************
  231. @@-
  232. </sect2>
  233. </sect1>
  234. </article>
  235. -@@
  236. ******************************************************************************/