diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2015-09-25 14:17:53 -0700 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2015-09-25 14:19:15 -0700 |
commit | abeaac66328f83d8962d6a5a4b9ce8712edbbaa5 (patch) | |
tree | 72ee133f395935a0ffe977f6a6f189dfb5314628 | |
parent | d591cebf4463e42569400bbcbaba5e16dcad734b (diff) |
Teach builtin_string to recognize redirections, not just pipes
Allows cases like `string split \n < file.txt` to work.
Fixes 2422
-rw-r--r-- | src/builtin_string.cpp | 2 | ||||
-rw-r--r-- | src/exec.cpp | 16 | ||||
-rw-r--r-- | src/fish_tests.cpp | 2 | ||||
-rw-r--r-- | src/io.h | 7 |
4 files changed, 21 insertions, 6 deletions
diff --git a/src/builtin_string.cpp b/src/builtin_string.cpp index 22f16fc6..a35903cb 100644 --- a/src/builtin_string.cpp +++ b/src/builtin_string.cpp @@ -54,7 +54,7 @@ static void string_unknown_option(parser_t &parser, io_streams_t &streams, const /* We read from stdin if we are the second or later process in a pipeline. */ static bool string_args_from_stdin(const io_streams_t &streams) { - return ! streams.is_first_process_in_pipeline; + return streams.stdin_is_directly_redirected; } static const wchar_t *string_get_arg_stdin(wcstring *storage, const io_streams_t &streams) diff --git a/src/exec.cpp b/src/exec.cpp index 5366e663..e4ae5104 100644 --- a/src/exec.cpp +++ b/src/exec.cpp @@ -953,11 +953,25 @@ void exec_job(parser_t &parser, job_t *j) } else { + // Determine if we have a "direct" redirection for stdin + bool stdin_is_directly_redirected; + if (p != j->first_process) + { + // We must have a pipe + stdin_is_directly_redirected = true; + } + else + { + // We are not a pipe. Check if there is a redirection local to the process that's not IO_CLOSE + const shared_ptr<const io_data_t> stdin_io = io_chain_get(p->io_chain(), STDIN_FILENO); + stdin_is_directly_redirected = stdin_io && stdin_io->io_mode != IO_CLOSE; + } + builtin_io_streams.reset(new io_streams_t()); builtin_io_streams->stdin_fd = local_builtin_stdin; builtin_io_streams->out_is_redirected = has_fd(process_net_io_chain, STDOUT_FILENO); builtin_io_streams->err_is_redirected = has_fd(process_net_io_chain, STDERR_FILENO); - builtin_io_streams->is_first_process_in_pipeline = (p == j->first_process); + builtin_io_streams->stdin_is_directly_redirected = stdin_is_directly_redirected; builtin_io_streams->io_chain = &process_net_io_chain; diff --git a/src/fish_tests.cpp b/src/fish_tests.cpp index 1b71411c..889dfbb8 100644 --- a/src/fish_tests.cpp +++ b/src/fish_tests.cpp @@ -4024,7 +4024,7 @@ static void run_one_string_test(const wchar_t **argv, int expected_rc, const wch { parser_t parser(PARSER_TYPE_GENERAL, true); io_streams_t streams; - streams.is_first_process_in_pipeline = true; // read from argv instead of stdin + streams.stdin_is_directly_redirected = false; // read from argv instead of stdin int rc = builtin_string(parser, streams, const_cast<wchar_t**>(argv)); wcstring args; for (int i = 0; argv[i] != 0; i++) @@ -288,8 +288,9 @@ struct io_streams_t // fd representing stdin. This is not closed by the destructor. int stdin_fd; - // Whether this is the first process in a pipeline - bool is_first_process_in_pipeline; + // Whether stdin is "directly redirected," meaning it is the recipient of a pipe (foo | cmd) or direct redirection (cmd < foo.txt) + // An "indirect redirection" would be e.g. begin ; cmd ; end < foo.txt + bool stdin_is_directly_redirected; // Indicates whether stdout and stderr are redirected (e.g. to a file or piped) bool out_is_redirected; @@ -298,7 +299,7 @@ struct io_streams_t // Actual IO redirections. This is only used by the source builtin. Unowned. const io_chain_t *io_chain; - io_streams_t() : stdin_fd(-1), is_first_process_in_pipeline(false), out_is_redirected(false), err_is_redirected(false), io_chain(NULL) + io_streams_t() : stdin_fd(-1), stdin_is_directly_redirected(false), out_is_redirected(false), err_is_redirected(false), io_chain(NULL) { } }; |