Annotation of 41BSD/cmd/oldcsh/sh.glob.c, revision 1.1.1.1

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #include "sh.h"
                      3: 
                      4: /*
                      5:  * C Shell
                      6:  */
                      7: 
                      8: int    globcnt;
                      9: 
                     10: char   *globchars =    "`{[*?";
                     11: 
                     12: char   *gpath, *gpathp, *lastgpathp;
                     13: int    globbed;
                     14: bool   noglob;
                     15: bool   nonomatch;
                     16: char   *entp;
                     17: char   **sortbas;
                     18: 
                     19: char **
                     20: glob(v)
                     21:        register char **v;
                     22: {
                     23:        char agpath[160];
                     24:        char *agargv[GAVSIZ];
                     25: 
                     26:        gpath = agpath; gpathp = gpath; *gpathp = 0;
                     27:        lastgpathp = &gpath[sizeof agpath - 2];
                     28:        ginit(agargv); globcnt = 0;
                     29: #ifdef GDEBUG
                     30:        printf("glob entered: "); blkpr(v); printf("\n");
                     31: #endif
                     32:        noglob = adrof("noglob") != 0;
                     33:        nonomatch = adrof("nonomatch") != 0;
                     34:        globcnt = noglob | nonomatch;
                     35:        while (*v)
                     36:                collect(*v++);
                     37: #ifdef GDEBUG
                     38:        printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");
                     39: #endif
                     40:        if (globcnt == 0 && (gflag&1)) {
                     41:                blkfree(gargv), gargv = 0;
                     42:                return (0);
                     43:        } else
                     44:                return (gargv = copyblk(gargv));
                     45: }
                     46: 
                     47: ginit(agargv)
                     48:        char **agargv;
                     49: {
                     50: 
                     51:        agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
                     52:        gnleft = NCARGS - 4;
                     53: }
                     54: 
                     55: collect(as)
                     56:        register char *as;
                     57: {
                     58:        register int i;
                     59: 
                     60:        if (any('`', as)) {
                     61: #ifdef GDEBUG
                     62:                printf("doing backp of %s\n", as);
                     63: #endif
                     64:                dobackp(as, 0);
                     65: #ifdef GDEBUG
                     66:                printf("backp done, acollect'ing\n");
                     67: #endif
                     68:                for (i = 0; i < pargc; i++)
                     69:                        if (noglob)
                     70:                                Gcat(pargv[i], "");
                     71:                        else
                     72:                                acollect(pargv[i]);
                     73:                if (pargv)
                     74:                        blkfree(pargv), pargv = 0;
                     75: #ifdef GDEBUG
                     76:                printf("acollect done\n");
                     77: #endif
                     78:        } else if (noglob)
                     79:                Gcat(as, "");
                     80:        else
                     81:                acollect(as);
                     82: }
                     83: 
                     84: acollect(as)
                     85:        register char *as;
                     86: {
                     87:        register int ogargc = gargc;
                     88: 
                     89:        gpathp = gpath; *gpathp = 0; globbed = 0;
                     90:        expand(as);
                     91:        if (gargc == ogargc) {
                     92:                if (nonomatch)
                     93:                        Gcat(as, "");
                     94:        } else
                     95:                sort();
                     96: }
                     97: 
                     98: sort()
                     99: {
                    100:        register char **p1, **p2, *c;
                    101:        char **Gvp = &gargv[gargc];
                    102: 
                    103:        p1 = sortbas;
                    104:        while (p1 < Gvp-1) {
                    105:                p2 = p1;
                    106:                while (++p2 < Gvp)
                    107:                        if (strcmp(*p1, *p2) > 0)
                    108:                                c = *p1, *p1 = *p2, *p2 = c;
                    109:                p1++;
                    110:        }
                    111:        sortbas = Gvp;
                    112: }
                    113: 
                    114: expand(as)
                    115:        char *as;
                    116: {
                    117:        register char *cs;
                    118:        register char *sgpathp, *oldcs;
                    119:        struct stat stb;
                    120: 
                    121:        sgpathp = gpathp;
                    122:        cs = as;
                    123:        if (*cs == '~' && gpathp == gpath) {
                    124:                addpath('~');
                    125:                for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
                    126:                        addpath(*cs++);
                    127:                if (!*cs || *cs == '/') {
                    128:                        if (gpathp != gpath + 1) {
                    129:                                *gpathp = 0;
                    130:                                if (gethdir(gpath + 1))
                    131:                                        error("Unknown user: %s", gpath + 1);
                    132:                                strcpy(gpath, gpath + 1);
                    133:                        } else
                    134:                                strcpy(gpath, value("home"));
                    135:                        gpathp = strend(gpath);
                    136:                }
                    137:        }
                    138:        while (!any(*cs, globchars)) {
                    139:                if (*cs == 0) {
                    140:                        if (!globbed)
                    141:                                Gcat(gpath, "");
                    142:                        else if (stat(gpath, &stb) >= 0) {
                    143:                                Gcat(gpath, "");
                    144:                                globcnt++;
                    145:                        }
                    146:                        goto endit;
                    147:                }
                    148:                addpath(*cs++);
                    149:        }
                    150:        oldcs = cs;
                    151:        while (cs > as && *cs != '/')
                    152:                cs--, gpathp--;
                    153:        if (*cs == '/')
                    154:                cs++, gpathp++;
                    155:        *gpathp = 0;
                    156:        if (*oldcs == '{') {
                    157:                execbrc(cs, 0);
                    158:                return;
                    159:        }
                    160:        matchdir(cs);
                    161: endit:
                    162:        gpathp = sgpathp;
                    163:        *gpathp = 0;
                    164: }
                    165: 
                    166: matchdir(pattern)
                    167:        char *pattern;
                    168: {
                    169:        struct stat stb;
                    170:        struct direct dirbuf[BUFSIZ / sizeof (struct direct)];
                    171:        char d_name[DIRSIZ+1];
                    172:        register int dirf, cnt;
                    173: 
                    174:        dirf = open(gpath, 0);
                    175:        if (dirf < 0) {
                    176:                if (globbed)
                    177:                        return;
                    178:                goto patherr;
                    179:        }
                    180:        if (fstat(dirf, &stb) < 0)
                    181:                goto patherr;
                    182:        if (!isdir(stb)) {
                    183:                errno = ENOTDIR;
                    184:                goto patherr;
                    185:        }
                    186:        while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) {
                    187:                register struct direct *ep = dirbuf;
                    188: 
                    189:                for (cnt /= sizeof (struct direct); cnt > 0; cnt--, ep++) {
                    190:                        if (ep->d_ino == 0)
                    191:                                continue;
                    192:                        copdent(d_name, ep->d_name);
                    193:                        if (match(d_name, pattern)) {
                    194:                                Gcat(gpath, d_name);
                    195:                                globcnt++;
                    196:                        }
                    197:                }
                    198:        }
                    199:        close(dirf);
                    200:        return;
                    201: 
                    202: patherr:
                    203:        Perror(gpath);
                    204: }
                    205: 
                    206: copdent(to, from)
                    207:        register char *to, *from;
                    208: {
                    209:        register int cnt = DIRSIZ;
                    210: 
                    211:        do
                    212:                *to++ = *from++;
                    213:        while (--cnt);
                    214:        *to = 0;
                    215: }
                    216: 
                    217: execbrc(p, s)
                    218:        char *p, *s;
                    219: {
                    220:        char restbuf[BUFSIZ + 2];
                    221:        register char *pe, *pm, *pl;
                    222:        int brclev = 0;
                    223:        char *lm, savec, *sgpathp;
                    224: 
                    225:        for (lm = restbuf; *p != '{'; *lm++ = *p++)
                    226:                continue;
                    227:        for (pe = ++p; *pe; pe++)
                    228:        switch (*pe) {
                    229: 
                    230:        case '{':
                    231:                brclev++;
                    232:                continue;
                    233:        case '}':
                    234:                if (brclev == 0)
                    235:                        goto pend;
                    236:                brclev--;
                    237:                continue;
                    238:        case '[':
                    239:                for (pe++; *pe && *pe != ']'; pe++)
                    240:                        continue;
                    241:                if (!*pe)
                    242:                        error("Missing ]");
                    243:                continue;
                    244: 
                    245:        }
                    246: pend:
                    247:        if (brclev || !*pe)
                    248:                error("Missing }");
                    249:        for (pl = pm = p; pm <= pe; pm++)
                    250:        switch (*pm) {
                    251: 
                    252:        case '{':
                    253:                brclev++;
                    254:                continue;
                    255:        case '}':
                    256:                if (brclev) {
                    257:                        brclev--;
                    258:                        continue;
                    259:                }
                    260:                goto doit;
                    261:        case ',':
                    262:                if (brclev)
                    263:                        continue;
                    264: doit:
                    265:                savec = *pm;
                    266:                *pm = 0;
                    267:                strcpy(lm, pl);
                    268:                strcat(restbuf, pe + 1);
                    269:                *pm = savec;
                    270:                if (s == 0) {
                    271:                        sgpathp = gpathp;
                    272:                        expand(restbuf);
                    273:                        gpathp = sgpathp;
                    274:                        *gpathp = 0;
                    275:                } else if (amatch(s, restbuf))
                    276:                        return (1);
                    277:                sort();
                    278:                pl = pm + 1;
                    279:                continue;
                    280:        case '[':
                    281:                for (pm++; *pm && *pm != ']'; pm++)
                    282:                        continue;
                    283:                if (!*pm)
                    284:                        error("Missing ]");
                    285:                continue;
                    286:        }
                    287:        return (0);
                    288: }
                    289: 
                    290: match(s, p)
                    291:        char *s, *p;
                    292: {
                    293:        register int c;
                    294:        register char *sentp;
                    295:        char sglobbed = globbed;
                    296: 
                    297:        if (*s == '.' && *p != '.')
                    298:                return (0);
                    299:        sentp = entp;
                    300:        entp = s;
                    301:        c = amatch(s, p);
                    302:        entp = sentp;
                    303:        globbed = sglobbed;
                    304:        return (c);
                    305: }
                    306: 
                    307: amatch(s, p)
                    308:        register char *s, *p;
                    309: {
                    310:        register int scc;
                    311:        int ok, lc;
                    312:        char *sgpathp;
                    313:        struct stat stb;
                    314:        int c, cc;
                    315: 
                    316:        globbed = 1;
                    317:        for (;;) {
                    318:                scc = *s++ & TRIM;
                    319:                switch (c = *p++) {
                    320: 
                    321:                case '{':
                    322:                        return (execbrc(p - 1, s - 1));
                    323: 
                    324:                case '[':
                    325:                        ok = 0;
                    326:                        lc = 077777;
                    327:                        while (cc = *p++) {
                    328:                                if (cc == ']') {
                    329:                                        if (ok)
                    330:                                                break;
                    331:                                        return (0);
                    332:                                }
                    333:                                if (cc == '-') {
                    334:                                        if (lc <= scc && scc <= *p++)
                    335:                                                ok++;
                    336:                                } else
                    337:                                        if (scc == (lc = cc))
                    338:                                                ok++;
                    339:                        }
                    340:                        if (cc == 0)
                    341:                                error("Missing ]");
                    342:                        continue;
                    343: 
                    344:                case '*':
                    345:                        if (!*p)
                    346:                                return (1);
                    347:                        if (*p == '/') {
                    348:                                p++;
                    349:                                goto slash;
                    350:                        }
                    351:                        for (s--; *s; s++)
                    352:                                if (amatch(s, p))
                    353:                                        return (1);
                    354:                        return (0);
                    355: 
                    356:                case 0:
                    357:                        return (scc == 0);
                    358: 
                    359:                default:
                    360:                        if (c != scc)
                    361:                                return (0);
                    362:                        continue;
                    363: 
                    364:                case '?':
                    365:                        if (scc == 0)
                    366:                                return (0);
                    367:                        continue;
                    368: 
                    369:                case '/':
                    370:                        if (scc)
                    371:                                return (0);
                    372: slash:
                    373:                        s = entp;
                    374:                        sgpathp = gpathp;
                    375:                        while (*s)
                    376:                                addpath(*s++);
                    377:                        addpath('/');
                    378:                        if (stat(gpath, &stb) == 0 && isdir(stb))
                    379:                                if (*p == 0) {
                    380:                                        Gcat(gpath, "");
                    381:                                        globcnt++;
                    382:                                } else
                    383:                                        expand(p);
                    384:                        gpathp = sgpathp;
                    385:                        *gpathp = 0;
                    386:                        return (0);
                    387:                }
                    388:        }
                    389: }
                    390: 
                    391: Gmatch(s, p)
                    392:        register char *s, *p;
                    393: {
                    394:        register int scc;
                    395:        int ok, lc;
                    396:        int c, cc;
                    397: 
                    398:        for (;;) {
                    399:                scc = *s++ & TRIM;
                    400:                switch (c = *p++) {
                    401: 
                    402:                case '[':
                    403:                        ok = 0;
                    404:                        lc = 077777;
                    405:                        while (cc = *p++) {
                    406:                                if (cc == ']') {
                    407:                                        if (ok)
                    408:                                                break;
                    409:                                        return (0);
                    410:                                }
                    411:                                if (cc == '-') {
                    412:                                        if (lc <= scc && scc <= *p++)
                    413:                                                ok++;
                    414:                                } else
                    415:                                        if (scc == (lc = cc))
                    416:                                                ok++;
                    417:                        }
                    418:                        if (cc == 0)
                    419:                                bferr("Missing ]");
                    420:                        continue;
                    421: 
                    422:                case '*':
                    423:                        if (!*p)
                    424:                                return (1);
                    425:                        for (s--; *s; s++)
                    426:                                if (Gmatch(s, p))
                    427:                                        return (1);
                    428:                        return (0);
                    429: 
                    430:                case 0:
                    431:                        return (scc == 0);
                    432: 
                    433:                default:
                    434:                        if ((c & TRIM) != scc)
                    435:                                return (0);
                    436:                        continue;
                    437: 
                    438:                case '?':
                    439:                        if (scc == 0)
                    440:                                return (0);
                    441:                        continue;
                    442: 
                    443:                }
                    444:        }
                    445: }
                    446: 
                    447: Gcat(s1, s2)
                    448:        register char *s1, *s2;
                    449: {
                    450: 
                    451:        gnleft -= strlen(s1) + strlen(s2) + 1;
                    452:        if (gnleft <= 0 || ++gargc >= GAVSIZ)
                    453:                error("Arguments too long");
                    454:        gargv[gargc] = 0;
                    455:        gargv[gargc - 1] = strspl(s1, s2);
                    456: }
                    457: 
                    458: addpath(c)
                    459:        char c;
                    460: {
                    461: 
                    462:        if (gpathp >= lastgpathp)
                    463:                error("Pathname too long");
                    464:        *gpathp++ = c;
                    465:        *gpathp = 0;
                    466: }
                    467: 
                    468: rscan(t, f)
                    469:        register char **t;
                    470:        int (*f)();
                    471: {
                    472:        register char *p, c;
                    473: 
                    474:        while (p = *t++) {
                    475:                if (f == tglob)
                    476:                        if (*p == '~')
                    477:                                gflag |= 2;
                    478:                        else if (eq(p, "{") || eq(p, "{}"))
                    479:                                continue;
                    480:                while (c = *p++)
                    481:                        (*f)(c);
                    482:        }
                    483: }
                    484: 
                    485: scan(t, f)
                    486:        register char **t;
                    487:        int (*f)();
                    488: {
                    489:        register char *p, c;
                    490: 
                    491:        while (p = *t++)
                    492:                while (c = *p)
                    493:                        *p++ = (*f)(c);
                    494: }
                    495: 
                    496: tglob(c)
                    497:        register char c;
                    498: {
                    499: 
                    500:        if (any(c, globchars))
                    501:                gflag |= c == '{' ? 2 : 1;
                    502:        return (c);
                    503: }
                    504: 
                    505: trim(c)
                    506:        char c;
                    507: {
                    508: 
                    509:        return (c & TRIM);
                    510: }
                    511: 
                    512: char *
                    513: globone(str)
                    514:        register char *str;
                    515: {
                    516:        char *gv[2];
                    517:        register char **gvp;
                    518:        register char *cp;
                    519: 
                    520:        gv[0] = str;
                    521:        gv[1] = 0;
                    522:        gflag = 0;
                    523:        rscan(gv, tglob);
                    524:        if (gflag) {
                    525:                gvp = glob(gv);
                    526:                if (gvp == 0) {
                    527:                        setname(str);
                    528:                        bferr("No match");
                    529:                }
                    530:                cp = *gvp++;
                    531:                if (cp == 0)
                    532:                        cp = "";
                    533:                else if (*gvp) {
                    534:                        setname(str);
                    535:                        bferr("Ambiguous");
                    536:                }
                    537: /*
                    538:                if (cp == 0 || *gvp) {
                    539:                        setname(str);
                    540:                        bferr(cp ? "Ambiguous" : "No output");
                    541:                }
                    542: */
                    543:                xfree(gargv); gargv = 0;
                    544:        } else {
                    545:                scan(gv, trim);
                    546:                cp = savestr(gv[0]);
                    547:        }
                    548:        return (cp);
                    549: }
                    550: 
                    551: /*
                    552:  * Command substitute cp.  If literal, then this is
                    553:  * a substitution from a << redirection, and so we should
                    554:  * not crunch blanks and tabs, separating words only at newlines.
                    555:  */
                    556: char **
                    557: dobackp(cp, literal)
                    558:        char *cp;
                    559:        bool literal;
                    560: {
                    561:        register char *lp, *rp;
                    562:        char *ep;
                    563:        char word[BUFSIZ];
                    564:        char *apargv[GAVSIZ + 2];
                    565: 
                    566:        if (pargv) {
                    567:                abort();
                    568:                blkfree(pargv);
                    569:        }
                    570:        pargv = apargv;
                    571:        pargv[0] = NOSTR;
                    572:        pargcp = pargs = word;
                    573:        pargc = 0;
                    574:        pnleft = BUFSIZ - 4;
                    575:        for (;;) {
                    576:                for (lp = cp; *lp != '`'; lp++) {
                    577:                        if (*lp == 0) {
                    578:                                if (pargcp != pargs)
                    579:                                        pword();
                    580: #ifdef GDEBUG
                    581:                                printf("leaving dobackp\n");
                    582: #endif
                    583:                                return (pargv = copyblk(pargv));
                    584:                        }
                    585:                        psave(*lp);
                    586:                }
                    587:                lp++;
                    588:                for (rp = lp; *rp && *rp != '`'; rp++)
                    589:                        if (*rp == '\\') {
                    590:                                rp++;
                    591:                                if (!*rp)
                    592:                                        goto oops;
                    593:                        }
                    594:                if (!*rp)
                    595: oops:
                    596:                        error("Unmatched `");
                    597:                ep = savestr(lp);
                    598:                ep[rp - lp] = 0;
                    599:                backeval(ep, literal);
                    600: #ifdef GDEBUG
                    601:                printf("back from backeval\n");
                    602: #endif
                    603:                cp = rp + 1;
                    604:        }
                    605: }
                    606: 
                    607: backeval(cp, literal)
                    608:        char *cp;
                    609:        bool literal;
                    610: {
                    611:        int pvec[2], pid;
                    612:        int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
                    613:        int (*oldint)();
                    614:        char ibuf[BUFSIZ];
                    615:        register int icnt = 0, c;
                    616:        register char *ip;
                    617:        bool hadnl = 0;
                    618: 
                    619:        oldint = signal(SIGINT, SIG_IGN);
                    620:        mypipe(pvec);
                    621:        pid = fork();
                    622:        if (pid < 0)
                    623:                bferr("No more processes");
                    624:        if (pid == 0) {
                    625:                struct wordent paraml;
                    626:                struct command *t;
                    627: 
                    628:                child++;
                    629:                signal(SIGINT, oldint);
                    630:                close(pvec[0]);
                    631:                dmove(pvec[1], 1);
                    632:                dmove(SHDIAG, 2);
                    633:                initdesc();
                    634:                arginp = cp;
                    635:                while (*cp)
                    636:                        *cp++ &= TRIM;
                    637:                lex(&paraml);
                    638:                if (err)
                    639:                        error(err);
                    640:                alias(&paraml);
                    641:                t = syntax(paraml.next, &paraml);
                    642:                if (err)
                    643:                        error(err);
                    644:                if (t)
                    645:                        t->t_dflg |= FPAR;
                    646:                execute(t);
                    647:                exitstat();
                    648:        }
                    649:        cadd(pid, "``");
                    650:        xfree(cp);
                    651:        signal(SIGINT, oldint);
                    652:        close(pvec[1]);
                    653:        do {
                    654:                int cnt = 0;
                    655:                for (;;) {
                    656:                        if (icnt == 0) {
                    657:                                ip = ibuf;
                    658:                                icnt = read(pvec[0], ip, BUFSIZ);
                    659:                                if (icnt <= 0) {
                    660:                                        c = -1;
                    661:                                        break;
                    662:                                }
                    663:                        }
                    664:                        if (hadnl)
                    665:                                break;
                    666:                        --icnt;
                    667:                        c = (*ip++ & TRIM);
                    668:                        if (c == 0)
                    669:                                break;
                    670:                        if (c == '\n') {
                    671:                                /*
                    672:                                 * Continue around the loop one
                    673:                                 * more time, so that we can eat
                    674:                                 * the last newline without terminating
                    675:                                 * this word.
                    676:                                 */
                    677:                                hadnl = 1;
                    678:                                continue;
                    679:                        }
                    680:                        if (!quoted && (c == ' ' || c == '\t'))
                    681:                                break;
                    682:                        cnt++;
                    683:                        psave(c | quoted);
                    684:                }
                    685:                /*
                    686:                 * Unless at end-of-file, we will form a new word
                    687:                 * here if there were characters in the word, or in
                    688:                 * any case when we take text literally.  If
                    689:                 * we didn't make empty words here when literal was
                    690:                 * set then we would lose blank lines.
                    691:                 */
                    692:                if (c != -1 && (cnt || literal))
                    693:                        pword();
                    694:                hadnl = 0;
                    695:        } while (c >= 0);
                    696: #ifdef GDEBUG
                    697:        printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);
                    698:        printf("also c = %c <%o>\n", c, c);
                    699: #endif
                    700:        close(pvec[0]);
                    701:        pwait(pid);
                    702: }
                    703: 
                    704: psave(c)
                    705:        char c;
                    706: {
                    707: 
                    708:        if (--pnleft <= 0)
                    709:                error("Word too long");
                    710:        *pargcp++ = c;
                    711: }
                    712: 
                    713: pword()
                    714: {
                    715: 
                    716:        psave(0);
                    717:        if (pargc == GAVSIZ)
                    718:                error("Too many words from ``");
                    719:        pargv[pargc++] = savestr(pargs);
                    720:        pargv[pargc] = NOSTR;
                    721: #ifdef GDEBUG
                    722:        printf("got word %s\n", pargv[pargc-1]);
                    723: #endif
                    724:        pargcp = pargs;
                    725:        pnleft = BUFSIZ - 4;
                    726: }

unix.superglobalmegacorp.com

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