1: static  char *sccsid = "@(#)sh.glob.c 4.2 3/11/81";
   2: #include "sh.h"
   3: 
   4: /*
   5:  * C Shell
   6:  */
   7: 
   8: int globcnt;
   9: 
  10: char    *globchars =    "`{[*?";
  11: 
  12: char    *gpath, *gpathp, *lastgpathp;
  13: int globbed;
  14: bool    noglob;
  15: bool    nonomatch;
  16: char    *entp;
  17: char    **sortbas;
  18: 
  19: char **
  20: glob(v)
  21:     register char **v;
  22: {
  23:     char agpath[BUFSIZ];
  24:     char *agargv[GAVSIZ];
  25: 
  26:     gpath = agpath; gpathp = gpath; *gpathp = 0;
  27:     lastgpathp = &gpath[sizeof agpath - 2];
  28:     ginit(agargv); globcnt = 0;
  29: #ifdef GDEBUG
  30:     printf("glob entered: "); blkpr(v); printf("\n");
  31: #endif
  32:     noglob = adrof("noglob") != 0;
  33:     nonomatch = adrof("nonomatch") != 0;
  34:     globcnt = noglob | nonomatch;
  35:     while (*v)
  36:         collect(*v++);
  37: #ifdef GDEBUG
  38:     printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");
  39: #endif
  40:     if (globcnt == 0 && (gflag&1)) {
  41:         blkfree(gargv), gargv = 0;
  42:         return (0);
  43:     } else
  44:         return (gargv = copyblk(gargv));
  45: }
  46: 
  47: ginit(agargv)
  48:     char **agargv;
  49: {
  50: 
  51:     agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
  52:     gnleft = NCARGS - 4;
  53: }
  54: 
  55: collect(as)
  56:     register char *as;
  57: {
  58:     register int i;
  59: 
  60:     if (any('`', as)) {
  61: #ifdef GDEBUG
  62:         printf("doing backp of %s\n", as);
  63: #endif
  64:         dobackp(as, 0);
  65: #ifdef GDEBUG
  66:         printf("backp done, acollect'ing\n");
  67: #endif
  68:         for (i = 0; i < pargc; i++)
  69:             if (noglob)
  70:                 Gcat(pargv[i], "");
  71:             else
  72:                 acollect(pargv[i]);
  73:         if (pargv)
  74:             blkfree(pargv), pargv = 0;
  75: #ifdef GDEBUG
  76:         printf("acollect done\n");
  77: #endif
  78:     } else if (noglob || eq(as, "{") || eq(as, "{}")) {
  79:         Gcat(as, "");
  80:         sort();
  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, NOSTR);
 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: 
 237:     case '}':
 238:         if (brclev == 0)
 239:             goto pend;
 240:         brclev--;
 241:         continue;
 242: 
 243:     case '[':
 244:         for (pe++; *pe && *pe != ']'; pe++)
 245:             continue;
 246:         if (!*pe)
 247:             error("Missing ]");
 248:         continue;
 249:     }
 250: pend:
 251:     if (brclev || !*pe)
 252:         error("Missing }");
 253:     for (pl = pm = p; pm <= pe; pm++)
 254:     switch (*pm & (QUOTE|TRIM)) {
 255: 
 256:     case '{':
 257:         brclev++;
 258:         continue;
 259: 
 260:     case '}':
 261:         if (brclev) {
 262:             brclev--;
 263:             continue;
 264:         }
 265:         goto doit;
 266: 
 267:     case ','|QUOTE:
 268:     case ',':
 269:         if (brclev)
 270:             continue;
 271: doit:
 272:         savec = *pm;
 273:         *pm = 0;
 274:         strcpy(lm, pl);
 275:         strcat(restbuf, pe + 1);
 276:         *pm = savec;
 277:         if (s == 0) {
 278:             sgpathp = gpathp;
 279:             expand(restbuf);
 280:             gpathp = sgpathp;
 281:             *gpathp = 0;
 282:         } else if (amatch(s, restbuf))
 283:             return (1);
 284:         sort();
 285:         pl = pm + 1;
 286:         continue;
 287: 
 288:     case '[':
 289:         for (pm++; *pm && *pm != ']'; pm++)
 290:             continue;
 291:         if (!*pm)
 292:             error("Missing ]");
 293:         continue;
 294:     }
 295:     return (0);
 296: }
 297: 
 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: amatch(s, p)
 316:     register char *s, *p;
 317: {
 318:     register int scc;
 319:     int ok, lc;
 320:     char *sgpathp;
 321:     struct stat stb;
 322:     int c, cc;
 323: 
 324:     globbed = 1;
 325:     for (;;) {
 326:         scc = *s++ & TRIM;
 327:         switch (c = *p++) {
 328: 
 329:         case '{':
 330:             return (execbrc(p - 1, s - 1));
 331: 
 332:         case '[':
 333:             ok = 0;
 334:             lc = 077777;
 335:             while (cc = *p++) {
 336:                 if (cc == ']') {
 337:                     if (ok)
 338:                         break;
 339:                     return (0);
 340:                 }
 341:                 if (cc == '-') {
 342:                     if (lc <= scc && scc <= *p++)
 343:                         ok++;
 344:                 } else
 345:                     if (scc == (lc = cc))
 346:                         ok++;
 347:             }
 348:             if (cc == 0)
 349:                 error("Missing ]");
 350:             continue;
 351: 
 352:         case '*':
 353:             if (!*p)
 354:                 return (1);
 355:             if (*p == '/') {
 356:                 p++;
 357:                 goto slash;
 358:             }
 359:             for (s--; *s; s++)
 360:                 if (amatch(s, p))
 361:                     return (1);
 362:             return (0);
 363: 
 364:         case 0:
 365:             return (scc == 0);
 366: 
 367:         default:
 368:             if (c != scc)
 369:                 return (0);
 370:             continue;
 371: 
 372:         case '?':
 373:             if (scc == 0)
 374:                 return (0);
 375:             continue;
 376: 
 377:         case '/':
 378:             if (scc)
 379:                 return (0);
 380: slash:
 381:             s = entp;
 382:             sgpathp = gpathp;
 383:             while (*s)
 384:                 addpath(*s++);
 385:             addpath('/');
 386:             if (stat(gpath, &stb) == 0 && isdir(stb))
 387:                 if (*p == 0) {
 388:                     Gcat(gpath, "");
 389:                     globcnt++;
 390:                 } else
 391:                     expand(p);
 392:             gpathp = sgpathp;
 393:             *gpathp = 0;
 394:             return (0);
 395:         }
 396:     }
 397: }
 398: 
 399: Gmatch(s, p)
 400:     register char *s, *p;
 401: {
 402:     register int scc;
 403:     int ok, lc;
 404:     int c, cc;
 405: 
 406:     for (;;) {
 407:         scc = *s++ & TRIM;
 408:         switch (c = *p++) {
 409: 
 410:         case '[':
 411:             ok = 0;
 412:             lc = 077777;
 413:             while (cc = *p++) {
 414:                 if (cc == ']') {
 415:                     if (ok)
 416:                         break;
 417:                     return (0);
 418:                 }
 419:                 if (cc == '-') {
 420:                     if (lc <= scc && scc <= *p++)
 421:                         ok++;
 422:                 } else
 423:                     if (scc == (lc = cc))
 424:                         ok++;
 425:             }
 426:             if (cc == 0)
 427:                 bferr("Missing ]");
 428:             continue;
 429: 
 430:         case '*':
 431:             if (!*p)
 432:                 return (1);
 433:             for (s--; *s; s++)
 434:                 if (Gmatch(s, p))
 435:                     return (1);
 436:             return (0);
 437: 
 438:         case 0:
 439:             return (scc == 0);
 440: 
 441:         default:
 442:             if ((c & TRIM) != scc)
 443:                 return (0);
 444:             continue;
 445: 
 446:         case '?':
 447:             if (scc == 0)
 448:                 return (0);
 449:             continue;
 450: 
 451:         }
 452:     }
 453: }
 454: 
 455: Gcat(s1, s2)
 456:     register char *s1, *s2;
 457: {
 458: 
 459:     gnleft -= strlen(s1) + strlen(s2) + 1;
 460:     if (gnleft <= 0 || ++gargc >= GAVSIZ)
 461:         error("Arguments too long");
 462:     gargv[gargc] = 0;
 463:     gargv[gargc - 1] = strspl(s1, s2);
 464: }
 465: 
 466: addpath(c)
 467:     char c;
 468: {
 469: 
 470:     if (gpathp >= lastgpathp)
 471:         error("Pathname too long");
 472:     *gpathp++ = c;
 473:     *gpathp = 0;
 474: }
 475: 
 476: rscan(t, f)
 477:     register char **t;
 478:     int (*f)();
 479: {
 480:     register char *p, c;
 481: 
 482:     while (p = *t++) {
 483:         if (f == tglob)
 484:             if (*p == '~')
 485:                 gflag |= 2;
 486:             else if (eq(p, "{") || eq(p, "{}"))
 487:                 continue;
 488:         while (c = *p++)
 489:             (*f)(c);
 490:     }
 491: }
 492: 
 493: scan(t, f)
 494:     register char **t;
 495:     int (*f)();
 496: {
 497:     register char *p, c;
 498: 
 499:     while (p = *t++)
 500:         while (c = *p)
 501:             *p++ = (*f)(c);
 502: }
 503: 
 504: tglob(c)
 505:     register char c;
 506: {
 507: 
 508:     if (any(c, globchars))
 509:         gflag |= c == '{' ? 2 : 1;
 510:     return (c);
 511: }
 512: 
 513: trim(c)
 514:     char c;
 515: {
 516: 
 517:     return (c & TRIM);
 518: }
 519: 
 520: tback(c)
 521:     char c;
 522: {
 523: 
 524:     if (c == '`')
 525:         gflag = 1;
 526: }
 527: 
 528: char *
 529: globone(str)
 530:     register char *str;
 531: {
 532:     char *gv[2];
 533:     register char **gvp;
 534:     register char *cp;
 535: 
 536:     gv[0] = str;
 537:     gv[1] = 0;
 538:     gflag = 0;
 539:     rscan(gv, tglob);
 540:     if (gflag) {
 541:         gvp = glob(gv);
 542:         if (gvp == 0) {
 543:             setname(str);
 544:             bferr("No match");
 545:         }
 546:         cp = *gvp++;
 547:         if (cp == 0)
 548:             cp = "";
 549:         else if (*gvp) {
 550:             setname(str);
 551:             bferr("Ambiguous");
 552:         } else
 553:             cp = strip(cp);
 554: /*
 555: 		if (cp == 0 || *gvp) {
 556: 			setname(str);
 557: 			bferr(cp ? "Ambiguous" : "No output");
 558: 		}
 559: */
 560:         xfree((char *)gargv); gargv = 0;
 561:     } else {
 562:         scan(gv, trim);
 563:         cp = savestr(gv[0]);
 564:     }
 565:     return (cp);
 566: }
 567: 
 568: /*
 569:  * Command substitute cp.  If literal, then this is
 570:  * a substitution from a << redirection, and so we should
 571:  * not crunch blanks and tabs, separating words only at newlines.
 572:  */
 573: char **
 574: dobackp(cp, literal)
 575:     char *cp;
 576:     bool literal;
 577: {
 578:     register char *lp, *rp;
 579:     char *ep;
 580:     char word[BUFSIZ];
 581:     char *apargv[GAVSIZ + 2];
 582: 
 583:     if (pargv) {
 584:         abort();
 585:         blkfree(pargv);
 586:     }
 587:     pargv = apargv;
 588:     pargv[0] = NOSTR;
 589:     pargcp = pargs = word;
 590:     pargc = 0;
 591:     pnleft = BUFSIZ - 4;
 592:     for (;;) {
 593:         for (lp = cp; *lp != '`'; lp++) {
 594:             if (*lp == 0) {
 595:                 if (pargcp != pargs)
 596:                     pword();
 597: #ifdef GDEBUG
 598:                 printf("leaving dobackp\n");
 599: #endif
 600:                 return (pargv = copyblk(pargv));
 601:             }
 602:             psave(*lp);
 603:         }
 604:         lp++;
 605:         for (rp = lp; *rp && *rp != '`'; rp++)
 606:             if (*rp == '\\') {
 607:                 rp++;
 608:                 if (!*rp)
 609:                     goto oops;
 610:             }
 611:         if (!*rp)
 612: oops:
 613:             error("Unmatched `");
 614:         ep = savestr(lp);
 615:         ep[rp - lp] = 0;
 616:         backeval(ep, literal);
 617: #ifdef GDEBUG
 618:         printf("back from backeval\n");
 619: #endif
 620:         cp = rp + 1;
 621:     }
 622: }
 623: 
 624: backeval(cp, literal)
 625:     char *cp;
 626:     bool literal;
 627: {
 628:     int pvec[2];
 629:     int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
 630:     char ibuf[BUFSIZ];
 631:     register int icnt = 0, c;
 632:     register char *ip;
 633:     bool hadnl = 0;
 634:     char *fakecom[2];
 635:     struct command faket;
 636: 
 637:     faket.t_dtyp = TCOM;
 638:     faket.t_dflg = 0;
 639:     faket.t_dlef = 0;
 640:     faket.t_drit = 0;
 641:     faket.t_dspr = 0;
 642:     faket.t_dcom = fakecom;
 643:     fakecom[0] = "` ... `";
 644:     fakecom[1] = 0;
 645:     /*
 646: 	 * We do the psave job to temporarily change the current job
 647: 	 * so that the following fork is considered a separate job.
 648: 	 * This is so that when backquotes are used in a
 649: 	 * builtin function that calls glob the "current job" is not corrupted.
 650: 	 * We only need one level of pushed jobs as long as we are sure to
 651: 	 * fork here.
 652: 	 */
 653:     psavejob();
 654:     /*
 655: 	 * It would be nicer if we could integrate this redirection more
 656: 	 * with the routines in sh.sem.c by doing a fake execute on a builtin
 657: 	 * function that was piped out.
 658: 	 */
 659:     mypipe(pvec);
 660:     if (pfork(&faket, -1) == 0) {
 661:         struct wordent paraml;
 662:         struct command *t;
 663: 
 664:         close(pvec[0]);
 665:         dmove(pvec[1], 1);
 666:         dmove(SHDIAG, 2);
 667:         initdesc();
 668:         arginp = cp;
 669:         while (*cp)
 670:             *cp++ &= TRIM;
 671:         lex(&paraml);
 672:         if (err)
 673:             error(err);
 674:         alias(&paraml);
 675:         t = syntax(paraml.next, &paraml, 0);
 676:         if (err)
 677:             error(err);
 678:         if (t)
 679:             t->t_dflg |= FPAR;
 680:         execute(t, -1);
 681:         exitstat();
 682:     }
 683:     xfree(cp);
 684:     close(pvec[1]);
 685:     do {
 686:         int cnt = 0;
 687:         for (;;) {
 688:             if (icnt == 0) {
 689:                 ip = ibuf;
 690:                 icnt = read(pvec[0], ip, BUFSIZ);
 691:                 if (icnt <= 0) {
 692:                     c = -1;
 693:                     break;
 694:                 }
 695:             }
 696:             if (hadnl)
 697:                 break;
 698:             --icnt;
 699:             c = (*ip++ & TRIM);
 700:             if (c == 0)
 701:                 break;
 702:             if (c == '\n') {
 703:                 /*
 704: 				 * Continue around the loop one
 705: 				 * more time, so that we can eat
 706: 				 * the last newline without terminating
 707: 				 * this word.
 708: 				 */
 709:                 hadnl = 1;
 710:                 continue;
 711:             }
 712:             if (!quoted && (c == ' ' || c == '\t'))
 713:                 break;
 714:             cnt++;
 715:             psave(c | quoted);
 716:         }
 717:         /*
 718: 		 * Unless at end-of-file, we will form a new word
 719: 		 * here if there were characters in the word, or in
 720: 		 * any case when we take text literally.  If
 721: 		 * we didn't make empty words here when literal was
 722: 		 * set then we would lose blank lines.
 723: 		 */
 724:         if (c != -1 && (cnt || literal))
 725:             pword();
 726:         hadnl = 0;
 727:     } while (c >= 0);
 728: #ifdef GDEBUG
 729:     printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);
 730:     printf("also c = %c <%o>\n", c, c);
 731: #endif
 732:     close(pvec[0]);
 733:     pwait();
 734:     prestjob();
 735: }
 736: 
 737: psave(c)
 738:     char c;
 739: {
 740: 
 741:     if (--pnleft <= 0)
 742:         error("Word too long");
 743:     *pargcp++ = c;
 744: }
 745: 
 746: pword()
 747: {
 748: 
 749:     psave(0);
 750:     if (pargc == GAVSIZ)
 751:         error("Too many words from ``");
 752:     pargv[pargc++] = savestr(pargs);
 753:     pargv[pargc] = NOSTR;
 754: #ifdef GDEBUG
 755:     printf("got word %s\n", pargv[pargc-1]);
 756: #endif
 757:     pargcp = pargs;
 758:     pnleft = BUFSIZ - 4;
 759: }

Defined functions

Gcat defined in line 455; used 8 times
Gmatch defined in line 399; used 5 times
acollect defined in line 85; used 2 times
addpath defined in line 466; used 5 times
amatch defined in line 315; used 3 times
backeval defined in line 624; used 1 times
collect defined in line 55; used 1 times
  • in line 36
copdent defined in line 209; used 2 times
dobackp defined in line 573; used 3 times
execbrc defined in line 220; used 2 times
expand defined in line 117; used 3 times
ginit defined in line 47; used 2 times
glob defined in line 19; used 7 times
match defined in line 298; used 1 times
matchdir defined in line 169; used 1 times
psave defined in line 737; used 3 times
pword defined in line 746; used 2 times
sort defined in line 101; used 4 times
tback defined in line 520; never used
tglob defined in line 504; used 3 times
trim defined in line 513; used 2 times

Defined variables

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