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