diff options
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 92 |
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 | */ |
7960 | typedef struct exp_t { | ||
7961 | char *dir; | ||
7962 | unsigned dir_max; | ||
7963 | } exp_t; | ||
7947 | static void | 7964 | static void |
7948 | expmeta(char *expdir, char *enddir, char *name) | 7965 | expmeta(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 | ||
8059 | static struct strlist * | 8089 | static 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(); |