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

Defined functions

Gcat defined in line 471; used 5 times
Gmatch defined in line 411; used 1 times
acollect defined in line 103; used 1 times
addpath defined in line 487; used 5 times
amatch defined in line 321; used 3 times
any defined in line 563; used 2 times
blkcpy defined in line 583; used 1 times
blkfree defined in line 595; used 5 times
blklen defined in line 573; used 1 times
collect defined in line 92; used 1 times
  • in line 75
copyblk defined in line 619; used 3 times
digit defined in line 556; used 1 times
execbrc defined in line 223; used 2 times
expand defined in line 132; used 3 times
gethdir defined in line 648; used 1 times
ginit defined in line 83; used 1 times
  • in line 74
glob defined in line 57; used 5 times
letter defined in line 549; used 1 times
match defined in line 303; used 1 times
matchdir defined in line 185; used 1 times
rscan defined in line 500; used 1 times
  • in line 67
scan defined in line 518; never used
sort defined in line 115; used 3 times
strend defined in line 632; used 2 times
strspl defined in line 605; used 2 times
tglob defined in line 530; used 3 times
trim defined in line 540; never used

Defined variables

entp defined in line 54; used 4 times
gargc defined in line 36; used 8 times
gargv defined in line 35; used 8 times
gflag defined in line 38; used 5 times
globbed defined in line 53; used 6 times
globchars defined in line 50; used 2 times
globcnt defined in line 48; used 5 times
globerr defined in line 41; used 11 times
gnleft defined in line 37; used 3 times
gpath defined in line 52; used 18 times
gpathp defined in line 52; used 23 times
home defined in line 42; used 8 times
lastgpathp defined in line 52; used 2 times
sccsid defined in line 14; never used
sortbas defined in line 55; used 3 times

Defined macros

GAVSIZ defined in line 32; used 2 times
QUOTE defined in line 29; used 1 times
TRIM defined in line 30; used 5 times
eq defined in line 31; used 4 times
isdir defined in line 33; used 2 times
Last modified: 1986-03-13
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1725
Valid CSS Valid XHTML 1.0 Strict