diff options
author | tegge <tegge@FreeBSD.org> | 1999-04-09 15:23:48 +0000 |
---|---|---|
committer | tegge <tegge@FreeBSD.org> | 1999-04-09 15:23:48 +0000 |
commit | e35119550e9142eb4be6ce80eab506e95a9ac0f8 (patch) | |
tree | fdfffe8e5c0927cda6bae4c7667c42cbb19f2d72 /bin/sh | |
parent | b624ddd42093f5eb9104e8e66da8b702e2d56476 (diff) | |
download | FreeBSD-src-e35119550e9142eb4be6ce80eab506e95a9ac0f8.zip FreeBSD-src-e35119550e9142eb4be6ce80eab506e95a9ac0f8.tar.gz |
When a variable expansion is enclosed in double quotes, the internal
representation of the expression is quoted. Take care of this when
doing pattern matching in conjunction with trimming.
#!/bin/sh
c=d:e; echo "${c%:e}"
PR: NetBSD PR#7231
Noticed by: Havard Eidnes <Havard.Eidnes@runit.sintef.no>
Diffstat (limited to 'bin/sh')
-rw-r--r-- | bin/sh/expand.c | 68 | ||||
-rw-r--r-- | bin/sh/expand.h | 4 |
2 files changed, 56 insertions, 16 deletions
diff --git a/bin/sh/expand.c b/bin/sh/expand.c index 757ff3a..8a6f03a 100644 --- a/bin/sh/expand.c +++ b/bin/sh/expand.c @@ -39,7 +39,7 @@ static char sccsid[] = "@(#)expand.c 8.5 (Berkeley) 5/15/95"; #endif static const char rcsid[] = - "$Id: expand.c,v 1.23 1998/09/06 21:13:09 tegge Exp $"; + "$Id: expand.c,v 1.24 1998/09/13 19:24:57 tegge Exp $"; #endif /* not lint */ #include <sys/types.h> @@ -110,7 +110,7 @@ STATIC void expmeta __P((char *, char *)); STATIC void addfname __P((char *)); STATIC struct strlist *expsort __P((struct strlist *)); STATIC struct strlist *msort __P((struct strlist *, int)); -STATIC int pmatch __P((char *, char *)); +STATIC int pmatch __P((char *, char *, int)); STATIC char *cvtnum __P((int, char *)); STATIC int collate_range_cmp __P((int, int)); @@ -517,6 +517,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags) { char *startp; char *loc = NULL; + char *q; int c = 0; int saveherefd = herefd; struct nodelist *saveargbackq = argbackq; @@ -555,43 +556,65 @@ subevalvar(p, str, strloc, subtype, startloc, varflags) for (loc = startp; loc < str; loc++) { c = *loc; *loc = '\0'; - if (patmatch(str, startp)) { + if (patmatch(str, startp, varflags & VSQUOTE)) { *loc = c; goto recordleft; } *loc = c; + if ((varflags & VSQUOTE) && *loc == CTLESC) + loc++; } return 0; case VSTRIMLEFTMAX: - for (loc = str - 1; loc >= startp; loc--) { + for (loc = str - 1; loc >= startp;) { c = *loc; *loc = '\0'; - if (patmatch(str, startp)) { + if (patmatch(str, startp, varflags & VSQUOTE)) { *loc = c; goto recordleft; } *loc = c; + loc--; + if ((varflags & VSQUOTE) && loc > startp && + *(loc - 1) == CTLESC) { + for (q = startp; q < loc; q++) + if (*q == CTLESC) + q++; + if (q > loc) + loc--; + } } return 0; case VSTRIMRIGHT: - for (loc = str - 1; loc >= startp; loc--) { - if (patmatch(str, loc)) { + for (loc = str - 1; loc >= startp;) { + if (patmatch(str, loc, varflags & VSQUOTE)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } + loc--; + if ((varflags & VSQUOTE) && loc > startp && + *(loc - 1) == CTLESC) { + for (q = startp; q < loc; q++) + if (*q == CTLESC) + q++; + if (q > loc) + loc--; + } } return 0; case VSTRIMRIGHTMAX: for (loc = startp; loc < str - 1; loc++) { - if (patmatch(str, loc)) { + if (patmatch(str, loc, varflags & VSQUOTE)) { amount = loc - expdest; STADJUST(amount, expdest); return 1; } + if ((varflags & VSQUOTE) && *loc == CTLESC) + loc++; } return 0; @@ -1206,7 +1229,7 @@ expmeta(enddir, name) while (! int_pending() && (dp = readdir(dirp)) != NULL) { if (dp->d_name[0] == '.' && ! matchdot) continue; - if (patmatch(start, dp->d_name)) { + if (patmatch(start, dp->d_name, 0)) { if (atend) { scopy(dp->d_name, enddir); addfname(expdir); @@ -1315,23 +1338,25 @@ msort(list, len) */ int -patmatch(pattern, string) +patmatch(pattern, string, squoted) char *pattern; char *string; + int squoted; /* string might have quote chars */ { #ifdef notdef if (pattern[0] == '!' && pattern[1] == '!') return 1 - pmatch(pattern + 2, string); else #endif - return pmatch(pattern, string); + return pmatch(pattern, string, squoted); } STATIC int -pmatch(pattern, string) +pmatch(pattern, string, squoted) char *pattern; char *string; + int squoted; { char *p, *q; char c; @@ -1343,12 +1368,16 @@ pmatch(pattern, string) case '\0': goto breakloop; case CTLESC: + if (squoted && *q == CTLESC) + q++; if (*q++ != *p++) return 0; break; case CTLQUOTEMARK: continue; case '?': + if (squoted && *q == CTLESC) + q++; if (*q++ == '\0') return 0; break; @@ -1359,14 +1388,21 @@ pmatch(pattern, string) if (c != CTLESC && c != CTLQUOTEMARK && c != '?' && c != '*' && c != '[') { while (*q != c) { + if (squoted && *q == CTLESC && + q[1] == c) + break; if (*q == '\0') return 0; + if (squoted && *q == CTLESC) + q++; q++; } } do { - if (pmatch(p, q)) + if (pmatch(p, q, squoted)) return 1; + if (squoted && *q == CTLESC) + q++; } while (*q++ != '\0'); return 0; case '[': { @@ -1394,6 +1430,8 @@ pmatch(pattern, string) } found = 0; chr = *q++; + if (squoted && chr == CTLESC) + chr = *q++; if (chr == '\0') return 0; c = *p++; @@ -1423,6 +1461,8 @@ pmatch(pattern, string) break; } dft: default: + if (squoted && *q == CTLESC) + q++; if (*q++ != c) return 0; break; @@ -1486,7 +1526,7 @@ casematch(pattern, val) argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); STPUTC('\0', expdest); p = grabstackstr(expdest); - result = patmatch(p, val); + result = patmatch(p, val, 0); popstackmark(&smark); return result; } diff --git a/bin/sh/expand.h b/bin/sh/expand.h index 18c1663..eec9885 100644 --- a/bin/sh/expand.h +++ b/bin/sh/expand.h @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * @(#)expand.h 8.2 (Berkeley) 5/4/95 - * $Id: expand.h,v 1.6 1998/09/06 21:13:09 tegge Exp $ + * $Id: expand.h,v 1.7 1998/09/13 19:24:57 tegge Exp $ */ struct strlist { @@ -62,6 +62,6 @@ union node; void expandhere __P((union node *, int)); void expandarg __P((union node *, struct arglist *, int)); void expari __P((int)); -int patmatch __P((char *, char *)); +int patmatch __P((char *, char *, int)); void rmescapes __P((char *)); int casematch __P((union node *, char *)); |