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

Defined functions

Gcat defined in line 465; used 5 times
Gmatch defined in line 405; used 1 times
acollect defined in line 98; used 1 times
  • in line 95
addpath defined in line 481; used 5 times
amatch defined in line 315; used 3 times
any defined in line 557; used 2 times
blkcpy defined in line 577; used 1 times
blkfree defined in line 589; used 5 times
blklen defined in line 567; used 1 times
collect defined in line 87; used 1 times
  • in line 70
copyblk defined in line 613; used 3 times
digit defined in line 550; used 1 times
execbrc defined in line 217; used 2 times
expand defined in line 127; used 3 times
gethdir defined in line 641; used 1 times
ginit defined in line 78; used 1 times
  • in line 69
glob defined in line 52; used 5 times
letter defined in line 543; used 1 times
match defined in line 297; used 1 times
matchdir defined in line 180; used 1 times
rscan defined in line 494; used 1 times
  • in line 62
sort defined in line 110; used 3 times
strend defined in line 625; used 2 times
strspl defined in line 599; used 2 times
tglob defined in line 524; used 3 times

Defined variables

entp defined in line 49; used 4 times
gargc defined in line 30; used 8 times
gargv defined in line 29; used 8 times
gflag defined in line 32; used 5 times
globbed defined in line 48; used 6 times
globchars defined in line 45; used 2 times
globcnt defined in line 43; used 5 times
globerr defined in line 35; used 9 times
gnleft defined in line 31; used 3 times
gpath defined in line 47; used 18 times
gpathp defined in line 47; used 23 times
home defined in line 36; used 8 times
lastgpathp defined in line 47; used 2 times
sccsid defined in line 8; never used
sortbas defined in line 50; used 3 times

Defined macros

GAVSIZ defined in line 26; used 2 times
QUOTE defined in line 23; used 1 times
TRIM defined in line 24; used 4 times
eq defined in line 25; used 4 times
isdir defined in line 27; used 2 times
Last modified: 1986-03-07
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 2203
Valid CSS Valid XHTML 1.0 Strict