Annotation of 43BSD/ucb/ftp/glob.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char sccsid[] = "@(#)glob.c     5.2 (Berkeley) 3/7/86";
                      9: #endif not lint
                     10: 
                     11: /*
                     12:  * C-shell glob for random programs.
                     13:  */
                     14: 
                     15: #include <sys/param.h>
                     16: #include <sys/stat.h>
                     17: #include <sys/dir.h>
                     18: 
                     19: #include <stdio.h>
                     20: #include <errno.h>
                     21: #include <pwd.h>
                     22: 
                     23: #define        QUOTE 0200
                     24: #define        TRIM 0177
                     25: #define        eq(a,b)         (strcmp(a, b)==0)
                     26: #define        GAVSIZ          (NCARGS/6)
                     27: #define        isdir(d)        ((d.st_mode & S_IFMT) == S_IFDIR)
                     28: 
                     29: static char **gargv;           /* Pointer to the (stack) arglist */
                     30: static short gargc;            /* Number args in gargv */
                     31: static short gnleft;
                     32: static short gflag;
                     33: static int tglob();
                     34: char   **glob();
                     35: char   *globerr;
                     36: char   *home;
                     37: struct passwd *getpwnam();
                     38: extern int errno;
                     39: static char *strspl(), *strend();
                     40: char   *malloc(), *strcpy(), *strcat();
                     41: char   **copyblk();
                     42: 
                     43: static int globcnt;
                     44: 
                     45: char   *globchars = "`{[*?";
                     46: 
                     47: static char *gpath, *gpathp, *lastgpathp;
                     48: static int globbed;
                     49: static char *entp;
                     50: static char **sortbas;
                     51: 
                     52: char **
                     53: glob(v)
                     54:        register char *v;
                     55: {
                     56:        char agpath[BUFSIZ];
                     57:        char *agargv[GAVSIZ];
                     58:        char *vv[2];
                     59:        vv[0] = v;
                     60:        vv[1] = 0;
                     61:        gflag = 0;
                     62:        rscan(vv, tglob);
                     63:        if (gflag == 0)
                     64:                return (copyblk(vv));
                     65: 
                     66:        globerr = 0;
                     67:        gpath = agpath; gpathp = gpath; *gpathp = 0;
                     68:        lastgpathp = &gpath[sizeof agpath - 2];
                     69:        ginit(agargv); globcnt = 0;
                     70:        collect(v);
                     71:        if (globcnt == 0 && (gflag&1)) {
                     72:                blkfree(gargv), gargv = 0;
                     73:                return (0);
                     74:        } else
                     75:                return (gargv = copyblk(gargv));
                     76: }
                     77: 
                     78: static
                     79: ginit(agargv)
                     80:        char **agargv;
                     81: {
                     82: 
                     83:        agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
                     84:        gnleft = NCARGS - 4;
                     85: }
                     86: 
                     87: static
                     88: collect(as)
                     89:        register char *as;
                     90: {
                     91:        if (eq(as, "{") || eq(as, "{}")) {
                     92:                Gcat(as, "");
                     93:                sort();
                     94:        } else
                     95:                acollect(as);
                     96: }
                     97: 
                     98: static
                     99: acollect(as)
                    100:        register char *as;
                    101: {
                    102:        register int ogargc = gargc;
                    103: 
                    104:        gpathp = gpath; *gpathp = 0; globbed = 0;
                    105:        expand(as);
                    106:        if (gargc != ogargc)
                    107:                sort();
                    108: }
                    109: 
                    110: static
                    111: sort()
                    112: {
                    113:        register char **p1, **p2, *c;
                    114:        char **Gvp = &gargv[gargc];
                    115: 
                    116:        p1 = sortbas;
                    117:        while (p1 < Gvp-1) {
                    118:                p2 = p1;
                    119:                while (++p2 < Gvp)
                    120:                        if (strcmp(*p1, *p2) > 0)
                    121:                                c = *p1, *p1 = *p2, *p2 = c;
                    122:                p1++;
                    123:        }
                    124:        sortbas = Gvp;
                    125: }
                    126: 
                    127: static
                    128: expand(as)
                    129:        char *as;
                    130: {
                    131:        register char *cs;
                    132:        register char *sgpathp, *oldcs;
                    133:        struct stat stb;
                    134: 
                    135:        sgpathp = gpathp;
                    136:        cs = as;
                    137:        if (*cs == '~' && gpathp == gpath) {
                    138:                addpath('~');
                    139:                for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
                    140:                        addpath(*cs++);
                    141:                if (!*cs || *cs == '/') {
                    142:                        if (gpathp != gpath + 1) {
                    143:                                *gpathp = 0;
                    144:                                if (gethdir(gpath + 1))
                    145:                                        globerr = "Unknown user name after ~";
                    146:                                (void) strcpy(gpath, gpath + 1);
                    147:                        } else
                    148:                                (void) strcpy(gpath, home);
                    149:                        gpathp = strend(gpath);
                    150:                }
                    151:        }
                    152:        while (!any(*cs, globchars)) {
                    153:                if (*cs == 0) {
                    154:                        if (!globbed)
                    155:                                Gcat(gpath, "");
                    156:                        else if (stat(gpath, &stb) >= 0) {
                    157:                                Gcat(gpath, "");
                    158:                                globcnt++;
                    159:                        }
                    160:                        goto endit;
                    161:                }
                    162:                addpath(*cs++);
                    163:        }
                    164:        oldcs = cs;
                    165:        while (cs > as && *cs != '/')
                    166:                cs--, gpathp--;
                    167:        if (*cs == '/')
                    168:                cs++, gpathp++;
                    169:        *gpathp = 0;
                    170:        if (*oldcs == '{') {
                    171:                (void) execbrc(cs, ((char *)0));
                    172:                return;
                    173:        }
                    174:        matchdir(cs);
                    175: endit:
                    176:        gpathp = sgpathp;
                    177:        *gpathp = 0;
                    178: }
                    179: 
                    180: static
                    181: matchdir(pattern)
                    182:        char *pattern;
                    183: {
                    184:        struct stat stb;
                    185:        register struct direct *dp;
                    186:        DIR *dirp;
                    187: 
                    188:        dirp = opendir(gpath);
                    189:        if (dirp == NULL) {
                    190:                if (globbed)
                    191:                        return;
                    192:                goto patherr2;
                    193:        }
                    194:        if (fstat(dirp->dd_fd, &stb) < 0)
                    195:                goto patherr1;
                    196:        if (!isdir(stb)) {
                    197:                errno = ENOTDIR;
                    198:                goto patherr1;
                    199:        }
                    200:        while ((dp = readdir(dirp)) != NULL) {
                    201:                if (dp->d_ino == 0)
                    202:                        continue;
                    203:                if (match(dp->d_name, pattern)) {
                    204:                        Gcat(gpath, dp->d_name);
                    205:                        globcnt++;
                    206:                }
                    207:        }
                    208:        closedir(dirp);
                    209:        return;
                    210: 
                    211: patherr1:
                    212:        closedir(dirp);
                    213: patherr2:
                    214:        globerr = "Bad directory components";
                    215: }
                    216: 
                    217: static
                    218: execbrc(p, s)
                    219:        char *p, *s;
                    220: {
                    221:        char restbuf[BUFSIZ + 2];
                    222:        register char *pe, *pm, *pl;
                    223:        int brclev = 0;
                    224:        char *lm, savec, *sgpathp;
                    225: 
                    226:        for (lm = restbuf; *p != '{'; *lm++ = *p++)
                    227:                continue;
                    228:        for (pe = ++p; *pe; pe++)
                    229:        switch (*pe) {
                    230: 
                    231:        case '{':
                    232:                brclev++;
                    233:                continue;
                    234: 
                    235:        case '}':
                    236:                if (brclev == 0)
                    237:                        goto pend;
                    238:                brclev--;
                    239:                continue;
                    240: 
                    241:        case '[':
                    242:                for (pe++; *pe && *pe != ']'; pe++)
                    243:                        continue;
                    244:                continue;
                    245:        }
                    246: pend:
                    247:        brclev = 0;
                    248:        for (pl = pm = p; pm <= pe; pm++)
                    249:        switch (*pm & (QUOTE|TRIM)) {
                    250: 
                    251:        case '{':
                    252:                brclev++;
                    253:                continue;
                    254: 
                    255:        case '}':
                    256:                if (brclev) {
                    257:                        brclev--;
                    258:                        continue;
                    259:                }
                    260:                goto doit;
                    261: 
                    262:        case ','|QUOTE:
                    263:        case ',':
                    264:                if (brclev)
                    265:                        continue;
                    266: doit:
                    267:                savec = *pm;
                    268:                *pm = 0;
                    269:                (void) strcpy(lm, pl);
                    270:                (void) strcat(restbuf, pe + 1);
                    271:                *pm = savec;
                    272:                if (s == 0) {
                    273:                        sgpathp = gpathp;
                    274:                        expand(restbuf);
                    275:                        gpathp = sgpathp;
                    276:                        *gpathp = 0;
                    277:                } else if (amatch(s, restbuf))
                    278:                        return (1);
                    279:                sort();
                    280:                pl = pm + 1;
                    281:                if (brclev)
                    282:                        return (0);
                    283:                continue;
                    284: 
                    285:        case '[':
                    286:                for (pm++; *pm && *pm != ']'; pm++)
                    287:                        continue;
                    288:                if (!*pm)
                    289:                        pm--;
                    290:                continue;
                    291:        }
                    292:        if (brclev)
                    293:                goto doit;
                    294:        return (0);
                    295: }
                    296: 
                    297: static
                    298: match(s, p)
                    299:        char *s, *p;
                    300: {
                    301:        register int c;
                    302:        register char *sentp;
                    303:        char sglobbed = globbed;
                    304: 
                    305:        if (*s == '.' && *p != '.')
                    306:                return (0);
                    307:        sentp = entp;
                    308:        entp = s;
                    309:        c = amatch(s, p);
                    310:        entp = sentp;
                    311:        globbed = sglobbed;
                    312:        return (c);
                    313: }
                    314: 
                    315: static
                    316: amatch(s, p)
                    317:        register char *s, *p;
                    318: {
                    319:        register int scc;
                    320:        int ok, lc;
                    321:        char *sgpathp;
                    322:        struct stat stb;
                    323:        int c, cc;
                    324: 
                    325:        globbed = 1;
                    326:        for (;;) {
                    327:                scc = *s++ & TRIM;
                    328:                switch (c = *p++) {
                    329: 
                    330:                case '{':
                    331:                        return (execbrc(p - 1, s - 1));
                    332: 
                    333:                case '[':
                    334:                        ok = 0;
                    335:                        lc = 077777;
                    336:                        while (cc = *p++) {
                    337:                                if (cc == ']') {
                    338:                                        if (ok)
                    339:                                                break;
                    340:                                        return (0);
                    341:                                }
                    342:                                if (cc == '-') {
                    343:                                        if (lc <= scc && scc <= *p++)
                    344:                                                ok++;
                    345:                                } else
                    346:                                        if (scc == (lc = cc))
                    347:                                                ok++;
                    348:                        }
                    349:                        if (cc == 0)
                    350:                                if (ok)
                    351:                                        p--;
                    352:                                else
                    353:                                        return 0;
                    354:                        continue;
                    355: 
                    356:                case '*':
                    357:                        if (!*p)
                    358:                                return (1);
                    359:                        if (*p == '/') {
                    360:                                p++;
                    361:                                goto slash;
                    362:                        }
                    363:                        s--;
                    364:                        do {
                    365:                                if (amatch(s, p))
                    366:                                        return (1);
                    367:                        } while (*s++);
                    368:                        return (0);
                    369: 
                    370:                case 0:
                    371:                        return (scc == 0);
                    372: 
                    373:                default:
                    374:                        if (c != scc)
                    375:                                return (0);
                    376:                        continue;
                    377: 
                    378:                case '?':
                    379:                        if (scc == 0)
                    380:                                return (0);
                    381:                        continue;
                    382: 
                    383:                case '/':
                    384:                        if (scc)
                    385:                                return (0);
                    386: slash:
                    387:                        s = entp;
                    388:                        sgpathp = gpathp;
                    389:                        while (*s)
                    390:                                addpath(*s++);
                    391:                        addpath('/');
                    392:                        if (stat(gpath, &stb) == 0 && isdir(stb))
                    393:                                if (*p == 0) {
                    394:                                        Gcat(gpath, "");
                    395:                                        globcnt++;
                    396:                                } else
                    397:                                        expand(p);
                    398:                        gpathp = sgpathp;
                    399:                        *gpathp = 0;
                    400:                        return (0);
                    401:                }
                    402:        }
                    403: }
                    404: 
                    405: static
                    406: Gmatch(s, p)
                    407:        register char *s, *p;
                    408: {
                    409:        register int scc;
                    410:        int ok, lc;
                    411:        int c, cc;
                    412: 
                    413:        for (;;) {
                    414:                scc = *s++ & TRIM;
                    415:                switch (c = *p++) {
                    416: 
                    417:                case '[':
                    418:                        ok = 0;
                    419:                        lc = 077777;
                    420:                        while (cc = *p++) {
                    421:                                if (cc == ']') {
                    422:                                        if (ok)
                    423:                                                break;
                    424:                                        return (0);
                    425:                                }
                    426:                                if (cc == '-') {
                    427:                                        if (lc <= scc && scc <= *p++)
                    428:                                                ok++;
                    429:                                } else
                    430:                                        if (scc == (lc = cc))
                    431:                                                ok++;
                    432:                        }
                    433:                        if (cc == 0)
                    434:                                if (ok)
                    435:                                        p--;
                    436:                                else
                    437:                                        return 0;
                    438:                        continue;
                    439: 
                    440:                case '*':
                    441:                        if (!*p)
                    442:                                return (1);
                    443:                        for (s--; *s; s++)
                    444:                                if (Gmatch(s, p))
                    445:                                        return (1);
                    446:                        return (0);
                    447: 
                    448:                case 0:
                    449:                        return (scc == 0);
                    450: 
                    451:                default:
                    452:                        if ((c & TRIM) != scc)
                    453:                                return (0);
                    454:                        continue;
                    455: 
                    456:                case '?':
                    457:                        if (scc == 0)
                    458:                                return (0);
                    459:                        continue;
                    460: 
                    461:                }
                    462:        }
                    463: }
                    464: 
                    465: static
                    466: Gcat(s1, s2)
                    467:        register char *s1, *s2;
                    468: {
                    469:        register int len = strlen(s1) + strlen(s2) + 1;
                    470: 
                    471:        if (len >= gnleft || gargc >= GAVSIZ - 1)
                    472:                globerr = "Arguments too long";
                    473:        else {
                    474:                gargc++;
                    475:                gnleft -= len;
                    476:                gargv[gargc] = 0;
                    477:                gargv[gargc - 1] = strspl(s1, s2);
                    478:        }
                    479: }
                    480: 
                    481: static
                    482: addpath(c)
                    483:        char c;
                    484: {
                    485: 
                    486:        if (gpathp >= lastgpathp)
                    487:                globerr = "Pathname too long";
                    488:        else {
                    489:                *gpathp++ = c;
                    490:                *gpathp = 0;
                    491:        }
                    492: }
                    493: 
                    494: static
                    495: rscan(t, f)
                    496:        register char **t;
                    497:        int (*f)();
                    498: {
                    499:        register char *p, c;
                    500: 
                    501:        while (p = *t++) {
                    502:                if (f == tglob)
                    503:                        if (*p == '~')
                    504:                                gflag |= 2;
                    505:                        else if (eq(p, "{") || eq(p, "{}"))
                    506:                                continue;
                    507:                while (c = *p++)
                    508:                        (*f)(c);
                    509:        }
                    510: }
                    511: /*
                    512: static
                    513: scan(t, f)
                    514:        register char **t;
                    515:        int (*f)();
                    516: {
                    517:        register char *p, c;
                    518: 
                    519:        while (p = *t++)
                    520:                while (c = *p)
                    521:                        *p++ = (*f)(c);
                    522: } */
                    523: 
                    524: static
                    525: tglob(c)
                    526:        register char c;
                    527: {
                    528: 
                    529:        if (any(c, globchars))
                    530:                gflag |= c == '{' ? 2 : 1;
                    531:        return (c);
                    532: }
                    533: /*
                    534: static
                    535: trim(c)
                    536:        char c;
                    537: {
                    538: 
                    539:        return (c & TRIM);
                    540: } */
                    541: 
                    542: 
                    543: letter(c)
                    544:        register char c;
                    545: {
                    546: 
                    547:        return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');
                    548: }
                    549: 
                    550: digit(c)
                    551:        register char c;
                    552: {
                    553: 
                    554:        return (c >= '0' && c <= '9');
                    555: }
                    556: 
                    557: any(c, s)
                    558:        register int c;
                    559:        register char *s;
                    560: {
                    561: 
                    562:        while (*s)
                    563:                if (*s++ == c)
                    564:                        return(1);
                    565:        return(0);
                    566: }
                    567: blklen(av)
                    568:        register char **av;
                    569: {
                    570:        register int i = 0;
                    571: 
                    572:        while (*av++)
                    573:                i++;
                    574:        return (i);
                    575: }
                    576: 
                    577: char **
                    578: blkcpy(oav, bv)
                    579:        char **oav;
                    580:        register char **bv;
                    581: {
                    582:        register char **av = oav;
                    583: 
                    584:        while (*av++ = *bv++)
                    585:                continue;
                    586:        return (oav);
                    587: }
                    588: 
                    589: blkfree(av0)
                    590:        char **av0;
                    591: {
                    592:        register char **av = av0;
                    593: 
                    594:        while (*av)
                    595:                free(*av++);
                    596:        free((char *)av0);
                    597: }
                    598: 
                    599: static
                    600: char *
                    601: strspl(cp, dp)
                    602:        register char *cp, *dp;
                    603: {
                    604:        register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
                    605: 
                    606:        if (ep == (char *)0)
                    607:                fatal("Out of memory");
                    608:        (void) strcpy(ep, cp);
                    609:        (void) strcat(ep, dp);
                    610:        return (ep);
                    611: }
                    612: 
                    613: char **
                    614: copyblk(v)
                    615:        register char **v;
                    616: {
                    617:        register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) *
                    618:                                                sizeof(char **)));
                    619:        if (nv == (char **)0)
                    620:                fatal("Out of memory");
                    621: 
                    622:        return (blkcpy(nv, v));
                    623: }
                    624: 
                    625: static
                    626: char *
                    627: strend(cp)
                    628:        register char *cp;
                    629: {
                    630: 
                    631:        while (*cp)
                    632:                cp++;
                    633:        return (cp);
                    634: }
                    635: /*
                    636:  * Extract a home directory from the password file
                    637:  * The argument points to a buffer where the name of the
                    638:  * user whose home directory is sought is currently.
                    639:  * We write the home directory of the user back there.
                    640:  */
                    641: gethdir(home)
                    642:        char *home;
                    643: {
                    644:        register struct passwd *pp = getpwnam(home);
                    645: 
                    646:        if (pp == 0)
                    647:                return (1);
                    648:        (void) strcpy(home, pp->pw_dir);
                    649:        return (0);
                    650: }

unix.superglobalmegacorp.com

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