aboutsummaryrefslogtreecommitdiff
path: root/toys
diff options
context:
space:
mode:
authorRob Landley <rob@landley.net>2020-04-08 23:08:57 -0500
committerRob Landley <rob@landley.net>2020-04-08 23:08:57 -0500
commit41dfa883e178c239bed0ec02fa38af09739d55b0 (patch)
tree1f3f6488f05d00130d485dee0e07c28d5c260c7f /toys
parent4f1e357b5d2064b433006bd707a2e7307d79542a (diff)
downloadtoybox-41dfa883e178c239bed0ec02fa38af09739d55b0.tar.gz
Implement ! and $$ and fix quoted "$(subshell)"
Diffstat (limited to 'toys')
-rw-r--r--toys/pending/sh.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index 55c30a19..183d5fd1 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -485,7 +485,7 @@ static int redir_prefix(char *word)
}
// parse next word from command line. Returns end, or 0 if need continuation
-// caller eats leading spaces. If early, stop at first unquoted char.
+// caller eats leading spaces. early = skip one quote block (or return start)
static char *parse_word(char *start, int early)
{
int i, quote = 0, q, qc = 0;
@@ -497,8 +497,7 @@ static char *parse_word(char *start, int early)
// Redirections. 123<<file- parses as 2 args: "123<<" "file-".
s = end + redir_prefix(end);
- if ((i = anystart(s, (void *)redirectors))) s += i;
- if (s != end) return (end == start) ? s : end;
+ if ((i = anystart(s, (void *)redirectors))) return s+i;
// (( is a special quote at the start of a word
if (strstart(&end, "((")) toybuf[quote++] = 254;
@@ -535,7 +534,8 @@ static char *parse_word(char *start, int early)
else if (q == '\'') end++;
else i++;
- // loop if we already handled a symbol
+ // loop if we already handled a symbol and aren't stopping early
+ if (early && !quote) return end;
if (!i) continue;
} else {
// Things that only matter when unquoted
@@ -565,10 +565,9 @@ static char *parse_word(char *start, int early)
toybuf[quote++] = ")}]"[i];
end++;
}
- } else {
- if (early && !quote) break;
- end++;
}
+ if (early && !quote) return end;
+ end++;
}
return quote ? 0 : end;
@@ -871,7 +870,7 @@ if (BUGBUG) dprintf(255, "expand %s\n", str);
off_t pp = 0;
s = str+ii-1;
- kk = parse_word(str+ii-1, 1)-s;
+ kk = parse_word(s, 1)-s;
if (*toybuf == 255) {
s += 3;
kk -= 5;
@@ -913,6 +912,7 @@ dprintf(2, "TODO: do math for %.*s\n", kk, s);
new[oo++] = cc;
break;
} else if (cc == '?') ifs = del = xmprintf("%d", toys.exitval);
+ else if (cc == '$') ifs = del = xmprintf("%d", TT.pid);
else if (cc == '#') ifs = del = xmprintf("%d", TT.arg->c?TT.arg->c-1:0);
else if (cc == '*' || cc == '@') {
// If not doing word split, handle here
@@ -1025,7 +1025,7 @@ static void expand_arg(struct sh_arg *arg, char *old, unsigned flags,
{
struct brace {
struct brace *next, *prev, *stack;
- int active, cnt, idx, commas[];
+ int active, cnt, idx, dots[2], commas[];
} *bb = 0, *blist = 0, *bstk, *bnext;
int i, j;
char *s, *ss;
@@ -1214,6 +1214,12 @@ static struct sh_process *expand_redir(struct sh_arg *arg, int envlen, int *urd)
s = arg->v[j];
+ if (!strcmp(s, "!")) {
+ pp->not ^= 1;
+
+ continue;
+ }
+
// Handle <() >() redirectionss
if ((*s == '<' || *s == '>') && s[1] == '(') {
int new = pipe_subshell(s+2, strlen(s+2)-1, *s == '>');
@@ -1884,7 +1890,7 @@ static int wait_pipeline(struct sh_process *pp)
pp->pid = 0;
}
// TODO handle set -o pipefail here
- rc = pp->exit;
+ rc = pp->not ? !pp->exit : pp->exit;
}
return rc;
@@ -2640,9 +2646,9 @@ void export_main(void)
void eval_main(void)
{
int len = 1;
- char *s = merge_args("", toys.optc+1, toys.argv, " ", &len, "");
+ char *s;
- sh_run(s);
+ sh_run(s = merge_args("", toys.optc+1, toys.argv, " ", &len, ""));
free(s);
}