1 /* $Header: /src/pub/tcsh/sh.glob.c,v 3.48 2001/01/04 18:51:57 christos Exp $ */ 2 /* 3 * sh.glob.c: Regular expression expansion 4 */ 5 /*- 6 * Copyright (c) 1980, 1991 The Regents of the University of California. 7 * All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 */ 37 #include "sh.h" 38 39 RCSID("$Id: sh.glob.c,v 3.48 2001/01/04 18:51:57 christos Exp $") 40 41 #include "tc.h" 42 43 #include "glob.h" 44 45 static int noglob; 46 static int pargsiz, gargsiz; 47 48 /* 49 * Values for gflag 50 */ 51 #define G_NONE 0 /* No globbing needed */ 52 #define G_GLOB 1 /* string contains *?[] characters */ 53 #define G_CSH 2 /* string contains ~`{ characters */ 54 55 #define GLOBSPACE 100 /* Alloc increment */ 56 #define LONGBSIZE 10240 /* Backquote expansion buffer size */ 57 58 59 #define LBRC '{' 60 #define RBRC '}' 61 #define LBRK '[' 62 #define RBRK ']' 63 #define EOS '\0' 64 65 Char **gargv = NULL; 66 int gargc = 0; 67 Char **pargv = NULL; 68 static int pargc = 0; 69 70 /* 71 * globbing is now done in two stages. In the first pass we expand 72 * csh globbing idioms ~`{ and then we proceed doing the normal 73 * globbing if needed ?*[ 74 * 75 * Csh type globbing is handled in globexpand() and the rest is 76 * handled in glob() which is part of the 4.4BSD libc. 77 * 78 */ 79 static Char *globtilde __P((Char **, Char *)); 80 static Char *handleone __P((Char *, Char **, int)); 81 static Char **libglob __P((Char **)); 82 static Char **globexpand __P((Char **)); 83 static int globbrace __P((Char *, Char *, Char ***)); 84 static void expbrace __P((Char ***, Char ***, int)); 85 static int pmatch __P((Char *, Char *, Char **)); 86 static void pword __P((int)); 87 static void psave __P((int)); 88 static void backeval __P((Char *, bool)); 89 90 static Char * 91 globtilde(nv, s) 92 Char **nv, *s; 93 { 94 Char gbuf[BUFSIZE], *gstart, *b, *u, *e; 95 #ifdef apollo 96 int slash; 97 #endif 98 99 gstart = gbuf; 100 *gstart++ = *s++; 101 u = s; 102 for (b = gstart, e = &gbuf[BUFSIZE - 1]; 103 *s && *s != '/' && *s != ':' && b < e; 104 *b++ = *s++) 105 continue; 106 *b = EOS; 107 if (gethdir(gstart)) { 108 if (adrof(STRnonomatch)) 109 return (--u); 110 blkfree(nv); 111 if (*gstart) 112 stderror(ERR_UNKUSER, short2str(gstart)); 113 else 114 stderror(ERR_NOHOME); 115 } 116 b = &gstart[Strlen(gstart)]; 117 #ifdef apollo 118 slash = gstart[0] == '/' && gstart[1] == '\0'; 119 #endif 120 while (*s) 121 *b++ = *s++; 122 *b = EOS; 123 --u; 124 xfree((ptr_t) u); 125 #ifdef apollo 126 if (slash && gstart[1] == '/') 127 gstart++; 128 #endif 129 return (Strsave(gstart)); 130 } 131 132 Char * 133 globequal(new, old) 134 Char *new, *old; 135 { 136 int dig; 137 Char *b, *d; 138 139 /* 140 * kfk - 17 Jan 1984 - stack hack allows user to get at arbitrary dir names 141 * in stack. PWP: let =foobar pass through (for X windows) 142 */ 143 if (old[1] == '-' && (old[2] == '\0' || old[2] == '/')) { 144 /* =- */ 145 dig = -1; 146 b = &old[2]; 147 } 148 else if (Isdigit(old[1])) { 149 /* =<number> */ 150 dig = old[1] - '0'; 151 for (b = &old[2]; Isdigit(*b); b++) 152 dig = dig * 10 + (*b - '0'); 153 if (*b != '\0' && *b != '/') 154 /* =<number>foobar */ 155 return old; 156 } 157 else 158 /* =foobar */ 159 return old; 160 161 if (!getstakd(new, dig)) 162 return NULL; 163 164 /* Copy the rest of the string */ 165 for (d = &new[Strlen(new)]; 166 d < &new[BUFSIZE - 1] && (*d++ = *b++) != '\0';) 167 continue; 168 *d = '\0'; 169 170 return new; 171 } 172 173 static int 174 globbrace(s, p, bl) 175 Char *s, *p, ***bl; 176 { 177 int i, len; 178 Char *pm, *pe, *lm, *pl; 179 Char **nv, **vl; 180 Char gbuf[BUFSIZE]; 181 int size = GLOBSPACE; 182 183 nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); 184 *vl = NULL; 185 186 len = 0; 187 /* copy part up to the brace */ 188 for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) 189 continue; 190 191 /* check for balanced braces */ 192 for (i = 0, pe = ++p; *pe; pe++) 193 #ifdef DSPMBYTE 194 if (Ismbyte1(*pe) && *(pe + 1) != EOS) 195 pe ++; 196 else 197 #endif /* DSPMBYTE */ 198 if (*pe == LBRK) { 199 /* Ignore everything between [] */ 200 for (++pe; *pe != RBRK && *pe != EOS; pe++) 201 #ifdef DSPMBYTE 202 if (Ismbyte1(*pe) && *(pe + 1) != EOS) 203 pe ++; 204 else 205 #endif /* DSPMBYTE */ 206 continue; 207 if (*pe == EOS) { 208 blkfree(nv); 209 return (-RBRK); 210 } 211 } 212 else if (*pe == LBRC) 213 i++; 214 else if (*pe == RBRC) { 215 if (i == 0) 216 break; 217 i--; 218 } 219 220 if (i != 0 || *pe == '\0') { 221 blkfree(nv); 222 return (-RBRC); 223 } 224 225 for (i = 0, pl = pm = p; pm <= pe; pm++) 226 #ifdef DSPMBYTE 227 if (Ismbyte1(*pm) && pm + 1 <= pe) 228 pm ++; 229 else 230 #endif /* DSPMBYTE */ 231 switch (*pm) { 232 case LBRK: 233 for (++pm; *pm != RBRK && *pm != EOS; pm++) 234 #ifdef DSPMBYTE 235 if (Ismbyte1(*pm) && *(pm + 1) != EOS) 236 pm ++; 237 else 238 #endif /* DSPMBYTE */ 239 continue; 240 if (*pm == EOS) { 241 *vl = NULL; 242 blkfree(nv); 243 return (-RBRK); 244 } 245 break; 246 case LBRC: 247 i++; 248 break; 249 case RBRC: 250 if (i) { 251 i--; 252 break; 253 } 254 /* FALLTHROUGH */ 255 case ',': 256 if (i && *pm == ',') 257 break; 258 else { 259 Char savec = *pm; 260 261 *pm = EOS; 262 (void) Strcpy(lm, pl); 263 (void) Strcat(gbuf, pe + 1); 264 *pm = savec; 265 *vl++ = Strsave(gbuf); 266 len++; 267 pl = pm + 1; 268 if (vl == &nv[size]) { 269 size += GLOBSPACE; 270 nv = (Char **) xrealloc((ptr_t) nv, 271 (size_t) (size * sizeof(Char *))); 272 vl = &nv[size - GLOBSPACE]; 273 } 274 } 275 break; 276 default: 277 break; 278 } 279 *vl = NULL; 280 *bl = nv; 281 return (len); 282 } 283 284 285 static void 286 expbrace(nvp, elp, size) 287 Char ***nvp, ***elp; 288 int size; 289 { 290 Char **vl, **el, **nv, *s; 291 292 vl = nv = *nvp; 293 if (elp != NULL) 294 el = *elp; 295 else 296 for (el = vl; *el; el++) 297 continue; 298 299 for (s = *vl; s; s = *++vl) { 300 Char *b; 301 Char **vp, **bp; 302 303 /* leave {} untouched for find */ 304 if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) 305 continue; 306 if ((b = Strchr(s, '{')) != NULL) { 307 Char **bl; 308 int len; 309 310 #if defined (DSPMBYTE) 311 if (b != s && Ismbyte2(*b) && Ismbyte1(*(b-1))) { 312 /* The "{" is the 2nd byte of a MB character */ 313 continue; 314 } 315 #endif /* DSPMBYTE */ 316 if ((len = globbrace(s, b, &bl)) < 0) { 317 xfree((ptr_t) nv); 318 stderror(ERR_MISSING, -len); 319 } 320 xfree((ptr_t) s); 321 if (len == 1) { 322 *vl-- = *bl; 323 xfree((ptr_t) bl); 324 continue; 325 } 326 if (&el[len] >= &nv[size]) { 327 int l, e; 328 l = (int) (&el[len] - &nv[size]); 329 size += GLOBSPACE > l ? GLOBSPACE : l; 330 l = (int) (vl - nv); 331 e = (int) (el - nv); 332 nv = (Char **) xrealloc((ptr_t) nv, 333 (size_t) (size * sizeof(Char *))); 334 vl = nv + l; 335 el = nv + e; 336 } 337 /* nv vl el bl 338 * | | | | 339 * -.--..-- x-- 340 * | len 341 * vp 342 */ 343 vp = vl--; 344 *vp = *bl; 345 len--; 346 for (bp = el; bp != vp; bp--) 347 bp[len] = *bp; 348 el += len; 349 /* nv vl el bl 350 * | | | | 351 * -.-x --- -- 352 * |len 353 * vp 354 */ 355 vp++; 356 for (bp = bl + 1; *bp; *vp++ = *bp++) 357 continue; 358 xfree((ptr_t) bl); 359 } 360 361 } 362 if (elp != NULL) 363 *elp = el; 364 *nvp = nv; 365 } 366 367 static Char ** 368 globexpand(v) 369 Char **v; 370 { 371 Char *s; 372 Char **nv, **vl, **el; 373 int size = GLOBSPACE; 374 375 376 nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); 377 *vl = NULL; 378 379 /* 380 * Step 1: expand backquotes. 381 */ 382 while ((s = *v++) != '\0') { 383 if (Strchr(s, '`')) { 384 int i; 385 386 (void) dobackp(s, 0); 387 for (i = 0; i < pargc; i++) { 388 *vl++ = pargv[i]; 389 if (vl == &nv[size]) { 390 size += GLOBSPACE; 391 nv = (Char **) xrealloc((ptr_t) nv, 392 (size_t) (size * sizeof(Char *))); 393 vl = &nv[size - GLOBSPACE]; 394 } 395 } 396 xfree((ptr_t) pargv); 397 pargv = NULL; 398 } 399 else { 400 *vl++ = Strsave(s); 401 if (vl == &nv[size]) { 402 size += GLOBSPACE; 403 nv = (Char **) xrealloc((ptr_t) nv, 404 (size_t) (size * sizeof(Char *))); 405 vl = &nv[size - GLOBSPACE]; 406 } 407 } 408 } 409 *vl = NULL; 410 411 if (noglob) 412 return (nv); 413 414 /* 415 * Step 2: expand braces 416 */ 417 el = vl; 418 expbrace(&nv, &el, size); 419 420 421 /* 422 * Step 3: expand ~ = 423 */ 424 vl = nv; 425 for (s = *vl; s; s = *++vl) 426 switch (*s) { 427 Char gp[BUFSIZE], *ns; 428 case '~': 429 *vl = globtilde(nv, s); 430 break; 431 case '=': 432 if ((ns = globequal(gp, s)) == NULL) { 433 if (!adrof(STRnonomatch)) { 434 /* Error */ 435 blkfree(nv); 436 stderror(ERR_DEEP); 437 } 438 } 439 if (ns && ns != s) { 440 /* Expansion succeeded */ 441 xfree((ptr_t) s); 442 *vl = Strsave(gp); 443 } 444 break; 445 default: 446 break; 447 } 448 vl = nv; 449 450 /* 451 * Step 4: expand .. if the variable symlinks==expand is set 452 */ 453 if (symlinks == SYM_EXPAND) { 454 for (s = *vl; s; s = *++vl) { 455 *vl = dnormalize(s, 1); 456 xfree((ptr_t) s); 457 } 458 } 459 vl = nv; 460 461 return (vl); 462 } 463 464 static Char * 465 handleone(str, vl, action) 466 Char *str, **vl; 467 int action; 468 { 469 470 Char **vlp = vl; 471 int chars; 472 Char **t, *p, *strp; 473 474 switch (action) { 475 case G_ERROR: 476 setname(short2str(str)); 477 blkfree(vl); 478 stderror(ERR_NAME | ERR_AMBIG); 479 break; 480 case G_APPEND: 481 chars = 0; 482 for (t = vlp; (p = *t++) != '\0'; chars++) 483 while (*p++) 484 chars++; 485 str = (Char *)xmalloc((size_t)(chars * sizeof(Char))); 486 for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) { 487 while (*p) 488 *strp++ = *p++ & TRIM; 489 *strp++ = ' '; 490 } 491 *--strp = '\0'; 492 blkfree(vl); 493 break; 494 case G_IGNORE: 495 str = Strsave(strip(*vlp)); 496 blkfree(vl); 497 break; 498 default: 499 break; 500 } 501 return (str); 502 } 503 504 static Char ** 505 libglob(vl) 506 Char **vl; 507 { 508 int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT; 509 glob_t globv; 510 char *ptr; 511 int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; 512 513 if (!vl || !vl[0]) 514 return(vl); 515 516 globv.gl_offs = 0; 517 globv.gl_pathv = 0; 518 globv.gl_pathc = 0; 519 520 if (nonomatch) 521 gflgs |= GLOB_NOCHECK; 522 523 do { 524 ptr = short2qstr(*vl); 525 switch (glob(ptr, gflgs, 0, &globv)) { 526 case GLOB_ABEND: 527 globfree(&globv); 528 setname(ptr); 529 stderror(ERR_NAME | ERR_GLOB); 530 /* NOTREACHED */ 531 case GLOB_NOSPACE: 532 globfree(&globv); 533 stderror(ERR_NOMEM); 534 /* NOTREACHED */ 535 default: 536 break; 537 } 538 if (globv.gl_flags & GLOB_MAGCHAR) { 539 match |= (globv.gl_matchc != 0); 540 magic = 1; 541 } 542 gflgs |= GLOB_APPEND; 543 } 544 while (*++vl); 545 vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 546 NULL : blk2short(globv.gl_pathv); 547 globfree(&globv); 548 return (vl); 549 } 550 551 Char * 552 globone(str, action) 553 Char *str; 554 int action; 555 { 556 557 Char *v[2], **vl, **vo; 558 int gflg; 559 560 noglob = adrof(STRnoglob) != 0; 561 gflag = 0; 562 v[0] = str; 563 v[1] = 0; 564 tglob(v); 565 gflg = gflag; 566 if (gflg == G_NONE) 567 return (strip(Strsave(str))); 568 569 if (gflg & G_CSH) { 570 /* 571 * Expand back-quote, tilde and brace 572 */ 573 vo = globexpand(v); 574 if (noglob || (gflg & G_GLOB) == 0) { 575 if (vo[0] == NULL) { 576 xfree((ptr_t) vo); 577 return (Strsave(STRNULL)); 578 } 579 if (vo[1] != NULL) 580 return (handleone(str, vo, action)); 581 else { 582 str = strip(vo[0]); 583 xfree((ptr_t) vo); 584 return (str); 585 } 586 } 587 } 588 else if (noglob || (gflg & G_GLOB) == 0) 589 return (strip(Strsave(str))); 590 else 591 vo = v; 592 593 vl = libglob(vo); 594 if ((gflg & G_CSH) && vl != vo) 595 blkfree(vo); 596 if (vl == NULL) { 597 setname(short2str(str)); 598 stderror(ERR_NAME | ERR_NOMATCH); 599 } 600 if (vl[0] == NULL) { 601 xfree((ptr_t) vl); 602 return (Strsave(STRNULL)); 603 } 604 if (vl[1]) 605 return (handleone(str, vl, action)); 606 else { 607 str = strip(*vl); 608 xfree((ptr_t) vl); 609 return (str); 610 } 611 } 612 613 Char ** 614 globall(v) 615 Char **v; 616 { 617 Char **vl, **vo; 618 int gflg = gflag; 619 620 if (!v || !v[0]) { 621 gargv = saveblk(v); 622 gargc = blklen(gargv); 623 return (gargv); 624 } 625 626 noglob = adrof(STRnoglob) != 0; 627 628 if (gflg & G_CSH) 629 /* 630 * Expand back-quote, tilde and brace 631 */ 632 vl = vo = globexpand(v); 633 else 634 vl = vo = saveblk(v); 635 636 if (!noglob && (gflg & G_GLOB)) { 637 vl = libglob(vo); 638 if (vl != vo) 639 blkfree(vo); 640 } 641 else 642 trim(vl); 643 644 gargc = vl ? blklen(vl) : 0; 645 return (gargv = vl); 646 } 647 648 void 649 ginit() 650 { 651 gargsiz = GLOBSPACE; 652 gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz)); 653 gargv[0] = 0; 654 gargc = 0; 655 } 656 657 void 658 rscan(t, f) 659 register Char **t; 660 void (*f) __P((int)); 661 { 662 register Char *p; 663 664 while ((p = *t++) != '\0') 665 while (*p) 666 (*f) (*p++); 667 } 668 669 void 670 trim(t) 671 register Char **t; 672 { 673 register Char *p; 674 675 while ((p = *t++) != '\0') 676 while (*p) 677 *p++ &= TRIM; 678 } 679 680 void 681 tglob(t) 682 register Char **t; 683 { 684 register Char *p, *c; 685 686 while ((p = *t++) != '\0') { 687 if (*p == '~' || *p == '=') 688 gflag |= G_CSH; 689 else if (*p == '{' && 690 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) 691 continue; 692 /* 693 * The following line used to be *(c = p++), but hp broke their 694 * optimizer in 9.01, so we break the assignment into two pieces 695 * The careful reader here will note that *most* compiler workarounds 696 * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence? 697 */ 698 while ( *(c = p) != '\0') { 699 p++; 700 if (*c == '`') { 701 gflag |= G_CSH; 702 #ifdef notdef 703 /* 704 * We do want to expand echo `echo '*'`, so we don't\ 705 * use this piece of code anymore. 706 */ 707 while (*p && *p != '`') 708 if (*p++ == '\\') { 709 if (*p) /* Quoted chars */ 710 p++; 711 else 712 break; 713 } 714 if (*p) /* The matching ` */ 715 p++; 716 else 717 break; 718 #endif 719 } 720 else if (*c == '{') 721 gflag |= G_CSH; 722 else if (isglob(*c)) 723 gflag |= G_GLOB; 724 else if (symlinks == SYM_EXPAND && 725 *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') ) 726 gflag |= G_CSH; 727 } 728 } 729 } 730 731 /* 732 * Command substitute cp. If literal, then this is a substitution from a 733 * << redirection, and so we should not crunch blanks and tabs, separating 734 * words only at newlines. 735 */ 736 Char ** 737 dobackp(cp, literal) 738 Char *cp; 739 bool literal; 740 { 741 register Char *lp, *rp; 742 Char *ep, word[LONGBSIZE]; 743 744 if (pargv) { 745 #ifdef notdef 746 abort(); 747 #endif 748 blkfree(pargv); 749 } 750 pargsiz = GLOBSPACE; 751 pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz)); 752 pargv[0] = NULL; 753 pargcp = pargs = word; 754 pargc = 0; 755 pnleft = LONGBSIZE - 4; 756 for (;;) { 757 #if defined(DSPMBYTE) 758 for (lp = cp;; lp++) { 759 if (*lp == '`' && 760 (lp-1 < cp || !Ismbyte2(*lp) || !Ismbyte1(*(lp-1)))) { 761 break; 762 } 763 #else /* DSPMBYTE */ 764 for (lp = cp; *lp != '`'; lp++) { 765 #endif /* DSPMBYTE */ 766 if (*lp == 0) { 767 if (pargcp != pargs) 768 pword(LONGBSIZE); 769 return (pargv); 770 } 771 psave(*lp); 772 } 773 lp++; 774 for (rp = lp; *rp && *rp != '`'; rp++) 775 if (*rp == '\\') { 776 rp++; 777 if (!*rp) 778 goto oops; 779 } 780 if (!*rp) 781 oops: stderror(ERR_UNMATCHED, '`'); 782 ep = Strsave(lp); 783 ep[rp - lp] = 0; 784 backeval(ep, literal); 785 cp = rp + 1; 786 } 787 } 788 789 790 static void 791 backeval(cp, literal) 792 Char *cp; 793 bool literal; 794 { 795 register int icnt, c; 796 register Char *ip; 797 struct command faket; 798 bool hadnl; 799 int pvec[2], quoted; 800 Char *fakecom[2], ibuf[BUFSIZE]; 801 char tibuf[BUFSIZE]; 802 803 hadnl = 0; 804 icnt = 0; 805 quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 806 faket.t_dtyp = NODE_COMMAND; 807 faket.t_dflg = F_BACKQ; 808 faket.t_dlef = 0; 809 faket.t_drit = 0; 810 faket.t_dspr = 0; 811 faket.t_dcom = fakecom; 812 fakecom[0] = STRfakecom1; 813 fakecom[1] = 0; 814 815 /* 816 * We do the psave job to temporarily change the current job so that the 817 * following fork is considered a separate job. This is so that when 818 * backquotes are used in a builtin function that calls glob the "current 819 * job" is not corrupted. We only need one level of pushed jobs as long as 820 * we are sure to fork here. 821 */ 822 psavejob(); 823 824 /* 825 * It would be nicer if we could integrate this redirection more with the 826 * routines in sh.sem.c by doing a fake execute on a builtin function that 827 * was piped out. 828 */ 829 mypipe(pvec); 830 if (pfork(&faket, -1) == 0) { 831 struct command *t; 832 833 (void) close(pvec[0]); 834 (void) dmove(pvec[1], 1); 835 (void) dmove(SHDIAG, 2); 836 initdesc(); 837 /* 838 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, 839 * posted to comp.bugs.4bsd 12 Sep. 1989. 840 */ 841 if (pargv) /* mg, 21.dec.88 */ 842 blkfree(pargv), pargv = 0, pargsiz = 0; 843 /* mg, 21.dec.88 */ 844 arginp = cp; 845 while (*cp) 846 *cp++ &= TRIM; 847 848 /* 849 * In the child ``forget'' everything about current aliases or 850 * eval vectors. 851 */ 852 alvec = NULL; 853 evalvec = NULL; 854 alvecp = NULL; 855 evalp = NULL; 856 (void) lex(¶ml); 857 if (seterr) 858 stderror(ERR_OLD); 859 alias(¶ml); 860 t = syntax(paraml.next, ¶ml, 0); 861 if (seterr) 862 stderror(ERR_OLD); 863 if (t) 864 t->t_dflg |= F_NOFORK; 865 #ifdef SIGTSTP 866 (void) sigignore(SIGTSTP); 867 #endif 868 #ifdef SIGTTIN 869 (void) sigignore(SIGTTIN); 870 #endif 871 #ifdef SIGTTOU 872 (void) sigignore(SIGTTOU); 873 #endif 874 execute(t, -1, NULL, NULL); 875 exitstat(); 876 } 877 xfree((ptr_t) cp); 878 (void) close(pvec[1]); 879 c = 0; 880 ip = NULL; 881 do { 882 int cnt = 0; 883 884 for (;;) { 885 if (icnt == 0) { 886 int i; 887 888 ip = ibuf; 889 do 890 icnt = read(pvec[0], tibuf, BUFSIZE); 891 while (icnt == -1 && errno == EINTR); 892 if (icnt <= 0) { 893 c = -1; 894 break; 895 } 896 for (i = 0; i < icnt; i++) 897 ip[i] = (unsigned char) tibuf[i]; 898 } 899 if (hadnl) 900 break; 901 --icnt; 902 c = (*ip++ & TRIM); 903 if (c == 0) 904 break; 905 #ifdef WINNT_NATIVE 906 if (c == '\r') 907 c = ' '; 908 #endif /* WINNT_NATIVE */ 909 if (c == '\n') { 910 /* 911 * Continue around the loop one more time, so that we can eat 912 * the last newline without terminating this word. 913 */ 914 hadnl = 1; 915 continue; 916 } 917 if (!quoted && (c == ' ' || c == '\t')) 918 break; 919 cnt++; 920 psave(c | quoted); 921 } 922 /* 923 * Unless at end-of-file, we will form a new word here if there were 924 * characters in the word, or in any case when we take text literally. 925 * If we didn't make empty words here when literal was set then we 926 * would lose blank lines. 927 */ 928 if (c != -1 && (cnt || literal)) 929 pword(BUFSIZE); 930 hadnl = 0; 931 } while (c >= 0); 932 (void) close(pvec[0]); 933 pwait(); 934 prestjob(); 935 } 936 937 static void 938 psave(c) 939 int c; 940 { 941 if (--pnleft <= 0) 942 stderror(ERR_WTOOLONG); 943 *pargcp++ = (Char) c; 944 } 945 946 static void 947 pword(bufsiz) 948 int bufsiz; 949 { 950 psave(0); 951 if (pargc == pargsiz - 1) { 952 pargsiz += GLOBSPACE; 953 pargv = (Char **) xrealloc((ptr_t) pargv, 954 (size_t) (pargsiz * sizeof(Char *))); 955 } 956 pargv[pargc++] = Strsave(pargs); 957 pargv[pargc] = NULL; 958 pargcp = pargs; 959 pnleft = bufsiz - 4; 960 } 961 962 int 963 Gmatch(string, pattern) 964 Char *string, *pattern; 965 { 966 return Gnmatch(string, pattern, NULL); 967 } 968 969 int 970 Gnmatch(string, pattern, endstr) 971 Char *string, *pattern, **endstr; 972 { 973 Char **blk, **p, *tstring = string; 974 int gpol = 1, gres = 0; 975 976 if (*pattern == '^') { 977 gpol = 0; 978 pattern++; 979 } 980 981 blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *))); 982 blk[0] = Strsave(pattern); 983 blk[1] = NULL; 984 985 expbrace(&blk, NULL, GLOBSPACE); 986 987 if (endstr == NULL) 988 /* Exact matches only */ 989 for (p = blk; *p; p++) 990 gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0; 991 else { 992 /* partial matches */ 993 int minc = 0x7fffffff; 994 for (p = blk; *p; p++) 995 if (pmatch(string, *p, &tstring) != 0) { 996 int t = (int) (tstring - string); 997 gres |= 1; 998 if (minc == -1 || minc > t) 999 minc = t; 1000 } 1001 *endstr = string + minc; 1002 } 1003 1004 blkfree(blk); 1005 return(gres == gpol); 1006 } 1007 1008 /* pmatch(): 1009 * Return 2 on exact match, 1010 * Return 1 on substring match. 1011 * Return 0 on no match. 1012 * *estr will point to the end of the longest exact or substring match. 1013 */ 1014 static int 1015 pmatch(string, pattern, estr) 1016 register Char *string, *pattern, **estr; 1017 { 1018 register Char stringc, patternc; 1019 int match, negate_range; 1020 Char rangec, *oestr, *pestr; 1021 1022 for (;; ++string) { 1023 stringc = *string & TRIM; 1024 /* 1025 * apollo compiler bug: switch (patternc = *pattern++) dies 1026 */ 1027 patternc = *pattern++; 1028 switch (patternc) { 1029 case 0: 1030 *estr = string; 1031 return (stringc == 0 ? 2 : 1); 1032 case '?': 1033 if (stringc == 0) 1034 return (0); 1035 *estr = string; 1036 break; 1037 case '*': 1038 if (!*pattern) { 1039 while (*string) string++; 1040 *estr = string; 1041 return (2); 1042 } 1043 oestr = *estr; 1044 pestr = NULL; 1045 1046 do { 1047 switch(pmatch(string, pattern, estr)) { 1048 case 0: 1049 break; 1050 case 1: 1051 pestr = *estr; 1052 break; 1053 case 2: 1054 return 2; 1055 default: 1056 abort(); /* Cannot happen */ 1057 } 1058 *estr = string; 1059 } 1060 while (*string++); 1061 1062 if (pestr) { 1063 *estr = pestr; 1064 return 1; 1065 } 1066 else { 1067 *estr = oestr; 1068 return 0; 1069 } 1070 1071 case '[': 1072 match = 0; 1073 if ((negate_range = (*pattern == '^')) != 0) 1074 pattern++; 1075 while ((rangec = *pattern++) != '\0') { 1076 if (rangec == ']') 1077 break; 1078 if (match) 1079 continue; 1080 if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { 1081 match = (globcharcoll(stringc, *pattern & TRIM) <= 0 && 1082 globcharcoll(*(pattern-2) & TRIM, stringc) <= 0); 1083 pattern++; 1084 } 1085 else 1086 match = (stringc == (rangec & TRIM)); 1087 } 1088 if (rangec == 0) 1089 stderror(ERR_NAME | ERR_MISSING, ']'); 1090 if (match == negate_range) 1091 return (0); 1092 *estr = string; 1093 break; 1094 default: 1095 if ((patternc & TRIM) != stringc) 1096 return (0); 1097 *estr = string; 1098 break; 1099 } 1100 } 1101 } 1102 1103 void 1104 Gcat(s1, s2) 1105 Char *s1, *s2; 1106 { 1107 register Char *p, *q; 1108 int n; 1109 1110 for (p = s1; *p++;) 1111 continue; 1112 for (q = s2; *q++;) 1113 continue; 1114 n = (int) ((p - s1) + (q - s2) - 1); 1115 if (++gargc >= gargsiz) { 1116 gargsiz += GLOBSPACE; 1117 gargv = (Char **) xrealloc((ptr_t) gargv, 1118 (size_t) (gargsiz * sizeof(Char *))); 1119 } 1120 gargv[gargc] = 0; 1121 p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char))); 1122 for (q = s1; (*p++ = *q++) != '\0';) 1123 continue; 1124 for (p--, q = s2; (*p++ = *q++) != '\0';) 1125 continue; 1126 } 1127 1128 #ifdef FILEC 1129 int 1130 sortscmp(a, b) 1131 register Char **a, **b; 1132 { 1133 if (!a) /* check for NULL */ 1134 return (b ? 1 : 0); 1135 if (!b) 1136 return (-1); 1137 1138 if (!*a) /* check for NULL */ 1139 return (*b ? 1 : 0); 1140 if (!*b) 1141 return (-1); 1142 1143 return (int) collate(*a, *b); 1144 } 1145 1146 #endif 1147