summaryrefslogtreecommitdiffstats
path: root/src/popen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/popen.c')
-rw-r--r--src/popen.c47
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