spawn: handle custom stdin/stdout/stderr fds being the same

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.
This commit is contained in:
Daniel Eklöf 2021-02-24 21:29:34 +01:00
parent b1385f6439
commit 9cb8f6e3b7
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

13
spawn.c
View file

@ -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)
{