summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2016-11-13 15:08:33 -0500
committerTavian Barnes <tavianator@tavianator.com>2016-11-13 15:44:48 -0500
commit58b4741d3d8eb50bd265e0aa5603923c1e3c04c4 (patch)
tree8ac8a78995df61d92359e33f5fcbc9a8299e9546
parent1c5168342e5248983d3a7929abaebe16ca3640a3 (diff)
downloadbfs-58b4741d3d8eb50bd265e0aa5603923c1e3c04c4.tar.xz
Redirect stdin from /dev/null for -ok and -okdir.
-rw-r--r--Makefile2
-rw-r--r--eval.c10
-rw-r--r--main.c36
-rwxr-xr-xtests.sh12
-rw-r--r--util.c50
-rw-r--r--util.h37
6 files changed, 113 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 86bf47f..5704823 100644
--- a/Makefile
+++ b/Makefile
@@ -34,7 +34,7 @@ ALL_LDFLAGS = $(ALL_CFLAGS) $(LDFLAGS)
all: bfs
-bfs: bftw.o color.o dstring.o eval.o main.o parse.o typo.o
+bfs: bftw.o color.o dstring.o eval.o main.o parse.o typo.o util.o
$(CC) $(ALL_LDFLAGS) $^ -o $@
release: CFLAGS := -O3 -flto -Wall -DNDEBUG
diff --git a/eval.c b/eval.c
index 54d9a7c..34343d4 100644
--- a/eval.c
+++ b/eval.c
@@ -12,6 +12,7 @@
#include "bfs.h"
#include "bftw.h"
#include "dstring.h"
+#include "util.h"
#include <assert.h>
#include <dirent.h>
#include <errno.h>
@@ -447,8 +448,17 @@ bool eval_exec(const struct expr *expr, struct eval_state *state) {
exec_chdir(ftwbuf);
}
+ if (expr->exec_flags & EXEC_CONFIRM) {
+ if (redirect(STDIN_FILENO, "/dev/null", O_RDONLY) < 0) {
+ perror("redirect()");
+ goto exit;
+ }
+ }
+
execvp(argv[0], argv);
perror("execvp()");
+
+ exit:
_Exit(EXIT_FAILURE);
}
diff --git a/main.c b/main.c
index 03c5020..7471156 100644
--- a/main.c
+++ b/main.c
@@ -10,6 +10,7 @@
*********************************************************************/
#include "bfs.h"
+#include "util.h"
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -17,43 +18,14 @@
#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)) {
+ if (isopen(fd)) {
return 0;
+ } else {
+ return redirect(fd, "/dev/null", flags);
}
-
- 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;
}
/**
diff --git a/tests.sh b/tests.sh
index 51f891c..87a0ea1 100755
--- a/tests.sh
+++ b/tests.sh
@@ -434,7 +434,17 @@ function test_0078() {
! "$BFS" "$perms" -perm +777 2>/dev/null
}
-for i in {1..78}; do
+function test_0079() {
+ # -ok should close stdin for the executed command
+ yes | "$BFS" "$basic" -ok cat ';' 2>/dev/null
+}
+
+function test_0080() {
+ # -okdir should close stdin for the executed command
+ yes | "$BFS" "$basic" -okdir cat ';' 2>/dev/null
+}
+
+for i in {1..80}; do
test="test_$(printf '%04d' $i)"
if [ -t 1 ]; then
diff --git a/util.c b/util.c
new file mode 100644
index 0000000..e0f6177
--- /dev/null
+++ b/util.c
@@ -0,0 +1,50 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2016 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
+#include "util.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+bool isopen(int fd) {
+ return fcntl(fd, F_GETFD) >= 0 || errno != EBADF;
+}
+
+int redirect(int fd, const char *path, int flags, ...) {
+ close(fd);
+
+ mode_t mode = 0;
+ if (flags & O_CREAT) {
+ va_list args;
+ va_start(args, flags);
+
+ // Use int rather than mode_t, because va_arg must receive a
+ // fully-promoted type
+ mode = va_arg(args, int);
+
+ va_end(args);
+ }
+
+ int ret = open(path, flags, mode);
+
+ if (ret >= 0 && ret != fd) {
+ int other = ret;
+ ret = dup2(other, fd);
+ if (close(other) != 0) {
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
diff --git a/util.h b/util.h
new file mode 100644
index 0000000..c3b3dbe
--- /dev/null
+++ b/util.h
@@ -0,0 +1,37 @@
+/*********************************************************************
+ * bfs *
+ * Copyright (C) 2016 Tavian Barnes <tavianator@tavianator.com> *
+ * *
+ * This program is free software. It comes without any warranty, to *
+ * the extent permitted by applicable law. You can redistribute it *
+ * and/or modify it under the terms of the Do What The Fuck You Want *
+ * To Public License, Version 2, as published by Sam Hocevar. See *
+ * the COPYING file or http://www.wtfpl.net/ for more details. *
+ *********************************************************************/
+
+#ifndef BFS_UTIL_H
+#define BFS_UTIL_H
+
+#include <stdbool.h>
+
+/**
+ * Check if a file descriptor is open.
+ */
+bool isopen(int fd);
+
+/**
+ * Open a file and redirect it to a particular descriptor.
+ *
+ * @param fd
+ * The file descriptor to redirect.
+ * @param path
+ * The path to open.
+ * @param flags
+ * The flags passed to open().
+ * @param mode
+ * The mode passed to open() (optional).
+ * @return fd on success, -1 on failure.
+ */
+int redirect(int fd, const char *path, int flags, ...);
+
+#endif // BFS_UTIL_H