172339Sabial#define Extern extern
272339Sabial#include <sys/types.h>
372339Sabial#include <signal.h>
472339Sabial#define _NSIG NSIG
572339Sabial#include <errno.h>
672339Sabial#include <setjmp.h>
772339Sabial#include "sh.h"
872339Sabial/* -------- sh.c -------- */
972339Sabial/*
1072339Sabial * shell
1172339Sabial */
1272339Sabial
1372339Sabial/* #include "sh.h" */
1472339Sabial
1572339Sabialint	intr;
1672339Sabialint	inparse;
1772339Sabialchar	flags['z'-'a'+1];
1872339Sabialchar	*flag = flags-'a';
1972339Sabialchar	*elinep = line+sizeof(line)-5;
2072339Sabialchar	*null	= "";
2172339Sabialint	heedint =1;
2272339Sabialstruct	env	e ={line, iostack, iostack-1,
2372339Sabial		    (xint *)NULL, FDBASE, (struct env *)NULL};
2472339Sabial
2572339Sabialextern	char	**environ;	/* environment pointer */
2672339Sabial
2772339Sabial/*
2872339Sabial * default shell, search rules
2972339Sabial */
3072339Sabialchar	shellname[] = "/bin/sh";
3172339Sabialchar	search[] = ":/bin:/usr/bin";
3272339Sabial
3372339Sabial_PROTOTYPE(void (*qflag), (int)) = SIG_IGN;
3472339Sabial
3572339Sabial_PROTOTYPE(int main, (int argc, char **argv ));
3672339Sabial_PROTOTYPE(int newfile, (char *s ));
3772339Sabial_PROTOTYPE(static char *findeq, (char *cp ));
3872339Sabial_PROTOTYPE(static char *cclass, (char *p, int sub ));
3972339Sabial_PROTOTYPE(void initarea, (void));
4072339Sabial
4172339Sabialint main(argc, argv)
4272339Sabialint argc;
4372339Sabialregister char **argv;
4472339Sabial{
4572339Sabial	register int f;
4672339Sabial	register char *s;
4772339Sabial	int cflag;
4872339Sabial	char *name, **ap;
4972339Sabial	int (*iof)();
5072339Sabial
5172339Sabial	initarea();
5272339Sabial	if ((ap = environ) != NULL) {
5372339Sabial		while (*ap)
5472339Sabial			assign(*ap++, !COPYV);
5572339Sabial		for (ap = environ; *ap;)
5672339Sabial			export(lookup(*ap++));
5772339Sabial	}
5872339Sabial	closeall();
5972339Sabial	areanum = 1;
6072339Sabial
6172339Sabial	shell = lookup("SHELL");
6272339Sabial	if (shell->value == null)
6372339Sabial		setval(shell, shellname);
6472339Sabial	export(shell);
6572339Sabial
6672339Sabial	homedir = lookup("HOME");
6772339Sabial	if (homedir->value == null)
6872339Sabial		setval(homedir, "/");
6972339Sabial	export(homedir);
7072339Sabial
7172339Sabial	setval(lookup("$"), itoa(getpid(), 5));
7272339Sabial
7372339Sabial	path = lookup("PATH");
7472339Sabial	if (path->value == null)
7572339Sabial		setval(path, search);
7672339Sabial	export(path);
7772339Sabial
7872339Sabial	ifs = lookup("IFS");
7972339Sabial	if (ifs->value == null)
8072339Sabial		setval(ifs, " \t\n");
8172339Sabial
8272339Sabial	prompt = lookup("PS1");
8372339Sabial	if (prompt->value == null)
8472339Sabial#ifndef UNIXSHELL
8572339Sabial		setval(prompt, "$ ");
8672339Sabial#else
8772339Sabial		setval(prompt, "% ");
8872339Sabial#endif
8972339Sabial
9072339Sabial	if (geteuid() == 0) {
9172339Sabial		setval(prompt, "# ");
9272339Sabial		prompt->status &= ~EXPORT;
9372339Sabial	}
9472339Sabial	cprompt = lookup("PS2");
9572339Sabial	if (cprompt->value == null)
9672339Sabial		setval(cprompt, "> ");
9772339Sabial
9872339Sabial	iof = filechar;
9972339Sabial	cflag = 0;
10072339Sabial	name = *argv++;
10172339Sabial	if (--argc >= 1) {
10272339Sabial		if(argv[0][0] == '-' && argv[0][1] != '\0') {
10372339Sabial			for (s = argv[0]+1; *s; s++)
10472339Sabial				switch (*s) {
10572339Sabial				case 'c':
10672339Sabial					prompt->status &= ~EXPORT;
10772339Sabial					cprompt->status &= ~EXPORT;
10872339Sabial					setval(prompt, "");
10972339Sabial					setval(cprompt, "");
11072339Sabial					cflag = 1;
11172339Sabial					if (--argc > 0)
11272339Sabial						PUSHIO(aword, *++argv, iof = nlchar);
11372339Sabial					break;
11472339Sabial
11572339Sabial				case 'q':
11672339Sabial					qflag = SIG_DFL;
11772339Sabial					break;
11872339Sabial
11972339Sabial				case 's':
12072339Sabial					/* standard input */
12172339Sabial					break;
12272339Sabial
12372339Sabial				case 't':
12472339Sabial					prompt->status &= ~EXPORT;
12572339Sabial					setval(prompt, "");
12672339Sabial					iof = linechar;
12772339Sabial					break;
12872339Sabial
12972339Sabial				case 'i':
13072339Sabial					talking++;
13172339Sabial				default:
13272339Sabial					if (*s>='a' && *s<='z')
13372339Sabial						flag[*s]++;
13472339Sabial				}
13572339Sabial		} else {
13672339Sabial			argv--;
13772339Sabial			argc++;
13872339Sabial		}
13972339Sabial		if (iof == filechar && --argc > 0) {
14072339Sabial			setval(prompt, "");
14172339Sabial			setval(cprompt, "");
14272339Sabial			prompt->status &= ~EXPORT;
14372339Sabial			cprompt->status &= ~EXPORT;
14472339Sabial			if (newfile(name = *++argv))
14572339Sabial				exit(1);
14672339Sabial		}
14772339Sabial	}
14872339Sabial	setdash();
14972339Sabial	if (e.iop < iostack) {
15072339Sabial		PUSHIO(afile, 0, iof);
15172339Sabial		if (isatty(0) && isatty(1) && !cflag)
15272339Sabial			talking++;
15372339Sabial	}
15472339Sabial	signal(SIGQUIT, qflag);
15572339Sabial	if (name && name[0] == '-') {
15672339Sabial		talking++;
15772339Sabial		if ((f = open(".profile", 0)) >= 0)
15872339Sabial			next(remap(f));
15972339Sabial		if ((f = open("/etc/profile", 0)) >= 0)
16072339Sabial			next(remap(f));
16172339Sabial	}
16272339Sabial	if (talking)
16372339Sabial		signal(SIGTERM, sig);
16472339Sabial	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
16572339Sabial		signal(SIGINT, onintr);
16672339Sabial	dolv = argv;
16772339Sabial	dolc = argc;
16872339Sabial	dolv[0] = name;
16972339Sabial	if (dolc > 1)
17072339Sabial		for (ap = ++argv; --argc > 0;)
17172339Sabial			if (assign(*ap = *argv++, !COPYV))
17272339Sabial				dolc--;	/* keyword */
17372339Sabial			else
17472339Sabial				ap++;
17572339Sabial	setval(lookup("#"), putn((--dolc < 0) ? (dolc = 0) : dolc));
17672339Sabial
17772339Sabial	for (;;) {
17872339Sabial		if (talking && e.iop <= iostack)
17972339Sabial			prs(prompt->value);
18072339Sabial		onecommand();
18172339Sabial	}
18272339Sabial}
18372339Sabial
18472339Sabialvoid
18572339Sabialsetdash()
18672339Sabial{
18772339Sabial	register char *cp, c;
18872339Sabial	char m['z'-'a'+1];
18972339Sabial
19072339Sabial	cp = m;
19172339Sabial	for (c='a'; c<='z'; c++)
19272339Sabial		if (flag[c])
19372339Sabial			*cp++ = c;
19472339Sabial	*cp = 0;
19572339Sabial	setval(lookup("-"), m);
19672339Sabial}
19772339Sabial
19872339Sabialint
19972339Sabialnewfile(s)
20072339Sabialregister char *s;
20172339Sabial{
20272339Sabial	register f;
20372339Sabial
20472339Sabial	if (strcmp(s, "-") != 0) {
20572339Sabial		f = open(s, 0);
20672339Sabial		if (f < 0) {
20772339Sabial			prs(s);
20872339Sabial			err(": cannot open");
20972339Sabial			return(1);
21072339Sabial		}
21172339Sabial	} else
21272339Sabial		f = 0;
21372339Sabial	next(remap(f));
21472339Sabial	return(0);
21572339Sabial}
21672339Sabial
21772339Sabialvoid
21872339Sabialonecommand()
21972339Sabial{
22072339Sabial	register i;
22172339Sabial	jmp_buf m1;
22272339Sabial
22372339Sabial	while (e.oenv)
22472339Sabial		quitenv();
22572339Sabial	areanum = 1;
22672339Sabial	freehere(areanum);
22772339Sabial	freearea(areanum);
22872339Sabial	garbage();
22972339Sabial	wdlist = 0;
23072339Sabial	iolist = 0;
23172339Sabial	e.errpt = 0;
23272339Sabial	e.linep = line;
23372339Sabial	yynerrs = 0;
23472339Sabial	multiline = 0;
23572339Sabial	inparse = 1;
23672339Sabial	intr = 0;
23772339Sabial	execflg = 0;
23872339Sabial	setjmp(failpt = m1);	/* Bruce Evans' fix */
23972339Sabial	if (setjmp(failpt = m1) || yyparse() || intr) {
24072339Sabial		while (e.oenv)
24172339Sabial			quitenv();
24272339Sabial		scraphere();
24372339Sabial		if (!talking && intr)
24472339Sabial			leave();
24572339Sabial		inparse = 0;
24672339Sabial		intr = 0;
24772339Sabial		return;
24872339Sabial	}
24972339Sabial	inparse = 0;
25072339Sabial	brklist = 0;
25172339Sabial	intr = 0;
25272339Sabial	execflg = 0;
25372339Sabial	if (!flag['n'])
25472339Sabial		execute(outtree, NOPIPE, NOPIPE, 0);
25572339Sabial	if (!talking && intr) {
25672339Sabial		execflg = 0;
25772339Sabial		leave();
25872339Sabial	}
25972339Sabial	if ((i = trapset) != 0) {
26072339Sabial		trapset = 0;
26172339Sabial		runtrap(i);
26272339Sabial	}
26372339Sabial}
26472339Sabial
26572339Sabialvoid
26672339Sabialfail()
26772339Sabial{
26872339Sabial	longjmp(failpt, 1);
26972339Sabial	/* NOTREACHED */
27072339Sabial}
27172339Sabial
27272339Sabialvoid
27372339Sabialleave()
27472339Sabial{
27572339Sabial	if (execflg)
27672339Sabial		fail();
27772339Sabial	scraphere();
27872339Sabial	freehere(1);
27972339Sabial	runtrap(0);
28072339Sabial	exit(exstat);
28172339Sabial	/* NOTREACHED */
28272339Sabial}
28372339Sabial
28472339Sabialvoid
28572339Sabialwarn(s)
28672339Sabialregister char *s;
28772339Sabial{
28872339Sabial	if(*s) {
28972339Sabial		prs(s);
29072339Sabial		exstat = -1;
29172339Sabial	}
29272339Sabial	prs("\n");
29372339Sabial	if (flag['e'])
29472339Sabial		leave();
29572339Sabial}
29672339Sabial
29772339Sabialvoid
29872339Sabialerr(s)
29972339Sabialchar *s;
30072339Sabial{
30172339Sabial	warn(s);
30272339Sabial	if (flag['n'])
30372339Sabial		return;
30472339Sabial	if (!talking)
30572339Sabial		leave();
30672339Sabial	if (e.errpt)
30772339Sabial		longjmp(e.errpt, 1);
30872339Sabial	closeall();
30972339Sabial	e.iop = e.iobase = iostack;
31072339Sabial}
31172339Sabial
31272339Sabialint
31372339Sabialnewenv(f)
31472339Sabialint f;
31572339Sabial{
31672339Sabial	register struct env *ep;
31772339Sabial
31872339Sabial	if (f) {
31972339Sabial		quitenv();
32072339Sabial		return(1);
32172339Sabial	}
32272339Sabial	ep = (struct env *) space(sizeof(*ep));
32372339Sabial	if (ep == NULL) {
32472339Sabial		while (e.oenv)
32572339Sabial			quitenv();
32672339Sabial		fail();
32772339Sabial	}
32872339Sabial	*ep = e;
32972339Sabial	e.oenv = ep;
33072339Sabial	e.errpt = errpt;
33172339Sabial	return(0);
33272339Sabial}
33372339Sabial
33472339Sabialvoid
33572339Sabialquitenv()
33672339Sabial{
33772339Sabial	register struct env *ep;
33872339Sabial	register fd;
33972339Sabial
34072339Sabial	if ((ep = e.oenv) != NULL) {
34172339Sabial		fd = e.iofd;
34272339Sabial		e = *ep;
34372339Sabial		/* should close `'d files */
34472339Sabial		DELETE(ep);
34572339Sabial		while (--fd >= e.iofd)
34672339Sabial			close(fd);
34772339Sabial	}
34872339Sabial}
34972339Sabial
35072339Sabial/*
35172339Sabial * Is any character from s1 in s2?
35272339Sabial */
35372339Sabialint
35472339Sabialanys(s1, s2)
35572339Sabialregister char *s1, *s2;
35672339Sabial{
35772339Sabial	while (*s1)
35872339Sabial		if (any(*s1++, s2))
35972339Sabial			return(1);
36072339Sabial	return(0);
36172339Sabial}
36272339Sabial
36372339Sabial/*
36472339Sabial * Is character c in s?
36572339Sabial */
36672339Sabialint
36772339Sabialany(c, s)
36872339Sabialregister int c;
36972339Sabialregister char *s;
37072339Sabial{
37172339Sabial	while (*s)
37272339Sabial		if (*s++ == c)
37372339Sabial			return(1);
37472339Sabial	return(0);
37572339Sabial}
37672339Sabial
37772339Sabialchar *
37872339Sabialputn(n)
37972339Sabialregister int n;
38072339Sabial{
38172339Sabial	return(itoa(n, -1));
38272339Sabial}
38372339Sabial
38472339Sabialchar *
38572339Sabialitoa(u, n)
38672339Sabialregister unsigned u;
38772339Sabialint n;
38872339Sabial{
38972339Sabial	register char *cp;
39072339Sabial	static char s[20];
39172339Sabial	int m;
39272339Sabial
39372339Sabial	m = 0;
39472339Sabial	if (n < 0 && (int) u < 0) {
39572339Sabial		m++;
39672339Sabial		u = -u;
39772339Sabial	}
39872339Sabial	cp = s+sizeof(s);
39972339Sabial	*--cp = 0;
40072339Sabial	do {
40172339Sabial		*--cp = u%10 + '0';
40272339Sabial		u /= 10;
40372339Sabial	} while (--n > 0 || u);
40472339Sabial	if (m)
40572339Sabial		*--cp = '-';
40672339Sabial	return(cp);
40772339Sabial}
40872339Sabial
40972339Sabialvoid
41072339Sabialnext(f)
41172339Sabialint f;
41272339Sabial{
41372339Sabial	PUSHIO(afile, f, filechar);
41472339Sabial}
41572339Sabial
41672339Sabialvoid
41772339Sabialonintr(s)
41872339Sabialint s;				/* ANSI C requires a parameter */
41972339Sabial{
42072339Sabial	signal(SIGINT, onintr);
42172339Sabial	intr = 1;
42272339Sabial	if (talking) {
42372339Sabial		if (inparse) {
42472339Sabial			prs("\n");
42572339Sabial			fail();
42672339Sabial		}
42772339Sabial	}
42872339Sabial	else if (heedint) {
42972339Sabial		execflg = 0;
43072339Sabial		leave();
43172339Sabial	}
43272339Sabial}
43372339Sabial
43472339Sabialint
43572339Sabialletter(c)
43672339Sabialregister c;
43772339Sabial{
43872339Sabial	return((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_');
43972339Sabial}
44072339Sabial
44172339Sabialint
44272339Sabialdigit(c)
44372339Sabialregister c;
44472339Sabial{
44572339Sabial	return(c >= '0' && c <= '9');
44672339Sabial}
44772339Sabial
44872339Sabialint
44972339Sabialletnum(c)
45072339Sabialregister c;
45172339Sabial{
45272339Sabial	return(letter(c) || digit(c));
45372339Sabial}
45472339Sabial
45572339Sabialchar *
45672339Sabialspace(n)
45772339Sabialint n;
45872339Sabial{
45972339Sabial	register char *cp;
46072339Sabial
46172339Sabial	if ((cp = getcell(n)) == 0)
46272339Sabial		err("out of string space");
46372339Sabial	return(cp);
46472339Sabial}
46572339Sabial
46672339Sabialchar *
46772339Sabialstrsave(s, a)
46872339Sabialregister char *s;
46972339Sabialint a;
47072339Sabial{
47172339Sabial	register char *cp, *xp;
47272339Sabial
47372339Sabial	if ((cp = space(strlen(s)+1)) != NULL) {
47472339Sabial		setarea((char *)cp, a);
47572339Sabial		for (xp = cp; (*xp++ = *s++) != '\0';)
47672339Sabial			;
47772339Sabial		return(cp);
47872339Sabial	}
47972339Sabial	return("");
48072339Sabial}
48172339Sabial
48272339Sabialvoid
48372339Sabialxfree(s)
48472339Sabialregister char *s;
48572339Sabial{
48672339Sabial	DELETE(s);
48772339Sabial}
48872339Sabial
48972339Sabial/*
49072339Sabial * trap handling
49172339Sabial */
49272339Sabialvoid
49372339Sabialsig(i)
49472339Sabialregister int i;
49572339Sabial{
49672339Sabial	trapset = i;
49772339Sabial	signal(i, sig);
49872339Sabial}
49972339Sabial
50072339Sabialvoid runtrap(i)
50172339Sabialint i;
50272339Sabial{
50372339Sabial	char *trapstr;
50472339Sabial
50572339Sabial	if ((trapstr = trap[i]) == NULL)
50672339Sabial		return;
50772339Sabial	if (i == 0)
50872339Sabial		trap[i] = 0;
50972339Sabial	RUN(aword, trapstr, nlchar);
51072339Sabial}
51172339Sabial
51272339Sabial/* -------- var.c -------- */
51372339Sabial/* #include "sh.h" */
51472339Sabial
51572339Sabial/*
51672339Sabial * Find the given name in the dictionary
51772339Sabial * and return its value.  If the name was
51872339Sabial * not previously there, enter it now and
51972339Sabial * return a null value.
52072339Sabial */
52172339Sabialstruct var *
52272339Sabiallookup(n)
52372339Sabialregister char *n;
52472339Sabial{
52572339Sabial	register struct var *vp;
52672339Sabial	register char *cp;
52772339Sabial	register int c;
52872339Sabial	static struct var dummy;
52972339Sabial
53072339Sabial	if (digit(*n)) {
53172339Sabial		dummy.name = n;
53272339Sabial		for (c = 0; digit(*n) && c < 1000; n++)
53372339Sabial			c = c*10 + *n-'0';
53472339Sabial		dummy.status = RONLY;
53572339Sabial		dummy.value = c <= dolc? dolv[c]: null;
53672339Sabial		return(&dummy);
53772339Sabial	}
53872339Sabial	for (vp = vlist; vp; vp = vp->next)
53972339Sabial		if (eqname(vp->name, n))
54072339Sabial			return(vp);
54172339Sabial	cp = findeq(n);
54272339Sabial	vp = (struct var *)space(sizeof(*vp));
54372339Sabial	if (vp == 0 || (vp->name = space((int)(cp-n)+2)) == 0) {
54472339Sabial		dummy.name = dummy.value = "";
54572339Sabial		return(&dummy);
54672339Sabial	}
54772339Sabial	for (cp = vp->name; (*cp = *n++) && *cp != '='; cp++)
54872339Sabial		;
54972339Sabial	if (*cp == 0)
55072339Sabial		*cp = '=';
55172339Sabial	*++cp = 0;
55272339Sabial	setarea((char *)vp, 0);
55372339Sabial	setarea((char *)vp->name, 0);
55472339Sabial	vp->value = null;
55572339Sabial	vp->next = vlist;
55672339Sabial	vp->status = GETCELL;
55772339Sabial	vlist = vp;
55872339Sabial	return(vp);
55972339Sabial}
56072339Sabial
56172339Sabial/*
56272339Sabial * give variable at `vp' the value `val'.
56372339Sabial */
56472339Sabialvoid
56572339Sabialsetval(vp, val)
56672339Sabialstruct var *vp;
56772339Sabialchar *val;
56872339Sabial{
56972339Sabial	nameval(vp, val, (char *)NULL);
57072339Sabial}
57172339Sabial
57272339Sabial/*
57372339Sabial * if name is not NULL, it must be
57472339Sabial * a prefix of the space `val',
57572339Sabial * and end with `='.
57672339Sabial * this is all so that exporting
57772339Sabial * values is reasonably painless.
57872339Sabial */
57972339Sabialvoid
58072339Sabialnameval(vp, val, name)
58172339Sabialregister struct var *vp;
58272339Sabialchar *val, *name;
58372339Sabial{
58472339Sabial	register char *cp, *xp;
58572339Sabial	char *nv;
58672339Sabial	int fl;
58772339Sabial
58872339Sabial	if (vp->status & RONLY) {
58972339Sabial		for (xp = vp->name; *xp && *xp != '=';)
59072339Sabial			putc(*xp++);
59172339Sabial		err(" is read-only");
59272339Sabial		return;
59372339Sabial	}
59472339Sabial	fl = 0;
59572339Sabial	if (name == NULL) {
59672339Sabial		xp = space(strlen(vp->name)+strlen(val)+2);
59772339Sabial		if (xp == 0)
59872339Sabial			return;
59972339Sabial		/* make string:  name=value */
60072339Sabial		setarea((char *)xp, 0);
60172339Sabial		name = xp;
60272339Sabial		for (cp = vp->name; (*xp = *cp++) && *xp!='='; xp++)
60372339Sabial			;
60472339Sabial		if (*xp++ == 0)
60572339Sabial			xp[-1] = '=';
60672339Sabial		nv = xp;
60772339Sabial		for (cp = val; (*xp++ = *cp++) != '\0';)
60872339Sabial			;
60972339Sabial		val = nv;
61072339Sabial		fl = GETCELL;
61172339Sabial	}
61272339Sabial	if (vp->status & GETCELL)
61372339Sabial		xfree(vp->name);	/* form new string `name=value' */
61472339Sabial	vp->name = name;
61572339Sabial	vp->value = val;
61672339Sabial	vp->status |= fl;
61772339Sabial}
61872339Sabial
61972339Sabialvoid
62072339Sabialexport(vp)
62172339Sabialstruct var *vp;
62272339Sabial{
62372339Sabial	vp->status |= EXPORT;
62472339Sabial}
62572339Sabial
62672339Sabialvoid
62772339Sabialronly(vp)
62872339Sabialstruct var *vp;
62972339Sabial{
63072339Sabial	if (letter(vp->name[0]))	/* not an internal symbol ($# etc) */
63172339Sabial		vp->status |= RONLY;
63272339Sabial}
63372339Sabial
63472339Sabialint
63572339Sabialisassign(s)
63672339Sabialregister char *s;
63772339Sabial{
63872339Sabial	if (!letter((int)*s))
63972339Sabial		return(0);
64072339Sabial	for (; *s != '='; s++)
64172339Sabial		if (*s == 0 || !letnum(*s))
64272339Sabial			return(0);
64372339Sabial	return(1);
64472339Sabial}
64572339Sabial
64672339Sabialint
64772339Sabialassign(s, cf)
64872339Sabialregister char *s;
64972339Sabialint cf;
65072339Sabial{
65172339Sabial	register char *cp;
65272339Sabial	struct var *vp;
65372339Sabial
65472339Sabial	if (!letter(*s))
65572339Sabial		return(0);
65672339Sabial	for (cp = s; *cp != '='; cp++)
65772339Sabial		if (*cp == 0 || !letnum(*cp))
65872339Sabial			return(0);
65972339Sabial	vp = lookup(s);
66072339Sabial	nameval(vp, ++cp, cf == COPYV? (char *)NULL: s);
66172339Sabial	if (cf != COPYV)
66272339Sabial		vp->status &= ~GETCELL;
66372339Sabial	return(1);
66472339Sabial}
66572339Sabial
66672339Sabialint
66772339Sabialcheckname(cp)
66872339Sabialregister char *cp;
66972339Sabial{
67072339Sabial	if (!letter(*cp++))
67172339Sabial		return(0);
67272339Sabial	while (*cp)
67372339Sabial		if (!letnum(*cp++))
67472339Sabial			return(0);
67572339Sabial	return(1);
67672339Sabial}
67772339Sabial
67872339Sabialvoid
67972339Sabialputvlist(f, out)
68072339Sabialregister int f, out;
68172339Sabial{
68272339Sabial	register struct var *vp;
68372339Sabial
68472339Sabial	for (vp = vlist; vp; vp = vp->next)
68572339Sabial		if (vp->status & f && letter(*vp->name)) {
68672339Sabial			if (vp->status & EXPORT)
68772339Sabial				write(out, "export ", 7);
68872339Sabial			if (vp->status & RONLY)
68972339Sabial				write(out, "readonly ", 9);
69072339Sabial			write(out, vp->name, (int)(findeq(vp->name) - vp->name));
69172339Sabial			write(out, "\n", 1);
69272339Sabial		}
69372339Sabial}
69472339Sabial
69572339Sabialint
69672339Sabialeqname(n1, n2)
69772339Sabialregister char *n1, *n2;
69872339Sabial{
69972339Sabial	for (; *n1 != '=' && *n1 != 0; n1++)
70072339Sabial		if (*n2++ != *n1)
70172339Sabial			return(0);
70272339Sabial	return(*n2 == 0 || *n2 == '=');
70372339Sabial}
70472339Sabial
70572339Sabialstatic char *
70672339Sabialfindeq(cp)
70772339Sabialregister char *cp;
70872339Sabial{
70972339Sabial	while (*cp != '\0' && *cp != '=')
71072339Sabial		cp++;
71172339Sabial	return(cp);
71272339Sabial}
71372339Sabial
71472339Sabial/* -------- gmatch.c -------- */
71572339Sabial/*
71672339Sabial * int gmatch(string, pattern)
71772339Sabial * char *string, *pattern;
71872339Sabial *
71972339Sabial * Match a pattern as in sh(1).
72072339Sabial */
72172339Sabial
72272339Sabial#define	CMASK	0377
72372339Sabial#define	QUOTE	0200
72472339Sabial#define	QMASK	(CMASK&~QUOTE)
72572339Sabial#define	NOT	'!'	/* might use ^ */
72672339Sabial
72772339Sabialint
72872339Sabialgmatch(s, p)
72972339Sabialregister char *s, *p;
73072339Sabial{
73172339Sabial	register int sc, pc;
73272339Sabial
73372339Sabial	if (s == NULL || p == NULL)
73472339Sabial		return(0);
73572339Sabial	while ((pc = *p++ & CMASK) != '\0') {
73672339Sabial		sc = *s++ & QMASK;
73772339Sabial		switch (pc) {
73872339Sabial		case '[':
73972339Sabial			if ((p = cclass(p, sc)) == NULL)
74072339Sabial				return(0);
74172339Sabial			break;
74272339Sabial
74372339Sabial		case '?':
74472339Sabial			if (sc == 0)
74572339Sabial				return(0);
74672339Sabial			break;
74772339Sabial
74872339Sabial		case '*':
74972339Sabial			s--;
75072339Sabial			do {
75172339Sabial				if (*p == '\0' || gmatch(s, p))
75272339Sabial					return(1);
75372339Sabial			} while (*s++ != '\0');
75472339Sabial			return(0);
75572339Sabial
75672339Sabial		default:
75772339Sabial			if (sc != (pc&~QUOTE))
75872339Sabial				return(0);
75972339Sabial		}
76072339Sabial	}
76172339Sabial	return(*s == 0);
76272339Sabial}
76372339Sabial
76472339Sabialstatic char *
76572339Sabialcclass(p, sub)
76672339Sabialregister char *p;
76772339Sabialregister int sub;
76872339Sabial{
76972339Sabial	register int c, d, not, found;
77072339Sabial
77172339Sabial	if ((not = *p == NOT) != 0)
77272339Sabial		p++;
77372339Sabial	found = not;
77472339Sabial	do {
77572339Sabial		if (*p == '\0')
77672339Sabial			return((char *)NULL);
77772339Sabial		c = *p & CMASK;
77872339Sabial		if (p[1] == '-' && p[2] != ']') {
77972339Sabial			d = p[2] & CMASK;
78072339Sabial			p++;
78172339Sabial		} else
78272339Sabial			d = c;
78372339Sabial		if (c == sub || (c <= sub && sub <= d))
78472339Sabial			found = !not;
78572339Sabial	} while (*++p != ']');
78672339Sabial	return(found? p+1: (char *)NULL);
78772339Sabial}
78872339Sabial
78972339Sabial/* -------- area.c -------- */
79072339Sabial#define	REGSIZE		sizeof(struct region)
79172339Sabial#define GROWBY		256
79272339Sabial#undef	SHRINKBY	64
79372339Sabial#define FREE 32767
79472339Sabial#define BUSY 0
79572339Sabial#define	ALIGN (sizeof(int)-1)
79672339Sabial
79772339Sabial/* #include "area.h" */
79872339Sabial
79972339Sabialstruct region {
80072339Sabial	struct	region *next;
80172339Sabial	int	area;
80272339Sabial};
80372339Sabial
80472339Sabial/*
80572339Sabial * All memory between (char *)areabot and (char *)(areatop+1) is
80672339Sabial * exclusively administered by the area management routines.
80772339Sabial * It is assumed that sbrk() and brk() manipulate the high end.
80872339Sabial */
80972339Sabialstatic	struct region *areabot;		/* bottom of area */
81072339Sabialstatic	struct region *areatop;		/* top of area */
81172339Sabialstatic	struct region *areanxt;		/* starting point of scan */
81272339Sabial
81372339Sabialvoid
81472339Sabialinitarea()
81572339Sabial{
81672339Sabial	while ((int)sbrk(0) & ALIGN)
81772339Sabial		sbrk(1);
81872339Sabial	areabot = (struct region *)sbrk(REGSIZE);
81972339Sabial	areabot->next = areabot;
82072339Sabial	areabot->area = BUSY;
82172339Sabial	areatop = areabot;
82272339Sabial	areanxt = areabot;
82372339Sabial}
82472339Sabial
82572339Sabialchar *
82672339Sabialgetcell(nbytes)
82772339Sabialunsigned nbytes;
82872339Sabial{
82972339Sabial	register int nregio;
83072339Sabial	register struct region *p, *q;
83172339Sabial	register i;
83272339Sabial
83372339Sabial	if (nbytes == 0)
83472339Sabial		abort();	/* silly and defeats the algorithm */
83572339Sabial	/*
83672339Sabial	 * round upwards and add administration area
83772339Sabial	 */
83872339Sabial	nregio = (nbytes+(REGSIZE-1))/REGSIZE + 1;
83972339Sabial	for (p = areanxt;;) {
84072339Sabial		if (p->area > areanum) {
84172339Sabial			/*
84272339Sabial			 * merge free cells
84372339Sabial			 */
84472339Sabial			while ((q = p->next)->area > areanum && q != areanxt)
84572339Sabial				p->next = q->next;
84672339Sabial			/*
84772339Sabial			 * exit loop if cell big enough
84872339Sabial			 */
84972339Sabial			if (q >= p + nregio)
85072339Sabial				goto found;
85172339Sabial		}
85272339Sabial		p = p->next;
85372339Sabial		if (p == areanxt)
85472339Sabial			break;
85572339Sabial	}
85672339Sabial	i = nregio >= GROWBY ? nregio : GROWBY;
85772339Sabial	p = (struct region *)sbrk(i * REGSIZE);
85872339Sabial	if (p == (struct region *)-1)
85972339Sabial		return((char *)NULL);
86072339Sabial	p--;
86172339Sabial	if (p != areatop)
86272339Sabial		abort();	/* allocated areas are contiguous */
86372339Sabial	q = p + i;
86472339Sabial	p->next = q;
86572339Sabial	p->area = FREE;
86672339Sabial	q->next = areabot;
86772339Sabial	q->area = BUSY;
86872339Sabial	areatop = q;
86972339Sabialfound:
87072339Sabial	/*
87172339Sabial	 * we found a FREE area big enough, pointed to by 'p', and up to 'q'
87272339Sabial	 */
87372339Sabial	areanxt = p + nregio;
87472339Sabial	if (areanxt < q) {
87572339Sabial		/*
87672339Sabial		 * split into requested area and rest
87772339Sabial		 */
87872339Sabial		if (areanxt+1 > q)
87972339Sabial			abort();	/* insufficient space left for admin */
88072339Sabial		areanxt->next = q;
88172339Sabial		areanxt->area = FREE;
88272339Sabial		p->next = areanxt;
88372339Sabial	}
88472339Sabial	p->area = areanum;
88572339Sabial	return((char *)(p+1));
88672339Sabial}
88772339Sabial
88872339Sabialvoid
88972339Sabialfreecell(cp)
89072339Sabialchar *cp;
89172339Sabial{
89272339Sabial	register struct region *p;
89372339Sabial
89472339Sabial	if ((p = (struct region *)cp) != NULL) {
89572339Sabial		p--;
89672339Sabial		if (p < areanxt)
89772339Sabial			areanxt = p;
89872339Sabial		p->area = FREE;
89972339Sabial	}
90072339Sabial}
90172339Sabial
90272339Sabialvoid
90372339Sabialfreearea(a)
90472339Sabialregister int a;
90572339Sabial{
90672339Sabial	register struct region *p, *top;
90772339Sabial
90872339Sabial	top = areatop;
90972339Sabial	for (p = areabot; p != top; p = p->next)
91072339Sabial		if (p->area >= a)
91172339Sabial			p->area = FREE;
91272339Sabial}
91372339Sabial
91472339Sabialvoid
91572339Sabialsetarea(cp,a)
91672339Sabialchar *cp;
91772339Sabialint a;
91872339Sabial{
91972339Sabial	register struct region *p;
92072339Sabial
92172339Sabial	if ((p = (struct region *)cp) != NULL)
92272339Sabial		(p-1)->area = a;
92372339Sabial}
92472339Sabial
92572339Sabialint
92672339Sabialgetarea(cp)
92772339Sabialchar *cp;
92872339Sabial{
92972339Sabial	return ((struct region*)cp-1)->area;
93072339Sabial}
93172339Sabial
93272339Sabialvoid
93372339Sabialgarbage()
93472339Sabial{
93572339Sabial	register struct region *p, *q, *top;
93672339Sabial
93772339Sabial	top = areatop;
93872339Sabial	for (p = areabot; p != top; p = p->next) {
93972339Sabial		if (p->area > areanum) {
94072339Sabial			while ((q = p->next)->area > areanum)
94172339Sabial				p->next = q->next;
94272339Sabial			areanxt = p;
94372339Sabial		}
94472339Sabial	}
94572339Sabial#ifdef SHRINKBY
94672339Sabial	if (areatop >= q + SHRINKBY && q->area > areanum) {
94772339Sabial		brk((char *)(q+1));
94872339Sabial		q->next = areabot;
94972339Sabial		q->area = BUSY;
95072339Sabial		areatop = q;
95172339Sabial	}
95272339Sabial#endif
95372339Sabial}
954