hush: bit better comments in redirect code. No logic changes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
e9abe75fda
commit
869994cf4f
49
shell/hush.c
49
shell/hush.c
@ -6099,10 +6099,12 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
|
|
||||||
for (redir = prog->redirects; redir; redir = redir->next) {
|
for (redir = prog->redirects; redir; redir = redir->next) {
|
||||||
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
if (redir->rd_type == REDIRECT_HEREDOC2) {
|
||||||
/* rd_fd<<HERE case */
|
/* "rd_fd<<HERE" case */
|
||||||
if (squirrel && redir->rd_fd < 3
|
if (redir->rd_fd <= 2
|
||||||
|
&& squirrel
|
||||||
&& squirrel[redir->rd_fd] < 0
|
&& squirrel[redir->rd_fd] < 0
|
||||||
) {
|
) {
|
||||||
|
/* Save old fds 0..2 if redirect uses them */
|
||||||
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
||||||
}
|
}
|
||||||
/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
|
/* for REDIRECT_HEREDOC2, rd_filename holds _contents_
|
||||||
@ -6114,7 +6116,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (redir->rd_dup == REDIRFD_TO_FILE) {
|
if (redir->rd_dup == REDIRFD_TO_FILE) {
|
||||||
/* rd_fd<*>file case (<*> is <,>,>>,<>) */
|
/* "rd_fd<*>file" case (<*> is <,>,>>,<>) */
|
||||||
char *p;
|
char *p;
|
||||||
if (redir->rd_filename == NULL) {
|
if (redir->rd_filename == NULL) {
|
||||||
/* Something went wrong in the parse.
|
/* Something went wrong in the parse.
|
||||||
@ -6127,20 +6129,33 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
openfd = open_or_warn(p, mode);
|
openfd = open_or_warn(p, mode);
|
||||||
free(p);
|
free(p);
|
||||||
if (openfd < 0) {
|
if (openfd < 0) {
|
||||||
/* this could get lost if stderr has been redirected, but
|
/* Error message from open_or_warn can be lost
|
||||||
* bash and ash both lose it as well (though zsh doesn't!) */
|
* if stderr has been redirected, but bash
|
||||||
//what the above comment tries to say?
|
* and ash both lose it as well
|
||||||
|
* (though zsh doesn't!)
|
||||||
|
*/
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* rd_fd<*>rd_dup or rd_fd<*>- cases */
|
/* "rd_fd<*>rd_dup" or "rd_fd<*>-" cases */
|
||||||
openfd = redir->rd_dup;
|
openfd = redir->rd_dup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (openfd != redir->rd_fd) {
|
if (openfd != redir->rd_fd) {
|
||||||
if (squirrel && redir->rd_fd < 3
|
if (redir->rd_fd <= 2
|
||||||
|
&& squirrel
|
||||||
&& squirrel[redir->rd_fd] < 0
|
&& 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);
|
squirrel[redir->rd_fd] = dup(redir->rd_fd);
|
||||||
}
|
}
|
||||||
if (openfd == REDIRFD_CLOSE) {
|
if (openfd == REDIRFD_CLOSE) {
|
||||||
@ -6159,7 +6174,7 @@ static int setup_redirects(struct command *prog, int squirrel[])
|
|||||||
static void restore_redirects(int squirrel[])
|
static void restore_redirects(int squirrel[])
|
||||||
{
|
{
|
||||||
int i, fd;
|
int i, fd;
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i <= 2; i++) {
|
||||||
fd = squirrel[i];
|
fd = squirrel[i];
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
/* We simply die on error */
|
/* We simply die on error */
|
||||||
@ -7144,6 +7159,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
|
if (x->b_function == builtin_exec && argv_expanded[1] == NULL) {
|
||||||
debug_printf("exec with redirects only\n");
|
debug_printf("exec with redirects only\n");
|
||||||
rcode = setup_redirects(command, NULL);
|
rcode = setup_redirects(command, NULL);
|
||||||
|
/* rcode=1 can be if redir file can't be opened */
|
||||||
goto clean_up_and_ret1;
|
goto clean_up_and_ret1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7270,9 +7286,20 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
if (pipefds.rd > 1)
|
if (pipefds.rd > 1)
|
||||||
close(pipefds.rd);
|
close(pipefds.rd);
|
||||||
/* Like bash, explicit redirects override pipes,
|
/* 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:
|
||||||
if (setup_redirects(command, NULL))
|
* "cmd1 2>&1 | cmd2": fd#1 is duped to fd#2, thus stderr
|
||||||
|
* of cmd1 goes into pipe.
|
||||||
|
*/
|
||||||
|
if (setup_redirects(command, 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);
|
_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
/* Stores to nommu_save list of env vars putenv'ed
|
/* Stores to nommu_save list of env vars putenv'ed
|
||||||
* (NOMMU, on MMU we don't need that) */
|
* (NOMMU, on MMU we don't need that) */
|
||||||
|
Loading…
Reference in New Issue
Block a user