X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;ds=sidebyside;f=plugins%2Fpopen.c;h=716bd524042c54b99ed2f69034436a62340e28de;hb=ed9a088b37dcb8ba56d397592f4e8230a6a011e5;hp=04eb3881b328fa0e0938a5b93295f661231119db;hpb=e9ccc6b21a1152bbf150302c4a29a6df79d75bd7;p=nagiosplug.git diff --git a/plugins/popen.c b/plugins/popen.c index 04eb388..716bd52 100644 --- a/plugins/popen.c +++ b/plugins/popen.c @@ -1,24 +1,42 @@ -/****************************************************************************** - * popen.c - * - * A safe alternative to popen - * - * Provides spopen and spclose - -FILE * spopen(const char *); -int spclose(FILE *); - - * - * Code taken with liitle modification from "Advanced Programming for the Unix - * Environment" by W. Richard Stevens - * - * This is considered safe in that no shell is spawned, and the environment and - * path passed to the exec'd program are esstially empty. (popen create a shell - * and passes the environment to it). - * - * $Id$ - * - ******************************************************************************/ +/***************************************************************************** +* +* Nagios plugins popen +* +* License: GPL +* Copyright (c) 2005-2007 Nagios Plugins Development Team +* +* Description: +* +* A safe alternative to popen +* +* Provides spopen and spclose +* +* FILE * spopen(const char *); +* int spclose(FILE *); +* +* Code taken with liitle modification from "Advanced Programming for the Unix +* Environment" by W. Richard Stevens +* +* This is considered safe in that no shell is spawned, and the environment +* and path passed to the exec'd program are essentially empty. (popen create +* a shell and passes the environment to it). +* +* +* 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 3 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, see . +* +* +*****************************************************************************/ #include "common.h" @@ -30,6 +48,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 /* ANSI C header file */ @@ -67,13 +88,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]; @@ -112,9 +137,9 @@ spopen (const char *cmdstring) /* there cannot be more args than characters */ argc = strlen (cmdstring) + 1; /* add 1 for NULL termination */ 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 +149,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 +160,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 +204,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 +259,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,14 +282,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) { - kill (childpid[fileno (child_process)], 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); } }