From 58b4741d3d8eb50bd265e0aa5603923c1e3c04c4 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Sun, 13 Nov 2016 15:08:33 -0500 Subject: Redirect stdin from /dev/null for -ok and -okdir. --- Makefile | 2 +- eval.c | 10 ++++++++++ main.c | 36 ++++-------------------------------- tests.sh | 12 +++++++++++- util.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ util.h | 37 +++++++++++++++++++++++++++++++++++++ 6 files changed, 113 insertions(+), 34 deletions(-) create mode 100644 util.c create mode 100644 util.h 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 #include #include @@ -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,50 +10,22 @@ *********************************************************************/ #include "bfs.h" +#include "util.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)) { + 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 * + * * + * 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 +#include +#include +#include +#include +#include + +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 * + * * + * 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 + +/** + * 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 -- cgit v1.2.3