aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
committerRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
commit0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch)
tree491d6184a44b8b525a4ca35759d622aecd7f6344 /shell
parent4859ddcb20616718efbea12c6bf8b27c469b68de (diff)
parentaaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff)
downloadbusybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c68
-rw-r--r--shell/ash_test/ash-arith/arith-postinc.right3
-rwxr-xr-xshell/ash_test/ash-arith/arith-postinc.tests4
-rw-r--r--shell/ash_test/ash-arith/arith.right78
-rwxr-xr-xshell/ash_test/ash-arith/arith.tests55
-rwxr-xr-xshell/ash_test/ash-arith/arith1.sub4
-rwxr-xr-xshell/ash_test/ash-arith/arith2.sub22
-rw-r--r--shell/ash_test/ash-comm/comm.right6
-rwxr-xr-xshell/ash_test/ash-comm/comm.tests20
-rw-r--r--shell/hush.c48
-rw-r--r--shell/hush_test/hush-arith/arith-postinc.right3
-rwxr-xr-xshell/hush_test/hush-arith/arith-postinc.tests4
-rw-r--r--shell/hush_test/hush-arith/arith.right37
-rwxr-xr-xshell/hush_test/hush-arith/arith.tests40
-rwxr-xr-xshell/hush_test/hush-arith/arith1.sub4
-rwxr-xr-xshell/hush_test/hush-arith/arith2.sub22
-rw-r--r--shell/hush_test/hush-comm/comm.right6
-rwxr-xr-xshell/hush_test/hush-comm/comm.tests20
-rw-r--r--shell/math.c71
19 files changed, 331 insertions, 184 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 9214982c1..98da20f8a 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -351,19 +351,6 @@ typedef long arith_t;
351# error "Do not even bother, ash will not run on NOMMU machine" 351# error "Do not even bother, ash will not run on NOMMU machine"
352#endif 352#endif
353 353
354/* We use a trick to have more optimized code (fewer pointer reloads):
355 * ash.c: extern struct globals *const ash_ptr_to_globals;
356 * ash_ptr_hack.c: struct globals *ash_ptr_to_globals;
357 * This way, compiler in ash.c knows the pointer can not change.
358 *
359 * However, this may break on weird arches or toolchains. In this case,
360 * set "-DBB_GLOBAL_CONST=''" in CONFIG_EXTRA_CFLAGS to disable
361 * this optimization.
362 */
363#ifndef BB_GLOBAL_CONST
364# define BB_GLOBAL_CONST const
365#endif
366
367#if ENABLE_PLATFORM_MINGW32 354#if ENABLE_PLATFORM_MINGW32
368# define FORKSHELL_DEBUG 0 355# define FORKSHELL_DEBUG 0
369 356
@@ -693,8 +680,7 @@ extern struct globals_misc *BB_GLOBAL_CONST ash_ptr_to_globals_misc;
693#endif 680#endif
694 681
695#define INIT_G_misc() do { \ 682#define INIT_G_misc() do { \
696 (*(struct globals_misc**)not_const_pp(&ash_ptr_to_globals_misc)) = xzalloc(sizeof(G_misc)); \ 683 XZALLOC_CONST_PTR(&ash_ptr_to_globals_misc, sizeof(G_misc)); \
697 barrier(); \
698 savestatus = -1; \ 684 savestatus = -1; \
699 curdir = nullstr; \ 685 curdir = nullstr; \
700 physdir = nullstr; \ 686 physdir = nullstr; \
@@ -1783,8 +1769,7 @@ extern struct globals_memstack *BB_GLOBAL_CONST ash_ptr_to_globals_memstack;
1783#define g_stacknleft (G_memstack.g_stacknleft) 1769#define g_stacknleft (G_memstack.g_stacknleft)
1784#define stackbase (G_memstack.stackbase ) 1770#define stackbase (G_memstack.stackbase )
1785#define INIT_G_memstack() do { \ 1771#define INIT_G_memstack() do { \
1786 (*(struct globals_memstack**)not_const_pp(&ash_ptr_to_globals_memstack)) = xzalloc(sizeof(G_memstack)); \ 1772 XZALLOC_CONST_PTR(&ash_ptr_to_globals_memstack, sizeof(G_memstack)); \
1787 barrier(); \
1788 g_stackp = &stackbase; \ 1773 g_stackp = &stackbase; \
1789 g_stacknxt = stackbase.space; \ 1774 g_stacknxt = stackbase.space; \
1790 g_stacknleft = MINSIZE; \ 1775 g_stacknleft = MINSIZE; \
@@ -2445,8 +2430,7 @@ extern struct globals_var *BB_GLOBAL_CONST ash_ptr_to_globals_var;
2445#endif 2430#endif
2446#define INIT_G_var() do { \ 2431#define INIT_G_var() do { \
2447 unsigned i; \ 2432 unsigned i; \
2448 (*(struct globals_var**)not_const_pp(&ash_ptr_to_globals_var)) = xzalloc(sizeof(G_var)); \ 2433 XZALLOC_CONST_PTR(&ash_ptr_to_globals_var, sizeof(G_var)); \
2449 barrier(); \
2450 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \ 2434 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
2451 varinit[i].flags = varinit_data[i].flags; \ 2435 varinit[i].flags = varinit_data[i].flags; \
2452 varinit[i].var_text = varinit_data[i].var_text; \ 2436 varinit[i].var_text = varinit_data[i].var_text; \
@@ -7840,14 +7824,19 @@ subevalvar(char *start, char *str, int strloc,
7840 if ((unsigned)len > (orig_len - pos)) 7824 if ((unsigned)len > (orig_len - pos))
7841 len = orig_len - pos; 7825 len = orig_len - pos;
7842 7826
7843 for (vstr = startp; pos; vstr++, pos--) { 7827 if (!quotes) {
7844 if (quotes && (unsigned char)*vstr == CTLESC) 7828 loc = mempcpy(startp, startp + pos, len);
7829 } else {
7830 for (vstr = startp; pos != 0; pos--) {
7831 if ((unsigned char)*vstr == CTLESC)
7832 vstr++;
7845 vstr++; 7833 vstr++;
7846 } 7834 }
7847 for (loc = startp; len; len--) { 7835 for (loc = startp; len != 0; len--) {
7848 if (quotes && (unsigned char)*vstr == CTLESC) 7836 if ((unsigned char)*vstr == CTLESC)
7837 *loc++ = *vstr++;
7849 *loc++ = *vstr++; 7838 *loc++ = *vstr++;
7850 *loc++ = *vstr++; 7839 }
7851 } 7840 }
7852 *loc = '\0'; 7841 *loc = '\0';
7853 goto out; 7842 goto out;
@@ -7901,7 +7890,7 @@ subevalvar(char *start, char *str, int strloc,
7901#if BASH_PATTERN_SUBST 7890#if BASH_PATTERN_SUBST
7902 workloc = expdest - (char *)stackblock(); 7891 workloc = expdest - (char *)stackblock();
7903 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 7892 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
7904 size_t no_meta_len; 7893 size_t no_meta_len, first_escaped;
7905 int len; 7894 int len;
7906 char *idx, *end; 7895 char *idx, *end;
7907 7896
@@ -7919,28 +7908,34 @@ subevalvar(char *start, char *str, int strloc,
7919 if (str[0] == '\0') 7908 if (str[0] == '\0')
7920 goto out1; 7909 goto out1;
7921 7910
7922 no_meta_len = (ENABLE_ASH_OPTIMIZE_FOR_SIZE || strpbrk(str, "*?[\\")) ? 0 : strlen(str); 7911 first_escaped = (str[0] == '\\' && str[1]);
7912 /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
7913 * as literal too (as it is semi-common, and easy to accomodate
7914 * by just using str + 1).
7915 */
7916 no_meta_len = strpbrk(str + first_escaped * 2, "*?[\\") ? 0 : strlen(str);
7923 len = 0; 7917 len = 0;
7924 idx = startp; 7918 idx = startp;
7925 end = str - 1; 7919 end = str - 1;
7926 while (idx <= end) { 7920 while (idx <= end) {
7927 try_to_match: 7921 try_to_match:
7928 if (no_meta_len == 0) { 7922 if (no_meta_len == 0) {
7929 /* pattern has meta chars, have to glob; or ENABLE_ASH_OPTIMIZE_FOR_SIZE */ 7923 /* pattern has meta chars, have to glob */
7930 loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1); 7924 loc = scanright(idx, rmesc, rmescend, str, quotes, /*match_at_start:*/ 1);
7931 } else { 7925 } else {
7932 /* Testcase for very slow replace (performs about 22k replaces): 7926 /* Testcase for very slow replace (performs about 22k replaces):
7933 * x=:::::::::::::::::::::: 7927 * x=::::::::::::::::::::::
7934 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} 7928 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
7935 * echo "${x//:/|}" 7929 * echo "${x//:/|}"
7930 * To test "first_escaped" logic, replace : with *.
7936 */ 7931 */
7937 if (strncmp(rmesc, str, no_meta_len) != 0) 7932 if (strncmp(rmesc, str + first_escaped, no_meta_len - first_escaped) != 0)
7938 goto no_match; 7933 goto no_match;
7939 loc = idx; 7934 loc = idx;
7940 if (!quotes) { 7935 if (!quotes) {
7941 loc += no_meta_len; 7936 loc += no_meta_len - first_escaped;
7942 } else { 7937 } else {
7943 size_t n = no_meta_len; 7938 size_t n = no_meta_len - first_escaped;
7944 do { 7939 do {
7945 if ((unsigned char)*loc == CTLESC) 7940 if ((unsigned char)*loc == CTLESC)
7946 loc++; 7941 loc++;
@@ -11811,14 +11806,14 @@ static void freestrings(struct strpush *sp)
11811 INT_OFF; 11806 INT_OFF;
11812 do { 11807 do {
11813 struct strpush *psp; 11808 struct strpush *psp;
11814 11809#if ENABLE_ASH_ALIAS
11815 if (sp->ap) { 11810 if (sp->ap) {
11816 sp->ap->flag &= ~ALIASINUSE; 11811 sp->ap->flag &= ~ALIASINUSE;
11817 if (sp->ap->flag & ALIASDEAD) { 11812 if (sp->ap->flag & ALIASDEAD) {
11818 unalias(sp->ap->name); 11813 unalias(sp->ap->name);
11819 } 11814 }
11820 } 11815 }
11821 11816#endif
11822 psp = sp; 11817 psp = sp;
11823 sp = sp->spfree; 11818 sp = sp->spfree;
11824 11819
@@ -15497,7 +15492,7 @@ init(void)
15497 15492
15498 15493
15499//usage:#define ash_trivial_usage 15494//usage:#define ash_trivial_usage
15500//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" 15495//usage: "[-il] [-|+Cabefmnuvx] [-|+o OPT]... [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
15501//////// comes from ^^^^^^^^^^optletters 15496//////// comes from ^^^^^^^^^^optletters
15502//usage:#define ash_full_usage "\n\n" 15497//usage:#define ash_full_usage "\n\n"
15503//usage: "Unix shell interpreter" 15498//usage: "Unix shell interpreter"
@@ -15764,13 +15759,12 @@ int ash_main(int argc UNUSED_PARAM, char **argv)
15764 } 15759 }
15765 state2: 15760 state2:
15766 state = 3; 15761 state = 3;
15767 if ( 15762 if (iflag
15768#if ENABLE_PLATFORM_POSIX 15763#if ENABLE_PLATFORM_POSIX
15769#ifndef linux 15764#ifndef linux
15770 getuid() == geteuid() && getgid() == getegid() && 15765 && getuid() == geteuid() && getgid() == getegid()
15771#endif 15766#endif
15772#endif 15767#endif
15773 iflag
15774 ) { 15768 ) {
15775 const char *shinit = lookupvar("ENV"); 15769 const char *shinit = lookupvar("ENV");
15776 if (shinit != NULL && *shinit != '\0') 15770 if (shinit != NULL && *shinit != '\0')
diff --git a/shell/ash_test/ash-arith/arith-postinc.right b/shell/ash_test/ash-arith/arith-postinc.right
index c95ce02bf..5cd4ba6b4 100644
--- a/shell/ash_test/ash-arith/arith-postinc.right
+++ b/shell/ash_test/ash-arith/arith-postinc.right
@@ -2,4 +2,7 @@
21 1 21 1
31 1 31 1
41 1 41 1
56 6
67 7
77 7
5Ok:0 8Ok:0
diff --git a/shell/ash_test/ash-arith/arith-postinc.tests b/shell/ash_test/ash-arith/arith-postinc.tests
index 3fd9bfed5..f2ae778df 100755
--- a/shell/ash_test/ash-arith/arith-postinc.tests
+++ b/shell/ash_test/ash-arith/arith-postinc.tests
@@ -2,4 +2,8 @@ echo 1 $((0++1))
2echo 1 $((0--1)) 2echo 1 $((0--1))
3x=-1; echo 1 $((0-$x)) 3x=-1; echo 1 $((0-$x))
4x=+1; echo 1 $((0+$x)) 4x=+1; echo 1 $((0+$x))
5a=3
6echo 6 $((a+++3)) # a++ + 3
7echo 7 $(((a)+++3)) # a + + + 3
8echo 7 $(((a)+++3)) # a + + + 3
5echo Ok:$? 9echo Ok:$?
diff --git a/shell/ash_test/ash-arith/arith.right b/shell/ash_test/ash-arith/arith.right
index 6936f1269..61fcab55e 100644
--- a/shell/ash_test/ash-arith/arith.right
+++ b/shell/ash_test/ash-arith/arith.right
@@ -43,40 +43,60 @@ Format: 'expected actual'
434 4 434 4
4429 29 4429 29
455 5 455 5
46unary plus, minus
46-4 -4 47-4 -4
474 4 484 4
49conditional expressions
481 1 501 1
4932 32 5132 32
5032 32 5232 32
511 1 531 1
521 1 541 1
5332 32 5532 32
56check that the unevaluated part of the ternary operator does not do evaluation or assignment
5420 20 5720 20
5530 30 5830 30
5620 20 5920 20
5730 30 6030 30
58./arith.tests: line 117: arithmetic syntax error 61check precedence of assignment vs. conditional operator
62./arith.tests: line 116: arithmetic syntax error
63check precedence of assignment vs. conditional operator
64associativity of assignment-operator operator
596 6 656 6
606,5,3 6,5,3 666,5,3 6,5,3
67octal, hex
61263 263 68263 263
62255 255 69255 255
6340 40 7040 40
64./arith.tests: line 163: arithmetic syntax error 71other bases
65./arith.tests: line 165: divide by zero 7210 10
66./arith.tests: let: line 166: arithmetic syntax error 7310 10
67./arith.tests: line 167: arithmetic syntax error 7410 10
68./arith.tests: let: line 168: arithmetic syntax error 7510 10
7610 10
7710 10
7836 36
7936 36
8062 62
8163 63
82missing number after base
830 0
84./arith.tests: line 162: arithmetic syntax error
85./arith.tests: line 164: divide by zero
86./arith.tests: let: line 165: arithmetic syntax error
87./arith.tests: line 166: arithmetic syntax error
88./arith.tests: let: line 167: arithmetic syntax error
69abc 89abc
70def 90def
71ghi 91ghi
72./arith.tests: line 191: arithmetic syntax error 92./arith.tests: line 190: arithmetic syntax error
7316 16 9316 16
74./arith.tests: line 196: arithmetic syntax error 94./arith.tests: line 195: arithmetic syntax error
75./arith.tests: line 197: malformed ?: operator 95./arith.tests: line 196: malformed ?: operator
76./arith.tests: line 198: arithmetic syntax error 96./arith.tests: line 197: arithmetic syntax error
779 9 979 9
78./arith.tests: line 205: arithmetic syntax error 98./arith.tests: line 204: arithmetic syntax error
79./arith.tests: line 208: arithmetic syntax error 99./arith.tests: line 207: arithmetic syntax error
809 9 1009 9
819 9 1019 9
829 9 1029 9
@@ -97,14 +117,17 @@ ghi
973 3 1173 3
984 4 1184 4
994 4 1194 4
100./arith.tests: line 257: arithmetic syntax error 1207 7
121./arith.tests: line 256: arithmetic syntax error
122./arith.tests: line 258: arithmetic syntax error
101./arith.tests: line 259: arithmetic syntax error 123./arith.tests: line 259: arithmetic syntax error
102./arith.tests: line 260: arithmetic syntax error 124./arith.tests: line 261: arithmetic syntax error
103./arith.tests: line 262: arithmetic syntax error 125./arith.tests: line 262: arithmetic syntax error
104./arith.tests: line 263: arithmetic syntax error
1054 4 1264 4
1067 7 1277 7
107-7 -7 128-7 -7
1297
1307
108./arith1.sub: line 2: arithmetic syntax error 131./arith1.sub: line 2: arithmetic syntax error
109./arith1.sub: line 3: arithmetic syntax error 132./arith1.sub: line 3: arithmetic syntax error
110./arith1.sub: line 4: arithmetic syntax error 133./arith1.sub: line 4: arithmetic syntax error
@@ -119,11 +142,12 @@ ghi
1192 2 1422 2
120-2 -2 143-2 -2
1211 1 1441 1
122./arith1.sub: line 37: arithmetic syntax error 1457
123./arith2.sub: line 2: arithmetic syntax error 1467
124./arith2.sub: line 3: arithmetic syntax error 1477
125./arith2.sub: line 4: arithmetic syntax error 1487
126./arith2.sub: line 5: arithmetic syntax error 1497
1507
1275 5 1515 5
1281 1 1521 1
1296 6 1536 6
@@ -132,11 +156,17 @@ ghi
1321 1 1561 1
1334 4 1574 4
1340 0 1580 0
135./arith2.sub: line 42: arithmetic syntax error 159-7
136./arith2.sub: line 47: arithmetic syntax error 160-7
1617
1627
163-7 -7
164-7 -7
1657 7
1667 7
1378 12 1678 12
138./arith.tests: line 290: arithmetic syntax error 168./arith.tests: line 289: arithmetic syntax error
13942 16942
14042 17042
14142 17142
142./arith.tests: line 302: a[b[c]d]=e: not found 172./arith.tests: line 301: a[b[c]d]=e: not found
diff --git a/shell/ash_test/ash-arith/arith.tests b/shell/ash_test/ash-arith/arith.tests
index d65758e7d..b9cb8ba4c 100755
--- a/shell/ash_test/ash-arith/arith.tests
+++ b/shell/ash_test/ash-arith/arith.tests
@@ -75,11 +75,11 @@ echo 4 $(( iv &= 4 ))
75echo 29 $(( iv += (jv + 9))) 75echo 29 $(( iv += (jv + 9)))
76echo 5 $(( (iv + 4) % 7 )) 76echo 5 $(( (iv + 4) % 7 ))
77 77
78# unary plus, minus 78echo unary plus, minus
79echo -4 $(( +4 - 8 )) 79echo -4 $(( +4 - 8 ))
80echo 4 $(( -4 + 8 )) 80echo 4 $(( -4 + 8 ))
81 81
82# conditional expressions 82echo conditional expressions
83echo 1 $(( 4<5 ? 1 : 32)) 83echo 1 $(( 4<5 ? 1 : 32))
84echo 32 $(( 4>5 ? 1 : 32)) 84echo 32 $(( 4>5 ? 1 : 32))
85echo 32 $(( 4>(2+3) ? 1 : 32)) 85echo 32 $(( 4>(2+3) ? 1 : 32))
@@ -87,8 +87,7 @@ echo 1 $(( 4<(2+3) ? 1 : 32))
87echo 1 $(( (2+2)<(2+3) ? 1 : 32)) 87echo 1 $(( (2+2)<(2+3) ? 1 : 32))
88echo 32 $(( (2+2)>(2+3) ? 1 : 32)) 88echo 32 $(( (2+2)>(2+3) ? 1 : 32))
89 89
90# check that the unevaluated part of the ternary operator does not do 90echo check that the unevaluated part of the ternary operator does not do evaluation or assignment
91# evaluation or assignment
92x=i+=2 91x=i+=2
93y=j+=2 92y=j+=2
94#ash# declare -i i=1 j=1 93#ash# declare -i i=1 j=1
@@ -109,20 +108,20 @@ echo 20 $((1 ? 20 : (x+=2)))
109echo 30 $((0 ? (y+=2) : 30)) 108echo 30 $((0 ? (y+=2) : 30))
110#ash# echo $i,$y # ash mishandles this 109#ash# echo $i,$y # ash mishandles this
111 110
112# check precedence of assignment vs. conditional operator 111echo check precedence of assignment vs. conditional operator
113# should be an error 112# should be an error
114#ash# declare -i x=2 113#ash# declare -i x=2
115 x=2 114 x=2
116#ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash: 115#ashnote# bash reports error but continues, ash aborts - using subshell to 'emulate' bash:
117( y=$((1 ? 20 : x+=2)) ) 116( y=$((1 ? 20 : x+=2)) )
118 117
119# check precedence of assignment vs. conditional operator 118echo check precedence of assignment vs. conditional operator
120#ash# declare -i x=2 119#ash# declare -i x=2
121 x=2 120 x=2
122# ash says "line NNN: syntax error: 0 ? x+=2 : 20" 121# ash says "line NNN: syntax error: 0 ? x+=2 : 20"
123#ash# echo 20 $((0 ? x+=2 : 20)) 122#ash# echo 20 $((0 ? x+=2 : 20))
124 123
125# associativity of assignment-operator operator 124echo associativity of assignment-operator operator
126#ash# declare -i i=1 j=2 k=3 125#ash# declare -i i=1 j=2 k=3
127i=1 126i=1
128j=2 127j=2
@@ -130,7 +129,7 @@ k=3
130echo 6 $((i += j += k)) 129echo 6 $((i += j += k))
131echo 6,5,3 $i,$j,$k 130echo 6,5,3 $i,$j,$k
132 131
133# octal, hex 132echo octal, hex
134echo 263 $(( 0x100 | 007 )) 133echo 263 $(( 0x100 | 007 ))
135echo 255 $(( 0xff )) 134echo 255 $(( 0xff ))
136#ash# echo 255 $(( 16#ff )) 135#ash# echo 255 $(( 16#ff ))
@@ -139,25 +138,25 @@ echo 255 $(( 0xff ))
139 138
140echo 40 $(( 8 ^ 32 )) 139echo 40 $(( 8 ^ 32 ))
141 140
142#ash# # other bases 141echo other bases
143#ash# echo 10 $(( 16#a )) 142echo 10 $(( 16#a ))
144#ash# echo 10 $(( 32#a )) 143echo 10 $(( 32#a ))
145#ash# echo 10 $(( 56#a )) 144echo 10 $(( 56#a ))
146#ash# echo 10 $(( 64#a )) 145echo 10 $(( 64#a ))
147#ash# 146
148#ash# echo 10 $(( 16#A )) 147echo 10 $(( 16#A ))
149#ash# echo 10 $(( 32#A )) 148echo 10 $(( 32#A ))
150#ash# echo 36 $(( 56#A )) 149echo 36 $(( 56#A ))
151#ash# echo 36 $(( 64#A )) 150echo 36 $(( 64#A ))
152#ash# 151
153#ash# echo 62 $(( 64#@ )) 152echo 62 $(( 64#@ ))
154#ash# echo 63 $(( 64#_ )) 153echo 63 $(( 64#_ ))
155 154
156#ash# # weird bases (error) 155#ash# # weird bases (error)
157#ash# echo $(( 3425#56 )) 156#ash# echo $(( 3425#56 ))
158 157
159#ash# # missing number after base 158echo missing number after base
160#ash# echo 0 $(( 2# )) 159echo 0 $(( 2# ))
161 160
162# these should generate errors 161# these should generate errors
163( echo $(( 7 = 43 )) ) 162( echo $(( 7 = 43 )) )
@@ -252,8 +251,8 @@ echo 3 $x
252echo 4 $(( ++x )) 251echo 4 $(( ++x ))
253echo 4 $x 252echo 4 $x
254 253
255# bash 3.2 apparently thinks that ++7 is 7 254# ++ is not a inc operator on non-variable, it is the + + sequence
256#ash# echo 7 $(( ++7 )) 255echo 7 $(( ++7 ))
257( echo $(( 7-- )) ) 256( echo $(( 7-- )) )
258 257
259( echo $(( --x=7 )) ) 258( echo $(( --x=7 )) )
@@ -267,9 +266,9 @@ echo 4 $x
267echo 7 $(( +7 )) 266echo 7 $(( +7 ))
268echo -7 $(( -7 )) 267echo -7 $(( -7 ))
269 268
270# bash 3.2 apparently thinks that ++7 is 7 269# ++ is not a inc operator on non-variable, it is the + + sequence
271#ash# echo $(( ++7 )) 270echo $(( ++7 ))
272#ash# echo $(( --7 )) 271echo $(( --7 ))
273 272
274${THIS_SH} ./arith1.sub 273${THIS_SH} ./arith1.sub
275${THIS_SH} ./arith2.sub 274${THIS_SH} ./arith2.sub
diff --git a/shell/ash_test/ash-arith/arith1.sub b/shell/ash_test/ash-arith/arith1.sub
index 80aa99922..a36785c67 100755
--- a/shell/ash_test/ash-arith/arith1.sub
+++ b/shell/ash_test/ash-arith/arith1.sub
@@ -35,6 +35,6 @@ echo 1 $a
35 35
36#ash# (( ++ )) 36#ash# (( ++ ))
37( echo $(( +++7 )) ) 37( echo $(( +++7 )) )
38# bash 3.2 apparently thinks that ++ +7 is 7 38# ++ is not a inc operator on non-variable, it is the + + sequence
39#ash# echo $(( ++ + 7 )) 39echo $(( ++ + 7 ))
40#ash# (( -- )) 40#ash# (( -- ))
diff --git a/shell/ash_test/ash-arith/arith2.sub b/shell/ash_test/ash-arith/arith2.sub
index 9105059db..8d7918114 100755
--- a/shell/ash_test/ash-arith/arith2.sub
+++ b/shell/ash_test/ash-arith/arith2.sub
@@ -1,4 +1,4 @@
1# bash 3.2 apparently thinks that ++7 is 7 etc 1# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences
2( echo $(( --7 )) ) 2( echo $(( --7 )) )
3( echo $(( ++7 )) ) 3( echo $(( ++7 )) )
4( echo $(( -- 7 )) ) 4( echo $(( -- 7 )) )
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a ))
37echo 0 $a 37echo 0 $a
38 38
39#ash# (( -- )) 39#ash# (( -- ))
40# bash 3.2 apparently thinks that ---7 is -7 40# -- is not a dec operator on non-variable, it is the - - sequence
41#ash# echo $(( ---7 )) 41echo $(( ---7 ))
42( echo $(( -- - 7 )) ) 42( echo $(( -- - 7 )) )
43 43
44#ash# (( ++ )) 44#ash# (( ++ ))
45# bash 3.2: 7 45# ++ is not a inc operator on non-variable, it is the + + sequence
46#ash# echo 7 $(( ++7 )) 46echo $(( ++7 ))
47( echo $(( ++ + 7 )) ) 47( echo $(( ++ + 7 )) )
48 48
49# bash 3.2: -7 49echo -7 $(( ++-7 ))
50#ash# echo -7 $(( ++-7 )) 50echo -7 $(( ++ - 7 ))
51# bash 3.2: -7
52#ash# echo -7 $(( ++ - 7 ))
53 51
54# bash 3.2: 7 52echo 7 $(( +--7 ))
55#ash# echo 7 $(( +--7 )) 53echo 7 $(( -- + 7 ))
56# bash 3.2: 7
57#ash# echo 7 $(( -- + 7 ))
diff --git a/shell/ash_test/ash-comm/comm.right b/shell/ash_test/ash-comm/comm.right
new file mode 100644
index 000000000..1d836656f
--- /dev/null
+++ b/shell/ash_test/ash-comm/comm.right
@@ -0,0 +1,6 @@
1./SCRIPT.sh:
2 /proc/N/comm: SCRIPT.sh
3exec ./SCRIPT.sh:
4 /proc/N/comm: SCRIPT.sh
5sh ./SCRIPT.sh:
6 /proc/N/comm: ash
diff --git a/shell/ash_test/ash-comm/comm.tests b/shell/ash_test/ash-comm/comm.tests
new file mode 100755
index 000000000..671bfc176
--- /dev/null
+++ b/shell/ash_test/ash-comm/comm.tests
@@ -0,0 +1,20 @@
1{
2echo "#!$THIS_SH"
3echo 'procdir=/proc/$$'
4#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"'
5echo 'echo " /proc/N/comm: $(cat $procdir/comm)"'
6} >SCRIPT.sh
7chmod 755 SCRIPT.sh
8
9# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
10echo './SCRIPT.sh:'
11./SCRIPT.sh
12
13# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
14echo 'exec ./SCRIPT.sh:'
15(exec ./SCRIPT.sh)
16
17echo 'sh ./SCRIPT.sh:'
18$THIS_SH ./SCRIPT.sh
19
20rm SCRIPT.sh
diff --git a/shell/hush.c b/shell/hush.c
index 6d472337f..6a27b1634 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -339,7 +339,7 @@
339 * therefore we don't show them either. 339 * therefore we don't show them either.
340 */ 340 */
341//usage:#define hush_trivial_usage 341//usage:#define hush_trivial_usage
342//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE [ARGS] | -s [ARGS]]" 342//usage: "[-enxl] [-c 'SCRIPT' [ARG0 ARGS] | FILE ARGS | -s ARGS]"
343//usage:#define hush_full_usage "\n\n" 343//usage:#define hush_full_usage "\n\n"
344//usage: "Unix shell interpreter" 344//usage: "Unix shell interpreter"
345 345
@@ -373,7 +373,7 @@
373# define F_DUPFD_CLOEXEC F_DUPFD 373# define F_DUPFD_CLOEXEC F_DUPFD
374#endif 374#endif
375 375
376#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !(ENABLE_ASH || ENABLE_SH_IS_ASH || ENABLE_BASH_IS_ASH) 376#if ENABLE_FEATURE_SH_EMBEDDED_SCRIPTS && !ENABLE_SHELL_ASH
377# include "embedded_scripts.h" 377# include "embedded_scripts.h"
378#else 378#else
379# define NUM_SCRIPTS 0 379# define NUM_SCRIPTS 0
@@ -3360,7 +3360,7 @@ static int glob_brace(char *pattern, o_string *o, int n)
3360 * NEXT points past the terminator of the first element, and REST 3360 * NEXT points past the terminator of the first element, and REST
3361 * points past the final }. We will accumulate result names from 3361 * points past the final }. We will accumulate result names from
3362 * recursive runs for each brace alternative in the buffer using 3362 * recursive runs for each brace alternative in the buffer using
3363 * GLOB_APPEND. */ 3363 * GLOB_APPEND. */
3364 3364
3365 p = begin + 1; 3365 p = begin + 1;
3366 while (1) { 3366 while (1) {
@@ -6311,7 +6311,7 @@ static char *encode_then_expand_vararg(const char *str, int handle_squotes, int
6311 6311
6312/* Expanding ARG in ${var+ARG}, ${var-ARG} 6312/* Expanding ARG in ${var+ARG}, ${var-ARG}
6313 */ 6313 */
6314static int encode_then_append_var_plusminus(o_string *output, int n, 6314static NOINLINE int encode_then_append_var_plusminus(o_string *output, int n,
6315 char *str, int dquoted) 6315 char *str, int dquoted)
6316{ 6316{
6317 struct in_str input; 6317 struct in_str input;
@@ -6472,16 +6472,21 @@ static arith_t expand_and_evaluate_arith(const char *arg, const char **errmsg_p)
6472/* ${var/[/]pattern[/repl]} helpers */ 6472/* ${var/[/]pattern[/repl]} helpers */
6473static char *strstr_pattern(char *val, const char *pattern, int *size) 6473static char *strstr_pattern(char *val, const char *pattern, int *size)
6474{ 6474{
6475 int sz = strcspn(pattern, "*?[\\"); 6475 int first_escaped = (pattern[0] == '\\' && pattern[1]);
6476 if (pattern[sz] == '\0') { 6476 /* "first_escaped" trick allows to treat e.g. "\*no_glob_chars"
6477 * as literal too (as it is semi-common, and easy to accomodate
6478 * by just using str + 1).
6479 */
6480 int sz = strcspn(pattern + first_escaped * 2, "*?[\\");
6481 if ((pattern + first_escaped * 2)[sz] == '\0') {
6477 /* Optimization for trivial patterns. 6482 /* Optimization for trivial patterns.
6478 * Testcase for very slow replace (performs about 22k replaces): 6483 * Testcase for very slow replace (performs about 22k replaces):
6479 * x=:::::::::::::::::::::: 6484 * x=::::::::::::::::::::::
6480 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x} 6485 * x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;x=$x$x;echo ${#x}
6481 * echo "${x//:/|}" 6486 * echo "${x//:/|}"
6482 */ 6487 */
6483 *size = sz; 6488 *size = sz + first_escaped;
6484 return strstr(val, pattern); 6489 return strstr(val, pattern + first_escaped);
6485 } 6490 }
6486 6491
6487 while (1) { 6492 while (1) {
@@ -10220,7 +10225,7 @@ int hush_main(int argc, char **argv)
10220 10225
10221 cached_getpid = getpid(); /* for tcsetpgrp() during init */ 10226 cached_getpid = getpid(); /* for tcsetpgrp() during init */
10222 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */ 10227 G.root_pid = cached_getpid; /* for $PID (NOMMU can override via -$HEXPID:HEXPPID:...) */
10223 G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */ 10228 G.root_ppid = getppid(); /* for $PPID (NOMMU can override) */
10224 10229
10225 /* Deal with HUSH_VERSION */ 10230 /* Deal with HUSH_VERSION */
10226 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION"); 10231 debug_printf_env("unsetenv '%s'\n", "HUSH_VERSION");
@@ -10351,6 +10356,29 @@ int hush_main(int argc, char **argv)
10351 /* Well, we cannot just declare interactiveness, 10356 /* Well, we cannot just declare interactiveness,
10352 * we have to have some stuff (ctty, etc) */ 10357 * we have to have some stuff (ctty, etc) */
10353 /* G_interactive_fd++; */ 10358 /* G_interactive_fd++; */
10359//There are a few cases where bash -i -c 'SCRIPT'
10360//has visible effect (differs from bash -c 'SCRIPT'):
10361//it ignores TERM:
10362// bash -i -c 'kill $$; echo ALIVE'
10363// ALIVE
10364//it resets SIG_INGed HUP to SIG_DFL:
10365// trap '' hup; bash -i -c 'kill -hup $$; echo ALIVE'
10366// Hangup [the message is not printed by bash, it's the shell which started it]
10367//is talkative about jobs and exiting:
10368// bash -i -c 'sleep 1 & exit'
10369// [1] 16170
10370// exit
10371//includes $ENV file (only if run as "sh"):
10372// echo last >/tmp/ENV; ENV=/tmp/ENV sh -i -c 'echo HERE'
10373// last: cannot open /var/log/wtmp: No such file or directory
10374// HERE
10375//(under "bash", it's the opposite: it runs $BASH_ENV file only *without* -i).
10376//
10377//ash -i -c 'sleep 3; sleep 3', on ^C, drops into a prompt instead of exiting
10378//(this may be a bug, bash does not do this).
10379//(ash -i -c 'sleep 3' won't show this, the last command gets auto-"exec"ed)
10380//
10381//None of the above feel like useful features people would rely on.
10354 break; 10382 break;
10355 case 's': 10383 case 's':
10356 G.opt_s = 1; 10384 G.opt_s = 1;
@@ -11727,7 +11755,7 @@ static int FAST_FUNC builtin_fg_bg(char **argv)
11727 /* TODO: bash prints a string representation 11755 /* TODO: bash prints a string representation
11728 * of job being foregrounded (like "sleep 1 | cat") */ 11756 * of job being foregrounded (like "sleep 1 | cat") */
11729 if (argv[0][0] == 'f' && G_saved_tty_pgrp) { 11757 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
11730 /* Put the job into the foreground. */ 11758 /* Put the job into the foreground. */
11731 tcsetpgrp(G_interactive_fd, pi->pgrp); 11759 tcsetpgrp(G_interactive_fd, pi->pgrp);
11732 } 11760 }
11733 11761
diff --git a/shell/hush_test/hush-arith/arith-postinc.right b/shell/hush_test/hush-arith/arith-postinc.right
index c95ce02bf..5cd4ba6b4 100644
--- a/shell/hush_test/hush-arith/arith-postinc.right
+++ b/shell/hush_test/hush-arith/arith-postinc.right
@@ -2,4 +2,7 @@
21 1 21 1
31 1 31 1
41 1 41 1
56 6
67 7
77 7
5Ok:0 8Ok:0
diff --git a/shell/hush_test/hush-arith/arith-postinc.tests b/shell/hush_test/hush-arith/arith-postinc.tests
index 3fd9bfed5..f2ae778df 100755
--- a/shell/hush_test/hush-arith/arith-postinc.tests
+++ b/shell/hush_test/hush-arith/arith-postinc.tests
@@ -2,4 +2,8 @@ echo 1 $((0++1))
2echo 1 $((0--1)) 2echo 1 $((0--1))
3x=-1; echo 1 $((0-$x)) 3x=-1; echo 1 $((0-$x))
4x=+1; echo 1 $((0+$x)) 4x=+1; echo 1 $((0+$x))
5a=3
6echo 6 $((a+++3)) # a++ + 3
7echo 7 $(((a)+++3)) # a + + + 3
8echo 7 $(((a)+++3)) # a + + + 3
5echo Ok:$? 9echo Ok:$?
diff --git a/shell/hush_test/hush-arith/arith.right b/shell/hush_test/hush-arith/arith.right
index c48e468a5..a8612295e 100644
--- a/shell/hush_test/hush-arith/arith.right
+++ b/shell/hush_test/hush-arith/arith.right
@@ -70,6 +70,19 @@ octal, hex
70263 263 70263 263
71255 255 71255 255
7240 40 7240 40
73other bases
7410 10
7510 10
7610 10
7710 10
7810 10
7910 10
8036 36
8136 36
8262 62
8363 63
84missing number after base
850 0
73hush: arithmetic syntax error 86hush: arithmetic syntax error
74hush: divide by zero 87hush: divide by zero
75hush: can't execute 'let': No such file or directory 88hush: can't execute 'let': No such file or directory
@@ -106,6 +119,7 @@ hush: arithmetic syntax error
1063 3 1193 3
1074 4 1204 4
1084 4 1214 4
1227 7
109hush: arithmetic syntax error 123hush: arithmetic syntax error
110hush: arithmetic syntax error 124hush: arithmetic syntax error
111hush: arithmetic syntax error 125hush: arithmetic syntax error
@@ -114,6 +128,8 @@ hush: arithmetic syntax error
1144 4 1284 4
1157 7 1297 7
116-7 -7 130-7 -7
1317
1327
117hush: arithmetic syntax error 133hush: arithmetic syntax error
118hush: arithmetic syntax error 134hush: arithmetic syntax error
119hush: arithmetic syntax error 135hush: arithmetic syntax error
@@ -128,11 +144,12 @@ hush: arithmetic syntax error
1282 2 1442 2
129-2 -2 145-2 -2
1301 1 1461 1
131hush: arithmetic syntax error 1477
132hush: arithmetic syntax error 1487
133hush: arithmetic syntax error 1497
134hush: arithmetic syntax error 1507
135hush: arithmetic syntax error 1517
1527
1365 5 1535 5
1371 1 1541 1
1386 6 1556 6
@@ -141,8 +158,14 @@ hush: arithmetic syntax error
1411 1 1581 1
1424 4 1594 4
1430 0 1600 0
144hush: arithmetic syntax error 161-7
145hush: arithmetic syntax error 162-7
1637
1647
165-7 -7
166-7 -7
1677 7
1687 7
1468 12 1698 12
147hush: arithmetic syntax error 170hush: arithmetic syntax error
14842 17142
diff --git a/shell/hush_test/hush-arith/arith.tests b/shell/hush_test/hush-arith/arith.tests
index bc6b341d1..6b707486c 100755
--- a/shell/hush_test/hush-arith/arith.tests
+++ b/shell/hush_test/hush-arith/arith.tests
@@ -142,25 +142,25 @@ echo 255 $(( 0xff ))
142 142
143echo 40 $(( 8 ^ 32 )) 143echo 40 $(( 8 ^ 32 ))
144 144
145#ash# # other bases 145echo other bases
146#ash# echo 10 $(( 16#a )) 146echo 10 $(( 16#a ))
147#ash# echo 10 $(( 32#a )) 147echo 10 $(( 32#a ))
148#ash# echo 10 $(( 56#a )) 148echo 10 $(( 56#a ))
149#ash# echo 10 $(( 64#a )) 149echo 10 $(( 64#a ))
150#ash# 150
151#ash# echo 10 $(( 16#A )) 151echo 10 $(( 16#A ))
152#ash# echo 10 $(( 32#A )) 152echo 10 $(( 32#A ))
153#ash# echo 36 $(( 56#A )) 153echo 36 $(( 56#A ))
154#ash# echo 36 $(( 64#A )) 154echo 36 $(( 64#A ))
155#ash# 155
156#ash# echo 62 $(( 64#@ )) 156echo 62 $(( 64#@ ))
157#ash# echo 63 $(( 64#_ )) 157echo 63 $(( 64#_ ))
158 158
159#ash# # weird bases (error) 159#ash# # weird bases (error)
160#ash# echo $(( 3425#56 )) 160#ash# echo $(( 3425#56 ))
161 161
162#ash# # missing number after base 162echo missing number after base
163#ash# echo 0 $(( 2# )) 163echo 0 $(( 2# ))
164 164
165# these should generate errors 165# these should generate errors
166( echo $(( 7 = 43 )) ) 166( echo $(( 7 = 43 )) )
@@ -255,8 +255,8 @@ echo 3 $x
255echo 4 $(( ++x )) 255echo 4 $(( ++x ))
256echo 4 $x 256echo 4 $x
257 257
258# bash 3.2 apparently thinks that ++7 is 7 258# ++ is not a inc operator on non-variable, it is the + + sequence
259#ash# echo 7 $(( ++7 )) 259echo 7 $(( ++7 ))
260( echo $(( 7-- )) ) 260( echo $(( 7-- )) )
261 261
262( echo $(( --x=7 )) ) 262( echo $(( --x=7 )) )
@@ -270,9 +270,9 @@ echo 4 $x
270echo 7 $(( +7 )) 270echo 7 $(( +7 ))
271echo -7 $(( -7 )) 271echo -7 $(( -7 ))
272 272
273# bash 3.2 apparently thinks that ++7 is 7 273# ++ is not a inc operator on non-variable, it is the + + sequence
274#ash# echo $(( ++7 )) 274echo $(( ++7 ))
275#ash# echo $(( --7 )) 275echo $(( --7 ))
276 276
277${THIS_SH} ./arith1.sub 277${THIS_SH} ./arith1.sub
278${THIS_SH} ./arith2.sub 278${THIS_SH} ./arith2.sub
diff --git a/shell/hush_test/hush-arith/arith1.sub b/shell/hush_test/hush-arith/arith1.sub
index 80aa99922..a36785c67 100755
--- a/shell/hush_test/hush-arith/arith1.sub
+++ b/shell/hush_test/hush-arith/arith1.sub
@@ -35,6 +35,6 @@ echo 1 $a
35 35
36#ash# (( ++ )) 36#ash# (( ++ ))
37( echo $(( +++7 )) ) 37( echo $(( +++7 )) )
38# bash 3.2 apparently thinks that ++ +7 is 7 38# ++ is not a inc operator on non-variable, it is the + + sequence
39#ash# echo $(( ++ + 7 )) 39echo $(( ++ + 7 ))
40#ash# (( -- )) 40#ash# (( -- ))
diff --git a/shell/hush_test/hush-arith/arith2.sub b/shell/hush_test/hush-arith/arith2.sub
index 9105059db..8d7918114 100755
--- a/shell/hush_test/hush-arith/arith2.sub
+++ b/shell/hush_test/hush-arith/arith2.sub
@@ -1,4 +1,4 @@
1# bash 3.2 apparently thinks that ++7 is 7 etc 1# ++ and -- are not inc/dec operators on non-variables, they are + + and - - sequences
2( echo $(( --7 )) ) 2( echo $(( --7 )) )
3( echo $(( ++7 )) ) 3( echo $(( ++7 )) )
4( echo $(( -- 7 )) ) 4( echo $(( -- 7 )) )
@@ -37,21 +37,17 @@ echo 4 $(( 4 - -- a ))
37echo 0 $a 37echo 0 $a
38 38
39#ash# (( -- )) 39#ash# (( -- ))
40# bash 3.2 apparently thinks that ---7 is -7 40# -- is not a dec operator on non-variable, it is the - - sequence
41#ash# echo $(( ---7 )) 41echo $(( ---7 ))
42( echo $(( -- - 7 )) ) 42( echo $(( -- - 7 )) )
43 43
44#ash# (( ++ )) 44#ash# (( ++ ))
45# bash 3.2: 7 45# ++ is not a inc operator on non-variable, it is the + + sequence
46#ash# echo 7 $(( ++7 )) 46echo $(( ++7 ))
47( echo $(( ++ + 7 )) ) 47( echo $(( ++ + 7 )) )
48 48
49# bash 3.2: -7 49echo -7 $(( ++-7 ))
50#ash# echo -7 $(( ++-7 )) 50echo -7 $(( ++ - 7 ))
51# bash 3.2: -7
52#ash# echo -7 $(( ++ - 7 ))
53 51
54# bash 3.2: 7 52echo 7 $(( +--7 ))
55#ash# echo 7 $(( +--7 )) 53echo 7 $(( -- + 7 ))
56# bash 3.2: 7
57#ash# echo 7 $(( -- + 7 ))
diff --git a/shell/hush_test/hush-comm/comm.right b/shell/hush_test/hush-comm/comm.right
new file mode 100644
index 000000000..1b62b617e
--- /dev/null
+++ b/shell/hush_test/hush-comm/comm.right
@@ -0,0 +1,6 @@
1./SCRIPT.sh:
2 /proc/N/comm: SCRIPT.sh
3exec ./SCRIPT.sh:
4 /proc/N/comm: SCRIPT.sh
5sh ./SCRIPT.sh:
6 /proc/N/comm: hush
diff --git a/shell/hush_test/hush-comm/comm.tests b/shell/hush_test/hush-comm/comm.tests
new file mode 100755
index 000000000..671bfc176
--- /dev/null
+++ b/shell/hush_test/hush-comm/comm.tests
@@ -0,0 +1,20 @@
1{
2echo "#!$THIS_SH"
3echo 'procdir=/proc/$$'
4#echo 'echo " /proc/N/exe: $(basename $(readlink $procdir/exe))"'
5echo 'echo " /proc/N/comm: $(cat $procdir/comm)"'
6} >SCRIPT.sh
7chmod 755 SCRIPT.sh
8
9# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
10echo './SCRIPT.sh:'
11./SCRIPT.sh
12
13# comm field was wrong if CONFIG_FEATURE_PREFER_APPLETS=y
14echo 'exec ./SCRIPT.sh:'
15(exec ./SCRIPT.sh)
16
17echo 'sh ./SCRIPT.sh:'
18$THIS_SH ./SCRIPT.sh
19
20rm SCRIPT.sh
diff --git a/shell/math.c b/shell/math.c
index 2942cdd26..76d22c9bd 100644
--- a/shell/math.c
+++ b/shell/math.c
@@ -116,10 +116,6 @@
116#include "libbb.h" 116#include "libbb.h"
117#include "math.h" 117#include "math.h"
118 118
119#define lookupvar (math_state->lookupvar)
120#define setvar (math_state->setvar )
121//#define endofname (math_state->endofname)
122
123typedef unsigned char operator; 119typedef unsigned char operator;
124 120
125/* An operator's token id is a bit of a bitfield. The lower 5 bits are the 121/* An operator's token id is a bit of a bitfield. The lower 5 bits are the
@@ -258,7 +254,7 @@ static const char*
258arith_lookup_val(arith_state_t *math_state, var_or_num_t *t) 254arith_lookup_val(arith_state_t *math_state, var_or_num_t *t)
259{ 255{
260 if (t->var) { 256 if (t->var) {
261 const char *p = lookupvar(t->var); 257 const char *p = math_state->lookupvar(t->var);
262 if (p) { 258 if (p) {
263 remembered_name *cur; 259 remembered_name *cur;
264 remembered_name cur_save; 260 remembered_name cur_save;
@@ -445,16 +441,15 @@ arith_apply(arith_state_t *math_state, operator op, var_or_num_t *numstack, var_
445 441
446 if (top_of_stack->var == NULL) { 442 if (top_of_stack->var == NULL) {
447 /* Hmm, 1=2 ? */ 443 /* Hmm, 1=2 ? */
448//TODO: actually, bash allows ++7 but for some reason it evals to 7, not 8
449 goto err; 444 goto err;
450 } 445 }
451 /* Save to shell variable */ 446 /* Save to shell variable */
452 sprintf(buf, ARITH_FMT, rez); 447 sprintf(buf, ARITH_FMT, rez);
453 setvar(top_of_stack->var, buf); 448 math_state->setvar(top_of_stack->var, buf);
454 /* After saving, make previous value for v++ or v-- */ 449 /* After saving, make previous value for v++ or v-- */
455 if (op == TOK_POST_INC) 450 if (op == TOK_POST_INC)
456 rez--; 451 rez--;
457 else if (op == TOK_POST_DEC) 452 if (op == TOK_POST_DEC)
458 rez++; 453 rez++;
459 } 454 }
460 455
@@ -607,11 +602,9 @@ evaluate_string(arith_state_t *math_state, const char *expr)
607 const char *p; 602 const char *p;
608 operator op; 603 operator op;
609 operator prec; 604 operator prec;
610 char arithval;
611 605
612 expr = skip_whitespace(expr); 606 expr = skip_whitespace(expr);
613 arithval = *expr; 607 if (*expr == '\0') {
614 if (arithval == '\0') {
615 if (expr == start_expr) { 608 if (expr == start_expr) {
616 /* Null expression */ 609 /* Null expression */
617 numstack->val = 0; 610 numstack->val = 0;
@@ -628,6 +621,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
628 * append a closing right paren 621 * append a closing right paren
629 * and let the loop process it */ 622 * and let the loop process it */
630 expr = ptr_to_rparen; 623 expr = ptr_to_rparen;
624//bb_error_msg("expr=')'");
631 continue; 625 continue;
632 } 626 }
633 /* At this point, we're done with the expression */ 627 /* At this point, we're done with the expression */
@@ -635,19 +629,16 @@ evaluate_string(arith_state_t *math_state, const char *expr)
635 /* ...but if there isn't, it's bad */ 629 /* ...but if there isn't, it's bad */
636 goto err; 630 goto err;
637 } 631 }
638 if (numstack->var) {
639 /* expression is $((var)) only, lookup now */
640 errmsg = arith_lookup_val(math_state, numstack);
641 }
642 goto ret; 632 goto ret;
643 } 633 }
644 634
645 p = endofname(expr); 635 p = endofname(expr);
646 if (p != expr) { 636 if (p != expr) {
647 /* Name */ 637 /* Name */
648 size_t var_name_size = (p-expr) + 1; /* +1 for NUL */ 638 size_t var_name_size = (p - expr) + 1; /* +1 for NUL */
649 numstackptr->var = alloca(var_name_size); 639 numstackptr->var = alloca(var_name_size);
650 safe_strncpy(numstackptr->var, expr, var_name_size); 640 safe_strncpy(numstackptr->var, expr, var_name_size);
641//bb_error_msg("var:'%s'", numstackptr->var);
651 expr = p; 642 expr = p;
652 num: 643 num:
653 numstackptr->second_val_present = 0; 644 numstackptr->second_val_present = 0;
@@ -656,11 +647,12 @@ evaluate_string(arith_state_t *math_state, const char *expr)
656 continue; 647 continue;
657 } 648 }
658 649
659 if (isdigit(arithval)) { 650 if (isdigit(*expr)) {
660 /* Number */ 651 /* Number */
661 numstackptr->var = NULL; 652 numstackptr->var = NULL;
662 errno = 0; 653 errno = 0;
663 numstackptr->val = strto_arith_t(expr, (char**) &expr); 654 numstackptr->val = strto_arith_t(expr, (char**) &expr);
655//bb_error_msg("val:%lld", numstackptr->val);
664 if (errno) 656 if (errno)
665 numstackptr->val = 0; /* bash compat */ 657 numstackptr->val = 0; /* bash compat */
666 goto num; 658 goto num;
@@ -668,19 +660,26 @@ evaluate_string(arith_state_t *math_state, const char *expr)
668 660
669 /* Should be an operator */ 661 /* Should be an operator */
670 662
671 /* Special case: NUM-- and NUM++ are not recognized if NUM 663 /* Special case: XYZ--, XYZ++, --XYZ, ++XYZ are recognized
672 * is a literal number, not a variable. IOW: 664 * only if XYZ is a variable name, not a number or EXPR. IOW:
673 * "a+++v" is a++ + v. 665 * "a+++v" is a++ + v.
666 * "(a)+++7" is ( a ) + + + 7.
674 * "7+++v" is 7 + ++v, not 7++ + v. 667 * "7+++v" is 7 + ++v, not 7++ + v.
668 * "--7" is - - 7, not --7.
669 * "++++a" is + + ++a, not ++ ++a.
675 */ 670 */
676 if (lasttok == TOK_NUM && !numstackptr[-1].var /* number literal */ 671 if ((expr[0] == '+' || expr[0] == '-')
677 && (expr[0] == '+' || expr[0] == '-')
678 && (expr[1] == expr[0]) 672 && (expr[1] == expr[0])
679 ) { 673 ) {
680 //bb_error_msg("special %c%c", expr[0], expr[0]); 674 if (numstackptr == numstack || !numstackptr[-1].var) { /* not a VAR++ */
681 op = (expr[0] == '+' ? TOK_ADD : TOK_SUB); 675 char next = skip_whitespace(expr + 2)[0];
682 expr += 1; 676 if (!(isalpha(next) || next == '_')) { /* not a ++VAR */
683 goto tok_found1; 677 //bb_error_msg("special %c%c", expr[0], expr[0]);
678 op = (expr[0] == '+' ? TOK_ADD : TOK_SUB);
679 expr++;
680 goto tok_found1;
681 }
682 }
684 } 683 }
685 684
686 p = op_tokens; 685 p = op_tokens;
@@ -749,26 +748,40 @@ evaluate_string(arith_state_t *math_state, const char *expr)
749 * "applied" in this way. 748 * "applied" in this way.
750 */ 749 */
751 prec = PREC(op); 750 prec = PREC(op);
751//bb_error_msg("prec:%02x", prec);
752 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) { 752 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
753 /* not left paren or unary */ 753 /* not left paren or unary */
754 if (lasttok != TOK_NUM) { 754 if (lasttok != TOK_NUM) {
755 /* binary op must be preceded by a num */ 755 /* binary op must be preceded by a num */
756 goto err; 756 goto err;
757 } 757 }
758 /* The algorithm employed here is simple: while we don't
759 * hit an open paren nor the bottom of the stack, pop
760 * tokens and apply them */
758 while (stackptr != stack) { 761 while (stackptr != stack) {
759 operator prev_op = *--stackptr; 762 operator prev_op = *--stackptr;
760 if (op == TOK_RPAREN) { 763 if (op == TOK_RPAREN) {
761 /* The algorithm employed here is simple: while we don't 764//bb_error_msg("op == TOK_RPAREN");
762 * hit an open paren nor the bottom of the stack, pop
763 * tokens and apply them */
764 if (prev_op == TOK_LPAREN) { 765 if (prev_op == TOK_LPAREN) {
766//bb_error_msg("prev_op == TOK_LPAREN");
767//bb_error_msg(" %p %p numstackptr[-1].var:'%s'", numstack, numstackptr-1, numstackptr[-1].var);
768 if (numstackptr[-1].var) {
769 /* Expression is (var), lookup now */
770 errmsg = arith_lookup_val(math_state, &numstackptr[-1]);
771 if (errmsg)
772 goto err_with_custom_msg;
773 /* Erase var name: (var) is just a number, for example, (var) = 1 is not valid */
774 numstackptr[-1].var = NULL;
775 }
765 /* Any operator directly after a 776 /* Any operator directly after a
766 * close paren should consider itself binary */ 777 * close paren should consider itself binary */
767 lasttok = TOK_NUM; 778 lasttok = TOK_NUM;
768 goto next; 779 goto next;
769 } 780 }
781//bb_error_msg("prev_op != TOK_LPAREN");
770 } else { 782 } else {
771 operator prev_prec = PREC(prev_op); 783 operator prev_prec = PREC(prev_op);
784//bb_error_msg("op != TOK_RPAREN");
772 fix_assignment_prec(prec); 785 fix_assignment_prec(prec);
773 fix_assignment_prec(prev_prec); 786 fix_assignment_prec(prev_prec);
774 if (prev_prec < prec 787 if (prev_prec < prec
@@ -778,6 +791,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
778 break; 791 break;
779 } 792 }
780 } 793 }
794//bb_error_msg("arith_apply(prev_op:%02x)", prev_op);
781 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr); 795 errmsg = arith_apply(math_state, prev_op, numstack, &numstackptr);
782 if (errmsg) 796 if (errmsg)
783 goto err_with_custom_msg; 797 goto err_with_custom_msg;
@@ -787,6 +801,7 @@ evaluate_string(arith_state_t *math_state, const char *expr)
787 } 801 }
788 802
789 /* Push this operator to the stack and remember it */ 803 /* Push this operator to the stack and remember it */
804//bb_error_msg("push op:%02x", op);
790 *stackptr++ = lasttok = op; 805 *stackptr++ = lasttok = op;
791 next: ; 806 next: ;
792 } /* while (1) */ 807 } /* while (1) */