hush: fix corner cases with exec in empty expansions
Cases like these: var=val exec >redir var=val `` >redir function old new delta run_pipe 1701 1723 +22 redirect_and_varexp_helper 56 55 -1 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 1/1 up/down: 22/-1) Total: 21 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
929a41d577
commit
41d8f10813
2
shell/ash_test/ash-redir/redir_exec1.right
Normal file
2
shell/ash_test/ash-redir/redir_exec1.right
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
redir_exec1.tests: line 1: can't create /cant/be/created: nonexistent directory
|
||||||
|
First
|
2
shell/ash_test/ash-redir/redir_exec1.tests
Executable file
2
shell/ash_test/ash-redir/redir_exec1.tests
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
v=`echo First >&2` exec >/cant/be/created
|
||||||
|
echo One:$?
|
43
shell/hush.c
43
shell/hush.c
@ -8200,19 +8200,21 @@ static int redirect_and_varexp_helper(
|
|||||||
struct squirrel **sqp,
|
struct squirrel **sqp,
|
||||||
char **argv_expanded)
|
char **argv_expanded)
|
||||||
{
|
{
|
||||||
|
/* Assignments occur before redirects. Try:
|
||||||
|
* a=`sleep 1` sleep 2 3>/qwe/rty
|
||||||
|
*/
|
||||||
|
|
||||||
|
char **new_env = expand_assignments(command->argv, command->assignment_cnt);
|
||||||
|
dump_cmd_in_x_mode(new_env);
|
||||||
|
dump_cmd_in_x_mode(argv_expanded);
|
||||||
|
/* this takes ownership of new_env[i] elements, and frees new_env: */
|
||||||
|
set_vars_and_save_old(new_env);
|
||||||
|
|
||||||
/* setup_redirects acts on file descriptors, not FILEs.
|
/* setup_redirects acts on file descriptors, not FILEs.
|
||||||
* This is perfect for work that comes after exec().
|
* This is perfect for work that comes after exec().
|
||||||
* Is it really safe for inline use? Experimentally,
|
* Is it really safe for inline use? Experimentally,
|
||||||
* things seem to work. */
|
* things seem to work. */
|
||||||
int rcode = setup_redirects(command, sqp);
|
return setup_redirects(command, sqp);
|
||||||
if (rcode == 0) {
|
|
||||||
char **new_env = expand_assignments(command->argv, command->assignment_cnt);
|
|
||||||
dump_cmd_in_x_mode(new_env);
|
|
||||||
dump_cmd_in_x_mode(argv_expanded);
|
|
||||||
/* this takes ownership of new_env[i] elements, and frees new_env: */
|
|
||||||
set_vars_and_save_old(new_env);
|
|
||||||
}
|
|
||||||
return rcode;
|
|
||||||
}
|
}
|
||||||
static NOINLINE int run_pipe(struct pipe *pi)
|
static NOINLINE int run_pipe(struct pipe *pi)
|
||||||
{
|
{
|
||||||
@ -8315,6 +8317,7 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
* Ensure redirects take effect (that is, create files).
|
* Ensure redirects take effect (that is, create files).
|
||||||
* Try "a=t >file"
|
* Try "a=t >file"
|
||||||
*/
|
*/
|
||||||
|
only_assignments:
|
||||||
G.expand_exitcode = 0;
|
G.expand_exitcode = 0;
|
||||||
|
|
||||||
rcode = setup_redirects(command, &squirrel);
|
rcode = setup_redirects(command, &squirrel);
|
||||||
@ -8359,12 +8362,10 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
#endif
|
#endif
|
||||||
argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
|
argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt);
|
||||||
|
|
||||||
/* if someone gives us an empty string: `cmd with empty output` */
|
/* If someone gives us an empty string: `cmd with empty output` */
|
||||||
//TODO: what about: var=EXPR `` >FILE ? will var be set? Will FILE be created?
|
|
||||||
if (!argv_expanded[0]) {
|
if (!argv_expanded[0]) {
|
||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
debug_leave();
|
goto only_assignments;
|
||||||
return G.last_exitcode;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
old_vars = NULL;
|
old_vars = NULL;
|
||||||
@ -8378,9 +8379,17 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
if (x || funcp) {
|
if (x || funcp) {
|
||||||
if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) {
|
if (x && 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);
|
/*
|
||||||
//TODO: what about: var=EXPR exec >FILE ? will var be set?
|
* Variable assignments are executed, but then "forgotten":
|
||||||
|
* a=`sleep 1;echo A` exec 3>&-; echo $a
|
||||||
|
* sleeps, but prints nothing.
|
||||||
|
*/
|
||||||
|
enter_var_nest_level();
|
||||||
|
G.shadowed_vars_pp = &old_vars;
|
||||||
|
rcode = redirect_and_varexp_helper(command, /*squirrel:*/ NULL, argv_expanded);
|
||||||
|
G.shadowed_vars_pp = sv_shadowed;
|
||||||
/* rcode=1 can be if redir file can't be opened */
|
/* rcode=1 can be if redir file can't be opened */
|
||||||
|
|
||||||
goto clean_up_and_ret1;
|
goto clean_up_and_ret1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8452,9 +8461,10 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
} else
|
} else
|
||||||
goto must_fork;
|
goto must_fork;
|
||||||
|
|
||||||
|
restore_redirects(squirrel);
|
||||||
|
clean_up_and_ret1:
|
||||||
leave_var_nest_level();
|
leave_var_nest_level();
|
||||||
add_vars(old_vars);
|
add_vars(old_vars);
|
||||||
restore_redirects(squirrel);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try "usleep 99999999" + ^C + "echo $?"
|
* Try "usleep 99999999" + ^C + "echo $?"
|
||||||
@ -8474,7 +8484,6 @@ static NOINLINE int run_pipe(struct pipe *pi)
|
|||||||
if (sigismember(&G.pending_set, SIGINT))
|
if (sigismember(&G.pending_set, SIGINT))
|
||||||
rcode = 128 + SIGINT;
|
rcode = 128 + SIGINT;
|
||||||
}
|
}
|
||||||
clean_up_and_ret1:
|
|
||||||
free(argv_expanded);
|
free(argv_expanded);
|
||||||
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;)
|
||||||
debug_leave();
|
debug_leave();
|
||||||
|
3
shell/hush_test/hush-redir/redir_exec1.right
Normal file
3
shell/hush_test/hush-redir/redir_exec1.right
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
First
|
||||||
|
hush: can't open '/cant/be/created': No such file or directory
|
||||||
|
One:1
|
2
shell/hush_test/hush-redir/redir_exec1.tests
Executable file
2
shell/hush_test/hush-redir/redir_exec1.tests
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
v=`echo First >&2` exec >/cant/be/created
|
||||||
|
echo One:$?
|
Loading…
Reference in New Issue
Block a user