sh.glob.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 846 行 · 第 1/2 页

C
846
字号
#ifndef lintstatic	char	*sccsid = "@(#)sh.glob.c	4.1	(ULTRIX)	7/17/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1988 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************/#include "sh.h"#include <sys/dir.h>/* * C Shell * Modification History * * 006 - Bob Fontaine and Gary A. Gaudet - Fri May 18 1990 *	Backed out fix in 004 below for QAR #00649 because the fix introduced *	a bug in that *.* also matched all . files include . and .. * * 005 - Gary A. Gaudet - Wed Jan 31 13:22:30 EST 1990 *	Fixed escaping command substitution and variable expansion in heredoc * * 004	Mon Dec 18 15:41:53 EST 1989, Gary A. Gaudet *	fixed u32_qar #00664: "set a '`pwd`'; echo `a`" dumps core *	fixed u32_qar #00649: "echo \.*" doesn't match files * * 003	12-Nov-88, Al Delorey (afd). *	Use "ifdef CSHEDIT" around the cmd line edit code. * * 002	20-Sep-88, Al Delorey (afd). *	Added command line edit capability: call lex with 2nd *	   arg of 0 (meaning dont't use editword to get words). * * 001 Sat Aug 13 15:28:57 EDT 1988, Gary A. Gaudet *	merging mips & ultrix for 8 bit clean and bug fixes */int	globcnt;char	*globchars =	"`{[*?";char	*gpath, *gpathp, *lastgpathp;int	globbed;bool	noglob;bool	nonomatch;char	*entp;char	**sortbas;int	sortscmp();#define sort()	qsort((char *)sortbas, &gargv[gargc] - sortbas, \		      sizeof(*sortbas), sortscmp), sortbas = &gargv[gargc]char **glob(v)	register char **v;{	char agpath[BUFSIZ];	char *agargv[GAVSIZ];	gpath = agpath;	gpathp = gpath;	*gpathp = 0;	lastgpathp = &gpath[sizeof agpath - 2];	ginit(agargv);	globcnt = 0;#ifdef GDEBUG	printf("glob entered: "); blkpr(v); printf("\n");#endif	noglob = adrof("noglob") != 0;	nonomatch = adrof("nonomatch") != 0;	globcnt = noglob | nonomatch;	while (*v)		collect(*v++);#ifdef GDEBUG	printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");#endif	if (globcnt == 0 && (gflag&1)) {		blkfree(gargv), gargv = 0;		return (0);	} else		return (gargv = copyblk(gargv));}ginit(agargv)	char **agargv;{	agargv[0] = 0;	gargv = agargv;	sortbas = agargv;	gargc = 0;	gnleft = NCARGS - 4;}collect(as)	register char *as;{	register int i;	if (any('`', as)) {#ifdef GDEBUG		printf("doing backp of %s\n", as);#endif		(void) dobackp(as, 0);#ifdef GDEBUG		printf("backp done, acollect'ing\n");#endif		for (i = 0; i < pargc; i++)			if (noglob) {				Gcat(pargv[i], "");				sortbas = &gargv[gargc];			} else				acollect(pargv[i]);		if (pargv)			blkfree(pargv), pargv = 0;#ifdef GDEBUG		printf("acollect done\n");#endif	} else if (noglob || eq(as, "{") || eq(as, "{}")) {		Gcat(as, "");		sort();	} else		acollect(as);}acollect(as)	register char *as;{	register int ogargc = gargc;	gpathp = gpath;	*gpathp = 0;	globbed = 0;	expand(as);	if (gargc == ogargc) {		if (nonomatch) {			Gcat(as, "");			sort();		}	} else		sort();}/* * String compare for qsort.  Also used by filec code in sh.file.c. */sortscmp(a1, a2)	char **a1, **a2;{	 return (strcmp(*a1, *a2));}expand(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))					error("Unknown user: %s", gpath + 1);				(void) strcpy(gpath, gpath + 1);			} else				(void) strcpy(gpath, value("home"));			gpathp = strend(gpath);		}	}	while (!any(((*cs & TRIM) == QUOTECHAR ? (*++cs & TRIM) | QUOTE : *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 != '/') {		if ((*cs & TRIM) != QUOTECHAR)  /* 004 - GAG */			gpathp--;		cs--;	}	if ((*cs & TRIM) == QUOTECHAR)		gpathp++;	if (*cs == '/')		cs++, gpathp++;	*gpathp = 0;	if (*oldcs == '{') {		(void) execbrc(cs, NOSTR);		return;	}	matchdir(cs);endit:	gpathp = sgpathp;	*gpathp = 0;}matchdir(pattern)	char *pattern;{	struct stat stb;	register struct direct *dp;	register DIR *dirp;	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:	Perror(gpath);}execbrc(p, s)	char *p, *s;{	char restbuf[BUFSIZ + 2];	register char *pe, *pm, *pl;	int brclev = 0;	char *lm, savec, *sgpathp;	int flag;	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;		if (!*pe)			error("Missing ]");		continue;	}pend:	if (brclev || !*pe)		error("Missing }");	for (pl = pm = p; pm <= pe; pm++) {	flag = 0;	if ((*pm  & TRIM) == QUOTECHAR) {		pm++;		flag = QUOTE;	}	switch ((*pm & TRIM) | flag) {	case '{':		brclev++;		continue;	case '}':		if (brclev) {			brclev--;			continue;		}		goto doit;	case ','|QUOTE:	case ',':		if (brclev)			continue;doit:		savec = *pm;		*pm = 0;		(void) strcpy(lm, pl);		(void) 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;		continue;	case '[':		for (pm++; *pm && *pm != ']'; pm++)			continue;		if (!*pm)			error("Missing ]");		continue;	}}	return (0);}match(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);}amatch(s, p)	register char *s, *p;{	register int scc;	int ok, lc;	char *sgpathp;	struct stat stb;	int c, cc;	globbed = 1;	for (;;) {		if ((scc = (*s++ & TRIM)) == QUOTECHAR)			scc = *s++ & TRIM;		switch (c = (*p++ & TRIM)) {		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)				error("Missing ]");			continue;		case '*':			if (!*p)				return (1);			if (*p == '/') {				p++;				goto slash;			}			for (s--; *s; s++)				if (amatch(s, p))					return (1);			return (0);

⌨️ 快捷键说明

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