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(¶ml); 642: if (err) 643: error(err); 644: alias(¶ml); 645: t = syntax(paraml.next, ¶ml, 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: }