diff options
-rw-r--r-- | shell/ash.c | 71 |
1 files changed, 54 insertions, 17 deletions
diff --git a/shell/ash.c b/shell/ash.c index e07b81c05..6be3ec600 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -7160,6 +7160,57 @@ addfname(const char *name) | |||
7160 | exparg.lastp = &sp->next; | 7160 | exparg.lastp = &sp->next; |
7161 | } | 7161 | } |
7162 | 7162 | ||
7163 | /* Avoid glob() (and thus, stat() et al) for words like "echo" */ | ||
7164 | static int | ||
7165 | hasmeta(const char *p) | ||
7166 | { | ||
7167 | static const char chars[] ALIGN1 = { | ||
7168 | '*', '?', '[', '\\', CTLQUOTEMARK, CTLESC, 0 | ||
7169 | }; | ||
7170 | |||
7171 | for (;;) { | ||
7172 | p = strpbrk(p, chars); | ||
7173 | if (!p) | ||
7174 | break; | ||
7175 | switch ((unsigned char) *p) { | ||
7176 | case CTLQUOTEMARK: | ||
7177 | for (;;) { | ||
7178 | p++; | ||
7179 | if (*p == CTLQUOTEMARK) | ||
7180 | break; | ||
7181 | if (*p == CTLESC) | ||
7182 | p++; | ||
7183 | if (*p == '\0') /* huh? */ | ||
7184 | return 0; | ||
7185 | } | ||
7186 | break; | ||
7187 | case '\\': | ||
7188 | case CTLESC: | ||
7189 | p++; | ||
7190 | if (*p == '\0') | ||
7191 | return 0; | ||
7192 | break; | ||
7193 | case '[': | ||
7194 | if (!strchr(p + 1, ']')) { | ||
7195 | /* It's not a properly closed [] pattern, | ||
7196 | * but other metas may follow. Continue checking. | ||
7197 | * my[file* _is_ globbed by bash | ||
7198 | * and matches filenames like "my[file1". | ||
7199 | */ | ||
7200 | break; | ||
7201 | } | ||
7202 | /* fallthrough */ | ||
7203 | default: | ||
7204 | /* case '*': */ | ||
7205 | /* case '?': */ | ||
7206 | return 1; | ||
7207 | } | ||
7208 | p++; | ||
7209 | } | ||
7210 | |||
7211 | return 0; | ||
7212 | } | ||
7213 | |||
7163 | /* If we want to use glob() from libc... */ | 7214 | /* If we want to use glob() from libc... */ |
7164 | #if !ENABLE_ASH_INTERNAL_GLOB | 7215 | #if !ENABLE_ASH_INTERNAL_GLOB |
7165 | 7216 | ||
@@ -7186,20 +7237,9 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7186 | if (fflag) | 7237 | if (fflag) |
7187 | goto nometa; | 7238 | goto nometa; |
7188 | 7239 | ||
7189 | /* Avoid glob() (and thus, stat() et al) for words like "echo" */ | 7240 | if (!hasmeta(str->text)) |
7190 | p = str->text; | 7241 | goto nometa; |
7191 | while (*p) { | ||
7192 | if (*p == '*') | ||
7193 | goto need_glob; | ||
7194 | if (*p == '?') | ||
7195 | goto need_glob; | ||
7196 | if (*p == '[') | ||
7197 | goto need_glob; | ||
7198 | p++; | ||
7199 | } | ||
7200 | goto nometa; | ||
7201 | 7242 | ||
7202 | need_glob: | ||
7203 | INT_OFF; | 7243 | INT_OFF; |
7204 | p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); | 7244 | p = preglob(str->text, RMESCAPE_ALLOC | RMESCAPE_HEAP); |
7205 | // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match | 7245 | // GLOB_NOMAGIC (GNU): if no *?[ chars in pattern, return it even if no match |
@@ -7436,9 +7476,6 @@ expsort(struct strlist *str) | |||
7436 | static void | 7476 | static void |
7437 | expandmeta(struct strlist *str /*, int flag*/) | 7477 | expandmeta(struct strlist *str /*, int flag*/) |
7438 | { | 7478 | { |
7439 | static const char metachars[] ALIGN1 = { | ||
7440 | '*', '?', '[', 0 | ||
7441 | }; | ||
7442 | /* TODO - EXP_REDIR */ | 7479 | /* TODO - EXP_REDIR */ |
7443 | 7480 | ||
7444 | while (str) { | 7481 | while (str) { |
@@ -7449,7 +7486,7 @@ expandmeta(struct strlist *str /*, int flag*/) | |||
7449 | 7486 | ||
7450 | if (fflag) | 7487 | if (fflag) |
7451 | goto nometa; | 7488 | goto nometa; |
7452 | if (!strpbrk(str->text, metachars)) | 7489 | if (!hasmeta(str->text)) |
7453 | goto nometa; | 7490 | goto nometa; |
7454 | savelastp = exparg.lastp; | 7491 | savelastp = exparg.lastp; |
7455 | 7492 | ||