From 7b6780f712abc45637bf0a049a6b7b2ec233172f Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Wed, 21 Aug 2013 13:46:11 -0700 Subject: [PATCH] Put read pipe last so that eval works again. Addresses https://github.com/fish-shell/fish-shell/issues/966 --- exec.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/exec.cpp b/exec.cpp index 85f73af62..dbfb66669 100644 --- a/exec.cpp +++ b/exec.cpp @@ -789,20 +789,19 @@ void exec_job(parser_t &parser, job_t *j) echo alpha | cat < beta.txt - Should cat output alpha or beta? bash and ksh output 'beta', tcsh gets it right and complains about ambiguity, and zsh outputs both (!). No shells appear to output 'alpha', so we match bash here. That means putting the pipe first, so that it gets trumped by the file redirection. + Should cat output alpha or beta? bash and ksh output 'beta', tcsh gets it right and complains about ambiguity, and zsh outputs both (!). No shells appear to output 'alpha', so we match bash here. That would mean putting the pipe first, so that it gets trumped by the file redirection. + + However, eval does this: + + echo "begin; $argv "\n" ;end eval2_inner <&3 3<&-" | source 3<&0 + + which depends on the redirection being evaluated before the pipe. So the write end of the pipe comes first, the read pipe of the pipe comes last. See issue #966. */ shared_ptr pipe_write; shared_ptr pipe_read; - if (p != j->first_process) - { - pipe_read.reset(new io_pipe_t(p->pipe_read_fd, true)); - /* Record the current read in pipe_read */ - pipe_read->pipe_fd[0] = pipe_current_read; - process_net_io_chain.push_back(pipe_read); - } - + /* Write pipe goes first */ if (p->next) { pipe_write.reset(new io_pipe_t(p->pipe_write_fd, false)); @@ -810,8 +809,18 @@ void exec_job(parser_t &parser, job_t *j) } - /* Now that we've added our pipes, add the rest of the IO redirections associated with that process */ + /* The explicit IO redirections associated with the process */ process_net_io_chain.append(p->io_chain()); + + /* Read pipe goes last */ + if (p != j->first_process) + { + pipe_read.reset(new io_pipe_t(p->pipe_read_fd, true)); + /* Record the current read in pipe_read */ + pipe_read->pipe_fd[0] = pipe_current_read; + process_net_io_chain.push_back(pipe_read); + } + /* This call is used so the global environment variable array