📄 glob.c
字号:
/* $Header: glob.c,v 2.0 85/11/21 07:22:47 jqj Exp $ *//* * $Log: glob.c,v $ * Revision 2.0 85/11/21 07:22:47 jqj * 4.3BSD standard release * * Revision 1.2 85/11/21 07:04:29 jqj * added RCS header line * */#ifndef lintstatic char sccsid[] = "@(#)glob.c 4.2 3/1/83";#endif/* * C-shell glob for random programs. */#include <sys/param.h>#include <sys/stat.h>#include <sys/dir.h>#include <stdio.h>#include <errno.h>#include <pwd.h>#define QUOTE 0200#define TRIM 0177#define eq(a,b) (strcmp(a, b)==0)#define GAVSIZ (NCARGS/6)#define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)static char **gargv; /* Pointer to the (stack) arglist */static short gargc; /* Number args in gargv */static short gnleft;static short gflag;static int tglob();char **glob();char *globerr;char *home;struct passwd *getpwnam();extern int errno;static char *strspl(), **copyblk(), *strend();char *malloc(), *strcpy(), *strcat();static int globcnt;char *globchars = "`{[*?";static char *gpath, *gpathp, *lastgpathp;static int globbed;static char *entp;static char **sortbas;char **glob(v) register char *v;{ char agpath[BUFSIZ]; char *agargv[GAVSIZ]; char *vv[2]; vv[0] = v; vv[1] = 0; gflag = 0; rscan(vv, tglob); if (gflag == 0) return (copyblk(vv)); globerr = 0; gpath = agpath; gpathp = gpath; *gpathp = 0; lastgpathp = &gpath[sizeof agpath - 2]; ginit(agargv); globcnt = 0; collect(v); if (globcnt == 0 && (gflag&1)) { blkfree(gargv), gargv = 0; return (0); } else return (gargv = copyblk(gargv));}staticginit(agargv) char **agargv;{ agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0; gnleft = NCARGS - 4;}staticcollect(as) register char *as;{ if (eq(as, "{") || eq(as, "{}")) { Gcat(as, ""); sort(); } else acollect(as);}staticacollect(as) register char *as;{ register int ogargc = gargc; gpathp = gpath; *gpathp = 0; globbed = 0; expand(as); if (gargc != ogargc) sort();}staticsort(){ register char **p1, **p2, *c; char **Gvp = &gargv[gargc]; p1 = sortbas; while (p1 < Gvp-1) { p2 = p1; while (++p2 < Gvp) if (strcmp(*p1, *p2) > 0) c = *p1, *p1 = *p2, *p2 = c; p1++; } sortbas = Gvp;}staticexpand(as) char *as;{ register char *cs; register char *sgpathp, *oldcs; struct stat stb; sgpathp = gpathp; cs = as; if (*cs == '~' && gpathp == gpath) { addpath('~'); for (cs++; letter(*cs) || digit(*cs) || *cs == '-';) addpath(*cs++); if (!*cs || *cs == '/') { if (gpathp != gpath + 1) { *gpathp = 0; if (gethdir(gpath + 1)) globerr = "Unknown user name after ~"; strcpy(gpath, gpath + 1); } else strcpy(gpath, home); gpathp = strend(gpath); } } while (!any(*cs, globchars)) { if (*cs == 0) { if (!globbed) Gcat(gpath, ""); else if (stat(gpath, &stb) >= 0) { Gcat(gpath, ""); globcnt++; } goto endit; } addpath(*cs++); } oldcs = cs; while (cs > as && *cs != '/') cs--, gpathp--; if (*cs == '/') cs++, gpathp++; *gpathp = 0; if (*oldcs == '{') { execbrc(cs, ((char *)0)); return; } matchdir(cs);endit: gpathp = sgpathp; *gpathp = 0;}staticmatchdir(pattern) char *pattern;{ struct stat stb; register struct direct *dp; DIR *dirp; register int cnt; dirp = opendir(gpath); if (dirp == NULL) { if (globbed) return; goto patherr2; } if (fstat(dirp->dd_fd, &stb) < 0) goto patherr1; if (!isdir(stb)) { errno = ENOTDIR; goto patherr1; } while ((dp = readdir(dirp)) != NULL) { if (dp->d_ino == 0) continue; if (match(dp->d_name, pattern)) { Gcat(gpath, dp->d_name); globcnt++; } } closedir(dirp); return;patherr1: closedir(dirp);patherr2: globerr = "Bad directory components";}staticexecbrc(p, s) char *p, *s;{ char restbuf[BUFSIZ + 2]; register char *pe, *pm, *pl; int brclev = 0; char *lm, savec, *sgpathp; for (lm = restbuf; *p != '{'; *lm++ = *p++) continue; for (pe = ++p; *pe; pe++) switch (*pe) { case '{': brclev++; continue; case '}': if (brclev == 0) goto pend; brclev--; continue; case '[': for (pe++; *pe && *pe != ']'; pe++) continue; continue; }pend: brclev = 0; for (pl = pm = p; pm <= pe; pm++) switch (*pm & (QUOTE|TRIM)) { case '{': brclev++; continue; case '}': if (brclev) { brclev--; continue; } goto doit; case ','|QUOTE: case ',': if (brclev) continue;doit: savec = *pm; *pm = 0; strcpy(lm, pl); strcat(restbuf, pe + 1); *pm = savec; if (s == 0) { sgpathp = gpathp; expand(restbuf); gpathp = sgpathp; *gpathp = 0; } else if (amatch(s, restbuf)) return (1); sort(); pl = pm + 1; if (brclev) return (0); continue; case '[': for (pm++; *pm && *pm != ']'; pm++) continue; if (!*pm) pm--; continue; } if (brclev) goto doit; return (0);}staticmatch(s, p) char *s, *p;{ register int c; register char *sentp; char sglobbed = globbed; if (*s == '.' && *p != '.') return (0); sentp = entp; entp = s; c = amatch(s, p); entp = sentp; globbed = sglobbed; return (c);}staticamatch(s, p) register char *s, *p;{ register int scc; int ok, lc; char *sgpathp; struct stat stb; int c, cc; globbed = 1; for (;;) { scc = *s++ & TRIM; switch (c = *p++) { case '{': return (execbrc(p - 1, s - 1)); case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc == ']') { if (ok) break; return (0); } if (cc == '-') { if (lc <= scc && scc <= *p++) ok++; } else if (scc == (lc = cc)) ok++; } if (cc == 0) if (ok) p--; else return 0; continue; case '*': if (!*p) return (1); if (*p == '/') { p++; goto slash; } s--; do { if (amatch(s, p)) return (1); } while (*s++); return (0); case 0: return (scc == 0); default: if (c != scc) return (0); continue; case '?': if (scc == 0) return (0); continue; case '/': if (scc) return (0);slash: s = entp; sgpathp = gpathp; while (*s) addpath(*s++); addpath('/'); if (stat(gpath, &stb) == 0 && isdir(stb)) if (*p == 0) { Gcat(gpath, ""); globcnt++; } else expand(p); gpathp = sgpathp; *gpathp = 0; return (0); } }}staticGmatch(s, p) register char *s, *p;{ register int scc; int ok, lc; int c, cc; for (;;) { scc = *s++ & TRIM; switch (c = *p++) { case '[': ok = 0; lc = 077777; while (cc = *p++) { if (cc == ']') { if (ok) break; return (0); } if (cc == '-') { if (lc <= scc && scc <= *p++) ok++; } else if (scc == (lc = cc)) ok++; } if (cc == 0) if (ok) p--; else return 0; continue; case '*': if (!*p) return (1); for (s--; *s; s++) if (Gmatch(s, p)) return (1); return (0); case 0: return (scc == 0); default: if ((c & TRIM) != scc) return (0); continue; case '?': if (scc == 0) return (0); continue; } }}staticGcat(s1, s2) register char *s1, *s2;{ register int len = strlen(s1) + strlen(s2) + 1; if (len >= gnleft || gargc >= GAVSIZ - 1) globerr = "Arguments too long"; else { gargc++; gnleft -= len; gargv[gargc] = 0; gargv[gargc - 1] = strspl(s1, s2); }}staticaddpath(c) char c;{ if (gpathp >= lastgpathp) globerr = "Pathname too long"; else { *gpathp++ = c; *gpathp = 0; }}staticrscan(t, f) register char **t; int (*f)();{ register char *p, c; while (p = *t++) { if (f == tglob) if (*p == '~') gflag |= 2; else if (eq(p, "{") || eq(p, "{}")) continue; while (c = *p++) (*f)(c); }}staticscan(t, f) register char **t; int (*f)();{ register char *p, c; while (p = *t++) while (c = *p) *p++ = (*f)(c);}statictglob(c) register char c;{ if (any(c, globchars)) gflag |= c == '{' ? 2 : 1; return (c);}statictrim(c) char c;{ return (c & TRIM);}letter(c) register char c;{ return (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '_');}digit(c) register char c;{ return (c >= '0' && c <= '9');}any(c, s) register int c; register char *s;{ while (*s) if (*s++ == c) return(1); return(0);}blklen(av) register char **av;{ register int i = 0; while (*av++) i++; return (i);}char **blkcpy(oav, bv) char **oav; register char **bv;{ register char **av = oav; while (*av++ = *bv++) continue; return (oav);}blkfree(av0) char **av0;{ register char **av = av0; while (*av) free(*av++); free((char *)av0);}staticchar *strspl(cp, dp) register char *cp, *dp;{ register char *ep = malloc((unsigned)(strlen(cp) + strlen(dp) + 1)); if (ep == (char *)0) fatal("Out of memory"); strcpy(ep, cp); strcat(ep, dp); return (ep);}staticchar **copyblk(v) register char **v;{ register char **nv = (char **)malloc((unsigned)((blklen(v) + 1) * sizeof(char **))); if (nv == (char **)0) fatal("Out of memory"); return (blkcpy(nv, v));}staticchar *strend(cp) register char *cp;{ while (*cp) cp++; return (cp);}/* * Extract a home directory from the password file * The argument points to a buffer where the name of the * user whose home directory is sought is currently. * We write the home directory of the user back there. */gethdir(home) char *home;{ register struct passwd *pp = getpwnam(home); if (pp == 0) return (1); strcpy(home, pp->pw_dir); return (0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -