1 /*- 2 * Copyright (c) 1980, 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 /*static char sccsid[] = "from: @(#)glob.c 5.21 (Berkeley) 6/25/91";*/ 36 static char rcsid[] = "$Id: glob.c,v 1.4 1993/08/01 19:00:42 mycroft Exp $"; 37 #endif /* not lint */ 38 39 #include <sys/param.h> 40 #include <glob.h> 41 #include <errno.h> 42 #include <stdlib.h> 43 #include <string.h> 44 #include <unistd.h> 45 #if __STDC__ 46 # include <stdarg.h> 47 #else 48 # include <varargs.h> 49 #endif 50 51 #include "csh.h" 52 #include "extern.h" 53 54 static int noglob, nonomatch; 55 static int pargsiz, gargsiz; 56 57 /* 58 * Values for gflag 59 */ 60 #define G_NONE 0 /* No globbing needed */ 61 #define G_GLOB 1 /* string contains *?[] characters */ 62 #define G_CSH 2 /* string contains ~`{ characters */ 63 64 #define GLOBSPACE 100 /* Alloc increment */ 65 66 #define LBRC '{' 67 #define RBRC '}' 68 #define LBRK '[' 69 #define RBRK ']' 70 #define EOS '\0' 71 72 Char **gargv = NULL; 73 long gargc = 0; 74 Char **pargv = NULL; 75 long pargc = 0; 76 77 /* 78 * globbing is now done in two stages. In the first pass we expand 79 * csh globbing idioms ~`{ and then we proceed doing the normal 80 * globbing if needed ?*[ 81 * 82 * Csh type globbing is handled in globexpand() and the rest is 83 * handled in glob() which is part of the 4.4BSD libc. 84 * 85 */ 86 static Char *globtilde __P((Char **, Char *)); 87 static Char **libglob __P((Char **)); 88 static Char **globexpand __P((Char **)); 89 static int globbrace __P((Char *, Char *, Char ***)); 90 static void pword __P((void)); 91 static void psave __P((int)); 92 static void backeval __P((Char *, bool)); 93 94 95 static Char * 96 globtilde(nv, s) 97 Char **nv, *s; 98 { 99 Char gbuf[MAXPATHLEN], *gstart, *b, *u, *e; 100 101 gstart = gbuf; 102 *gstart++ = *s++; 103 u = s; 104 for (b = gstart, e = &gbuf[MAXPATHLEN - 1]; *s && *s != '/' && b < e; 105 *b++ = *s++); 106 *b = EOS; 107 if (gethdir(gstart)) { 108 blkfree(nv); 109 if (*gstart) 110 stderror(ERR_UNKUSER, short2str(gstart)); 111 else 112 stderror(ERR_NOHOME); 113 } 114 b = &gstart[Strlen(gstart)]; 115 while (*s) 116 *b++ = *s++; 117 *b = EOS; 118 --u; 119 xfree((ptr_t) u); 120 return (Strsave(gstart)); 121 } 122 123 static int 124 globbrace(s, p, bl) 125 Char *s, *p, ***bl; 126 { 127 int i, len; 128 Char *pm, *pe, *lm, *pl; 129 Char **nv, **vl; 130 Char gbuf[MAXPATHLEN]; 131 int size = GLOBSPACE; 132 133 nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); 134 *vl = NULL; 135 136 len = 0; 137 /* copy part up to the brace */ 138 for (lm = gbuf, p = s; *p != LBRC; *lm++ = *p++) 139 continue; 140 141 /* check for balanced braces */ 142 for (i = 0, pe = ++p; *pe; pe++) 143 if (*pe == LBRK) { 144 /* Ignore everything between [] */ 145 for (++pe; *pe != RBRK && *pe != EOS; pe++) 146 continue; 147 if (*pe == EOS) { 148 blkfree(nv); 149 return (-LBRK); 150 } 151 } 152 else if (*pe == LBRC) 153 i++; 154 else if (*pe == RBRC) { 155 if (i == 0) 156 break; 157 i--; 158 } 159 160 if (i != 0) { 161 blkfree(nv); 162 return (-LBRC); 163 } 164 165 for (i = 0, pl = pm = p; pm <= pe; pm++) 166 switch (*pm) { 167 case LBRK: 168 for (++pm; *pm != RBRK && *pm != EOS; pm++) 169 continue; 170 if (*pm == EOS) { 171 *vl = NULL; 172 blkfree(nv); 173 return (-RBRK); 174 } 175 break; 176 case LBRC: 177 i++; 178 break; 179 case RBRC: 180 if (i) { 181 i--; 182 break; 183 } 184 /* FALLTHROUGH */ 185 case ',': 186 if (i && *pm == ',') 187 break; 188 else { 189 Char savec = *pm; 190 191 *pm = EOS; 192 (void) Strcpy(lm, pl); 193 (void) Strcat(gbuf, pe + 1); 194 *pm = savec; 195 *vl++ = Strsave(gbuf); 196 len++; 197 pl = pm + 1; 198 if (vl == &nv[size]) { 199 size += GLOBSPACE; 200 nv = (Char **) xrealloc((ptr_t) nv, (size_t) 201 size * sizeof(Char *)); 202 vl = &nv[size - GLOBSPACE]; 203 } 204 } 205 break; 206 } 207 *vl = NULL; 208 *bl = nv; 209 return (len); 210 } 211 212 static Char ** 213 globexpand(v) 214 Char **v; 215 { 216 Char *s; 217 Char **nv, **vl, **el; 218 int size = GLOBSPACE; 219 220 221 nv = vl = (Char **) xmalloc((size_t) sizeof(Char *) * size); 222 *vl = NULL; 223 224 /* 225 * Step 1: expand backquotes. 226 */ 227 while (s = *v++) { 228 if (Strchr(s, '`')) { 229 int i; 230 231 (void) dobackp(s, 0); 232 for (i = 0; i < pargc; i++) { 233 *vl++ = pargv[i]; 234 if (vl == &nv[size]) { 235 size += GLOBSPACE; 236 nv = (Char **) xrealloc((ptr_t) nv, 237 (size_t) size * sizeof(Char *)); 238 vl = &nv[size - GLOBSPACE]; 239 } 240 } 241 xfree((ptr_t) pargv); 242 pargv = NULL; 243 } 244 else { 245 *vl++ = Strsave(s); 246 if (vl == &nv[size]) { 247 size += GLOBSPACE; 248 nv = (Char **) xrealloc((ptr_t) nv, (size_t) 249 size * sizeof(Char *)); 250 vl = &nv[size - GLOBSPACE]; 251 } 252 } 253 } 254 *vl = NULL; 255 256 if (noglob) 257 return (nv); 258 259 /* 260 * Step 2: expand braces 261 */ 262 el = vl; 263 vl = nv; 264 for (s = *vl; s; s = *++vl) { 265 Char *b; 266 Char **vp, **bp; 267 268 if (b = Strchr(s, LBRC)) { 269 Char **bl; 270 int len; 271 272 if ((len = globbrace(s, b, &bl)) < 0) { 273 blkfree(nv); 274 stderror(ERR_MISSING, -len); 275 } 276 xfree((ptr_t) s); 277 if (len == 1) { 278 *vl-- = *bl; 279 xfree((ptr_t) bl); 280 continue; 281 } 282 len = blklen(bl); 283 if (&el[len] >= &nv[size]) { 284 int l, e; 285 286 l = &el[len] - &nv[size]; 287 size += GLOBSPACE > l ? GLOBSPACE : l; 288 l = vl - nv; 289 e = el - nv; 290 nv = (Char **) xrealloc((ptr_t) nv, (size_t) 291 size * sizeof(Char *)); 292 vl = nv + l; 293 el = nv + e; 294 } 295 vp = vl--; 296 *vp = *bl; 297 len--; 298 for (bp = el; bp != vp; bp--) 299 bp[len] = *bp; 300 el += len; 301 vp++; 302 for (bp = bl + 1; *bp; *vp++ = *bp++) 303 continue; 304 xfree((ptr_t) bl); 305 } 306 307 } 308 309 /* 310 * Step 3: expand ~ 311 */ 312 vl = nv; 313 for (s = *vl; s; s = *++vl) 314 if (*s == '~') 315 *vl = globtilde(nv, s); 316 vl = nv; 317 return (vl); 318 } 319 320 static Char * 321 handleone(str, vl, action) 322 Char *str, **vl; 323 int action; 324 { 325 326 Char *cp, **vlp = vl; 327 328 switch (action) { 329 case G_ERROR: 330 setname(short2str(str)); 331 blkfree(vl); 332 stderror(ERR_NAME | ERR_AMBIG); 333 break; 334 case G_APPEND: 335 trim(vlp); 336 str = Strsave(*vlp++); 337 do { 338 cp = Strspl(str, STRspace); 339 xfree((ptr_t) str); 340 str = Strspl(cp, *vlp); 341 xfree((ptr_t) cp); 342 } 343 while (*++vlp); 344 blkfree(vl); 345 break; 346 case G_IGNORE: 347 str = Strsave(strip(*vlp)); 348 blkfree(vl); 349 break; 350 } 351 return (str); 352 } 353 354 static Char ** 355 libglob(vl) 356 Char **vl; 357 { 358 int gflgs = GLOB_QUOTE | GLOB_NOCHECK; 359 glob_t globv; 360 char *ptr; 361 362 globv.gl_offs = 0; 363 globv.gl_pathv = 0; 364 globv.gl_pathc = 0; 365 nonomatch = adrof(STRnonomatch) != 0; 366 do { 367 ptr = short2qstr(*vl); 368 switch (glob(ptr, gflgs, 0, &globv)) { 369 case GLOB_ABEND: 370 setname(ptr); 371 stderror(ERR_NAME | ERR_GLOB); 372 /* NOTREACHED */ 373 case GLOB_NOSPACE: 374 stderror(ERR_NOMEM); 375 /* NOTREACHED */ 376 default: 377 break; 378 } 379 if (!nonomatch && (globv.gl_matchc == 0) && 380 (globv.gl_flags & GLOB_MAGCHAR)) { 381 globfree(&globv); 382 return (NULL); 383 } 384 gflgs |= GLOB_APPEND; 385 } 386 while (*++vl); 387 vl = blk2short(globv.gl_pathv); 388 globfree(&globv); 389 return (vl); 390 } 391 392 Char * 393 globone(str, action) 394 Char *str; 395 int action; 396 { 397 398 Char *v[2], **vl, **vo; 399 400 noglob = adrof(STRnoglob) != 0; 401 gflag = 0; 402 v[0] = str; 403 v[1] = 0; 404 tglob(v); 405 if (gflag == G_NONE) 406 return (strip(Strsave(str))); 407 408 if (gflag & G_CSH) { 409 /* 410 * Expand back-quote, tilde and brace 411 */ 412 vo = globexpand(v); 413 if (noglob || (gflag & G_GLOB) == 0) { 414 if (vo[0] == NULL) { 415 xfree((ptr_t) vo); 416 return (Strsave(STRNULL)); 417 } 418 if (vo[1] != NULL) 419 return (handleone(str, vo, action)); 420 else { 421 str = strip(vo[0]); 422 xfree((ptr_t) vo); 423 return (str); 424 } 425 } 426 } 427 else if (noglob || (gflag & G_GLOB) == 0) 428 return (strip(Strsave(str))); 429 else 430 vo = v; 431 432 vl = libglob(vo); 433 if (gflag & G_CSH) 434 blkfree(vo); 435 if (vl == NULL) { 436 setname(short2str(str)); 437 stderror(ERR_NAME | ERR_NOMATCH); 438 } 439 if (vl[0] == NULL) { 440 xfree((ptr_t) vl); 441 return (Strsave(STRNULL)); 442 } 443 if (vl[1] != NULL) 444 return (handleone(str, vl, action)); 445 else { 446 str = strip(*vl); 447 xfree((ptr_t) vl); 448 return (str); 449 } 450 } 451 452 Char ** 453 globall(v) 454 Char **v; 455 { 456 Char **vl, **vo; 457 458 if (!v || !v[0]) { 459 gargv = saveblk(v); 460 gargc = blklen(gargv); 461 return (gargv); 462 } 463 464 noglob = adrof(STRnoglob) != 0; 465 466 if (gflag & G_CSH) 467 /* 468 * Expand back-quote, tilde and brace 469 */ 470 vl = vo = globexpand(v); 471 else 472 vl = vo = saveblk(v); 473 474 if (!noglob && (gflag & G_GLOB)) { 475 vl = libglob(vo); 476 if (gflag & G_CSH) 477 blkfree(vo); 478 } 479 480 gargc = vl ? blklen(vl) : 0; 481 return (gargv = vl); 482 } 483 484 void 485 ginit() 486 { 487 gargsiz = GLOBSPACE; 488 gargv = (Char **) xmalloc((size_t) sizeof(Char *) * gargsiz); 489 gargv[0] = 0; 490 gargc = 0; 491 } 492 493 void 494 rscan(t, f) 495 register Char **t; 496 void (*f) (); 497 { 498 register Char *p; 499 500 while (p = *t++) 501 while (*p) 502 (*f) (*p++); 503 } 504 505 void 506 trim(t) 507 register Char **t; 508 { 509 register Char *p; 510 511 while (p = *t++) 512 while (*p) 513 *p++ &= TRIM; 514 } 515 516 void 517 tglob(t) 518 register Char **t; 519 { 520 register Char *p, c; 521 522 while (p = *t++) { 523 if (*p == '~' || *p == '=') 524 gflag |= G_CSH; 525 else if (*p == '{' && 526 (p[1] == '\0' || p[1] == '}' && p[2] == '\0')) 527 continue; 528 while (c = *p++) 529 if (isglob(c)) 530 gflag |= (c == '{' || c == '`') ? G_CSH : G_GLOB; 531 } 532 } 533 534 /* 535 * Command substitute cp. If literal, then this is a substitution from a 536 * << redirection, and so we should not crunch blanks and tabs, separating 537 * words only at newlines. 538 */ 539 Char ** 540 dobackp(cp, literal) 541 Char *cp; 542 bool literal; 543 { 544 register Char *lp, *rp; 545 Char *ep, word[MAXPATHLEN]; 546 547 if (pargv) { 548 abort(); 549 blkfree(pargv); 550 } 551 pargsiz = GLOBSPACE; 552 pargv = (Char **) xmalloc((size_t) sizeof(Char *) * pargsiz); 553 pargv[0] = NULL; 554 pargcp = pargs = word; 555 pargc = 0; 556 pnleft = MAXPATHLEN - 4; 557 for (;;) { 558 for (lp = cp; *lp != '`'; lp++) { 559 if (*lp == 0) { 560 if (pargcp != pargs) 561 pword(); 562 return (pargv); 563 } 564 psave(*lp); 565 } 566 lp++; 567 for (rp = lp; *rp && *rp != '`'; rp++) 568 if (*rp == '\\') { 569 rp++; 570 if (!*rp) 571 goto oops; 572 } 573 if (!*rp) 574 oops: stderror(ERR_UNMATCHED, '`'); 575 ep = Strsave(lp); 576 ep[rp - lp] = 0; 577 backeval(ep, literal); 578 cp = rp + 1; 579 } 580 } 581 582 static void 583 backeval(cp, literal) 584 Char *cp; 585 bool literal; 586 { 587 register int icnt, c; 588 register Char *ip; 589 struct command faket; 590 bool hadnl; 591 int pvec[2], quoted; 592 Char *fakecom[2], ibuf[BUFSIZ]; 593 char tibuf[BUFSIZ]; 594 595 hadnl = 0; 596 icnt = 0; 597 quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0; 598 faket.t_dtyp = NODE_COMMAND; 599 faket.t_dflg = 0; 600 faket.t_dlef = 0; 601 faket.t_drit = 0; 602 faket.t_dspr = 0; 603 faket.t_dcom = fakecom; 604 fakecom[0] = STRfakecom1; 605 fakecom[1] = 0; 606 607 /* 608 * We do the psave job to temporarily change the current job so that the 609 * following fork is considered a separate job. This is so that when 610 * backquotes are used in a builtin function that calls glob the "current 611 * job" is not corrupted. We only need one level of pushed jobs as long as 612 * we are sure to fork here. 613 */ 614 psavejob(); 615 616 /* 617 * It would be nicer if we could integrate this redirection more with the 618 * routines in sh.sem.c by doing a fake execute on a builtin function that 619 * was piped out. 620 */ 621 mypipe(pvec); 622 if (pfork(&faket, -1) == 0) { 623 struct wordent paraml; 624 struct command *t; 625 626 (void) close(pvec[0]); 627 (void) dmove(pvec[1], 1); 628 (void) dmove(SHDIAG, 2); 629 initdesc(); 630 /* 631 * Bugfix for nested backquotes by Michael Greim <greim@sbsvax.UUCP>, 632 * posted to comp.bugs.4bsd 12 Sep. 1989. 633 */ 634 if (pargv) /* mg, 21.dec.88 */ 635 blkfree(pargv), pargv = 0, pargsiz = 0; 636 /* mg, 21.dec.88 */ 637 arginp = cp; 638 while (*cp) 639 *cp++ &= TRIM; 640 (void) lex(¶ml); 641 if (seterr) 642 stderror(ERR_OLD); 643 alias(¶ml); 644 t = syntax(paraml.next, ¶ml, 0); 645 if (seterr) 646 stderror(ERR_OLD); 647 if (t) 648 t->t_dflg |= F_NOFORK; 649 (void) signal(SIGTSTP, SIG_IGN); 650 (void) signal(SIGTTIN, SIG_IGN); 651 (void) signal(SIGTTOU, SIG_IGN); 652 execute(t, -1, NULL, NULL); 653 exitstat(); 654 } 655 xfree((ptr_t) cp); 656 (void) close(pvec[1]); 657 c = 0; 658 ip = NULL; 659 do { 660 int cnt = 0; 661 662 for (;;) { 663 if (icnt == 0) { 664 int i; 665 666 ip = ibuf; 667 do 668 icnt = read(pvec[0], tibuf, BUFSIZ); 669 while (icnt == -1 && errno == EINTR); 670 if (icnt <= 0) { 671 c = -1; 672 break; 673 } 674 for (i = 0; i < icnt; i++) 675 ip[i] = (unsigned char) tibuf[i]; 676 } 677 if (hadnl) 678 break; 679 --icnt; 680 c = (*ip++ & TRIM); 681 if (c == 0) 682 break; 683 if (c == '\n') { 684 /* 685 * Continue around the loop one more time, so that we can eat 686 * the last newline without terminating this word. 687 */ 688 hadnl = 1; 689 continue; 690 } 691 if (!quoted && (c == ' ' || c == '\t')) 692 break; 693 cnt++; 694 psave(c | quoted); 695 } 696 /* 697 * Unless at end-of-file, we will form a new word here if there were 698 * characters in the word, or in any case when we take text literally. 699 * If we didn't make empty words here when literal was set then we 700 * would lose blank lines. 701 */ 702 if (c != -1 && (cnt || literal)) 703 pword(); 704 hadnl = 0; 705 } while (c >= 0); 706 (void) close(pvec[0]); 707 pwait(); 708 prestjob(); 709 } 710 711 static void 712 psave(c) 713 int c; 714 { 715 if (--pnleft <= 0) 716 stderror(ERR_WTOOLONG); 717 *pargcp++ = c; 718 } 719 720 static void 721 pword() 722 { 723 psave(0); 724 if (pargc == pargsiz - 1) { 725 pargsiz += GLOBSPACE; 726 pargv = (Char **) xrealloc((ptr_t) pargv, 727 (size_t) pargsiz * sizeof(Char *)); 728 } 729 pargv[pargc++] = Strsave(pargs); 730 pargv[pargc] = NULL; 731 pargcp = pargs; 732 pnleft = MAXPATHLEN - 4; 733 } 734 735 int 736 Gmatch(string, pattern) 737 register Char *string, *pattern; 738 { 739 register Char stringc, patternc; 740 int match; 741 Char rangec; 742 743 for (;; ++string) { 744 stringc = *string & TRIM; 745 patternc = *pattern++; 746 switch (patternc) { 747 case 0: 748 return (stringc == 0); 749 case '?': 750 if (stringc == 0) 751 return (0); 752 break; 753 case '*': 754 if (!*pattern) 755 return (1); 756 while (*string) 757 if (Gmatch(string++, pattern)) 758 return (1); 759 return (0); 760 case '[': 761 match = 0; 762 while (rangec = *pattern++) { 763 if (rangec == ']') 764 if (match) 765 break; 766 else 767 return (0); 768 if (match) 769 continue; 770 if (rangec == '-' && *(pattern - 2) != '[' && *pattern != ']') { 771 match = (stringc <= (*pattern & TRIM) && 772 (*(pattern - 2) & TRIM) <= stringc); 773 pattern++; 774 } 775 else 776 match = (stringc == rangec); 777 } 778 if (rangec == 0) 779 stderror(ERR_NAME | ERR_MISSING, ']'); 780 break; 781 default: 782 if ((patternc & TRIM) != stringc) 783 return (0); 784 break; 785 786 } 787 } 788 } 789 790 void 791 Gcat(s1, s2) 792 Char *s1, *s2; 793 { 794 register Char *p, *q; 795 int n; 796 797 for (p = s1; *p++;); 798 for (q = s2; *q++;); 799 n = (p - s1) + (q - s2) - 1; 800 if (++gargc >= gargsiz) { 801 gargsiz += GLOBSPACE; 802 gargv = (Char **) xrealloc((ptr_t) gargv, 803 (size_t) gargsiz * sizeof(Char *)); 804 } 805 gargv[gargc] = 0; 806 p = gargv[gargc - 1] = (Char *) xmalloc((size_t) n * sizeof(Char)); 807 for (q = s1; *p++ = *q++;); 808 for (p--, q = s2; *p++ = *q++;); 809 } 810 811 #ifdef FILEC 812 int 813 sortscmp(a, b) 814 register Char **a, **b; 815 { 816 #if defined(NLS) && !defined(NOSTRCOLL) 817 char buf[2048]; 818 819 #endif 820 821 if (!a) /* check for NULL */ 822 return (b ? 1 : 0); 823 if (!b) 824 return (-1); 825 826 if (!*a) /* check for NULL */ 827 return (*b ? 1 : 0); 828 if (!*b) 829 return (-1); 830 831 #if defined(NLS) && !defined(NOSTRCOLL) 832 (void) strcpy(buf, short2str(*a)); 833 return ((int) strcoll(buf, short2str(*b))); 834 #else 835 return ((int) Strcmp(*a, *b)); 836 #endif 837 } 838 #endif /* FILEC */ 839