From 9cb8f6e3b7549b1f279f6de34a97c0e568f4d148 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 24 Feb 2021 21:29:34 +0100 Subject: [PATCH] spawn: handle custom stdin/stdout/stderr fds being the same MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the caller to pass the same FD (for example, a single /dev/null FD) to spawn(). All we need to do to handle this correctly is ensure we don’t try to close the same FD multiple times. --- spawn.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/spawn.c b/spawn.c index 3f8a8fd3..d200ed12 100644 --- a/spawn.c +++ b/spawn.c @@ -45,9 +45,16 @@ spawn(struct reaper *reaper, const char *cwd, char *const argv[], _exit(errno_copy); } - if ((stdin_fd >= 0 && (dup2(stdin_fd, STDIN_FILENO) < 0 || close(stdin_fd) < 0)) || - (stdout_fd >= 0 && (dup2(stdout_fd, STDOUT_FILENO) < 0 || close(stdout_fd) < 0)) || - (stderr_fd >= 0 && (dup2(stderr_fd, STDERR_FILENO) < 0 || close(stderr_fd) < 0)) || + bool close_stderr = stderr_fd >= 0; + bool close_stdout = stdout_fd >= 0 && stdout_fd != stderr_fd; + bool close_stdin = stdin_fd >= 0 && stdin_fd != stdout_fd && stdin_fd != stderr_fd; + + if ((stdin_fd >= 0 && (dup2(stdin_fd, STDIN_FILENO) < 0 + || (close_stdin && close(stdin_fd) < 0))) || + (stdout_fd >= 0 && (dup2(stdout_fd, STDOUT_FILENO) < 0 + || (close_stdout && close(stdout_fd) < 0))) || + (stderr_fd >= 0 && (dup2(stderr_fd, STDERR_FILENO) < 0 + || (close_stderr && close(stderr_fd) < 0))) || (cwd != NULL && chdir(cwd) < 0) || execvp(argv[0], argv) < 0) {