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