summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-10-16 17:33:36 -0400
committerTavian Barnes <tavianator@tavianator.com>2016-10-16 17:38:47 -0400
commitc2e9f525239d8bd9e46b7540c23c26a26a5d66f6 (patch)
treee135d83d13a8230d202af2a422427176ad689237
parentec8c425866a164c3e73144751a5071aaf6660664 (diff)
downloadbfs-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.
-rw-r--r--main.c59
1 files changed, 59 insertions, 0 deletions
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 <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;
}