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