Annotation of 43BSDReno/usr.bin/ftp/glob.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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