diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-10-16 17:33:36 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-10-16 17:38:47 -0400 |
commit | c2e9f525239d8bd9e46b7540c23c26a26a5d66f6 (patch) | |
tree | e135d83d13a8230d202af2a422427176ad689237 /main.c | |
parent | ec8c425866a164c3e73144751a5071aaf6660664 (diff) | |
download | bfs-c2e9f525239d8bd9e46b7540c23c26a26a5d66f6.tar.xz |
main: Make sure that STD{IN,OUT,ERR}_FILENO are open.
Otherwise invocations like bfs >&- may do weird things like try to write
to directory descriptors.
Diffstat (limited to 'main.c')
-rw-r--r-- | main.c | 59 |
1 files changed, 59 insertions, 0 deletions
@@ -10,11 +10,68 @@ *********************************************************************/ #include "bfs.h" +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> #include <stdlib.h> +#include <unistd.h> +/** + * Check if a file descriptor is open. + */ +static bool is_fd_open(int fd) { + return fcntl(fd, F_GETFD) >= 0 || errno != EBADF; +} + +/** + * Ensure that a file descriptor is open. + */ +static int ensure_fd_open(int fd, int flags) { + if (is_fd_open(fd)) { + return 0; + } + + int devnull = open("/dev/null", flags); + if (devnull < 0) { + perror("open()"); + return -1; + } + + int ret = 0; + + if (devnull != fd) { + // Probably not reachable + + if (dup2(devnull, fd) < 0) { + perror("dup2()"); + ret = -1; + } + + if (close(devnull) != 0) { + perror("close()"); + ret = -1; + } + } + + return ret; +} + +/** + * bfs entry point. + */ int main(int argc, char *argv[]) { int ret = EXIT_FAILURE; + if (ensure_fd_open(STDIN_FILENO, O_WRONLY) != 0) { + goto done; + } + if (ensure_fd_open(STDOUT_FILENO, O_RDONLY) != 0) { + goto done; + } + if (ensure_fd_open(STDERR_FILENO, O_RDONLY) != 0) { + goto done; + } + struct cmdline *cmdline = parse_cmdline(argc, argv); if (cmdline) { if (eval_cmdline(cmdline) == 0) { @@ -23,5 +80,7 @@ int main(int argc, char *argv[]) { } free_cmdline(cmdline); + +done: return ret; } |