Annotation of 43BSDTahoe/ucb/rdist/expand.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.