From dcee8dfbf94b90712defb982d4a5c88f4a7c51ae Mon Sep 17 00:00:00 2001 From: Frank Benkstein Date: Tue, 2 Oct 2007 21:30:15 +0200 Subject: [PATCH] src/process.{c,h}: first implementation of create_child --- src/process.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/process.h | 4 +-- 2 files changed, 115 insertions(+), 2 deletions(-) diff --git a/src/process.c b/src/process.c index d61c471..94c6faf 100644 --- a/src/process.c +++ b/src/process.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "process.h" @@ -131,7 +132,119 @@ void close_all_fds(void) } } +static int open_devnull(void) +{ + static int devnull_fd = -1; + + if (devnull_fd < 0) + devnull_fd = open("/dev/null", O_RDWR); + + return devnull_fd; +} + bool create_child(struct child_process *child) { + int stdin_pipe[2]; + int stdout_pipe[2]; + int stderr_pipe[3]; + + if (child->stdin_fd == REDIRECT_PIPE) { + if (pipe(stdin_pipe) < 0) + return false; + } + + if (child->stdout_fd == REDIRECT_PIPE) { + if (pipe(stdout_pipe) < 0) + goto stdout_pipe_failed; + } + + if (child->stderr_fd == REDIRECT_PIPE) { + if (pipe(stderr_pipe) < 0) + goto stderr_pipe_failed; + } + + child->pid = fork(); + + if (child->pid == 0) { + /* Child. */ + if (child->stdin_fd == REDIRECT_PIPE) + (void) dup2(STDIN_FILENO, stdin_pipe[0]); + else if (child->stdin_fd == REDIRECT_DEV_NULL) + (void) dup2(STDIN_FILENO, open_devnull()); + else if (child->stdin_fd != NO_REDIRECT) + (void) dup2(STDIN_FILENO, child->stdin_fd); + + if (child->stdout_fd == REDIRECT_PIPE) + (void) dup2(STDIN_FILENO, stdout_pipe[1]); + else if (child->stdout_fd == REDIRECT_DEV_NULL) + (void) dup2(STDIN_FILENO, open_devnull()); + else if (child->stdout_fd != NO_REDIRECT) + (void) dup2(STDIN_FILENO, child->stdout_fd); + + if (child->stderr_fd == REDIRECT_PIPE) + (void) dup2(STDIN_FILENO, stderr_pipe[1]); + else if (child->stderr_fd == REDIRECT_DEV_NULL) + (void) dup2(STDIN_FILENO, open_devnull()); + else if (child->stderr_fd != NO_REDIRECT) + (void) dup2(STDIN_FILENO, child->stderr_fd); + + (void) close_all_fds(); + + (void) setgid(getgid()); + (void) setuid(getuid()); + + if (child->function != NULL) { + _exit(child->function(child->argument)); + } else { + execv(child->path, (char *const*)child->argv); + } + + _exit(1); + } + + if (child->pid < 0) + goto fork_failed; + + if (child->stdin_fd == REDIRECT_PIPE) { + /* Write end. */ + child->stdin_fd = stdin_pipe[1]; + /* Read end. */ + (void) close(stdin_pipe[0]); + } + + if (child->stdout_fd == REDIRECT_PIPE) { + /* Read end. */ + child->stdout_fd = stdout_pipe[0]; + /* Write end. */ + (void) close(stdout_pipe[1]); + } + + if (child->stderr_fd == REDIRECT_PIPE) { + /* Read end. */ + child->stderr_fd = stderr_pipe[0]; + /* Write end. */ + (void) close(stderr_pipe[1]); + } + + return true; + +fork_failed: + if (child->stderr_fd == REDIRECT_PIPE) { + (void) close(stderr_pipe[0]); + (void) close(stderr_pipe[1]); + } + +stderr_pipe_failed: + if (child->stdout_fd == REDIRECT_PIPE) { + (void) close(stdout_pipe[0]); + (void) close(stdout_pipe[1]); + } + +stdout_pipe_failed: + if (child->stdin_fd == REDIRECT_PIPE) { + (void) close(stdin_pipe[0]); + (void) close(stdin_pipe[1]); + } + return false; } diff --git a/src/process.h b/src/process.h index e59144a..f741517 100644 --- a/src/process.h +++ b/src/process.h @@ -32,13 +32,13 @@ void close_all_fds(void); struct child_process { /* Function that will be run in the child. */ - void (*function)(void *argument); + int (*function)(void *argument); /* Argument for the function. */ void *argument; /* First argument to execv. */ const char *path; /* Second argument to execv. */ - const char **argv; + const char *const *argv; /* The child's stdin. */ int stdin_fd; /* The child's stdout. */ -- 2.11.4.GIT