diff options
-rw-r--r-- | hush.c | 30 | ||||
-rw-r--r-- | shell/hush.c | 30 | ||||
-rw-r--r-- | tests/sh.testcases | 29 |
3 files changed, 61 insertions, 28 deletions
@@ -1326,19 +1326,18 @@ static int run_pipe_real(struct pipe *pi) | |||
1326 | * Builtins within pipes have to fork anyway, and are handled in | 1326 | * Builtins within pipes have to fork anyway, and are handled in |
1327 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. | 1327 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. |
1328 | */ | 1328 | */ |
1329 | if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { | 1329 | if (pi->num_progs == 1) child = & (pi->progs[0]); |
1330 | child = & (pi->progs[0]); | 1330 | if (pi->num_progs == 1 && child->group && child->subshell == 0) { |
1331 | if (child->group && ! child->subshell) { | 1331 | int squirrel[] = {-1, -1, -1}; |
1332 | int squirrel[] = {-1, -1, -1}; | 1332 | int rcode; |
1333 | int rcode; | 1333 | debug_printf("non-subshell grouping\n"); |
1334 | debug_printf("non-subshell grouping\n"); | 1334 | setup_redirects(child, squirrel); |
1335 | setup_redirects(child, squirrel); | 1335 | /* XXX could we merge code with following builtin case, |
1336 | /* XXX could we merge code with following builtin case, | 1336 | * by creating a pseudo builtin that calls run_list_real? */ |
1337 | * by creating a pseudo builtin that calls run_list_real? */ | 1337 | rcode = run_list_real(child->group); |
1338 | rcode = run_list_real(child->group); | 1338 | restore_redirects(squirrel); |
1339 | restore_redirects(squirrel); | 1339 | return rcode; |
1340 | return rcode; | 1340 | } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { |
1341 | } | ||
1342 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } | 1341 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } |
1343 | if (i!=0 && child->argv[i]==NULL) { | 1342 | if (i!=0 && child->argv[i]==NULL) { |
1344 | /* assignments, but no command: set the local environment */ | 1343 | /* assignments, but no command: set the local environment */ |
@@ -1352,7 +1351,8 @@ static int run_pipe_real(struct pipe *pi) | |||
1352 | * variable. */ | 1351 | * variable. */ |
1353 | int export_me=0; | 1352 | int export_me=0; |
1354 | char *name, *value; | 1353 | char *name, *value; |
1355 | name = strdup(child->argv[i]); | 1354 | name = xstrdup(child->argv[i]); |
1355 | debug_printf("Local environment set: %s\n", name); | ||
1356 | value = strchr(name, '='); | 1356 | value = strchr(name, '='); |
1357 | if (value) | 1357 | if (value) |
1358 | *value=0; | 1358 | *value=0; |
@@ -1478,6 +1478,7 @@ static int run_list_real(struct pipe *pi) | |||
1478 | if (rmode == RES_ELIF && !if_code) continue; | 1478 | if (rmode == RES_ELIF && !if_code) continue; |
1479 | if (pi->num_progs == 0) continue; | 1479 | if (pi->num_progs == 0) continue; |
1480 | rcode = run_pipe_real(pi); | 1480 | rcode = run_pipe_real(pi); |
1481 | debug_printf("run_pipe_real returned %d\n",rcode); | ||
1481 | if (rcode!=-1) { | 1482 | if (rcode!=-1) { |
1482 | /* We only ran a builtin: rcode was set by the return value | 1483 | /* We only ran a builtin: rcode was set by the return value |
1483 | * of run_pipe_real(), and we don't need to wait for anything. */ | 1484 | * of run_pipe_real(), and we don't need to wait for anything. */ |
@@ -1943,6 +1944,7 @@ int reserved_word(o_string *dest, struct p_context *ctx) | |||
1943 | debug_printf("pop stack\n"); | 1944 | debug_printf("pop stack\n"); |
1944 | old = ctx->stack; | 1945 | old = ctx->stack; |
1945 | old->child->group = ctx->list_head; | 1946 | old->child->group = ctx->list_head; |
1947 | old->child->subshell = 0; | ||
1946 | *ctx = *old; /* physical copy */ | 1948 | *ctx = *old; /* physical copy */ |
1947 | free(old); | 1949 | free(old); |
1948 | } | 1950 | } |
diff --git a/shell/hush.c b/shell/hush.c index 126f9da89..3b1e53c82 100644 --- a/shell/hush.c +++ b/shell/hush.c | |||
@@ -1326,19 +1326,18 @@ static int run_pipe_real(struct pipe *pi) | |||
1326 | * Builtins within pipes have to fork anyway, and are handled in | 1326 | * Builtins within pipes have to fork anyway, and are handled in |
1327 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. | 1327 | * pseudo_exec. "echo foo | read bar" doesn't work on bash, either. |
1328 | */ | 1328 | */ |
1329 | if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { | 1329 | if (pi->num_progs == 1) child = & (pi->progs[0]); |
1330 | child = & (pi->progs[0]); | 1330 | if (pi->num_progs == 1 && child->group && child->subshell == 0) { |
1331 | if (child->group && ! child->subshell) { | 1331 | int squirrel[] = {-1, -1, -1}; |
1332 | int squirrel[] = {-1, -1, -1}; | 1332 | int rcode; |
1333 | int rcode; | 1333 | debug_printf("non-subshell grouping\n"); |
1334 | debug_printf("non-subshell grouping\n"); | 1334 | setup_redirects(child, squirrel); |
1335 | setup_redirects(child, squirrel); | 1335 | /* XXX could we merge code with following builtin case, |
1336 | /* XXX could we merge code with following builtin case, | 1336 | * by creating a pseudo builtin that calls run_list_real? */ |
1337 | * by creating a pseudo builtin that calls run_list_real? */ | 1337 | rcode = run_list_real(child->group); |
1338 | rcode = run_list_real(child->group); | 1338 | restore_redirects(squirrel); |
1339 | restore_redirects(squirrel); | 1339 | return rcode; |
1340 | return rcode; | 1340 | } else if (pi->num_progs == 1 && pi->progs[0].argv != NULL) { |
1341 | } | ||
1342 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } | 1341 | for (i=0; is_assignment(child->argv[i]); i++) { /* nothing */ } |
1343 | if (i!=0 && child->argv[i]==NULL) { | 1342 | if (i!=0 && child->argv[i]==NULL) { |
1344 | /* assignments, but no command: set the local environment */ | 1343 | /* assignments, but no command: set the local environment */ |
@@ -1352,7 +1351,8 @@ static int run_pipe_real(struct pipe *pi) | |||
1352 | * variable. */ | 1351 | * variable. */ |
1353 | int export_me=0; | 1352 | int export_me=0; |
1354 | char *name, *value; | 1353 | char *name, *value; |
1355 | name = strdup(child->argv[i]); | 1354 | name = xstrdup(child->argv[i]); |
1355 | debug_printf("Local environment set: %s\n", name); | ||
1356 | value = strchr(name, '='); | 1356 | value = strchr(name, '='); |
1357 | if (value) | 1357 | if (value) |
1358 | *value=0; | 1358 | *value=0; |
@@ -1478,6 +1478,7 @@ static int run_list_real(struct pipe *pi) | |||
1478 | if (rmode == RES_ELIF && !if_code) continue; | 1478 | if (rmode == RES_ELIF && !if_code) continue; |
1479 | if (pi->num_progs == 0) continue; | 1479 | if (pi->num_progs == 0) continue; |
1480 | rcode = run_pipe_real(pi); | 1480 | rcode = run_pipe_real(pi); |
1481 | debug_printf("run_pipe_real returned %d\n",rcode); | ||
1481 | if (rcode!=-1) { | 1482 | if (rcode!=-1) { |
1482 | /* We only ran a builtin: rcode was set by the return value | 1483 | /* We only ran a builtin: rcode was set by the return value |
1483 | * of run_pipe_real(), and we don't need to wait for anything. */ | 1484 | * of run_pipe_real(), and we don't need to wait for anything. */ |
@@ -1943,6 +1944,7 @@ int reserved_word(o_string *dest, struct p_context *ctx) | |||
1943 | debug_printf("pop stack\n"); | 1944 | debug_printf("pop stack\n"); |
1944 | old = ctx->stack; | 1945 | old = ctx->stack; |
1945 | old->child->group = ctx->list_head; | 1946 | old->child->group = ctx->list_head; |
1947 | old->child->subshell = 0; | ||
1946 | *ctx = *old; /* physical copy */ | 1948 | *ctx = *old; /* physical copy */ |
1947 | free(old); | 1949 | free(old); |
1948 | } | 1950 | } |
diff --git a/tests/sh.testcases b/tests/sh.testcases index 88e709f87..e2a75873e 100644 --- a/tests/sh.testcases +++ b/tests/sh.testcases | |||
@@ -28,6 +28,35 @@ if false; then tr 'A-Z' 'a-z'; else echo bar4; fi <foo | |||
28 | if true || false; then echo foo; else echo bar5; fi | 28 | if true || false; then echo foo; else echo bar5; fi |
29 | if true && false; then echo bar6; else echo foo; fi | 29 | if true && false; then echo bar6; else echo foo; fi |
30 | 30 | ||
31 | # basic distinction between local and env variables | ||
32 | unset FOO | ||
33 | FOO=bar env | grep FOO | ||
34 | echo "but not here: $FOO" | ||
35 | FOO=bar | ||
36 | env | grep FOO | ||
37 | echo "yes, here: $FOO" | ||
38 | FOO= | ||
39 | echo a $FOO b | ||
40 | echo "a $FOO b" | ||
41 | |||
42 | # not quite so basic variables. Credit to Matt Kraai. | ||
43 | unset FOO | ||
44 | FOO=bar | ||
45 | export FOO | ||
46 | env | grep FOO | ||
47 | unset FOO | ||
48 | export FOO=bar | ||
49 | FOO=baz | ||
50 | env | grep FOO | ||
51 | |||
52 | # interaction between environment variables and if/then and subshells | ||
53 | FOO=default | ||
54 | if true; then FOO=new; fi | ||
55 | echo $FOO | ||
56 | FOO=default | ||
57 | (FOO=bogus) | ||
58 | echo $FOO | ||
59 | |||
31 | # make sure we can duplicate file descriptors properly | 60 | # make sure we can duplicate file descriptors properly |
32 | echo replacement >foo 2>&1 | 61 | echo replacement >foo 2>&1 |
33 | cat foo | 62 | cat foo |