14887Schin /*********************************************************************** 24887Schin * * 34887Schin * This software is part of the ast package * 4*8462SApril.Chin@Sun.COM * Copyright (c) 1985-2008 AT&T Intellectual Property * 54887Schin * and is licensed under the * 64887Schin * Common Public License, Version 1.0 * 7*8462SApril.Chin@Sun.COM * by AT&T Intellectual Property * 84887Schin * * 94887Schin * A copy of the License is available at * 104887Schin * http://www.opensource.org/licenses/cpl1.0.txt * 114887Schin * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 124887Schin * * 134887Schin * Information and Software Systems Research * 144887Schin * AT&T Research * 154887Schin * Florham Park NJ * 164887Schin * * 174887Schin * Glenn Fowler <gsf@research.att.com> * 184887Schin * David Korn <dgk@research.att.com> * 194887Schin * Phong Vo <kpv@research.att.com> * 204887Schin * * 214887Schin ***********************************************************************/ 224887Schin #pragma prototyped 234887Schin 244887Schin /* 254887Schin * file name expansion - posix.2 glob with gnu and ast extensions 264887Schin * 274887Schin * David Korn 284887Schin * Glenn Fowler 294887Schin * AT&T Research 304887Schin */ 314887Schin 324887Schin #include <ast.h> 334887Schin #include <ls.h> 344887Schin #include <stak.h> 354887Schin #include <ast_dir.h> 364887Schin #include <error.h> 374887Schin #include <ctype.h> 384887Schin #include <regex.h> 394887Schin 404887Schin #define GLOB_MAGIC 0xaaaa0000 414887Schin 424887Schin #define MATCH_RAW 1 434887Schin #define MATCH_MAKE 2 444887Schin #define MATCH_META 4 454887Schin 464887Schin #define MATCHPATH(g) (offsetof(globlist_t,gl_path)+(g)->gl_extra) 474887Schin 484887Schin typedef int (*GL_error_f)(const char*, int); 494887Schin typedef void* (*GL_opendir_f)(const char*); 504887Schin typedef struct dirent* (*GL_readdir_f)(void*); 514887Schin typedef void (*GL_closedir_f)(void*); 524887Schin typedef int (*GL_stat_f)(const char*, struct stat*); 534887Schin 544887Schin #define _GLOB_PRIVATE_ \ 554887Schin GL_error_f gl_errfn; \ 564887Schin int gl_error; \ 574887Schin char* gl_nextpath; \ 584887Schin globlist_t* gl_rescan; \ 594887Schin globlist_t* gl_match; \ 604887Schin Stak_t* gl_stak; \ 614887Schin int re_flags; \ 624887Schin regex_t* gl_ignore; \ 634887Schin regex_t* gl_ignorei; \ 644887Schin regex_t re_ignore; \ 654887Schin regex_t re_ignorei; \ 664887Schin unsigned long gl_starstar; \ 674887Schin char* gl_opt; \ 684887Schin char* gl_pat; \ 694887Schin char* gl_pad[4]; 704887Schin 714887Schin #include <glob.h> 724887Schin 734887Schin /* 744887Schin * default gl_diropen 754887Schin */ 764887Schin 774887Schin static void* 784887Schin gl_diropen(glob_t* gp, const char* path) 794887Schin { 804887Schin return (*gp->gl_opendir)(path); 814887Schin } 824887Schin 834887Schin /* 844887Schin * default gl_dirnext 854887Schin */ 864887Schin 874887Schin static char* 884887Schin gl_dirnext(glob_t* gp, void* handle) 894887Schin { 904887Schin struct dirent* dp; 914887Schin 924887Schin while (dp = (struct dirent*)(*gp->gl_readdir)(handle)) 934887Schin #ifdef D_FILENO 944887Schin if (D_FILENO(dp)) 954887Schin #endif 964887Schin { 974887Schin #ifdef D_TYPE 984887Schin if (D_TYPE(dp) != DT_UNKNOWN && D_TYPE(dp) != DT_DIR && D_TYPE(dp) != DT_LNK) 994887Schin gp->gl_status |= GLOB_NOTDIR; 1004887Schin #endif 1014887Schin return dp->d_name; 1024887Schin } 1034887Schin return 0; 1044887Schin } 1054887Schin 1064887Schin /* 1074887Schin * default gl_dirclose 1084887Schin */ 1094887Schin 1104887Schin static void 1114887Schin gl_dirclose(glob_t* gp, void* handle) 1124887Schin { 1134887Schin (gp->gl_closedir)(handle); 1144887Schin } 1154887Schin 1164887Schin /* 1174887Schin * default gl_type 1184887Schin */ 1194887Schin 1204887Schin static int 121*8462SApril.Chin@Sun.COM gl_type(glob_t* gp, const char* path, int flags) 1224887Schin { 1234887Schin register int type; 1244887Schin struct stat st; 1254887Schin 126*8462SApril.Chin@Sun.COM if ((flags & GLOB_STARSTAR) ? (*gp->gl_lstat)(path, &st) : (*gp->gl_stat)(path, &st)) 1274887Schin type = 0; 1284887Schin else if (S_ISDIR(st.st_mode)) 1294887Schin type = GLOB_DIR; 1304887Schin else if (!S_ISREG(st.st_mode)) 1314887Schin type = GLOB_DEV; 1324887Schin else if (st.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) 1334887Schin type = GLOB_EXE; 1344887Schin else 1354887Schin type = GLOB_REG; 1364887Schin return type; 1374887Schin } 1384887Schin 1394887Schin /* 1404887Schin * default gl_attr 1414887Schin */ 1424887Schin 1434887Schin static int 144*8462SApril.Chin@Sun.COM gl_attr(glob_t* gp, const char* path, int flags) 1454887Schin { 1464887Schin return strchr(astconf("PATH_ATTRIBUTES", path, NiL), 'c') ? GLOB_ICASE : 0; 1474887Schin } 1484887Schin 1494887Schin /* 1504887Schin * default gl_nextdir 1514887Schin */ 1524887Schin 1534887Schin static char* 1544887Schin gl_nextdir(glob_t* gp, char* dir) 1554887Schin { 1564887Schin if (!(dir = gp->gl_nextpath)) 1574887Schin dir = gp->gl_nextpath = stakcopy(pathbin()); 1584887Schin switch (*gp->gl_nextpath) 1594887Schin { 1604887Schin case 0: 1614887Schin dir = 0; 1624887Schin break; 1634887Schin case ':': 1644887Schin while (*gp->gl_nextpath == ':') 1654887Schin gp->gl_nextpath++; 1664887Schin dir = "."; 1674887Schin break; 1684887Schin default: 1694887Schin while (*gp->gl_nextpath) 1704887Schin if (*gp->gl_nextpath++ == ':') 1714887Schin { 1724887Schin *(gp->gl_nextpath - 1) = 0; 1734887Schin break; 1744887Schin } 1754887Schin break; 1764887Schin } 1774887Schin return dir; 1784887Schin } 1794887Schin 1804887Schin /* 1814887Schin * error intercept 1824887Schin */ 1834887Schin 1844887Schin static int 1854887Schin errorcheck(register glob_t* gp, const char* path) 1864887Schin { 1874887Schin int r = 1; 1884887Schin 1894887Schin if (gp->gl_errfn) 1904887Schin r = (*gp->gl_errfn)(path, errno); 1914887Schin if (gp->gl_flags & GLOB_ERR) 1924887Schin r = 0; 1934887Schin if (!r) 1944887Schin gp->gl_error = GLOB_ABORTED; 1954887Schin return r; 1964887Schin } 1974887Schin 1984887Schin /* 1994887Schin * remove backslashes 2004887Schin */ 2014887Schin 2024887Schin static void 2034887Schin trim(register char* sp, register char* p1, int* n1, register char* p2, int* n2) 2044887Schin { 2054887Schin register char* dp = sp; 2064887Schin register int c; 2074887Schin register int n; 2084887Schin 2094887Schin if (p1) 2104887Schin *n1 = 0; 2114887Schin if (p2) 2124887Schin *n2 = 0; 2134887Schin do 2144887Schin { 2154887Schin if ((c = *sp++) == '\\' && (c = *sp++)) 2164887Schin n++; 2174887Schin if (sp == p1) 2184887Schin { 2194887Schin p1 = 0; 2204887Schin *n1 = sp - dp - 1; 2214887Schin } 2224887Schin if (sp == p2) 2234887Schin { 2244887Schin p2 = 0; 2254887Schin *n2 = sp - dp - 1; 2264887Schin } 2274887Schin } while (*dp++ = c); 2284887Schin } 2294887Schin 2304887Schin static void 2314887Schin addmatch(register glob_t* gp, const char* dir, const char* pat, register const char* rescan, char* endslash, int meta) 2324887Schin { 2334887Schin register globlist_t* ap; 2344887Schin int offset; 2354887Schin int type; 2364887Schin 2374887Schin stakseek(MATCHPATH(gp)); 2384887Schin if (dir) 2394887Schin { 2404887Schin stakputs(dir); 2414887Schin stakputc(gp->gl_delim); 2424887Schin } 2434887Schin if (endslash) 2444887Schin *endslash = 0; 2454887Schin stakputs(pat); 2464887Schin if (rescan) 2474887Schin { 248*8462SApril.Chin@Sun.COM if ((*gp->gl_type)(gp, stakptr(MATCHPATH(gp)), 0) != GLOB_DIR) 2494887Schin return; 2504887Schin stakputc(gp->gl_delim); 2514887Schin offset = staktell(); 2524887Schin /* if null, reserve room for . */ 2534887Schin if (*rescan) 2544887Schin stakputs(rescan); 2554887Schin else 2564887Schin stakputc(0); 2574887Schin stakputc(0); 2584887Schin rescan = stakptr(offset); 2594887Schin ap = (globlist_t*)stakfreeze(0); 2604887Schin ap->gl_begin = (char*)rescan; 2614887Schin ap->gl_next = gp->gl_rescan; 2624887Schin gp->gl_rescan = ap; 2634887Schin } 2644887Schin else 2654887Schin { 266*8462SApril.Chin@Sun.COM if (!endslash && (gp->gl_flags & GLOB_MARK) && (type = (*gp->gl_type)(gp, stakptr(MATCHPATH(gp)), 0))) 2674887Schin { 2684887Schin if ((gp->gl_flags & GLOB_COMPLETE) && type != GLOB_EXE) 2694887Schin { 2704887Schin stakseek(0); 2714887Schin return; 2724887Schin } 2734887Schin else if (type == GLOB_DIR && (gp->gl_flags & GLOB_MARK)) 2744887Schin stakputc(gp->gl_delim); 2754887Schin } 2764887Schin ap = (globlist_t*)stakfreeze(1); 2774887Schin ap->gl_next = gp->gl_match; 2784887Schin gp->gl_match = ap; 2794887Schin gp->gl_pathc++; 2804887Schin } 2814887Schin ap->gl_flags = MATCH_RAW|meta; 2824887Schin if (gp->gl_flags & GLOB_COMPLETE) 2834887Schin ap->gl_flags |= MATCH_MAKE; 2844887Schin } 2854887Schin 2864887Schin /* 2874887Schin * this routine builds a list of files that match a given pathname 2884887Schin * uses REG_SHELL of <regex> to match each component 2894887Schin * a leading . must match explicitly 2904887Schin */ 2914887Schin 2924887Schin static void 2934887Schin glob_dir(glob_t* gp, globlist_t* ap) 2944887Schin { 2954887Schin register char* rescan; 2964887Schin register char* prefix; 2974887Schin register char* pat; 2984887Schin register char* name; 2994887Schin register int c; 3004887Schin char* dirname; 3014887Schin void* dirf; 3024887Schin char first; 3034887Schin regex_t* ire; 3044887Schin regex_t* pre; 3054887Schin regex_t rec; 3064887Schin regex_t rei; 3074887Schin int notdir; 3084887Schin int t1; 3094887Schin int t2; 3104887Schin int bracket; 3114887Schin 3124887Schin int anymeta = ap->gl_flags & MATCH_META; 3134887Schin int complete = 0; 3144887Schin int err = 0; 3154887Schin int meta = ((gp->re_flags & REG_ICASE) && *ap->gl_begin != '/') ? MATCH_META : 0; 3164887Schin int quote = 0; 3174887Schin int savequote = 0; 3184887Schin char* restore1 = 0; 3194887Schin char* restore2 = 0; 3204887Schin regex_t* prec = 0; 3214887Schin regex_t* prei = 0; 3224887Schin char* matchdir = 0; 3234887Schin int starstar = 0; 3244887Schin 3254887Schin if (*gp->gl_intr) 3264887Schin { 3274887Schin gp->gl_error = GLOB_INTR; 3284887Schin return; 3294887Schin } 3304887Schin pat = rescan = ap->gl_begin; 3314887Schin prefix = dirname = ap->gl_path + gp->gl_extra; 3324887Schin first = (rescan == prefix); 3334887Schin again: 3344887Schin bracket = 0; 3354887Schin for (;;) 3364887Schin { 3374887Schin switch (c = *rescan++) 3384887Schin { 3394887Schin case 0: 3404887Schin if (meta) 3414887Schin { 3424887Schin rescan = 0; 3434887Schin break; 3444887Schin } 3454887Schin if (quote) 3464887Schin { 3474887Schin trim(ap->gl_begin, rescan, &t1, NiL, NiL); 3484887Schin rescan -= t1; 3494887Schin } 3504887Schin if (!first && !*rescan && *(rescan - 2) == gp->gl_delim) 3514887Schin { 3524887Schin *(rescan - 2) = 0; 353*8462SApril.Chin@Sun.COM c = (*gp->gl_type)(gp, prefix, 0); 3544887Schin *(rescan - 2) = gp->gl_delim; 3554887Schin if (c == GLOB_DIR) 3564887Schin addmatch(gp, NiL, prefix, NiL, rescan - 1, anymeta); 3574887Schin } 358*8462SApril.Chin@Sun.COM else if ((anymeta || !(gp->gl_flags & GLOB_NOCHECK)) && (*gp->gl_type)(gp, prefix, 0)) 3594887Schin addmatch(gp, NiL, prefix, NiL, NiL, anymeta); 3604887Schin return; 3614887Schin case '[': 3624887Schin if (!bracket) 3634887Schin { 3644887Schin bracket = MATCH_META; 3654887Schin if (*rescan == '!' || *rescan == '^') 3664887Schin rescan++; 3674887Schin if (*rescan == ']') 3684887Schin rescan++; 3694887Schin } 3704887Schin continue; 3714887Schin case ']': 3724887Schin meta |= bracket; 3734887Schin continue; 3744887Schin case '(': 3754887Schin if (!(gp->gl_flags & GLOB_AUGMENTED)) 3764887Schin continue; 3774887Schin case '*': 3784887Schin case '?': 3794887Schin meta = MATCH_META; 3804887Schin continue; 3814887Schin case '\\': 3824887Schin if (!(gp->gl_flags & GLOB_NOESCAPE)) 3834887Schin { 3844887Schin quote = 1; 3854887Schin if (*rescan) 3864887Schin rescan++; 3874887Schin } 3884887Schin continue; 3894887Schin default: 3904887Schin if (c == gp->gl_delim) 3914887Schin { 3924887Schin if (meta) 3934887Schin break; 3944887Schin pat = rescan; 3954887Schin bracket = 0; 3964887Schin savequote = quote; 3974887Schin } 3984887Schin continue; 3994887Schin } 4004887Schin break; 4014887Schin } 4024887Schin anymeta |= meta; 4034887Schin if (matchdir) 4044887Schin goto skip; 4054887Schin if (pat == prefix) 4064887Schin { 4074887Schin prefix = 0; 4084887Schin if (!rescan && (gp->gl_flags & GLOB_COMPLETE)) 4094887Schin { 4104887Schin complete = 1; 4114887Schin dirname = 0; 4124887Schin } 4134887Schin else 4144887Schin dirname = "."; 4154887Schin } 4164887Schin else 4174887Schin { 4184887Schin if (pat == prefix + 1) 4194887Schin dirname = "/"; 4204887Schin if (savequote) 4214887Schin { 4224887Schin quote = 0; 4234887Schin trim(ap->gl_begin, pat, &t1, rescan, &t2); 4244887Schin pat -= t1; 4254887Schin if (rescan) 4264887Schin rescan -= t2; 4274887Schin } 4284887Schin *(restore1 = pat - 1) = 0; 4294887Schin } 4304887Schin if (!complete && (gp->gl_flags & GLOB_STARSTAR)) 4314887Schin while (pat[0] == '*' && pat[1] == '*' && (pat[2] == '/' || pat[2]==0)) 4324887Schin { 4334887Schin matchdir = pat; 4344887Schin if (pat[2]) 4354887Schin { 4364887Schin pat += 3; 4374887Schin while (*pat=='/') pat++; 4384887Schin if (*pat) 4394887Schin continue; 4404887Schin } 4414887Schin rescan = *pat?0:pat; 4424887Schin pat = "*"; 4434887Schin goto skip; 4444887Schin } 4454887Schin if (matchdir) 4464887Schin { 4474887Schin rescan = pat; 4484887Schin goto again; 4494887Schin } 4504887Schin skip: 4514887Schin if (rescan) 4524887Schin *(restore2 = rescan - 1) = 0; 4534887Schin if (rescan && !complete && (gp->gl_flags & GLOB_STARSTAR)) 4544887Schin { 4554887Schin register char *p = rescan; 4564887Schin while (p[0] == '*' && p[1] == '*' && (p[2] == '/' || p[2]==0)) 4574887Schin { 4584887Schin rescan = p; 4594887Schin if (starstar = (p[2]==0)) 4604887Schin break; 4614887Schin p += 3; 4624887Schin while (*p=='/') 4634887Schin p++; 4644887Schin if (*p==0) 4654887Schin { 4664887Schin starstar = 2; 4674887Schin break; 4684887Schin } 4694887Schin } 4704887Schin } 4714887Schin if (matchdir) 4724887Schin gp->gl_starstar++; 4734887Schin if (gp->gl_opt) 4744887Schin pat = strcpy(gp->gl_opt, pat); 4754887Schin for (;;) 4764887Schin { 4774887Schin if (complete) 4784887Schin { 4794887Schin if (!(dirname = (*gp->gl_nextdir)(gp, dirname))) 4804887Schin break; 4814887Schin prefix = streq(dirname, ".") ? (char*)0 : dirname; 4824887Schin } 483*8462SApril.Chin@Sun.COM if ((!starstar && !gp->gl_starstar || (*gp->gl_type)(gp, dirname, GLOB_STARSTAR) == GLOB_DIR) && (dirf = (*gp->gl_diropen)(gp, dirname))) 4844887Schin { 485*8462SApril.Chin@Sun.COM if (!(gp->re_flags & REG_ICASE) && ((*gp->gl_attr)(gp, dirname, 0) & GLOB_ICASE)) 4864887Schin { 4874887Schin if (!prei) 4884887Schin { 4894887Schin if (err = regcomp(&rei, pat, gp->re_flags|REG_ICASE)) 4904887Schin break; 4914887Schin prei = &rei; 4924887Schin } 4934887Schin pre = prei; 4944887Schin if (gp->gl_ignore) 4954887Schin { 4964887Schin if (!gp->gl_ignorei) 4974887Schin { 4984887Schin if (regcomp(&gp->re_ignorei, gp->gl_fignore, gp->re_flags|REG_ICASE)) 4994887Schin { 5004887Schin gp->gl_error = GLOB_APPERR; 5014887Schin break; 5024887Schin } 5034887Schin gp->gl_ignorei = &gp->re_ignorei; 5044887Schin } 5054887Schin ire = gp->gl_ignorei; 5064887Schin } 5074887Schin else 5084887Schin ire = 0; 5094887Schin } 5104887Schin else 5114887Schin { 5124887Schin if (!prec) 5134887Schin { 5144887Schin if (err = regcomp(&rec, pat, gp->re_flags)) 5154887Schin break; 5164887Schin prec = &rec; 5174887Schin } 5184887Schin pre = prec; 5194887Schin ire = gp->gl_ignore; 5204887Schin } 5214887Schin if (restore2) 5224887Schin *restore2 = gp->gl_delim; 5234887Schin while ((name = (*gp->gl_dirnext)(gp, dirf)) && !*gp->gl_intr) 5244887Schin { 5254887Schin if (notdir = (gp->gl_status & GLOB_NOTDIR)) 5264887Schin gp->gl_status &= ~GLOB_NOTDIR; 5274887Schin if (ire && !regexec(ire, name, 0, NiL, 0)) 5284887Schin continue; 5294887Schin if (matchdir && (name[0] != '.' || name[1] && (name[1] != '.' || name[2])) && !notdir) 5304887Schin addmatch(gp, prefix, name, matchdir, NiL, anymeta); 5314887Schin if (!regexec(pre, name, 0, NiL, 0)) 5324887Schin { 5334887Schin if (!rescan || !notdir) 5344887Schin addmatch(gp, prefix, name, rescan, NiL, anymeta); 5354887Schin if (starstar==1 || (starstar==2 && !notdir)) 5364887Schin addmatch(gp, prefix, name, starstar==2?"":NiL, NiL, anymeta); 5374887Schin } 5384887Schin errno = 0; 5394887Schin } 5404887Schin (*gp->gl_dirclose)(gp, dirf); 5414887Schin if (err || errno && !errorcheck(gp, dirname)) 5424887Schin break; 5434887Schin } 5444887Schin else if (!complete && !errorcheck(gp, dirname)) 5454887Schin break; 5464887Schin if (!complete) 5474887Schin break; 5484887Schin if (*gp->gl_intr) 5494887Schin { 5504887Schin gp->gl_error = GLOB_INTR; 5514887Schin break; 5524887Schin } 5534887Schin } 5544887Schin if (restore1) 5554887Schin *restore1 = gp->gl_delim; 5564887Schin if (restore2) 5574887Schin *restore2 = gp->gl_delim; 5584887Schin if (prec) 5594887Schin regfree(prec); 5604887Schin if (prei) 5614887Schin regfree(prei); 5624887Schin if (err == REG_ESPACE) 5634887Schin gp->gl_error = GLOB_NOSPACE; 5644887Schin } 5654887Schin 5664887Schin int 5674887Schin glob(const char* pattern, int flags, int (*errfn)(const char*, int), register glob_t* gp) 5684887Schin { 5694887Schin register globlist_t* ap; 5704887Schin register char* pat; 5714887Schin globlist_t* top; 5724887Schin Stak_t* oldstak; 5734887Schin char** argv; 5744887Schin char** av; 5754887Schin size_t skip; 5764887Schin unsigned long f; 5774887Schin int n; 5784887Schin int x; 5794887Schin 5804887Schin const char* nocheck = pattern; 5814887Schin int optlen = 0; 5824887Schin int suflen = 0; 5834887Schin int extra = 1; 5844887Schin unsigned char intr = 0; 5854887Schin 5864887Schin gp->gl_rescan = 0; 5874887Schin gp->gl_error = 0; 5884887Schin gp->gl_errfn = errfn; 5894887Schin if (flags & GLOB_APPEND) 5904887Schin { 5914887Schin if ((gp->gl_flags |= GLOB_APPEND) ^ (flags|GLOB_MAGIC)) 5924887Schin return GLOB_APPERR; 5934887Schin if (((gp->gl_flags & GLOB_STACK) == 0) == (gp->gl_stak == 0)) 5944887Schin return GLOB_APPERR; 5954887Schin if (gp->gl_starstar > 1) 5964887Schin gp->gl_flags |= GLOB_STARSTAR; 5974887Schin else 5984887Schin gp->gl_starstar = 0; 5994887Schin } 6004887Schin else 6014887Schin { 6024887Schin gp->gl_flags = (flags&0xffff)|GLOB_MAGIC; 6034887Schin gp->re_flags = REG_SHELL|REG_NOSUB|REG_LEFT|REG_RIGHT|((flags&GLOB_AUGMENTED)?REG_AUGMENTED:0); 6044887Schin gp->gl_pathc = 0; 6054887Schin gp->gl_ignore = 0; 6064887Schin gp->gl_ignorei = 0; 6074887Schin gp->gl_starstar = 0; 6084887Schin if (!(flags & GLOB_DISC)) 6094887Schin { 6104887Schin gp->gl_fignore = 0; 6114887Schin gp->gl_suffix = 0; 6124887Schin gp->gl_intr = 0; 6134887Schin gp->gl_delim = 0; 6144887Schin gp->gl_handle = 0; 6154887Schin gp->gl_diropen = 0; 6164887Schin gp->gl_dirnext = 0; 6174887Schin gp->gl_dirclose = 0; 6184887Schin gp->gl_type = 0; 6194887Schin gp->gl_attr = 0; 6204887Schin gp->gl_nextdir = 0; 6214887Schin gp->gl_stat = 0; 622*8462SApril.Chin@Sun.COM gp->gl_lstat = 0; 6234887Schin gp->gl_extra = 0; 6244887Schin } 6254887Schin if (!(flags & GLOB_ALTDIRFUNC)) 6264887Schin { 6274887Schin gp->gl_opendir = (GL_opendir_f)opendir; 6284887Schin gp->gl_readdir = (GL_readdir_f)readdir; 6294887Schin gp->gl_closedir = (GL_closedir_f)closedir; 6304887Schin if (!gp->gl_stat) 631*8462SApril.Chin@Sun.COM gp->gl_stat = (GL_stat_f)pathstat; 6324887Schin } 633*8462SApril.Chin@Sun.COM if (!gp->gl_lstat) 634*8462SApril.Chin@Sun.COM gp->gl_lstat = (GL_stat_f)lstat; 6354887Schin if (!gp->gl_intr) 6364887Schin gp->gl_intr = &intr; 6374887Schin if (!gp->gl_delim) 6384887Schin gp->gl_delim = '/'; 6394887Schin if (!gp->gl_diropen) 6404887Schin gp->gl_diropen = gl_diropen; 6414887Schin if (!gp->gl_dirnext) 6424887Schin gp->gl_dirnext = gl_dirnext; 6434887Schin if (!gp->gl_dirclose) 6444887Schin gp->gl_dirclose = gl_dirclose; 6454887Schin if (!gp->gl_type) 6464887Schin gp->gl_type = gl_type; 6474887Schin if (!gp->gl_attr) 6484887Schin gp->gl_attr = gl_attr; 6494887Schin if (flags & GLOB_ICASE) 6504887Schin gp->re_flags |= REG_ICASE; 6514887Schin if (!gp->gl_fignore) 6524887Schin gp->re_flags |= REG_SHELL_DOT; 6534887Schin else if (*gp->gl_fignore) 6544887Schin { 6554887Schin if (regcomp(&gp->re_ignore, gp->gl_fignore, gp->re_flags)) 6564887Schin return GLOB_APPERR; 6574887Schin gp->gl_ignore = &gp->re_ignore; 6584887Schin } 6594887Schin if (gp->gl_flags & GLOB_STACK) 6604887Schin gp->gl_stak = 0; 6614887Schin else if (!(gp->gl_stak = stakcreate(0))) 6624887Schin return GLOB_NOSPACE; 6634887Schin if ((gp->gl_flags & GLOB_COMPLETE) && !gp->gl_nextdir) 6644887Schin gp->gl_nextdir = gl_nextdir; 6654887Schin } 6664887Schin skip = gp->gl_pathc; 6674887Schin if (gp->gl_stak) 6684887Schin oldstak = stakinstall(gp->gl_stak, 0); 6694887Schin if (flags & GLOB_DOOFFS) 6704887Schin extra += gp->gl_offs; 6714887Schin if (gp->gl_suffix) 6724887Schin suflen = strlen(gp->gl_suffix); 6734887Schin if (*(pat = (char*)pattern) == '~' && *(pat + 1) == '(') 6744887Schin { 6754887Schin f = gp->gl_flags; 6764887Schin n = 1; 6774887Schin x = 1; 6784887Schin pat += 2; 6794887Schin for (;;) 6804887Schin { 6814887Schin switch (*pat++) 6824887Schin { 6834887Schin case 0: 6844887Schin case ':': 6854887Schin break; 6864887Schin case '-': 6874887Schin n = 0; 6884887Schin continue; 6894887Schin case '+': 6904887Schin n = 1; 6914887Schin continue; 6924887Schin case 'i': 6934887Schin if (n) 6944887Schin f |= GLOB_ICASE; 6954887Schin else 6964887Schin f &= ~GLOB_ICASE; 6974887Schin continue; 6984887Schin case 'M': 6994887Schin if (n) 7004887Schin f |= GLOB_BRACE; 7014887Schin else 7024887Schin f &= ~GLOB_BRACE; 7034887Schin continue; 7044887Schin case 'N': 7054887Schin if (n) 7064887Schin f &= ~GLOB_NOCHECK; 7074887Schin else 7084887Schin f |= GLOB_NOCHECK; 7094887Schin continue; 710*8462SApril.Chin@Sun.COM case 'O': 7114887Schin if (n) 7124887Schin f |= GLOB_STARSTAR; 7134887Schin else 7144887Schin f &= ~GLOB_STARSTAR; 7154887Schin continue; 7164887Schin case ')': 7174887Schin flags = (gp->gl_flags = f) & 0xffff; 7184887Schin if (f & GLOB_ICASE) 7194887Schin gp->re_flags |= REG_ICASE; 7204887Schin else 7214887Schin gp->re_flags &= ~REG_ICASE; 7224887Schin if (x) 7234887Schin optlen = pat - (char*)pattern; 7244887Schin break; 7254887Schin default: 7264887Schin x = 0; 7274887Schin continue; 7284887Schin } 7294887Schin break; 7304887Schin } 7314887Schin } 7324887Schin top = ap = (globlist_t*)stakalloc((optlen ? 2 : 1) * strlen(pattern) + sizeof(globlist_t) + suflen + gp->gl_extra); 7334887Schin ap->gl_next = 0; 7344887Schin ap->gl_flags = 0; 7354887Schin ap->gl_begin = ap->gl_path + gp->gl_extra; 7364887Schin pat = strcopy(ap->gl_begin, pattern + optlen); 7374887Schin if (suflen) 7384887Schin pat = strcopy(pat, gp->gl_suffix); 7394887Schin gp->gl_pat = optlen ? strncpy(gp->gl_opt = pat + 1, pattern, optlen) : (char*)0; 7404887Schin suflen = 0; 7414887Schin if (!(flags & GLOB_LIST)) 7424887Schin gp->gl_match = 0; 7434887Schin do 7444887Schin { 7454887Schin gp->gl_rescan = ap->gl_next; 7464887Schin glob_dir(gp, ap); 7474887Schin } while (!gp->gl_error && (ap = gp->gl_rescan)); 7484887Schin if (gp->gl_pathc == skip) 7494887Schin { 7504887Schin if (flags & GLOB_NOCHECK) 7514887Schin { 7524887Schin gp->gl_pathc++; 7534887Schin top->gl_next = gp->gl_match; 7544887Schin gp->gl_match = top; 7554887Schin strcopy(top->gl_path + gp->gl_extra, nocheck); 7564887Schin } 7574887Schin else 7584887Schin gp->gl_error = GLOB_NOMATCH; 7594887Schin } 7604887Schin if (flags & GLOB_LIST) 7614887Schin gp->gl_list = gp->gl_match; 7624887Schin else 7634887Schin { 7644887Schin argv = (char**)stakalloc((gp->gl_pathc + extra) * sizeof(char*)); 7654887Schin if (gp->gl_flags & GLOB_APPEND) 7664887Schin { 7674887Schin skip += --extra; 7684887Schin memcpy(argv, gp->gl_pathv, skip * sizeof(char*)); 7694887Schin av = argv + skip; 7704887Schin } 7714887Schin else 7724887Schin { 7734887Schin av = argv; 7744887Schin while (--extra > 0) 7754887Schin *av++ = 0; 7764887Schin } 7774887Schin gp->gl_pathv = argv; 7784887Schin argv = av; 7794887Schin ap = gp->gl_match; 7804887Schin while (ap) 7814887Schin { 7824887Schin *argv++ = ap->gl_path + gp->gl_extra; 7834887Schin ap = ap->gl_next; 7844887Schin } 7854887Schin *argv = 0; 7864887Schin if (!(flags & GLOB_NOSORT) && (argv - av) > 1) 7874887Schin { 7884887Schin strsort(av, argv - av, strcoll); 7894887Schin if (gp->gl_starstar > 1) 7904887Schin av[gp->gl_pathc = struniq(av, argv - av)] = 0; 7914887Schin gp->gl_starstar = 0; 7924887Schin } 7934887Schin } 7944887Schin if (gp->gl_starstar > 1) 7954887Schin gp->gl_flags &= ~GLOB_STARSTAR; 7964887Schin if (gp->gl_stak) 7974887Schin stakinstall(oldstak, 0); 7984887Schin return gp->gl_error; 7994887Schin } 8004887Schin 8014887Schin void 8024887Schin globfree(glob_t* gp) 8034887Schin { 8044887Schin if ((gp->gl_flags & GLOB_MAGIC) == GLOB_MAGIC) 8054887Schin { 8064887Schin gp->gl_flags &= ~GLOB_MAGIC; 8074887Schin if (gp->gl_stak) 8084887Schin stkclose(gp->gl_stak); 8094887Schin if (gp->gl_ignore) 8104887Schin regfree(gp->gl_ignore); 8114887Schin if (gp->gl_ignorei) 8124887Schin regfree(gp->gl_ignorei); 8134887Schin } 8144887Schin } 815