aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c71
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" */
7164static int
7165hasmeta(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)
7436static void 7476static void
7437expandmeta(struct strlist *str /*, int flag*/) 7477expandmeta(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