[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.11

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