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 #ifndef lint 8 static char *sccsid = "@(#)glob.c 5.5 (Berkeley) 12/22/87"; 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 (!isdir(stb)) { 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 ',': 261 if (brclev) 262 continue; 263 doit: 264 savec = *pm; 265 *pm = 0; 266 (void) strcpy(lm, pl); 267 (void) strcat(restbuf, pe + 1); 268 *pm = savec; 269 if (s == 0) { 270 sgpathp = gpathp; 271 expand(restbuf); 272 gpathp = sgpathp; 273 *gpathp = 0; 274 } else if (amatch(s, restbuf)) 275 return (1); 276 sort(); 277 pl = pm + 1; 278 continue; 279 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 & TRIM) != 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 char *s1, *s2; 449 { 450 register char *p, *q; 451 int n; 452 453 for (p = s1; *p++;) 454 ; 455 for (q = s2; *q++;) 456 ; 457 gnleft -= (n = (p - s1) + (q - s2) - 1); 458 if (gnleft <= 0 || ++gargc >= GAVSIZ) 459 error("Arguments too long"); 460 gargv[gargc] = 0; 461 p = gargv[gargc - 1] = xalloc((unsigned)n); 462 for (q = s1; *p++ = *q++;) 463 ; 464 for (p--, q = s2; *p++ = *q++;) 465 ; 466 } 467 468 addpath(c) 469 char c; 470 { 471 472 if (gpathp >= lastgpathp) 473 error("Pathname too long"); 474 *gpathp++ = c & TRIM; 475 *gpathp = 0; 476 } 477 478 rscan(t, f) 479 register char **t; 480 int (*f)(); 481 { 482 register char *p; 483 484 while (p = *t++) 485 while (*p) 486 (*f)(*p++); 487 } 488 489 trim(t) 490 register char **t; 491 { 492 register char *p; 493 494 while (p = *t++) 495 while (*p) 496 *p++ &= TRIM; 497 } 498 499 tglob(t) 500 register char **t; 501 { 502 register char *p, c; 503 504 while (p = *t++) { 505 if (*p == '~') 506 gflag |= 2; 507 else if (*p == '{' && (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) 508 continue; 509 while (c = *p++) 510 if (isglob(c)) 511 gflag |= c == '{' ? 2 : 1; 512 } 513 } 514 515 char * 516 globone(str) 517 register char *str; 518 { 519 char *gv[2]; 520 register char **gvp; 521 register char *cp; 522 523 gv[0] = str; 524 gv[1] = 0; 525 gflag = 0; 526 tglob(gv); 527 if (gflag) { 528 gvp = glob(gv); 529 if (gvp == 0) { 530 setname(str); 531 bferr("No match"); 532 } 533 cp = *gvp++; 534 if (cp == 0) 535 cp = ""; 536 else if (*gvp) { 537 setname(str); 538 bferr("Ambiguous"); 539 } else 540 cp = strip(cp); 541 /* 542 if (cp == 0 || *gvp) { 543 setname(str); 544 bferr(cp ? "Ambiguous" : "No output"); 545 } 546 */ 547 xfree((char *)gargv); gargv = 0; 548 } else { 549 trim(gv); 550 cp = savestr(gv[0]); 551 } 552 return (cp); 553 } 554 555 /* 556 * Command substitute cp. If literal, then this is 557 * a substitution from a << redirection, and so we should 558 * not crunch blanks and tabs, separating words only at newlines. 559 */ 560 char ** 561 dobackp(cp, literal) 562 char *cp; 563 bool literal; 564 { 565 register char *lp, *rp; 566 char *ep; 567 char word[BUFSIZ]; 568 char *apargv[GAVSIZ + 2]; 569 570 if (pargv) { 571 abort(); 572 blkfree(pargv); 573 } 574 pargv = apargv; 575 pargv[0] = NOSTR; 576 pargcp = pargs = word; 577 pargc = 0; 578 pnleft = BUFSIZ - 4; 579 for (;;) { 580 for (lp = cp; *lp != '`'; lp++) { 581 if (*lp == 0) { 582 if (pargcp != pargs) 583 pword(); 584 #ifdef GDEBUG 585 printf("leaving dobackp\n"); 586 #endif 587 return (pargv = copyblk(pargv)); 588 } 589 psave(*lp); 590 } 591 lp++; 592 for (rp = lp; *rp && *rp != '`'; rp++) 593 if (*rp == '\\') { 594 rp++; 595 if (!*rp) 596 goto oops; 597 } 598 if (!*rp) 599 oops: 600 error("Unmatched `"); 601 ep = savestr(lp); 602 ep[rp - lp] = 0; 603 backeval(ep, literal); 604 #ifdef GDEBUG 605 printf("back from backeval\n"); 606 #endif 607 cp = rp + 1; 608 } 609 } 610 611 backeval(cp, literal) 612 char *cp; 613 bool literal; 614 { 615 int pvec[2]; 616 int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 617 char ibuf[BUFSIZ]; 618 register int icnt = 0, c; 619 register char *ip; 620 bool hadnl = 0; 621 char *fakecom[2]; 622 struct command faket; 623 624 faket.t_dtyp = TCOM; 625 faket.t_dflg = 0; 626 faket.t_dlef = 0; 627 faket.t_drit = 0; 628 faket.t_dspr = 0; 629 faket.t_dcom = fakecom; 630 fakecom[0] = "` ... `"; 631 fakecom[1] = 0; 632 /* 633 * We do the psave job to temporarily change the current job 634 * so that the following fork is considered a separate job. 635 * This is so that when backquotes are used in a 636 * builtin function that calls glob the "current job" is not corrupted. 637 * We only need one level of pushed jobs as long as we are sure to 638 * fork here. 639 */ 640 psavejob(); 641 /* 642 * It would be nicer if we could integrate this redirection more 643 * with the routines in sh.sem.c by doing a fake execute on a builtin 644 * function that was piped out. 645 */ 646 mypipe(pvec); 647 if (pfork(&faket, -1) == 0) { 648 struct wordent paraml; 649 struct command *t; 650 651 (void) close(pvec[0]); 652 (void) dmove(pvec[1], 1); 653 (void) dmove(SHDIAG, 2); 654 initdesc(); 655 arginp = cp; 656 while (*cp) 657 *cp++ &= TRIM; 658 (void) lex(¶ml); 659 if (err) 660 error(err); 661 alias(¶ml); 662 t = syntax(paraml.next, ¶ml, 0); 663 if (err) 664 error(err); 665 if (t) 666 t->t_dflg |= FPAR; 667 (void) signal(SIGTSTP, SIG_IGN); 668 (void) signal(SIGTTIN, SIG_IGN); 669 (void) signal(SIGTTOU, SIG_IGN); 670 execute(t, -1); 671 exitstat(); 672 } 673 xfree(cp); 674 (void) close(pvec[1]); 675 do { 676 int cnt = 0; 677 for (;;) { 678 if (icnt == 0) { 679 ip = ibuf; 680 icnt = read(pvec[0], ip, BUFSIZ); 681 if (icnt <= 0) { 682 c = -1; 683 break; 684 } 685 } 686 if (hadnl) 687 break; 688 --icnt; 689 c = (*ip++ & TRIM); 690 if (c == 0) 691 break; 692 if (c == '\n') { 693 /* 694 * Continue around the loop one 695 * more time, so that we can eat 696 * the last newline without terminating 697 * this word. 698 */ 699 hadnl = 1; 700 continue; 701 } 702 if (!quoted && (c == ' ' || c == '\t')) 703 break; 704 cnt++; 705 psave(c | quoted); 706 } 707 /* 708 * Unless at end-of-file, we will form a new word 709 * here if there were characters in the word, or in 710 * any case when we take text literally. If 711 * we didn't make empty words here when literal was 712 * set then we would lose blank lines. 713 */ 714 if (c != -1 && (cnt || literal)) 715 pword(); 716 hadnl = 0; 717 } while (c >= 0); 718 #ifdef GDEBUG 719 printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]); 720 printf("also c = %c <%o>\n", c, c); 721 #endif 722 (void) close(pvec[0]); 723 pwait(); 724 prestjob(); 725 } 726 727 psave(c) 728 char c; 729 { 730 731 if (--pnleft <= 0) 732 error("Word too long"); 733 *pargcp++ = c; 734 } 735 736 pword() 737 { 738 739 psave(0); 740 if (pargc == GAVSIZ) 741 error("Too many words from ``"); 742 pargv[pargc++] = savestr(pargs); 743 pargv[pargc] = NOSTR; 744 #ifdef GDEBUG 745 printf("got word %s\n", pargv[pargc-1]); 746 #endif 747 pargcp = pargs; 748 pnleft = BUFSIZ - 4; 749 } 750