void _popen_noshell_child_process( /* We need the pointer *arg_ptr only to free whatever we reference if exec() fails and we were fork()'ed (thus memory was copied), * not clone()'d */ struct popen_noshell_clone_arg *arg_ptr, /* NULL if we were called by pure fork() (not because of Valgrind) */ int pipefd_0, int pipefd_1, int read_pipe, int ignore_stderr, const char *file, const char * const *argv) { int closed_child_fd; int closed_pipe_fd; int dupped_child_fd; int pipefd[2] = {pipefd_0, pipefd_1}; if (ignore_stderr) { /* ignore STDERR completely? */ if (popen_noshell_reopen_fd_to_dev_null(STDERR_FILENO) != 0) _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", STDERR_FILENO); } if (read_pipe) { closed_child_fd = STDIN_FILENO; /* re-open STDIN to /dev/null */ closed_pipe_fd = 0; /* close read end of pipe */ dupped_child_fd = STDOUT_FILENO; /* dup the other pipe end to STDOUT */ } else { closed_child_fd = STDOUT_FILENO; /* ignore STDOUT completely */ closed_pipe_fd = 1; /* close write end of pipe */ dupped_child_fd = STDIN_FILENO; /* dup the other pipe end to STDIN */ } if (popen_noshell_reopen_fd_to_dev_null(closed_child_fd) != 0) { _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", closed_child_fd); } if (_popen_noshell_close_and_dup(pipefd, closed_pipe_fd, dupped_child_fd) != 0) { _ERR(255, "_popen_noshell_close_and_dup(%d ,%d)", closed_pipe_fd, dupped_child_fd); } execvp(file, (char * const *)argv); /* if we are here, exec() failed */ warn("exec(\"%s\") inside the child", file); #ifdef POPEN_NOSHELL_VALGRIND_DEBUG if (arg_ptr) { /* not NULL if we were called by clone() */ /* but Valgrind does not support clone(), so we were actually called by fork(), thus memory was copied... */ /* free this copied memory; if it was not Valgrind, this memory would have been shared and would belong to the parent! */ _pclose_noshell_free_clone_arg_memory(arg_ptr); } #endif if (fflush(stdout) != 0) _ERR(255, "fflush(stdout)"); if (fflush(stderr) != 0) _ERR(255, "fflush(stderr)"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); _exit(255); // call _exit() and not exit(), or you'll have troubles in C++ }
static void popen_noshell_child_process( int pipefd_0, int pipefd_1, int read_pipe, int ignore_stderr, const char *file, const char * const *argv) { int closed_child_fd; int closed_pipe_fd; int dupped_child_fd; int pipefd[2] = {pipefd_0, pipefd_1}; if (ignore_stderr) { /* ignore STDERR completely? */ if (popen_noshell_reopen_fd_to_dev_null(STDERR_FILENO) != 0) _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", STDERR_FILENO); } if (read_pipe) { closed_child_fd = STDIN_FILENO; /* re-open STDIN to /dev/null */ closed_pipe_fd = 0; /* close read end of pipe */ dupped_child_fd = STDOUT_FILENO; /* dup the other pipe end to STDOUT */ } else { closed_child_fd = STDOUT_FILENO; /* ignore STDOUT completely */ closed_pipe_fd = 1; /* close write end of pipe */ dupped_child_fd = STDIN_FILENO; /* dup the other pipe end to STDIN */ } if (popen_noshell_reopen_fd_to_dev_null(closed_child_fd) != 0) { _ERR(255, "popen_noshell_reopen_fd_to_dev_null(%d)", closed_child_fd); } if (popen_noshell_close_and_dup(pipefd, closed_pipe_fd, dupped_child_fd) != 0) { _ERR(255, "popen_noshell_close_and_dup(%d ,%d)", closed_pipe_fd, dupped_child_fd); } execvp(file, (char * const *)argv); /* if we are here, exec() failed */ warn("exec(\"%s\") inside the child", file); if (fflush(stdout) != 0) _ERR(255, "fflush(stdout)"); if (fflush(stderr) != 0) _ERR(255, "fflush(stderr)"); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); _exit(255); // call _exit() and not exit(), or you'll have troubles in C++ }