sh.glob.c revision 59243
1/* $Header: /src/pub/tcsh/sh.glob.c,v 3.43 1998/10/25 15:10:14 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 39RCSID("$Id: sh.glob.c,v 3.43 1998/10/25 15:10:14 christos Exp $") 40 41#include "tc.h" 42 43#include "glob.h" 44 45static int noglob; 46static 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 65Char **gargv = NULL; 66int gargc = 0; 67Char **pargv = NULL; 68static 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 */ 79static Char *globtilde __P((Char **, Char *)); 80static Char *handleone __P((Char *, Char **, int)); 81static Char **libglob __P((Char **)); 82static Char **globexpand __P((Char **)); 83static int globbrace __P((Char *, Char *, Char ***)); 84static void expbrace __P((Char ***, Char ***, int)); 85static int pmatch __P((Char *, Char *, Char **)); 86static void pword __P((int)); 87static void psave __P((int)); 88static void backeval __P((Char *, bool)); 89 90static Char * 91globtilde(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 132Char * 133globequal(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 173static int 174globbrace(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 if (*pe == LBRK) { 194 /* Ignore everything between [] */ 195 for (++pe; *pe != RBRK && *pe != EOS; pe++) 196 continue; 197 if (*pe == EOS) { 198 blkfree(nv); 199 return (-RBRK); 200 } 201 } 202 else if (*pe == LBRC) 203 i++; 204 else if (*pe == RBRC) { 205 if (i == 0) 206 break; 207 i--; 208 } 209 210 if (i != 0 || *pe == '\0') { 211 blkfree(nv); 212 return (-RBRC); 213 } 214 215 for (i = 0, pl = pm = p; pm <= pe; pm++) 216 switch (*pm) { 217 case LBRK: 218 for (++pm; *pm != RBRK && *pm != EOS; pm++) 219 continue; 220 if (*pm == EOS) { 221 *vl = NULL; 222 blkfree(nv); 223 return (-RBRK); 224 } 225 break; 226 case LBRC: 227 i++; 228 break; 229 case RBRC: 230 if (i) { 231 i--; 232 break; 233 } 234 /* FALLTHROUGH */ 235 case ',': 236 if (i && *pm == ',') 237 break; 238 else { 239 Char savec = *pm; 240 241 *pm = EOS; 242 (void) Strcpy(lm, pl); 243 (void) Strcat(gbuf, pe + 1); 244 *pm = savec; 245 *vl++ = Strsave(gbuf); 246 len++; 247 pl = pm + 1; 248 if (vl == &nv[size]) { 249 size += GLOBSPACE; 250 nv = (Char **) xrealloc((ptr_t) nv, 251 (size_t) (size * sizeof(Char *))); 252 vl = &nv[size - GLOBSPACE]; 253 } 254 } 255 break; 256 default: 257 break; 258 } 259 *vl = NULL; 260 *bl = nv; 261 return (len); 262} 263 264 265static void 266expbrace(nvp, elp, size) 267 Char ***nvp, ***elp; 268 int size; 269{ 270 Char **vl, **el, **nv, *s; 271 272 vl = nv = *nvp; 273 if (elp != NULL) 274 el = *elp; 275 else 276 for (el = vl; *el; el++) 277 continue; 278 279 for (s = *vl; s; s = *++vl) { 280 Char *b; 281 Char **vp, **bp; 282 283 /* leave {} untouched for find */ 284 if (s[0] == '{' && (s[1] == '\0' || (s[1] == '}' && s[2] == '\0'))) 285 continue; 286 if ((b = Strchr(s, '{')) != NULL) { 287 Char **bl; 288 int len; 289 290 if ((len = globbrace(s, b, &bl)) < 0) { 291 xfree((ptr_t) nv); 292 stderror(ERR_MISSING, -len); 293 } 294 xfree((ptr_t) s); 295 if (len == 1) { 296 *vl-- = *bl; 297 xfree((ptr_t) bl); 298 continue; 299 } 300 if (&el[len] >= &nv[size]) { 301 int l, e; 302 l = (int) (&el[len] - &nv[size]); 303 size += GLOBSPACE > l ? GLOBSPACE : l; 304 l = (int) (vl - nv); 305 e = (int) (el - nv); 306 nv = (Char **) xrealloc((ptr_t) nv, 307 (size_t) (size * sizeof(Char *))); 308 vl = nv + l; 309 el = nv + e; 310 } 311 /* nv vl el bl 312 * | | | | 313 * -.--..-- x-- 314 * | len 315 * vp 316 */ 317 vp = vl--; 318 *vp = *bl; 319 len--; 320 for (bp = el; bp != vp; bp--) 321 bp[len] = *bp; 322 el += len; 323 /* nv vl el bl 324 * | | | | 325 * -.-x --- -- 326 * |len 327 * vp 328 */ 329 vp++; 330 for (bp = bl + 1; *bp; *vp++ = *bp++) 331 continue; 332 xfree((ptr_t) bl); 333 } 334 335 } 336 if (elp != NULL) 337 *elp = el; 338 *nvp = nv; 339} 340 341static Char ** 342globexpand(v) 343 Char **v; 344{ 345 Char *s; 346 Char **nv, **vl, **el; 347 int size = GLOBSPACE; 348 349 350 nv = vl = (Char **) xmalloc((size_t) (sizeof(Char *) * size)); 351 *vl = NULL; 352 353 /* 354 * Step 1: expand backquotes. 355 */ 356 while ((s = *v++) != '\0') { 357 if (Strchr(s, '`')) { 358 int i; 359 360 (void) dobackp(s, 0); 361 for (i = 0; i < pargc; i++) { 362 *vl++ = pargv[i]; 363 if (vl == &nv[size]) { 364 size += GLOBSPACE; 365 nv = (Char **) xrealloc((ptr_t) nv, 366 (size_t) (size * sizeof(Char *))); 367 vl = &nv[size - GLOBSPACE]; 368 } 369 } 370 xfree((ptr_t) pargv); 371 pargv = NULL; 372 } 373 else { 374 *vl++ = Strsave(s); 375 if (vl == &nv[size]) { 376 size += GLOBSPACE; 377 nv = (Char **) xrealloc((ptr_t) nv, 378 (size_t) (size * sizeof(Char *))); 379 vl = &nv[size - GLOBSPACE]; 380 } 381 } 382 } 383 *vl = NULL; 384 385 if (noglob) 386 return (nv); 387 388 /* 389 * Step 2: expand braces 390 */ 391 el = vl; 392 expbrace(&nv, &el, size); 393 394 395 /* 396 * Step 3: expand ~ = 397 */ 398 vl = nv; 399 for (s = *vl; s; s = *++vl) 400 switch (*s) { 401 Char gp[BUFSIZE], *ns; 402 case '~': 403 *vl = globtilde(nv, s); 404 break; 405 case '=': 406 if ((ns = globequal(gp, s)) == NULL) { 407 if (!adrof(STRnonomatch)) { 408 /* Error */ 409 blkfree(nv); 410 stderror(ERR_DEEP); 411 } 412 } 413 if (ns && ns != s) { 414 /* Expansion succeeded */ 415 xfree((ptr_t) s); 416 *vl = Strsave(gp); 417 } 418 break; 419 default: 420 break; 421 } 422 vl = nv; 423 424 /* 425 * Step 4: expand .. if the variable symlinks==expand is set 426 */ 427 if ( symlinks == SYM_EXPAND ) 428 for (s = *vl; s; s = *++vl) { 429 *vl = dnormalize(s, 1); 430 xfree((ptr_t) s); 431 } 432 vl = nv; 433 434 return (vl); 435} 436 437static Char * 438handleone(str, vl, action) 439 Char *str, **vl; 440 int action; 441{ 442 443 Char **vlp = vl; 444 int chars; 445 Char **t, *p, *strp; 446 447 switch (action) { 448 case G_ERROR: 449 setname(short2str(str)); 450 blkfree(vl); 451 stderror(ERR_NAME | ERR_AMBIG); 452 break; 453 case G_APPEND: 454 chars = 0; 455 for (t = vlp; (p = *t++) != '\0'; chars++) 456 while (*p++) 457 chars++; 458 str = (Char *)xmalloc((size_t)(chars * sizeof(Char))); 459 for (t = vlp, strp = str; (p = *t++) != '\0'; chars++) { 460 while (*p) 461 *strp++ = *p++ & TRIM; 462 *strp++ = ' '; 463 } 464 *--strp = '\0'; 465 blkfree(vl); 466 break; 467 case G_IGNORE: 468 str = Strsave(strip(*vlp)); 469 blkfree(vl); 470 break; 471 default: 472 break; 473 } 474 return (str); 475} 476 477static Char ** 478libglob(vl) 479 Char **vl; 480{ 481 int gflgs = GLOB_QUOTE | GLOB_NOMAGIC | GLOB_ALTNOT; 482 glob_t globv; 483 char *ptr; 484 int nonomatch = adrof(STRnonomatch) != 0, magic = 0, match = 0; 485 486 if (!vl || !vl[0]) 487 return(vl); 488 489 globv.gl_offs = 0; 490 globv.gl_pathv = 0; 491 globv.gl_pathc = 0; 492 493 if (nonomatch) 494 gflgs |= GLOB_NOCHECK; 495 496 do { 497 ptr = short2qstr(*vl); 498 switch (glob(ptr, gflgs, 0, &globv)) { 499 case GLOB_ABEND: 500 globfree(&globv); 501 setname(ptr); 502 stderror(ERR_NAME | ERR_GLOB); 503 /* NOTREACHED */ 504 case GLOB_NOSPACE: 505 globfree(&globv); 506 stderror(ERR_NOMEM); 507 /* NOTREACHED */ 508 default: 509 break; 510 } 511 if (globv.gl_flags & GLOB_MAGCHAR) { 512 match |= (globv.gl_matchc != 0); 513 magic = 1; 514 } 515 gflgs |= GLOB_APPEND; 516 } 517 while (*++vl); 518 vl = (globv.gl_pathc == 0 || (magic && !match && !nonomatch)) ? 519 NULL : blk2short(globv.gl_pathv); 520 globfree(&globv); 521 return (vl); 522} 523 524Char * 525globone(str, action) 526 Char *str; 527 int action; 528{ 529 530 Char *v[2], **vl, **vo; 531 int gflg; 532 533 noglob = adrof(STRnoglob) != 0; 534 gflag = 0; 535 v[0] = str; 536 v[1] = 0; 537 tglob(v); 538 gflg = gflag; 539 if (gflg == G_NONE) 540 return (strip(Strsave(str))); 541 542 if (gflg & G_CSH) { 543 /* 544 * Expand back-quote, tilde and brace 545 */ 546 vo = globexpand(v); 547 if (noglob || (gflg & G_GLOB) == 0) { 548 if (vo[0] == NULL) { 549 xfree((ptr_t) vo); 550 return (Strsave(STRNULL)); 551 } 552 if (vo[1] != NULL) 553 return (handleone(str, vo, action)); 554 else { 555 str = strip(vo[0]); 556 xfree((ptr_t) vo); 557 return (str); 558 } 559 } 560 } 561 else if (noglob || (gflg & G_GLOB) == 0) 562 return (strip(Strsave(str))); 563 else 564 vo = v; 565 566 vl = libglob(vo); 567 if ((gflg & G_CSH) && vl != vo) 568 blkfree(vo); 569 if (vl == NULL) { 570 setname(short2str(str)); 571 stderror(ERR_NAME | ERR_NOMATCH); 572 } 573 if (vl[0] == NULL) { 574 xfree((ptr_t) vl); 575 return (Strsave(STRNULL)); 576 } 577 if (vl[1]) 578 return (handleone(str, vl, action)); 579 else { 580 str = strip(*vl); 581 xfree((ptr_t) vl); 582 return (str); 583 } 584} 585 586Char ** 587globall(v) 588 Char **v; 589{ 590 Char **vl, **vo; 591 int gflg = gflag; 592 593 if (!v || !v[0]) { 594 gargv = saveblk(v); 595 gargc = blklen(gargv); 596 return (gargv); 597 } 598 599 noglob = adrof(STRnoglob) != 0; 600 601 if (gflg & G_CSH) 602 /* 603 * Expand back-quote, tilde and brace 604 */ 605 vl = vo = globexpand(v); 606 else 607 vl = vo = saveblk(v); 608 609 if (!noglob && (gflg & G_GLOB)) { 610 vl = libglob(vo); 611 if (vl != vo) 612 blkfree(vo); 613 } 614 else 615 trim(vl); 616 617 gargc = vl ? blklen(vl) : 0; 618 return (gargv = vl); 619} 620 621void 622ginit() 623{ 624 gargsiz = GLOBSPACE; 625 gargv = (Char **) xmalloc((size_t) (sizeof(Char *) * gargsiz)); 626 gargv[0] = 0; 627 gargc = 0; 628} 629 630void 631rscan(t, f) 632 register Char **t; 633 void (*f) __P((int)); 634{ 635 register Char *p; 636 637 while ((p = *t++) != '\0') 638 while (*p) 639 (*f) (*p++); 640} 641 642void 643trim(t) 644 register Char **t; 645{ 646 register Char *p; 647 648 while ((p = *t++) != '\0') 649 while (*p) 650 *p++ &= TRIM; 651} 652 653void 654tglob(t) 655 register Char **t; 656{ 657 register Char *p, *c; 658 659 while ((p = *t++) != '\0') { 660 if (*p == '~' || *p == '=') 661 gflag |= G_CSH; 662 else if (*p == '{' && 663 (p[1] == '\0' || (p[1] == '}' && p[2] == '\0'))) 664 continue; 665 /* 666 * The following line used to be *(c = p++), but hp broke their 667 * optimizer in 9.01, so we break the assignment into two pieces 668 * The careful reader here will note that *most* compiler workarounds 669 * in tcsh are either for apollo/DomainOS or hpux. Is it a coincidence? 670 */ 671 while ( *(c = p) != '\0') { 672 p++; 673 if (*c == '`') { 674 gflag |= G_CSH; 675#ifdef notdef 676 /* 677 * We do want to expand echo `echo '*'`, so we don't\ 678 * use this piece of code anymore. 679 */ 680 while (*p && *p != '`') 681 if (*p++ == '\\') { 682 if (*p) /* Quoted chars */ 683 p++; 684 else 685 break; 686 } 687 if (*p) /* The matching ` */ 688 p++; 689 else 690 break; 691#endif 692 } 693 else if (*c == '{') 694 gflag |= G_CSH; 695 else if (isglob(*c)) 696 gflag |= G_GLOB; 697 else if (symlinks == SYM_EXPAND && 698 *p && ISDOTDOT(c) && (c == *(t-1) || *(c-1) == '/') ) 699 gflag |= G_CSH; 700 } 701 } 702} 703 704/* 705 * Command substitute cp. If literal, then this is a substitution from a 706 * << redirection, and so we should not crunch blanks and tabs, separating 707 * words only at newlines. 708 */ 709Char ** 710dobackp(cp, literal) 711 Char *cp; 712 bool literal; 713{ 714 register Char *lp, *rp; 715 Char *ep, word[LONGBSIZE]; 716 717 if (pargv) { 718#ifdef notdef 719 abort(); 720#endif 721 blkfree(pargv); 722 } 723 pargsiz = GLOBSPACE; 724 pargv = (Char **) xmalloc((size_t) (sizeof(Char *) * pargsiz)); 725 pargv[0] = NULL; 726 pargcp = pargs = word; 727 pargc = 0; 728 pnleft = LONGBSIZE - 4; 729 for (;;) { 730 for (lp = cp; *lp != '`'; lp++) { 731 if (*lp == 0) { 732 if (pargcp != pargs) 733 pword(LONGBSIZE); 734 return (pargv); 735 } 736 psave(*lp); 737 } 738 lp++; 739 for (rp = lp; *rp && *rp != '`'; rp++) 740 if (*rp == '\\') { 741 rp++; 742 if (!*rp) 743 goto oops; 744 } 745 if (!*rp) 746 oops: stderror(ERR_UNMATCHED, '`'); 747 ep = Strsave(lp); 748 ep[rp - lp] = 0; 749 backeval(ep, literal); 750 cp = rp + 1; 751 } 752} 753 754 755static void 756backeval(cp, literal) 757 Char *cp; 758 bool literal; 759{ 760 register int icnt, c; 761 register Char *ip; 762 struct command faket; 763 bool hadnl; 764 int pvec[2], quoted; 765 Char *fakecom[2], ibuf[BUFSIZE]; 766 char tibuf[BUFSIZE]; 767 768 hadnl = 0; 769 icnt = 0; 770 quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 771 faket.t_dtyp = NODE_COMMAND; 772 faket.t_dflg = F_BACKQ; 773 faket.t_dlef = 0; 774 faket.t_drit = 0; 775 faket.t_dspr = 0; 776 faket.t_dcom = fakecom; 777 fakecom[0] = STRfakecom1; 778 fakecom[1] = 0; 779 780 /* 781 * We do the psave job to temporarily change the current job so that the 782 * following fork is considered a separate job. This is so that when 783 * backquotes are used in a builtin function that calls glob the "current 784 * job" is not corrupted. We only need one level of pushed jobs as long as 785 * we are sure to fork here. 786 */ 787 psavejob(); 788 789 /* 790 * It would be nicer if we could integrate this redirection more with the 791 * routines in sh.sem.c by doing a fake execute on a builtin function that 792 * was piped out. 793 */ 794 mypipe(pvec); 795 if (pfork(&faket, -1) == 0) { 796 struct command *t; 797 798 (void) close(pvec[0]); 799 (void) dmove(pvec[1], 1); 800 (void) dmove(SHDIAG, 2); 801 initdesc(); 802 /* 803 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, 804 * posted to comp.bugs.4bsd 12 Sep. 1989. 805 */ 806 if (pargv) /* mg, 21.dec.88 */ 807 blkfree(pargv), pargv = 0, pargsiz = 0; 808 /* mg, 21.dec.88 */ 809 arginp = cp; 810 while (*cp) 811 *cp++ &= TRIM; 812 813 /* 814 * In the child ``forget'' everything about current aliases or 815 * eval vectors. 816 */ 817 alvec = NULL; 818 evalvec = NULL; 819 alvecp = NULL; 820 evalp = NULL; 821 (void) lex(¶ml); 822 if (seterr) 823 stderror(ERR_OLD); 824 alias(¶ml); 825 t = syntax(paraml.next, ¶ml, 0); 826 if (seterr) 827 stderror(ERR_OLD); 828 if (t) 829 t->t_dflg |= F_NOFORK; 830#ifdef SIGTSTP 831 (void) sigignore(SIGTSTP); 832#endif 833#ifdef SIGTTIN 834 (void) sigignore(SIGTTIN); 835#endif 836#ifdef SIGTTOU 837 (void) sigignore(SIGTTOU); 838#endif 839 execute(t, -1, NULL, NULL); 840 exitstat(); 841 } 842 xfree((ptr_t) cp); 843 (void) close(pvec[1]); 844 c = 0; 845 ip = NULL; 846 do { 847 int cnt = 0; 848 849 for (;;) { 850 if (icnt == 0) { 851 int i; 852 853 ip = ibuf; 854 do 855 icnt = read(pvec[0], tibuf, BUFSIZE); 856 while (icnt == -1 && errno == EINTR); 857 if (icnt <= 0) { 858 c = -1; 859 break; 860 } 861 for (i = 0; i < icnt; i++) 862 ip[i] = (unsigned char) tibuf[i]; 863 } 864 if (hadnl) 865 break; 866 --icnt; 867 c = (*ip++ & TRIM); 868 if (c == 0) 869 break; 870#ifdef WINNT 871 if (c == '\r') 872 c = ' '; 873#endif /* WINNT */ 874 if (c == '\n') { 875 /* 876 * Continue around the loop one more time, so that we can eat 877 * the last newline without terminating this word. 878 */ 879 hadnl = 1; 880 continue; 881 } 882 if (!quoted && (c == ' ' || c == '\t')) 883 break; 884 cnt++; 885 psave(c | quoted); 886 } 887 /* 888 * Unless at end-of-file, we will form a new word here if there were 889 * characters in the word, or in any case when we take text literally. 890 * If we didn't make empty words here when literal was set then we 891 * would lose blank lines. 892 */ 893 if (c != -1 && (cnt || literal)) 894 pword(BUFSIZE); 895 hadnl = 0; 896 } while (c >= 0); 897 (void) close(pvec[0]); 898 pwait(); 899 prestjob(); 900} 901 902static void 903psave(c) 904 int c; 905{ 906 if (--pnleft <= 0) 907 stderror(ERR_WTOOLONG); 908 *pargcp++ = (Char) c; 909} 910 911static void 912pword(bufsiz) 913 int bufsiz; 914{ 915 psave(0); 916 if (pargc == pargsiz - 1) { 917 pargsiz += GLOBSPACE; 918 pargv = (Char **) xrealloc((ptr_t) pargv, 919 (size_t) (pargsiz * sizeof(Char *))); 920 } 921 pargv[pargc++] = Strsave(pargs); 922 pargv[pargc] = NULL; 923 pargcp = pargs; 924 pnleft = bufsiz - 4; 925} 926 927int 928Gmatch(string, pattern) 929 Char *string, *pattern; 930{ 931 return Gnmatch(string, pattern, NULL); 932} 933 934int 935Gnmatch(string, pattern, endstr) 936 Char *string, *pattern, **endstr; 937{ 938 Char **blk, **p, *tstring = string; 939 int gpol = 1, gres = 0; 940 941 if (*pattern == '^') { 942 gpol = 0; 943 pattern++; 944 } 945 946 blk = (Char **) xmalloc((size_t) (GLOBSPACE * sizeof(Char *))); 947 blk[0] = Strsave(pattern); 948 blk[1] = NULL; 949 950 expbrace(&blk, NULL, GLOBSPACE); 951 952 if (endstr == NULL) 953 /* Exact matches only */ 954 for (p = blk; *p; p++) 955 gres |= pmatch(string, *p, &tstring) == 2 ? 1 : 0; 956 else { 957 /* partial matches */ 958 int minc = 0x7fffffff; 959 for (p = blk; *p; p++) 960 if (pmatch(string, *p, &tstring) != 0) { 961 int t = (int) (tstring - string); 962 gres |= 1; 963 if (minc == -1 || minc > t) 964 minc = t; 965 } 966 *endstr = string + minc; 967 } 968 969 blkfree(blk); 970 return(gres == gpol); 971} 972 973/* pmatch(): 974 * Return 2 on exact match, 975 * Return 1 on substring match. 976 * Return 0 on no match. 977 * *estr will point to the end of the longest exact or substring match. 978 */ 979static int 980pmatch(string, pattern, estr) 981 register Char *string, *pattern, **estr; 982{ 983 register Char stringc, patternc; 984 int match, negate_range; 985 Char rangec, *oestr, *pestr; 986 987 for (;; ++string) { 988 stringc = *string & TRIM; 989 /* 990 * apollo compiler bug: switch (patternc = *pattern++) dies 991 */ 992 patternc = *pattern++; 993 switch (patternc) { 994 case 0: 995 *estr = string; 996 return (stringc == 0 ? 2 : 1); 997 case '?': 998 if (stringc == 0) 999 return (0); 1000 *estr = string; 1001 break; 1002 case '*': 1003 if (!*pattern) { 1004 while (*string) string++; 1005 *estr = string; 1006 return (2); 1007 } 1008 oestr = *estr; 1009 pestr = NULL; 1010 1011 do { 1012 switch(pmatch(string, pattern, estr)) { 1013 case 0: 1014 break; 1015 case 1: 1016 pestr = *estr; 1017 break; 1018 case 2: 1019 return 2; 1020 default: 1021 abort(); /* Cannot happen */ 1022 } 1023 *estr = string; 1024 } 1025 while (*string++); 1026 1027 if (pestr) { 1028 *estr = pestr; 1029 return 1; 1030 } 1031 else { 1032 *estr = oestr; 1033 return 0; 1034 } 1035 1036 case '[': 1037 match = 0; 1038 if ((negate_range = (*pattern == '^')) != 0) 1039 pattern++; 1040 while ((rangec = *pattern++) != '\0') { 1041 if (rangec == ']') 1042 break; 1043 if (match) 1044 continue; 1045 if (rangec == '-' && *(pattern-2) != '[' && *pattern != ']') { 1046 match = (globcharcoll(stringc, *pattern & TRIM) <= 0 && 1047 globcharcoll(*(pattern-2) & TRIM, stringc) <= 0); 1048 pattern++; 1049 } 1050 else 1051 match = (stringc == (rangec & TRIM)); 1052 } 1053 if (rangec == 0) 1054 stderror(ERR_NAME | ERR_MISSING, ']'); 1055 if (match == negate_range) 1056 return (0); 1057 *estr = string; 1058 break; 1059 default: 1060 if ((patternc & TRIM) != stringc) 1061 return (0); 1062 *estr = string; 1063 break; 1064 } 1065 } 1066} 1067 1068void 1069Gcat(s1, s2) 1070 Char *s1, *s2; 1071{ 1072 register Char *p, *q; 1073 int n; 1074 1075 for (p = s1; *p++;) 1076 continue; 1077 for (q = s2; *q++;) 1078 continue; 1079 n = (int) ((p - s1) + (q - s2) - 1); 1080 if (++gargc >= gargsiz) { 1081 gargsiz += GLOBSPACE; 1082 gargv = (Char **) xrealloc((ptr_t) gargv, 1083 (size_t) (gargsiz * sizeof(Char *))); 1084 } 1085 gargv[gargc] = 0; 1086 p = gargv[gargc - 1] = (Char *) xmalloc((size_t) (n * sizeof(Char))); 1087 for (q = s1; (*p++ = *q++) != '\0';) 1088 continue; 1089 for (p--, q = s2; (*p++ = *q++) != '\0';) 1090 continue; 1091} 1092 1093#ifdef FILEC 1094int 1095sortscmp(a, b) 1096 register Char **a, **b; 1097{ 1098 if (!a) /* check for NULL */ 1099 return (b ? 1 : 0); 1100 if (!b) 1101 return (-1); 1102 1103 if (!*a) /* check for NULL */ 1104 return (*b ? 1 : 0); 1105 if (!*b) 1106 return (-1); 1107 1108 return (int) collate(*a, *b); 1109} 1110 1111#endif 1112