Code

Removed debug line
[nagiosplug.git] / plugins / popen.c
index 062cf274a476fe8a775c2c562c777747a046f9f3..45d2a3dc937e19345e4da5605465660f683c6673 100644 (file)
@@ -1,13 +1,21 @@
-/******************************************************************************
- * popen.c
+/****************************************************************************
+ *
+ * Nagios plugins popen
+ *
+ * License: GPL
+ * Copyright (c) 2005 nagios-plugins team
+ *
+ * Last Modified: $Date$
+ *
+ * Description:
  *
  * A safe alternative to popen
  * 
  * Provides spopen and spclose
-
-FILE * spopen(const char *);
-int spclose(FILE *);
-
+ *
+ * FILE * spopen(const char *);
+ * int spclose(FILE *);
+ *
  *
  * Code taken with liitle modification from "Advanced Programming for the Unix
  * Environment" by W. Richard Stevens
@@ -16,6 +24,22 @@ int spclose(FILE *);
  * path passed to the exec'd program are esstially empty. (popen create a shell
  * and passes the environment to it).
  *
+ * License Information:
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
+ *
  * $Id$
  *
  ******************************************************************************/
@@ -30,6 +54,9 @@ extern FILE *child_process;
 
 FILE *spopen (const char *);
 int spclose (FILE *);
+#ifdef REDHAT_SPOPEN_ERROR
+RETSIGTYPE popen_sigchld_handler (int);
+#endif
 RETSIGTYPE popen_timeout_alarm_handler (int);
 
 #include <stdarg.h>                                                    /* ANSI C header file */
@@ -67,13 +94,17 @@ char *pname = NULL;                                                 /* caller can set this from argv[0] */
 /*extern pid_t *childpid = NULL; *//* ptr to array allocated at run-time */
 static int maxfd;                                                              /* from our open_max(), {Prog openmax} */
 
+#ifdef REDHAT_SPOPEN_ERROR
+static volatile int childtermd = 0;
+#endif
+
 FILE *
 spopen (const char *cmdstring)
 {
        char *env[2];
        char *cmd = NULL;
        char **argv = NULL;
-       char *str;
+       char *str, *tmp;
        int argc;
 
        int i = 0, pfd[2], pfderr[2];
@@ -114,7 +145,7 @@ spopen (const char *cmdstring)
        argv = malloc (sizeof(char*)*argc);
        
        if (argv == NULL) {
-               printf (_("Could not malloc argv array in popen()\n"));
+               printf ("%s\n", _("Could not malloc argv array in popen()"));
                return NULL;
        }
 
@@ -124,7 +155,7 @@ spopen (const char *cmdstring)
                str += strspn (str, " \t\r\n"); /* trim any leading whitespace */
 
                if (i >= argc - 2) {
-                       printf (_("CRITICAL - You need more args!!!\n"));
+                       printf ("%s\n",_("CRITICAL - You need more args!!!"));
                        return (NULL);
                }
 
@@ -135,7 +166,15 @@ spopen (const char *cmdstring)
                        cmd = 1 + strstr (str, "'");
                        str[strcspn (str, "'")] = 0;
                }
-               else {
+               else if (strcspn(str,"'") < strcspn (str, " \t\r\n")) {
+                                                                               /* handle --option='foo bar' strings */
+                       tmp = str + strcspn(str, "'") + 1; 
+                       if (!strstr (tmp, "'"))
+                               return NULL;                                            /* balanced? */
+                       tmp += strcspn(tmp,"'") + 1;
+                       *tmp = 0;
+                       cmd = tmp + 1;
+               } else {
                        if (strpbrk (str, " \t\r\n")) {
                                cmd = 1 + strpbrk (str, " \t\r\n");
                                str[strcspn (str, " \t\r\n")] = 0;
@@ -171,6 +210,12 @@ spopen (const char *cmdstring)
        if (pipe (pfderr) < 0)
                return (NULL);                                                  /* errno set by pipe() */
 
+#ifdef REDHAT_SPOPEN_ERROR
+       if (signal (SIGCHLD, popen_sigchld_handler) == SIG_ERR) {
+               usage4 (_("Cannot catch SIGCHLD"));
+       }
+#endif
+
        if ((pid = fork ()) < 0)
                return (NULL);                                                  /* errno set by fork() */
        else if (pid == 0) {                                    /* child */
@@ -220,6 +265,10 @@ spclose (FILE * fp)
        if (fclose (fp) == EOF)
                return (1);
 
+#ifdef REDHAT_SPOPEN_ERROR
+       while (!childtermd);                                                            /* wait until SIGCHLD */
+#endif
+
        while (waitpid (pid, &status, 0) < 0)
                if (errno != EINTR)
                        return (1);                                                     /* error other than EINTR from waitpid() */
@@ -239,18 +288,30 @@ static int openmax = 0;
 #define        OPEN_MAX_GUESS  256                     /* if OPEN_MAX is indeterminate */
                                /* no guarantee this is adequate */
 
+#ifdef REDHAT_SPOPEN_ERROR
+RETSIGTYPE
+popen_sigchld_handler (int signo)
+{
+       if (signo == SIGCHLD)
+               childtermd = 1;
+}
+#endif
 
-void
+RETSIGTYPE
 popen_timeout_alarm_handler (int signo)
 {
        int fh;
        if (signo == SIGALRM) {
-               fh=fileno (child_process);
-               if(fh >= 0){
-                       kill (childpid[fh], SIGKILL);
-               }
-               printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
+               if (child_process != NULL) {
+                       fh=fileno (child_process);
+                       if(fh >= 0){
+                               kill (childpid[fh], SIGKILL);
+                       }
+                       printf (_("CRITICAL - Plugin timed out after %d seconds\n"),
                                                timeout_interval);
+               } else {
+                       printf ("%s\n", _("CRITICAL - popen timeout received, but no child process"));
+               }
                exit (STATE_CRITICAL);
        }
 }