Back to index

nagios-plugins  1.4.16
Defines | Functions | Variables
popen.c File Reference
#include "common.h"
#include <stdarg.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/resource.h>

Go to the source code of this file.

Defines

#define WEXITSTATUS(stat_val)   ((unsigned)(stat_val) >> 8)
#define WIFEXITED(stat_val)   (((stat_val) & 255) == 0)
#define min(a, b)   ((a) < (b) ? (a) : (b))
#define max(a, b)   ((a) > (b) ? (a) : (b))
#define OPEN_MAX_GUESS   256 /* if OPEN_MAX is indeterminate */
#define MAXLINE   2048

Functions

FILE * spopen (const char *)
int spclose (FILE *)
RETSIGTYPE popen_timeout_alarm_handler (int)
int open_max (void)
static void err_sys (const char *,...)
char * rtrim (char *str, const char *tok)

Variables

int timeout_interval
pid_t * childpid
int * child_stderr_array
FILE * child_process
static int openmax = 0

Define Documentation

#define max (   a,
 
)    ((a) > (b) ? (a) : (b))

Definition at line 80 of file popen.c.

#define MAXLINE   2048

Definition at line 333 of file popen.c.

#define min (   a,
 
)    ((a) < (b) ? (a) : (b))

Definition at line 79 of file popen.c.

#define OPEN_MAX_GUESS   256 /* if OPEN_MAX is indeterminate */

Definition at line 282 of file popen.c.

#define WEXITSTATUS (   stat_val)    ((unsigned)(stat_val) >> 8)

Definition at line 67 of file popen.c.

#define WIFEXITED (   stat_val)    (((stat_val) & 255) == 0)

Definition at line 71 of file popen.c.


Function Documentation

static void err_sys ( const char *  fmt,
  ... 
) [static]

Definition at line 82 of file popen.c.

{
       char *env[2];
       char *cmd = NULL;
       char **argv = NULL;
       char *str, *tmp;
       int argc;

       int i = 0, pfd[2], pfderr[2];
       pid_t pid;

#ifdef        RLIMIT_CORE
       /* do not leave core files */
       struct rlimit limit;
       getrlimit (RLIMIT_CORE, &limit);
       limit.rlim_cur = 0;
       setrlimit (RLIMIT_CORE, &limit);
#endif

       env[0] = strdup("LC_ALL=C");
       env[1] = '\0';

       /* if no command was passed, return with no error */
       if (cmdstring == NULL)
              return (NULL);

       /* make copy of command string so strtok() doesn't silently modify it */
       /* (the calling program may want to access it later) */
       cmd = malloc (strlen (cmdstring) + 1);
       if (cmd == NULL)
              return NULL;
       strcpy (cmd, cmdstring);

       /* This is not a shell, so we don't handle "???" */
       if (strstr (cmdstring, "\""))
              return NULL;

       /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
       if (strstr (cmdstring, " ' ") || strstr (cmdstring, "'''"))
              return NULL;

       /* 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 ("%s\n", _("Could not malloc argv array in popen()"));
              return NULL;
       }

       /* loop to get arguments to command */
       while (cmd) {
              str = cmd;
              str += strspn (str, " \t\r\n");    /* trim any leading whitespace */

              if (i >= argc - 2) {
                     printf ("%s\n",_("CRITICAL - You need more args!!!"));
                     return (NULL);
              }

              if (strstr (str, "'") == str) {    /* handle SIMPLE quoted strings */
                     str++;
                     if (!strstr (str, "'"))
                            return NULL;                                     /* balanced? */
                     cmd = 1 + strstr (str, "'");
                     str[strcspn (str, "'")] = 0;
              }
              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;
                     }
                     else {
                            cmd = NULL;
                     }
              }

              if (cmd && strlen (cmd) == strspn (cmd, " \t\r\n"))
                     cmd = NULL;

              argv[i++] = str;

       }
       argv[i] = NULL;

       if (childpid == NULL) {                          /* first time through */
              maxfd = open_max ();                      /* allocate zeroed out array for child pids */
              if ((childpid = calloc ((size_t)maxfd, sizeof (pid_t))) == NULL)
                     return (NULL);
       }

       if (child_stderr_array == NULL) {  /* first time through */
              maxfd = open_max ();                      /* allocate zeroed out array for child pids */
              if ((child_stderr_array = calloc ((size_t)maxfd, sizeof (int))) == NULL)
                     return (NULL);
       }

       if (pipe (pfd) < 0)
              return (NULL);                                                 /* errno set by pipe() */

       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 */
              close (pfd[0]);
              if (pfd[1] != STDOUT_FILENO) {
                     dup2 (pfd[1], STDOUT_FILENO);
                     close (pfd[1]);
              }
              close (pfderr[0]);
              if (pfderr[1] != STDERR_FILENO) {
                     dup2 (pfderr[1], STDERR_FILENO);
                     close (pfderr[1]);
              }
              /* close all descriptors in childpid[] */
              for (i = 0; i < maxfd; i++)
                     if (childpid[i] > 0)
                            close (i);

              execve (argv[0], argv, env);
              _exit (0);
       }

       close (pfd[1]);                                                       /* parent */
       if ((child_process = fdopen (pfd[0], "r")) == NULL)
              return (NULL);
       close (pfderr[1]);

       childpid[fileno (child_process)] = pid;   /* remember child pid for this fd */
       child_stderr_array[fileno (child_process)] = pfderr[0]; /* remember STDERR */
       return (child_process);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int open_max ( void  )

Definition at line 315 of file popen.c.

{
       if (openmax == 0) {                                     /* first time through */
              errno = 0;
              if ((openmax = sysconf (_SC_OPEN_MAX)) < 0) {
                     if (errno == 0)
                            openmax = OPEN_MAX_GUESS;   /* it's indeterminate */
                     else
                            err_sys (_("sysconf error for _SC_OPEN_MAX"));
              }
       }
       return (openmax);
}

Here is the call graph for this function:

Here is the caller graph for this function:

RETSIGTYPE popen_timeout_alarm_handler ( int  signo)

Definition at line 295 of file popen.c.

{
       int fh;
       if (signo == SIGALRM) {
              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);
       }
}

Here is the caller graph for this function:

char* rtrim ( char *  str,
const char *  tok 
)

Definition at line 358 of file popen.c.

{
       int i = 0;
       int j = sizeof (str);

       while (str != NULL && i < j) {
              if (*(str + i) == *tok) {
                     sprintf (str + i, "%s", "\0");
                     return str;
              }
              i++;
       }
       return str;
}
int spclose ( FILE *  fp)

Definition at line 246 of file popen.c.

{
       int fd, status;
       pid_t pid;

       if (childpid == NULL)
              return (1);                                                    /* popen() has never been called */

       fd = fileno (fp);
       if ((pid = childpid[fd]) == 0)
              return (1);                                                    /* fp wasn't opened by popen() */

       childpid[fd] = 0;
       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() */

       if (WIFEXITED (status))
              return (WEXITSTATUS (status));     /* return child's termination status */

       return (1);
}

Here is the caller graph for this function:

FILE* spopen ( const char *  )

Variable Documentation

Definition at line 13 of file popen.h.

Definition at line 12 of file popen.h.

pid_t* childpid

Definition at line 11 of file popen.h.

int openmax = 0 [static]

Definition at line 279 of file popen.c.

Definition at line 35 of file check_hltherm.c.