⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glob.c

📁 UNIX FTP client
💻 C
字号:
/* * 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. *//* * From: @(#)glob.c	5.9 (Berkeley) 2/25/91 */char glob_rcsid[] =   "$Id: glob.c,v 1.5 1996/08/14 23:27:28 dholland Exp $";/* * C-shell glob for random programs. */#include <sys/param.h>#include <sys/stat.h>#include <dirent.h>#include <pwd.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include "ftp_var.h"  /* for protos only */#include "glob.h"#define	QUOTE 0200#define	TRIM 0177#define	eq(a,b)		(strcmp(a, b)==0)#define	GAVSIZ		(ARG_MAX/6)#define	isdir(d)	((d.st_mode & S_IFMT) == S_IFDIR)const char *globerr;extern const char *home;typedef struct {    const char *text;} centry;typedef struct {    char *text;} entry;static entry *gargv;	/* Pointer to the (stack) arglist */static entry *sortbas;static int gargc;	/* Number args in gargv */static int gnleft;      /* space left before we hit max args length */static short gflag;static int globcnt;static const char *globchars = "`{[*?";static char *gpath;static char *gpathp, *lastgpathp;static int globbed;static const char *entp;static int tglob(char c);static char *strspl(const char *, const char *);static char *strend(char *);static char **copyblk(entry *);static char **cloneblk(const centry *);static void addpath(char c);static void acollect(const char *);static void collect(const char *);static void expand(const char *);static void Gcat(const char *, const char *);static void ginit(entry *);static void matchdir(const char *);static void rscan(centry *, int (*f)(char));static void sort(void);static void efree(entry *);static int amatch(const char *, const char *);static int execbrc(const char *, const char *);static int match(const char *, const char *);static int gethdir(char *homedir);static int letter(char c);static int digit(char c);static int any(int c, const char *s);char **ftpglob(const char *v){	char agpath[BUFSIZ];	entry agargv[GAVSIZ];	centry vv[2];	vv[0].text = v;	vv[1].text = NULL;	gflag = 0;	rscan(vv, tglob);	if (gflag == 0) {		return cloneblk(vv);	}	globerr = 0;	gpath = agpath; 	gpathp = gpath; 	*gpathp = 0;	lastgpathp = agpath + sizeof(agpath) - 2;	ginit(agargv); 	globcnt = 0;	collect(v);	if (globcnt == 0 && (gflag&1)) {		efree(gargv);		gargv = NULL;		return NULL;	} 	else {		char **rv = copyblk(gargv);		gargv = NULL;		return rv;	}}static voidginit(entry *agargv){	agargv[0].text = NULL; 	gargv = agargv; 	sortbas = agargv; 	gargc = 0;	gnleft = ARG_MAX - 4;}static voidcollect(const char *as){	if (eq(as, "{") || eq(as, "{}")) {		Gcat(as, "");		sort();	} 	else {		acollect(as);	}}static voidacollect(const char *as){	int ogargc = gargc;	gpathp = gpath; *gpathp = 0; globbed = 0;	expand(as);	if (gargc != ogargc)		sort();}static voidsort(void){	entry *p1, *p2, c;	entry *Gvp = &gargv[gargc];	p1 = sortbas;	while (p1 < Gvp-1) {		p2 = p1;		while (++p2 < Gvp)			if (strcmp(p1->text, p2->text) > 0)				c = *p1, *p1 = *p2, *p2 = c;		p1++;	}	sortbas = Gvp;}static voidexpand(const char *as){	const char *cs;	const char *oldcs;	char *sgpathp;	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 ~";				(void) strcpy(gpath, gpath + 1);			} 			else {				(void) 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 == '{') {		(void) execbrc(cs, ((char *)0));		return;	}	matchdir(cs);endit:	gpathp = sgpathp;	*gpathp = 0;}static voidmatchdir(const char *pattern){	struct stat stb;	register struct dirent *dp;	DIR *dirp;#if 0#ifdef	__linux__	if (gpath == NULL || *gpath == '\0')		gpath = "./";#endif#endif	dirp = opendir((!gpath || !*gpath) ? "./" : gpath);	if (dirp == NULL) {		if (globbed)			return;		goto patherr2;	}	if (fstat(dirfd(dirp), &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";}static intexecbrc(const char *p, const char *s){	char restbuf[BUFSIZ + 2];	const char *pe, *pm, *pl;	int brclev = 0;	char *lm, *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:#if 0		savec = *pm;		*pm = 0;		strcpy(lm, pl);		*pm = savec;#else		strncpy(lm, pl, pm-pl);		lm[pm-pl] = 0;#endif		(void) strcat(restbuf, pe + 1);		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);}static intmatch(const char *s, const char *p){	int c;	const 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 intamatch(const char *s, const 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++) != 0) {				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);		}	}}static intGmatch(const char *s, const 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++) != 0) {				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;		}	}}static voidGcat(const char *s1, const char *s2){	int len = strlen(s1) + strlen(s2) + 1;	if (len >= gnleft || gargc >= GAVSIZ - 1) {		globerr = "Arguments too long";	}	else {		gargc++;		gnleft -= len;		gargv[gargc].text = NULL;		gargv[gargc - 1].text = strspl(s1, s2);	}}static voidaddpath(char c){	if (gpathp >= lastgpathp)		globerr = "Pathname too long";	else {		*gpathp++ = c;		*gpathp = 0;	}}static voidrscan(centry *t, int (*f)(char)){	const char *p;	char c;	while ((p = (t++)->text) != NULL) {		if (f == tglob)			if (*p == '~')				gflag |= 2;			else if (eq(p, "{") || eq(p, "{}"))				continue;		while ((c = *p++) != 0)			(*f)(c);	}}static inttglob(char c){	if (any(c, globchars))		gflag |= c == '{' ? 2 : 1;	return (c);}static intletter(char c){	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_';}static intdigit(char c){	return (c >= '0' && c <= '9');}static intany(int c, const char *s){	while (*s) if (*s++ == c) return 1;	return 0;}static intcblklen(const centry *av){	int i = 0;	while ((av++)->text) i++;	return i;}static intblklen(const entry *av){	int i = 0;	while ((av++)->text) i++;	return i;}voidblkfree(char **av){	int i;	for (i=0; av[i]; i++) free(av[i]);}staticvoid efree(entry *av) {    int i;    for (i=0; av[i].text; i++) free(av[i].text);}staticchar *strspl(const char *cp, const char *dp){	char *ep = malloc(strlen(cp) + strlen(dp) + 1);	if (ep == NULL)	fatal("Out of memory");	strcpy(ep, cp);	strcat(ep, dp);	return ep;}static char **copyblk(entry *v){	int i;	char **nv = malloc((blklen(v) + 1) * sizeof(char **));	if (nv == NULL) fatal("Out of memory");	for (i=0; v[i].text; i++) {	    nv[i] = v[i].text;	    v[i].text = NULL;	}	nv[i] = NULL;	return nv;}staticchar **cloneblk(const centry *v){	int i;	char **nv = malloc((cblklen(v) + 1) * sizeof(char **));	if (nv == NULL) fatal("Out of memory");	for (i=0; v[i].text; i++) {	    nv[i] = strdup(v[i].text);	}	nv[i] = NULL;	return nv;}staticchar *strend(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. */static intgethdir(char *homedir){	register struct passwd *pp = getpwnam(homedir);	if (!pp || homedir + strlen(pp->pw_dir) >= lastgpathp)		return 1;	strcpy(homedir, pp->pw_dir);	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -