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