ash: improve set -x to quote strings as necessary
Basen on the patch from Martijn Dekker <martijn@inlv.org> function old new delta evalcommand 1161 1302 +141 maybe_single_quote - 60 +60 getoptscmd 527 546 +19 readtoken1 2819 2823 +4 localcmd 366 364 -2 evaltreenr 495 479 -16 evaltree 495 479 -16 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 3/3 up/down: 224/-34) Total: 190 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
168f0ef8dd
commit
42ba757d5e
81
shell/ash.c
81
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);
|
||||
}
|
||||
|
10
shell/ash_test/ash-quoting/mode_x.right
Normal file
10
shell/ash_test/ash-quoting/mode_x.right
Normal file
@ -0,0 +1,10 @@
|
||||
+ var1=val
|
||||
+ var2='one two'
|
||||
+ true '%s\n' one 'two '"'"'three' four
|
||||
+ this=command
|
||||
+ 'this=command'
|
||||
./mode_x.tests: line 1: this=command: not found
|
||||
+ true
|
||||
+ true
|
||||
+ 'if' true
|
||||
./mode_x.tests: line 1: if: not found
|
14
shell/ash_test/ash-quoting/mode_x.tests
Executable file
14
shell/ash_test/ash-quoting/mode_x.tests
Executable file
@ -0,0 +1,14 @@
|
||||
set -x
|
||||
|
||||
var1=val
|
||||
var2='one two'
|
||||
true %s\\n one "two 'three" four
|
||||
|
||||
# assignment:
|
||||
this=command
|
||||
# NOT assignment, +x code should show it quoted:
|
||||
"this=command"
|
||||
|
||||
if true; then true; fi
|
||||
# +x code should quote 'if' here:
|
||||
"if" true
|
Loading…
Reference in New Issue
Block a user