From c2e9f525239d8bd9e46b7540c23c26a26a5d66f6 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 16 Oct 2016 17:33:36 -0400 Subject: 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. --- main.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'main.c') diff --git a/main.c b/main.c index 55e07e2..2a32b3a 100644 --- a/main.c +++ b/main.c @@ -10,11 +10,68 @@ *********************************************************************/ #include "bfs.h" +#include +#include +#include #include +#include +/** + * 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; } -- cgit v1.2.3