aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2020-02-06 14:27:46 -0600
committerRob Landley <rob@landley.net>2020-02-06 14:27:46 -0600
commit31711481dc06ab4b3068fc284529e0644b5e3673 (patch)
treec7fe7c44c7fab73482528fc9ee5f0a47d3cd1efe
parent01bf7f6e61d13c57aa6159262af43792793afcae (diff)
downloadtoybox-31711481dc06ab4b3068fc284529e0644b5e3673.tar.gz
Basic parenthetical subshell support.
-rwxr-xr-xtests/sh.test5
-rw-r--r--toys/pending/sh.c31
2 files changed, 25 insertions, 11 deletions
diff --git a/tests/sh.test b/tests/sh.test
index 4895ca7b..ca6a2831 100755
--- a/tests/sh.test
+++ b/tests/sh.test
@@ -57,9 +57,12 @@ testing "leading variable assignments" \
#testing "can't have space before first : but yes around arguments" \
# 'BLAH=abcdefghi; echo ${BLAH: 1 : 3 }' "bcd\n" "" ""
-testing "curly brackets and pipe" \
+NOSPACE=1 testing "curly brackets and pipe" \
'{ echo one; echo two ; } | tee blah.txt; wc blah.txt' \
"one\ntwo\n2 2 8 blah.txt\n" "" ""
+NOSPACE=1 testing "parentheses and pipe" \
+ '(echo two;echo three)|tee blah.txt;wc blah.txt' \
+ "two\nthree\n2 2 10 blah.txt\n" "" ""
# texpect "name" "command" E/O/I"string"
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 5beebca2..9f686932 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -142,6 +142,7 @@ static void syntax_err(char *msg, ...)
{
va_list va;
+// TODO rethink syntax errordom
va_start(va, msg);
verror_msg(msg, 0, va);
va_end(va);
@@ -579,7 +580,7 @@ int save_redirect(int **rd, int from, int to)
if (hfd != dup2(to, hfd)) hfd = -1;
else fcntl(hfd, F_SETFD, FD_CLOEXEC);
-if (BUGBUG) dprintf(255, "redir from=%d to=%d hfd=%d\n", from, to, hfd);
+if (BUGBUG) dprintf(255, "%d redir from=%d to=%d hfd=%d\n", getpid(), from, to, hfd);
// dup "to"
if (from != -1 && to != dup2(from, to)) {
if (hfd != -1) close(hfd);
@@ -1573,7 +1574,7 @@ static void run_function(struct sh_pipeline *pl)
while (pl) {
struct sh_arg *arg = pl->arg;
char *s = *arg->v, *ss = arg->v[1], *ctl = arg->v[arg->c];
-if (BUGBUG) dprintf(255, "runtype=%d %s %s\n", pl->type, s, ctl);
+if (BUGBUG) dprintf(255, "%d runtype=%d %s %s\n", getpid(), pl->type, s, ctl);
// Is this an executable segment?
if (!pl->type) {
@@ -1582,7 +1583,6 @@ if (BUGBUG) dprintf(255, "runtype=%d %s %s\n", pl->type, s, ctl);
while (pl->next && !pl->next->type) pl = pl->next;
continue;
}
-
if (pipe_segments(ctl, pipes, &urd)) break;
// If we just started a new pipeline, implicit parentheses (subshell)
@@ -1648,10 +1648,10 @@ if (BUGBUG) dprintf(255, "runtype=%d %s %s\n", pl->type, s, ctl);
// Start of flow control block?
} else if (pl->type == 1) {
+ struct sh_process *pp = 0;
// are we entering this block (rather than looping back to it)?
if (!blk || blk->start != pl) {
- struct sh_process *pp;
// If it's a nested block we're not running, skip ahead.
end = block_end(pl->next);
@@ -1681,10 +1681,13 @@ if (BUGBUG) dprintf(255, "runtype=%d %s %s\n", pl->type, s, ctl);
// Perform redirects listed at end of block
pp = expand_redir(end->arg, 1, blk->urd);
blk->urd = pp->urd;
- if (pp->arg.c) perror_msg("unexpected %s", *pp->arg.v);
- llist_traverse(pp->delete, free);
- if (pp->arg.c) break;
- free(pp);
+ if (pp->arg.c) {
+// TODO this is a syntax_error
+ perror_msg("unexpected %s", *pp->arg.v);
+ llist_traverse(pp->delete, free);
+ free(pp);
+ break;
+ }
}
// What flow control statement is this?
@@ -1720,9 +1723,17 @@ TODO: a | b | c needs subshell for builtins?
} else if (!strcmp(s, "(")) {
if (!CFG_TOYBOX_FORK) {
ss = pl2str(pl->next);
- run_subshell(ss, strlen(ss));
+ pp->pid = run_subshell(ss, strlen(ss));
+ free(ss);
+ } else {
+ if (!(pp->pid = fork())) {
+ run_function(pl->next);
+ _exit(toys.exitval);
+ }
}
- pl = blk->end;
+
+ dlist_add_nomalloc((void *)&pplist, (void *)pp);
+ pl = blk->end->prev;
}
// gearshift from block start to block body (end of flow control test)