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