glob.c
资源名称:socks5.zip [点击查看]
上传用户:sddyfurun
上传日期:2007-01-04
资源大小:525k
文件大小:12k
源码类别:
代理服务器
开发平台:
Unix_Linux
- /*
- * Copyright (c) 1980 Regents of the University of California.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
- /*
- * C-shell glob for random programs.
- */
- #include "ftp_var.h"
- #ifdef HAVE_SYS_STAT_H
- #include <sys/stat.h>
- #endif
- #ifdef HAVE_DIRENT_H
- # include <dirent.h>
- # define NLENGTH(direct) (strlen((direct)->d_name))
- #else /* not HAVE_DIRENT_H */
- # define dirent direct
- # define NLENGTH(direct) ((direct)->d_namlen)
- # ifdef HAVE_SYS_NDIR_H
- # include <sys/ndir.h>
- # endif /* HAVE_SYS_NDIR_H */
- # ifdef HAVE_SYS_DIR_H
- # include <sys/dir.h>
- # endif /* HAVE_SYS_DIR_H */
- # ifdef HAVE_NDIR_H
- # include <ndir.h>
- # endif /* HAVE_NDIR_H */
- #endif /* HAVE_DIRENT_H */
- #include <pwd.h>
- #include <errno.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #define QUOTE 0200
- #define TRIM 0177
- #define eq(a,b) (strcmp(a, b)==0)
- #ifndef NCARGS
- #define NCARGS 256
- #endif
- #define GAVSIZ (NCARGS/6)
- #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
- static char **gargv; /* Pointer to the (stack) arglist */
- static int gargc; /* Number args in gargv */
- static int gnleft;
- static short gflag;
- static char *gpath, *gpathp, *lastgpathp;
- static int globbed, globcnt;
- static char **sortbas;
- static char *entp;
- char *globchars = "`{[*?";
- char *globerr;
- char *home;
- extern int errno;
- static int match P((char *, char *));
- static int execbrc P((char *, char *));
- int any(register int c, register char *s) {
- while (*s) if (*s++ == c) return(1);
- return(0);
- }
- static int tglob(register char c) {
- if (any(c, globchars)) gflag |= c == '{' ? 2 : 1;
- return (c);
- }
- int letter(register char c) {
- return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
- }
- int digit(register char c) {
- return (c >= '0' && c <= '9');
- }
- int blklen(register char **av) {
- register int i = 0;
- while (*av++) i++;
- return (i);
- }
- char ** blkcpy(char **oav, register char **bv) {
- register char **av = oav;
- while ((*av++ = *bv++));
- return (oav);
- }
- void blkfree(char **av0) {
- register char **av = av0;
- /* if gflag is 0, we did not malloc() the space! */
- if (!av || !gflag) return;
- while (*av) free(*av++);
- }
- static void ginit(char **agargv) {
- agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
- gnleft = NCARGS - 4;
- }
- static void sort() {
- 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;
- }
- static void addpath(char c) {
- if (gpathp >= lastgpathp)
- globerr = "Pathname too long";
- else {
- *gpathp++ = c;
- *gpathp = 0;
- }
- }
- static char *strspl(register char *cp, register char *dp) {
- register char *ep = (char *)malloc((unsigned)(strlen(cp) + strlen(dp) + 1));
- if (ep == NULL) fatal("Out of memory");
- strcpy(ep, cp);
- strcat(ep, dp);
- return (ep);
- }
- static char *strend(register char *cp) {
- while (*cp) cp++;
- return (cp);
- }
- static void Gcat(register char *s1, register char *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);
- }
- }
- /*
- * 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.
- */
- int gethdir(char *home) {
- register struct passwd *pp = getpwnam(home);
- if (!pp || home + strlen(pp->pw_dir) >= lastgpathp) return (1);
- strcpy(home, pp->pw_dir);
- return (0);
- }
- static void matchdir(char *pattern) {
- register struct dirent *dp;
- DIR *dirp;
- /*
- * opendir() does not accept a null directory string
- * to mean the current directory. Must use ".". But leave
- * the gpath prefix alone
- */
- if (*gpath == 0)
- dirp = opendir(".");
- else
- dirp = opendir(gpath);
- if (dirp == NULL) {
- if (globbed) return;
- goto patherr2;
- }
- #ifndef linux
- {
- struct stat stb;
- if (fstat(dirp->dd_fd, &stb) < 0)
- goto patherr1;
- if (!isdir(stb)) {
- errno = ENOTDIR;
- goto patherr1;
- }
- }
- #endif /* linux */
- 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;
- #ifndef linux
- patherr1:
- #endif
- closedir(dirp);
- patherr2:
- globerr = "Bad directory components";
- }
- static void expand(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;
- }
- static int amatch(register char *s, register char *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) return 0;
- else p--;
- 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);
- }
- }
- }
- static int match(char *s, char *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);
- }
- static int execbrc(char *p, char *s) {
- char restbuf[BUFSIZ + 2];
- register char *pe, *pm, *pl;
- int brclev = 0;
- char *lm, savec, *sgpathp;
- for (lm = restbuf; *p != '{'; *lm++ = *p++);
- 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;
- }
- 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++);
- if (!*pm) pm--;
- continue;
- }
- if (brclev) goto doit;
- return (0);
- }
- static void acollect(register char *as) {
- register int ogargc = gargc;
- gpathp = gpath; *gpathp = 0; globbed = 0;
- expand(as);
- if (gargc != ogargc) sort();
- }
- static void collect(register char *as) {
- if (eq(as, "{") || eq(as, "{}")) {
- Gcat(as, "");
- sort();
- } else
- acollect(as);
- }
- static int Gmatch(register char *s, register char *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) return 0;
- else p--;
- 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;
- }
- }
- }
- static void rscan(register char **t, int (*f)P((char))) {
- 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);
- }
- }
- char **copyblk(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));
- }
- char **ftpglob(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));
- }
- }