diff options
-rw-r--r-- | shell/ash_test/ash-redir/redir_exec1.right | 2 | ||||
-rwxr-xr-x | shell/ash_test/ash-redir/redir_exec1.tests | 2 | ||||
-rw-r--r-- | shell/hush.c | 43 | ||||
-rw-r--r-- | shell/hush_test/hush-redir/redir_exec1.right | 3 | ||||
-rwxr-xr-x | shell/hush_test/hush-redir/redir_exec1.tests | 2 |
5 files changed, 35 insertions, 17 deletions
diff --git a/shell/ash_test/ash-redir/redir_exec1.right b/shell/ash_test/ash-redir/redir_exec1.right new file mode 100644 index 000000000..d4393d10c --- /dev/null +++ b/shell/ash_test/ash-redir/redir_exec1.right | |||
@@ -0,0 +1,2 @@ | |||
1 | redir_exec1.tests: line 1: can't create /cant/be/created: nonexistent directory | ||
2 | First | ||
diff --git a/shell/ash_test/ash-redir/redir_exec1.tests b/shell/ash_test/ash-redir/redir_exec1.tests new file mode 100755 index 000000000..290e1cb39 --- /dev/null +++ b/shell/ash_test/ash-redir/redir_exec1.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | v=`echo First >&2` exec >/cant/be/created | ||
2 | echo One:$? | ||
diff --git a/shell/hush.c b/shell/hush.c index 24ae237d7..43702360a 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -8200,19 +8200,21 @@ static int redirect_and_varexp_helper( | |||
8200 | struct squirrel **sqp, | 8200 | struct squirrel **sqp, |
8201 | char **argv_expanded) | 8201 | char **argv_expanded) |
8202 | { | 8202 | { |
8203 | /* Assignments occur before redirects. Try: | ||
8204 | * a=`sleep 1` sleep 2 3>/qwe/rty | ||
8205 | */ | ||
8206 | |||
8207 | char **new_env = expand_assignments(command->argv, command->assignment_cnt); | ||
8208 | dump_cmd_in_x_mode(new_env); | ||
8209 | dump_cmd_in_x_mode(argv_expanded); | ||
8210 | /* this takes ownership of new_env[i] elements, and frees new_env: */ | ||
8211 | set_vars_and_save_old(new_env); | ||
8212 | |||
8203 | /* setup_redirects acts on file descriptors, not FILEs. | 8213 | /* setup_redirects acts on file descriptors, not FILEs. |
8204 | * This is perfect for work that comes after exec(). | 8214 | * This is perfect for work that comes after exec(). |
8205 | * Is it really safe for inline use? Experimentally, | 8215 | * Is it really safe for inline use? Experimentally, |
8206 | * things seem to work. */ | 8216 | * things seem to work. */ |
8207 | int rcode = setup_redirects(command, sqp); | 8217 | return setup_redirects(command, sqp); |
8208 | if (rcode == 0) { | ||
8209 | char **new_env = expand_assignments(command->argv, command->assignment_cnt); | ||
8210 | dump_cmd_in_x_mode(new_env); | ||
8211 | dump_cmd_in_x_mode(argv_expanded); | ||
8212 | /* this takes ownership of new_env[i] elements, and frees new_env: */ | ||
8213 | set_vars_and_save_old(new_env); | ||
8214 | } | ||
8215 | return rcode; | ||
8216 | } | 8218 | } |
8217 | static NOINLINE int run_pipe(struct pipe *pi) | 8219 | static NOINLINE int run_pipe(struct pipe *pi) |
8218 | { | 8220 | { |
@@ -8315,6 +8317,7 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8315 | * Ensure redirects take effect (that is, create files). | 8317 | * Ensure redirects take effect (that is, create files). |
8316 | * Try "a=t >file" | 8318 | * Try "a=t >file" |
8317 | */ | 8319 | */ |
8320 | only_assignments: | ||
8318 | G.expand_exitcode = 0; | 8321 | G.expand_exitcode = 0; |
8319 | 8322 | ||
8320 | rcode = setup_redirects(command, &squirrel); | 8323 | rcode = setup_redirects(command, &squirrel); |
@@ -8359,12 +8362,10 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8359 | #endif | 8362 | #endif |
8360 | argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt); | 8363 | argv_expanded = expand_strvec_to_strvec(argv + command->assignment_cnt); |
8361 | 8364 | ||
8362 | /* if someone gives us an empty string: `cmd with empty output` */ | 8365 | /* If someone gives us an empty string: `cmd with empty output` */ |
8363 | //TODO: what about: var=EXPR `` >FILE ? will var be set? Will FILE be created? | ||
8364 | if (!argv_expanded[0]) { | 8366 | if (!argv_expanded[0]) { |
8365 | free(argv_expanded); | 8367 | free(argv_expanded); |
8366 | debug_leave(); | 8368 | goto only_assignments; |
8367 | return G.last_exitcode; | ||
8368 | } | 8369 | } |
8369 | 8370 | ||
8370 | old_vars = NULL; | 8371 | old_vars = NULL; |
@@ -8378,9 +8379,17 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8378 | if (x || funcp) { | 8379 | if (x || funcp) { |
8379 | if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) { | 8380 | if (x && x->b_function == builtin_exec && argv_expanded[1] == NULL) { |
8380 | debug_printf("exec with redirects only\n"); | 8381 | debug_printf("exec with redirects only\n"); |
8381 | rcode = setup_redirects(command, NULL); | 8382 | /* |
8382 | //TODO: what about: var=EXPR exec >FILE ? will var be set? | 8383 | * Variable assignments are executed, but then "forgotten": |
8384 | * a=`sleep 1;echo A` exec 3>&-; echo $a | ||
8385 | * sleeps, but prints nothing. | ||
8386 | */ | ||
8387 | enter_var_nest_level(); | ||
8388 | G.shadowed_vars_pp = &old_vars; | ||
8389 | rcode = redirect_and_varexp_helper(command, /*squirrel:*/ NULL, argv_expanded); | ||
8390 | G.shadowed_vars_pp = sv_shadowed; | ||
8383 | /* rcode=1 can be if redir file can't be opened */ | 8391 | /* rcode=1 can be if redir file can't be opened */ |
8392 | |||
8384 | goto clean_up_and_ret1; | 8393 | goto clean_up_and_ret1; |
8385 | } | 8394 | } |
8386 | 8395 | ||
@@ -8452,9 +8461,10 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8452 | } else | 8461 | } else |
8453 | goto must_fork; | 8462 | goto must_fork; |
8454 | 8463 | ||
8464 | restore_redirects(squirrel); | ||
8465 | clean_up_and_ret1: | ||
8455 | leave_var_nest_level(); | 8466 | leave_var_nest_level(); |
8456 | add_vars(old_vars); | 8467 | add_vars(old_vars); |
8457 | restore_redirects(squirrel); | ||
8458 | 8468 | ||
8459 | /* | 8469 | /* |
8460 | * Try "usleep 99999999" + ^C + "echo $?" | 8470 | * Try "usleep 99999999" + ^C + "echo $?" |
@@ -8474,7 +8484,6 @@ static NOINLINE int run_pipe(struct pipe *pi) | |||
8474 | if (sigismember(&G.pending_set, SIGINT)) | 8484 | if (sigismember(&G.pending_set, SIGINT)) |
8475 | rcode = 128 + SIGINT; | 8485 | rcode = 128 + SIGINT; |
8476 | } | 8486 | } |
8477 | clean_up_and_ret1: | ||
8478 | free(argv_expanded); | 8487 | free(argv_expanded); |
8479 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) | 8488 | IF_HAS_KEYWORDS(if (pi->pi_inverted) rcode = !rcode;) |
8480 | debug_leave(); | 8489 | debug_leave(); |
diff --git a/shell/hush_test/hush-redir/redir_exec1.right b/shell/hush_test/hush-redir/redir_exec1.right new file mode 100644 index 000000000..6ff8fc832 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_exec1.right | |||
@@ -0,0 +1,3 @@ | |||
1 | First | ||
2 | hush: can't open '/cant/be/created': No such file or directory | ||
3 | One:1 | ||
diff --git a/shell/hush_test/hush-redir/redir_exec1.tests b/shell/hush_test/hush-redir/redir_exec1.tests new file mode 100755 index 000000000..290e1cb39 --- /dev/null +++ b/shell/hush_test/hush-redir/redir_exec1.tests | |||
@@ -0,0 +1,2 @@ | |||
1 | v=`echo First >&2` exec >/cant/be/created | ||
2 | echo One:$? | ||