xref: /original-bsd/bin/ed/ed.c (revision 522670b9)
1854cc826Ssam #ifndef lint
2*522670b9Sbostic static char sccsid[] = "@(#)ed.c	4.11 (Berkeley) 09/15/89";
3854cc826Ssam #endif
491c17a00Smckusick 
591c17a00Smckusick /*
691c17a00Smckusick  * Editor
791c17a00Smckusick  */
8d3b12757Sbostic #define CRYPT
991c17a00Smckusick 
10*522670b9Sbostic #include <sys/signal.h>
1191c17a00Smckusick #include <sgtty.h>
1219f69de9Ssam #undef CEOF
1391c17a00Smckusick #include <setjmp.h>
1473bab485Sbostic #include "pathnames.h"
1573bab485Sbostic 
1691c17a00Smckusick #define	NULL	0
1791c17a00Smckusick #define	FNSIZE	64
1891c17a00Smckusick #define	LBSIZE	512
1991c17a00Smckusick #define	ESIZE	128
2091c17a00Smckusick #define	GBSIZE	256
2191c17a00Smckusick #define	NBRA	5
2291c17a00Smckusick #define	EOF	-1
2391c17a00Smckusick 
2491c17a00Smckusick #define	CBRA	1
2591c17a00Smckusick #define	CCHR	2
2691c17a00Smckusick #define	CDOT	4
2791c17a00Smckusick #define	CCL	6
2891c17a00Smckusick #define	NCCL	8
2991c17a00Smckusick #define	CDOL	10
3091c17a00Smckusick #define	CEOF	11
3191c17a00Smckusick #define	CKET	12
3291c17a00Smckusick #define	CBACK	14
3391c17a00Smckusick 
3491c17a00Smckusick #define	STAR	01
3591c17a00Smckusick 
3691c17a00Smckusick char	Q[]	= "";
3791c17a00Smckusick char	T[]	= "TMP";
3891c17a00Smckusick #define	READ	0
3991c17a00Smckusick #define	WRITE	1
4091c17a00Smckusick 
4191c17a00Smckusick int	peekc;
4291c17a00Smckusick int	lastc;
4391c17a00Smckusick char	savedfile[FNSIZE];
4491c17a00Smckusick char	file[FNSIZE];
4591c17a00Smckusick char	linebuf[LBSIZE];
4691c17a00Smckusick char	rhsbuf[LBSIZE/2];
4791c17a00Smckusick char	expbuf[ESIZE+4];
4891c17a00Smckusick int	circfl;
4991c17a00Smckusick int	*zero;
5091c17a00Smckusick int	*dot;
5191c17a00Smckusick int	*dol;
5291c17a00Smckusick int	*addr1;
5391c17a00Smckusick int	*addr2;
5491c17a00Smckusick char	genbuf[LBSIZE];
5591c17a00Smckusick long	count;
5691c17a00Smckusick char	*nextip;
5791c17a00Smckusick char	*linebp;
5891c17a00Smckusick int	ninbuf;
5991c17a00Smckusick int	io;
6091c17a00Smckusick int	pflag;
6191c17a00Smckusick long	lseek();
62*522670b9Sbostic sig_t	oldhup;
63*522670b9Sbostic sig_t	oldquit;
6491c17a00Smckusick int	vflag	= 1;
65da1d502bSmckusick 
66d3b12757Sbostic #ifdef CRYPT
67d3b12757Sbostic /*
68d3b12757Sbostic  * Various flags and buffers needed by the encryption routines.
69d3b12757Sbostic  */
70d3b12757Sbostic #define	KSIZE	9
71d3b12757Sbostic int	xflag;
72d3b12757Sbostic int	xtflag;
73d3b12757Sbostic int	kflag;
74d3b12757Sbostic char	key[KSIZE + 1];
75d3b12757Sbostic char	crbuf[512];
76d3b12757Sbostic char	perm[768];
77d3b12757Sbostic char	tperm[768];
78d3b12757Sbostic #endif CRYPT
79da1d502bSmckusick 
8091c17a00Smckusick int	listf;
8191c17a00Smckusick int	col;
8291c17a00Smckusick char	*globp;
8391c17a00Smckusick int	tfile	= -1;
8491c17a00Smckusick int	tline;
85bad56901Sbostic char	tfname[sizeof(_PATH_TMP) + 20];
8691c17a00Smckusick char	*loc1;
8791c17a00Smckusick char	*loc2;
8891c17a00Smckusick char	*locs;
8991c17a00Smckusick char	ibuff[512];
9091c17a00Smckusick int	iblock	= -1;
9191c17a00Smckusick char	obuff[512];
9291c17a00Smckusick int	oblock	= -1;
9391c17a00Smckusick int	ichanged;
9491c17a00Smckusick int	nleft;
9591c17a00Smckusick char	WRERR[]	= "WRITE ERROR";
9691c17a00Smckusick int	names[26];
9791c17a00Smckusick int	anymarks;
9891c17a00Smckusick char	*braslist[NBRA];
9991c17a00Smckusick char	*braelist[NBRA];
10091c17a00Smckusick int	nbra;
10191c17a00Smckusick int	subnewa;
10291c17a00Smckusick int	subolda;
10391c17a00Smckusick int	fchange;
10491c17a00Smckusick int	wrapp;
10591c17a00Smckusick unsigned nlall = 128;
10691c17a00Smckusick 
10791c17a00Smckusick int	*address();
10891c17a00Smckusick char	*getline();
10991c17a00Smckusick char	*getblock();
11091c17a00Smckusick char	*place();
11191c17a00Smckusick char	*mktemp();
11291c17a00Smckusick char	*malloc();
11391c17a00Smckusick char	*realloc();
11491c17a00Smckusick jmp_buf	savej;
11591c17a00Smckusick 
11691c17a00Smckusick main(argc, argv)
11791c17a00Smckusick char **argv;
11891c17a00Smckusick {
11991c17a00Smckusick 	register char *p1, *p2;
120*522670b9Sbostic 	extern void onintr(), quit(), onhup();
121*522670b9Sbostic 	sig_t oldintr;
12291c17a00Smckusick 
12391c17a00Smckusick 	oldquit = signal(SIGQUIT, SIG_IGN);
12491c17a00Smckusick 	oldhup = signal(SIGHUP, SIG_IGN);
12591c17a00Smckusick 	oldintr = signal(SIGINT, SIG_IGN);
12691c17a00Smckusick 	if ((int)signal(SIGTERM, SIG_IGN) == 0)
12791c17a00Smckusick 		signal(SIGTERM, quit);
12891c17a00Smckusick 	argv++;
12991c17a00Smckusick 	while (argc > 1 && **argv=='-') {
13091c17a00Smckusick 		switch((*argv)[1]) {
13191c17a00Smckusick 
13291c17a00Smckusick 		case '\0':
13391c17a00Smckusick 			vflag = 0;
13491c17a00Smckusick 			break;
13591c17a00Smckusick 
13691c17a00Smckusick 		case 'q':
13791c17a00Smckusick 			signal(SIGQUIT, SIG_DFL);
13891c17a00Smckusick 			vflag = 1;
13991c17a00Smckusick 			break;
14091c17a00Smckusick 
141d3b12757Sbostic #ifdef CRYPT
142d3b12757Sbostic 		case 'x':
143d3b12757Sbostic 			xflag = 1;
144d3b12757Sbostic 			break;
145d3b12757Sbostic #endif CRYPT
14691c17a00Smckusick 		}
14791c17a00Smckusick 		argv++;
14891c17a00Smckusick 		argc--;
14991c17a00Smckusick 	}
150d3b12757Sbostic #ifdef CRYPT
151d3b12757Sbostic 	if(xflag){
152d3b12757Sbostic 		getkey();
153d3b12757Sbostic 		kflag = crinit(key, perm);
154d3b12757Sbostic 	}
155d3b12757Sbostic #endif CRYPT
15691c17a00Smckusick 
15791c17a00Smckusick 	if (argc>1) {
15891c17a00Smckusick 		p1 = *argv;
15991c17a00Smckusick 		p2 = savedfile;
16091c17a00Smckusick 		while (*p2++ = *p1++)
16191c17a00Smckusick 			;
16291c17a00Smckusick 		globp = "r";
16391c17a00Smckusick 	}
16491c17a00Smckusick 	zero = (int *)malloc(nlall*sizeof(int));
165bad56901Sbostic 	(void)strcpy(tfname, _PATH_TMP);
166bad56901Sbostic 	(void)strcat(tfname, "_edXXXXXX");
167bad56901Sbostic 	(void)mktemp(tfname);
16891c17a00Smckusick 	init();
16991c17a00Smckusick 	if (((int)oldintr&01) == 0)
17091c17a00Smckusick 		signal(SIGINT, onintr);
17191c17a00Smckusick 	if (((int)oldhup&01) == 0)
17291c17a00Smckusick 		signal(SIGHUP, onhup);
17391c17a00Smckusick 	setjmp(savej);
17491c17a00Smckusick 	commands();
17591c17a00Smckusick 	quit();
17691c17a00Smckusick }
17791c17a00Smckusick 
17891c17a00Smckusick commands()
17991c17a00Smckusick {
18091c17a00Smckusick 	int getfile(), gettty();
18191c17a00Smckusick 	register *a1, c;
18291c17a00Smckusick 
18391c17a00Smckusick 	for (;;) {
18491c17a00Smckusick 	if (pflag) {
18591c17a00Smckusick 		pflag = 0;
18691c17a00Smckusick 		addr1 = addr2 = dot;
18791c17a00Smckusick 		goto print;
18891c17a00Smckusick 	}
18991c17a00Smckusick 	addr1 = 0;
19091c17a00Smckusick 	addr2 = 0;
19191c17a00Smckusick 	do {
19291c17a00Smckusick 		addr1 = addr2;
19391c17a00Smckusick 		if ((a1 = address())==0) {
19491c17a00Smckusick 			c = getchr();
19591c17a00Smckusick 			break;
19691c17a00Smckusick 		}
19791c17a00Smckusick 		addr2 = a1;
19891c17a00Smckusick 		if ((c=getchr()) == ';') {
19991c17a00Smckusick 			c = ',';
20091c17a00Smckusick 			dot = a1;
20191c17a00Smckusick 		}
20291c17a00Smckusick 	} while (c==',');
20391c17a00Smckusick 	if (addr1==0)
20491c17a00Smckusick 		addr1 = addr2;
20591c17a00Smckusick 	switch(c) {
20691c17a00Smckusick 
20791c17a00Smckusick 	case 'a':
20891c17a00Smckusick 		setdot();
20991c17a00Smckusick 		newline();
21091c17a00Smckusick 		append(gettty, addr2);
21191c17a00Smckusick 		continue;
21291c17a00Smckusick 
21391c17a00Smckusick 	case 'c':
21491c17a00Smckusick 		delete();
21591c17a00Smckusick 		append(gettty, addr1-1);
21691c17a00Smckusick 		continue;
21791c17a00Smckusick 
21891c17a00Smckusick 	case 'd':
21991c17a00Smckusick 		delete();
22091c17a00Smckusick 		continue;
22191c17a00Smckusick 
22291c17a00Smckusick 	case 'E':
22391c17a00Smckusick 		fchange = 0;
22491c17a00Smckusick 		c = 'e';
22591c17a00Smckusick 	case 'e':
22691c17a00Smckusick 		setnoaddr();
22791c17a00Smckusick 		if (vflag && fchange) {
22891c17a00Smckusick 			fchange = 0;
22991c17a00Smckusick 			error(Q);
23091c17a00Smckusick 		}
23191c17a00Smckusick 		filename(c);
23291c17a00Smckusick 		init();
23391c17a00Smckusick 		addr2 = zero;
23491c17a00Smckusick 		goto caseread;
23591c17a00Smckusick 
23691c17a00Smckusick 	case 'f':
23791c17a00Smckusick 		setnoaddr();
23891c17a00Smckusick 		filename(c);
23991c17a00Smckusick 		puts(savedfile);
24091c17a00Smckusick 		continue;
24191c17a00Smckusick 
24291c17a00Smckusick 	case 'g':
24391c17a00Smckusick 		global(1);
24491c17a00Smckusick 		continue;
24591c17a00Smckusick 
24691c17a00Smckusick 	case 'i':
24791c17a00Smckusick 		setdot();
24891c17a00Smckusick 		nonzero();
24991c17a00Smckusick 		newline();
25091c17a00Smckusick 		append(gettty, addr2-1);
25191c17a00Smckusick 		continue;
25291c17a00Smckusick 
25391c17a00Smckusick 
25491c17a00Smckusick 	case 'j':
25591c17a00Smckusick 		if (addr2==0) {
25691c17a00Smckusick 			addr1 = dot;
25791c17a00Smckusick 			addr2 = dot+1;
25891c17a00Smckusick 		}
25991c17a00Smckusick 		setdot();
26091c17a00Smckusick 		newline();
26191c17a00Smckusick 		nonzero();
26291c17a00Smckusick 		join();
26391c17a00Smckusick 		continue;
26491c17a00Smckusick 
26591c17a00Smckusick 	case 'k':
26691c17a00Smckusick 		if ((c = getchr()) < 'a' || c > 'z')
26791c17a00Smckusick 			error(Q);
26891c17a00Smckusick 		newline();
26991c17a00Smckusick 		setdot();
27091c17a00Smckusick 		nonzero();
27191c17a00Smckusick 		names[c-'a'] = *addr2 & ~01;
27291c17a00Smckusick 		anymarks |= 01;
27391c17a00Smckusick 		continue;
27491c17a00Smckusick 
27591c17a00Smckusick 	case 'm':
27691c17a00Smckusick 		move(0);
27791c17a00Smckusick 		continue;
27891c17a00Smckusick 
27991c17a00Smckusick 	case '\n':
28091c17a00Smckusick 		if (addr2==0)
28191c17a00Smckusick 			addr2 = dot+1;
28291c17a00Smckusick 		addr1 = addr2;
28391c17a00Smckusick 		goto print;
28491c17a00Smckusick 
28591c17a00Smckusick 	case 'l':
28691c17a00Smckusick 		listf++;
28791c17a00Smckusick 	case 'p':
28891c17a00Smckusick 	case 'P':
28991c17a00Smckusick 		newline();
29091c17a00Smckusick 	print:
29191c17a00Smckusick 		setdot();
29291c17a00Smckusick 		nonzero();
29391c17a00Smckusick 		a1 = addr1;
29491c17a00Smckusick 		do {
29591c17a00Smckusick 			puts(getline(*a1++));
29691c17a00Smckusick 		} while (a1 <= addr2);
29791c17a00Smckusick 		dot = addr2;
29891c17a00Smckusick 		listf = 0;
29991c17a00Smckusick 		continue;
30091c17a00Smckusick 
30191c17a00Smckusick 	case 'Q':
30291c17a00Smckusick 		fchange = 0;
30391c17a00Smckusick 	case 'q':
30491c17a00Smckusick 		setnoaddr();
30591c17a00Smckusick 		newline();
30691c17a00Smckusick 		quit();
30791c17a00Smckusick 
30891c17a00Smckusick 	case 'r':
30991c17a00Smckusick 		filename(c);
31091c17a00Smckusick 	caseread:
31191c17a00Smckusick 		if ((io = open(file, 0)) < 0) {
31291c17a00Smckusick 			lastc = '\n';
31391c17a00Smckusick 			error(file);
31491c17a00Smckusick 		}
31591c17a00Smckusick 		setall();
31691c17a00Smckusick 		ninbuf = 0;
31791c17a00Smckusick 		c = zero != dol;
31891c17a00Smckusick 		append(getfile, addr2);
31991c17a00Smckusick 		exfile();
32091c17a00Smckusick 		fchange = c;
32191c17a00Smckusick 		continue;
32291c17a00Smckusick 
32391c17a00Smckusick 	case 's':
32491c17a00Smckusick 		setdot();
32591c17a00Smckusick 		nonzero();
32691c17a00Smckusick 		substitute(globp!=0);
32791c17a00Smckusick 		continue;
32891c17a00Smckusick 
32991c17a00Smckusick 	case 't':
33091c17a00Smckusick 		move(1);
33191c17a00Smckusick 		continue;
33291c17a00Smckusick 
33391c17a00Smckusick 	case 'u':
33491c17a00Smckusick 		setdot();
33591c17a00Smckusick 		nonzero();
33691c17a00Smckusick 		newline();
33791c17a00Smckusick 		if ((*addr2&~01) != subnewa)
33891c17a00Smckusick 			error(Q);
33991c17a00Smckusick 		*addr2 = subolda;
34091c17a00Smckusick 		dot = addr2;
34191c17a00Smckusick 		continue;
34291c17a00Smckusick 
34391c17a00Smckusick 	case 'v':
34491c17a00Smckusick 		global(0);
34591c17a00Smckusick 		continue;
34691c17a00Smckusick 
34791c17a00Smckusick 	case 'W':
34891c17a00Smckusick 		wrapp++;
34991c17a00Smckusick 	case 'w':
35091c17a00Smckusick 		setall();
35191c17a00Smckusick 		nonzero();
35291c17a00Smckusick 		filename(c);
35391c17a00Smckusick 		if(!wrapp ||
35491c17a00Smckusick 		  ((io = open(file,1)) == -1) ||
35591c17a00Smckusick 		  ((lseek(io, 0L, 2)) == -1))
35691c17a00Smckusick 			if ((io = creat(file, 0666)) < 0)
35791c17a00Smckusick 				error(file);
35891c17a00Smckusick 		wrapp = 0;
35991c17a00Smckusick 		putfile();
36091c17a00Smckusick 		exfile();
36191c17a00Smckusick 		if (addr1==zero+1 && addr2==dol)
36291c17a00Smckusick 			fchange = 0;
36391c17a00Smckusick 		continue;
36491c17a00Smckusick 
365d3b12757Sbostic #ifdef CRYPT
366d3b12757Sbostic 	case 'x':
367d3b12757Sbostic 		setnoaddr();
368d3b12757Sbostic 		newline();
369d3b12757Sbostic 		xflag = 1;
370d3b12757Sbostic 		puts("Entering encrypting mode!");
371d3b12757Sbostic 		getkey();
372d3b12757Sbostic 		kflag = crinit(key, perm);
373d3b12757Sbostic 		continue;
374d3b12757Sbostic #endif CRYPT
37591c17a00Smckusick 
37691c17a00Smckusick 
37791c17a00Smckusick 	case '=':
37891c17a00Smckusick 		setall();
37991c17a00Smckusick 		newline();
38091c17a00Smckusick 		count = (addr2-zero)&077777;
38191c17a00Smckusick 		putd();
38291c17a00Smckusick 		putchr('\n');
38391c17a00Smckusick 		continue;
38491c17a00Smckusick 
38591c17a00Smckusick 	case '!':
38691c17a00Smckusick 		callunix();
38791c17a00Smckusick 		continue;
38891c17a00Smckusick 
38991c17a00Smckusick 	case EOF:
39091c17a00Smckusick 		return;
39191c17a00Smckusick 
39291c17a00Smckusick 	}
39391c17a00Smckusick 	error(Q);
39491c17a00Smckusick 	}
39591c17a00Smckusick }
39691c17a00Smckusick 
39791c17a00Smckusick int *
39891c17a00Smckusick address()
39991c17a00Smckusick {
40091c17a00Smckusick 	register *a1, minus, c;
40191c17a00Smckusick 	int n, relerr;
40291c17a00Smckusick 
40391c17a00Smckusick 	minus = 0;
40491c17a00Smckusick 	a1 = 0;
40591c17a00Smckusick 	for (;;) {
40691c17a00Smckusick 		c = getchr();
40791c17a00Smckusick 		if ('0'<=c && c<='9') {
40891c17a00Smckusick 			n = 0;
40991c17a00Smckusick 			do {
41091c17a00Smckusick 				n *= 10;
41191c17a00Smckusick 				n += c - '0';
41291c17a00Smckusick 			} while ((c = getchr())>='0' && c<='9');
41391c17a00Smckusick 			peekc = c;
41491c17a00Smckusick 			if (a1==0)
41591c17a00Smckusick 				a1 = zero;
41691c17a00Smckusick 			if (minus<0)
41791c17a00Smckusick 				n = -n;
41891c17a00Smckusick 			a1 += n;
41991c17a00Smckusick 			minus = 0;
42091c17a00Smckusick 			continue;
42191c17a00Smckusick 		}
42291c17a00Smckusick 		relerr = 0;
42391c17a00Smckusick 		if (a1 || minus)
42491c17a00Smckusick 			relerr++;
42591c17a00Smckusick 		switch(c) {
42691c17a00Smckusick 		case ' ':
42791c17a00Smckusick 		case '\t':
42891c17a00Smckusick 			continue;
42991c17a00Smckusick 
43091c17a00Smckusick 		case '+':
43191c17a00Smckusick 			minus++;
43291c17a00Smckusick 			if (a1==0)
43391c17a00Smckusick 				a1 = dot;
43491c17a00Smckusick 			continue;
43591c17a00Smckusick 
43691c17a00Smckusick 		case '-':
43791c17a00Smckusick 		case '^':
43891c17a00Smckusick 			minus--;
43991c17a00Smckusick 			if (a1==0)
44091c17a00Smckusick 				a1 = dot;
44191c17a00Smckusick 			continue;
44291c17a00Smckusick 
44391c17a00Smckusick 		case '?':
44491c17a00Smckusick 		case '/':
44591c17a00Smckusick 			compile(c);
44691c17a00Smckusick 			a1 = dot;
44791c17a00Smckusick 			for (;;) {
44891c17a00Smckusick 				if (c=='/') {
44991c17a00Smckusick 					a1++;
45091c17a00Smckusick 					if (a1 > dol)
45191c17a00Smckusick 						a1 = zero;
45291c17a00Smckusick 				} else {
45391c17a00Smckusick 					a1--;
45491c17a00Smckusick 					if (a1 < zero)
45591c17a00Smckusick 						a1 = dol;
45691c17a00Smckusick 				}
45791c17a00Smckusick 				if (execute(0, a1))
45891c17a00Smckusick 					break;
45991c17a00Smckusick 				if (a1==dot)
46091c17a00Smckusick 					error(Q);
46191c17a00Smckusick 			}
46291c17a00Smckusick 			break;
46391c17a00Smckusick 
46491c17a00Smckusick 		case '$':
46591c17a00Smckusick 			a1 = dol;
46691c17a00Smckusick 			break;
46791c17a00Smckusick 
46891c17a00Smckusick 		case '.':
46991c17a00Smckusick 			a1 = dot;
47091c17a00Smckusick 			break;
47191c17a00Smckusick 
47291c17a00Smckusick 		case '\'':
47391c17a00Smckusick 			if ((c = getchr()) < 'a' || c > 'z')
47491c17a00Smckusick 				error(Q);
47591c17a00Smckusick 			for (a1=zero; a1<=dol; a1++)
47691c17a00Smckusick 				if (names[c-'a'] == (*a1 & ~01))
47791c17a00Smckusick 					break;
47891c17a00Smckusick 			break;
47991c17a00Smckusick 
48091c17a00Smckusick 		default:
48191c17a00Smckusick 			peekc = c;
48291c17a00Smckusick 			if (a1==0)
48391c17a00Smckusick 				return(0);
48491c17a00Smckusick 			a1 += minus;
48591c17a00Smckusick 			if (a1<zero || a1>dol)
48691c17a00Smckusick 				error(Q);
48791c17a00Smckusick 			return(a1);
48891c17a00Smckusick 		}
48991c17a00Smckusick 		if (relerr)
49091c17a00Smckusick 			error(Q);
49191c17a00Smckusick 	}
49291c17a00Smckusick }
49391c17a00Smckusick 
49491c17a00Smckusick setdot()
49591c17a00Smckusick {
49691c17a00Smckusick 	if (addr2 == 0)
49791c17a00Smckusick 		addr1 = addr2 = dot;
49891c17a00Smckusick 	if (addr1 > addr2)
49991c17a00Smckusick 		error(Q);
50091c17a00Smckusick }
50191c17a00Smckusick 
50291c17a00Smckusick setall()
50391c17a00Smckusick {
50491c17a00Smckusick 	if (addr2==0) {
50591c17a00Smckusick 		addr1 = zero+1;
50691c17a00Smckusick 		addr2 = dol;
50791c17a00Smckusick 		if (dol==zero)
50891c17a00Smckusick 			addr1 = zero;
50991c17a00Smckusick 	}
51091c17a00Smckusick 	setdot();
51191c17a00Smckusick }
51291c17a00Smckusick 
51391c17a00Smckusick setnoaddr()
51491c17a00Smckusick {
51591c17a00Smckusick 	if (addr2)
51691c17a00Smckusick 		error(Q);
51791c17a00Smckusick }
51891c17a00Smckusick 
51991c17a00Smckusick nonzero()
52091c17a00Smckusick {
52191c17a00Smckusick 	if (addr1<=zero || addr2>dol)
52291c17a00Smckusick 		error(Q);
52391c17a00Smckusick }
52491c17a00Smckusick 
52591c17a00Smckusick newline()
52691c17a00Smckusick {
52791c17a00Smckusick 	register c;
52891c17a00Smckusick 
52991c17a00Smckusick 	if ((c = getchr()) == '\n')
53091c17a00Smckusick 		return;
53191c17a00Smckusick 	if (c=='p' || c=='l') {
53291c17a00Smckusick 		pflag++;
53391c17a00Smckusick 		if (c=='l')
53491c17a00Smckusick 			listf++;
53591c17a00Smckusick 		if (getchr() == '\n')
53691c17a00Smckusick 			return;
53791c17a00Smckusick 	}
53891c17a00Smckusick 	error(Q);
53991c17a00Smckusick }
54091c17a00Smckusick 
54191c17a00Smckusick filename(comm)
54291c17a00Smckusick {
54391c17a00Smckusick 	register char *p1, *p2;
54491c17a00Smckusick 	register c;
54591c17a00Smckusick 
54691c17a00Smckusick 	count = 0;
54791c17a00Smckusick 	c = getchr();
54891c17a00Smckusick 	if (c=='\n' || c==EOF) {
54991c17a00Smckusick 		p1 = savedfile;
55091c17a00Smckusick 		if (*p1==0 && comm!='f')
55191c17a00Smckusick 			error(Q);
55291c17a00Smckusick 		p2 = file;
55391c17a00Smckusick 		while (*p2++ = *p1++)
55491c17a00Smckusick 			;
55591c17a00Smckusick 		return;
55691c17a00Smckusick 	}
55791c17a00Smckusick 	if (c!=' ')
55891c17a00Smckusick 		error(Q);
55991c17a00Smckusick 	while ((c = getchr()) == ' ')
56091c17a00Smckusick 		;
56191c17a00Smckusick 	if (c=='\n')
56291c17a00Smckusick 		error(Q);
56391c17a00Smckusick 	p1 = file;
56491c17a00Smckusick 	do {
56591c17a00Smckusick 		*p1++ = c;
56691c17a00Smckusick 		if (c==' ' || c==EOF)
56791c17a00Smckusick 			error(Q);
56891c17a00Smckusick 	} while ((c = getchr()) != '\n');
56991c17a00Smckusick 	*p1++ = 0;
57091c17a00Smckusick 	if (savedfile[0]==0 || comm=='e' || comm=='f') {
57191c17a00Smckusick 		p1 = savedfile;
57291c17a00Smckusick 		p2 = file;
57391c17a00Smckusick 		while (*p1++ = *p2++)
57491c17a00Smckusick 			;
57591c17a00Smckusick 	}
57691c17a00Smckusick }
57791c17a00Smckusick 
57891c17a00Smckusick exfile()
57991c17a00Smckusick {
58091c17a00Smckusick 	close(io);
58191c17a00Smckusick 	io = -1;
58291c17a00Smckusick 	if (vflag) {
58391c17a00Smckusick 		putd();
58491c17a00Smckusick 		putchr('\n');
58591c17a00Smckusick 	}
58691c17a00Smckusick }
58791c17a00Smckusick 
588*522670b9Sbostic void
58991c17a00Smckusick onintr()
59091c17a00Smckusick {
591*522670b9Sbostic 	/* not necessary: (void)signal(SIGINT, onintr); */
59291c17a00Smckusick 	putchr('\n');
59391c17a00Smckusick 	lastc = '\n';
59491c17a00Smckusick 	error(Q);
59591c17a00Smckusick }
59691c17a00Smckusick 
597*522670b9Sbostic void
59891c17a00Smckusick onhup()
59991c17a00Smckusick {
600*522670b9Sbostic 	/* not necessary: (void)signal(SIGINT, SIG_IGN); */
601*522670b9Sbostic 	/* not necessary: (void)signal(SIGHUP, SIG_IGN); */
60291c17a00Smckusick 	if (dol > zero) {
60391c17a00Smckusick 		addr1 = zero+1;
60491c17a00Smckusick 		addr2 = dol;
60591c17a00Smckusick 		io = creat("ed.hup", 0666);
60691c17a00Smckusick 		if (io > 0)
60791c17a00Smckusick 			putfile();
60891c17a00Smckusick 	}
60991c17a00Smckusick 	fchange = 0;
61091c17a00Smckusick 	quit();
61191c17a00Smckusick }
61291c17a00Smckusick 
61391c17a00Smckusick error(s)
61491c17a00Smckusick char *s;
61591c17a00Smckusick {
61691c17a00Smckusick 	register c;
61791c17a00Smckusick 
61891c17a00Smckusick 	wrapp = 0;
61991c17a00Smckusick 	listf = 0;
62091c17a00Smckusick 	putchr('?');
62191c17a00Smckusick 	puts(s);
62291c17a00Smckusick 	count = 0;
62391c17a00Smckusick 	lseek(0, (long)0, 2);
62491c17a00Smckusick 	pflag = 0;
62591c17a00Smckusick 	if (globp)
62691c17a00Smckusick 		lastc = '\n';
62791c17a00Smckusick 	globp = 0;
62891c17a00Smckusick 	peekc = lastc;
62991c17a00Smckusick 	if(lastc)
63091c17a00Smckusick 		while ((c = getchr()) != '\n' && c != EOF)
63191c17a00Smckusick 			;
63291c17a00Smckusick 	if (io > 0) {
63391c17a00Smckusick 		close(io);
63491c17a00Smckusick 		io = -1;
63591c17a00Smckusick 	}
63691c17a00Smckusick 	longjmp(savej, 1);
63791c17a00Smckusick }
63891c17a00Smckusick 
63991c17a00Smckusick getchr()
64091c17a00Smckusick {
64191c17a00Smckusick 	char c;
64291c17a00Smckusick 	if (lastc=peekc) {
64391c17a00Smckusick 		peekc = 0;
64491c17a00Smckusick 		return(lastc);
64591c17a00Smckusick 	}
64691c17a00Smckusick 	if (globp) {
64791c17a00Smckusick 		if ((lastc = *globp++) != 0)
64891c17a00Smckusick 			return(lastc);
64991c17a00Smckusick 		globp = 0;
65091c17a00Smckusick 		return(EOF);
65191c17a00Smckusick 	}
65291c17a00Smckusick 	if (read(0, &c, 1) <= 0)
65391c17a00Smckusick 		return(lastc = EOF);
65491c17a00Smckusick 	lastc = c&0177;
65591c17a00Smckusick 	return(lastc);
65691c17a00Smckusick }
65791c17a00Smckusick 
65891c17a00Smckusick gettty()
65991c17a00Smckusick {
66091c17a00Smckusick 	register c;
66191c17a00Smckusick 	register char *gf;
66291c17a00Smckusick 	register char *p;
66391c17a00Smckusick 
66491c17a00Smckusick 	p = linebuf;
66591c17a00Smckusick 	gf = globp;
66691c17a00Smckusick 	while ((c = getchr()) != '\n') {
66791c17a00Smckusick 		if (c==EOF) {
66891c17a00Smckusick 			if (gf)
66991c17a00Smckusick 				peekc = c;
67091c17a00Smckusick 			return(c);
67191c17a00Smckusick 		}
67291c17a00Smckusick 		if ((c &= 0177) == 0)
67391c17a00Smckusick 			continue;
67491c17a00Smckusick 		*p++ = c;
67591c17a00Smckusick 		if (p >= &linebuf[LBSIZE-2])
67691c17a00Smckusick 			error(Q);
67791c17a00Smckusick 	}
67891c17a00Smckusick 	*p++ = 0;
67991c17a00Smckusick 	if (linebuf[0]=='.' && linebuf[1]==0)
68091c17a00Smckusick 		return(EOF);
68191c17a00Smckusick 	return(0);
68291c17a00Smckusick }
68391c17a00Smckusick 
68491c17a00Smckusick getfile()
68591c17a00Smckusick {
68691c17a00Smckusick 	register c;
68791c17a00Smckusick 	register char *lp, *fp;
68891c17a00Smckusick 
68991c17a00Smckusick 	lp = linebuf;
69091c17a00Smckusick 	fp = nextip;
69191c17a00Smckusick 	do {
69291c17a00Smckusick 		if (--ninbuf < 0) {
69391c17a00Smckusick 			if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
69491c17a00Smckusick 				return(EOF);
69591c17a00Smckusick 			fp = genbuf;
69691c17a00Smckusick 			while(fp < &genbuf[ninbuf]) {
69791c17a00Smckusick 				if (*fp++ & 0200) {
698d3b12757Sbostic #ifdef CRYPT
699d3b12757Sbostic 					if (kflag)
700d3b12757Sbostic 						crblock(perm, genbuf, ninbuf+1, count);
701d3b12757Sbostic #endif CRYPT
70291c17a00Smckusick 					break;
70391c17a00Smckusick 				}
70491c17a00Smckusick 			}
70591c17a00Smckusick 			fp = genbuf;
70691c17a00Smckusick 		}
70791c17a00Smckusick 		c = *fp++;
70891c17a00Smckusick 		if (c=='\0')
70991c17a00Smckusick 			continue;
71091c17a00Smckusick 		if (c&0200 || lp >= &linebuf[LBSIZE]) {
71191c17a00Smckusick 			lastc = '\n';
71291c17a00Smckusick 			error(Q);
71391c17a00Smckusick 		}
71491c17a00Smckusick 		*lp++ = c;
71591c17a00Smckusick 		count++;
71691c17a00Smckusick 	} while (c != '\n');
71791c17a00Smckusick 	*--lp = 0;
71891c17a00Smckusick 	nextip = fp;
71991c17a00Smckusick 	return(0);
72091c17a00Smckusick }
72191c17a00Smckusick 
72291c17a00Smckusick putfile()
72391c17a00Smckusick {
72491c17a00Smckusick 	int *a1, n;
72591c17a00Smckusick 	register char *fp, *lp;
72691c17a00Smckusick 	register nib;
72791c17a00Smckusick 
72891c17a00Smckusick 	nib = 512;
72991c17a00Smckusick 	fp = genbuf;
73091c17a00Smckusick 	a1 = addr1;
73191c17a00Smckusick 	do {
73291c17a00Smckusick 		lp = getline(*a1++);
73391c17a00Smckusick 		for (;;) {
73491c17a00Smckusick 			if (--nib < 0) {
73591c17a00Smckusick 				n = fp-genbuf;
736d3b12757Sbostic #ifdef CRYPT
737d3b12757Sbostic 				if(kflag)
738d3b12757Sbostic 					crblock(perm, genbuf, n, count-n);
739d3b12757Sbostic #endif CRYPT
74091c17a00Smckusick 				if(write(io, genbuf, n) != n) {
74191c17a00Smckusick 					puts(WRERR);
74291c17a00Smckusick 					error(Q);
74391c17a00Smckusick 				}
74491c17a00Smckusick 				nib = 511;
74591c17a00Smckusick 				fp = genbuf;
74691c17a00Smckusick 			}
74791c17a00Smckusick 			count++;
74891c17a00Smckusick 			if ((*fp++ = *lp++) == 0) {
74991c17a00Smckusick 				fp[-1] = '\n';
75091c17a00Smckusick 				break;
75191c17a00Smckusick 			}
75291c17a00Smckusick 		}
75391c17a00Smckusick 	} while (a1 <= addr2);
75491c17a00Smckusick 	n = fp-genbuf;
755d3b12757Sbostic #ifdef CRYPT
756d3b12757Sbostic 	if(kflag)
757d3b12757Sbostic 		crblock(perm, genbuf, n, count-n);
758d3b12757Sbostic #endif CRYPT
75991c17a00Smckusick 	if(write(io, genbuf, n) != n) {
76091c17a00Smckusick 		puts(WRERR);
76191c17a00Smckusick 		error(Q);
76291c17a00Smckusick 	}
76391c17a00Smckusick }
76491c17a00Smckusick 
76591c17a00Smckusick append(f, a)
76691c17a00Smckusick int *a;
76791c17a00Smckusick int (*f)();
76891c17a00Smckusick {
76991c17a00Smckusick 	register *a1, *a2, *rdot;
77091c17a00Smckusick 	int nline, tl;
77191c17a00Smckusick 
77291c17a00Smckusick 	nline = 0;
77391c17a00Smckusick 	dot = a;
77491c17a00Smckusick 	while ((*f)() == 0) {
77591c17a00Smckusick 		if ((dol-zero)+1 >= nlall) {
77691c17a00Smckusick 			int *ozero = zero;
77791c17a00Smckusick 			nlall += 512;
77891c17a00Smckusick 			if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) {
77991c17a00Smckusick 				lastc = '\n';
78091c17a00Smckusick 				zero = ozero;
78191c17a00Smckusick 				error("MEM?");
78291c17a00Smckusick 			}
78391c17a00Smckusick 			dot += zero - ozero;
78491c17a00Smckusick 			dol += zero - ozero;
78591c17a00Smckusick 		}
78691c17a00Smckusick 		tl = putline();
78791c17a00Smckusick 		nline++;
78891c17a00Smckusick 		a1 = ++dol;
78991c17a00Smckusick 		a2 = a1+1;
79091c17a00Smckusick 		rdot = ++dot;
79191c17a00Smckusick 		while (a1 > rdot)
79291c17a00Smckusick 			*--a2 = *--a1;
79391c17a00Smckusick 		*rdot = tl;
79491c17a00Smckusick 	}
79591c17a00Smckusick 	return(nline);
79691c17a00Smckusick }
79791c17a00Smckusick 
79891c17a00Smckusick callunix()
79991c17a00Smckusick {
800*522670b9Sbostic 	register sig_t savint;
801*522670b9Sbostic 	register int pid, rpid;
80291c17a00Smckusick 	int retcode;
80391c17a00Smckusick 
80491c17a00Smckusick 	setnoaddr();
80591c17a00Smckusick 	if ((pid = fork()) == 0) {
80691c17a00Smckusick 		signal(SIGHUP, oldhup);
80791c17a00Smckusick 		signal(SIGQUIT, oldquit);
80873bab485Sbostic 		execl(_PATH_BSHELL, "sh", "-t", 0);
80991c17a00Smckusick 		exit(0100);
81091c17a00Smckusick 	}
81191c17a00Smckusick 	savint = signal(SIGINT, SIG_IGN);
81291c17a00Smckusick 	while ((rpid = wait(&retcode)) != pid && rpid != -1)
81391c17a00Smckusick 		;
81491c17a00Smckusick 	signal(SIGINT, savint);
81591c17a00Smckusick 	puts("!");
81691c17a00Smckusick }
81791c17a00Smckusick 
818*522670b9Sbostic void
81991c17a00Smckusick quit()
82091c17a00Smckusick {
82191c17a00Smckusick 	if (vflag && fchange && dol!=zero) {
82291c17a00Smckusick 		fchange = 0;
82391c17a00Smckusick 		error(Q);
82491c17a00Smckusick 	}
82591c17a00Smckusick 	unlink(tfname);
82691c17a00Smckusick 	exit(0);
82791c17a00Smckusick }
82891c17a00Smckusick 
82991c17a00Smckusick delete()
83091c17a00Smckusick {
83191c17a00Smckusick 	setdot();
83291c17a00Smckusick 	newline();
83391c17a00Smckusick 	nonzero();
83491c17a00Smckusick 	rdelete(addr1, addr2);
83591c17a00Smckusick }
83691c17a00Smckusick 
83791c17a00Smckusick rdelete(ad1, ad2)
83891c17a00Smckusick int *ad1, *ad2;
83991c17a00Smckusick {
84091c17a00Smckusick 	register *a1, *a2, *a3;
84191c17a00Smckusick 
84291c17a00Smckusick 	a1 = ad1;
84391c17a00Smckusick 	a2 = ad2+1;
84491c17a00Smckusick 	a3 = dol;
84591c17a00Smckusick 	dol -= a2 - a1;
84691c17a00Smckusick 	do {
84791c17a00Smckusick 		*a1++ = *a2++;
84891c17a00Smckusick 	} while (a2 <= a3);
84991c17a00Smckusick 	a1 = ad1;
85091c17a00Smckusick 	if (a1 > dol)
85191c17a00Smckusick 		a1 = dol;
85291c17a00Smckusick 	dot = a1;
85391c17a00Smckusick 	fchange = 1;
85491c17a00Smckusick }
85591c17a00Smckusick 
85691c17a00Smckusick gdelete()
85791c17a00Smckusick {
85891c17a00Smckusick 	register *a1, *a2, *a3;
85991c17a00Smckusick 
86091c17a00Smckusick 	a3 = dol;
86191c17a00Smckusick 	for (a1=zero+1; (*a1&01)==0; a1++)
86291c17a00Smckusick 		if (a1>=a3)
86391c17a00Smckusick 			return;
86491c17a00Smckusick 	for (a2=a1+1; a2<=a3;) {
86591c17a00Smckusick 		if (*a2&01) {
86691c17a00Smckusick 			a2++;
86791c17a00Smckusick 			dot = a1;
86891c17a00Smckusick 		} else
86991c17a00Smckusick 			*a1++ = *a2++;
87091c17a00Smckusick 	}
87191c17a00Smckusick 	dol = a1-1;
87291c17a00Smckusick 	if (dot>dol)
87391c17a00Smckusick 		dot = dol;
87491c17a00Smckusick 	fchange = 1;
87591c17a00Smckusick }
87691c17a00Smckusick 
87791c17a00Smckusick char *
87891c17a00Smckusick getline(tl)
87991c17a00Smckusick {
88091c17a00Smckusick 	register char *bp, *lp;
88191c17a00Smckusick 	register nl;
88291c17a00Smckusick 
88391c17a00Smckusick 	lp = linebuf;
88491c17a00Smckusick 	bp = getblock(tl, READ);
88591c17a00Smckusick 	nl = nleft;
88691c17a00Smckusick 	tl &= ~0377;
88791c17a00Smckusick 	while (*lp++ = *bp++)
88891c17a00Smckusick 		if (--nl == 0) {
88991c17a00Smckusick 			bp = getblock(tl+=0400, READ);
89091c17a00Smckusick 			nl = nleft;
89191c17a00Smckusick 		}
89291c17a00Smckusick 	return(linebuf);
89391c17a00Smckusick }
89491c17a00Smckusick 
89591c17a00Smckusick putline()
89691c17a00Smckusick {
89791c17a00Smckusick 	register char *bp, *lp;
89891c17a00Smckusick 	register nl;
89991c17a00Smckusick 	int tl;
90091c17a00Smckusick 
90191c17a00Smckusick 	fchange = 1;
90291c17a00Smckusick 	lp = linebuf;
90391c17a00Smckusick 	tl = tline;
90491c17a00Smckusick 	bp = getblock(tl, WRITE);
90591c17a00Smckusick 	nl = nleft;
90691c17a00Smckusick 	tl &= ~0377;
90791c17a00Smckusick 	while (*bp = *lp++) {
90891c17a00Smckusick 		if (*bp++ == '\n') {
90991c17a00Smckusick 			*--bp = 0;
91091c17a00Smckusick 			linebp = lp;
91191c17a00Smckusick 			break;
91291c17a00Smckusick 		}
91391c17a00Smckusick 		if (--nl == 0) {
91491c17a00Smckusick 			bp = getblock(tl+=0400, WRITE);
91591c17a00Smckusick 			nl = nleft;
91691c17a00Smckusick 		}
91791c17a00Smckusick 	}
91891c17a00Smckusick 	nl = tline;
91991c17a00Smckusick 	tline += (((lp-linebuf)+03)>>1)&077776;
92091c17a00Smckusick 	return(nl);
92191c17a00Smckusick }
92291c17a00Smckusick 
92391c17a00Smckusick char *
92491c17a00Smckusick getblock(atl, iof)
92591c17a00Smckusick {
92691c17a00Smckusick 	extern read(), write();
92791c17a00Smckusick 	register bno, off;
92891c17a00Smckusick 	register char *p1, *p2;
92991c17a00Smckusick 	register int n;
93091c17a00Smckusick 
93191c17a00Smckusick 	bno = (atl>>8)&0377;
93291c17a00Smckusick 	off = (atl<<1)&0774;
93391c17a00Smckusick 	if (bno >= 255) {
93491c17a00Smckusick 		lastc = '\n';
93591c17a00Smckusick 		error(T);
93691c17a00Smckusick 	}
93791c17a00Smckusick 	nleft = 512 - off;
93891c17a00Smckusick 	if (bno==iblock) {
93991c17a00Smckusick 		ichanged |= iof;
94091c17a00Smckusick 		return(ibuff+off);
94191c17a00Smckusick 	}
94291c17a00Smckusick 	if (bno==oblock)
94391c17a00Smckusick 		return(obuff+off);
94491c17a00Smckusick 	if (iof==READ) {
94591c17a00Smckusick 		if (ichanged) {
946d3b12757Sbostic #ifdef CRYPT
947d3b12757Sbostic 			if(xtflag)
948d3b12757Sbostic 				crblock(tperm, ibuff, 512, (long)0);
949d3b12757Sbostic #endif CRYPT
95091c17a00Smckusick 			blkio(iblock, ibuff, write);
95191c17a00Smckusick 		}
95291c17a00Smckusick 		ichanged = 0;
95391c17a00Smckusick 		iblock = bno;
95491c17a00Smckusick 		blkio(bno, ibuff, read);
955d3b12757Sbostic #ifdef CRYPT
956d3b12757Sbostic 		if(xtflag)
957d3b12757Sbostic 			crblock(tperm, ibuff, 512, (long)0);
958d3b12757Sbostic #endif CRYPT
95991c17a00Smckusick 		return(ibuff+off);
96091c17a00Smckusick 	}
96191c17a00Smckusick 	if (oblock>=0) {
962d3b12757Sbostic #ifdef CRYPT
963d3b12757Sbostic 		if(xtflag) {
964d3b12757Sbostic 			p1 = obuff;
965d3b12757Sbostic 			p2 = crbuf;
966d3b12757Sbostic 			n = 512;
967d3b12757Sbostic 			while(n--)
968d3b12757Sbostic 				*p2++ = *p1++;
969d3b12757Sbostic 			crblock(tperm, crbuf, 512, (long)0);
970d3b12757Sbostic 			blkio(oblock, crbuf, write);
971d3b12757Sbostic 		} else
972d3b12757Sbostic #endif CRYPT
97391c17a00Smckusick 			blkio(oblock, obuff, write);
97491c17a00Smckusick 	}
97591c17a00Smckusick 	oblock = bno;
97691c17a00Smckusick 	return(obuff+off);
97791c17a00Smckusick }
97891c17a00Smckusick 
97991c17a00Smckusick blkio(b, buf, iofcn)
98091c17a00Smckusick char *buf;
98191c17a00Smckusick int (*iofcn)();
98291c17a00Smckusick {
98391c17a00Smckusick 	lseek(tfile, (long)b<<9, 0);
98491c17a00Smckusick 	if ((*iofcn)(tfile, buf, 512) != 512) {
98591c17a00Smckusick 		error(T);
98691c17a00Smckusick 	}
98791c17a00Smckusick }
98891c17a00Smckusick 
98991c17a00Smckusick init()
99091c17a00Smckusick {
99191c17a00Smckusick 	register *markp;
99291c17a00Smckusick 
99391c17a00Smckusick 	close(tfile);
99491c17a00Smckusick 	tline = 2;
99591c17a00Smckusick 	for (markp = names; markp < &names[26]; )
99691c17a00Smckusick 		*markp++ = 0;
99791c17a00Smckusick 	subnewa = 0;
99891c17a00Smckusick 	anymarks = 0;
99991c17a00Smckusick 	iblock = -1;
100091c17a00Smckusick 	oblock = -1;
100191c17a00Smckusick 	ichanged = 0;
100291c17a00Smckusick 	close(creat(tfname, 0600));
100391c17a00Smckusick 	tfile = open(tfname, 2);
1004d3b12757Sbostic #ifdef CRYPT
1005d3b12757Sbostic 	if(xflag) {
1006d3b12757Sbostic 		xtflag = 1;
1007d3b12757Sbostic 		makekey(key, tperm);
1008d3b12757Sbostic 	}
1009d3b12757Sbostic #endif CRYPT
101091c17a00Smckusick 	dot = dol = zero;
101191c17a00Smckusick }
101291c17a00Smckusick 
101391c17a00Smckusick global(k)
101491c17a00Smckusick {
101591c17a00Smckusick 	register char *gp;
101691c17a00Smckusick 	register c;
101791c17a00Smckusick 	register int *a1;
101891c17a00Smckusick 	char globuf[GBSIZE];
101991c17a00Smckusick 
102091c17a00Smckusick 	if (globp)
102191c17a00Smckusick 		error(Q);
102291c17a00Smckusick 	setall();
102391c17a00Smckusick 	nonzero();
102491c17a00Smckusick 	if ((c=getchr())=='\n')
102591c17a00Smckusick 		error(Q);
102691c17a00Smckusick 	compile(c);
102791c17a00Smckusick 	gp = globuf;
102891c17a00Smckusick 	while ((c = getchr()) != '\n') {
102991c17a00Smckusick 		if (c==EOF)
103091c17a00Smckusick 			error(Q);
103191c17a00Smckusick 		if (c=='\\') {
103291c17a00Smckusick 			c = getchr();
103391c17a00Smckusick 			if (c!='\n')
103491c17a00Smckusick 				*gp++ = '\\';
103591c17a00Smckusick 		}
103691c17a00Smckusick 		*gp++ = c;
103791c17a00Smckusick 		if (gp >= &globuf[GBSIZE-2])
103891c17a00Smckusick 			error(Q);
103991c17a00Smckusick 	}
104091c17a00Smckusick 	*gp++ = '\n';
104191c17a00Smckusick 	*gp++ = 0;
104291c17a00Smckusick 	for (a1=zero; a1<=dol; a1++) {
104391c17a00Smckusick 		*a1 &= ~01;
104491c17a00Smckusick 		if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k)
104591c17a00Smckusick 			*a1 |= 01;
104691c17a00Smckusick 	}
104791c17a00Smckusick 	/*
104891c17a00Smckusick 	 * Special case: g/.../d (avoid n^2 algorithm)
104991c17a00Smckusick 	 */
105091c17a00Smckusick 	if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
105191c17a00Smckusick 		gdelete();
105291c17a00Smckusick 		return;
105391c17a00Smckusick 	}
105491c17a00Smckusick 	for (a1=zero; a1<=dol; a1++) {
105591c17a00Smckusick 		if (*a1 & 01) {
105691c17a00Smckusick 			*a1 &= ~01;
105791c17a00Smckusick 			dot = a1;
105891c17a00Smckusick 			globp = globuf;
105991c17a00Smckusick 			commands();
106091c17a00Smckusick 			a1 = zero;
106191c17a00Smckusick 		}
106291c17a00Smckusick 	}
106391c17a00Smckusick }
106491c17a00Smckusick 
106591c17a00Smckusick join()
106691c17a00Smckusick {
106791c17a00Smckusick 	register char *gp, *lp;
106891c17a00Smckusick 	register *a1;
106991c17a00Smckusick 
107091c17a00Smckusick 	gp = genbuf;
107191c17a00Smckusick 	for (a1=addr1; a1<=addr2; a1++) {
107291c17a00Smckusick 		lp = getline(*a1);
107391c17a00Smckusick 		while (*gp = *lp++)
107491c17a00Smckusick 			if (gp++ >= &genbuf[LBSIZE-2])
107591c17a00Smckusick 				error(Q);
107691c17a00Smckusick 	}
107791c17a00Smckusick 	lp = linebuf;
107891c17a00Smckusick 	gp = genbuf;
107991c17a00Smckusick 	while (*lp++ = *gp++)
108091c17a00Smckusick 		;
108191c17a00Smckusick 	*addr1 = putline();
108291c17a00Smckusick 	if (addr1<addr2)
108391c17a00Smckusick 		rdelete(addr1+1, addr2);
108491c17a00Smckusick 	dot = addr1;
108591c17a00Smckusick }
108691c17a00Smckusick 
108791c17a00Smckusick substitute(inglob)
108891c17a00Smckusick {
108991c17a00Smckusick 	register *markp, *a1, nl;
109091c17a00Smckusick 	int gsubf;
109191c17a00Smckusick 	int getsub();
109291c17a00Smckusick 
109391c17a00Smckusick 	gsubf = compsub();
109491c17a00Smckusick 	for (a1 = addr1; a1 <= addr2; a1++) {
109591c17a00Smckusick 		int *ozero;
109691c17a00Smckusick 		if (execute(0, a1)==0)
109791c17a00Smckusick 			continue;
109891c17a00Smckusick 		inglob |= 01;
109991c17a00Smckusick 		dosub();
110091c17a00Smckusick 		if (gsubf) {
110191c17a00Smckusick 			while (*loc2) {
110291c17a00Smckusick 				if (execute(1, (int *)0)==0)
110391c17a00Smckusick 					break;
110491c17a00Smckusick 				dosub();
110591c17a00Smckusick 			}
110691c17a00Smckusick 		}
110791c17a00Smckusick 		subnewa = putline();
110891c17a00Smckusick 		*a1 &= ~01;
110991c17a00Smckusick 		if (anymarks) {
111091c17a00Smckusick 			for (markp = names; markp < &names[26]; markp++)
111191c17a00Smckusick 				if (*markp == *a1)
111291c17a00Smckusick 					*markp = subnewa;
111391c17a00Smckusick 		}
111491c17a00Smckusick 		subolda = *a1;
111591c17a00Smckusick 		*a1 = subnewa;
111691c17a00Smckusick 		ozero = zero;
111791c17a00Smckusick 		nl = append(getsub, a1);
111891c17a00Smckusick 		nl += zero-ozero;
111991c17a00Smckusick 		a1 += nl;
112091c17a00Smckusick 		addr2 += nl;
112191c17a00Smckusick 	}
112291c17a00Smckusick 	if (inglob==0)
112391c17a00Smckusick 		error(Q);
112491c17a00Smckusick }
112591c17a00Smckusick 
112691c17a00Smckusick compsub()
112791c17a00Smckusick {
112891c17a00Smckusick 	register seof, c;
112991c17a00Smckusick 	register char *p;
113091c17a00Smckusick 
113191c17a00Smckusick 	if ((seof = getchr()) == '\n' || seof == ' ')
113291c17a00Smckusick 		error(Q);
113391c17a00Smckusick 	compile(seof);
113491c17a00Smckusick 	p = rhsbuf;
113591c17a00Smckusick 	for (;;) {
113691c17a00Smckusick 		c = getchr();
113791c17a00Smckusick 		if (c=='\\')
113891c17a00Smckusick 			c = getchr() | 0200;
113991c17a00Smckusick 		if (c=='\n') {
114091c17a00Smckusick 			if (globp)
114191c17a00Smckusick 				c |= 0200;
114291c17a00Smckusick 			else
114391c17a00Smckusick 				error(Q);
114491c17a00Smckusick 		}
114591c17a00Smckusick 		if (c==seof)
114691c17a00Smckusick 			break;
114791c17a00Smckusick 		*p++ = c;
114891c17a00Smckusick 		if (p >= &rhsbuf[LBSIZE/2])
114991c17a00Smckusick 			error(Q);
115091c17a00Smckusick 	}
115191c17a00Smckusick 	*p++ = 0;
115291c17a00Smckusick 	if ((peekc = getchr()) == 'g') {
115391c17a00Smckusick 		peekc = 0;
115491c17a00Smckusick 		newline();
115591c17a00Smckusick 		return(1);
115691c17a00Smckusick 	}
115791c17a00Smckusick 	newline();
115891c17a00Smckusick 	return(0);
115991c17a00Smckusick }
116091c17a00Smckusick 
116191c17a00Smckusick getsub()
116291c17a00Smckusick {
116391c17a00Smckusick 	register char *p1, *p2;
116491c17a00Smckusick 
116591c17a00Smckusick 	p1 = linebuf;
116691c17a00Smckusick 	if ((p2 = linebp) == 0)
116791c17a00Smckusick 		return(EOF);
116891c17a00Smckusick 	while (*p1++ = *p2++)
116991c17a00Smckusick 		;
117091c17a00Smckusick 	linebp = 0;
117191c17a00Smckusick 	return(0);
117291c17a00Smckusick }
117391c17a00Smckusick 
117491c17a00Smckusick dosub()
117591c17a00Smckusick {
117691c17a00Smckusick 	register char *lp, *sp, *rp;
117791c17a00Smckusick 	int c;
117891c17a00Smckusick 
117991c17a00Smckusick 	lp = linebuf;
118091c17a00Smckusick 	sp = genbuf;
118191c17a00Smckusick 	rp = rhsbuf;
118291c17a00Smckusick 	while (lp < loc1)
118391c17a00Smckusick 		*sp++ = *lp++;
118491c17a00Smckusick 	while (c = *rp++&0377) {
118591c17a00Smckusick 		if (c=='&') {
118691c17a00Smckusick 			sp = place(sp, loc1, loc2);
118791c17a00Smckusick 			continue;
118891c17a00Smckusick 		} else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') {
118991c17a00Smckusick 			sp = place(sp, braslist[c-'1'], braelist[c-'1']);
119091c17a00Smckusick 			continue;
119191c17a00Smckusick 		}
119291c17a00Smckusick 		*sp++ = c&0177;
119391c17a00Smckusick 		if (sp >= &genbuf[LBSIZE])
119491c17a00Smckusick 			error(Q);
119591c17a00Smckusick 	}
119691c17a00Smckusick 	lp = loc2;
119791c17a00Smckusick 	loc2 = sp - genbuf + linebuf;
119891c17a00Smckusick 	while (*sp++ = *lp++)
119991c17a00Smckusick 		if (sp >= &genbuf[LBSIZE])
120091c17a00Smckusick 			error(Q);
120191c17a00Smckusick 	lp = linebuf;
120291c17a00Smckusick 	sp = genbuf;
120391c17a00Smckusick 	while (*lp++ = *sp++)
120491c17a00Smckusick 		;
120591c17a00Smckusick }
120691c17a00Smckusick 
120791c17a00Smckusick char *
120891c17a00Smckusick place(sp, l1, l2)
120991c17a00Smckusick register char *sp, *l1, *l2;
121091c17a00Smckusick {
121191c17a00Smckusick 
121291c17a00Smckusick 	while (l1 < l2) {
121391c17a00Smckusick 		*sp++ = *l1++;
121491c17a00Smckusick 		if (sp >= &genbuf[LBSIZE])
121591c17a00Smckusick 			error(Q);
121691c17a00Smckusick 	}
121791c17a00Smckusick 	return(sp);
121891c17a00Smckusick }
121991c17a00Smckusick 
122091c17a00Smckusick move(cflag)
122191c17a00Smckusick {
122291c17a00Smckusick 	register int *adt, *ad1, *ad2;
122391c17a00Smckusick 	int getcopy();
122491c17a00Smckusick 
122591c17a00Smckusick 	setdot();
122691c17a00Smckusick 	nonzero();
122791c17a00Smckusick 	if ((adt = address())==0)
122891c17a00Smckusick 		error(Q);
122991c17a00Smckusick 	newline();
123091c17a00Smckusick 	if (cflag) {
123191c17a00Smckusick 		int *ozero, delta;
123291c17a00Smckusick 		ad1 = dol;
123391c17a00Smckusick 		ozero = zero;
123491c17a00Smckusick 		append(getcopy, ad1++);
123591c17a00Smckusick 		ad2 = dol;
123691c17a00Smckusick 		delta = zero - ozero;
123791c17a00Smckusick 		ad1 += delta;
123891c17a00Smckusick 		adt += delta;
123991c17a00Smckusick 	} else {
124091c17a00Smckusick 		ad2 = addr2;
124191c17a00Smckusick 		for (ad1 = addr1; ad1 <= ad2;)
124291c17a00Smckusick 			*ad1++ &= ~01;
124391c17a00Smckusick 		ad1 = addr1;
124491c17a00Smckusick 	}
124591c17a00Smckusick 	ad2++;
124691c17a00Smckusick 	if (adt<ad1) {
124791c17a00Smckusick 		dot = adt + (ad2-ad1);
124891c17a00Smckusick 		if ((++adt)==ad1)
124991c17a00Smckusick 			return;
125091c17a00Smckusick 		reverse(adt, ad1);
125191c17a00Smckusick 		reverse(ad1, ad2);
125291c17a00Smckusick 		reverse(adt, ad2);
125391c17a00Smckusick 	} else if (adt >= ad2) {
125491c17a00Smckusick 		dot = adt++;
125591c17a00Smckusick 		reverse(ad1, ad2);
125691c17a00Smckusick 		reverse(ad2, adt);
125791c17a00Smckusick 		reverse(ad1, adt);
125891c17a00Smckusick 	} else
125991c17a00Smckusick 		error(Q);
126091c17a00Smckusick 	fchange = 1;
126191c17a00Smckusick }
126291c17a00Smckusick 
126391c17a00Smckusick reverse(a1, a2)
126491c17a00Smckusick register int *a1, *a2;
126591c17a00Smckusick {
126691c17a00Smckusick 	register int t;
126791c17a00Smckusick 
126891c17a00Smckusick 	for (;;) {
126991c17a00Smckusick 		t = *--a2;
127091c17a00Smckusick 		if (a2 <= a1)
127191c17a00Smckusick 			return;
127291c17a00Smckusick 		*a2 = *a1;
127391c17a00Smckusick 		*a1++ = t;
127491c17a00Smckusick 	}
127591c17a00Smckusick }
127691c17a00Smckusick 
127791c17a00Smckusick getcopy()
127891c17a00Smckusick {
127991c17a00Smckusick 	if (addr1 > addr2)
128091c17a00Smckusick 		return(EOF);
128191c17a00Smckusick 	getline(*addr1++);
128291c17a00Smckusick 	return(0);
128391c17a00Smckusick }
128491c17a00Smckusick 
128591c17a00Smckusick compile(aeof)
128691c17a00Smckusick {
128791c17a00Smckusick 	register eof, c;
128891c17a00Smckusick 	register char *ep;
128991c17a00Smckusick 	char *lastep;
129091c17a00Smckusick 	char bracket[NBRA], *bracketp;
129191c17a00Smckusick 	int cclcnt;
129291c17a00Smckusick 
129391c17a00Smckusick 	ep = expbuf;
129491c17a00Smckusick 	eof = aeof;
129591c17a00Smckusick 	bracketp = bracket;
129691c17a00Smckusick 	if ((c = getchr()) == eof) {
129791c17a00Smckusick 		if (*ep==0)
129891c17a00Smckusick 			error(Q);
129991c17a00Smckusick 		return;
130091c17a00Smckusick 	}
130191c17a00Smckusick 	circfl = 0;
130291c17a00Smckusick 	nbra = 0;
130391c17a00Smckusick 	if (c=='^') {
130491c17a00Smckusick 		c = getchr();
130591c17a00Smckusick 		circfl++;
130691c17a00Smckusick 	}
130791c17a00Smckusick 	peekc = c;
130891c17a00Smckusick 	lastep = 0;
130991c17a00Smckusick 	for (;;) {
131091c17a00Smckusick 		if (ep >= &expbuf[ESIZE])
131191c17a00Smckusick 			goto cerror;
131291c17a00Smckusick 		c = getchr();
131391c17a00Smckusick 		if (c==eof) {
131491c17a00Smckusick 			if (bracketp != bracket)
131591c17a00Smckusick 				goto cerror;
131691c17a00Smckusick 			*ep++ = CEOF;
131791c17a00Smckusick 			return;
131891c17a00Smckusick 		}
131991c17a00Smckusick 		if (c!='*')
132091c17a00Smckusick 			lastep = ep;
132191c17a00Smckusick 		switch (c) {
132291c17a00Smckusick 
132391c17a00Smckusick 		case '\\':
132491c17a00Smckusick 			if ((c = getchr())=='(') {
132591c17a00Smckusick 				if (nbra >= NBRA)
132691c17a00Smckusick 					goto cerror;
132791c17a00Smckusick 				*bracketp++ = nbra;
132891c17a00Smckusick 				*ep++ = CBRA;
132991c17a00Smckusick 				*ep++ = nbra++;
133091c17a00Smckusick 				continue;
133191c17a00Smckusick 			}
133291c17a00Smckusick 			if (c == ')') {
133391c17a00Smckusick 				if (bracketp <= bracket)
133491c17a00Smckusick 					goto cerror;
133591c17a00Smckusick 				*ep++ = CKET;
133691c17a00Smckusick 				*ep++ = *--bracketp;
133791c17a00Smckusick 				continue;
133891c17a00Smckusick 			}
133991c17a00Smckusick 			if (c>='1' && c<'1'+NBRA) {
134091c17a00Smckusick 				*ep++ = CBACK;
134191c17a00Smckusick 				*ep++ = c-'1';
134291c17a00Smckusick 				continue;
134391c17a00Smckusick 			}
134491c17a00Smckusick 			*ep++ = CCHR;
134591c17a00Smckusick 			if (c=='\n')
134691c17a00Smckusick 				goto cerror;
134791c17a00Smckusick 			*ep++ = c;
134891c17a00Smckusick 			continue;
134991c17a00Smckusick 
135091c17a00Smckusick 		case '.':
135191c17a00Smckusick 			*ep++ = CDOT;
135291c17a00Smckusick 			continue;
135391c17a00Smckusick 
135491c17a00Smckusick 		case '\n':
135591c17a00Smckusick 			goto cerror;
135691c17a00Smckusick 
135791c17a00Smckusick 		case '*':
135891c17a00Smckusick 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
135991c17a00Smckusick 				goto defchar;
136091c17a00Smckusick 			*lastep |= STAR;
136191c17a00Smckusick 			continue;
136291c17a00Smckusick 
136391c17a00Smckusick 		case '$':
136491c17a00Smckusick 			if ((peekc=getchr()) != eof)
136591c17a00Smckusick 				goto defchar;
136691c17a00Smckusick 			*ep++ = CDOL;
136791c17a00Smckusick 			continue;
136891c17a00Smckusick 
136991c17a00Smckusick 		case '[':
137091c17a00Smckusick 			*ep++ = CCL;
137191c17a00Smckusick 			*ep++ = 0;
137291c17a00Smckusick 			cclcnt = 1;
137391c17a00Smckusick 			if ((c=getchr()) == '^') {
137491c17a00Smckusick 				c = getchr();
137591c17a00Smckusick 				ep[-2] = NCCL;
137691c17a00Smckusick 			}
137791c17a00Smckusick 			do {
137891c17a00Smckusick 				if (c=='\n')
137991c17a00Smckusick 					goto cerror;
138091c17a00Smckusick 				if (c=='-' && ep[-1]!=0) {
138191c17a00Smckusick 					if ((c=getchr())==']') {
138291c17a00Smckusick 						*ep++ = '-';
138391c17a00Smckusick 						cclcnt++;
138491c17a00Smckusick 						break;
138591c17a00Smckusick 					}
138691c17a00Smckusick 					while (ep[-1]<c) {
138791c17a00Smckusick 						*ep = ep[-1]+1;
138891c17a00Smckusick 						ep++;
138991c17a00Smckusick 						cclcnt++;
139091c17a00Smckusick 						if (ep>=&expbuf[ESIZE])
139191c17a00Smckusick 							goto cerror;
139291c17a00Smckusick 					}
139391c17a00Smckusick 				}
139491c17a00Smckusick 				*ep++ = c;
139591c17a00Smckusick 				cclcnt++;
139691c17a00Smckusick 				if (ep >= &expbuf[ESIZE])
139791c17a00Smckusick 					goto cerror;
139891c17a00Smckusick 			} while ((c = getchr()) != ']');
139991c17a00Smckusick 			lastep[1] = cclcnt;
140091c17a00Smckusick 			continue;
140191c17a00Smckusick 
140291c17a00Smckusick 		defchar:
140391c17a00Smckusick 		default:
140491c17a00Smckusick 			*ep++ = CCHR;
140591c17a00Smckusick 			*ep++ = c;
140691c17a00Smckusick 		}
140791c17a00Smckusick 	}
140891c17a00Smckusick    cerror:
140991c17a00Smckusick 	expbuf[0] = 0;
141091c17a00Smckusick 	nbra = 0;
141191c17a00Smckusick 	error(Q);
141291c17a00Smckusick }
141391c17a00Smckusick 
141491c17a00Smckusick execute(gf, addr)
141591c17a00Smckusick int *addr;
141691c17a00Smckusick {
141791c17a00Smckusick 	register char *p1, *p2, c;
141891c17a00Smckusick 
141991c17a00Smckusick 	for (c=0; c<NBRA; c++) {
142091c17a00Smckusick 		braslist[c] = 0;
142191c17a00Smckusick 		braelist[c] = 0;
142291c17a00Smckusick 	}
142391c17a00Smckusick 	if (gf) {
142491c17a00Smckusick 		if (circfl)
142591c17a00Smckusick 			return(0);
142691c17a00Smckusick 		p1 = linebuf;
142791c17a00Smckusick 		p2 = genbuf;
142891c17a00Smckusick 		while (*p1++ = *p2++)
142991c17a00Smckusick 			;
143091c17a00Smckusick 		locs = p1 = loc2;
143191c17a00Smckusick 	} else {
143291c17a00Smckusick 		if (addr==zero)
143391c17a00Smckusick 			return(0);
143491c17a00Smckusick 		p1 = getline(*addr);
143591c17a00Smckusick 		locs = 0;
143691c17a00Smckusick 	}
143791c17a00Smckusick 	p2 = expbuf;
143891c17a00Smckusick 	if (circfl) {
143991c17a00Smckusick 		loc1 = p1;
144091c17a00Smckusick 		return(advance(p1, p2));
144191c17a00Smckusick 	}
144291c17a00Smckusick 	/* fast check for first character */
144391c17a00Smckusick 	if (*p2==CCHR) {
144491c17a00Smckusick 		c = p2[1];
144591c17a00Smckusick 		do {
144691c17a00Smckusick 			if (*p1!=c)
144791c17a00Smckusick 				continue;
144891c17a00Smckusick 			if (advance(p1, p2)) {
144991c17a00Smckusick 				loc1 = p1;
145091c17a00Smckusick 				return(1);
145191c17a00Smckusick 			}
145291c17a00Smckusick 		} while (*p1++);
145391c17a00Smckusick 		return(0);
145491c17a00Smckusick 	}
145591c17a00Smckusick 	/* regular algorithm */
145691c17a00Smckusick 	do {
145791c17a00Smckusick 		if (advance(p1, p2)) {
145891c17a00Smckusick 			loc1 = p1;
145991c17a00Smckusick 			return(1);
146091c17a00Smckusick 		}
146191c17a00Smckusick 	} while (*p1++);
146291c17a00Smckusick 	return(0);
146391c17a00Smckusick }
146491c17a00Smckusick 
146591c17a00Smckusick advance(lp, ep)
146691c17a00Smckusick register char *ep, *lp;
146791c17a00Smckusick {
146891c17a00Smckusick 	register char *curlp;
146991c17a00Smckusick 	int i;
147091c17a00Smckusick 
147191c17a00Smckusick 	for (;;) switch (*ep++) {
147291c17a00Smckusick 
147391c17a00Smckusick 	case CCHR:
147491c17a00Smckusick 		if (*ep++ == *lp++)
147591c17a00Smckusick 			continue;
147691c17a00Smckusick 		return(0);
147791c17a00Smckusick 
147891c17a00Smckusick 	case CDOT:
147991c17a00Smckusick 		if (*lp++)
148091c17a00Smckusick 			continue;
148191c17a00Smckusick 		return(0);
148291c17a00Smckusick 
148391c17a00Smckusick 	case CDOL:
148491c17a00Smckusick 		if (*lp==0)
148591c17a00Smckusick 			continue;
148691c17a00Smckusick 		return(0);
148791c17a00Smckusick 
148891c17a00Smckusick 	case CEOF:
148991c17a00Smckusick 		loc2 = lp;
149091c17a00Smckusick 		return(1);
149191c17a00Smckusick 
149291c17a00Smckusick 	case CCL:
149391c17a00Smckusick 		if (cclass(ep, *lp++, 1)) {
149491c17a00Smckusick 			ep += *ep;
149591c17a00Smckusick 			continue;
149691c17a00Smckusick 		}
149791c17a00Smckusick 		return(0);
149891c17a00Smckusick 
149991c17a00Smckusick 	case NCCL:
150091c17a00Smckusick 		if (cclass(ep, *lp++, 0)) {
150191c17a00Smckusick 			ep += *ep;
150291c17a00Smckusick 			continue;
150391c17a00Smckusick 		}
150491c17a00Smckusick 		return(0);
150591c17a00Smckusick 
150691c17a00Smckusick 	case CBRA:
150791c17a00Smckusick 		braslist[*ep++] = lp;
150891c17a00Smckusick 		continue;
150991c17a00Smckusick 
151091c17a00Smckusick 	case CKET:
151191c17a00Smckusick 		braelist[*ep++] = lp;
151291c17a00Smckusick 		continue;
151391c17a00Smckusick 
151491c17a00Smckusick 	case CBACK:
151591c17a00Smckusick 		if (braelist[i = *ep++]==0)
151691c17a00Smckusick 			error(Q);
151791c17a00Smckusick 		if (backref(i, lp)) {
151891c17a00Smckusick 			lp += braelist[i] - braslist[i];
151991c17a00Smckusick 			continue;
152091c17a00Smckusick 		}
152191c17a00Smckusick 		return(0);
152291c17a00Smckusick 
152391c17a00Smckusick 	case CBACK|STAR:
152491c17a00Smckusick 		if (braelist[i = *ep++] == 0)
152591c17a00Smckusick 			error(Q);
152691c17a00Smckusick 		curlp = lp;
152791c17a00Smckusick 		while (backref(i, lp))
152891c17a00Smckusick 			lp += braelist[i] - braslist[i];
152991c17a00Smckusick 		while (lp >= curlp) {
153091c17a00Smckusick 			if (advance(lp, ep))
153191c17a00Smckusick 				return(1);
153291c17a00Smckusick 			lp -= braelist[i] - braslist[i];
153391c17a00Smckusick 		}
153491c17a00Smckusick 		continue;
153591c17a00Smckusick 
153691c17a00Smckusick 	case CDOT|STAR:
153791c17a00Smckusick 		curlp = lp;
153891c17a00Smckusick 		while (*lp++)
153991c17a00Smckusick 			;
154091c17a00Smckusick 		goto star;
154191c17a00Smckusick 
154291c17a00Smckusick 	case CCHR|STAR:
154391c17a00Smckusick 		curlp = lp;
154491c17a00Smckusick 		while (*lp++ == *ep)
154591c17a00Smckusick 			;
154691c17a00Smckusick 		ep++;
154791c17a00Smckusick 		goto star;
154891c17a00Smckusick 
154991c17a00Smckusick 	case CCL|STAR:
155091c17a00Smckusick 	case NCCL|STAR:
155191c17a00Smckusick 		curlp = lp;
155291c17a00Smckusick 		while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)))
155391c17a00Smckusick 			;
155491c17a00Smckusick 		ep += *ep;
155591c17a00Smckusick 		goto star;
155691c17a00Smckusick 
155791c17a00Smckusick 	star:
155891c17a00Smckusick 		do {
155991c17a00Smckusick 			lp--;
156091c17a00Smckusick 			if (lp==locs)
156191c17a00Smckusick 				break;
156291c17a00Smckusick 			if (advance(lp, ep))
156391c17a00Smckusick 				return(1);
156491c17a00Smckusick 		} while (lp > curlp);
156591c17a00Smckusick 		return(0);
156691c17a00Smckusick 
156791c17a00Smckusick 	default:
156891c17a00Smckusick 		error(Q);
156991c17a00Smckusick 	}
157091c17a00Smckusick }
157191c17a00Smckusick 
157291c17a00Smckusick backref(i, lp)
157391c17a00Smckusick register i;
157491c17a00Smckusick register char *lp;
157591c17a00Smckusick {
157691c17a00Smckusick 	register char *bp;
157791c17a00Smckusick 
157891c17a00Smckusick 	bp = braslist[i];
157991c17a00Smckusick 	while (*bp++ == *lp++)
158091c17a00Smckusick 		if (bp >= braelist[i])
158191c17a00Smckusick 			return(1);
158291c17a00Smckusick 	return(0);
158391c17a00Smckusick }
158491c17a00Smckusick 
158591c17a00Smckusick cclass(set, c, af)
158691c17a00Smckusick register char *set, c;
158791c17a00Smckusick {
158891c17a00Smckusick 	register n;
158991c17a00Smckusick 
159091c17a00Smckusick 	if (c==0)
159191c17a00Smckusick 		return(0);
159291c17a00Smckusick 	n = *set++;
159391c17a00Smckusick 	while (--n)
159491c17a00Smckusick 		if (*set++ == c)
159591c17a00Smckusick 			return(af);
159691c17a00Smckusick 	return(!af);
159791c17a00Smckusick }
159891c17a00Smckusick 
159991c17a00Smckusick putd()
160091c17a00Smckusick {
160191c17a00Smckusick 	register r;
160291c17a00Smckusick 
160391c17a00Smckusick 	r = count%10;
160491c17a00Smckusick 	count /= 10;
160591c17a00Smckusick 	if (count)
160691c17a00Smckusick 		putd();
160791c17a00Smckusick 	putchr(r + '0');
160891c17a00Smckusick }
160991c17a00Smckusick 
161091c17a00Smckusick puts(sp)
161191c17a00Smckusick register char *sp;
161291c17a00Smckusick {
161391c17a00Smckusick 	col = 0;
161491c17a00Smckusick 	while (*sp)
161591c17a00Smckusick 		putchr(*sp++);
161691c17a00Smckusick 	putchr('\n');
161791c17a00Smckusick }
161891c17a00Smckusick 
161991c17a00Smckusick char	line[70];
162091c17a00Smckusick char	*linp	= line;
162191c17a00Smckusick 
162291c17a00Smckusick putchr(ac)
162391c17a00Smckusick {
162491c17a00Smckusick 	register char *lp;
162591c17a00Smckusick 	register c;
162691c17a00Smckusick 
162791c17a00Smckusick 	lp = linp;
162891c17a00Smckusick 	c = ac;
162991c17a00Smckusick 	if (listf) {
163091c17a00Smckusick 		col++;
163191c17a00Smckusick 		if (col >= 72) {
163291c17a00Smckusick 			col = 0;
163391c17a00Smckusick 			*lp++ = '\\';
163491c17a00Smckusick 			*lp++ = '\n';
163591c17a00Smckusick 		}
163691c17a00Smckusick 		if (c=='\t') {
163791c17a00Smckusick 			c = '>';
163891c17a00Smckusick 			goto esc;
163991c17a00Smckusick 		}
164091c17a00Smckusick 		if (c=='\b') {
164191c17a00Smckusick 			c = '<';
164291c17a00Smckusick 		esc:
164391c17a00Smckusick 			*lp++ = '-';
164491c17a00Smckusick 			*lp++ = '\b';
164591c17a00Smckusick 			*lp++ = c;
164691c17a00Smckusick 			goto out;
164791c17a00Smckusick 		}
164891c17a00Smckusick 		if (c<' ' && c!= '\n') {
164991c17a00Smckusick 			*lp++ = '\\';
165091c17a00Smckusick 			*lp++ = (c>>3)+'0';
165191c17a00Smckusick 			*lp++ = (c&07)+'0';
165291c17a00Smckusick 			col += 2;
165391c17a00Smckusick 			goto out;
165491c17a00Smckusick 		}
165591c17a00Smckusick 	}
165691c17a00Smckusick 	*lp++ = c;
165791c17a00Smckusick out:
165891c17a00Smckusick 	if(c == '\n' || lp >= &line[64]) {
165991c17a00Smckusick 		linp = line;
166091c17a00Smckusick 		write(1, line, lp-line);
166191c17a00Smckusick 		return;
166291c17a00Smckusick 	}
166391c17a00Smckusick 	linp = lp;
166491c17a00Smckusick }
1665da1d502bSmckusick 
1666d3b12757Sbostic #ifdef CRYPT
1667d3b12757Sbostic /*
1668d3b12757Sbostic  * Begin routines for doing encryption.
1669d3b12757Sbostic  */
1670d3b12757Sbostic crblock(permp, buf, nchar, startn)
1671d3b12757Sbostic char *permp;
1672d3b12757Sbostic char *buf;
1673d3b12757Sbostic long startn;
1674d3b12757Sbostic {
1675d3b12757Sbostic 	register char *p1;
1676d3b12757Sbostic 	int n1;
1677d3b12757Sbostic 	int n2;
1678d3b12757Sbostic 	register char *t1, *t2, *t3;
1679d3b12757Sbostic 
1680d3b12757Sbostic 	t1 = permp;
1681d3b12757Sbostic 	t2 = &permp[256];
1682d3b12757Sbostic 	t3 = &permp[512];
1683d3b12757Sbostic 
1684d3b12757Sbostic 	n1 = startn&0377;
1685d3b12757Sbostic 	n2 = (startn>>8)&0377;
1686d3b12757Sbostic 	p1 = buf;
1687d3b12757Sbostic 	while(nchar--) {
1688d3b12757Sbostic 		*p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1;
1689d3b12757Sbostic 		n1++;
1690d3b12757Sbostic 		if(n1==256){
1691d3b12757Sbostic 			n1 = 0;
1692d3b12757Sbostic 			n2++;
1693d3b12757Sbostic 			if(n2==256) n2 = 0;
1694d3b12757Sbostic 		}
1695d3b12757Sbostic 		p1++;
1696d3b12757Sbostic 	}
1697d3b12757Sbostic }
1698d3b12757Sbostic 
1699d3b12757Sbostic getkey()
1700d3b12757Sbostic {
1701d3b12757Sbostic 	struct sgttyb b;
1702d3b12757Sbostic 	int save;
1703*522670b9Sbostic 	sig_t sig;
1704d3b12757Sbostic 	register char *p;
1705d3b12757Sbostic 	register c;
1706d3b12757Sbostic 
1707d3b12757Sbostic 	sig = signal(SIGINT, SIG_IGN);
170856423badSbostic 	if (ioctl(0, TIOCGETP, &b) == -1)
1709d3b12757Sbostic 		error("Input not tty");
1710d3b12757Sbostic 	save = b.sg_flags;
1711d3b12757Sbostic 	b.sg_flags &= ~ECHO;
171256423badSbostic 	(void)ioctl(0, TIOCSETP, &b);
1713d3b12757Sbostic 	puts("Key:");
1714d3b12757Sbostic 	p = key;
1715d3b12757Sbostic 	while(((c=getchr()) != EOF) && (c!='\n')) {
1716d3b12757Sbostic 		if(p < &key[KSIZE])
1717d3b12757Sbostic 			*p++ = c;
1718d3b12757Sbostic 	}
1719d3b12757Sbostic 	*p = 0;
1720d3b12757Sbostic 	b.sg_flags = save;
172156423badSbostic 	(void)ioctl(0, TIOCSETP, &b);
1722d3b12757Sbostic 	signal(SIGINT, sig);
1723d3b12757Sbostic 	return(key[0] != 0);
1724d3b12757Sbostic }
1725d3b12757Sbostic 
1726d3b12757Sbostic /*
1727d3b12757Sbostic  * Besides initializing the encryption machine, this routine
1728d3b12757Sbostic  * returns 0 if the key is null, and 1 if it is non-null.
1729d3b12757Sbostic  */
1730d3b12757Sbostic crinit(keyp, permp)
1731d3b12757Sbostic char	*keyp, *permp;
1732d3b12757Sbostic {
1733d3b12757Sbostic 	register char *t1, *t2, *t3;
1734d3b12757Sbostic 	register i;
1735d3b12757Sbostic 	int ic, k, temp, pf[2];
1736d3b12757Sbostic 	unsigned random;
1737d3b12757Sbostic 	char buf[13];
1738d3b12757Sbostic 	long seed;
1739d3b12757Sbostic 
1740d3b12757Sbostic 	t1 = permp;
1741d3b12757Sbostic 	t2 = &permp[256];
1742d3b12757Sbostic 	t3 = &permp[512];
1743d3b12757Sbostic 	if(*keyp == 0)
1744d3b12757Sbostic 		return(0);
1745d3b12757Sbostic 	strncpy(buf, keyp, 8);
1746d3b12757Sbostic 	while (*keyp)
1747d3b12757Sbostic 		*keyp++ = '\0';
1748d3b12757Sbostic 	buf[8] = buf[0];
1749d3b12757Sbostic 	buf[9] = buf[1];
1750d3b12757Sbostic 	if (pipe(pf)<0)
1751d3b12757Sbostic 		pf[0] = pf[1] = -1;
1752d3b12757Sbostic 	if (fork()==0) {
1753d3b12757Sbostic 		close(0);
1754d3b12757Sbostic 		close(1);
1755d3b12757Sbostic 		dup(pf[0]);
1756d3b12757Sbostic 		dup(pf[1]);
1757f1a7ebf6Sbostic 		execl(_PATH_MAKEKEY, "-", 0);
1758d3b12757Sbostic 		exit(1);
1759d3b12757Sbostic 	}
1760d3b12757Sbostic 	write(pf[1], buf, 10);
1761d3b12757Sbostic 	if (wait((int *)NULL)==-1 || read(pf[0], buf, 13)!=13)
1762d3b12757Sbostic 		error("crypt: cannot generate key");
1763d3b12757Sbostic 	close(pf[0]);
1764d3b12757Sbostic 	close(pf[1]);
1765d3b12757Sbostic 	seed = 123;
1766d3b12757Sbostic 	for (i=0; i<13; i++)
1767d3b12757Sbostic 		seed = seed*buf[i] + i;
1768d3b12757Sbostic 	for(i=0;i<256;i++){
1769d3b12757Sbostic 		t1[i] = i;
1770d3b12757Sbostic 		t3[i] = 0;
1771d3b12757Sbostic 	}
1772d3b12757Sbostic 	for(i=0; i<256; i++) {
1773d3b12757Sbostic 		seed = 5*seed + buf[i%13];
1774d3b12757Sbostic 		random = seed % 65521;
1775d3b12757Sbostic 		k = 256-1 - i;
1776d3b12757Sbostic 		ic = (random&0377) % (k+1);
1777d3b12757Sbostic 		random >>= 8;
1778d3b12757Sbostic 		temp = t1[k];
1779d3b12757Sbostic 		t1[k] = t1[ic];
1780d3b12757Sbostic 		t1[ic] = temp;
1781d3b12757Sbostic 		if(t3[k]!=0) continue;
1782d3b12757Sbostic 		ic = (random&0377) % k;
1783d3b12757Sbostic 		while(t3[ic]!=0) ic = (ic+1) % k;
1784d3b12757Sbostic 		t3[k] = ic;
1785d3b12757Sbostic 		t3[ic] = k;
1786d3b12757Sbostic 	}
1787d3b12757Sbostic 	for(i=0; i<256; i++)
1788d3b12757Sbostic 		t2[t1[i]&0377] = i;
1789d3b12757Sbostic 	return(1);
1790d3b12757Sbostic }
1791d3b12757Sbostic 
1792d3b12757Sbostic makekey(a, b)
1793d3b12757Sbostic char *a, *b;
1794d3b12757Sbostic {
1795d3b12757Sbostic 	register int i;
1796d3b12757Sbostic 	long t;
1797d3b12757Sbostic 	char temp[KSIZE + 1];
1798d3b12757Sbostic 
1799d3b12757Sbostic 	for(i = 0; i < KSIZE; i++)
1800d3b12757Sbostic 		temp[i] = *a++;
1801d3b12757Sbostic 	time(&t);
1802d3b12757Sbostic 	t += getpid();
1803d3b12757Sbostic 	for(i = 0; i < 4; i++)
1804d3b12757Sbostic 		temp[i] ^= (t>>(8*i))&0377;
1805d3b12757Sbostic 	crinit(temp, b);
1806d3b12757Sbostic }
1807d3b12757Sbostic #endif CRYPT
1808