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

Defined functions

Gcat defined in line 451; used 8 times
Gmatch defined in line 395; used 3 times
acollect defined in line 85; used 2 times
addpath defined in line 462; used 5 times
amatch defined in line 311; used 3 times
backeval defined in line 611; used 1 times
collect defined in line 56; used 1 times
  • in line 37
copdent defined in line 209; used 2 times
dobackp defined in line 560; used 3 times
execbrc defined in line 220; used 2 times
expand defined in line 117; used 3 times
ginit defined in line 48; used 2 times
match defined in line 294; used 1 times
matchdir defined in line 169; used 1 times
psave defined in line 708; used 3 times
pword defined in line 717; used 2 times
sort defined in line 101; used 3 times
tglob defined in line 500; used 3 times
trim defined in line 509; used 2 times

Defined variables

entp defined in line 17; used 4 times
globbed defined in line 14; used 6 times
globchars defined in line 11; used 2 times
globcnt defined in line 9; used 7 times
gpath defined in line 13; used 20 times
gpathp defined in line 13; used 23 times
lastgpathp defined in line 13; used 2 times
noglob defined in line 15; used 4 times
nonomatch defined in line 16; used 3 times
sortbas defined in line 18; used 3 times
Last modified: 1981-12-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1974
Valid CSS Valid XHTML 1.0 Strict