1: #undef DEBUG 2: /* 3: * Copyright (c) 1989 The Regents of the University of California. 4: * All rights reserved. 5: * 6: * This code is derived from software contributed to Berkeley by 7: * Guido van Rossum. 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 "config.h" 38: #if defined(LIBC_SCCS) && !defined(lint) 39: static char sccsid[] = "@(#)glob.c 5.12 (Berkeley) 6/24/91"; 40: #endif /* LIBC_SCCS and not lint */ 41: /* 42: * Glob: the interface is a superset of the one defined in POSIX 1003.2, 43: * draft 9. 44: * 45: * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 46: * 47: * Optional extra services, controlled by flags not defined by POSIX: 48: * 49: * GLOB_QUOTE: 50: * Escaping convention: \ inhibits any special meaning the following 51: * character might have (except \ at end of string is retained). 52: * GLOB_MAGCHAR: 53: * Set in gl_flags if pattern contained a globbing character. 54: * GLOB_ALTNOT: 55: * Use ^ instead of ! for "not". 56: * gl_matchc: 57: * Number of matches in the current invocation of glob. 58: */ 59: 60: #ifdef notdef 61: #include <sys/types.h> 62: #include <sys/param.h> 63: #include <sys/stat.h> 64: #include <dirent.h> 65: #include <ctype.h> 66: typedef void * ptr_t; 67: #endif 68: 69: #include "sh.h" 70: #undef QUOTE 71: #undef TILDE 72: #undef META 73: #undef CHAR 74: #undef ismeta 75: #undef Strchr 76: 77: #include <glob.h> 78: 79: #ifndef S_ISDIR 80: #define S_ISDIR(a) (((a) & S_IFMT) == S_IFDIR) 81: #endif 82: 83: #if !defined(S_ISLNK) && defined(S_IFLNK) 84: #define S_ISLNK(a) (((a) & S_IFMT) == S_IFLNK) 85: #endif 86: 87: #if !defined(S_ISLNK) && !defined(lstat) 88: #define lstat stat 89: #endif 90: 91: #ifdef notdef 92: typedef unsigned short Char; 93: #endif 94: 95: static int glob1 __P((Char *, glob_t *, int)); 96: static int glob2 __P((Char *, Char *, Char *, glob_t *, int)); 97: static int glob3 __P((Char *, Char *, Char *, Char *, 98: glob_t *, int)); 99: static int globextend __P((Char *, glob_t *)); 100: static int match __P((Char *, Char *, Char *, int)); 101: static int compare __P((const void *, const void *)); 102: static DIR *Opendir __P((Char *)); 103: #ifdef S_IFLNK 104: static int Lstat __P((Char *, struct stat *)); 105: #endif 106: static Char *Strchr __P((Char *, int)); 107: #ifdef DEBUG 108: static void qprintf __P((Char *)); 109: #endif 110: 111: #define DOLLAR '$' 112: #define DOT '.' 113: #define EOS '\0' 114: #define LBRACKET '[' 115: #define NOT '!' 116: #define ALTNOT '^' 117: #define QUESTION '?' 118: #define QUOTE '\\' 119: #define RANGE '-' 120: #define RBRACKET ']' 121: #define SEP '/' 122: #define STAR '*' 123: #define TILDE '~' 124: #define UNDERSCORE '_' 125: 126: #ifdef SHORT_STRINGS 127: #define M_META 0x8000 128: #define M_PROTECT 0x4000 129: #define M_MASK 0xffff 130: #define M_ASCII 0x00ff 131: #else 132: #define M_META 0x0080 /* 0200 */ 133: #define M_PROTECT 0x007f /* 0177 0300 */ 134: #define M_MASK 0x00ff /* 0377 */ 135: #define M_ASCII 0x007f /* 0177 */ 136: #endif /* SHORT_STRINGS */ 137: 138: #define CHAR(c) ((c)&M_ASCII) 139: #define META(c) ((c)|M_META) 140: #define M_ALL META('*') 141: #define M_END META(']') 142: #define M_NOT META('!') 143: #define M_ALTNOT META('^') 144: #define M_ONE META('?') 145: #define M_RNG META('-') 146: #define M_SET META('[') 147: #define ismeta(c) (((c)&M_META) != 0) 148: 149: /* 150: * Need to dodge two kernel bugs: 151: * opendir("") != opendir(".") 152: * NAMEI_BUG: on plain files trailing slashes are ignored in some kernels. 153: * POSIX specifies that they should be ignored in directories. 154: */ 155: 156: static DIR * 157: Opendir(str) 158: register Char *str; 159: { 160: char buf[MAXPATHLEN]; 161: register char *dc = buf; 162: 163: if (!*str) 164: return (opendir(".")); 165: while (*dc++ = *str++); 166: return (opendir(buf)); 167: } 168: 169: #ifdef S_IFLNK 170: static int 171: Lstat(fn, sb) 172: register Char *fn; 173: struct stat *sb; 174: { 175: char buf[MAXPATHLEN]; 176: register char *dc = buf; 177: 178: while (*dc++ = *fn++); 179: # ifdef NAMEI_BUG 180: { 181: int st; 182: 183: st = lstat(buf, sb); 184: if (*buf) 185: dc--; 186: return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 187: } 188: # else 189: return (lstat(buf, sb)); 190: # endif /* NAMEI_BUG */ 191: } 192: #else 193: #define Lstat Stat 194: #endif /* S_IFLNK */ 195: 196: static int 197: Stat(fn, sb) 198: register Char *fn; 199: struct stat *sb; 200: { 201: char buf[MAXPATHLEN]; 202: register char *dc = buf; 203: 204: while (*dc++ = *fn++); 205: #ifdef NAMEI_BUG 206: { 207: int st; 208: 209: st = lstat(buf, sb); 210: if (*buf) 211: dc--; 212: return (*--dc == '/' && !S_ISDIR(sb->st_mode) ? -1 : st); 213: } 214: #else 215: return (stat(buf, sb)); 216: #endif /* NAMEI_BUG */ 217: } 218: 219: static Char * 220: Strchr(str, ch) 221: Char *str; 222: int ch; 223: { 224: do 225: if (*str == ch) 226: return (str); 227: while (*str++); 228: return (NULL); 229: } 230: 231: #ifdef DEBUG 232: static void 233: qprintf(s) 234: Char *s; 235: { 236: Char *p; 237: 238: for (p = s; *p; p++) 239: printf("%c", *p & 0xff); 240: printf("\n"); 241: for (p = s; *p; p++) 242: printf("%c", *p & M_PROTECT ? '"' : ' '); 243: printf("\n"); 244: for (p = s; *p; p++) 245: printf("%c", *p & M_META ? '_' : ' '); 246: printf("\n"); 247: } 248: #endif /* DEBUG */ 249: 250: static int 251: compare(p, q) 252: const void *p, *q; 253: { 254: return (strcmp(*(char **) p, *(char **) q)); 255: } 256: 257: /* 258: * The main glob() routine: comp_s the pattern (optionally processing 259: * quotes), calls glob1() to do the real pattern matching, and finally 260: * sorts the list (unless unsorted operation is requested). Returns 0 261: * if things went well, nonzero if errors occurred. It is not an error 262: * to find no matches. 263: */ 264: int 265: glob(pattern, flags, errfunc, pglob) 266: const char *pattern; 267: int flags; 268: int (*errfunc) __P((char *, int)); 269: glob_t *pglob; 270: { 271: int err, o_pthc; 272: Char *bufnext, *bufend, *comp_buf, m_not; 273: const unsigned char *comp_pat, *patnext; 274: int c, not; 275: Char patbuf[MAXPATHLEN + 1], *qpatnext; 276: int no_match; 277: 278: patnext = (unsigned char *) pattern; 279: if (!(flags & GLOB_APPEND)) { 280: pglob->gl_p_c = 0; 281: pglob->gl_p_v = NULL; 282: if (!(flags & GLOB_DOOFFS)) 283: pglob->gl_offs = 0; 284: } 285: pglob->gl_flags = flags & ~GLOB_MAGCHAR; 286: pglob->gl_errfunc = errfunc; 287: o_pthc = pglob->gl_p_c; 288: pglob->gl_matchc = 0; 289: 290: if (pglob->gl_flags & GLOB_ALTNOT) { 291: not = ALTNOT; 292: m_not = M_ALTNOT; 293: } 294: else { 295: not = NOT; 296: m_not = M_NOT; 297: } 298: 299: no_match = *patnext == not; 300: if (no_match) 301: patnext++; 302: 303: bufnext = patbuf; 304: bufend = bufnext + MAXPATHLEN; 305: comp_buf = bufnext; 306: comp_pat = patnext; 307: if (flags & GLOB_QUOTE) { 308: /* Protect the quoted characters */ 309: while (bufnext < bufend && (c = *patnext++) != EOS) 310: if (c == QUOTE) { 311: if ((c = *patnext++) == EOS) { 312: c = QUOTE; 313: --patnext; 314: } 315: *bufnext++ = c | M_PROTECT; 316: } 317: else 318: *bufnext++ = c; 319: } 320: else 321: while (bufnext < bufend && (c = *patnext++) != EOS) 322: *bufnext++ = c; 323: *bufnext = EOS; 324: 325: bufnext = patbuf; 326: qpatnext = patbuf; 327: /* we don't need to check for buffer overflow any more */ 328: while ((c = *qpatnext++) != EOS) { 329: switch (c) { 330: case LBRACKET: 331: pglob->gl_flags |= GLOB_MAGCHAR; 332: c = *qpatnext; 333: if (c == not) 334: ++qpatnext; 335: if (*qpatnext == EOS || 336: Strchr(qpatnext + 1, RBRACKET) == NULL) { 337: *bufnext++ = LBRACKET; 338: if (c == not) 339: --qpatnext; 340: break; 341: } 342: *bufnext++ = M_SET; 343: if (c == not) 344: *bufnext++ = m_not; 345: c = *qpatnext++; 346: do { 347: *bufnext++ = CHAR(c); 348: if (*qpatnext == RANGE && 349: (c = qpatnext[1]) != RBRACKET) { 350: *bufnext++ = M_RNG; 351: *bufnext++ = CHAR(c); 352: qpatnext += 2; 353: } 354: } while ((c = *qpatnext++) != RBRACKET); 355: *bufnext++ = M_END; 356: break; 357: case QUESTION: 358: pglob->gl_flags |= GLOB_MAGCHAR; 359: *bufnext++ = M_ONE; 360: break; 361: case STAR: 362: pglob->gl_flags |= GLOB_MAGCHAR; 363: *bufnext++ = M_ALL; 364: break; 365: default: 366: *bufnext++ = CHAR(c); 367: break; 368: } 369: } 370: *bufnext = EOS; 371: #ifdef DEBUG 372: qprintf(patbuf); 373: #endif 374: 375: if ((err = glob1(patbuf, pglob, no_match)) != 0) 376: return (err); 377: 378: if (pglob->gl_p_c == o_pthc && flags & GLOB_NOCHECK) { 379: if (!(flags & GLOB_QUOTE)) { 380: Char *dp = comp_buf; 381: const unsigned char *sp = comp_pat; 382: 383: while (*dp++ = *sp++); 384: } 385: else { 386: /* 387: * copy pattern, interpreting quotes; this is slightly different 388: * than the interpretation of quotes above -- which should prevail? 389: */ 390: while (*comp_pat != EOS) { 391: if (*comp_pat == QUOTE) { 392: if (*++comp_pat == EOS) 393: --comp_pat; 394: } 395: *comp_buf++ = (unsigned char) *comp_pat++; 396: } 397: *comp_buf = EOS; 398: } 399: return (globextend(patbuf, pglob)); 400: } 401: else if (!(flags & GLOB_NOSORT)) 402: qsort((char *) (pglob->gl_p_v + pglob->gl_offs + o_pthc), 403: pglob->gl_p_c - o_pthc, sizeof(char *), compare); 404: return (0); 405: } 406: 407: static int 408: glob1(pattern, pglob, no_match) 409: Char *pattern; 410: glob_t *pglob; 411: int no_match; 412: { 413: Char pathbuf[MAXPATHLEN + 1]; 414: 415: /* 416: * a null pathname is invalid -- POSIX 1003.1 sect. 2.4. 417: */ 418: if (*pattern == EOS) 419: return (0); 420: return (glob2(pathbuf, pathbuf, pattern, pglob, no_match)); 421: } 422: 423: /* 424: * functions glob2 and glob3 are mutually recursive; there is one level 425: * of recursion for each segment in the pattern that contains one or 426: * more meta characters. 427: */ 428: static int 429: glob2(pathbuf, pathend, pattern, pglob, no_match) 430: Char *pathbuf, *pathend, *pattern; 431: glob_t *pglob; 432: int no_match; 433: { 434: struct stat sbuf; 435: int anymeta; 436: Char *p, *q; 437: 438: /* 439: * loop over pattern segments until end of pattern or until segment with 440: * meta character found. 441: */ 442: anymeta = 0; 443: for (;;) { 444: if (*pattern == EOS) { /* end of pattern? */ 445: *pathend = EOS; 446: if (Lstat(pathbuf, &sbuf)) 447: return (0); 448: 449: if (((pglob->gl_flags & GLOB_MARK) && 450: pathend[-1] != SEP) && 451: (S_ISDIR(sbuf.st_mode) 452: #ifdef S_IFLNK 453: || (S_ISLNK(sbuf.st_mode) && 454: (Stat(pathbuf, &sbuf) == 0) && 455: S_ISDIR(sbuf.st_mode)) 456: #endif 457: )) { 458: *pathend++ = SEP; 459: *pathend = EOS; 460: } 461: ++pglob->gl_matchc; 462: return (globextend(pathbuf, pglob)); 463: } 464: 465: /* find end of next segment, copy tentatively to pathend */ 466: q = pathend; 467: p = pattern; 468: while (*p != EOS && *p != SEP) { 469: if (ismeta(*p)) 470: anymeta = 1; 471: *q++ = *p++; 472: } 473: 474: if (!anymeta) { /* no expansion, do next segment */ 475: pathend = q; 476: pattern = p; 477: while (*pattern == SEP) 478: *pathend++ = *pattern++; 479: } 480: else /* need expansion, recurse */ 481: return (glob3(pathbuf, pathend, pattern, p, pglob, no_match)); 482: } 483: /* NOTREACHED */ 484: } 485: 486: 487: static int 488: glob3(pathbuf, pathend, pattern, restpattern, pglob, no_match) 489: Char *pathbuf, *pathend, *pattern, *restpattern; 490: glob_t *pglob; 491: int no_match; 492: { 493: extern int errno; 494: DIR *dirp; 495: struct dirent *dp; 496: int err; 497: Char m_not = (pglob->gl_flags & GLOB_ALTNOT) ? M_ALTNOT : M_NOT; 498: 499: *pathend = EOS; 500: errno = 0; 501: 502: if (!(dirp = Opendir(pathbuf))) 503: /* todo: don't call for ENOENT or ENOTDIR? */ 504: if (pglob->gl_errfunc && 505: (*pglob->gl_errfunc) (pathbuf, errno) || 506: (pglob->gl_flags & GLOB_ERR)) 507: return (GLOB_ABEND); 508: else 509: return (0); 510: 511: err = 0; 512: 513: /* search directory for matching names */ 514: while ((dp = readdir(dirp))) { 515: register unsigned char *sc; 516: register Char *dc; 517: 518: /* initial DOT must be matched literally */ 519: if (dp->d_name[0] == DOT && *pattern != DOT) 520: continue; 521: for (sc = (unsigned char *) dp->d_name, dc = pathend; *dc++ = *sc++;); 522: if (match(pathend, pattern, restpattern, m_not) == no_match) { 523: *pathend = EOS; 524: continue; 525: } 526: err = glob2(pathbuf, --dc, restpattern, pglob, no_match); 527: if (err) 528: break; 529: } 530: /* todo: check error from readdir? */ 531: (void) closedir(dirp); 532: return (err); 533: } 534: 535: 536: /* 537: * Extend the gl_p_v member of a glob_t structure to accomodate a new item, 538: * add the new item, and update gl_p_c. 539: * 540: * This assumes the BSD realloc, which only copies the block when its size 541: * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 542: * behavior. 543: * 544: * Return 0 if new item added, error code if memory couldn't be allocated. 545: * 546: * Invariant of the glob_t structure: 547: * Either gl_p_c is zero and gl_p_v is NULL; or gl_p_c > 0 and 548: * gl_p_v points to (gl_offs + gl_p_c + 1) items. 549: */ 550: #define JPN 551: #ifndef JPN 552: static int 553: globextend(path, pglob) 554: Char *path; 555: glob_t *pglob; 556: { 557: register char **pathv; 558: register int i; 559: unsigned int newsize; 560: char *copy; 561: Char *p; 562: 563: newsize = sizeof(*pathv) * (2 + pglob->gl_p_c + pglob->gl_offs); 564: pathv = (char **) (pglob->gl_p_v ? 565: realloc((ptr_t) pglob->gl_p_v, newsize) : 566: malloc((size_t) newsize)); 567: if (pathv == NULL) 568: return (GLOB_NOSPACE); 569: 570: if (pglob->gl_p_v == NULL && pglob->gl_offs > 0) { 571: /* first time around -- clear initial gl_offs items */ 572: pathv += pglob->gl_offs; 573: for (i = pglob->gl_offs; --i >= 0;) 574: *--pathv = NULL; 575: } 576: pglob->gl_p_v = pathv; 577: 578: for (p = path; *p++;); 579: if ((copy = (char *) malloc((size_t) (p - path))) != NULL) { 580: register char *dc = copy; 581: register Char *sc = path; 582: 583: while (*dc++ = *sc++); 584: pathv[pglob->gl_offs + pglob->gl_p_c++] = copy; 585: } 586: pathv[pglob->gl_offs + pglob->gl_p_c] = NULL; 587: return ((copy == NULL) ? GLOB_NOSPACE : 0); 588: } 589: #else 590: /* 591: * jpn: pdp11 version to get around quadradic behavior of above version 592: * by managing the increments of storage allocation directly 593: * note: gl_offs not used in tcsh6.00.00 594: */ 595: #define NFIRST 100 596: #define NINC 50 597: 598: static int 599: globextend(path, pglob) 600: Char *path; 601: glob_t *pglob; 602: { 603: register char **pathv; 604: register char **opathv; 605: register int i; 606: unsigned getmem; 607: static unsigned int globsize = 0; 608: static unsigned int pathslots = 0; 609: 610: if (pglob->gl_p_c == 0) { 611: /* first pass; allow for NULL at end of array */ 612: getmem = sizeof(*pathv) * (1 + NFIRST + pglob->gl_offs); 613: pathv = (char **) malloc((size_t) getmem); 614: if (pathv == NULL) 615: return (GLOB_NOSPACE); 616: globsize = getmem; 617: #undef DEBUG 618: #ifdef DEBUG 619: xprintf("new gl_p_c globsize=%d\n",globsize); 620: #endif DEBUG 621: pathslots = NFIRST; 622: pglob->gl_p_v = pathv; 623: if (pglob->gl_offs > 0) { 624: /* first time around -- clear initial gl_offs items */ 625: pathv += pglob->gl_offs; 626: for (i = pglob->gl_offs; --i >= 0;) 627: *--pathv = NULL; 628: } 629: } else if (pglob->gl_p_c >= pathslots) { 630: /* high water, increment needed */ 631: char **npp; 632: char **opp; 633: opathv = pglob->gl_p_v; 634: getmem = globsize + (NINC * sizeof(*pathv)); 635: pathv = (char **) malloc((size_t) getmem); 636: if (pathv == NULL) 637: return (GLOB_NOSPACE); 638: globsize = getmem; 639: #ifdef DEBUG 640: xprintf("new increment, globsize=%d\n",globsize); 641: #endif DEBUG 642: pathslots += NINC; 643: 644: /* copy slots including gl_offs if any, whether or not NULL */ 645: i = pglob->gl_offs + pglob->gl_p_c ; 646: for( npp=pathv, opp=opathv; i > 0 ; i--) { 647: *npp++ = *opp++; 648: } 649: *npp = NULL; /* no assumption that slots are NULL */ 650: pglob->gl_p_v = pathv; 651: xfree(opathv); /* free the old base pointer; data has been copied */ 652: } else { 653: /* still room for more */ 654: pathv = pglob->gl_p_v; 655: #ifdef DEBUG 656: xprintf("same gl_p_v globsize=%d\n",globsize); 657: #endif DEBUG 658: } 659: 660: /* now that a free slot has been assured, save the path there */ 661: { 662: register Char *p; 663: char *copy; 664: register char *dc; 665: register Char *sc; 666: int i; 667: 668: for (p = path; *p++;); 669: i = p - path; 670: copy = (char *) malloc((size_t) (p - path)); 671: if (copy == NULL) 672: return (GLOB_NOSPACE); 673: dc = copy; 674: sc = path; 675: while (*dc++ = *sc++); 676: pathv[pglob->gl_offs + pglob->gl_p_c] = copy; 677: pglob->gl_p_c++; 678: pathv[pglob->gl_offs + pglob->gl_p_c] = NULL; 679: #ifdef DEBUG 680: xprintf("gl_p_c= %d\n",pglob->gl_p_c); 681: #endif DEBUG 682: #ifdef DEBUG2 683: xprintf("path is %s\n",path); 684: xprintf("malloc size is %d\n",i); 685: xprintf("copy is %s\n",copy); 686: #endif DEBUG2 687: } 688: return (0); 689: } 690: #endif /* pdp11 */ 691: 692: /* 693: * pattern matching function for filenames. Each occurrence of the * 694: * pattern causes a recursion level. 695: */ 696: static int 697: match(name, pat, patend, m_not) 698: register Char *name, *pat, *patend; 699: int m_not; 700: { 701: int ok, negate_range; 702: Char c, k; 703: 704: while (pat < patend) { 705: c = *pat++; 706: switch (c & M_MASK) { 707: case M_ALL: 708: if (pat == patend) 709: return (1); 710: for (; *name != EOS; ++name) { 711: if (match(name, pat, patend, m_not)) 712: return (1); 713: } 714: return (0); 715: case M_ONE: 716: if (*name++ == EOS) 717: return (0); 718: break; 719: case M_SET: 720: ok = 0; 721: k = *name++; 722: if (negate_range = ((*pat & M_MASK) == m_not)) 723: ++pat; 724: while (((c = *pat++) & M_MASK) != M_END) { 725: if ((*pat & M_MASK) == M_RNG) { 726: if (c <= k && k <= pat[1]) 727: ok = 1; 728: pat += 2; 729: } 730: else if (c == k) 731: ok = 1; 732: } 733: if (ok == negate_range) 734: return (0); 735: break; 736: default: 737: if (*name++ != c) 738: return (0); 739: break; 740: } 741: } 742: return (*name == EOS); 743: } 744: 745: /* free allocated data belonging to a glob_t structure */ 746: void 747: globfree(pglob) 748: glob_t *pglob; 749: { 750: register int i; 751: register char **pp; 752: 753: if (pglob->gl_p_v != NULL) { 754: pp = pglob->gl_p_v + pglob->gl_offs; 755: for (i = pglob->gl_p_c; i--; ++pp) 756: if (*pp) 757: xfree((ptr_t) * pp); 758: xfree((ptr_t) pglob->gl_p_v); 759: pglob->gl_p_c = 0; /* jpn */ 760: } 761: #ifdef DEBUG 762: xprintf("did globfree\n"); 763: #endif 764: }