[BACK]Return to expand.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rdist

Annotation of src/usr.bin/rdist/expand.c, Revision 1.9

1.9     ! millert     1: /*     $OpenBSD: expand.c,v 1.8 2003/04/05 20:31:58 deraadt Exp $      */
1.4       deraadt     2:
1.1       deraadt     3: /*
1.2       dm          4:  * Copyright (c) 1983 Regents of the University of California.
                      5:  * All rights reserved.
1.1       deraadt     6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
                     36: #ifndef lint
1.5       millert    37: #if 0
1.2       dm         38: static char RCSid[] =
1.5       millert    39: "$From: expand.c,v 6.18 1998/03/24 00:37:10 michaelc Exp $";
                     40: #else
                     41: static char RCSid[] =
1.9     ! millert    42: "$OpenBSD: expand.c,v 1.8 2003/04/05 20:31:58 deraadt Exp $";
1.5       millert    43: #endif
1.2       dm         44:
                     45: static char sccsid[] = "@(#)expand.c   5.2 (Berkeley) 3/28/86";
                     46:
                     47: char copyright[] =
                     48: "@(#) Copyright (c) 1983 Regents of the University of California.\n\
                     49:  All rights reserved.\n";
1.1       deraadt    50: #endif /* not lint */
                     51:
                     52: #include "defs.h"
                     53:
1.2       dm         54: #define        MAXEARGS        2048
                     55: #define LC             '{'
                     56: #define RC             '}'
1.1       deraadt    57:
                     58: static char    shchars[] = "${[*?";
                     59:
1.2       dm         60: int            which;          /* bit mask of types to expand */
                     61: int            eargc;          /* expanded arg count */
                     62: char         **eargv;          /* expanded arg vectors */
                     63: char          *path;
                     64: char          *pathp;
                     65: char          *lastpathp;
                     66: char          *tilde;          /* "~user" if not expanding tilde, else "" */
                     67: char          *tpathp;
                     68:
                     69: int            expany;         /* any expansions done? */
                     70: char          *entp;
                     71: char         **sortbase;
                     72: char          *argvbuf[MAXEARGS];
                     73:
                     74: static int     argcmp();
                     75: void           expstr();
                     76: void           expsh();
                     77: void           matchdir();
1.1       deraadt    78:
                     79: #define sort() qsort((char *)sortbase, &eargv[eargc] - sortbase, \
                     80:                      sizeof(*sortbase), argcmp), sortbase = &eargv[eargc]
                     81:
1.2       dm         82: static void Cat(s1, s2)                                /* quote in s1 and s2 */
1.7       mpech      83:        u_char *s1, *s2;
1.2       dm         84: {
1.7       mpech      85:        char *cp;
1.2       dm         86:        int len = strlen((char *)s1) + strlen((char *)s2) + 2;
                     87:
                     88:        if ((eargc + 1) >= MAXEARGS) {
                     89:                yyerror("Too many names");
                     90:                return;
                     91:        }
                     92:
1.5       millert    93:        eargv[++eargc] = NULL;
1.2       dm         94:        eargv[eargc - 1] = cp = xmalloc(len);
                     95:
                     96:        do {
                     97:                if (*s1 == QUOTECHAR)
                     98:                        s1++;
1.5       millert    99:        } while ((*cp++ = *s1++));
1.2       dm        100:        cp--;
                    101:        do {
                    102:                if (*s2 == QUOTECHAR)
                    103:                        s2++;
1.5       millert   104:        } while ((*cp++ = *s2++));
1.2       dm        105: }
                    106:
                    107: static void addpath(c)
                    108:        char c;
                    109: {
                    110:        if (pathp >= lastpathp) {
                    111:                yyerror("Pathname too long");
                    112:                return;
                    113:        } else {
                    114:                *pathp++ = c;
                    115:                *pathp = CNULL;
                    116:        }
                    117: }
1.1       deraadt   118:
                    119: /*
                    120:  * Take a list of names and expand any macros, etc.
                    121:  * wh = E_VARS if expanding variables.
                    122:  * wh = E_SHELL if expanding shell characters.
                    123:  * wh = E_TILDE if expanding `~'.
                    124:  * or any of these or'ed together.
                    125:  *
                    126:  * Major portions of this were snarfed from csh/sh.glob.c.
                    127:  */
                    128: struct namelist *
1.2       dm        129: expand(list, wh)                               /* quote in list->n_name */
1.1       deraadt   130:        struct namelist *list;
                    131:        int wh;
                    132: {
1.7       mpech     133:        struct namelist *nl, *prev;
                    134:        int n;
1.1       deraadt   135:        char pathbuf[BUFSIZ];
                    136:
1.2       dm        137:        if (debug)
                    138:                debugmsg(DM_CALL, "expand(%x, %d) start, list = %s",
                    139:                         list, wh, getnlstr(list));
1.1       deraadt   140:
1.2       dm        141:        if (wh == 0)
                    142:                fatalerr("expand() contains invalid 'wh' argument.");
1.1       deraadt   143:
                    144:        which = wh;
                    145:        path = tpathp = pathp = pathbuf;
1.2       dm        146:        *pathp = CNULL;
1.9     ! millert   147:        lastpathp = &pathbuf[sizeof pathbuf - 2];
1.1       deraadt   148:        tilde = "";
                    149:        eargc = 0;
                    150:        eargv = sortbase = argvbuf;
1.5       millert   151:        *eargv = NULL;
1.2       dm        152:
1.1       deraadt   153:        /*
                    154:         * Walk the name list and expand names into eargv[];
                    155:         */
                    156:        for (nl = list; nl != NULL; nl = nl->n_next)
1.2       dm        157:                expstr((u_char *)nl->n_name);
1.1       deraadt   158:        /*
                    159:         * Take expanded list of names from eargv[] and build a new list.
                    160:         */
                    161:        list = prev = NULL;
                    162:        for (n = 0; n < eargc; n++) {
1.5       millert   163:                nl = makenl(NULL);
1.1       deraadt   164:                nl->n_name = eargv[n];
                    165:                if (prev == NULL)
                    166:                        list = prev = nl;
                    167:                else {
                    168:                        prev->n_next = nl;
                    169:                        prev = nl;
                    170:                }
                    171:        }
1.2       dm        172:
1.1       deraadt   173:        return(list);
                    174: }
                    175:
1.2       dm        176: /*
                    177:  * xstrchr() is a version of strchr() that
                    178:  * handles u_char buffers.
                    179:  */
                    180: u_char *xstrchr(str, ch)
                    181:        u_char *str;
                    182:        int ch;
1.1       deraadt   183: {
1.7       mpech     184:        u_char *cp;
1.2       dm        185:
                    186:        for (cp = str; cp && *cp != CNULL; ++cp)
                    187:                if (ch == *cp)
                    188:                        return(cp);
                    189:
1.5       millert   190:        return(NULL);
1.2       dm        191: }
                    192:
                    193: void expstr(s)
                    194:        u_char *s;
                    195: {
1.7       mpech     196:        u_char *cp, *cp1;
                    197:        struct namelist *tp;
1.2       dm        198:        u_char *tail;
                    199:        u_char ebuf[BUFSIZ];
                    200:        u_char varbuff[BUFSIZ];
1.1       deraadt   201:        int savec, oeargc;
1.2       dm        202:        extern char *homedir;
1.1       deraadt   203:
1.2       dm        204:        if (s == NULL || *s == CNULL)
1.1       deraadt   205:                return;
                    206:
1.2       dm        207:        /*
                    208:         * Remove quoted characters
                    209:         */
                    210:        if (IS_ON(which, E_VARS)) {
                    211:                if ((int)strlen((char *)s) > sizeof(varbuff)) {
                    212:                        yyerror("Variable is too large.");
                    213:                        return;
                    214:                }
                    215:                for (cp = s, cp1 = varbuff; cp && *cp; ++cp) {
                    216:                        /*
                    217:                         * remove quoted character if the next
                    218:                         * character is not $
                    219:                         */
                    220:                        if (*cp == QUOTECHAR && *(cp+1) != '$')
                    221:                                ++cp;
                    222:                        else
                    223:                                *cp1++ = *cp;
                    224:                }
                    225:                *cp1 = CNULL;
                    226:                s = varbuff;
                    227:        }
                    228:
                    229:        /*
                    230:         * Consider string 's' a variable that should be expanded if
                    231:         * there is a '$' in 's' that is not quoted.
                    232:         */
                    233:        if (IS_ON(which, E_VARS) &&
                    234:            ((cp = xstrchr(s, '$')) && !(cp > s && *(cp-1) == QUOTECHAR))) {
                    235:                *cp++ = CNULL;
                    236:                if (*cp == CNULL) {
1.1       deraadt   237:                        yyerror("no variable name after '$'");
                    238:                        return;
                    239:                }
                    240:                if (*cp == LC) {
                    241:                        cp++;
1.2       dm        242:                        for (cp1 = cp; ; cp1 = tail + 1) {
                    243:                                if ((tail = xstrchr(cp1, RC)) == NULL) {
                    244:                                        yyerror("unmatched '{'");
                    245:                                        return;
                    246:                                }
                    247:                                if (tail[-1] != QUOTECHAR) break;
1.1       deraadt   248:                        }
1.2       dm        249:                        *tail++ = savec = CNULL;
                    250:                        if (*cp == CNULL) {
1.1       deraadt   251:                                yyerror("no variable name after '$'");
                    252:                                return;
                    253:                        }
                    254:                } else {
                    255:                        tail = cp + 1;
                    256:                        savec = *tail;
1.2       dm        257:                        *tail = CNULL;
1.1       deraadt   258:                }
1.5       millert   259:                tp = lookup((char *)cp, LOOKUP, NULL);
1.2       dm        260:                if (savec != CNULL)
1.1       deraadt   261:                        *tail = savec;
                    262:                if (tp != NULL) {
                    263:                        for (; tp != NULL; tp = tp->n_next) {
1.6       deraadt   264:                                (void) snprintf((char *)ebuf, sizeof ebuf,
                    265:                                    "%s%s%s", s, tp->n_name, tail);
1.2       dm        266:                                expstr(ebuf);
1.1       deraadt   267:                        }
                    268:                        return;
                    269:                }
1.6       deraadt   270:                (void) snprintf((char *)ebuf, sizeof ebuf, "%s%s", s, tail);
1.2       dm        271:                expstr(ebuf);
1.1       deraadt   272:                return;
                    273:        }
1.2       dm        274:        if ((which & ~E_VARS) == 0 || !strcmp((char *)s, "{") ||
                    275:            !strcmp((char *)s, "{}")) {
                    276:                Cat(s, (u_char *)"");
1.1       deraadt   277:                sort();
                    278:                return;
                    279:        }
                    280:        if (*s == '~') {
                    281:                cp = ++s;
1.2       dm        282:                if (*cp == CNULL || *cp == '/') {
1.1       deraadt   283:                        tilde = "~";
1.2       dm        284:                        cp1 = (u_char *)homedir;
1.1       deraadt   285:                } else {
1.2       dm        286:                        tilde = (char *)(cp1 = ebuf);
1.1       deraadt   287:                        *cp1++ = '~';
                    288:                        do
                    289:                                *cp1++ = *cp++;
                    290:                        while (*cp && *cp != '/');
1.2       dm        291:                        *cp1 = CNULL;
                    292:                        if (pw == NULL || strcmp(pw->pw_name,
                    293:                                                 (char *)ebuf+1) != 0) {
                    294:                                if ((pw = getpwnam((char *)ebuf+1)) == NULL) {
1.9     ! millert   295:                                        strlcat((char *)ebuf,
        !           296:                                            ": unknown user name",
        !           297:                                            sizeof(ebuf));
1.2       dm        298:                                        yyerror((char *)ebuf+1);
1.1       deraadt   299:                                        return;
                    300:                                }
                    301:                        }
1.2       dm        302:                        cp1 = (u_char *)pw->pw_dir;
1.1       deraadt   303:                        s = cp;
                    304:                }
1.5       millert   305:                for (cp = (u_char *)path; (*cp++ = *cp1++); )
1.1       deraadt   306:                        ;
1.2       dm        307:                tpathp = pathp = (char *)cp - 1;
1.1       deraadt   308:        } else {
                    309:                tpathp = pathp = path;
                    310:                tilde = "";
                    311:        }
1.2       dm        312:        *pathp = CNULL;
1.1       deraadt   313:        if (!(which & E_SHELL)) {
                    314:                if (which & E_TILDE)
1.2       dm        315:                        Cat((u_char *)path, s);
1.1       deraadt   316:                else
1.2       dm        317:                        Cat((u_char *)tilde, s);
1.1       deraadt   318:                sort();
                    319:                return;
                    320:        }
                    321:        oeargc = eargc;
                    322:        expany = 0;
                    323:        expsh(s);
                    324:        if (eargc == oeargc)
1.2       dm        325:                Cat(s, (u_char *)"");           /* "nonomatch" is set */
1.1       deraadt   326:        sort();
                    327: }
                    328:
1.5       millert   329: static int
1.1       deraadt   330: argcmp(a1, a2)
1.2       dm        331:        char **a1, **a2;
1.1       deraadt   332: {
                    333:
1.2       dm        334:        return (strcmp(*a1, *a2));
1.1       deraadt   335: }
                    336:
                    337: /*
                    338:  * If there are any Shell meta characters in the name,
                    339:  * expand into a list, after searching directory
                    340:  */
1.2       dm        341: void expsh(s)                          /* quote in s */
                    342:        u_char *s;
1.1       deraadt   343: {
1.7       mpech     344:        u_char *cp, *oldcp;
                    345:        char *spathp;
1.1       deraadt   346:        struct stat stb;
                    347:
                    348:        spathp = pathp;
                    349:        cp = s;
                    350:        while (!any(*cp, shchars)) {
1.2       dm        351:                if (*cp == CNULL) {
1.1       deraadt   352:                        if (!expany || stat(path, &stb) >= 0) {
                    353:                                if (which & E_TILDE)
1.2       dm        354:                                        Cat((u_char *)path, (u_char *)"");
1.1       deraadt   355:                                else
1.2       dm        356:                                        Cat((u_char *)tilde, (u_char *)tpathp);
1.1       deraadt   357:                        }
                    358:                        goto endit;
                    359:                }
1.2       dm        360:                if (*cp == QUOTECHAR) cp++;
1.1       deraadt   361:                addpath(*cp++);
                    362:        }
                    363:        oldcp = cp;
                    364:        while (cp > s && *cp != '/')
                    365:                cp--, pathp--;
                    366:        if (*cp == '/')
                    367:                cp++, pathp++;
1.2       dm        368:        *pathp = CNULL;
1.1       deraadt   369:        if (*oldcp == '{') {
1.5       millert   370:                (void) execbrc(cp, NULL);
1.1       deraadt   371:                return;
                    372:        }
1.2       dm        373:        matchdir((char *)cp);
1.1       deraadt   374: endit:
                    375:        pathp = spathp;
1.2       dm        376:        *pathp = CNULL;
1.1       deraadt   377: }
                    378:
1.2       dm        379: void matchdir(pattern)                         /* quote in pattern */
1.1       deraadt   380:        char *pattern;
                    381: {
                    382:        struct stat stb;
1.7       mpech     383:        DIRENTRY *dp;
1.1       deraadt   384:        DIR *dirp;
                    385:
                    386:        dirp = opendir(path);
                    387:        if (dirp == NULL) {
                    388:                if (expany)
                    389:                        return;
                    390:                goto patherr2;
                    391:        }
                    392:        if (fstat(dirp->dd_fd, &stb) < 0)
                    393:                goto patherr1;
1.2       dm        394:        if (!S_ISDIR(stb.st_mode)) {
1.1       deraadt   395:                errno = ENOTDIR;
                    396:                goto patherr1;
                    397:        }
                    398:        while ((dp = readdir(dirp)) != NULL)
                    399:                if (match(dp->d_name, pattern)) {
                    400:                        if (which & E_TILDE)
1.2       dm        401:                                Cat((u_char *)path, (u_char *)dp->d_name);
1.1       deraadt   402:                        else {
1.9     ! millert   403:                                (void) strlcpy(pathp, dp->d_name,
        !           404:                                    lastpathp - pathp + 2);
1.2       dm        405:                                Cat((u_char *)tilde, (u_char *)tpathp);
                    406:                                *pathp = CNULL;
1.1       deraadt   407:                        }
                    408:                }
                    409:        closedir(dirp);
                    410:        return;
                    411:
                    412: patherr1:
                    413:        closedir(dirp);
                    414: patherr2:
1.9     ! millert   415:        (void) strlcat(path, ": ", lastpathp - path + 2);
        !           416:        (void) strlcat(path, SYSERR, lastpathp - path + 2);
1.1       deraadt   417:        yyerror(path);
                    418: }
                    419:
1.5       millert   420: int
1.2       dm        421: execbrc(p, s)                          /* quote in p */
                    422:        u_char *p, *s;
1.1       deraadt   423: {
1.2       dm        424:        u_char restbuf[BUFSIZ + 2];
1.7       mpech     425:        u_char *pe, *pm, *pl;
1.1       deraadt   426:        int brclev = 0;
1.2       dm        427:        u_char *lm, savec;
                    428:        char *spathp;
1.1       deraadt   429:
                    430:        for (lm = restbuf; *p != '{'; *lm++ = *p++)
1.2       dm        431:                if (*p == QUOTECHAR) *lm++ = *p++;
                    432:
1.1       deraadt   433:        for (pe = ++p; *pe; pe++)
                    434:                switch (*pe) {
                    435:
                    436:                case '{':
                    437:                        brclev++;
                    438:                        continue;
                    439:
                    440:                case '}':
                    441:                        if (brclev == 0)
                    442:                                goto pend;
                    443:                        brclev--;
                    444:                        continue;
                    445:
                    446:                case '[':
                    447:                        for (pe++; *pe && *pe != ']'; pe++)
1.2       dm        448:                                if (*p == QUOTECHAR) pe++;
1.1       deraadt   449:                        if (!*pe)
                    450:                                yyerror("Missing ']'");
                    451:                        continue;
1.2       dm        452:
                    453:                case QUOTECHAR:         /* skip this character */
                    454:                        pe++;
                    455:                        continue;
1.1       deraadt   456:                }
                    457: pend:
                    458:        if (brclev || !*pe) {
                    459:                yyerror("Missing '}'");
                    460:                return (0);
                    461:        }
                    462:        for (pl = pm = p; pm <= pe; pm++)
1.2       dm        463:                /* the strip code was a noop */
                    464:                switch (*pm) {
1.1       deraadt   465:
                    466:                case '{':
                    467:                        brclev++;
                    468:                        continue;
                    469:
                    470:                case '}':
                    471:                        if (brclev) {
                    472:                                brclev--;
                    473:                                continue;
                    474:                        }
                    475:                        goto doit;
                    476:
                    477:                case ',':
                    478:                        if (brclev)
                    479:                                continue;
                    480: doit:
                    481:                        savec = *pm;
                    482:                        *pm = 0;
1.9     ! millert   483:                        *lm = 0;
        !           484:                        (void) strlcat((char *)restbuf, (char *)pl,
        !           485:                            sizeof restbuf);
1.8       deraadt   486:                        (void) strlcat((char *)restbuf, (char *)pe + 1,
                    487:                            sizeof restbuf);
1.1       deraadt   488:                        *pm = savec;
                    489:                        if (s == 0) {
                    490:                                spathp = pathp;
                    491:                                expsh(restbuf);
                    492:                                pathp = spathp;
                    493:                                *pathp = 0;
1.2       dm        494:                        } else if (amatch((char *)s, restbuf))
1.1       deraadt   495:                                return (1);
                    496:                        sort();
                    497:                        pl = pm + 1;
                    498:                        continue;
                    499:
                    500:                case '[':
                    501:                        for (pm++; *pm && *pm != ']'; pm++)
1.2       dm        502:                                if (*pm == QUOTECHAR) pm++;
1.1       deraadt   503:                        if (!*pm)
                    504:                                yyerror("Missing ']'");
                    505:                        continue;
1.2       dm        506:
                    507:                case QUOTECHAR:                 /* skip one character */
                    508:                        pm++;
                    509:                        continue;
1.1       deraadt   510:                }
                    511:        return (0);
                    512: }
                    513:
1.5       millert   514: int
1.2       dm        515: match(s, p)                                    /* quote in p */
1.1       deraadt   516:        char *s, *p;
                    517: {
1.7       mpech     518:        int c;
                    519:        char *sentp;
1.1       deraadt   520:        char sexpany = expany;
                    521:
                    522:        if (*s == '.' && *p != '.')
                    523:                return (0);
                    524:        sentp = entp;
                    525:        entp = s;
                    526:        c = amatch(s, p);
                    527:        entp = sentp;
                    528:        expany = sexpany;
                    529:        return (c);
                    530: }
                    531:
1.5       millert   532: int
1.2       dm        533: amatch(s, p)                                   /* quote in p */
1.7       mpech     534:        char *s;
                    535:        u_char *p;
1.1       deraadt   536: {
1.7       mpech     537:        int scc;
1.1       deraadt   538:        int ok, lc;
                    539:        char *spathp;
                    540:        struct stat stb;
                    541:        int c, cc;
                    542:
                    543:        expany = 1;
                    544:        for (;;) {
1.2       dm        545:                scc = *s++;
1.1       deraadt   546:                switch (c = *p++) {
                    547:
                    548:                case '{':
1.2       dm        549:                        return (execbrc((u_char *)p - 1, (u_char *)s - 1));
1.1       deraadt   550:
                    551:                case '[':
                    552:                        ok = 0;
                    553:                        lc = 077777;
1.5       millert   554:                        while ((cc = *p++)) {
1.1       deraadt   555:                                if (cc == ']') {
                    556:                                        if (ok)
                    557:                                                break;
                    558:                                        return (0);
                    559:                                }
1.2       dm        560:                                if (cc == QUOTECHAR) cc = *p++;
1.1       deraadt   561:                                if (cc == '-') {
1.2       dm        562:                                        if (lc <= scc && scc <= (int)*p++)
1.1       deraadt   563:                                                ok++;
                    564:                                } else
                    565:                                        if (scc == (lc = cc))
                    566:                                                ok++;
                    567:                        }
                    568:                        if (cc == 0) {
                    569:                                yyerror("Missing ']'");
                    570:                                return (0);
                    571:                        }
                    572:                        continue;
                    573:
                    574:                case '*':
                    575:                        if (!*p)
                    576:                                return (1);
                    577:                        if (*p == '/') {
                    578:                                p++;
                    579:                                goto slash;
                    580:                        }
                    581:                        for (s--; *s; s++)
                    582:                                if (amatch(s, p))
                    583:                                        return (1);
                    584:                        return (0);
                    585:
1.2       dm        586:                case CNULL:
                    587:                        return (scc == CNULL);
1.1       deraadt   588:
                    589:                default:
1.2       dm        590:                        if (c != scc)
1.1       deraadt   591:                                return (0);
                    592:                        continue;
                    593:
                    594:                case '?':
1.2       dm        595:                        if (scc == CNULL)
1.1       deraadt   596:                                return (0);
                    597:                        continue;
                    598:
                    599:                case '/':
                    600:                        if (scc)
                    601:                                return (0);
                    602: slash:
                    603:                        s = entp;
                    604:                        spathp = pathp;
                    605:                        while (*s)
                    606:                                addpath(*s++);
                    607:                        addpath('/');
1.2       dm        608:                        if (stat(path, &stb) == 0 && S_ISDIR(stb.st_mode))
                    609:                                if (*p == CNULL) {
1.1       deraadt   610:                                        if (which & E_TILDE)
1.2       dm        611:                                                Cat((u_char *)path,
                    612:                                                    (u_char *)"");
1.1       deraadt   613:                                        else
1.2       dm        614:                                                Cat((u_char *)tilde,
                    615:                                                    (u_char *)tpathp);
1.5       millert   616:                                } else {
1.1       deraadt   617:                                        expsh(p);
1.5       millert   618:                                }
1.1       deraadt   619:                        pathp = spathp;
1.2       dm        620:                        *pathp = CNULL;
1.1       deraadt   621:                        return (0);
                    622:                }
                    623:        }
                    624: }