1 /* 2 * Copyright (c) 1989 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Guido van Rossum. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 #if defined(LIBC_SCCS) && !defined(lint) 33 static char sccsid[] = "@(#)glob.c 5.12 (Berkeley) 6/24/91"; 34 #endif /* LIBC_SCCS and not lint */ 35 /* 36 * Glob: the interface is a superset of the one defined in POSIX 1003.2, 37 * draft 9. 38 * 39 * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 40 * 41 * Optional extra services, controlled by flags not defined by POSIX: 42 * 43 * GLOB_QUOTE: 44 * Escaping convention: \ inhibits any special meaning the following 45 * character might have (except \ at end of string is retained). 46 * GLOB_MAGCHAR: 47 * Set in gl_flags if pattern contained a globbing character. 48 * GLOB_ALTNOT: 49 * Use ^ instead of ! for "not". 50 * gl_matchc: 51 * Number of matches in the current invocation of glob. 52 */ 53 54 #ifdef WINNT_NATIVE 55 #pragma warning(disable:4244) 56 #endif /* WINNT_NATIVE */ 57 58 #define Char __Char 59 #include "sh.h" 60 #include "glob.h" 61 62 #undef Char 63 #undef QUOTE 64 #undef TILDE 65 #undef META 66 #undef CHAR 67 #undef ismeta 68 #undef Strchr 69 70 #ifndef S_ISDIR 71 #define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 72 #endif 73 74 #if !defined(S_ISLNK) && defined(S_IFLNK) 75 #define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK) 76 #endif 77 78 #if !defined(S_ISLNK) && !defined(lstat) 79 #define lstat stat 80 #endif 81 82 typedef unsigned short Char; 83 84 static int glob1 __P((Char *, glob_t *, int)); 85 static int glob2 __P((Char *, Char *, Char *, glob_t *, int)); 86 static int glob3 __P((Char *, Char *, Char *, Char *, 87 glob_t *, int)); 88 static int globextend __P((Char *, glob_t *)); 89 static int match __P((Char *, Char *, Char *, int)); 90 #ifndef __clipper__ 91 static int compare __P((const ptr_t, const ptr_t)); 92 #endif 93 static DIR *Opendir __P((Char *)); 94 #ifdef S_IFLNK 95 static int Lstat __P((Char *, struct stat *)); 96 #endif 97 static int Stat __P((Char *, struct stat *sb)); 98 static Char *Strchr __P((Char *, int)); 99 #ifdef DEBUG 100 static void qprintf __P((Char *)); 101 #endif 102 103 #define DOLLAR '$' 104 #define DOT '.' 105 #define EOS '\0' 106 #define LBRACKET '[' 107 #define NOT '!' 108 #define ALTNOT '^' 109 #define QUESTION '?' 110 #define QUOTE '\\' 111 #define RANGE '-' 112 #define RBRACKET ']' 113 #define SEP '/' 114 #define STAR '*' 115 #define TILDE '~' 116 #define UNDERSCORE '_' 117 118 #define M_META 0x8000 119 #define M_PROTECT 0x4000 120 #define M_MASK 0xffff 121 #define M_ASCII 0x00ff 122 123 #define CHAR(c) ((c)&M_ASCII) 124 #define META(c) ((c)|M_META) 125 #define M_ALL META('*') 126 #define M_END META(']') 127 #define M_NOT META('!') 128 #define M_ALTNOT META('^') 129 #define M_ONE META('?') 130 #define M_RNG META('-') 131 #define M_SET META('[') 132 #define ismeta(c) (((c)&M_META) != 0) 133 134 #ifndef BUFSIZE 135 #define GLOBBUFLEN MAXPATHLEN 136 #else 137 #define GLOBBUFLEN BUFSIZE 138 #endif 139 140 int 141 globcharcoll(c1, c2, cs) 142 NLSChar c1, c2; 143 int cs; 144 { 145 #if defined(NLS) && defined(LC_COLLATE) && !defined(NOSTRCOLL) 146 # if defined(SHORT_STRINGS) 147 wchar_t s1[2], s2[2]; 148 149 if (c1 == c2) 150 return (0); 151 if (cs) { 152 c1 = towlower(c1); 153 c2 = towlower(c2); 154 } else { 155 /* This should not be here, but I'll rather leave it in than engage in 156 a LC_COLLATE flamewar about a shell I don't use... */ 157 if (iswlower(c1) && iswupper(c2)) 158 return (1); 159 if (iswupper(c1) && iswlower(c2)) 160 return (-1); 161 } 162 s1[0] = c1; 163 s2[0] = c2; 164 s1[1] = s2[1] = '\0'; 165 return wcscoll(s1, s2); 166 # else /* not SHORT_STRINGS */ 167 char s1[2], s2[2]; 168 169 if (c1 == c2) 170 return (0); 171 /* 172 * From kevin lyda <kevin@suberic.net>: 173 * strcoll does not guarantee case sorting, so we pre-process now: 174 */ 175 if (cs) { 176 c1 = islower(c1) ? c1 : tolower(c1); 177 c2 = islower(c2) ? c2 : tolower(c2); 178 } else { 179 if (islower(c1) && isupper(c2)) 180 return (1); 181 if (isupper(c1) && islower(c2)) 182 return (-1); 183 } 184 s1[0] = c1; 185 s2[0] = c2; 186 s1[1] = s2[1] = '\0'; 187 return strcoll(s1, s2); 188 # endif 189 #else 190 return (c1 - c2); 191 #endif 192 } 193 194 /* 195 * Need to dodge two kernel bugs: 196 * opendir("") != opendir(".") 197 * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels. 198 * POSIX specifies that they should be ignored in directories. 199 */ 200 201 static DIR * 202 Opendir(str) 203 Char *str; 204 { 205 char buf[GLOBBUFLEN]; 206 char *dc = buf; 207 #if defined(hpux) || defined(__hpux) 208 struct stat st; 209 #endif 210 211 if (!*str) 212 return (opendir(".")); 213 while ((*dc++ = *str++) != '\0') 214 continue; 215 #if defined(hpux) || defined(__hpux) 216 /* 217 * Opendir on some device files hangs, so avoid it 218 */ 219 if (stat(buf, &st) == -1 || !S_ISDIR(st.st_mode)) 220 return NULL; 221 #endif 222 return (opendir(buf)); 223 } 224 225 #ifdef S_IFLNK 226 static int 227 Lstat(fn, sb) 228 Char *fn; 229 struct stat *sb; 230 { 231 char buf[GLOBBUFLEN]; 232 char *dc = buf; 233 234 while ((*dc++ = *fn++) != '\0') 235 continue; 236 # ifdef NAMEI_BUG 237 { 238 int st; 239 240 st = lstat(buf, sb); 241 if (*buf) 242 dc--; 243 return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 244 } 245 # else 246 return (lstat(buf, sb)); 247 # endif /* NAMEI_BUG */ 248 } 249 #else 250 #define Lstat Stat 251 #endif /* S_IFLNK */ 252 253 static int 254 Stat(fn, sb) 255 Char *fn; 256 struct stat *sb; 257 { 258 char buf[GLOBBUFLEN]; 259 char *dc = buf; 260 261 while ((*dc++ = *fn++) != '\0') 262 continue; 263 #ifdef NAMEI_BUG 264 { 265 int st; 266 267 st = stat(buf, sb); 268 if (*buf) 269 dc--; 270 return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 271 } 272 #else 273 return (stat(buf, sb)); 274 #endif /* NAMEI_BUG */ 275 } 276 277 static Char * 278 Strchr(str, ch) 279 Char *str; 280 int ch; 281 { 282 do 283 if (*str == ch) 284 return (str); 285 while (*str++); 286 return (NULL); 287 } 288 289 #ifdef DEBUG 290 static void 291 qprintf(s) 292 Char *s; 293 { 294 Char *p; 295 296 for (p = s; *p; p++) 297 printf("%c", *p & 0xff); 298 printf("\n"); 299 for (p = s; *p; p++) 300 printf("%c", *p & M_PROTECT ? '"' : ' '); 301 printf("\n"); 302 for (p = s; *p; p++) 303 printf("%c", *p & M_META ? '_' : ' '); 304 printf("\n"); 305 } 306 #endif /* DEBUG */ 307 308 static int 309 compare(p, q) 310 const ptr_t p, q; 311 { 312 #if defined(NLS) && !defined(NOSTRCOLL) 313 errno = 0; /* strcoll sets errno, another brain-damage */ 314 315 return (strcoll(*(char **) p, *(char **) q)); 316 #else 317 return (strcmp(*(char **) p, *(char **) q)); 318 #endif /* NLS && !NOSTRCOLL */ 319 } 320 321 /* 322 * The main glob() routine: compiles the pattern (optionally processing 323 * quotes), calls glob1() to do the real pattern matching, and finally 324 * sorts the list (unless unsorted operation is requested). Returns 0 325 * if things went well, nonzero if errors occurred. It is not an error 326 * to find no matches. 327 */ 328 int 329 glob(pattern, flags, errfunc, pglob) 330 const char *pattern; 331 int flags; 332 int (*errfunc) __P((const char *, int)); 333 glob_t *pglob; 334 { 335 int err, oldpathc; 336 Char *bufnext, *bufend, *compilebuf, m_not; 337 const unsigned char *compilepat, *patnext; 338 int c, not; 339 Char *qpatnext; 340 #ifdef WIDE_STRINGS 341 Char patbuf[GLOBBUFLEN + MB_LEN_MAX + 1]; 342 #else 343 Char patbuf[GLOBBUFLEN + 1]; 344 #endif 345 int no_match; 346 347 patnext = (const unsigned char *) pattern; 348 if (!(flags & GLOB_APPEND)) { 349 pglob->gl_pathc = 0; 350 pglob->gl_pathv = NULL; 351 if (!(flags & GLOB_DOOFFS)) 352 pglob->gl_offs = 0; 353 } 354 pglob->gl_flags = flags & ~GLOB_MAGCHAR; 355 pglob->gl_errfunc = errfunc; 356 oldpathc = pglob->gl_pathc; 357 pglob->gl_matchc = 0; 358 359 if (pglob->gl_flags & GLOB_ALTNOT) { 360 not = ALTNOT; 361 m_not = M_ALTNOT; 362 } 363 else { 364 not = NOT; 365 m_not = M_NOT; 366 } 367 368 bufnext = patbuf; 369 bufend = bufnext + GLOBBUFLEN; 370 compilebuf = bufnext; 371 compilepat = patnext; 372 373 no_match = *patnext == not; 374 if (no_match) 375 patnext++; 376 377 if (flags & GLOB_QUOTE) { 378 /* Protect the quoted characters */ 379 while (bufnext < bufend && (c = *patnext++) != EOS) { 380 #ifdef WIDE_STRINGS 381 int len; 382 383 len = mblen((const char *)(patnext - 1), MB_LEN_MAX); 384 if (len == -1) 385 mblen(NULL, 0); 386 if (len > 1) { 387 *bufnext++ = (Char) c; 388 while (--len != 0) 389 *bufnext++ = (Char) (*patnext++ | M_PROTECT); 390 } else 391 #endif /* WIDE_STRINGS */ 392 if (c == QUOTE) { 393 if ((c = *patnext++) == EOS) { 394 c = QUOTE; 395 --patnext; 396 } 397 *bufnext++ = (Char) (c | M_PROTECT); 398 } 399 else 400 *bufnext++ = (Char) c; 401 } 402 } 403 else 404 while (bufnext < bufend && (c = *patnext++) != EOS) 405 *bufnext++ = (Char) c; 406 *bufnext = EOS; 407 408 bufnext = patbuf; 409 qpatnext = patbuf; 410 /* we don't need to check for buffer overflow any more */ 411 while ((c = *qpatnext++) != EOS) { 412 switch (c) { 413 case LBRACKET: 414 c = *qpatnext; 415 if (c == not) 416 ++qpatnext; 417 if (*qpatnext == EOS || 418 Strchr(qpatnext + 1, RBRACKET) == NULL) { 419 *bufnext++ = LBRACKET; 420 if (c == not) 421 --qpatnext; 422 break; 423 } 424 pglob->gl_flags |= GLOB_MAGCHAR; 425 *bufnext++ = M_SET; 426 if (c == not) 427 *bufnext++ = m_not; 428 c = *qpatnext++; 429 do { 430 *bufnext++ = CHAR(c); 431 if (*qpatnext == RANGE && 432 (c = qpatnext[1]) != RBRACKET) { 433 *bufnext++ = M_RNG; 434 *bufnext++ = CHAR(c); 435 qpatnext += 2; 436 } 437 } while ((c = *qpatnext++) != RBRACKET); 438 *bufnext++ = M_END; 439 break; 440 case QUESTION: 441 pglob->gl_flags |= GLOB_MAGCHAR; 442 *bufnext++ = M_ONE; 443 break; 444 case STAR: 445 pglob->gl_flags |= GLOB_MAGCHAR; 446 /* collapse adjacent stars to one, to avoid 447 * exponential behavior 448 */ 449 if (bufnext == patbuf || bufnext[-1] != M_ALL) 450 *bufnext++ = M_ALL; 451 break; 452 default: 453 *bufnext++ = CHAR(c); 454 break; 455 } 456 } 457 *bufnext = EOS; 458 #ifdef DEBUG 459 qprintf(patbuf); 460 #endif 461 462 if ((err = glob1(patbuf, pglob, no_match)) != 0) 463 return (err); 464 465 /* 466 * If there was no match we are going to append the pattern 467 * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 468 * and the pattern did not contain any magic characters 469 * GLOB_NOMAGIC is there just for compatibility with csh. 470 */ 471 if (pglob->gl_pathc == oldpathc && 472 ((flags & GLOB_NOCHECK) || 473 ((flags & GLOB_NOMAGIC) && !(pglob->gl_flags & GLOB_MAGCHAR)))) { 474 if (!(flags & GLOB_QUOTE)) { 475 Char *dp = compilebuf; 476 const unsigned char *sp = compilepat; 477 478 while ((*dp++ = *sp++) != '\0') 479 continue; 480 } 481 else { 482 /* 483 * copy pattern, interpreting quotes; this is slightly different 484 * than the interpretation of quotes above -- which should prevail? 485 */ 486 while (*compilepat != EOS) { 487 if (*compilepat == QUOTE) { 488 if (*++compilepat == EOS) 489 --compilepat; 490 } 491 *compilebuf++ = (unsigned char) *compilepat++; 492 } 493 *compilebuf = EOS; 494 } 495 return (globextend(patbuf, pglob)); 496 } 497 else if (!(flags & GLOB_NOSORT) && (pglob->gl_pathc != oldpathc)) 498 qsort((char *) (pglob->gl_pathv + pglob->gl_offs + oldpathc), 499 pglob->gl_pathc - oldpathc, sizeof(char *), 500 (int (*) __P((const void *, const void *))) compare); 501 return (0); 502 } 503 504 static int 505 glob1(pattern, pglob, no_match) 506 Char *pattern; 507 glob_t *pglob; 508 int no_match; 509 { 510 Char pathbuf[GLOBBUFLEN + 1]; 511 512 /* 513 * a null pathname is invalid -- POSIX 1003.1 sect. 2.4. 514 */ 515 if (*pattern == EOS) 516 return (0); 517 return (glob2(pathbuf, pathbuf, pattern, pglob, no_match)); 518 } 519 520 /* 521 * functions glob2 and glob3 are mutually recursive; there is one level 522 * of recursion for each segment in the pattern that contains one or 523 * more meta characters. 524 */ 525 static int 526 glob2(pathbuf, pathend, pattern, pglob, no_match) 527 Char *pathbuf, *pathend, *pattern; 528 glob_t *pglob; 529 int no_match; 530 { 531 struct stat sbuf; 532 int anymeta; 533 Char *p, *q; 534 535 /* 536 * loop over pattern segments until end of pattern or until segment with 537 * meta character found. 538 */ 539 anymeta = 0; 540 for (;;) { 541 if (*pattern == EOS) { /* end of pattern? */ 542 *pathend = EOS; 543 544 if (Lstat(pathbuf, &sbuf)) 545 return (0); 546 547 if (((pglob->gl_flags & GLOB_MARK) && 548 pathend[-1] != SEP) && 549 (S_ISDIR(sbuf.st_mode) 550 #ifdef S_IFLNK 551 || (S_ISLNK(sbuf.st_mode) && 552 (Stat(pathbuf, &sbuf) == 0) && 553 S_ISDIR(sbuf.st_mode)) 554 #endif 555 )) { 556 *pathend++ = SEP; 557 *pathend = EOS; 558 } 559 ++pglob->gl_matchc; 560 return (globextend(pathbuf, pglob)); 561 } 562 563 /* find end of next segment, copy tentatively to pathend */ 564 q = pathend; 565 p = pattern; 566 while (*p != EOS && *p != SEP) { 567 if (ismeta(*p)) 568 anymeta = 1; 569 *q++ = *p++; 570 } 571 572 if (!anymeta) { /* no expansion, do next segment */ 573 pathend = q; 574 pattern = p; 575 while (*pattern == SEP) 576 *pathend++ = *pattern++; 577 } 578 else /* need expansion, recurse */ 579 return (glob3(pathbuf, pathend, pattern, p, pglob, no_match)); 580 } 581 /* NOTREACHED */ 582 } 583 584 585 static int 586 glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match) 587 Char *pathbuf, *pathend, *pattern, *restpattern; 588 glob_t *pglob; 589 int no_match; 590 { 591 DIR *dirp; 592 struct dirent *dp; 593 int err; 594 Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT; 595 char cpathbuf[GLOBBUFLEN], *ptr;; 596 597 *pathend = EOS; 598 errno = 0; 599 600 if (!(dirp = Opendir(pathbuf))) { 601 /* todo: don't call for ENOENT or ENOTDIR? */ 602 for (ptr = cpathbuf; (*ptr++ = (char) *pathbuf++) != EOS;) 603 continue; 604 if ((pglob->gl_errfunc && (*pglob->gl_errfunc) (cpathbuf, errno)) || 605 (pglob->gl_flags & GLOB_ERR)) 606 return (GLOB_ABEND); 607 else 608 return (0); 609 } 610 611 err = 0; 612 613 /* search directory for matching names */ 614 while ((dp = readdir(dirp)) != NULL) { 615 unsigned char *sc; 616 Char *dc; 617 618 /* initial DOT must be matched literally */ 619 if (dp->d_name[0] == DOT && *pattern != DOT) 620 continue; 621 for (sc = (unsigned char *) dp->d_name, dc = pathend; 622 (*dc++ = *sc++) != '\0';) 623 continue; 624 if (match(pathend, pattern, restpattern, (int) m_not) == no_match) { 625 *pathend = EOS; 626 continue; 627 } 628 err = glob2(pathbuf, --dc, restpattern, pglob, no_match); 629 if (err) 630 break; 631 } 632 /* todo: check error from readdir? */ 633 (void) closedir(dirp); 634 return (err); 635 } 636 637 638 /* 639 * Extend the gl_pathv member of a glob_t structure to accomodate a new item, 640 * add the new item, and update gl_pathc. 641 * 642 * This assumes the BSD realloc, which only copies the block when its size 643 * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 644 * behavior. 645 * 646 * Return 0 if new item added, error code if memory couldn't be allocated. 647 * 648 * Invariant of the glob_t structure: 649 * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 650 * gl_pathv points to (gl_offs + gl_pathc + 1) items. 651 */ 652 static int 653 globextend(path, pglob) 654 Char *path; 655 glob_t *pglob; 656 { 657 char **pathv; 658 int i; 659 unsigned int newsize; 660 char *copy; 661 Char *p; 662 663 newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 664 pathv = (char **) (pglob->gl_pathv ? 665 xrealloc((ptr_t) pglob->gl_pathv, (size_t) newsize) : 666 xmalloc((size_t) newsize)); 667 if (pathv == NULL) 668 return (GLOB_NOSPACE); 669 670 if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 671 /* first time around -- clear initial gl_offs items */ 672 pathv += pglob->gl_offs; 673 for (i = pglob->gl_offs; --i >= 0;) 674 *--pathv = NULL; 675 } 676 pglob->gl_pathv = pathv; 677 678 for (p = path; *p++;) 679 continue; 680 if ((copy = (char *) xmalloc((size_t) (p - path))) != NULL) { 681 char *dc = copy; 682 Char *sc = path; 683 684 while ((*dc++ = *sc++) != '\0') 685 continue; 686 pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 687 } 688 pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 689 return ((copy == NULL) ? GLOB_NOSPACE : 0); 690 } 691 692 693 static size_t 694 One_mbtowc(NLSChar *pwc, const Char *s, size_t n) 695 { 696 #ifdef WIDE_STRINGS 697 char buf[MB_LEN_MAX], *p; 698 699 if (n > MB_LEN_MAX) 700 n = MB_LEN_MAX; 701 p = buf; 702 while (p < buf + n && (*p++ = CHAR(*s++)) != 0) 703 ; 704 return one_mbtowc(pwc, buf, n); 705 #else 706 return NLSFrom(s, n, pwc); 707 #endif 708 } 709 710 /* 711 * pattern matching function for filenames. Each occurrence of the * 712 * pattern causes a recursion level. 713 */ 714 static int 715 match(name, pat, patend, m_not) 716 Char *name, *pat, *patend; 717 int m_not; 718 { 719 int ok, negate_range; 720 Char c, k; 721 722 while (pat < patend) { 723 size_t lwk; 724 NLSChar wc, wk; 725 726 USE(k); 727 c = *pat; /* Only for M_MASK bits */ 728 pat += One_mbtowc(&wc, pat, MB_LEN_MAX); 729 lwk = One_mbtowc(&wk, name, MB_LEN_MAX); 730 switch (c & M_MASK) { 731 case M_ALL: 732 if (pat == patend) 733 return (1); 734 for (;;) { 735 if (match(name, pat, patend, m_not)) 736 return (1); 737 if (*name == EOS) 738 break; 739 name += lwk; 740 lwk = One_mbtowc(&wk, name, MB_LEN_MAX); 741 } 742 return (0); 743 case M_ONE: 744 if (*name == EOS) 745 return (0); 746 name += lwk; 747 break; 748 case M_SET: 749 ok = 0; 750 if (*name == EOS) 751 return (0); 752 name += lwk; 753 if ((negate_range = ((*pat & M_MASK) == m_not)) != 0) 754 ++pat; 755 while ((*pat & M_MASK) != M_END) { 756 pat += One_mbtowc(&wc, pat, MB_LEN_MAX); 757 if ((*pat & M_MASK) == M_RNG) { 758 NLSChar wc2; 759 760 pat++; 761 pat += One_mbtowc(&wc2, pat, MB_LEN_MAX); 762 if (globcharcoll(wc, wk, 0) <= 0 && 763 globcharcoll(wk, wc2, 0) <= 0) 764 ok = 1; 765 } else if (wc == wk) 766 ok = 1; 767 } 768 pat += One_mbtowc(&wc, pat, MB_LEN_MAX); 769 if (ok == negate_range) 770 return (0); 771 break; 772 default: 773 name += lwk; 774 if (samecase(wk) != samecase(wc)) 775 return (0); 776 break; 777 } 778 } 779 return (*name == EOS); 780 } 781 782 /* free allocated data belonging to a glob_t structure */ 783 void 784 globfree(pglob) 785 glob_t *pglob; 786 { 787 int i; 788 char **pp; 789 790 if (pglob->gl_pathv != NULL) { 791 pp = pglob->gl_pathv + pglob->gl_offs; 792 for (i = pglob->gl_pathc; i--; ++pp) 793 if (*pp) 794 xfree((ptr_t) *pp), *pp = NULL; 795 xfree((ptr_t) pglob->gl_pathv), pglob->gl_pathv = NULL; 796 } 797 } 798