xref: /original-bsd/bin/ed/ed.c (revision a9a02843)
1 #ifndef lint
2 static char sccsid[] = "@(#)ed.c	4.10 (Berkeley) 05/27/89";
3 #endif
4 
5 /*
6  * Editor
7  */
8 #define CRYPT
9 
10 #include <signal.h>
11 #include <sgtty.h>
12 #undef CEOF
13 #include <setjmp.h>
14 #include "pathnames.h"
15 
16 #define	NULL	0
17 #define	FNSIZE	64
18 #define	LBSIZE	512
19 #define	ESIZE	128
20 #define	GBSIZE	256
21 #define	NBRA	5
22 #define	EOF	-1
23 
24 #define	CBRA	1
25 #define	CCHR	2
26 #define	CDOT	4
27 #define	CCL	6
28 #define	NCCL	8
29 #define	CDOL	10
30 #define	CEOF	11
31 #define	CKET	12
32 #define	CBACK	14
33 
34 #define	STAR	01
35 
36 char	Q[]	= "";
37 char	T[]	= "TMP";
38 #define	READ	0
39 #define	WRITE	1
40 
41 int	peekc;
42 int	lastc;
43 char	savedfile[FNSIZE];
44 char	file[FNSIZE];
45 char	linebuf[LBSIZE];
46 char	rhsbuf[LBSIZE/2];
47 char	expbuf[ESIZE+4];
48 int	circfl;
49 int	*zero;
50 int	*dot;
51 int	*dol;
52 int	*addr1;
53 int	*addr2;
54 char	genbuf[LBSIZE];
55 long	count;
56 char	*nextip;
57 char	*linebp;
58 int	ninbuf;
59 int	io;
60 int	pflag;
61 long	lseek();
62 int	(*oldhup)();
63 int	(*oldquit)();
64 int	vflag	= 1;
65 
66 #ifdef CRYPT
67 /*
68  * Various flags and buffers needed by the encryption routines.
69  */
70 #define	KSIZE	9
71 int	xflag;
72 int	xtflag;
73 int	kflag;
74 char	key[KSIZE + 1];
75 char	crbuf[512];
76 char	perm[768];
77 char	tperm[768];
78 #endif CRYPT
79 
80 int	listf;
81 int	col;
82 char	*globp;
83 int	tfile	= -1;
84 int	tline;
85 char	tfname[sizeof(_PATH_TMP) + 20];
86 char	*loc1;
87 char	*loc2;
88 char	*locs;
89 char	ibuff[512];
90 int	iblock	= -1;
91 char	obuff[512];
92 int	oblock	= -1;
93 int	ichanged;
94 int	nleft;
95 char	WRERR[]	= "WRITE ERROR";
96 int	names[26];
97 int	anymarks;
98 char	*braslist[NBRA];
99 char	*braelist[NBRA];
100 int	nbra;
101 int	subnewa;
102 int	subolda;
103 int	fchange;
104 int	wrapp;
105 unsigned nlall = 128;
106 
107 int	*address();
108 char	*getline();
109 char	*getblock();
110 char	*place();
111 char	*mktemp();
112 char	*malloc();
113 char	*realloc();
114 jmp_buf	savej;
115 
116 main(argc, argv)
117 char **argv;
118 {
119 	register char *p1, *p2;
120 	extern int onintr(), quit(), onhup();
121 	int (*oldintr)();
122 
123 	oldquit = signal(SIGQUIT, SIG_IGN);
124 	oldhup = signal(SIGHUP, SIG_IGN);
125 	oldintr = signal(SIGINT, SIG_IGN);
126 	if ((int)signal(SIGTERM, SIG_IGN) == 0)
127 		signal(SIGTERM, quit);
128 	argv++;
129 	while (argc > 1 && **argv=='-') {
130 		switch((*argv)[1]) {
131 
132 		case '\0':
133 			vflag = 0;
134 			break;
135 
136 		case 'q':
137 			signal(SIGQUIT, SIG_DFL);
138 			vflag = 1;
139 			break;
140 
141 #ifdef CRYPT
142 		case 'x':
143 			xflag = 1;
144 			break;
145 #endif CRYPT
146 		}
147 		argv++;
148 		argc--;
149 	}
150 #ifdef CRYPT
151 	if(xflag){
152 		getkey();
153 		kflag = crinit(key, perm);
154 	}
155 #endif CRYPT
156 
157 	if (argc>1) {
158 		p1 = *argv;
159 		p2 = savedfile;
160 		while (*p2++ = *p1++)
161 			;
162 		globp = "r";
163 	}
164 	zero = (int *)malloc(nlall*sizeof(int));
165 	(void)strcpy(tfname, _PATH_TMP);
166 	(void)strcat(tfname, "_edXXXXXX");
167 	(void)mktemp(tfname);
168 	init();
169 	if (((int)oldintr&01) == 0)
170 		signal(SIGINT, onintr);
171 	if (((int)oldhup&01) == 0)
172 		signal(SIGHUP, onhup);
173 	setjmp(savej);
174 	commands();
175 	quit();
176 }
177 
178 commands()
179 {
180 	int getfile(), gettty();
181 	register *a1, c;
182 
183 	for (;;) {
184 	if (pflag) {
185 		pflag = 0;
186 		addr1 = addr2 = dot;
187 		goto print;
188 	}
189 	addr1 = 0;
190 	addr2 = 0;
191 	do {
192 		addr1 = addr2;
193 		if ((a1 = address())==0) {
194 			c = getchr();
195 			break;
196 		}
197 		addr2 = a1;
198 		if ((c=getchr()) == ';') {
199 			c = ',';
200 			dot = a1;
201 		}
202 	} while (c==',');
203 	if (addr1==0)
204 		addr1 = addr2;
205 	switch(c) {
206 
207 	case 'a':
208 		setdot();
209 		newline();
210 		append(gettty, addr2);
211 		continue;
212 
213 	case 'c':
214 		delete();
215 		append(gettty, addr1-1);
216 		continue;
217 
218 	case 'd':
219 		delete();
220 		continue;
221 
222 	case 'E':
223 		fchange = 0;
224 		c = 'e';
225 	case 'e':
226 		setnoaddr();
227 		if (vflag && fchange) {
228 			fchange = 0;
229 			error(Q);
230 		}
231 		filename(c);
232 		init();
233 		addr2 = zero;
234 		goto caseread;
235 
236 	case 'f':
237 		setnoaddr();
238 		filename(c);
239 		puts(savedfile);
240 		continue;
241 
242 	case 'g':
243 		global(1);
244 		continue;
245 
246 	case 'i':
247 		setdot();
248 		nonzero();
249 		newline();
250 		append(gettty, addr2-1);
251 		continue;
252 
253 
254 	case 'j':
255 		if (addr2==0) {
256 			addr1 = dot;
257 			addr2 = dot+1;
258 		}
259 		setdot();
260 		newline();
261 		nonzero();
262 		join();
263 		continue;
264 
265 	case 'k':
266 		if ((c = getchr()) < 'a' || c > 'z')
267 			error(Q);
268 		newline();
269 		setdot();
270 		nonzero();
271 		names[c-'a'] = *addr2 & ~01;
272 		anymarks |= 01;
273 		continue;
274 
275 	case 'm':
276 		move(0);
277 		continue;
278 
279 	case '\n':
280 		if (addr2==0)
281 			addr2 = dot+1;
282 		addr1 = addr2;
283 		goto print;
284 
285 	case 'l':
286 		listf++;
287 	case 'p':
288 	case 'P':
289 		newline();
290 	print:
291 		setdot();
292 		nonzero();
293 		a1 = addr1;
294 		do {
295 			puts(getline(*a1++));
296 		} while (a1 <= addr2);
297 		dot = addr2;
298 		listf = 0;
299 		continue;
300 
301 	case 'Q':
302 		fchange = 0;
303 	case 'q':
304 		setnoaddr();
305 		newline();
306 		quit();
307 
308 	case 'r':
309 		filename(c);
310 	caseread:
311 		if ((io = open(file, 0)) < 0) {
312 			lastc = '\n';
313 			error(file);
314 		}
315 		setall();
316 		ninbuf = 0;
317 		c = zero != dol;
318 		append(getfile, addr2);
319 		exfile();
320 		fchange = c;
321 		continue;
322 
323 	case 's':
324 		setdot();
325 		nonzero();
326 		substitute(globp!=0);
327 		continue;
328 
329 	case 't':
330 		move(1);
331 		continue;
332 
333 	case 'u':
334 		setdot();
335 		nonzero();
336 		newline();
337 		if ((*addr2&~01) != subnewa)
338 			error(Q);
339 		*addr2 = subolda;
340 		dot = addr2;
341 		continue;
342 
343 	case 'v':
344 		global(0);
345 		continue;
346 
347 	case 'W':
348 		wrapp++;
349 	case 'w':
350 		setall();
351 		nonzero();
352 		filename(c);
353 		if(!wrapp ||
354 		  ((io = open(file,1)) == -1) ||
355 		  ((lseek(io, 0L, 2)) == -1))
356 			if ((io = creat(file, 0666)) < 0)
357 				error(file);
358 		wrapp = 0;
359 		putfile();
360 		exfile();
361 		if (addr1==zero+1 && addr2==dol)
362 			fchange = 0;
363 		continue;
364 
365 #ifdef CRYPT
366 	case 'x':
367 		setnoaddr();
368 		newline();
369 		xflag = 1;
370 		puts("Entering encrypting mode!");
371 		getkey();
372 		kflag = crinit(key, perm);
373 		continue;
374 #endif CRYPT
375 
376 
377 	case '=':
378 		setall();
379 		newline();
380 		count = (addr2-zero)&077777;
381 		putd();
382 		putchr('\n');
383 		continue;
384 
385 	case '!':
386 		callunix();
387 		continue;
388 
389 	case EOF:
390 		return;
391 
392 	}
393 	error(Q);
394 	}
395 }
396 
397 int *
398 address()
399 {
400 	register *a1, minus, c;
401 	int n, relerr;
402 
403 	minus = 0;
404 	a1 = 0;
405 	for (;;) {
406 		c = getchr();
407 		if ('0'<=c && c<='9') {
408 			n = 0;
409 			do {
410 				n *= 10;
411 				n += c - '0';
412 			} while ((c = getchr())>='0' && c<='9');
413 			peekc = c;
414 			if (a1==0)
415 				a1 = zero;
416 			if (minus<0)
417 				n = -n;
418 			a1 += n;
419 			minus = 0;
420 			continue;
421 		}
422 		relerr = 0;
423 		if (a1 || minus)
424 			relerr++;
425 		switch(c) {
426 		case ' ':
427 		case '\t':
428 			continue;
429 
430 		case '+':
431 			minus++;
432 			if (a1==0)
433 				a1 = dot;
434 			continue;
435 
436 		case '-':
437 		case '^':
438 			minus--;
439 			if (a1==0)
440 				a1 = dot;
441 			continue;
442 
443 		case '?':
444 		case '/':
445 			compile(c);
446 			a1 = dot;
447 			for (;;) {
448 				if (c=='/') {
449 					a1++;
450 					if (a1 > dol)
451 						a1 = zero;
452 				} else {
453 					a1--;
454 					if (a1 < zero)
455 						a1 = dol;
456 				}
457 				if (execute(0, a1))
458 					break;
459 				if (a1==dot)
460 					error(Q);
461 			}
462 			break;
463 
464 		case '$':
465 			a1 = dol;
466 			break;
467 
468 		case '.':
469 			a1 = dot;
470 			break;
471 
472 		case '\'':
473 			if ((c = getchr()) < 'a' || c > 'z')
474 				error(Q);
475 			for (a1=zero; a1<=dol; a1++)
476 				if (names[c-'a'] == (*a1 & ~01))
477 					break;
478 			break;
479 
480 		default:
481 			peekc = c;
482 			if (a1==0)
483 				return(0);
484 			a1 += minus;
485 			if (a1<zero || a1>dol)
486 				error(Q);
487 			return(a1);
488 		}
489 		if (relerr)
490 			error(Q);
491 	}
492 }
493 
494 setdot()
495 {
496 	if (addr2 == 0)
497 		addr1 = addr2 = dot;
498 	if (addr1 > addr2)
499 		error(Q);
500 }
501 
502 setall()
503 {
504 	if (addr2==0) {
505 		addr1 = zero+1;
506 		addr2 = dol;
507 		if (dol==zero)
508 			addr1 = zero;
509 	}
510 	setdot();
511 }
512 
513 setnoaddr()
514 {
515 	if (addr2)
516 		error(Q);
517 }
518 
519 nonzero()
520 {
521 	if (addr1<=zero || addr2>dol)
522 		error(Q);
523 }
524 
525 newline()
526 {
527 	register c;
528 
529 	if ((c = getchr()) == '\n')
530 		return;
531 	if (c=='p' || c=='l') {
532 		pflag++;
533 		if (c=='l')
534 			listf++;
535 		if (getchr() == '\n')
536 			return;
537 	}
538 	error(Q);
539 }
540 
541 filename(comm)
542 {
543 	register char *p1, *p2;
544 	register c;
545 
546 	count = 0;
547 	c = getchr();
548 	if (c=='\n' || c==EOF) {
549 		p1 = savedfile;
550 		if (*p1==0 && comm!='f')
551 			error(Q);
552 		p2 = file;
553 		while (*p2++ = *p1++)
554 			;
555 		return;
556 	}
557 	if (c!=' ')
558 		error(Q);
559 	while ((c = getchr()) == ' ')
560 		;
561 	if (c=='\n')
562 		error(Q);
563 	p1 = file;
564 	do {
565 		*p1++ = c;
566 		if (c==' ' || c==EOF)
567 			error(Q);
568 	} while ((c = getchr()) != '\n');
569 	*p1++ = 0;
570 	if (savedfile[0]==0 || comm=='e' || comm=='f') {
571 		p1 = savedfile;
572 		p2 = file;
573 		while (*p1++ = *p2++)
574 			;
575 	}
576 }
577 
578 exfile()
579 {
580 	close(io);
581 	io = -1;
582 	if (vflag) {
583 		putd();
584 		putchr('\n');
585 	}
586 }
587 
588 onintr()
589 {
590 	signal(SIGINT, onintr);
591 	putchr('\n');
592 	lastc = '\n';
593 	error(Q);
594 }
595 
596 onhup()
597 {
598 	signal(SIGINT, SIG_IGN);
599 	signal(SIGHUP, SIG_IGN);
600 	if (dol > zero) {
601 		addr1 = zero+1;
602 		addr2 = dol;
603 		io = creat("ed.hup", 0666);
604 		if (io > 0)
605 			putfile();
606 	}
607 	fchange = 0;
608 	quit();
609 }
610 
611 error(s)
612 char *s;
613 {
614 	register c;
615 
616 	wrapp = 0;
617 	listf = 0;
618 	putchr('?');
619 	puts(s);
620 	count = 0;
621 	lseek(0, (long)0, 2);
622 	pflag = 0;
623 	if (globp)
624 		lastc = '\n';
625 	globp = 0;
626 	peekc = lastc;
627 	if(lastc)
628 		while ((c = getchr()) != '\n' && c != EOF)
629 			;
630 	if (io > 0) {
631 		close(io);
632 		io = -1;
633 	}
634 	longjmp(savej, 1);
635 }
636 
637 getchr()
638 {
639 	char c;
640 	if (lastc=peekc) {
641 		peekc = 0;
642 		return(lastc);
643 	}
644 	if (globp) {
645 		if ((lastc = *globp++) != 0)
646 			return(lastc);
647 		globp = 0;
648 		return(EOF);
649 	}
650 	if (read(0, &c, 1) <= 0)
651 		return(lastc = EOF);
652 	lastc = c&0177;
653 	return(lastc);
654 }
655 
656 gettty()
657 {
658 	register c;
659 	register char *gf;
660 	register char *p;
661 
662 	p = linebuf;
663 	gf = globp;
664 	while ((c = getchr()) != '\n') {
665 		if (c==EOF) {
666 			if (gf)
667 				peekc = c;
668 			return(c);
669 		}
670 		if ((c &= 0177) == 0)
671 			continue;
672 		*p++ = c;
673 		if (p >= &linebuf[LBSIZE-2])
674 			error(Q);
675 	}
676 	*p++ = 0;
677 	if (linebuf[0]=='.' && linebuf[1]==0)
678 		return(EOF);
679 	return(0);
680 }
681 
682 getfile()
683 {
684 	register c;
685 	register char *lp, *fp;
686 
687 	lp = linebuf;
688 	fp = nextip;
689 	do {
690 		if (--ninbuf < 0) {
691 			if ((ninbuf = read(io, genbuf, LBSIZE)-1) < 0)
692 				return(EOF);
693 			fp = genbuf;
694 			while(fp < &genbuf[ninbuf]) {
695 				if (*fp++ & 0200) {
696 #ifdef CRYPT
697 					if (kflag)
698 						crblock(perm, genbuf, ninbuf+1, count);
699 #endif CRYPT
700 					break;
701 				}
702 			}
703 			fp = genbuf;
704 		}
705 		c = *fp++;
706 		if (c=='\0')
707 			continue;
708 		if (c&0200 || lp >= &linebuf[LBSIZE]) {
709 			lastc = '\n';
710 			error(Q);
711 		}
712 		*lp++ = c;
713 		count++;
714 	} while (c != '\n');
715 	*--lp = 0;
716 	nextip = fp;
717 	return(0);
718 }
719 
720 putfile()
721 {
722 	int *a1, n;
723 	register char *fp, *lp;
724 	register nib;
725 
726 	nib = 512;
727 	fp = genbuf;
728 	a1 = addr1;
729 	do {
730 		lp = getline(*a1++);
731 		for (;;) {
732 			if (--nib < 0) {
733 				n = fp-genbuf;
734 #ifdef CRYPT
735 				if(kflag)
736 					crblock(perm, genbuf, n, count-n);
737 #endif CRYPT
738 				if(write(io, genbuf, n) != n) {
739 					puts(WRERR);
740 					error(Q);
741 				}
742 				nib = 511;
743 				fp = genbuf;
744 			}
745 			count++;
746 			if ((*fp++ = *lp++) == 0) {
747 				fp[-1] = '\n';
748 				break;
749 			}
750 		}
751 	} while (a1 <= addr2);
752 	n = fp-genbuf;
753 #ifdef CRYPT
754 	if(kflag)
755 		crblock(perm, genbuf, n, count-n);
756 #endif CRYPT
757 	if(write(io, genbuf, n) != n) {
758 		puts(WRERR);
759 		error(Q);
760 	}
761 }
762 
763 append(f, a)
764 int *a;
765 int (*f)();
766 {
767 	register *a1, *a2, *rdot;
768 	int nline, tl;
769 
770 	nline = 0;
771 	dot = a;
772 	while ((*f)() == 0) {
773 		if ((dol-zero)+1 >= nlall) {
774 			int *ozero = zero;
775 			nlall += 512;
776 			if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) {
777 				lastc = '\n';
778 				zero = ozero;
779 				error("MEM?");
780 			}
781 			dot += zero - ozero;
782 			dol += zero - ozero;
783 		}
784 		tl = putline();
785 		nline++;
786 		a1 = ++dol;
787 		a2 = a1+1;
788 		rdot = ++dot;
789 		while (a1 > rdot)
790 			*--a2 = *--a1;
791 		*rdot = tl;
792 	}
793 	return(nline);
794 }
795 
796 callunix()
797 {
798 	register (*savint)(), pid, rpid;
799 	int retcode;
800 
801 	setnoaddr();
802 	if ((pid = fork()) == 0) {
803 		signal(SIGHUP, oldhup);
804 		signal(SIGQUIT, oldquit);
805 		execl(_PATH_BSHELL, "sh", "-t", 0);
806 		exit(0100);
807 	}
808 	savint = signal(SIGINT, SIG_IGN);
809 	while ((rpid = wait(&retcode)) != pid && rpid != -1)
810 		;
811 	signal(SIGINT, savint);
812 	puts("!");
813 }
814 
815 quit()
816 {
817 	if (vflag && fchange && dol!=zero) {
818 		fchange = 0;
819 		error(Q);
820 	}
821 	unlink(tfname);
822 	exit(0);
823 }
824 
825 delete()
826 {
827 	setdot();
828 	newline();
829 	nonzero();
830 	rdelete(addr1, addr2);
831 }
832 
833 rdelete(ad1, ad2)
834 int *ad1, *ad2;
835 {
836 	register *a1, *a2, *a3;
837 
838 	a1 = ad1;
839 	a2 = ad2+1;
840 	a3 = dol;
841 	dol -= a2 - a1;
842 	do {
843 		*a1++ = *a2++;
844 	} while (a2 <= a3);
845 	a1 = ad1;
846 	if (a1 > dol)
847 		a1 = dol;
848 	dot = a1;
849 	fchange = 1;
850 }
851 
852 gdelete()
853 {
854 	register *a1, *a2, *a3;
855 
856 	a3 = dol;
857 	for (a1=zero+1; (*a1&01)==0; a1++)
858 		if (a1>=a3)
859 			return;
860 	for (a2=a1+1; a2<=a3;) {
861 		if (*a2&01) {
862 			a2++;
863 			dot = a1;
864 		} else
865 			*a1++ = *a2++;
866 	}
867 	dol = a1-1;
868 	if (dot>dol)
869 		dot = dol;
870 	fchange = 1;
871 }
872 
873 char *
874 getline(tl)
875 {
876 	register char *bp, *lp;
877 	register nl;
878 
879 	lp = linebuf;
880 	bp = getblock(tl, READ);
881 	nl = nleft;
882 	tl &= ~0377;
883 	while (*lp++ = *bp++)
884 		if (--nl == 0) {
885 			bp = getblock(tl+=0400, READ);
886 			nl = nleft;
887 		}
888 	return(linebuf);
889 }
890 
891 putline()
892 {
893 	register char *bp, *lp;
894 	register nl;
895 	int tl;
896 
897 	fchange = 1;
898 	lp = linebuf;
899 	tl = tline;
900 	bp = getblock(tl, WRITE);
901 	nl = nleft;
902 	tl &= ~0377;
903 	while (*bp = *lp++) {
904 		if (*bp++ == '\n') {
905 			*--bp = 0;
906 			linebp = lp;
907 			break;
908 		}
909 		if (--nl == 0) {
910 			bp = getblock(tl+=0400, WRITE);
911 			nl = nleft;
912 		}
913 	}
914 	nl = tline;
915 	tline += (((lp-linebuf)+03)>>1)&077776;
916 	return(nl);
917 }
918 
919 char *
920 getblock(atl, iof)
921 {
922 	extern read(), write();
923 	register bno, off;
924 	register char *p1, *p2;
925 	register int n;
926 
927 	bno = (atl>>8)&0377;
928 	off = (atl<<1)&0774;
929 	if (bno >= 255) {
930 		lastc = '\n';
931 		error(T);
932 	}
933 	nleft = 512 - off;
934 	if (bno==iblock) {
935 		ichanged |= iof;
936 		return(ibuff+off);
937 	}
938 	if (bno==oblock)
939 		return(obuff+off);
940 	if (iof==READ) {
941 		if (ichanged) {
942 #ifdef CRYPT
943 			if(xtflag)
944 				crblock(tperm, ibuff, 512, (long)0);
945 #endif CRYPT
946 			blkio(iblock, ibuff, write);
947 		}
948 		ichanged = 0;
949 		iblock = bno;
950 		blkio(bno, ibuff, read);
951 #ifdef CRYPT
952 		if(xtflag)
953 			crblock(tperm, ibuff, 512, (long)0);
954 #endif CRYPT
955 		return(ibuff+off);
956 	}
957 	if (oblock>=0) {
958 #ifdef CRYPT
959 		if(xtflag) {
960 			p1 = obuff;
961 			p2 = crbuf;
962 			n = 512;
963 			while(n--)
964 				*p2++ = *p1++;
965 			crblock(tperm, crbuf, 512, (long)0);
966 			blkio(oblock, crbuf, write);
967 		} else
968 #endif CRYPT
969 			blkio(oblock, obuff, write);
970 	}
971 	oblock = bno;
972 	return(obuff+off);
973 }
974 
975 blkio(b, buf, iofcn)
976 char *buf;
977 int (*iofcn)();
978 {
979 	lseek(tfile, (long)b<<9, 0);
980 	if ((*iofcn)(tfile, buf, 512) != 512) {
981 		error(T);
982 	}
983 }
984 
985 init()
986 {
987 	register *markp;
988 
989 	close(tfile);
990 	tline = 2;
991 	for (markp = names; markp < &names[26]; )
992 		*markp++ = 0;
993 	subnewa = 0;
994 	anymarks = 0;
995 	iblock = -1;
996 	oblock = -1;
997 	ichanged = 0;
998 	close(creat(tfname, 0600));
999 	tfile = open(tfname, 2);
1000 #ifdef CRYPT
1001 	if(xflag) {
1002 		xtflag = 1;
1003 		makekey(key, tperm);
1004 	}
1005 #endif CRYPT
1006 	dot = dol = zero;
1007 }
1008 
1009 global(k)
1010 {
1011 	register char *gp;
1012 	register c;
1013 	register int *a1;
1014 	char globuf[GBSIZE];
1015 
1016 	if (globp)
1017 		error(Q);
1018 	setall();
1019 	nonzero();
1020 	if ((c=getchr())=='\n')
1021 		error(Q);
1022 	compile(c);
1023 	gp = globuf;
1024 	while ((c = getchr()) != '\n') {
1025 		if (c==EOF)
1026 			error(Q);
1027 		if (c=='\\') {
1028 			c = getchr();
1029 			if (c!='\n')
1030 				*gp++ = '\\';
1031 		}
1032 		*gp++ = c;
1033 		if (gp >= &globuf[GBSIZE-2])
1034 			error(Q);
1035 	}
1036 	*gp++ = '\n';
1037 	*gp++ = 0;
1038 	for (a1=zero; a1<=dol; a1++) {
1039 		*a1 &= ~01;
1040 		if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k)
1041 			*a1 |= 01;
1042 	}
1043 	/*
1044 	 * Special case: g/.../d (avoid n^2 algorithm)
1045 	 */
1046 	if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
1047 		gdelete();
1048 		return;
1049 	}
1050 	for (a1=zero; a1<=dol; a1++) {
1051 		if (*a1 & 01) {
1052 			*a1 &= ~01;
1053 			dot = a1;
1054 			globp = globuf;
1055 			commands();
1056 			a1 = zero;
1057 		}
1058 	}
1059 }
1060 
1061 join()
1062 {
1063 	register char *gp, *lp;
1064 	register *a1;
1065 
1066 	gp = genbuf;
1067 	for (a1=addr1; a1<=addr2; a1++) {
1068 		lp = getline(*a1);
1069 		while (*gp = *lp++)
1070 			if (gp++ >= &genbuf[LBSIZE-2])
1071 				error(Q);
1072 	}
1073 	lp = linebuf;
1074 	gp = genbuf;
1075 	while (*lp++ = *gp++)
1076 		;
1077 	*addr1 = putline();
1078 	if (addr1<addr2)
1079 		rdelete(addr1+1, addr2);
1080 	dot = addr1;
1081 }
1082 
1083 substitute(inglob)
1084 {
1085 	register *markp, *a1, nl;
1086 	int gsubf;
1087 	int getsub();
1088 
1089 	gsubf = compsub();
1090 	for (a1 = addr1; a1 <= addr2; a1++) {
1091 		int *ozero;
1092 		if (execute(0, a1)==0)
1093 			continue;
1094 		inglob |= 01;
1095 		dosub();
1096 		if (gsubf) {
1097 			while (*loc2) {
1098 				if (execute(1, (int *)0)==0)
1099 					break;
1100 				dosub();
1101 			}
1102 		}
1103 		subnewa = putline();
1104 		*a1 &= ~01;
1105 		if (anymarks) {
1106 			for (markp = names; markp < &names[26]; markp++)
1107 				if (*markp == *a1)
1108 					*markp = subnewa;
1109 		}
1110 		subolda = *a1;
1111 		*a1 = subnewa;
1112 		ozero = zero;
1113 		nl = append(getsub, a1);
1114 		nl += zero-ozero;
1115 		a1 += nl;
1116 		addr2 += nl;
1117 	}
1118 	if (inglob==0)
1119 		error(Q);
1120 }
1121 
1122 compsub()
1123 {
1124 	register seof, c;
1125 	register char *p;
1126 
1127 	if ((seof = getchr()) == '\n' || seof == ' ')
1128 		error(Q);
1129 	compile(seof);
1130 	p = rhsbuf;
1131 	for (;;) {
1132 		c = getchr();
1133 		if (c=='\\')
1134 			c = getchr() | 0200;
1135 		if (c=='\n') {
1136 			if (globp)
1137 				c |= 0200;
1138 			else
1139 				error(Q);
1140 		}
1141 		if (c==seof)
1142 			break;
1143 		*p++ = c;
1144 		if (p >= &rhsbuf[LBSIZE/2])
1145 			error(Q);
1146 	}
1147 	*p++ = 0;
1148 	if ((peekc = getchr()) == 'g') {
1149 		peekc = 0;
1150 		newline();
1151 		return(1);
1152 	}
1153 	newline();
1154 	return(0);
1155 }
1156 
1157 getsub()
1158 {
1159 	register char *p1, *p2;
1160 
1161 	p1 = linebuf;
1162 	if ((p2 = linebp) == 0)
1163 		return(EOF);
1164 	while (*p1++ = *p2++)
1165 		;
1166 	linebp = 0;
1167 	return(0);
1168 }
1169 
1170 dosub()
1171 {
1172 	register char *lp, *sp, *rp;
1173 	int c;
1174 
1175 	lp = linebuf;
1176 	sp = genbuf;
1177 	rp = rhsbuf;
1178 	while (lp < loc1)
1179 		*sp++ = *lp++;
1180 	while (c = *rp++&0377) {
1181 		if (c=='&') {
1182 			sp = place(sp, loc1, loc2);
1183 			continue;
1184 		} else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') {
1185 			sp = place(sp, braslist[c-'1'], braelist[c-'1']);
1186 			continue;
1187 		}
1188 		*sp++ = c&0177;
1189 		if (sp >= &genbuf[LBSIZE])
1190 			error(Q);
1191 	}
1192 	lp = loc2;
1193 	loc2 = sp - genbuf + linebuf;
1194 	while (*sp++ = *lp++)
1195 		if (sp >= &genbuf[LBSIZE])
1196 			error(Q);
1197 	lp = linebuf;
1198 	sp = genbuf;
1199 	while (*lp++ = *sp++)
1200 		;
1201 }
1202 
1203 char *
1204 place(sp, l1, l2)
1205 register char *sp, *l1, *l2;
1206 {
1207 
1208 	while (l1 < l2) {
1209 		*sp++ = *l1++;
1210 		if (sp >= &genbuf[LBSIZE])
1211 			error(Q);
1212 	}
1213 	return(sp);
1214 }
1215 
1216 move(cflag)
1217 {
1218 	register int *adt, *ad1, *ad2;
1219 	int getcopy();
1220 
1221 	setdot();
1222 	nonzero();
1223 	if ((adt = address())==0)
1224 		error(Q);
1225 	newline();
1226 	if (cflag) {
1227 		int *ozero, delta;
1228 		ad1 = dol;
1229 		ozero = zero;
1230 		append(getcopy, ad1++);
1231 		ad2 = dol;
1232 		delta = zero - ozero;
1233 		ad1 += delta;
1234 		adt += delta;
1235 	} else {
1236 		ad2 = addr2;
1237 		for (ad1 = addr1; ad1 <= ad2;)
1238 			*ad1++ &= ~01;
1239 		ad1 = addr1;
1240 	}
1241 	ad2++;
1242 	if (adt<ad1) {
1243 		dot = adt + (ad2-ad1);
1244 		if ((++adt)==ad1)
1245 			return;
1246 		reverse(adt, ad1);
1247 		reverse(ad1, ad2);
1248 		reverse(adt, ad2);
1249 	} else if (adt >= ad2) {
1250 		dot = adt++;
1251 		reverse(ad1, ad2);
1252 		reverse(ad2, adt);
1253 		reverse(ad1, adt);
1254 	} else
1255 		error(Q);
1256 	fchange = 1;
1257 }
1258 
1259 reverse(a1, a2)
1260 register int *a1, *a2;
1261 {
1262 	register int t;
1263 
1264 	for (;;) {
1265 		t = *--a2;
1266 		if (a2 <= a1)
1267 			return;
1268 		*a2 = *a1;
1269 		*a1++ = t;
1270 	}
1271 }
1272 
1273 getcopy()
1274 {
1275 	if (addr1 > addr2)
1276 		return(EOF);
1277 	getline(*addr1++);
1278 	return(0);
1279 }
1280 
1281 compile(aeof)
1282 {
1283 	register eof, c;
1284 	register char *ep;
1285 	char *lastep;
1286 	char bracket[NBRA], *bracketp;
1287 	int cclcnt;
1288 
1289 	ep = expbuf;
1290 	eof = aeof;
1291 	bracketp = bracket;
1292 	if ((c = getchr()) == eof) {
1293 		if (*ep==0)
1294 			error(Q);
1295 		return;
1296 	}
1297 	circfl = 0;
1298 	nbra = 0;
1299 	if (c=='^') {
1300 		c = getchr();
1301 		circfl++;
1302 	}
1303 	peekc = c;
1304 	lastep = 0;
1305 	for (;;) {
1306 		if (ep >= &expbuf[ESIZE])
1307 			goto cerror;
1308 		c = getchr();
1309 		if (c==eof) {
1310 			if (bracketp != bracket)
1311 				goto cerror;
1312 			*ep++ = CEOF;
1313 			return;
1314 		}
1315 		if (c!='*')
1316 			lastep = ep;
1317 		switch (c) {
1318 
1319 		case '\\':
1320 			if ((c = getchr())=='(') {
1321 				if (nbra >= NBRA)
1322 					goto cerror;
1323 				*bracketp++ = nbra;
1324 				*ep++ = CBRA;
1325 				*ep++ = nbra++;
1326 				continue;
1327 			}
1328 			if (c == ')') {
1329 				if (bracketp <= bracket)
1330 					goto cerror;
1331 				*ep++ = CKET;
1332 				*ep++ = *--bracketp;
1333 				continue;
1334 			}
1335 			if (c>='1' && c<'1'+NBRA) {
1336 				*ep++ = CBACK;
1337 				*ep++ = c-'1';
1338 				continue;
1339 			}
1340 			*ep++ = CCHR;
1341 			if (c=='\n')
1342 				goto cerror;
1343 			*ep++ = c;
1344 			continue;
1345 
1346 		case '.':
1347 			*ep++ = CDOT;
1348 			continue;
1349 
1350 		case '\n':
1351 			goto cerror;
1352 
1353 		case '*':
1354 			if (lastep==0 || *lastep==CBRA || *lastep==CKET)
1355 				goto defchar;
1356 			*lastep |= STAR;
1357 			continue;
1358 
1359 		case '$':
1360 			if ((peekc=getchr()) != eof)
1361 				goto defchar;
1362 			*ep++ = CDOL;
1363 			continue;
1364 
1365 		case '[':
1366 			*ep++ = CCL;
1367 			*ep++ = 0;
1368 			cclcnt = 1;
1369 			if ((c=getchr()) == '^') {
1370 				c = getchr();
1371 				ep[-2] = NCCL;
1372 			}
1373 			do {
1374 				if (c=='\n')
1375 					goto cerror;
1376 				if (c=='-' && ep[-1]!=0) {
1377 					if ((c=getchr())==']') {
1378 						*ep++ = '-';
1379 						cclcnt++;
1380 						break;
1381 					}
1382 					while (ep[-1]<c) {
1383 						*ep = ep[-1]+1;
1384 						ep++;
1385 						cclcnt++;
1386 						if (ep>=&expbuf[ESIZE])
1387 							goto cerror;
1388 					}
1389 				}
1390 				*ep++ = c;
1391 				cclcnt++;
1392 				if (ep >= &expbuf[ESIZE])
1393 					goto cerror;
1394 			} while ((c = getchr()) != ']');
1395 			lastep[1] = cclcnt;
1396 			continue;
1397 
1398 		defchar:
1399 		default:
1400 			*ep++ = CCHR;
1401 			*ep++ = c;
1402 		}
1403 	}
1404    cerror:
1405 	expbuf[0] = 0;
1406 	nbra = 0;
1407 	error(Q);
1408 }
1409 
1410 execute(gf, addr)
1411 int *addr;
1412 {
1413 	register char *p1, *p2, c;
1414 
1415 	for (c=0; c<NBRA; c++) {
1416 		braslist[c] = 0;
1417 		braelist[c] = 0;
1418 	}
1419 	if (gf) {
1420 		if (circfl)
1421 			return(0);
1422 		p1 = linebuf;
1423 		p2 = genbuf;
1424 		while (*p1++ = *p2++)
1425 			;
1426 		locs = p1 = loc2;
1427 	} else {
1428 		if (addr==zero)
1429 			return(0);
1430 		p1 = getline(*addr);
1431 		locs = 0;
1432 	}
1433 	p2 = expbuf;
1434 	if (circfl) {
1435 		loc1 = p1;
1436 		return(advance(p1, p2));
1437 	}
1438 	/* fast check for first character */
1439 	if (*p2==CCHR) {
1440 		c = p2[1];
1441 		do {
1442 			if (*p1!=c)
1443 				continue;
1444 			if (advance(p1, p2)) {
1445 				loc1 = p1;
1446 				return(1);
1447 			}
1448 		} while (*p1++);
1449 		return(0);
1450 	}
1451 	/* regular algorithm */
1452 	do {
1453 		if (advance(p1, p2)) {
1454 			loc1 = p1;
1455 			return(1);
1456 		}
1457 	} while (*p1++);
1458 	return(0);
1459 }
1460 
1461 advance(lp, ep)
1462 register char *ep, *lp;
1463 {
1464 	register char *curlp;
1465 	int i;
1466 
1467 	for (;;) switch (*ep++) {
1468 
1469 	case CCHR:
1470 		if (*ep++ == *lp++)
1471 			continue;
1472 		return(0);
1473 
1474 	case CDOT:
1475 		if (*lp++)
1476 			continue;
1477 		return(0);
1478 
1479 	case CDOL:
1480 		if (*lp==0)
1481 			continue;
1482 		return(0);
1483 
1484 	case CEOF:
1485 		loc2 = lp;
1486 		return(1);
1487 
1488 	case CCL:
1489 		if (cclass(ep, *lp++, 1)) {
1490 			ep += *ep;
1491 			continue;
1492 		}
1493 		return(0);
1494 
1495 	case NCCL:
1496 		if (cclass(ep, *lp++, 0)) {
1497 			ep += *ep;
1498 			continue;
1499 		}
1500 		return(0);
1501 
1502 	case CBRA:
1503 		braslist[*ep++] = lp;
1504 		continue;
1505 
1506 	case CKET:
1507 		braelist[*ep++] = lp;
1508 		continue;
1509 
1510 	case CBACK:
1511 		if (braelist[i = *ep++]==0)
1512 			error(Q);
1513 		if (backref(i, lp)) {
1514 			lp += braelist[i] - braslist[i];
1515 			continue;
1516 		}
1517 		return(0);
1518 
1519 	case CBACK|STAR:
1520 		if (braelist[i = *ep++] == 0)
1521 			error(Q);
1522 		curlp = lp;
1523 		while (backref(i, lp))
1524 			lp += braelist[i] - braslist[i];
1525 		while (lp >= curlp) {
1526 			if (advance(lp, ep))
1527 				return(1);
1528 			lp -= braelist[i] - braslist[i];
1529 		}
1530 		continue;
1531 
1532 	case CDOT|STAR:
1533 		curlp = lp;
1534 		while (*lp++)
1535 			;
1536 		goto star;
1537 
1538 	case CCHR|STAR:
1539 		curlp = lp;
1540 		while (*lp++ == *ep)
1541 			;
1542 		ep++;
1543 		goto star;
1544 
1545 	case CCL|STAR:
1546 	case NCCL|STAR:
1547 		curlp = lp;
1548 		while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)))
1549 			;
1550 		ep += *ep;
1551 		goto star;
1552 
1553 	star:
1554 		do {
1555 			lp--;
1556 			if (lp==locs)
1557 				break;
1558 			if (advance(lp, ep))
1559 				return(1);
1560 		} while (lp > curlp);
1561 		return(0);
1562 
1563 	default:
1564 		error(Q);
1565 	}
1566 }
1567 
1568 backref(i, lp)
1569 register i;
1570 register char *lp;
1571 {
1572 	register char *bp;
1573 
1574 	bp = braslist[i];
1575 	while (*bp++ == *lp++)
1576 		if (bp >= braelist[i])
1577 			return(1);
1578 	return(0);
1579 }
1580 
1581 cclass(set, c, af)
1582 register char *set, c;
1583 {
1584 	register n;
1585 
1586 	if (c==0)
1587 		return(0);
1588 	n = *set++;
1589 	while (--n)
1590 		if (*set++ == c)
1591 			return(af);
1592 	return(!af);
1593 }
1594 
1595 putd()
1596 {
1597 	register r;
1598 
1599 	r = count%10;
1600 	count /= 10;
1601 	if (count)
1602 		putd();
1603 	putchr(r + '0');
1604 }
1605 
1606 puts(sp)
1607 register char *sp;
1608 {
1609 	col = 0;
1610 	while (*sp)
1611 		putchr(*sp++);
1612 	putchr('\n');
1613 }
1614 
1615 char	line[70];
1616 char	*linp	= line;
1617 
1618 putchr(ac)
1619 {
1620 	register char *lp;
1621 	register c;
1622 
1623 	lp = linp;
1624 	c = ac;
1625 	if (listf) {
1626 		col++;
1627 		if (col >= 72) {
1628 			col = 0;
1629 			*lp++ = '\\';
1630 			*lp++ = '\n';
1631 		}
1632 		if (c=='\t') {
1633 			c = '>';
1634 			goto esc;
1635 		}
1636 		if (c=='\b') {
1637 			c = '<';
1638 		esc:
1639 			*lp++ = '-';
1640 			*lp++ = '\b';
1641 			*lp++ = c;
1642 			goto out;
1643 		}
1644 		if (c<' ' && c!= '\n') {
1645 			*lp++ = '\\';
1646 			*lp++ = (c>>3)+'0';
1647 			*lp++ = (c&07)+'0';
1648 			col += 2;
1649 			goto out;
1650 		}
1651 	}
1652 	*lp++ = c;
1653 out:
1654 	if(c == '\n' || lp >= &line[64]) {
1655 		linp = line;
1656 		write(1, line, lp-line);
1657 		return;
1658 	}
1659 	linp = lp;
1660 }
1661 
1662 #ifdef CRYPT
1663 /*
1664  * Begin routines for doing encryption.
1665  */
1666 crblock(permp, buf, nchar, startn)
1667 char *permp;
1668 char *buf;
1669 long startn;
1670 {
1671 	register char *p1;
1672 	int n1;
1673 	int n2;
1674 	register char *t1, *t2, *t3;
1675 
1676 	t1 = permp;
1677 	t2 = &permp[256];
1678 	t3 = &permp[512];
1679 
1680 	n1 = startn&0377;
1681 	n2 = (startn>>8)&0377;
1682 	p1 = buf;
1683 	while(nchar--) {
1684 		*p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1;
1685 		n1++;
1686 		if(n1==256){
1687 			n1 = 0;
1688 			n2++;
1689 			if(n2==256) n2 = 0;
1690 		}
1691 		p1++;
1692 	}
1693 }
1694 
1695 getkey()
1696 {
1697 	struct sgttyb b;
1698 	int save;
1699 	int (*sig)();
1700 	register char *p;
1701 	register c;
1702 
1703 	sig = signal(SIGINT, SIG_IGN);
1704 	if (ioctl(0, TIOCGETP, &b) == -1)
1705 		error("Input not tty");
1706 	save = b.sg_flags;
1707 	b.sg_flags &= ~ECHO;
1708 	(void)ioctl(0, TIOCSETP, &b);
1709 	puts("Key:");
1710 	p = key;
1711 	while(((c=getchr()) != EOF) && (c!='\n')) {
1712 		if(p < &key[KSIZE])
1713 			*p++ = c;
1714 	}
1715 	*p = 0;
1716 	b.sg_flags = save;
1717 	(void)ioctl(0, TIOCSETP, &b);
1718 	signal(SIGINT, sig);
1719 	return(key[0] != 0);
1720 }
1721 
1722 /*
1723  * Besides initializing the encryption machine, this routine
1724  * returns 0 if the key is null, and 1 if it is non-null.
1725  */
1726 crinit(keyp, permp)
1727 char	*keyp, *permp;
1728 {
1729 	register char *t1, *t2, *t3;
1730 	register i;
1731 	int ic, k, temp, pf[2];
1732 	unsigned random;
1733 	char buf[13];
1734 	long seed;
1735 
1736 	t1 = permp;
1737 	t2 = &permp[256];
1738 	t3 = &permp[512];
1739 	if(*keyp == 0)
1740 		return(0);
1741 	strncpy(buf, keyp, 8);
1742 	while (*keyp)
1743 		*keyp++ = '\0';
1744 	buf[8] = buf[0];
1745 	buf[9] = buf[1];
1746 	if (pipe(pf)<0)
1747 		pf[0] = pf[1] = -1;
1748 	if (fork()==0) {
1749 		close(0);
1750 		close(1);
1751 		dup(pf[0]);
1752 		dup(pf[1]);
1753 		execl(_PATH_MAKEKEY, "-", 0);
1754 		exit(1);
1755 	}
1756 	write(pf[1], buf, 10);
1757 	if (wait((int *)NULL)==-1 || read(pf[0], buf, 13)!=13)
1758 		error("crypt: cannot generate key");
1759 	close(pf[0]);
1760 	close(pf[1]);
1761 	seed = 123;
1762 	for (i=0; i<13; i++)
1763 		seed = seed*buf[i] + i;
1764 	for(i=0;i<256;i++){
1765 		t1[i] = i;
1766 		t3[i] = 0;
1767 	}
1768 	for(i=0; i<256; i++) {
1769 		seed = 5*seed + buf[i%13];
1770 		random = seed % 65521;
1771 		k = 256-1 - i;
1772 		ic = (random&0377) % (k+1);
1773 		random >>= 8;
1774 		temp = t1[k];
1775 		t1[k] = t1[ic];
1776 		t1[ic] = temp;
1777 		if(t3[k]!=0) continue;
1778 		ic = (random&0377) % k;
1779 		while(t3[ic]!=0) ic = (ic+1) % k;
1780 		t3[k] = ic;
1781 		t3[ic] = k;
1782 	}
1783 	for(i=0; i<256; i++)
1784 		t2[t1[i]&0377] = i;
1785 	return(1);
1786 }
1787 
1788 makekey(a, b)
1789 char *a, *b;
1790 {
1791 	register int i;
1792 	long t;
1793 	char temp[KSIZE + 1];
1794 
1795 	for(i = 0; i < KSIZE; i++)
1796 		temp[i] = *a++;
1797 	time(&t);
1798 	t += getpid();
1799 	for(i = 0; i < 4; i++)
1800 		temp[i] ^= (t>>(8*i))&0377;
1801 	crinit(temp, b);
1802 }
1803 #endif CRYPT
1804