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