140087Sbostic /* 240087Sbostic * Copyright (c) 1989 The Regents of the University of California. 340087Sbostic * All rights reserved. 440087Sbostic * 540087Sbostic * This code is derived from software contributed to Berkeley by 640087Sbostic * Guido van Rossum. 740087Sbostic * 842625Sbostic * %sccs.include.redist.c% 940087Sbostic */ 1040087Sbostic 1140087Sbostic #if defined(LIBC_SCCS) && !defined(lint) 12*57897Sbostic static char sccsid[] = "@(#)glob.c 5.19 (Berkeley) 02/10/93"; 1340087Sbostic #endif /* LIBC_SCCS and not lint */ 1440087Sbostic 1540087Sbostic /* 1650050Sbostic * glob(3) -- a superset of the one defined in POSIX 1003.2. 1740087Sbostic * 1840087Sbostic * The [!...] convention to negate a range is supported (SysV, Posix, ksh). 1940087Sbostic * 2040087Sbostic * Optional extra services, controlled by flags not defined by POSIX: 2147590Sbostic * 2247590Sbostic * GLOB_QUOTE: 2347590Sbostic * Escaping convention: \ inhibits any special meaning the following 2447590Sbostic * character might have (except \ at end of string is retained). 2547590Sbostic * GLOB_MAGCHAR: 2648540Sbostic * Set in gl_flags if pattern contained a globbing character. 2750420Sbostic * GLOB_NOMAGIC: 2850420Sbostic * Same as GLOB_NOCHECK, but it will only append pattern if it did 2950420Sbostic * not contain any magic characters. [Used in csh style globbing] 3056942Smckusick * GLOB_ALTDIRFUNC: 3156942Smckusick * Use alternately specified directory access functions. 32*57897Sbostic * GLOB_TILDE: 33*57897Sbostic * expand ~user/foo to the /home/dir/of/user/foo 34*57897Sbostic * GLOB_BRACE: 35*57897Sbostic * expand {1,2}{a,b} to 1a 1b 2a 2b 3647590Sbostic * gl_matchc: 3747590Sbostic * Number of matches in the current invocation of glob. 3840087Sbostic */ 3940087Sbostic 4040087Sbostic #include <sys/param.h> 4140087Sbostic #include <sys/stat.h> 42*57897Sbostic 43*57897Sbostic #include <ctype.h> 4440087Sbostic #include <dirent.h> 45*57897Sbostic #include <errno.h> 4640087Sbostic #include <glob.h> 47*57897Sbostic #include <pwd.h> 4840087Sbostic #include <stdio.h> 4946597Sdonn #include <stdlib.h> 50*57897Sbostic #include <string.h> 51*57897Sbostic #include <unistd.h> 5240087Sbostic 5340087Sbostic #define DOLLAR '$' 5440087Sbostic #define DOT '.' 5540087Sbostic #define EOS '\0' 5640087Sbostic #define LBRACKET '[' 5740087Sbostic #define NOT '!' 5840087Sbostic #define QUESTION '?' 5940087Sbostic #define QUOTE '\\' 6040087Sbostic #define RANGE '-' 6140087Sbostic #define RBRACKET ']' 6240087Sbostic #define SEP '/' 6340087Sbostic #define STAR '*' 6440087Sbostic #define TILDE '~' 6540087Sbostic #define UNDERSCORE '_' 66*57897Sbostic #define LBRACE '{' 67*57897Sbostic #define RBRACE '}' 68*57897Sbostic #define SLASH '/' 69*57897Sbostic #define COMMA ',' 7040087Sbostic 71*57897Sbostic #ifndef DEBUG 72*57897Sbostic 7350049Sbostic #define M_QUOTE 0x8000 7450049Sbostic #define M_PROTECT 0x4000 7548540Sbostic #define M_MASK 0xffff 7650121Sbostic #define M_ASCII 0x00ff 7748540Sbostic 78*57897Sbostic typedef u_short Char; 79*57897Sbostic 80*57897Sbostic #else 81*57897Sbostic 82*57897Sbostic #define M_QUOTE 0x80 83*57897Sbostic #define M_PROTECT 0x40 84*57897Sbostic #define M_MASK 0xff 85*57897Sbostic #define M_ASCII 0x7f 86*57897Sbostic 87*57897Sbostic typedef char Char; 88*57897Sbostic 89*57897Sbostic #endif 90*57897Sbostic 91*57897Sbostic 92*57897Sbostic #define CHAR(c) ((Char)((c)&M_ASCII)) 93*57897Sbostic #define META(c) ((Char)((c)|M_QUOTE)) 9440087Sbostic #define M_ALL META('*') 9540087Sbostic #define M_END META(']') 9640087Sbostic #define M_NOT META('!') 9740087Sbostic #define M_ONE META('?') 9840087Sbostic #define M_RNG META('-') 9940087Sbostic #define M_SET META('[') 10050049Sbostic #define ismeta(c) (((c)&M_QUOTE) != 0) 10140087Sbostic 10250049Sbostic 10350050Sbostic static int compare __P((const void *, const void *)); 104*57897Sbostic static void g_Ctoc __P((const Char *, char *)); 10556942Smckusick static int g_lstat __P((Char *, struct stat *, glob_t *)); 10656942Smckusick static DIR *g_opendir __P((Char *, glob_t *)); 10750050Sbostic static Char *g_strchr __P((Char *, int)); 108*57897Sbostic #ifdef notdef 109*57897Sbostic static Char *g_strcat __P((Char *, const Char *)); 110*57897Sbostic #endif 11156942Smckusick static int g_stat __P((Char *, struct stat *, glob_t *)); 112*57897Sbostic static int glob0 __P((const Char *, glob_t *)); 11350050Sbostic static int glob1 __P((Char *, glob_t *)); 11450050Sbostic static int glob2 __P((Char *, Char *, Char *, glob_t *)); 11550050Sbostic static int glob3 __P((Char *, Char *, Char *, Char *, glob_t *)); 116*57897Sbostic static int globextend __P((const Char *, glob_t *)); 117*57897Sbostic static const Char * globtilde __P((const Char *, Char *, glob_t *)); 118*57897Sbostic static int globexp1 __P((const Char *, glob_t *)); 119*57897Sbostic static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); 12050050Sbostic static int match __P((Char *, Char *, Char *)); 12150049Sbostic #ifdef DEBUG 122*57897Sbostic static void qprintf __P((const char *, Char *)); 12350049Sbostic #endif 12450049Sbostic 125*57897Sbostic int 12640087Sbostic glob(pattern, flags, errfunc, pglob) 12746597Sdonn const char *pattern; 128*57897Sbostic int flags, (*errfunc) __P((const char *, int)); 12940087Sbostic glob_t *pglob; 13040087Sbostic { 131*57897Sbostic const u_char *patnext; 132*57897Sbostic int c; 133*57897Sbostic Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; 13440087Sbostic 13550121Sbostic patnext = (u_char *) pattern; 13640087Sbostic if (!(flags & GLOB_APPEND)) { 13740087Sbostic pglob->gl_pathc = 0; 13840087Sbostic pglob->gl_pathv = NULL; 13940087Sbostic if (!(flags & GLOB_DOOFFS)) 14040087Sbostic pglob->gl_offs = 0; 14140087Sbostic } 14247590Sbostic pglob->gl_flags = flags & ~GLOB_MAGCHAR; 14340087Sbostic pglob->gl_errfunc = errfunc; 14447590Sbostic pglob->gl_matchc = 0; 14540087Sbostic 14640087Sbostic bufnext = patbuf; 14750049Sbostic bufend = bufnext + MAXPATHLEN; 14850049Sbostic if (flags & GLOB_QUOTE) { 14950050Sbostic /* Protect the quoted characters. */ 15050049Sbostic while (bufnext < bufend && (c = *patnext++) != EOS) 15150049Sbostic if (c == QUOTE) { 15250049Sbostic if ((c = *patnext++) == EOS) { 15350049Sbostic c = QUOTE; 15450049Sbostic --patnext; 15550049Sbostic } 15650049Sbostic *bufnext++ = c | M_PROTECT; 15750049Sbostic } 15850049Sbostic else 15950049Sbostic *bufnext++ = c; 16050049Sbostic } 16150049Sbostic else 16250049Sbostic while (bufnext < bufend && (c = *patnext++) != EOS) 16350049Sbostic *bufnext++ = c; 16450049Sbostic *bufnext = EOS; 16540087Sbostic 166*57897Sbostic if (flags & GLOB_BRACE) 167*57897Sbostic return globexp1(patbuf, pglob); 168*57897Sbostic else 169*57897Sbostic return glob0(patbuf, pglob); 170*57897Sbostic } 171*57897Sbostic 172*57897Sbostic /* 173*57897Sbostic * Expand recursively a glob {} pattern. When there is no more expansion 174*57897Sbostic * invoke the standard globbing routine to glob the rest of the magic 175*57897Sbostic * characters 176*57897Sbostic */ 177*57897Sbostic static int globexp1(pattern, pglob) 178*57897Sbostic const Char *pattern; 179*57897Sbostic glob_t *pglob; 180*57897Sbostic { 181*57897Sbostic const Char* ptr = pattern; 182*57897Sbostic int rv; 183*57897Sbostic 184*57897Sbostic /* Protect a single {}, for find(1), like csh */ 185*57897Sbostic if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) 186*57897Sbostic return glob0(pattern, pglob); 187*57897Sbostic 188*57897Sbostic while ((ptr = (const Char *) g_strchr((Char *) ptr, LBRACE)) != NULL) 189*57897Sbostic if (!globexp2(ptr, pattern, pglob, &rv)) 190*57897Sbostic return rv; 191*57897Sbostic 192*57897Sbostic return glob0(pattern, pglob); 193*57897Sbostic } 194*57897Sbostic 195*57897Sbostic 196*57897Sbostic /* 197*57897Sbostic * Recursive brace globbing helper. Tries to expand a single brace. 198*57897Sbostic * If it succeeds then it invokes globexp1 with the new pattern. 199*57897Sbostic * If it fails then it tries to glob the rest of the pattern and returns. 200*57897Sbostic */ 201*57897Sbostic static int globexp2(ptr, pattern, pglob, rv) 202*57897Sbostic const Char *ptr, *pattern; 203*57897Sbostic glob_t *pglob; 204*57897Sbostic int *rv; 205*57897Sbostic { 206*57897Sbostic int i; 207*57897Sbostic Char *lm, *ls; 208*57897Sbostic const Char *pe, *pm, *pl; 209*57897Sbostic Char patbuf[MAXPATHLEN + 1]; 210*57897Sbostic 211*57897Sbostic /* copy part up to the brace */ 212*57897Sbostic for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++) 213*57897Sbostic continue; 214*57897Sbostic ls = lm; 215*57897Sbostic 216*57897Sbostic /* Find the balanced brace */ 217*57897Sbostic for (i = 0, pe = ++ptr; *pe; pe++) 218*57897Sbostic if (*pe == LBRACKET) { 219*57897Sbostic /* Ignore everything between [] */ 220*57897Sbostic for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++) 221*57897Sbostic continue; 222*57897Sbostic if (*pe == EOS) { 223*57897Sbostic /* 224*57897Sbostic * We could not find a matching RBRACKET. 225*57897Sbostic * Ignore and just look for RBRACE 226*57897Sbostic */ 227*57897Sbostic pe = pm; 228*57897Sbostic } 229*57897Sbostic } 230*57897Sbostic else if (*pe == LBRACE) 231*57897Sbostic i++; 232*57897Sbostic else if (*pe == RBRACE) { 233*57897Sbostic if (i == 0) 234*57897Sbostic break; 235*57897Sbostic i--; 236*57897Sbostic } 237*57897Sbostic 238*57897Sbostic /* Non matching braces; just glob the pattern */ 239*57897Sbostic if (i != 0 || *pe == EOS) { 240*57897Sbostic *rv = glob0(patbuf, pglob); 241*57897Sbostic return 0; 242*57897Sbostic } 243*57897Sbostic 244*57897Sbostic for (i = 0, pl = pm = ptr; pm <= pe; pm++) 245*57897Sbostic switch (*pm) { 246*57897Sbostic case LBRACKET: 247*57897Sbostic /* Ignore everything between [] */ 248*57897Sbostic for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++) 249*57897Sbostic continue; 250*57897Sbostic if (*pm == EOS) { 251*57897Sbostic /* 252*57897Sbostic * We could not find a matching RBRACKET. 253*57897Sbostic * Ignore and just look for RBRACE 254*57897Sbostic */ 255*57897Sbostic pm = pl; 256*57897Sbostic } 257*57897Sbostic break; 258*57897Sbostic 259*57897Sbostic case LBRACE: 260*57897Sbostic i++; 261*57897Sbostic break; 262*57897Sbostic 263*57897Sbostic case RBRACE: 264*57897Sbostic if (i) { 265*57897Sbostic i--; 266*57897Sbostic break; 267*57897Sbostic } 268*57897Sbostic /* FALLTHROUGH */ 269*57897Sbostic case COMMA: 270*57897Sbostic if (i && *pm == COMMA) 271*57897Sbostic break; 272*57897Sbostic else { 273*57897Sbostic /* Append the current string */ 274*57897Sbostic for (lm = ls; (pl < pm); *lm++ = *pl++) 275*57897Sbostic continue; 276*57897Sbostic /* 277*57897Sbostic * Append the rest of the pattern after the 278*57897Sbostic * closing brace 279*57897Sbostic */ 280*57897Sbostic for (pl = pe + 1; (*lm++ = *pl++) != EOS;) 281*57897Sbostic continue; 282*57897Sbostic 283*57897Sbostic /* Expand the current pattern */ 284*57897Sbostic #ifdef DEBUG 285*57897Sbostic qprintf("globexp2:", patbuf); 286*57897Sbostic #endif 287*57897Sbostic *rv = globexp1(patbuf, pglob); 288*57897Sbostic 289*57897Sbostic /* move after the comma, to the next string */ 290*57897Sbostic pl = pm + 1; 291*57897Sbostic } 292*57897Sbostic break; 293*57897Sbostic 294*57897Sbostic default: 295*57897Sbostic break; 296*57897Sbostic } 297*57897Sbostic *rv = 0; 298*57897Sbostic return 0; 299*57897Sbostic } 300*57897Sbostic 301*57897Sbostic 302*57897Sbostic 303*57897Sbostic /* 304*57897Sbostic * expand tilde from the passwd file. 305*57897Sbostic */ 306*57897Sbostic static const Char * 307*57897Sbostic globtilde(pattern, patbuf, pglob) 308*57897Sbostic const Char *pattern; 309*57897Sbostic Char *patbuf; 310*57897Sbostic glob_t *pglob; 311*57897Sbostic { 312*57897Sbostic struct passwd *pwd; 313*57897Sbostic char *h; 314*57897Sbostic const Char *p; 315*57897Sbostic Char *b; 316*57897Sbostic 317*57897Sbostic if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE)) 318*57897Sbostic return pattern; 319*57897Sbostic 320*57897Sbostic /* Copy up to the end of the string or / */ 321*57897Sbostic for (p = pattern + 1, h = (char *) patbuf; *p && *p != SLASH; 322*57897Sbostic *h++ = *p++) 323*57897Sbostic continue; 324*57897Sbostic 325*57897Sbostic *h = EOS; 326*57897Sbostic 327*57897Sbostic if (((char *) patbuf)[0] == EOS) { 328*57897Sbostic /* 329*57897Sbostic * handle a plain ~ or ~/ by expanding $HOME 330*57897Sbostic * first and then trying the password file 331*57897Sbostic */ 332*57897Sbostic if ((h = getenv("HOME")) == NULL) { 333*57897Sbostic if ((pwd = getpwuid(getuid())) == NULL) 334*57897Sbostic return pattern; 335*57897Sbostic else 336*57897Sbostic h = pwd->pw_dir; 337*57897Sbostic } 338*57897Sbostic } 339*57897Sbostic else { 340*57897Sbostic /* 341*57897Sbostic * Expand a ~user 342*57897Sbostic */ 343*57897Sbostic if ((pwd = getpwnam((char*) patbuf)) == NULL) 344*57897Sbostic return pattern; 345*57897Sbostic else 346*57897Sbostic h = pwd->pw_dir; 347*57897Sbostic } 348*57897Sbostic 349*57897Sbostic /* Copy the home directory */ 350*57897Sbostic for (b = patbuf; *h; *b++ = *h++) 351*57897Sbostic continue; 352*57897Sbostic 353*57897Sbostic /* Append the rest of the pattern */ 354*57897Sbostic while ((*b++ = *p++) != EOS) 355*57897Sbostic continue; 356*57897Sbostic 357*57897Sbostic return patbuf; 358*57897Sbostic } 359*57897Sbostic 360*57897Sbostic 361*57897Sbostic /* 362*57897Sbostic * The main glob() routine: compiles the pattern (optionally processing 363*57897Sbostic * quotes), calls glob1() to do the real pattern matching, and finally 364*57897Sbostic * sorts the list (unless unsorted operation is requested). Returns 0 365*57897Sbostic * if things went well, nonzero if errors occurred. It is not an error 366*57897Sbostic * to find no matches. 367*57897Sbostic */ 368*57897Sbostic static int 369*57897Sbostic glob0(pattern, pglob) 370*57897Sbostic const Char *pattern; 371*57897Sbostic glob_t *pglob; 372*57897Sbostic { 373*57897Sbostic const Char *qpatnext; 374*57897Sbostic int c, err, oldpathc; 375*57897Sbostic Char *bufnext, *bufend, patbuf[MAXPATHLEN+1]; 376*57897Sbostic 377*57897Sbostic qpatnext = globtilde(pattern, patbuf, pglob); 378*57897Sbostic 379*57897Sbostic oldpathc = pglob->gl_pathc; 380*57897Sbostic pglob->gl_matchc = 0; 381*57897Sbostic 382*57897Sbostic bufnext = patbuf; 383*57897Sbostic bufend = bufnext + MAXPATHLEN; 384*57897Sbostic 38550050Sbostic /* We don't need to check for buffer overflow any more. */ 38650049Sbostic while ((c = *qpatnext++) != EOS) { 38740087Sbostic switch (c) { 38840087Sbostic case LBRACKET: 38950049Sbostic c = *qpatnext; 39040087Sbostic if (c == NOT) 39150049Sbostic ++qpatnext; 39250049Sbostic if (*qpatnext == EOS || 393*57897Sbostic g_strchr((Char *) qpatnext+1, RBRACKET) == NULL) { 39440087Sbostic *bufnext++ = LBRACKET; 39540087Sbostic if (c == NOT) 39650049Sbostic --qpatnext; 39740087Sbostic break; 39840087Sbostic } 39940087Sbostic *bufnext++ = M_SET; 40040087Sbostic if (c == NOT) 40140087Sbostic *bufnext++ = M_NOT; 40250049Sbostic c = *qpatnext++; 40340087Sbostic do { 40450121Sbostic *bufnext++ = CHAR(c); 40550049Sbostic if (*qpatnext == RANGE && 40650049Sbostic (c = qpatnext[1]) != RBRACKET) { 40740087Sbostic *bufnext++ = M_RNG; 40850121Sbostic *bufnext++ = CHAR(c); 40950049Sbostic qpatnext += 2; 41040087Sbostic } 41150049Sbostic } while ((c = *qpatnext++) != RBRACKET); 41250420Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 41340087Sbostic *bufnext++ = M_END; 41440087Sbostic break; 41540087Sbostic case QUESTION: 41647590Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 41740087Sbostic *bufnext++ = M_ONE; 41840087Sbostic break; 41940087Sbostic case STAR: 42047590Sbostic pglob->gl_flags |= GLOB_MAGCHAR; 42156373Sbostic /* collapse adjacent stars to one, 42256373Sbostic * to avoid exponential behavior 42356373Sbostic */ 42456373Sbostic if (bufnext == patbuf || bufnext[-1] != M_ALL) 42556373Sbostic *bufnext++ = M_ALL; 42640087Sbostic break; 42740087Sbostic default: 42850121Sbostic *bufnext++ = CHAR(c); 42940087Sbostic break; 43040087Sbostic } 43140087Sbostic } 43240087Sbostic *bufnext = EOS; 43350049Sbostic #ifdef DEBUG 434*57897Sbostic qprintf("glob0:", patbuf); 43550049Sbostic #endif 43640087Sbostic 43740087Sbostic if ((err = glob1(patbuf, pglob)) != 0) 43840087Sbostic return(err); 43940087Sbostic 44050420Sbostic /* 44150420Sbostic * If there was no match we are going to append the pattern 44250420Sbostic * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified 44350420Sbostic * and the pattern did not contain any magic characters 44450420Sbostic * GLOB_NOMAGIC is there just for compatibility with csh. 44550420Sbostic */ 44650420Sbostic if (pglob->gl_pathc == oldpathc && 447*57897Sbostic ((pglob->gl_flags & GLOB_NOCHECK) || 448*57897Sbostic ((pglob->gl_flags & (GLOB_NOMAGIC|GLOB_BRACE|GLOB_TILDE)) || 449*57897Sbostic !(pglob->gl_flags & GLOB_MAGCHAR)))) 450*57897Sbostic return(globextend(pattern, pglob)); 451*57897Sbostic else if (!(pglob->gl_flags & GLOB_NOSORT)) 45250050Sbostic qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc, 45350050Sbostic pglob->gl_pathc - oldpathc, sizeof(char *), compare); 45440087Sbostic return(0); 45540087Sbostic } 45640087Sbostic 45750050Sbostic static int 45850050Sbostic compare(p, q) 45950050Sbostic const void *p, *q; 46050050Sbostic { 46150050Sbostic return(strcmp(*(char **)p, *(char **)q)); 46250050Sbostic } 46350050Sbostic 464*57897Sbostic static int 46540087Sbostic glob1(pattern, pglob) 46650050Sbostic Char *pattern; 46740087Sbostic glob_t *pglob; 46840087Sbostic { 46950050Sbostic Char pathbuf[MAXPATHLEN+1]; 47040087Sbostic 47150050Sbostic /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */ 47240087Sbostic if (*pattern == EOS) 47340087Sbostic return(0); 47440087Sbostic return(glob2(pathbuf, pathbuf, pattern, pglob)); 47540087Sbostic } 47640087Sbostic 47740087Sbostic /* 47850050Sbostic * The functions glob2 and glob3 are mutually recursive; there is one level 47950050Sbostic * of recursion for each segment in the pattern that contains one or more 48050050Sbostic * meta characters. 48140087Sbostic */ 482*57897Sbostic static int 48340087Sbostic glob2(pathbuf, pathend, pattern, pglob) 48450050Sbostic Char *pathbuf, *pathend, *pattern; 48540087Sbostic glob_t *pglob; 48640087Sbostic { 48750050Sbostic struct stat sb; 48850050Sbostic Char *p, *q; 48948540Sbostic int anymeta; 49040087Sbostic 49140087Sbostic /* 49250050Sbostic * Loop over pattern segments until end of pattern or until 49340087Sbostic * segment with meta character found. 49440087Sbostic */ 49548357Sbostic for (anymeta = 0;;) { 49650050Sbostic if (*pattern == EOS) { /* End of pattern? */ 49740087Sbostic *pathend = EOS; 49856942Smckusick if (g_lstat(pathbuf, &sb, pglob)) 49948357Sbostic return(0); 50048540Sbostic 50148540Sbostic if (((pglob->gl_flags & GLOB_MARK) && 50250050Sbostic pathend[-1] != SEP) && (S_ISDIR(sb.st_mode) 50350050Sbostic || (S_ISLNK(sb.st_mode) && 50456942Smckusick (g_stat(pathbuf, &sb, pglob) == 0) && 50550050Sbostic S_ISDIR(sb.st_mode)))) { 50640087Sbostic *pathend++ = SEP; 50740087Sbostic *pathend = EOS; 50840087Sbostic } 50947590Sbostic ++pglob->gl_matchc; 51040087Sbostic return(globextend(pathbuf, pglob)); 51140087Sbostic } 51240087Sbostic 51350050Sbostic /* Find end of next segment, copy tentatively to pathend. */ 51440087Sbostic q = pathend; 51540087Sbostic p = pattern; 51640087Sbostic while (*p != EOS && *p != SEP) { 51740087Sbostic if (ismeta(*p)) 51840087Sbostic anymeta = 1; 51940087Sbostic *q++ = *p++; 52040087Sbostic } 52140087Sbostic 52250050Sbostic if (!anymeta) { /* No expansion, do next segment. */ 52340087Sbostic pathend = q; 52440087Sbostic pattern = p; 52540087Sbostic while (*pattern == SEP) 52640087Sbostic *pathend++ = *pattern++; 52750050Sbostic } else /* Need expansion, recurse. */ 52840087Sbostic return(glob3(pathbuf, pathend, pattern, p, pglob)); 52940087Sbostic } 53040087Sbostic /* NOTREACHED */ 53140087Sbostic } 53240087Sbostic 533*57897Sbostic static int 53440087Sbostic glob3(pathbuf, pathend, pattern, restpattern, pglob) 53550050Sbostic Char *pathbuf, *pathend, *pattern, *restpattern; 53640087Sbostic glob_t *pglob; 53740087Sbostic { 53850050Sbostic register struct dirent *dp; 53940087Sbostic DIR *dirp; 540*57897Sbostic int err; 54157006Sbostic char buf[MAXPATHLEN]; 54240087Sbostic 543*57897Sbostic /* 544*57897Sbostic * The readdirfunc declaration can't be prototyped, because it is 545*57897Sbostic * assigned, below, to two functions which are prototyped in glob.h 546*57897Sbostic * and dirent.h as taking pointers to differently typed opaque 547*57897Sbostic * structures. 548*57897Sbostic */ 549*57897Sbostic struct dirent *(*readdirfunc)(); 550*57897Sbostic 55140087Sbostic *pathend = EOS; 55240087Sbostic errno = 0; 55348540Sbostic 55457006Sbostic if ((dirp = g_opendir(pathbuf, pglob)) == NULL) { 55550050Sbostic /* TODO: don't call for ENOENT or ENOTDIR? */ 55657006Sbostic if (pglob->gl_errfunc) { 55757006Sbostic g_Ctoc(pathbuf, buf); 55857006Sbostic if (pglob->gl_errfunc(buf, errno) || 55957006Sbostic pglob->gl_flags & GLOB_ERR) 56057006Sbostic return (GLOB_ABEND); 56157006Sbostic } 56257006Sbostic return(0); 56357006Sbostic } 56440087Sbostic 56540087Sbostic err = 0; 56640087Sbostic 56750050Sbostic /* Search directory for matching names. */ 56856942Smckusick if (pglob->gl_flags & GLOB_ALTDIRFUNC) 56956942Smckusick readdirfunc = pglob->gl_readdir; 57056942Smckusick else 57156942Smckusick readdirfunc = readdir; 57256942Smckusick while ((dp = (*readdirfunc)(dirp))) { 57350121Sbostic register u_char *sc; 57450050Sbostic register Char *dc; 57550050Sbostic 57650050Sbostic /* Initial DOT must be matched literally. */ 57740087Sbostic if (dp->d_name[0] == DOT && *pattern != DOT) 57840087Sbostic continue; 57950121Sbostic for (sc = (u_char *) dp->d_name, dc = pathend; 580*57897Sbostic (*dc++ = *sc++) != EOS;) 581*57897Sbostic continue; 58248540Sbostic if (!match(pathend, pattern, restpattern)) { 58348540Sbostic *pathend = EOS; 58440087Sbostic continue; 58548540Sbostic } 58648540Sbostic err = glob2(pathbuf, --dc, restpattern, pglob); 58740087Sbostic if (err) 58840087Sbostic break; 58940087Sbostic } 59050050Sbostic 59156942Smckusick if (pglob->gl_flags & GLOB_ALTDIRFUNC) 59256942Smckusick (*pglob->gl_closedir)(dirp); 59356942Smckusick else 59456942Smckusick closedir(dirp); 59540087Sbostic return(err); 59640087Sbostic } 59740087Sbostic 59840087Sbostic 59940087Sbostic /* 60040087Sbostic * Extend the gl_pathv member of a glob_t structure to accomodate a new item, 60140087Sbostic * add the new item, and update gl_pathc. 60240087Sbostic * 60340087Sbostic * This assumes the BSD realloc, which only copies the block when its size 60440087Sbostic * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic 60540087Sbostic * behavior. 60640087Sbostic * 60740087Sbostic * Return 0 if new item added, error code if memory couldn't be allocated. 60840087Sbostic * 60940087Sbostic * Invariant of the glob_t structure: 61040087Sbostic * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and 61150050Sbostic * gl_pathv points to (gl_offs + gl_pathc + 1) items. 61240087Sbostic */ 61348540Sbostic static int 61440087Sbostic globextend(path, pglob) 615*57897Sbostic const Char *path; 61640087Sbostic glob_t *pglob; 61740087Sbostic { 61840087Sbostic register char **pathv; 61940087Sbostic register int i; 62048540Sbostic u_int newsize; 62140087Sbostic char *copy; 622*57897Sbostic const Char *p; 62340087Sbostic 62440087Sbostic newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs); 625*57897Sbostic pathv = pglob->gl_pathv ? 626*57897Sbostic realloc((char *)pglob->gl_pathv, newsize) : 627*57897Sbostic malloc(newsize); 62840087Sbostic if (pathv == NULL) 62940087Sbostic return(GLOB_NOSPACE); 63040087Sbostic 63140087Sbostic if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) { 63240087Sbostic /* first time around -- clear initial gl_offs items */ 63340087Sbostic pathv += pglob->gl_offs; 63440087Sbostic for (i = pglob->gl_offs; --i >= 0; ) 63540087Sbostic *--pathv = NULL; 63640087Sbostic } 63740087Sbostic pglob->gl_pathv = pathv; 63840087Sbostic 639*57897Sbostic for (p = path; *p++;) 640*57897Sbostic continue; 64148540Sbostic if ((copy = malloc(p - path)) != NULL) { 64250050Sbostic g_Ctoc(path, copy); 64340087Sbostic pathv[pglob->gl_offs + pglob->gl_pathc++] = copy; 64440087Sbostic } 64540087Sbostic pathv[pglob->gl_offs + pglob->gl_pathc] = NULL; 64650050Sbostic return(copy == NULL ? GLOB_NOSPACE : 0); 64740087Sbostic } 64840087Sbostic 64940087Sbostic 65040087Sbostic /* 65140087Sbostic * pattern matching function for filenames. Each occurrence of the * 65240087Sbostic * pattern causes a recursion level. 65340087Sbostic */ 654*57897Sbostic static int 65540087Sbostic match(name, pat, patend) 65650050Sbostic register Char *name, *pat, *patend; 65740087Sbostic { 65848540Sbostic int ok, negate_range; 65950050Sbostic Char c, k; 66040087Sbostic 66140087Sbostic while (pat < patend) { 66240087Sbostic c = *pat++; 66348540Sbostic switch (c & M_MASK) { 66440087Sbostic case M_ALL: 66540087Sbostic if (pat == patend) 66640087Sbostic return(1); 66756373Sbostic do 66856373Sbostic if (match(name, pat, patend)) 66956373Sbostic return(1); 67056373Sbostic while (*name++ != EOS); 67140087Sbostic return(0); 67240087Sbostic case M_ONE: 67340087Sbostic if (*name++ == EOS) 67440087Sbostic return(0); 67540087Sbostic break; 67640087Sbostic case M_SET: 67740087Sbostic ok = 0; 67852339Sbostic if ((k = *name++) == EOS) 67952339Sbostic return(0); 680*57897Sbostic if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS) 68140087Sbostic ++pat; 68250050Sbostic while (((c = *pat++) & M_MASK) != M_END) 68348540Sbostic if ((*pat & M_MASK) == M_RNG) { 68440087Sbostic if (c <= k && k <= pat[1]) 68540087Sbostic ok = 1; 68640087Sbostic pat += 2; 68750050Sbostic } else if (c == k) 68840087Sbostic ok = 1; 68940087Sbostic if (ok == negate_range) 69040087Sbostic return(0); 69140087Sbostic break; 69240087Sbostic default: 69340087Sbostic if (*name++ != c) 69440087Sbostic return(0); 69540087Sbostic break; 69640087Sbostic } 69740087Sbostic } 69840087Sbostic return(*name == EOS); 69940087Sbostic } 70040087Sbostic 70150050Sbostic /* Free allocated data belonging to a glob_t structure. */ 70240087Sbostic void 70340087Sbostic globfree(pglob) 70440087Sbostic glob_t *pglob; 70540087Sbostic { 70640087Sbostic register int i; 70740087Sbostic register char **pp; 70840087Sbostic 70940087Sbostic if (pglob->gl_pathv != NULL) { 71040087Sbostic pp = pglob->gl_pathv + pglob->gl_offs; 71140087Sbostic for (i = pglob->gl_pathc; i--; ++pp) 71240087Sbostic if (*pp) 71350050Sbostic free(*pp); 71450049Sbostic free(pglob->gl_pathv); 71540087Sbostic } 71640087Sbostic } 71750050Sbostic 71850050Sbostic static DIR * 71956942Smckusick g_opendir(str, pglob) 72050050Sbostic register Char *str; 72156942Smckusick glob_t *pglob; 72250050Sbostic { 72350050Sbostic char buf[MAXPATHLEN]; 72450050Sbostic 72550050Sbostic if (!*str) 72656942Smckusick strcpy(buf, "."); 72756942Smckusick else 72856942Smckusick g_Ctoc(str, buf); 729*57897Sbostic 73056942Smckusick if (pglob->gl_flags & GLOB_ALTDIRFUNC) 73156942Smckusick return((*pglob->gl_opendir)(buf)); 732*57897Sbostic 73350050Sbostic return(opendir(buf)); 73450050Sbostic } 73550050Sbostic 73650050Sbostic static int 73756942Smckusick g_lstat(fn, sb, pglob) 73850050Sbostic register Char *fn; 73950050Sbostic struct stat *sb; 74056942Smckusick glob_t *pglob; 74150050Sbostic { 74250050Sbostic char buf[MAXPATHLEN]; 74350050Sbostic 74450050Sbostic g_Ctoc(fn, buf); 74556942Smckusick if (pglob->gl_flags & GLOB_ALTDIRFUNC) 74656942Smckusick return((*pglob->gl_lstat)(buf, sb)); 74750050Sbostic return(lstat(buf, sb)); 74850050Sbostic } 74950050Sbostic 75050050Sbostic static int 75156942Smckusick g_stat(fn, sb, pglob) 75250050Sbostic register Char *fn; 75350050Sbostic struct stat *sb; 75456942Smckusick glob_t *pglob; 75550050Sbostic { 75650050Sbostic char buf[MAXPATHLEN]; 75750050Sbostic 75850050Sbostic g_Ctoc(fn, buf); 75956942Smckusick if (pglob->gl_flags & GLOB_ALTDIRFUNC) 76056942Smckusick return((*pglob->gl_stat)(buf, sb)); 76150050Sbostic return(stat(buf, sb)); 76250050Sbostic } 76350050Sbostic 76450050Sbostic static Char * 76550050Sbostic g_strchr(str, ch) 76650050Sbostic Char *str; 76750050Sbostic int ch; 76850050Sbostic { 76950050Sbostic do { 77050050Sbostic if (*str == ch) 77150050Sbostic return (str); 77250050Sbostic } while (*str++); 77350050Sbostic return (NULL); 77450050Sbostic } 77550050Sbostic 776*57897Sbostic #ifdef notdef 777*57897Sbostic static Char * 778*57897Sbostic g_strcat(dst, src) 779*57897Sbostic Char *dst; 780*57897Sbostic const Char* src; 781*57897Sbostic { 782*57897Sbostic Char *sdst = dst; 783*57897Sbostic 784*57897Sbostic while (*dst++) 785*57897Sbostic continue; 786*57897Sbostic --dst; 787*57897Sbostic while((*dst++ = *src++) != EOS) 788*57897Sbostic continue; 789*57897Sbostic 790*57897Sbostic return (sdst); 791*57897Sbostic } 792*57897Sbostic #endif 793*57897Sbostic 79450050Sbostic static void 79550050Sbostic g_Ctoc(str, buf) 796*57897Sbostic register const Char *str; 79750050Sbostic char *buf; 79850050Sbostic { 79950050Sbostic register char *dc; 80050050Sbostic 801*57897Sbostic for (dc = buf; (*dc++ = *str++) != EOS;) 802*57897Sbostic continue; 80350050Sbostic } 80450050Sbostic 80550050Sbostic #ifdef DEBUG 80650050Sbostic static void 807*57897Sbostic qprintf(str, s) 808*57897Sbostic const char *str; 80950050Sbostic register Char *s; 81050050Sbostic { 81150050Sbostic register Char *p; 81250050Sbostic 813*57897Sbostic (void)printf("%s:\n", str); 81450050Sbostic for (p = s; *p; p++) 81557006Sbostic (void)printf("%c", CHAR(*p)); 81650050Sbostic (void)printf("\n"); 81750050Sbostic for (p = s; *p; p++) 81850050Sbostic (void)printf("%c", *p & M_PROTECT ? '"' : ' '); 81950050Sbostic (void)printf("\n"); 82050050Sbostic for (p = s; *p; p++) 82157006Sbostic (void)printf("%c", ismeta(*p) ? '_' : ' '); 82250050Sbostic (void)printf("\n"); 82350050Sbostic } 82450050Sbostic #endif 825