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