diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 81 |
1 files changed, 70 insertions, 11 deletions
diff --git a/shell/ash.c b/shell/ash.c index b28731e..a461bb7 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -1742,7 +1742,7 @@ number(const char *s) } /* - * Produce a possibly single quoted string suitable as input to the shell. + * Produce a single quoted string suitable as input to the shell. * The return string is allocated on the stack. */ static char * @@ -1786,6 +1786,47 @@ single_quote(const char *s) return stackblock(); } +/* + * Produce a possibly single quoted string suitable as input to the shell. + * If 'conditional' is nonzero, quoting is only done if the string contains + * non-shellsafe characters, or is identical to a shell keyword (reserved + * word); if it is zero, quoting is always done. + * If quoting was done, the return string is allocated on the stack, + * otherwise a pointer to the original string is returned. + */ +static const char * +maybe_single_quote(const char *s) +{ + const char *p = s; + + while (*p) { + /* Assuming ACSII */ + /* quote ctrl_chars space !"#$%&'()* */ + if (*p < '+') + goto need_quoting; + /* quote ;<=>? */ + if (*p >= ';' && *p <= '?') + goto need_quoting; + /* quote `[\ */ + if (*p == '`') + goto need_quoting; + if (*p == '[') + goto need_quoting; + if (*p == '\\') + goto need_quoting; + /* quote {|}~ DEL and high bytes */ + if (*p > 'z') + goto need_quoting; + /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */ + /* TODO: maybe avoid quoting % */ + p++; + } + return s; + + need_quoting: + return single_quote(s); +} + /* ============ nextopt */ @@ -9700,18 +9741,36 @@ evalcommand(union node *cmd, int flags) /* Print the command if xflag is set. */ if (xflag) { - int n; - const char *p = " %s" + 1; + const char *pfx = ""; + + fdprintf(preverrout_fd, "%s", expandstr(ps4val())); - fdprintf(preverrout_fd, p, expandstr(ps4val())); sp = varlist.list; - for (n = 0; n < 2; n++) { - while (sp) { - fdprintf(preverrout_fd, p, sp->text); - sp = sp->next; - p = " %s"; - } - sp = arglist.list; + while (sp) { + char *varval = sp->text; + char *eq = strchrnul(varval, '='); + if (*eq) + eq++; + fdprintf(preverrout_fd, "%s%.*s%s", + pfx, + (int)(eq - varval), varval, + maybe_single_quote(eq) + ); + sp = sp->next; + pfx = " "; + } + + sp = arglist.list; + while (sp) { + fdprintf(preverrout_fd, "%s%s", + pfx, + /* always quote if matches reserved word: */ + findkwd(sp->text) + ? single_quote(sp->text) + : maybe_single_quote(sp->text) + ); + sp = sp->next; + pfx = " "; } safe_write(preverrout_fd, "\n", 1); } |