1BSD/s8/glob2.c

Compare this file to the similar file:
Show the results in this format:

#

/*
 * glob1 libs command arg ...
 *
 * Modified by: Bill Joy (UCB) Oct 1976
 *
 *  takes library name string from the shell
 *  allows patterns to match directory names, i.e. "/mnt/c*?/.q"
 *  knows about pascal object and forks px's
 */

char	usagestr[] "usage: glob2 libs command arg ...";

char	shell[] "/bin/sh";
char	px[]	"/bin/px";

#define	PCXN	0404
#define	E2BIG	7
#define	ENOEXEC	8
#define	ENOENT	2

#define	STRSIZ	522
#define	PTHSIZ	100

char	*lib;

char	ab[STRSIZ];
char	*ava[200];
char	**av &ava[1];
char	*string ab;
int	ncoll;

char	path[100];
char	*pathp path;
int	globbed;
char	*entp;

int	errno;
int	stbuff[18];

main(argc, argv)
char *argv[];
{
	register char *cp1, *cp2, *cpl;

	if (argc < 4)
		panic(usagestr);
	argv++;
	argc--;
	lib = *argv++;
	argc--;
	*av++ = *argv++;
	argc--;
	while (argc)
	{
		collect(*argv++);
		argc--;
	}
	if (ncoll==0)
		panic("No match");
	cp1 = ava[1];
	while(*cp1 && *cp1 != '/')
		cp1++;
	if (*cp1 || getuid())
		execute(ava[1], &ava[1]);
	if (!*cp1)
	{
		if (cpl = lib)
			for(;;)
			{
				while ((*cpl & 0177) == ' ')
					cpl++;
				if (!*cpl)
					break;
				cp1 = path;
				while (*cpl =& 0177)
					if (*cpl == ' ')
						break;
					else if (cp1 >= &path[PTHSIZ-2])
						patherr();
					else
						*cp1++ = *cpl++;
				*cp1++ = '/';
				cp2 = ava[1];
				while(*cp1++ = *cp2++)
					if (cp1 >= &path[PTHSIZ])
						patherr();
				execute(path, &ava[1]);
			}
		cp1 = path;
		cp2 = "/usr/bin/";
		while(*cp1++ = *cp2++)
			;
		cp1--;
		cp2 = ava[1];
		while(*cp1++ = *cp2++)
			if (cp1 >= &path[PTHSIZ])
				patherr();
		execute(path+4, &ava[1]);
		execute(path, &ava[1]);
	}
	prs(ava[1]);
	panic(": not found");
}

execute(afile, aarg)
char *afile;
char **aarg;
{
	register char *file, **arg;
	register i;
	int w;

	arg = aarg;
	file = afile;
	execv(file, arg);
	if (errno==ENOEXEC) {
		arg[0] = file;
		*--arg = shell;
		i = open(file, 0);
		if (i >= 0) {
			if (read(i, &w, 2) == 2 && w == PCXN)
				*arg = px;
			close(i);
		}
		execv(*arg, arg);
		prs("no ");
		prs(*arg);
		panic("!!");
	} else if (errno==E2BIG)
		toolong();
}

collect(as)
{
	char **oav;

	oav = av;
	globbed = 0;
	expand(as);
	sort(oav);
}

sort(oav)
char **oav;
{
	register char **p1, **p2, **c;

	p1 = oav;
	while (p1 < av-1) {
		p2 = p1;
		while(++p2 < av) {
			if (compar(*p1, *p2) > 0) {
				c = *p1;
				*p1 = *p2;
				*p2 = c;
			}
		}
		p1++;
	}
}

expand(as)
char *as;
{
	register char *cs;
	char *spathp;
	register int dirf;
	static struct {
		int	ino;
		char	name[16];
	} entry;

	spathp = pathp;
	cs = as;
	while (*cs != '*' && *cs != '?' && *cs != '[') {
		if (pathp >= &path[PTHSIZ])
			patherr();
		else if ((*pathp++ = *cs++) == 0) {
			if (!globbed)
				*av++ = cat(as, "");
			else if (stat(path, &stbuff) >= 0) {
				*av++ = cat(path, "");
				ncoll++;
			}
			goto endit;
		}
	}
	pathp = spathp;
	cs--;
	while (cs >= as && *cs != '/')
		cs--;
	while (as <= cs)
		if (pathp >= &path[PTHSIZ])
			patherr();
		else
			*pathp++ = *as++;
	*pathp = 0;
	dirf = open(path, 0);
	if (dirf<0)
		if (globbed)
			goto endit;
		else {
			prs(path);
			panic(": cannot open");
		}
	globbed++;
	cs++;
	while (read(dirf, &entry, 16) == 16) {
		if (entry.ino==0)
			continue;
		if (match(entry.name, cs)) {
			*av++ = cat(path, entry.name);
			ncoll++;
		}
	}
	close(dirf);
endit:
	pathp = spathp;
	*pathp = 0;
}

toolong()
{
	panic("Arg list too long");
}

patherr()
{
	prs("Path too long: ");
	panic(path);
}

match(s, p)
char *s, *p;
{
	register c, sentp;

	if (*s == '.' && *p != '.')
		return(0);
	sentp = entp;
	entp = s;
	c = amatch(s, p);
	entp = sentp;
	return(c);
}

amatch(as, ap)
char *as, *ap;
{
	register char *s, *p;
	register scc;
	int c, cc, ok, lc;
	char *spathp;

	s = as;
	p = ap;
nextc:
	if(scc = *s++ & 0177)
		if ((scc =& 0177) == 0)
			scc = 0200;
	switch (c = *p++) {
		case '[':
			ok = 0;
			lc = 077777;
			while (cc = *p++) {
				if (cc == ']') {
					if (ok)
						goto nextc;
					else
						return(0);
				} else if (cc == '-') {
					if (lc <= scc && scc <= *p++)
						ok++;
				} else
					if (scc == (lc = cc))
						ok++;
			}
			panic("missing ]");
		case '*':
			if(*p == '\0')
				return(1);
			else if (*p == '/') {
				p++;
				goto slash;
			}
			s--;
			while(*s)
				if (amatch(s, p))
					return(1);
				else
					s++;
			return(0);
		case '\0':
			return(scc == '\0');
		default:
			if (c == scc)
				goto nextc;
			else
				return(0);
		case '?':
			if (scc != '\0')
				goto nextc;
			else
				return(0);
		case '/':
			if (scc == '\0') {
slash:
				s = entp;
				spathp = pathp;
				while (*pathp = *s++)
					pathp++;
				*pathp++ = '/';
				*pathp = 0;
				if (stat(path, &stbuff) == 0)
					if ((stbuff[2] & 060000) == 040000)
						if (*p == 0) {
							*av++ = cat(path, "");
							ncoll++;
						} else
							expand(p);
				pathp = spathp;
				*pathp = 0;
			}
			return(0);
	}
}

compar(as1, as2)
char *as1, *as2;
{
	register char *s1, *s2;

	s1 = as1;
	s2 = as2;
	while (*s1++ == *s2)
		if (*s2++ == 0)
			return(0);
	if (*--s1 == '/')
		return(-1);
	else if (*s2 == '/')
		return(1);
	else
		return (*s1 - *s2);
}

cat(as1, as2)
char *as1, *as2;
{
	register char *s1, *s2;

	s2 = string;
	s1 = as1;
	while (*s2++ = (*s1++ & 0177))
		if (s2 >= &ab[STRSIZ])
			toolong();
	s1 = as2;
	s2--;
	while (*s2++ = *s1++)
		if (s2 > &ab[STRSIZ])
			toolong();
	s1 = string;
	string = s2;
	return(s1);
}

prs(str)
char *str;
{
	register char *cp;

	cp = str;
	while(*cp)
		cp++;
	write(2, str, cp-str);
}

panic(str)
{
	prs(str);
	write(2, &"\n", 1);
	exit(1);
}