aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-07-21 13:20:14 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2017-07-21 13:20:14 +0200
commit42ba757d5e80ba25cc192939aa3525049f9e092f (patch)
treec89b3d378eb9f98eed81466122e269554a81400a
parent168f0ef8ddb6c840662bd15bad86177b0d238120 (diff)
downloadbusybox-w32-42ba757d5e80ba25cc192939aa3525049f9e092f.tar.gz
busybox-w32-42ba757d5e80ba25cc192939aa3525049f9e092f.tar.bz2
busybox-w32-42ba757d5e80ba25cc192939aa3525049f9e092f.zip
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>
-rw-r--r--shell/ash.c81
-rw-r--r--shell/ash_test/ash-quoting/mode_x.right10
-rwxr-xr-xshell/ash_test/ash-quoting/mode_x.tests14
3 files changed, 94 insertions, 11 deletions
diff --git a/shell/ash.c b/shell/ash.c
index b28731eb1..a461bb7df 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -1742,7 +1742,7 @@ number(const char *s)
1742} 1742}
1743 1743
1744/* 1744/*
1745 * Produce a possibly single quoted string suitable as input to the shell. 1745 * Produce a single quoted string suitable as input to the shell.
1746 * The return string is allocated on the stack. 1746 * The return string is allocated on the stack.
1747 */ 1747 */
1748static char * 1748static char *
@@ -1786,6 +1786,47 @@ single_quote(const char *s)
1786 return stackblock(); 1786 return stackblock();
1787} 1787}
1788 1788
1789/*
1790 * Produce a possibly single quoted string suitable as input to the shell.
1791 * If 'conditional' is nonzero, quoting is only done if the string contains
1792 * non-shellsafe characters, or is identical to a shell keyword (reserved
1793 * word); if it is zero, quoting is always done.
1794 * If quoting was done, the return string is allocated on the stack,
1795 * otherwise a pointer to the original string is returned.
1796 */
1797static const char *
1798maybe_single_quote(const char *s)
1799{
1800 const char *p = s;
1801
1802 while (*p) {
1803 /* Assuming ACSII */
1804 /* quote ctrl_chars space !"#$%&'()* */
1805 if (*p < '+')
1806 goto need_quoting;
1807 /* quote ;<=>? */
1808 if (*p >= ';' && *p <= '?')
1809 goto need_quoting;
1810 /* quote `[\ */
1811 if (*p == '`')
1812 goto need_quoting;
1813 if (*p == '[')
1814 goto need_quoting;
1815 if (*p == '\\')
1816 goto need_quoting;
1817 /* quote {|}~ DEL and high bytes */
1818 if (*p > 'z')
1819 goto need_quoting;
1820 /* Not quoting these: +,-./ 0-9 :@ A-Z ]^_ a-z */
1821 /* TODO: maybe avoid quoting % */
1822 p++;
1823 }
1824 return s;
1825
1826 need_quoting:
1827 return single_quote(s);
1828}
1829
1789 1830
1790/* ============ nextopt */ 1831/* ============ nextopt */
1791 1832
@@ -9700,18 +9741,36 @@ evalcommand(union node *cmd, int flags)
9700 9741
9701 /* Print the command if xflag is set. */ 9742 /* Print the command if xflag is set. */
9702 if (xflag) { 9743 if (xflag) {
9703 int n; 9744 const char *pfx = "";
9704 const char *p = " %s" + 1; 9745
9746 fdprintf(preverrout_fd, "%s", expandstr(ps4val()));
9705 9747
9706 fdprintf(preverrout_fd, p, expandstr(ps4val()));
9707 sp = varlist.list; 9748 sp = varlist.list;
9708 for (n = 0; n < 2; n++) { 9749 while (sp) {
9709 while (sp) { 9750 char *varval = sp->text;
9710 fdprintf(preverrout_fd, p, sp->text); 9751 char *eq = strchrnul(varval, '=');
9711 sp = sp->next; 9752 if (*eq)
9712 p = " %s"; 9753 eq++;
9713 } 9754 fdprintf(preverrout_fd, "%s%.*s%s",
9714 sp = arglist.list; 9755 pfx,
9756 (int)(eq - varval), varval,
9757 maybe_single_quote(eq)
9758 );
9759 sp = sp->next;
9760 pfx = " ";
9761 }
9762
9763 sp = arglist.list;
9764 while (sp) {
9765 fdprintf(preverrout_fd, "%s%s",
9766 pfx,
9767 /* always quote if matches reserved word: */
9768 findkwd(sp->text)
9769 ? single_quote(sp->text)
9770 : maybe_single_quote(sp->text)
9771 );
9772 sp = sp->next;
9773 pfx = " ";
9715 } 9774 }
9716 safe_write(preverrout_fd, "\n", 1); 9775 safe_write(preverrout_fd, "\n", 1);
9717 } 9776 }
diff --git a/shell/ash_test/ash-quoting/mode_x.right b/shell/ash_test/ash-quoting/mode_x.right
new file mode 100644
index 000000000..c2dd3550c
--- /dev/null
+++ b/shell/ash_test/ash-quoting/mode_x.right
@@ -0,0 +1,10 @@
1+ var1=val
2+ var2='one two'
3+ true '%s\n' one 'two '"'"'three' four
4+ this=command
5+ 'this=command'
6./mode_x.tests: line 1: this=command: not found
7+ true
8+ true
9+ 'if' true
10./mode_x.tests: line 1: if: not found
diff --git a/shell/ash_test/ash-quoting/mode_x.tests b/shell/ash_test/ash-quoting/mode_x.tests
new file mode 100755
index 000000000..16dae3f4b
--- /dev/null
+++ b/shell/ash_test/ash-quoting/mode_x.tests
@@ -0,0 +1,14 @@
1set -x
2
3var1=val
4var2='one two'
5true %s\\n one "two 'three" four
6
7# assignment:
8this=command
9# NOT assignment, +x code should show it quoted:
10"this=command"
11
12if true; then true; fi
13# +x code should quote 'if' here:
14"if" true