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