1 static char *sccsid = "@(#)glob.c 4.3 02/12/82"; 2 3 #include "sh.h" 4 #include <ndir.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 else 74 acollect(pargv[i]); 75 if (pargv) 76 blkfree(pargv), pargv = 0; 77 #ifdef GDEBUG 78 printf("acollect done\n"); 79 #endif 80 } else if (noglob || eq(as, "{") || eq(as, "{}")) { 81 Gcat(as, ""); 82 sort(); 83 } else 84 acollect(as); 85 } 86 87 acollect(as) 88 register char *as; 89 { 90 register int ogargc = gargc; 91 92 gpathp = gpath; *gpathp = 0; globbed = 0; 93 expand(as); 94 if (gargc == ogargc) { 95 if (nonomatch) { 96 Gcat(as, ""); 97 sort(); 98 } 99 } else 100 sort(); 101 } 102 103 sort() 104 { 105 register char **p1, **p2, *c; 106 char **Gvp = &gargv[gargc]; 107 108 p1 = sortbas; 109 while (p1 < Gvp-1) { 110 p2 = p1; 111 while (++p2 < Gvp) 112 if (strcmp(*p1, *p2) > 0) 113 c = *p1, *p1 = *p2, *p2 = c; 114 p1++; 115 } 116 sortbas = Gvp; 117 } 118 119 expand(as) 120 char *as; 121 { 122 register char *cs; 123 register char *sgpathp, *oldcs; 124 struct stat stb; 125 126 sgpathp = gpathp; 127 cs = as; 128 if (*cs == '~' && gpathp == gpath) { 129 addpath('~'); 130 for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) 131 addpath(*cs++); 132 if (!*cs || *cs == '/') { 133 if (gpathp != gpath + 1) { 134 *gpathp = 0; 135 if (gethdir(gpath + 1)) 136 error("Unknown user: %s", gpath + 1); 137 strcpy(gpath, gpath + 1); 138 } else 139 strcpy(gpath, value("home")); 140 gpathp = strend(gpath); 141 } 142 } 143 while (!any(*cs, globchars)) { 144 if (*cs == 0) { 145 if (!globbed) 146 Gcat(gpath, ""); 147 else if (stat(gpath, &stb) >= 0) { 148 Gcat(gpath, ""); 149 globcnt++; 150 } 151 goto endit; 152 } 153 addpath(*cs++); 154 } 155 oldcs = cs; 156 while (cs > as && *cs != '/') 157 cs--, gpathp--; 158 if (*cs == '/') 159 cs++, gpathp++; 160 *gpathp = 0; 161 if (*oldcs == '{') { 162 execbrc(cs, NOSTR); 163 return; 164 } 165 matchdir(cs); 166 endit: 167 gpathp = sgpathp; 168 *gpathp = 0; 169 } 170 171 matchdir(pattern) 172 char *pattern; 173 { 174 struct stat stb; 175 register struct direct *dp; 176 DIR *dirp; 177 register int cnt; 178 179 dirp = opendir(gpath); 180 if (dirp == NULL) { 181 if (globbed) 182 return; 183 goto patherr2; 184 } 185 if (fstat(dirp->dd_fd, &stb) < 0) 186 goto patherr1; 187 if (!isdir(stb)) { 188 errno = ENOTDIR; 189 goto patherr1; 190 } 191 while ((dp = readdir(dirp)) != NULL) { 192 if (dp->d_ino == 0) 193 continue; 194 if (match(dp->d_name, pattern)) { 195 Gcat(gpath, dp->d_name); 196 globcnt++; 197 } 198 } 199 closedir(dirp); 200 return; 201 202 patherr1: 203 closedir(dirp); 204 patherr2: 205 Perror(gpath); 206 } 207 208 execbrc(p, s) 209 char *p, *s; 210 { 211 char restbuf[BUFSIZ + 2]; 212 register char *pe, *pm, *pl; 213 int brclev = 0; 214 char *lm, savec, *sgpathp; 215 216 for (lm = restbuf; *p != '{'; *lm++ = *p++) 217 continue; 218 for (pe = ++p; *pe; pe++) 219 switch (*pe) { 220 221 case '{': 222 brclev++; 223 continue; 224 225 case '}': 226 if (brclev == 0) 227 goto pend; 228 brclev--; 229 continue; 230 231 case '[': 232 for (pe++; *pe && *pe != ']'; pe++) 233 continue; 234 if (!*pe) 235 error("Missing ]"); 236 continue; 237 } 238 pend: 239 if (brclev || !*pe) 240 error("Missing }"); 241 for (pl = pm = p; pm <= pe; pm++) 242 switch (*pm & (QUOTE|TRIM)) { 243 244 case '{': 245 brclev++; 246 continue; 247 248 case '}': 249 if (brclev) { 250 brclev--; 251 continue; 252 } 253 goto doit; 254 255 case ','|QUOTE: 256 case ',': 257 if (brclev) 258 continue; 259 doit: 260 savec = *pm; 261 *pm = 0; 262 strcpy(lm, pl); 263 strcat(restbuf, pe + 1); 264 *pm = savec; 265 if (s == 0) { 266 sgpathp = gpathp; 267 expand(restbuf); 268 gpathp = sgpathp; 269 *gpathp = 0; 270 } else if (amatch(s, restbuf)) 271 return (1); 272 sort(); 273 pl = pm + 1; 274 continue; 275 276 case '[': 277 for (pm++; *pm && *pm != ']'; pm++) 278 continue; 279 if (!*pm) 280 error("Missing ]"); 281 continue; 282 } 283 return (0); 284 } 285 286 match(s, p) 287 char *s, *p; 288 { 289 register int c; 290 register char *sentp; 291 char sglobbed = globbed; 292 293 if (*s == '.' && *p != '.') 294 return (0); 295 sentp = entp; 296 entp = s; 297 c = amatch(s, p); 298 entp = sentp; 299 globbed = sglobbed; 300 return (c); 301 } 302 303 amatch(s, p) 304 register char *s, *p; 305 { 306 register int scc; 307 int ok, lc; 308 char *sgpathp; 309 struct stat stb; 310 int c, cc; 311 312 globbed = 1; 313 for (;;) { 314 scc = *s++ & TRIM; 315 switch (c = *p++) { 316 317 case '{': 318 return (execbrc(p - 1, s - 1)); 319 320 case '[': 321 ok = 0; 322 lc = 077777; 323 while (cc = *p++) { 324 if (cc == ']') { 325 if (ok) 326 break; 327 return (0); 328 } 329 if (cc == '-') { 330 if (lc <= scc && scc <= *p++) 331 ok++; 332 } else 333 if (scc == (lc = cc)) 334 ok++; 335 } 336 if (cc == 0) 337 error("Missing ]"); 338 continue; 339 340 case '*': 341 if (!*p) 342 return (1); 343 if (*p == '/') { 344 p++; 345 goto slash; 346 } 347 for (s--; *s; s++) 348 if (amatch(s, p)) 349 return (1); 350 return (0); 351 352 case 0: 353 return (scc == 0); 354 355 default: 356 if (c != scc) 357 return (0); 358 continue; 359 360 case '?': 361 if (scc == 0) 362 return (0); 363 continue; 364 365 case '/': 366 if (scc) 367 return (0); 368 slash: 369 s = entp; 370 sgpathp = gpathp; 371 while (*s) 372 addpath(*s++); 373 addpath('/'); 374 if (stat(gpath, &stb) == 0 && isdir(stb)) 375 if (*p == 0) { 376 Gcat(gpath, ""); 377 globcnt++; 378 } else 379 expand(p); 380 gpathp = sgpathp; 381 *gpathp = 0; 382 return (0); 383 } 384 } 385 } 386 387 Gmatch(s, p) 388 register char *s, *p; 389 { 390 register int scc; 391 int ok, lc; 392 int c, cc; 393 394 for (;;) { 395 scc = *s++ & TRIM; 396 switch (c = *p++) { 397 398 case '[': 399 ok = 0; 400 lc = 077777; 401 while (cc = *p++) { 402 if (cc == ']') { 403 if (ok) 404 break; 405 return (0); 406 } 407 if (cc == '-') { 408 if (lc <= scc && scc <= *p++) 409 ok++; 410 } else 411 if (scc == (lc = cc)) 412 ok++; 413 } 414 if (cc == 0) 415 bferr("Missing ]"); 416 continue; 417 418 case '*': 419 if (!*p) 420 return (1); 421 for (s--; *s; s++) 422 if (Gmatch(s, p)) 423 return (1); 424 return (0); 425 426 case 0: 427 return (scc == 0); 428 429 default: 430 if ((c & TRIM) != scc) 431 return (0); 432 continue; 433 434 case '?': 435 if (scc == 0) 436 return (0); 437 continue; 438 439 } 440 } 441 } 442 443 Gcat(s1, s2) 444 register char *s1, *s2; 445 { 446 447 gnleft -= strlen(s1) + strlen(s2) + 1; 448 if (gnleft <= 0 || ++gargc >= GAVSIZ) 449 error("Arguments too long"); 450 gargv[gargc] = 0; 451 gargv[gargc - 1] = strspl(s1, s2); 452 } 453 454 addpath(c) 455 char c; 456 { 457 458 if (gpathp >= lastgpathp) 459 error("Pathname too long"); 460 *gpathp++ = c; 461 *gpathp = 0; 462 } 463 464 rscan(t, f) 465 register char **t; 466 int (*f)(); 467 { 468 register char *p, c; 469 470 while (p = *t++) { 471 if (f == tglob) 472 if (*p == '~') 473 gflag |= 2; 474 else if (eq(p, "{") || eq(p, "{}")) 475 continue; 476 while (c = *p++) 477 (*f)(c); 478 } 479 } 480 481 scan(t, f) 482 register char **t; 483 int (*f)(); 484 { 485 register char *p, c; 486 487 while (p = *t++) 488 while (c = *p) 489 *p++ = (*f)(c); 490 } 491 492 tglob(c) 493 register char c; 494 { 495 496 if (any(c, globchars)) 497 gflag |= c == '{' ? 2 : 1; 498 return (c); 499 } 500 501 trim(c) 502 char c; 503 { 504 505 return (c & TRIM); 506 } 507 508 tback(c) 509 char c; 510 { 511 512 if (c == '`') 513 gflag = 1; 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 } 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 scan(gv, trim); 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 close(pvec[0]); 653 dmove(pvec[1], 1); 654 dmove(SHDIAG, 2); 655 initdesc(); 656 arginp = cp; 657 while (*cp) 658 *cp++ &= TRIM; 659 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 execute(t, -1); 669 exitstat(); 670 } 671 xfree(cp); 672 close(pvec[1]); 673 do { 674 int cnt = 0; 675 for (;;) { 676 if (icnt == 0) { 677 ip = ibuf; 678 icnt = read(pvec[0], ip, BUFSIZ); 679 if (icnt <= 0) { 680 c = -1; 681 break; 682 } 683 } 684 if (hadnl) 685 break; 686 --icnt; 687 c = (*ip++ & TRIM); 688 if (c == 0) 689 break; 690 if (c == '\n') { 691 /* 692 * Continue around the loop one 693 * more time, so that we can eat 694 * the last newline without terminating 695 * this word. 696 */ 697 hadnl = 1; 698 continue; 699 } 700 if (!quoted && (c == ' ' || c == '\t')) 701 break; 702 cnt++; 703 psave(c | quoted); 704 } 705 /* 706 * Unless at end-of-file, we will form a new word 707 * here if there were characters in the word, or in 708 * any case when we take text literally. If 709 * we didn't make empty words here when literal was 710 * set then we would lose blank lines. 711 */ 712 if (c != -1 && (cnt || literal)) 713 pword(); 714 hadnl = 0; 715 } while (c >= 0); 716 #ifdef GDEBUG 717 printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); 718 printf("also c = %c <%o>\n", c, c); 719 #endif 720 close(pvec[0]); 721 pwait(); 722 prestjob(); 723 } 724 725 psave(c) 726 char c; 727 { 728 729 if (--pnleft <= 0) 730 error("Word too long"); 731 *pargcp++ = c; 732 } 733 734 pword() 735 { 736 737 psave(0); 738 if (pargc == GAVSIZ) 739 error("Too many words from ``"); 740 pargv[pargc++] = savestr(pargs); 741 pargv[pargc] = NOSTR; 742 #ifdef GDEBUG 743 printf("got word %s\n", pargv[pargc-1]); 744 #endif 745 pargcp = pargs; 746 pnleft = BUFSIZ - 4; 747 } 748