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

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

unix.superglobalmegacorp.com

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