From 7a4524c989c2702b0c86ebe210aa6315da3a1a77 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 19 Mar 2021 03:05:06 -0500 Subject: Fix some more sh regressions. --- tests/sh.test | 5 ----- toys/pending/sh.c | 42 +++++++++++++++++++++--------------------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/tests/sh.test b/tests/sh.test index efd906d6..84f8dab3 100644 --- a/tests/sh.test +++ b/tests/sh.test @@ -118,20 +118,15 @@ testing 'simple script in $PATH' "PATH='$PWD/sub:$PATH' $SH script" \ rm -rf sub testing "script file" "chmod +x input; ./input" "hello\n" "#!$C\necho hello" "" - testing 'IFS $*' "$SH -c 'IFS=xy; echo \"\$*\"' one two tyree" "twoxtyree\n" \ "" "" - testing 'default exports' \ "env -i \"$(which $SH)\" --noprofile --norc -c env | sort" \ "PWD=$(pwd)\nSHLVL=1\n_=$(which env)\n" "" "" - testing "leading assignment fail" \ "{ \$SH -c 'X=\${a?blah} > walroid';ls walroid;} 2>/dev/null" '' '' '' - testing "lineno" "$SH input" "5 one\n6 one\n5 two\n6 two\n" \ '#!/bin/bash\n\nfor i in one two\ndo\n echo $LINENO $i\n echo $LINENO $i\ndone\n' "" - testing "eval0" "sh -c 'eval echo \$*' one two three" "two three\n" "" "" ######################################################################### diff --git a/toys/pending/sh.c b/toys/pending/sh.c index 473bc935..b3414a7e 100644 --- a/toys/pending/sh.c +++ b/toys/pending/sh.c @@ -590,7 +590,7 @@ static char *parse_word(char *start, int early, int quote) int ii, qq, qc = 0; char *end = start, *ss; - // Things that only matter at the start of word: redirections, <(), (( )) + // Handle redirections, <(), (( )) that only count at the start of word ss = end + redir_prefix(end); // 123<(")) { toybuf[quote++]=')'; @@ -636,19 +636,19 @@ static char *parse_word(char *start, int early, int quote) // start new quote context? (' not special within ") if (strchr("'\"`"+(qq=='"'), ii = *end++)) toybuf[quote++] = ii; - // backslash escapes - else if (ii=='\\') { - if (!*end || (*end=='\n' && !end[1])) return early ? end : 0; - end++; - } else if (ii=='$' && -1!=(qq = stridx("({[", *end))) { - if (strstart(&end, "((")) { - toybuf[quote++] = 255; - end++; - } else toybuf[quote++] = ")}]"[qq]; - } else if (*end=='(' && strchr("?*+@!", ii)) { - toybuf[quote++] = ')'; + // \? $() ${} $[] ?() *() +() @() !() + else { + if (ii=='\\') { // TODO why end[1] here? sh -c $'abc\\\ndef' Add test. + if (!*end || (*end=='\n' && !end[1])) return early ? end : 0; + } else if (ii=='$' && -1!=(qq = stridx("({[", *end))) { + if (strstart(&end, "((")) { + toybuf[quote++] = 255; + end++; + } else toybuf[quote++] = ")}]"[qq]; + } else if (*end=='(' && strchr("?*+@!", ii)) toybuf[quote++] = ')'; + else end--; end++; - }; + } } return (quote && !early) ? 0 : end; @@ -2232,7 +2232,7 @@ static struct sh_process *run_command(void) { char *s, *sss; struct sh_arg *arg = TT.ff->pl->arg; - int envlen, jj = 0, ll; + int envlen, jj = 0, persist; struct sh_process *pp = 0; struct arg_list *delete = 0; struct toy_list *tl; @@ -2248,21 +2248,21 @@ static struct sh_process *run_command(void) struct sh_vars *vv; // If prefix assignment, create temp function context to hold vars - if (!(ll = envlen==arg->c)) call_function(); + if (!(persist = envlen==arg->c)) call_function(); for (; jjv[jj]; - if (!ll && (!(vv = findvar(s, &ff)) || ff != TT.ff)) { + if (!persist && (!(vv = findvar(s, &ff)) || ff != TT.ff)) { if (vv && (vv->flags&VAR_READONLY)) { error_msg("%.*s: readonly variable", (int)(varend(s)-s), s); continue; } addvar(s, TT.ff)->flags = VAR_NOFREE|VAR_GLOBAL; } - if (!(sss = expand_one_arg(s, SEMI_IFS, ll ? &delete : 0))) { + if (!(sss = expand_one_arg(s, SEMI_IFS, persist ? 0 : &delete))) { if (!pp) pp = xzalloc(sizeof(struct sh_process)); pp->exit = 1; - } else setvar((!ll || sss != s) ? s : xstrdup(s)); + } else setvar((!persist || sss != s) ? sss : xstrdup(sss)); } } @@ -2446,7 +2446,7 @@ static int parse_line(char *line, struct sh_pipeline **ppl, // Parse next word and detect overflow (too many nested quotes). if ((end = parse_word(start, 0, 0)) == (void *)1) goto flush; - +//dprintf(2, "word=%.*s\n", (int)(end-start), end ? start : ""); // Is this a new pipeline segment? if (!pl) pl = add_pl(ppl, &arg); @@ -2909,7 +2909,7 @@ static void run_lines(void) ctl = TT.ff->pl->end->arg->v[TT.ff->pl->end->arg->c]; s = *TT.ff->pl->arg->v; ss = TT.ff->pl->arg->v[1]; -//dprintf(2, "s=%s ss=%s ctl=%s type=%d\n", s, ss, ctl, TT->ff->pl->type); +//dprintf(2, "s=%s ss=%s ctl=%s type=%d\n", s, ss, ctl, TT.ff->pl->type); if (!pplist) TT.hfd = 10; // Skip disabled blocks, handle pipes and backgrounding -- cgit v1.2.3