Merge commit '869994cf4f9647fdfb519a1945f8582e71d3df3d'

# Conflicts:
#	shell/hush.c
This commit is contained in:
Stephen Heumann 2018-01-01 14:00:10 -06:00
commit 75a4347378
1 changed files with 35 additions and 9 deletions

View File

@ -6532,10 +6532,12 @@ static int setup_redirects(struct command *prog, int *squirrel)
for (redir = prog->redirects; redir; redir = redir->next) {
if (redir->rd_type == REDIRECT_HEREDOC2) {
/* rd_fd<<HERE case */
if (squirrel && redir->rd_fd <= STDERR_FILENO
/* "rd_fd<<HERE" case */
if (redir->rd_fd <= STDERR_FILENO
&& squirrel
&& squirrel[redir->rd_fd] < 0
) {
/* Save old fds 0..2 if redirect uses them */
squirrel[redir->rd_fd] = dup(redir->rd_fd);
}
/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
@ -6547,7 +6549,7 @@ static int setup_redirects(struct command *prog, int *squirrel)
}
if (redir->rd_dup == REDIRFD_TO_FILE) {
/* rd_fd<*>file case (<*> is <,>,>>,<>) */
/* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
char *p;
if (redir->rd_filename == NULL) {
/* Something went wrong in the parse.
@ -6560,20 +6562,33 @@ static int setup_redirects(struct command *prog, int *squirrel)
openfd = open_or_warn(p, mode);
free(p);
if (openfd < 0) {
/* this could get lost if stderr has been redirected, but
* bash and ash both lose it as well (though zsh doesn't!) */
//what the above comment tries to say?
/* Error message from open_or_warn can be lost
* if stderr has been redirected, but bash
* and ash both lose it as well
* (though zsh doesn't!)
*/
return 1;
}
} else {
/* rd_fd<*>rd_dup or rd_fd<*>- cases */
/* "rd_fd<*>rd_dup" or "rd_fd<*>-" cases */
openfd = redir->rd_dup;
}
if (openfd != redir->rd_fd) {
if (squirrel && redir->rd_fd <= STDERR_FILENO
if (redir->rd_fd <= STDERR_FILENO
&& squirrel
&& squirrel[redir->rd_fd] < 0
) {
/* Save old fds 0..2 if redirect uses them */
//FIXME: script fd's also need this! "sh SCRIPT" and SCRIPT has "echo FOO 3>&-":
// open("SCRIPT", O_RDONLY) = 3
// fcntl(3, F_SETFD, FD_CLOEXEC) = 0
// read(3, "echo FOO 3>&-\n....", 4096) = N
// close(3) = 0
// write(1, "FOO\n", 4) = 4
// ...
// read(3, 0x205f8e0, 4096) = -1 EBADF <== BUG
//
squirrel[redir->rd_fd] = dup(redir->rd_fd);
}
if (openfd == REDIRFD_CLOSE) {
@ -7601,6 +7616,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
debug_printf(("exec with redirects only\n"));
rcode = setup_redirects(command, NULL);
/* rcode=1 can be if redir file can't be opened */
goto clean_up_and_ret1;
}
}
@ -7834,8 +7850,18 @@ static void forked_child(void *args_struct)
if (args->pipefds_p->rd > STDOUT_FILENO)
close(args->pipefds_p->rd);
/* Like bash, explicit redirects override pipes,
* and the pipe fd is available for dup'ing. */
* and the pipe fd (fd#1) is available for dup'ing:
* "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
* of cmd1 goes into pipe.
*/
if (setup_redirects(*args->command_p, NULL)) {
/* Happens when redir file can't be opened:
* $ hush -c 'echo FOO >&2 | echo BAR 3>/qwe/rty; echo BAZ'
* FOO
* hush: can't open '/qwe/rty': No such file or directory
* BAZ
* (echo BAR is not executed, it hits _exit(1) below)
*/
_exit(1);
}