# 2.11BSD#431 - /usr/src/ucb/ftp/glob.c

##### Functions

    any               X
    blkcpy            X
    blkfree           X
    blklen            X
    copyblk           X
    digit             X
    gethdir           X
    glob              X
    letter            X

##### Variables

    globchars         X
    globerr           X
    home              X

##### Macros

    GAVSIZ            X
    QUOTE             X
    TRIM              X
    eq                X
    isdir             X

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

#### Defined functions

Gcat defined in line 479; used 5 times

- in line 106, 169-171(2), 218, 408

Gmatch defined in line 419; used 1 times

- in line 458

acollect defined in line 112; used 1 times

- in line 109

addpath defined in line 495; used 5 times

- in line 152-154(2), 176, 404-405(2)

amatch defined in line 329; used 3 times

- in line 291, 323, 379

any defined in line 571; used 2 times

- in line 166, 543

blkcpy defined in line 591; used 1 times

- in line 635

blkfree defined in line 603; used 5 times

- in line 86
- in /usr/src/ucb/ftp/cmds.c line 456, 478, 1593, 1602

blklen defined in line 581; used 1 times

- in line 630

collect defined in line 101; used 1 times

- in line 84

copyblk defined in line 626; used 3 times

- in line 52, 77, 89

digit defined in line 564; used 1 times

- in line 153

execbrc defined in line 231; used 2 times

- in line 185, 345

expand defined in line 141; used 3 times

- in line 119, 288, 411

gethdir defined in line 654; used 1 times

- in line 158

ginit defined in line 92; used 1 times

- in line 83

glob defined in line 63; used 5 times

- in line 45
- in /usr/src/ucb/ftp/cmds.c line 47, 452, 1589
- in /usr/src/ucb/ftp/domacro.c line 38

letter defined in line 557; used 1 times

- in line 153

match defined in line 311; used 1 times

- in line 217

matchdir defined in line 194; used 1 times

- in line 188

rscan defined in line 508; used 1 times

- in line 73

sort defined in line 124; used 3 times

- in line 107, 121, 293

strend defined in line 638; used 2 times

- in line 50, 163

strspl defined in line 612; used 2 times

- in line 50, 491

tglob defined in line 538; used 3 times

- in line 44, 73, 516

#### Defined variables

entp defined in line 60; used 4 times

- in line 321-324(3), 401

gargc defined in line 41; used 8 times

- in line 97, 116-120(2), 128, 485-491(4)

gargv defined in line 40; used 8 times

- in line 86-89(4), 97, 128, 490-491(2)

gflag defined in line 43; used 5 times

- in line 72-74(2), 85, 518, 544

globbed defined in line 59; used 6 times

- in line 118, 168, 204, 317, 325, 339

globchars defined in line 56; used 2 times

- in line 166, 543

globcnt defined in line 54; used 5 times

- in line 83-85(2), 172, 219, 409

globerr defined in line 46; used 9 times

- in line 80, 159, 228, 486, 501
- in /usr/src/ucb/ftp/cmds.c line 453-454(2), 1590-1591(2)

gnleft defined in line 42; used 3 times

- in line 98, 485-489(2)

gpath defined in line 58; used 18 times

- in line 81-82(3), 118, 151-163(7), 169-171(3), 202, 218, 406-408(2)

gpathp defined in line 58; used 23 times

- in line 81(2), 118(2), 149-157(4), 163, 180-183(3), 190-191(2), 287-290(3), 402, 412-413(2), 500-504(3)

home defined in line 47; used 9 times

- in line 162, 654-661(5)
- in /usr/src/ucb/ftp/cmds.c line 997
- in /usr/src/ucb/ftp/main.c line 126-127(2)

lastgpathp defined in line 58; used 3 times

- in line 82, 500, 659

sccsid defined in line 19; never used
sortbas defined in line 61; used 3 times

- in line 97, 130, 138

#### Defined macros

GAVSIZ defined in line 37; used 2 times

- in line 68, 485

QUOTE defined in line 34; used 1 times

- in line 263

TRIM defined in line 35; used 4 times

- in line 263, 341, 428, 466

eq defined in line 36; used 4 times

- in line 105(2), 519(2)

isdir defined in line 38; used 2 times

- in line 210, 406

Last modified: 1990-05-19 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2515 |