Annotation of 43BSD/contrib/xns/examples/filing/glob.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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