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