diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2016-11-13 15:08:33 -0500 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2016-11-13 15:44:48 -0500 |
commit | 58b4741d3d8eb50bd265e0aa5603923c1e3c04c4 (patch) | |
tree | 8ac8a78995df61d92359e33f5fcbc9a8299e9546 | |
parent | 1c5168342e5248983d3a7929abaebe16ca3640a3 (diff) | |
download | bfs-58b4741d3d8eb50bd265e0aa5603923c1e3c04c4.tar.xz |
Redirect stdin from /dev/null for -ok and -okdir.
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | eval.c | 10 | ||||
-rw-r--r-- | main.c | 36 | ||||
-rwxr-xr-x | tests.sh | 12 | ||||
-rw-r--r-- | util.c | 50 | ||||
-rw-r--r-- | util.h | 37 |
6 files changed, 113 insertions, 34 deletions
@@ -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 @@ -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); } @@ -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; } /** @@ -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 @@ -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; +} @@ -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 |