aboutsummaryrefslogtreecommitdiff
path: root/shell/ash.c
diff options
context:
space:
mode:
Diffstat (limited to 'shell/ash.c')
-rw-r--r--shell/ash.c92
1 files changed, 64 insertions, 28 deletions
diff --git a/shell/ash.c b/shell/ash.c
index a8ba9c4ef..7fa9dae21 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -224,7 +224,20 @@
224#define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT 224#define IF_BASH_PATTERN_SUBST IF_ASH_BASH_COMPAT
225#define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT 225#define BASH_SUBSTR ENABLE_ASH_BASH_COMPAT
226#define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT 226#define IF_BASH_SUBSTR IF_ASH_BASH_COMPAT
227/* [[ EXPR ]] */ 227/* BASH_TEST2: [[ EXPR ]]
228 * Status of [[ support:
229 * We replace && and || with -a and -o
230 * TODO:
231 * singleword+noglob expansion:
232 * v='a b'; [[ $v = 'a b' ]]; echo 0:$?
233 * [[ /bin/n* ]]; echo 0:$?
234 * -a/-o are not AND/OR ops! (they are just strings)
235 * quoting needs to be considered (-f is an operator, "-f" and ""-f are not; etc)
236 * = is glob match operator, not equality operator: STR = GLOB
237 * (in GLOB, quoting is significant on char-by-char basis: a*cd"*")
238 * == same as =
239 * add =~ regex match operator: STR =~ REGEX
240 */
228#define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST) 241#define BASH_TEST2 (ENABLE_ASH_BASH_COMPAT * ENABLE_ASH_TEST)
229#define BASH_SOURCE ENABLE_ASH_BASH_COMPAT 242#define BASH_SOURCE ENABLE_ASH_BASH_COMPAT
230#define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT 243#define BASH_PIPEFAIL ENABLE_ASH_BASH_COMPAT
@@ -7944,9 +7957,16 @@ expandmeta(struct strlist *str /*, int flag*/)
7944/* 7957/*
7945 * Do metacharacter (i.e. *, ?, [...]) expansion. 7958 * Do metacharacter (i.e. *, ?, [...]) expansion.
7946 */ 7959 */
7960typedef struct exp_t {
7961 char *dir;
7962 unsigned dir_max;
7963} exp_t;
7947static void 7964static void
7948expmeta(char *expdir, char *enddir, char *name) 7965expmeta(exp_t *exp, char *name, unsigned name_len, unsigned expdir_len)
7949{ 7966{
7967#define expdir exp->dir
7968#define expdir_max exp->dir_max
7969 char *enddir = expdir + expdir_len;
7950 char *p; 7970 char *p;
7951 const char *cp; 7971 const char *cp;
7952 char *start; 7972 char *start;
@@ -7989,15 +8009,15 @@ expmeta(char *expdir, char *enddir, char *name)
7989 } 8009 }
7990 } 8010 }
7991 if (metaflag == 0) { /* we've reached the end of the file name */ 8011 if (metaflag == 0) { /* we've reached the end of the file name */
7992 if (enddir != expdir) 8012 if (!expdir_len)
7993 metaflag++; 8013 return;
7994 p = name; 8014 p = name;
7995 do { 8015 do {
7996 if (*p == '\\') 8016 if (*p == '\\')
7997 p++; 8017 p++;
7998 *enddir++ = *p; 8018 *enddir++ = *p;
7999 } while (*p++); 8019 } while (*p++);
8000 if (metaflag == 0 || lstat(expdir, &statb) >= 0) 8020 if (lstat(expdir, &statb) == 0)
8001 addfname(expdir); 8021 addfname(expdir);
8002 return; 8022 return;
8003 } 8023 }
@@ -8010,19 +8030,14 @@ expmeta(char *expdir, char *enddir, char *name)
8010 *enddir++ = *p++; 8030 *enddir++ = *p++;
8011 } while (p < start); 8031 } while (p < start);
8012 } 8032 }
8013 if (enddir == expdir) { 8033 *enddir = '\0';
8034 cp = expdir;
8035 expdir_len = enddir - cp;
8036 if (!expdir_len)
8014 cp = "."; 8037 cp = ".";
8015 } else if (enddir == expdir + 1 && *expdir == '/') {
8016 cp = "/";
8017 } else {
8018 cp = expdir;
8019 enddir[-1] = '\0';
8020 }
8021 dirp = opendir(cp); 8038 dirp = opendir(cp);
8022 if (dirp == NULL) 8039 if (dirp == NULL)
8023 return; 8040 return;
8024 if (enddir != expdir)
8025 enddir[-1] = '/';
8026 if (*endname == 0) { 8041 if (*endname == 0) {
8027 atend = 1; 8042 atend = 1;
8028 } else { 8043 } else {
@@ -8030,6 +8045,7 @@ expmeta(char *expdir, char *enddir, char *name)
8030 *endname = '\0'; 8045 *endname = '\0';
8031 endname += esc + 1; 8046 endname += esc + 1;
8032 } 8047 }
8048 name_len -= endname - name;
8033 matchdot = 0; 8049 matchdot = 0;
8034 p = start; 8050 p = start;
8035 if (*p == '\\') 8051 if (*p == '\\')
@@ -8044,16 +8060,30 @@ expmeta(char *expdir, char *enddir, char *name)
8044 strcpy(enddir, dp->d_name); 8060 strcpy(enddir, dp->d_name);
8045 addfname(expdir); 8061 addfname(expdir);
8046 } else { 8062 } else {
8047 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';) 8063 unsigned offset;
8048 continue; 8064 unsigned len;
8049 p[-1] = '/'; 8065
8050 expmeta(expdir, p, endname); 8066 p = stpcpy(enddir, dp->d_name);
8067 *p = '/';
8068
8069 offset = p - expdir + 1;
8070 len = offset + name_len + NAME_MAX;
8071 if (len > expdir_max) {
8072 len += PATH_MAX;
8073 expdir = ckrealloc(expdir, len);
8074 expdir_max = len;
8075 }
8076
8077 expmeta(exp, endname, name_len, offset);
8078 enddir = expdir + expdir_len;
8051 } 8079 }
8052 } 8080 }
8053 } 8081 }
8054 closedir(dirp); 8082 closedir(dirp);
8055 if (!atend) 8083 if (!atend)
8056 endname[-esc - 1] = esc ? '\\' : '/'; 8084 endname[-esc - 1] = esc ? '\\' : '/';
8085#undef expdir
8086#undef expdir_max
8057} 8087}
8058 8088
8059static struct strlist * 8089static struct strlist *
@@ -8126,10 +8156,11 @@ expandmeta(struct strlist *str /*, int flag*/)
8126 /* TODO - EXP_REDIR */ 8156 /* TODO - EXP_REDIR */
8127 8157
8128 while (str) { 8158 while (str) {
8129 char *expdir; 8159 exp_t exp;
8130 struct strlist **savelastp; 8160 struct strlist **savelastp;
8131 struct strlist *sp; 8161 struct strlist *sp;
8132 char *p; 8162 char *p;
8163 unsigned len;
8133 8164
8134 if (fflag) 8165 if (fflag)
8135 goto nometa; 8166 goto nometa;
@@ -8139,13 +8170,12 @@ expandmeta(struct strlist *str /*, int flag*/)
8139 8170
8140 INT_OFF; 8171 INT_OFF;
8141 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); 8172 p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP);
8142 { 8173 len = strlen(p);
8143 int i = strlen(str->text); 8174 exp.dir_max = len + PATH_MAX;
8144//BUGGY estimation of how long expanded name can be 8175 exp.dir = ckmalloc(exp.dir_max);
8145 expdir = ckmalloc(i < 2048 ? 2048 : i+1); 8176
8146 } 8177 expmeta(&exp, p, len, 0);
8147 expmeta(expdir, expdir, p); 8178 free(exp.dir);
8148 free(expdir);
8149 if (p != str->text) 8179 if (p != str->text)
8150 free(p); 8180 free(p);
8151 INT_ON; 8181 INT_ON;
@@ -12128,10 +12158,12 @@ simplecmd(void)
12128 case TLP: 12158 case TLP:
12129 function_flag = 0; 12159 function_flag = 0;
12130 break; 12160 break;
12161# if BASH_TEST2
12131 case TWORD: 12162 case TWORD:
12132 if (strcmp("[[", wordtext) == 0) 12163 if (strcmp("[[", wordtext) == 0)
12133 goto do_func; 12164 goto do_func;
12134 /* fall through */ 12165 /* fall through */
12166# endif
12135 default: 12167 default:
12136 raise_error_unexpected_syntax(-1); 12168 raise_error_unexpected_syntax(-1);
12137 } 12169 }
@@ -12179,7 +12211,8 @@ simplecmd(void)
12179 *vpp = NULL; 12211 *vpp = NULL;
12180 *rpp = NULL; 12212 *rpp = NULL;
12181 n = stzalloc(sizeof(struct ncmd)); 12213 n = stzalloc(sizeof(struct ncmd));
12182 n->type = NCMD; 12214 if (NCMD != 0)
12215 n->type = NCMD;
12183 n->ncmd.linno = savelinno; 12216 n->ncmd.linno = savelinno;
12184 n->ncmd.args = args; 12217 n->ncmd.args = args;
12185 n->ncmd.assign = vars; 12218 n->ncmd.assign = vars;
@@ -12500,8 +12533,11 @@ readtoken1(int c, int syntax, char *eofmark, int striptabs)
12500 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */ 12533 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
12501 switch (SIT(c, synstack->syntax)) { 12534 switch (SIT(c, synstack->syntax)) {
12502 case CNL: /* '\n' */ 12535 case CNL: /* '\n' */
12503 if (synstack->syntax == BASESYNTAX) 12536 if (synstack->syntax == BASESYNTAX
12537 && !synstack->varnest
12538 ) {
12504 goto endword; /* exit outer loop */ 12539 goto endword; /* exit outer loop */
12540 }
12505 USTPUTC(c, out); 12541 USTPUTC(c, out);
12506 nlprompt(); 12542 nlprompt();
12507 c = pgetc(); 12543 c = pgetc();