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