aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-06-07 16:42:05 +0000
committerEric Andersen <andersen@codepoet.org>2001-06-07 16:42:05 +0000
commit04407e522b43c37198c8a821723950470d0919f5 (patch)
tree26d6ed9beac36d72c4423ae6eddfdd7bf31a43c4
parent4f3e24979bfa8f6a954d5222c7508545c42867e0 (diff)
downloadbusybox-w32-04407e522b43c37198c8a821723950470d0919f5.tar.gz
busybox-w32-04407e522b43c37198c8a821723950470d0919f5.tar.bz2
busybox-w32-04407e522b43c37198c8a821723950470d0919f5.zip
Another hush update from Larry:
Fixes the interaction between if/then/else/fi syntax and variables. I planned to do it right from the beginning, but my implementation was buggy. Also adds the relevant test cases. Also adds some old Matt Kraai variable test cases that got left out somehow.
-rw-r--r--hush.c30
-rw-r--r--shell/hush.c30
-rw-r--r--tests/sh.testcases29
3 files changed, 61 insertions, 28 deletions
diff --git a/hush.c b/hush.c
index 126f9da89..3b1e53c82 100644
--- a/hush.c
+++ b/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/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
28if true || false; then echo foo; else echo bar5; fi 28if true || false; then echo foo; else echo bar5; fi
29if true && false; then echo bar6; else echo foo; fi 29if true && false; then echo bar6; else echo foo; fi
30 30
31# basic distinction between local and env variables
32unset FOO
33FOO=bar env | grep FOO
34echo "but not here: $FOO"
35FOO=bar
36env | grep FOO
37echo "yes, here: $FOO"
38FOO=
39echo a $FOO b
40echo "a $FOO b"
41
42# not quite so basic variables. Credit to Matt Kraai.
43unset FOO
44FOO=bar
45export FOO
46env | grep FOO
47unset FOO
48export FOO=bar
49FOO=baz
50env | grep FOO
51
52# interaction between environment variables and if/then and subshells
53FOO=default
54if true; then FOO=new; fi
55echo $FOO
56FOO=default
57(FOO=bogus)
58echo $FOO
59
31# make sure we can duplicate file descriptors properly 60# make sure we can duplicate file descriptors properly
32echo replacement >foo 2>&1 61echo replacement >foo 2>&1
33cat foo 62cat foo