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

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