From 99c4509d7349b0855a8401fbdb627c8eb14a8991 Mon Sep 17 00:00:00 2001 From: Johan Danielsson Date: Tue, 19 Jun 2001 23:53:23 +0000 Subject: [PATCH] rename check_status to wait_for_process, and export it; function pipe_execv similar to popen, but with more control over input and output git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@10132 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/roken/simple_exec.c | 96 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 92 insertions(+), 4 deletions(-) diff --git a/lib/roken/simple_exec.c b/lib/roken/simple_exec.c index c03e9d922..e0aa1ba08 100644 --- a/lib/roken/simple_exec.c +++ b/lib/roken/simple_exec.c @@ -64,8 +64,8 @@ RCSID("$Id$"); 128- is 128 + signal that killed subprocess */ -static int -check_status(pid_t pid) +int +wait_for_process(pid_t pid) { while(1) { int status; @@ -82,6 +82,94 @@ check_status(pid_t pid) } } +int +pipe_execv(FILE **stdin_fd, FILE **stdout_fd, FILE **stderr_fd, + const char *file, ...) +{ + int in_fd[2], out_fd[2], err_fd[2]; + pid_t pid; + va_list ap; + char **argv; + int ret; + + if(stdin_fd != NULL) + pipe(in_fd); + if(stdout_fd != NULL) + pipe(out_fd); + if(stderr_fd != NULL) + pipe(err_fd); + pid = fork(); + switch(pid) { + case 0: + va_start(ap, file); + argv = vstrcollect(&ap); + va_end(ap); + if(argv == NULL) + exit(-1); + + /* close pipes we're not interested in */ + if(stdin_fd != NULL) + close(in_fd[1]); + if(stdout_fd != NULL) + close(out_fd[0]); + if(stderr_fd != NULL) + close(err_fd[0]); + + /* pipe everything caller doesn't care about to /dev/null */ + if(stdin_fd == NULL) + in_fd[0] = open(_PATH_DEVNULL, O_RDONLY); + if(stdout_fd == NULL) + out_fd[1] = open(_PATH_DEVNULL, O_WRONLY); + if(stderr_fd == NULL) + err_fd[1] = open(_PATH_DEVNULL, O_WRONLY); + + /* move to proper descriptors */ + if(in_fd[0] != STDIN_FILENO) { + dup2(in_fd[0], STDIN_FILENO); + close(in_fd[0]); + } + if(out_fd[1] != STDOUT_FILENO) { + dup2(out_fd[1], STDOUT_FILENO); + close(out_fd[1]); + } + if(err_fd[1] != STDERR_FILENO) { + dup2(err_fd[1], STDERR_FILENO); + close(err_fd[1]); + } + + execv(file, argv); + exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); + case -1: + if(stdin_fd != NULL) { + close(in_fd[0]); + close(in_fd[1]); + } + if(stdout_fd != NULL) { + close(out_fd[0]); + close(out_fd[1]); + } + if(stderr_fd != NULL) { + close(err_fd[0]); + close(err_fd[1]); + } + return -2; + default: + if(stdin_fd != NULL) { + close(in_fd[0]); + *stdin_fd = fdopen(in_fd[1], "w"); + } + if(stdout_fd != NULL) { + close(out_fd[1]); + *stdout_fd = fdopen(out_fd[0], "r"); + } + if(stderr_fd != NULL) { + close(err_fd[1]); + *stderr_fd = fdopen(err_fd[0], "r"); + } + } + return pid; +} + int simple_execvp(const char *file, char *const args[]) { @@ -93,7 +181,7 @@ simple_execvp(const char *file, char *const args[]) execvp(file, args); exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); default: - return check_status(pid); + return wait_for_process(pid); } } @@ -109,7 +197,7 @@ simple_execve(const char *file, char *const args[], char *const envp[]) execve(file, args, envp); exit((errno == ENOENT) ? EX_NOTFOUND : EX_NOEXEC); default: - return check_status(pid); + return wait_for_process(pid); } }