diff options
Diffstat (limited to 'src/popen.c')
-rw-r--r-- | src/popen.c | 47 |
1 files changed, 39 insertions, 8 deletions
diff --git a/src/popen.c b/src/popen.c index 27be61774..eda1c05b9 100644 --- a/src/popen.c +++ b/src/popen.c @@ -43,7 +43,7 @@ static void mypopen_del(FILE *fp) { #define PIPE_READ 0 #define PIPE_WRITE 1 -FILE *mypopen(const char *command, pid_t *pidptr) +FILE *mypopen(const char *command, volatile pid_t *pidptr) { int pipefd[2]; @@ -113,6 +113,42 @@ FILE *mypopen(const char *command, pid_t *pidptr) exit(1); } +FILE *mypopene(const char *command, volatile pid_t *pidptr, char **env) { + int pipefd[2]; + + if(pipe(pipefd) == -1) + return NULL; + + int pid = fork(); + if(pid == -1) { + close(pipefd[PIPE_READ]); + close(pipefd[PIPE_WRITE]); + return NULL; + } + if(pid != 0) { + // the parent + *pidptr = pid; + close(pipefd[PIPE_WRITE]); + FILE *fp = fdopen(pipefd[PIPE_READ], "r"); + return(fp); + } + // the child + + // close all files + int i; + for(i = (int) (sysconf(_SC_OPEN_MAX) - 1); i > 0; i--) + if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i); + + // move the pipe to stdout + if(pipefd[PIPE_WRITE] != STDOUT_FILENO) { + dup2(pipefd[PIPE_WRITE], STDOUT_FILENO); + close(pipefd[PIPE_WRITE]); + } + + execle("/bin/sh", "sh", "-c", command, NULL, env); + exit(1); +} + int mypclose(FILE *fp, pid_t pid) { debug(D_EXIT, "Request to mypclose() on pid %d", pid); @@ -126,6 +162,8 @@ int mypclose(FILE *fp, pid_t pid) { // close the pipe file pointer fclose(fp); + errno = 0; + siginfo_t info; if(waitid(P_PID, (id_t) pid, &info, WEXITED) != -1) { switch(info.si_code) { @@ -133,37 +171,30 @@ int mypclose(FILE *fp, pid_t pid) { if(info.si_status) error("child pid %d exited with code %d.", info.si_pid, info.si_status); return(info.si_status); - break; case CLD_KILLED: error("child pid %d killed by signal %d.", info.si_pid, info.si_status); return(-1); - break; case CLD_DUMPED: error("child pid %d core dumped by signal %d.", info.si_pid, info.si_status); return(-2); - break; case CLD_STOPPED: error("child pid %d stopped by signal %d.", info.si_pid, info.si_status); return(0); - break; case CLD_TRAPPED: error("child pid %d trapped by signal %d.", info.si_pid, info.si_status); return(-4); - break; case CLD_CONTINUED: error("child pid %d continued by signal %d.", info.si_pid, info.si_status); return(0); - break; default: error("child pid %d gave us a SIGCHLD with code %d and status %d.", info.si_pid, info.si_code, info.si_status); return(-5); - break; } } else |