aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2017-01-11 14:00:38 +0100
committerDenys Vlasenko <vda.linux@googlemail.com>2017-01-11 14:00:38 +0100
commit7d4aec0c3ecb0c10de60070616d9d8fb9b074497 (patch)
treec4edb5852c5d64a3310d521a7b12e03d3e5fc1d1 /shell
parenta8a075acfee7b31c4da00cf3500b67354339e3b9 (diff)
downloadbusybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.tar.gz
busybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.tar.bz2
busybox-w32-7d4aec0c3ecb0c10de60070616d9d8fb9b074497.zip
ash: split bash compatible extensions into separate defines. No code changes
Splitting these options makes it self-documenting about what bash-compatible features we have. Signed-off-by: Kang-Che Sung <explorer09@gmail.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c175
1 files changed, 101 insertions, 74 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 866c7de05..02545f565 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -145,15 +145,10 @@
145//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o 145//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
146 146
147/* 147/*
148 * The following should be set to reflect the type of system you have: 148 * DEBUG=1 to compile in debugging ('set -o debug' turns on)
149 * JOBS -> 1 if you have Berkeley job control, 0 otherwise. 149 * DEBUG=2 to compile in and turn on debugging.
150 * define SYSV if you are running under System V. 150 * When debugging is on ("set -o debug" was executed, or DEBUG=2),
151 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on) 151 * debugging info is written to ./trace, quit signal generates core dump.
152 * define DEBUG=2 to compile in and turn on debugging.
153 *
154 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
155 * debugging info will be written to ./trace and a quit signal
156 * will generate a core dump.
157 */ 152 */
158#define DEBUG 0 153#define DEBUG 0
159/* Tweak debug output verbosity here */ 154/* Tweak debug output verbosity here */
@@ -170,9 +165,30 @@
170#include <fnmatch.h> 165#include <fnmatch.h>
171#include <sys/times.h> 166#include <sys/times.h>
172#include <sys/utsname.h> /* for setting $HOSTNAME */ 167#include <sys/utsname.h> /* for setting $HOSTNAME */
173
174#include "busybox.h" /* for applet_names */ 168#include "busybox.h" /* for applet_names */
175 169
170/* So far, all bash compat is controlled by one config option */
171/* Separate defines document which part of code implements what */
172/* function keyword */
173#define BASH_FUNCTION ENABLE_ASH_BASH_COMPAT
174#define IF_BASH_FUNCTION IF_ASH_BASH_COMPAT
175/* &>file */
176#define BASH_REDIR_OUTPUT ENABLE_ASH_BASH_COMPAT
177#define IF_BASH_REDIR_OUTPUT IF_ASH_BASH_COMPAT
178/* $'...' */
179#define BASH_DOLLAR_SQUOTE ENABLE_ASH_BASH_COMPAT
180#define IF_BASH_DOLLAR_SQUOTE IF_ASH_BASH_COMPAT
181#define BASH_PATTERN_SUBST ENABLE_ASH_BASH_COMPAT
182#define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT
183#define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT
184#define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT
185/* [[ EXPR ]] */
186#define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
187#define BASH_SOURCE ENABLE_ASH_BASH_COMPAT
188#define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT
189#define BASH_HOSTNAME_VAR ENABLE_ASH_BASH_COMPAT
190#define BASH_SHLVL_VAR ENABLE_ASH_BASH_COMPAT
191
176#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24 192#if defined(__ANDROID_API__) && __ANDROID_API__ <= 24
177/* Bionic at least up to version 24 has no glob() */ 193/* Bionic at least up to version 24 has no glob() */
178# undef ENABLE_ASH_INTERNAL_GLOB 194# undef ENABLE_ASH_INTERNAL_GLOB
@@ -250,7 +266,7 @@ static const char *const optletters_optnames[] = {
250 "b" "notify", 266 "b" "notify",
251 "u" "nounset", 267 "u" "nounset",
252 "\0" "vi" 268 "\0" "vi"
253#if ENABLE_ASH_BASH_COMPAT 269#if BASH_PIPEFAIL
254 ,"\0" "pipefail" 270 ,"\0" "pipefail"
255#endif 271#endif
256#if DEBUG 272#if DEBUG
@@ -327,14 +343,14 @@ struct globals_misc {
327#define bflag optlist[11] 343#define bflag optlist[11]
328#define uflag optlist[12] 344#define uflag optlist[12]
329#define viflag optlist[13] 345#define viflag optlist[13]
330#if ENABLE_ASH_BASH_COMPAT 346#if BASH_PIPEFAIL
331# define pipefail optlist[14] 347# define pipefail optlist[14]
332#else 348#else
333# define pipefail 0 349# define pipefail 0
334#endif 350#endif
335#if DEBUG 351#if DEBUG
336# define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT] 352# define nolog optlist[14 + BASH_PIPEFAIL]
337# define debug optlist[15 + ENABLE_ASH_BASH_COMPAT] 353# define debug optlist[15 + BASH_PIPEFAIL]
338#endif 354#endif
339 355
340 /* trap handler commands */ 356 /* trap handler commands */
@@ -655,8 +671,10 @@ out2str(const char *p)
655#define VSTRIMLEFT 0x8 /* ${var#pattern} */ 671#define VSTRIMLEFT 0x8 /* ${var#pattern} */
656#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */ 672#define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
657#define VSLENGTH 0xa /* ${#var} */ 673#define VSLENGTH 0xa /* ${#var} */
658#if ENABLE_ASH_BASH_COMPAT 674#if BASH_SUBSTR
659#define VSSUBSTR 0xc /* ${var:position:length} */ 675#define VSSUBSTR 0xc /* ${var:position:length} */
676#endif
677#if BASH_PATTERN_SUBST
660#define VSREPLACE 0xd /* ${var/pattern/replacement} */ 678#define VSREPLACE 0xd /* ${var/pattern/replacement} */
661#define VSREPLACEALL 0xe /* ${var//pattern/replacement} */ 679#define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
662#endif 680#endif
@@ -683,7 +701,7 @@ static const char dolatstr[] ALIGN1 = {
683#define NDEFUN 14 701#define NDEFUN 14
684#define NARG 15 702#define NARG 15
685#define NTO 16 703#define NTO 16
686#if ENABLE_ASH_BASH_COMPAT 704#if BASH_REDIR_OUTPUT
687#define NTO2 17 705#define NTO2 17
688#endif 706#endif
689#define NCLOBBER 18 707#define NCLOBBER 18
@@ -1093,7 +1111,7 @@ shcmd(union node *cmd, FILE *fp)
1093 case NTO: s = ">>"+1; dftfd = 1; break; 1111 case NTO: s = ">>"+1; dftfd = 1; break;
1094 case NCLOBBER: s = ">|"; dftfd = 1; break; 1112 case NCLOBBER: s = ">|"; dftfd = 1; break;
1095 case NAPPEND: s = ">>"; dftfd = 1; break; 1113 case NAPPEND: s = ">>"; dftfd = 1; break;
1096#if ENABLE_ASH_BASH_COMPAT 1114#if BASH_REDIR_OUTPUT
1097 case NTO2: 1115 case NTO2:
1098#endif 1116#endif
1099 case NTOFD: s = ">&"; dftfd = 1; break; 1117 case NTOFD: s = ">&"; dftfd = 1; break;
@@ -4455,7 +4473,8 @@ cmdputs(const char *s)
4455 static const char vstype[VSTYPE + 1][3] = { 4473 static const char vstype[VSTYPE + 1][3] = {
4456 "", "}", "-", "+", "?", "=", 4474 "", "}", "-", "+", "?", "=",
4457 "%", "%%", "#", "##" 4475 "%", "%%", "#", "##"
4458 IF_ASH_BASH_COMPAT(, ":", "/", "//") 4476 IF_BASH_SUBSTR(, ":")
4477 IF_BASH_PATTERN_SUBST(, "/", "//")
4459 }; 4478 };
4460 4479
4461 const char *p, *str; 4480 const char *p, *str;
@@ -4682,7 +4701,7 @@ cmdtxt(union node *n)
4682 case NAPPEND: 4701 case NAPPEND:
4683 p = ">>"; 4702 p = ">>";
4684 goto redir; 4703 goto redir;
4685#if ENABLE_ASH_BASH_COMPAT 4704#if BASH_REDIR_OUTPUT
4686 case NTO2: 4705 case NTO2:
4687#endif 4706#endif
4688 case NTOFD: 4707 case NTOFD:
@@ -5209,7 +5228,7 @@ openredirect(union node *redir)
5209 goto ecreate; 5228 goto ecreate;
5210 break; 5229 break;
5211 case NTO: 5230 case NTO:
5212#if ENABLE_ASH_BASH_COMPAT 5231#if BASH_REDIR_OUTPUT
5213 case NTO2: 5232 case NTO2:
5214#endif 5233#endif
5215 /* Take care of noclobber mode. */ 5234 /* Take care of noclobber mode. */
@@ -5370,7 +5389,7 @@ redirect(union node *redir, int flags)
5370 union node *tmp = redir; 5389 union node *tmp = redir;
5371 do { 5390 do {
5372 sv_pos++; 5391 sv_pos++;
5373#if ENABLE_ASH_BASH_COMPAT 5392#if BASH_REDIR_OUTPUT
5374 if (tmp->nfile.type == NTO2) 5393 if (tmp->nfile.type == NTO2)
5375 sv_pos++; 5394 sv_pos++;
5376#endif 5395#endif
@@ -5412,7 +5431,7 @@ redirect(union node *redir, int flags)
5412 continue; 5431 continue;
5413 } 5432 }
5414 } 5433 }
5415#if ENABLE_ASH_BASH_COMPAT 5434#if BASH_REDIR_OUTPUT
5416 redirect_more: 5435 redirect_more:
5417#endif 5436#endif
5418 if (need_to_remember(sv, fd)) { 5437 if (need_to_remember(sv, fd)) {
@@ -5465,12 +5484,12 @@ redirect(union node *redir, int flags)
5465 } 5484 }
5466 } else if (fd != newfd) { /* move newfd to fd */ 5485 } else if (fd != newfd) { /* move newfd to fd */
5467 dup2_or_raise(newfd, fd); 5486 dup2_or_raise(newfd, fd);
5468#if ENABLE_ASH_BASH_COMPAT 5487#if BASH_REDIR_OUTPUT
5469 if (!(redir->nfile.type == NTO2 && fd == 2)) 5488 if (!(redir->nfile.type == NTO2 && fd == 2))
5470#endif 5489#endif
5471 close(newfd); 5490 close(newfd);
5472 } 5491 }
5473#if ENABLE_ASH_BASH_COMPAT 5492#if BASH_REDIR_OUTPUT
5474 if (redir->nfile.type == NTO2 && fd == 1) { 5493 if (redir->nfile.type == NTO2 && fd == 1) {
5475 /* We already redirected it to fd 1, now copy it to 2 */ 5494 /* We already redirected it to fd 1, now copy it to 2 */
5476 newfd = 1; 5495 newfd = 1;
@@ -5787,15 +5806,15 @@ static char *
5787rmescapes(char *str, int flag) 5806rmescapes(char *str, int flag)
5788{ 5807{
5789 static const char qchars[] ALIGN1 = { 5808 static const char qchars[] ALIGN1 = {
5790 IF_ASH_BASH_COMPAT('/',) CTLESC, CTLQUOTEMARK, '\0' }; 5809 IF_BASH_PATTERN_SUBST('/',) CTLESC, CTLQUOTEMARK, '\0' };
5791 5810
5792 char *p, *q, *r; 5811 char *p, *q, *r;
5793 unsigned inquotes; 5812 unsigned inquotes;
5794 unsigned protect_against_glob; 5813 unsigned protect_against_glob;
5795 unsigned globbing; 5814 unsigned globbing;
5796 IF_ASH_BASH_COMPAT(unsigned slash = flag & RMESCAPE_SLASH;) 5815 IF_BASH_PATTERN_SUBST(unsigned slash = flag & RMESCAPE_SLASH;)
5797 5816
5798 p = strpbrk(str, qchars IF_ASH_BASH_COMPAT(+ !slash)); 5817 p = strpbrk(str, qchars IF_BASH_PATTERN_SUBST(+ !slash));
5799 if (!p) 5818 if (!p)
5800 return str; 5819 return str;
5801 5820
@@ -5847,7 +5866,7 @@ rmescapes(char *str, int flag)
5847 protect_against_glob = 0; 5866 protect_against_glob = 0;
5848 goto copy; 5867 goto copy;
5849 } 5868 }
5850#if ENABLE_ASH_BASH_COMPAT 5869#if BASH_PATTERN_SUBST
5851 else if (*p == '/' && slash) { 5870 else if (*p == '/' && slash) {
5852 /* stop handling globbing and mark location of slash */ 5871 /* stop handling globbing and mark location of slash */
5853 globbing = slash = 0; 5872 globbing = slash = 0;
@@ -6494,10 +6513,10 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6494 char *loc; 6513 char *loc;
6495 char *rmesc, *rmescend; 6514 char *rmesc, *rmescend;
6496 char *str; 6515 char *str;
6497 IF_ASH_BASH_COMPAT(char *repl = NULL;) 6516 IF_BASH_SUBSTR(int pos, len, orig_len;)
6498 IF_ASH_BASH_COMPAT(int pos, len, orig_len;)
6499 int amount, resetloc; 6517 int amount, resetloc;
6500 IF_ASH_BASH_COMPAT(int workloc;) 6518 IF_BASH_PATTERN_SUBST(int workloc;)
6519 IF_BASH_PATTERN_SUBST(char *repl = NULL;)
6501 int zero; 6520 int zero;
6502 char *(*scan)(char*, char*, char*, char*, int, int); 6521 char *(*scan)(char*, char*, char*, char*, int, int);
6503 6522
@@ -6522,7 +6541,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6522 varunset(p, varname, startp, varflags); 6541 varunset(p, varname, startp, varflags);
6523 /* NOTREACHED */ 6542 /* NOTREACHED */
6524 6543
6525#if ENABLE_ASH_BASH_COMPAT 6544#if BASH_SUBSTR
6526 case VSSUBSTR: 6545 case VSSUBSTR:
6527//TODO: support more general format ${v:EXPR:EXPR}, 6546//TODO: support more general format ${v:EXPR:EXPR},
6528// where EXPR follows $(()) rules 6547// where EXPR follows $(()) rules
@@ -6591,17 +6610,19 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6591 amount = loc - expdest; 6610 amount = loc - expdest;
6592 STADJUST(amount, expdest); 6611 STADJUST(amount, expdest);
6593 return loc; 6612 return loc;
6594#endif 6613#endif /* BASH_SUBSTR */
6595 } 6614 }
6596 6615
6597 resetloc = expdest - (char *)stackblock(); 6616 resetloc = expdest - (char *)stackblock();
6598 6617
6618#if BASH_PATTERN_SUBST
6599 /* We'll comeback here if we grow the stack while handling 6619 /* We'll comeback here if we grow the stack while handling
6600 * a VSREPLACE or VSREPLACEALL, since our pointers into the 6620 * a VSREPLACE or VSREPLACEALL, since our pointers into the
6601 * stack will need rebasing, and we'll need to remove our work 6621 * stack will need rebasing, and we'll need to remove our work
6602 * areas each time 6622 * areas each time
6603 */ 6623 */
6604 IF_ASH_BASH_COMPAT(restart:) 6624 restart:
6625#endif
6605 6626
6606 amount = expdest - ((char *)stackblock() + resetloc); 6627 amount = expdest - ((char *)stackblock() + resetloc);
6607 STADJUST(-amount, expdest); 6628 STADJUST(-amount, expdest);
@@ -6626,11 +6647,11 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6626 * RMESCAPE_SLASH causes preglob to work differently on the pattern 6647 * RMESCAPE_SLASH causes preglob to work differently on the pattern
6627 * and string. It's only used on the first call. 6648 * and string. It's only used on the first call.
6628 */ 6649 */
6629 preglob(str, IF_ASH_BASH_COMPAT( 6650 preglob(str, IF_BASH_PATTERN_SUBST(
6630 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ? 6651 (subtype == VSREPLACE || subtype == VSREPLACEALL) && !repl ?
6631 RMESCAPE_SLASH :) 0); 6652 RMESCAPE_SLASH : ) 0);
6632 6653
6633#if ENABLE_ASH_BASH_COMPAT 6654#if BASH_PATTERN_SUBST
6634 workloc = expdest - (char *)stackblock(); 6655 workloc = expdest - (char *)stackblock();
6635 if (subtype == VSREPLACE || subtype == VSREPLACEALL) { 6656 if (subtype == VSREPLACE || subtype == VSREPLACEALL) {
6636 char *idx, *end; 6657 char *idx, *end;
@@ -6731,7 +6752,7 @@ subevalvar(char *p, char *varname, int strloc, int subtype,
6731 STADJUST(-amount, expdest); 6752 STADJUST(-amount, expdest);
6732 return startp; 6753 return startp;
6733 } 6754 }
6734#endif /* ENABLE_ASH_BASH_COMPAT */ 6755#endif /* BASH_PATTERN_SUBST */
6735 6756
6736 subtype -= VSTRIMRIGHT; 6757 subtype -= VSTRIMRIGHT;
6737#if DEBUG 6758#if DEBUG
@@ -6999,8 +7020,10 @@ evalvar(char *p, int flag, struct strlist *var_str_list)
6999 case VSTRIMLEFTMAX: 7020 case VSTRIMLEFTMAX:
7000 case VSTRIMRIGHT: 7021 case VSTRIMRIGHT:
7001 case VSTRIMRIGHTMAX: 7022 case VSTRIMRIGHTMAX:
7002#if ENABLE_ASH_BASH_COMPAT 7023#if BASH_SUBSTR
7003 case VSSUBSTR: 7024 case VSSUBSTR:
7025#endif
7026#if BASH_PATTERN_SUBST
7004 case VSREPLACE: 7027 case VSREPLACE:
7005 case VSREPLACEALL: 7028 case VSREPLACEALL:
7006#endif 7029#endif
@@ -7924,7 +7947,7 @@ enum {
7924 TESAC, 7947 TESAC,
7925 TFI, 7948 TFI,
7926 TFOR, 7949 TFOR,
7927#if ENABLE_ASH_BASH_COMPAT 7950#if BASH_FUNCTION
7928 TFUNCTION, 7951 TFUNCTION,
7929#endif 7952#endif
7930 TIF, 7953 TIF,
@@ -7962,7 +7985,7 @@ enum {
7962 /* 19 */ | (1u << TESAC) 7985 /* 19 */ | (1u << TESAC)
7963 /* 20 */ | (1u << TFI) 7986 /* 20 */ | (1u << TFI)
7964 /* 21 */ | (0u << TFOR) 7987 /* 21 */ | (0u << TFOR)
7965#if ENABLE_ASH_BASH_COMPAT 7988#if BASH_FUNCTION
7966 /* 22 */ | (0u << TFUNCTION) 7989 /* 22 */ | (0u << TFUNCTION)
7967#endif 7990#endif
7968 /* 23 */ | (0u << TIF) 7991 /* 23 */ | (0u << TIF)
@@ -8000,7 +8023,7 @@ static const char *const tokname_array[] = {
8000 "esac", 8023 "esac",
8001 "fi", 8024 "fi",
8002 "for", 8025 "for",
8003#if ENABLE_ASH_BASH_COMPAT 8026#if BASH_FUNCTION
8004 "function", 8027 "function",
8005#endif 8028#endif
8006 "if", 8029 "if",
@@ -8244,7 +8267,7 @@ static const uint8_t nodesize[N_NUMBER] ALIGN1 = {
8244 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)), 8267 [NDEFUN ] = SHELL_ALIGN(sizeof(struct narg)),
8245 [NARG ] = SHELL_ALIGN(sizeof(struct narg)), 8268 [NARG ] = SHELL_ALIGN(sizeof(struct narg)),
8246 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)), 8269 [NTO ] = SHELL_ALIGN(sizeof(struct nfile)),
8247#if ENABLE_ASH_BASH_COMPAT 8270#if BASH_REDIR_OUTPUT
8248 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)), 8271 [NTO2 ] = SHELL_ALIGN(sizeof(struct nfile)),
8249#endif 8272#endif
8250 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)), 8273 [NCLOBBER ] = SHELL_ALIGN(sizeof(struct nfile)),
@@ -8326,7 +8349,7 @@ calcsize(int funcblocksize, union node *n)
8326 funcblocksize = calcsize(funcblocksize, n->narg.next); 8349 funcblocksize = calcsize(funcblocksize, n->narg.next);
8327 break; 8350 break;
8328 case NTO: 8351 case NTO:
8329#if ENABLE_ASH_BASH_COMPAT 8352#if BASH_REDIR_OUTPUT
8330 case NTO2: 8353 case NTO2:
8331#endif 8354#endif
8332 case NCLOBBER: 8355 case NCLOBBER:
@@ -8440,7 +8463,7 @@ copynode(union node *n)
8440 new->narg.next = copynode(n->narg.next); 8463 new->narg.next = copynode(n->narg.next);
8441 break; 8464 break;
8442 case NTO: 8465 case NTO:
8443#if ENABLE_ASH_BASH_COMPAT 8466#if BASH_REDIR_OUTPUT
8444 case NTO2: 8467 case NTO2:
8445#endif 8468#endif
8446 case NCLOBBER: 8469 case NCLOBBER:
@@ -8873,14 +8896,14 @@ expredir(union node *n)
8873 case NFROMTO: 8896 case NFROMTO:
8874 case NFROM: 8897 case NFROM:
8875 case NTO: 8898 case NTO:
8876#if ENABLE_ASH_BASH_COMPAT 8899#if BASH_REDIR_OUTPUT
8877 case NTO2: 8900 case NTO2:
8878#endif 8901#endif
8879 case NCLOBBER: 8902 case NCLOBBER:
8880 case NAPPEND: 8903 case NAPPEND:
8881 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR); 8904 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
8882 TRACE(("expredir expanded to '%s'\n", fn.list->text)); 8905 TRACE(("expredir expanded to '%s'\n", fn.list->text));
8883#if ENABLE_ASH_BASH_COMPAT 8906#if BASH_REDIR_OUTPUT
8884 store_expfname: 8907 store_expfname:
8885#endif 8908#endif
8886#if 0 8909#if 0
@@ -8902,7 +8925,7 @@ expredir(union node *n)
8902 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE); 8925 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
8903 if (fn.list == NULL) 8926 if (fn.list == NULL)
8904 ash_msg_and_raise_error("redir error"); 8927 ash_msg_and_raise_error("redir error");
8905#if ENABLE_ASH_BASH_COMPAT 8928#if BASH_REDIR_OUTPUT
8906//FIXME: we used expandarg with different args! 8929//FIXME: we used expandarg with different args!
8907 if (!isdigit_str9(fn.list->text)) { 8930 if (!isdigit_str9(fn.list->text)) {
8908 /* >&file, not >&fd */ 8931 /* >&file, not >&fd */
@@ -9298,7 +9321,7 @@ static int FAST_FUNC echocmd(int argc, char **argv) { return echo_main(argc, a
9298#if ENABLE_ASH_PRINTF 9321#if ENABLE_ASH_PRINTF
9299static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); } 9322static int FAST_FUNC printfcmd(int argc, char **argv) { return printf_main(argc, argv); }
9300#endif 9323#endif
9301#if ENABLE_ASH_TEST 9324#if ENABLE_ASH_TEST || BASH_TEST2
9302static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); } 9325static int FAST_FUNC testcmd(int argc, char **argv) { return test_main(argc, argv); }
9303#endif 9326#endif
9304 9327
@@ -9308,9 +9331,9 @@ static const struct builtincmd builtintab[] = {
9308 { BUILTIN_SPEC_REG ":" , truecmd }, 9331 { BUILTIN_SPEC_REG ":" , truecmd },
9309#if ENABLE_ASH_TEST 9332#if ENABLE_ASH_TEST
9310 { BUILTIN_REGULAR "[" , testcmd }, 9333 { BUILTIN_REGULAR "[" , testcmd },
9311# if ENABLE_ASH_BASH_COMPAT 9334#endif
9335#if BASH_TEST2
9312 { BUILTIN_REGULAR "[[" , testcmd }, 9336 { BUILTIN_REGULAR "[[" , testcmd },
9313# endif
9314#endif 9337#endif
9315#if ENABLE_ASH_ALIAS 9338#if ENABLE_ASH_ALIAS
9316 { BUILTIN_REG_ASSG "alias" , aliascmd }, 9339 { BUILTIN_REG_ASSG "alias" , aliascmd },
@@ -9363,7 +9386,7 @@ static const struct builtincmd builtintab[] = {
9363 { BUILTIN_SPEC_REG "return" , returncmd }, 9386 { BUILTIN_SPEC_REG "return" , returncmd },
9364 { BUILTIN_SPEC_REG "set" , setcmd }, 9387 { BUILTIN_SPEC_REG "set" , setcmd },
9365 { BUILTIN_SPEC_REG "shift" , shiftcmd }, 9388 { BUILTIN_SPEC_REG "shift" , shiftcmd },
9366#if ENABLE_ASH_BASH_COMPAT 9389#if BASH_SOURCE
9367 { BUILTIN_SPEC_REG "source" , dotcmd }, 9390 { BUILTIN_SPEC_REG "source" , dotcmd },
9368#endif 9391#endif
9369#if ENABLE_ASH_TEST 9392#if ENABLE_ASH_TEST
@@ -9386,7 +9409,7 @@ static const struct builtincmd builtintab[] = {
9386#define COMMANDCMD (builtintab + \ 9409#define COMMANDCMD (builtintab + \
9387 /* . : */ 2 + \ 9410 /* . : */ 2 + \
9388 /* [ */ 1 * ENABLE_ASH_TEST + \ 9411 /* [ */ 1 * ENABLE_ASH_TEST + \
9389 /* [[ */ 1 * ENABLE_ASH_TEST * ENABLE_ASH_BASH_COMPAT + \ 9412 /* [[ */ 1 * BASH_TEST2 + \
9390 /* alias */ 1 * ENABLE_ASH_ALIAS + \ 9413 /* alias */ 1 * ENABLE_ASH_ALIAS + \
9391 /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \ 9414 /* bg */ 1 * ENABLE_ASH_JOB_CONTROL + \
9392 /* break cd cddir */ 3) 9415 /* break cd cddir */ 3)
@@ -11008,10 +11031,10 @@ simplecmd(void)
11008 union node *vars, **vpp; 11031 union node *vars, **vpp;
11009 union node **rpp, *redir; 11032 union node **rpp, *redir;
11010 int savecheckkwd; 11033 int savecheckkwd;
11011#if ENABLE_ASH_BASH_COMPAT 11034#if BASH_TEST2
11012 smallint double_brackets_flag = 0; 11035 smallint double_brackets_flag = 0;
11013 smallint function_flag = 0;
11014#endif 11036#endif
11037 IF_BASH_FUNCTION(smallint function_flag = 0;)
11015 11038
11016 args = NULL; 11039 args = NULL;
11017 app = &args; 11040 app = &args;
@@ -11026,12 +11049,14 @@ simplecmd(void)
11026 checkkwd = savecheckkwd; 11049 checkkwd = savecheckkwd;
11027 t = readtoken(); 11050 t = readtoken();
11028 switch (t) { 11051 switch (t) {
11029#if ENABLE_ASH_BASH_COMPAT 11052#if BASH_FUNCTION
11030 case TFUNCTION: 11053 case TFUNCTION:
11031 if (peektoken() != TWORD) 11054 if (peektoken() != TWORD)
11032 raise_error_unexpected_syntax(TWORD); 11055 raise_error_unexpected_syntax(TWORD);
11033 function_flag = 1; 11056 function_flag = 1;
11034 break; 11057 break;
11058#endif
11059#if BASH_TEST2
11035 case TAND: /* "&&" */ 11060 case TAND: /* "&&" */
11036 case TOR: /* "||" */ 11061 case TOR: /* "||" */
11037 if (!double_brackets_flag) { 11062 if (!double_brackets_flag) {
@@ -11045,7 +11070,7 @@ simplecmd(void)
11045 n->type = NARG; 11070 n->type = NARG;
11046 /*n->narg.next = NULL; - stzalloc did it */ 11071 /*n->narg.next = NULL; - stzalloc did it */
11047 n->narg.text = wordtext; 11072 n->narg.text = wordtext;
11048#if ENABLE_ASH_BASH_COMPAT 11073#if BASH_TEST2
11049 if (strcmp("[[", wordtext) == 0) 11074 if (strcmp("[[", wordtext) == 0)
11050 double_brackets_flag = 1; 11075 double_brackets_flag = 1;
11051 else if (strcmp("]]", wordtext) == 0) 11076 else if (strcmp("]]", wordtext) == 0)
@@ -11060,7 +11085,7 @@ simplecmd(void)
11060 app = &n->narg.next; 11085 app = &n->narg.next;
11061 savecheckkwd = 0; 11086 savecheckkwd = 0;
11062 } 11087 }
11063#if ENABLE_ASH_BASH_COMPAT 11088#if BASH_FUNCTION
11064 if (function_flag) { 11089 if (function_flag) {
11065 checkkwd = CHKNL | CHKKWD; 11090 checkkwd = CHKNL | CHKKWD;
11066 switch (peektoken()) { 11091 switch (peektoken()) {
@@ -11090,7 +11115,7 @@ simplecmd(void)
11090 parsefname(); /* read name of redirection file */ 11115 parsefname(); /* read name of redirection file */
11091 break; 11116 break;
11092 case TLP: 11117 case TLP:
11093 IF_ASH_BASH_COMPAT(do_func:) 11118 IF_BASH_FUNCTION(do_func:)
11094 if (args && app == &args->narg.next 11119 if (args && app == &args->narg.next
11095 && !vars && !redir 11120 && !vars && !redir
11096 ) { 11121 ) {
@@ -11098,7 +11123,7 @@ simplecmd(void)
11098 const char *name; 11123 const char *name;
11099 11124
11100 /* We have a function */ 11125 /* We have a function */
11101 if (IF_ASH_BASH_COMPAT(!function_flag &&) readtoken() != TRP) 11126 if (IF_BASH_FUNCTION(!function_flag &&) readtoken() != TRP)
11102 raise_error_unexpected_syntax(TRP); 11127 raise_error_unexpected_syntax(TRP);
11103 name = n->narg.text; 11128 name = n->narg.text;
11104 if (!goodname(name) 11129 if (!goodname(name)
@@ -11111,7 +11136,7 @@ simplecmd(void)
11111 n->narg.next = parse_command(); 11136 n->narg.next = parse_command();
11112 return n; 11137 return n;
11113 } 11138 }
11114 IF_ASH_BASH_COMPAT(function_flag = 0;) 11139 IF_BASH_FUNCTION(function_flag = 0;)
11115 /* fall through */ 11140 /* fall through */
11116 default: 11141 default:
11117 tokpushback = 1; 11142 tokpushback = 1;
@@ -11292,7 +11317,7 @@ parse_command(void)
11292 n1 = list(0); 11317 n1 = list(0);
11293 t = TEND; 11318 t = TEND;
11294 break; 11319 break;
11295 IF_ASH_BASH_COMPAT(case TFUNCTION:) 11320 IF_BASH_FUNCTION(case TFUNCTION:)
11296 case TWORD: 11321 case TWORD:
11297 case TREDIR: 11322 case TREDIR:
11298 tokpushback = 1; 11323 tokpushback = 1;
@@ -11325,7 +11350,7 @@ parse_command(void)
11325 return n1; 11350 return n1;
11326} 11351}
11327 11352
11328#if ENABLE_ASH_BASH_COMPAT 11353#if BASH_DOLLAR_SQUOTE
11329static int 11354static int
11330decode_dollar_squote(void) 11355decode_dollar_squote(void)
11331{ 11356{
@@ -11410,7 +11435,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11410 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */ 11435 IF_FEATURE_SH_MATH(int parenlevel;) /* levels of parens in arithmetic */
11411 int dqvarnest; /* levels of variables expansion within double quotes */ 11436 int dqvarnest; /* levels of variables expansion within double quotes */
11412 11437
11413 IF_ASH_BASH_COMPAT(smallint bash_dollar_squote = 0;) 11438 IF_BASH_DOLLAR_SQUOTE(smallint bash_dollar_squote = 0;)
11414 11439
11415 startlinno = g_parsefile->linno; 11440 startlinno = g_parsefile->linno;
11416 bqlist = NULL; 11441 bqlist = NULL;
@@ -11445,7 +11470,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11445 USTPUTC(c, out); 11470 USTPUTC(c, out);
11446 break; 11471 break;
11447 case CCTL: 11472 case CCTL:
11448#if ENABLE_ASH_BASH_COMPAT 11473#if BASH_DOLLAR_SQUOTE
11449 if (c == '\\' && bash_dollar_squote) { 11474 if (c == '\\' && bash_dollar_squote) {
11450 c = decode_dollar_squote(); 11475 c = decode_dollar_squote();
11451 if (c == '\0') { 11476 if (c == '\0') {
@@ -11506,7 +11531,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11506 dblquote = 1; 11531 dblquote = 1;
11507 goto quotemark; 11532 goto quotemark;
11508 case CENDQUOTE: 11533 case CENDQUOTE:
11509 IF_ASH_BASH_COMPAT(bash_dollar_squote = 0;) 11534 IF_BASH_DOLLAR_SQUOTE(bash_dollar_squote = 0;)
11510 if (eofmark != NULL && varnest == 0) { 11535 if (eofmark != NULL && varnest == 0) {
11511 USTPUTC(c, out); 11536 USTPUTC(c, out);
11512 } else { 11537 } else {
@@ -11565,7 +11590,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11565 break; 11590 break;
11566 default: 11591 default:
11567 if (varnest == 0) { 11592 if (varnest == 0) {
11568#if ENABLE_ASH_BASH_COMPAT 11593#if BASH_REDIR_OUTPUT
11569 if (c == '&') { 11594 if (c == '&') {
11570//Can't call pgetc_eatbnl() here, this requires three-deep pungetc() 11595//Can't call pgetc_eatbnl() here, this requires three-deep pungetc()
11571 if (pgetc() == '>') 11596 if (pgetc() == '>')
@@ -11597,7 +11622,7 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
11597 len = out - (char *)stackblock(); 11622 len = out - (char *)stackblock();
11598 out = stackblock(); 11623 out = stackblock();
11599 if (eofmark == NULL) { 11624 if (eofmark == NULL) {
11600 if ((c == '>' || c == '<' IF_ASH_BASH_COMPAT( || c == 0x100 + '>')) 11625 if ((c == '>' || c == '<' IF_BASH_REDIR_OUTPUT( || c == 0x100 + '>'))
11601 && quotef == 0 11626 && quotef == 0
11602 ) { 11627 ) {
11603 if (isdigit_str9(out)) { 11628 if (isdigit_str9(out)) {
@@ -11685,7 +11710,7 @@ parseredir: {
11685 pungetc(); 11710 pungetc();
11686 } 11711 }
11687 } 11712 }
11688#if ENABLE_ASH_BASH_COMPAT 11713#if BASH_REDIR_OUTPUT
11689 else if (c == 0x100 + '>') { /* this flags &> redirection */ 11714 else if (c == 0x100 + '>') { /* this flags &> redirection */
11690 np->nfile.fd = 1; 11715 np->nfile.fd = 1;
11691 pgetc(); /* this is '>', no need to check */ 11716 pgetc(); /* this is '>', no need to check */
@@ -11751,7 +11776,7 @@ parsesub: {
11751 if (c > 255 /* PEOA or PEOF */ 11776 if (c > 255 /* PEOA or PEOF */
11752 || (c != '(' && c != '{' && !is_name(c) && !is_special(c)) 11777 || (c != '(' && c != '{' && !is_name(c) && !is_special(c))
11753 ) { 11778 ) {
11754#if ENABLE_ASH_BASH_COMPAT 11779#if BASH_DOLLAR_SQUOTE
11755 if (syntax != DQSYNTAX && c == '\'') 11780 if (syntax != DQSYNTAX && c == '\'')
11756 bash_dollar_squote = 1; 11781 bash_dollar_squote = 1;
11757 else 11782 else
@@ -11827,7 +11852,7 @@ parsesub: {
11827 switch (c) { 11852 switch (c) {
11828 case ':': 11853 case ':':
11829 c = pgetc_eatbnl(); 11854 c = pgetc_eatbnl();
11830#if ENABLE_ASH_BASH_COMPAT 11855#if BASH_SUBSTR
11831 /* This check is only needed to not misinterpret 11856 /* This check is only needed to not misinterpret
11832 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD} 11857 * ${VAR:-WORD}, ${VAR:+WORD}, ${VAR:=WORD}, ${VAR:?WORD}
11833 * constructs. 11858 * constructs.
@@ -11857,7 +11882,7 @@ parsesub: {
11857 subtype++; 11882 subtype++;
11858 break; 11883 break;
11859 } 11884 }
11860#if ENABLE_ASH_BASH_COMPAT 11885#if BASH_PATTERN_SUBST
11861 case '/': 11886 case '/':
11862 /* ${v/[/]pattern/repl} */ 11887 /* ${v/[/]pattern/repl} */
11863//TODO: encode pattern and repl separately. 11888//TODO: encode pattern and repl separately.
@@ -12112,7 +12137,7 @@ xxreadtoken(void)
12112 p += xxreadtoken_doubles + 1; 12137 p += xxreadtoken_doubles + 1;
12113 } else { 12138 } else {
12114 pungetc(); 12139 pungetc();
12115#if ENABLE_ASH_BASH_COMPAT 12140#if BASH_REDIR_OUTPUT
12116 if (c == '&' && cc == '>') /* &> */ 12141 if (c == '&' && cc == '>') /* &> */
12117 break; /* return readtoken1(...) */ 12142 break; /* return readtoken1(...) */
12118#endif 12143#endif
@@ -13274,9 +13299,11 @@ init(void)
13274 setvareq((char*)defoptindvar, VTEXTFIXED); 13299 setvareq((char*)defoptindvar, VTEXTFIXED);
13275 13300
13276 setvar0("PPID", utoa(getppid())); 13301 setvar0("PPID", utoa(getppid()));
13277#if ENABLE_ASH_BASH_COMPAT 13302#if BASH_SHLVL_VAR
13278 p = lookupvar("SHLVL"); 13303 p = lookupvar("SHLVL");
13279 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT); 13304 setvar("SHLVL", utoa((p ? atoi(p) : 0) + 1), VEXPORT);
13305#endif
13306#if BASH_HOSTNAME_VAR
13280 if (!lookupvar("HOSTNAME")) { 13307 if (!lookupvar("HOSTNAME")) {
13281 struct utsname uts; 13308 struct utsname uts;
13282 uname(&uts); 13309 uname(&uts);