typo in nntp name
[unix-history] / usr / src / bin / ed / ed.c
CommitLineData
205a2d85 1#ifndef lint
3b1d2c60 2static char sccsid[] = "@(#)ed.c 4.4 (Berkeley) %G%";
205a2d85 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;
31e58db8
KM
752 if ((zero = (int *)realloc((char *)zero, nlall*sizeof(int)))==NULL) {
753 lastc = '\n';
754 zero = ozero;
755 error("MEM?");
756 }
757 dot += zero - ozero;
758 dol += zero - ozero;
759 }
760 tl = putline();
761 nline++;
762 a1 = ++dol;
763 a2 = a1+1;
764 rdot = ++dot;
765 while (a1 > rdot)
766 *--a2 = *--a1;
767 *rdot = tl;
768 }
769 return(nline);
770}
771
772callunix()
773{
774 register (*savint)(), pid, rpid;
775 int retcode;
776
777 setnoaddr();
778 if ((pid = fork()) == 0) {
779 signal(SIGHUP, oldhup);
780 signal(SIGQUIT, oldquit);
781 execl("/bin/sh", "sh", "-t", 0);
782 exit(0100);
783 }
784 savint = signal(SIGINT, SIG_IGN);
785 while ((rpid = wait(&retcode)) != pid && rpid != -1)
786 ;
787 signal(SIGINT, savint);
788 puts("!");
789}
790
791quit()
792{
793 if (vflag && fchange && dol!=zero) {
794 fchange = 0;
795 error(Q);
796 }
797 unlink(tfname);
798 exit(0);
799}
800
801delete()
802{
803 setdot();
804 newline();
805 nonzero();
806 rdelete(addr1, addr2);
807}
808
809rdelete(ad1, ad2)
810int *ad1, *ad2;
811{
812 register *a1, *a2, *a3;
813
814 a1 = ad1;
815 a2 = ad2+1;
816 a3 = dol;
817 dol -= a2 - a1;
818 do {
819 *a1++ = *a2++;
820 } while (a2 <= a3);
821 a1 = ad1;
822 if (a1 > dol)
823 a1 = dol;
824 dot = a1;
825 fchange = 1;
826}
827
828gdelete()
829{
830 register *a1, *a2, *a3;
831
832 a3 = dol;
833 for (a1=zero+1; (*a1&01)==0; a1++)
834 if (a1>=a3)
835 return;
836 for (a2=a1+1; a2<=a3;) {
837 if (*a2&01) {
838 a2++;
839 dot = a1;
840 } else
841 *a1++ = *a2++;
842 }
843 dol = a1-1;
844 if (dot>dol)
845 dot = dol;
846 fchange = 1;
847}
848
849char *
850getline(tl)
851{
852 register char *bp, *lp;
853 register nl;
854
855 lp = linebuf;
856 bp = getblock(tl, READ);
857 nl = nleft;
858 tl &= ~0377;
859 while (*lp++ = *bp++)
860 if (--nl == 0) {
861 bp = getblock(tl+=0400, READ);
862 nl = nleft;
863 }
864 return(linebuf);
865}
866
867putline()
868{
869 register char *bp, *lp;
870 register nl;
871 int tl;
872
873 fchange = 1;
874 lp = linebuf;
875 tl = tline;
876 bp = getblock(tl, WRITE);
877 nl = nleft;
878 tl &= ~0377;
879 while (*bp = *lp++) {
880 if (*bp++ == '\n') {
881 *--bp = 0;
882 linebp = lp;
883 break;
884 }
885 if (--nl == 0) {
886 bp = getblock(tl+=0400, WRITE);
887 nl = nleft;
888 }
889 }
890 nl = tline;
891 tline += (((lp-linebuf)+03)>>1)&077776;
892 return(nl);
893}
894
895char *
896getblock(atl, iof)
897{
898 extern read(), write();
899 register bno, off;
900 register char *p1, *p2;
901 register int n;
902
903 bno = (atl>>8)&0377;
904 off = (atl<<1)&0774;
905 if (bno >= 255) {
906 lastc = '\n';
907 error(T);
908 }
909 nleft = 512 - off;
910 if (bno==iblock) {
911 ichanged |= iof;
912 return(ibuff+off);
913 }
914 if (bno==oblock)
915 return(obuff+off);
916 if (iof==READ) {
917 if (ichanged) {
918 if(xtflag)
919 crblock(tperm, ibuff, 512, (long)0);
920 blkio(iblock, ibuff, write);
921 }
922 ichanged = 0;
923 iblock = bno;
924 blkio(bno, ibuff, read);
925 if(xtflag)
926 crblock(tperm, ibuff, 512, (long)0);
927 return(ibuff+off);
928 }
929 if (oblock>=0) {
930 if(xtflag) {
931 p1 = obuff;
932 p2 = crbuf;
933 n = 512;
934 while(n--)
935 *p2++ = *p1++;
936 crblock(tperm, crbuf, 512, (long)0);
937 blkio(oblock, crbuf, write);
938 } else
939 blkio(oblock, obuff, write);
940 }
941 oblock = bno;
942 return(obuff+off);
943}
944
945blkio(b, buf, iofcn)
946char *buf;
947int (*iofcn)();
948{
949 lseek(tfile, (long)b<<9, 0);
950 if ((*iofcn)(tfile, buf, 512) != 512) {
951 error(T);
952 }
953}
954
955init()
956{
957 register *markp;
958
959 close(tfile);
960 tline = 2;
961 for (markp = names; markp < &names[26]; )
962 *markp++ = 0;
963 subnewa = 0;
964 anymarks = 0;
965 iblock = -1;
966 oblock = -1;
967 ichanged = 0;
968 close(creat(tfname, 0600));
969 tfile = open(tfname, 2);
970 if(xflag) {
971 xtflag = 1;
972 makekey(key, tperm);
973 }
974 dot = dol = zero;
975}
976
977global(k)
978{
979 register char *gp;
980 register c;
981 register int *a1;
982 char globuf[GBSIZE];
983
984 if (globp)
985 error(Q);
986 setall();
987 nonzero();
988 if ((c=getchr())=='\n')
989 error(Q);
990 compile(c);
991 gp = globuf;
992 while ((c = getchr()) != '\n') {
993 if (c==EOF)
994 error(Q);
995 if (c=='\\') {
996 c = getchr();
997 if (c!='\n')
998 *gp++ = '\\';
999 }
1000 *gp++ = c;
1001 if (gp >= &globuf[GBSIZE-2])
1002 error(Q);
1003 }
1004 *gp++ = '\n';
1005 *gp++ = 0;
1006 for (a1=zero; a1<=dol; a1++) {
1007 *a1 &= ~01;
1008 if (a1>=addr1 && a1<=addr2 && execute(0, a1)==k)
1009 *a1 |= 01;
1010 }
1011 /*
1012 * Special case: g/.../d (avoid n^2 algorithm)
1013 */
1014 if (globuf[0]=='d' && globuf[1]=='\n' && globuf[2]=='\0') {
1015 gdelete();
1016 return;
1017 }
1018 for (a1=zero; a1<=dol; a1++) {
1019 if (*a1 & 01) {
1020 *a1 &= ~01;
1021 dot = a1;
1022 globp = globuf;
1023 commands();
1024 a1 = zero;
1025 }
1026 }
1027}
1028
1029join()
1030{
1031 register char *gp, *lp;
1032 register *a1;
1033
1034 gp = genbuf;
1035 for (a1=addr1; a1<=addr2; a1++) {
1036 lp = getline(*a1);
1037 while (*gp = *lp++)
1038 if (gp++ >= &genbuf[LBSIZE-2])
1039 error(Q);
1040 }
1041 lp = linebuf;
1042 gp = genbuf;
1043 while (*lp++ = *gp++)
1044 ;
1045 *addr1 = putline();
1046 if (addr1<addr2)
1047 rdelete(addr1+1, addr2);
1048 dot = addr1;
1049}
1050
1051substitute(inglob)
1052{
1053 register *markp, *a1, nl;
1054 int gsubf;
1055 int getsub();
1056
1057 gsubf = compsub();
1058 for (a1 = addr1; a1 <= addr2; a1++) {
1059 int *ozero;
1060 if (execute(0, a1)==0)
1061 continue;
1062 inglob |= 01;
1063 dosub();
1064 if (gsubf) {
1065 while (*loc2) {
1066 if (execute(1, (int *)0)==0)
1067 break;
1068 dosub();
1069 }
1070 }
1071 subnewa = putline();
1072 *a1 &= ~01;
1073 if (anymarks) {
1074 for (markp = names; markp < &names[26]; markp++)
1075 if (*markp == *a1)
1076 *markp = subnewa;
1077 }
1078 subolda = *a1;
1079 *a1 = subnewa;
1080 ozero = zero;
1081 nl = append(getsub, a1);
1082 nl += zero-ozero;
1083 a1 += nl;
1084 addr2 += nl;
1085 }
1086 if (inglob==0)
1087 error(Q);
1088}
1089
1090compsub()
1091{
1092 register seof, c;
1093 register char *p;
1094
1095 if ((seof = getchr()) == '\n' || seof == ' ')
1096 error(Q);
1097 compile(seof);
1098 p = rhsbuf;
1099 for (;;) {
1100 c = getchr();
1101 if (c=='\\')
1102 c = getchr() | 0200;
1103 if (c=='\n') {
1104 if (globp)
1105 c |= 0200;
1106 else
1107 error(Q);
1108 }
1109 if (c==seof)
1110 break;
1111 *p++ = c;
1112 if (p >= &rhsbuf[LBSIZE/2])
1113 error(Q);
1114 }
1115 *p++ = 0;
1116 if ((peekc = getchr()) == 'g') {
1117 peekc = 0;
1118 newline();
1119 return(1);
1120 }
1121 newline();
1122 return(0);
1123}
1124
1125getsub()
1126{
1127 register char *p1, *p2;
1128
1129 p1 = linebuf;
1130 if ((p2 = linebp) == 0)
1131 return(EOF);
1132 while (*p1++ = *p2++)
1133 ;
1134 linebp = 0;
1135 return(0);
1136}
1137
1138dosub()
1139{
1140 register char *lp, *sp, *rp;
1141 int c;
1142
1143 lp = linebuf;
1144 sp = genbuf;
1145 rp = rhsbuf;
1146 while (lp < loc1)
1147 *sp++ = *lp++;
1148 while (c = *rp++&0377) {
1149 if (c=='&') {
1150 sp = place(sp, loc1, loc2);
1151 continue;
1152 } else if (c&0200 && (c &= 0177) >='1' && c < nbra+'1') {
1153 sp = place(sp, braslist[c-'1'], braelist[c-'1']);
1154 continue;
1155 }
1156 *sp++ = c&0177;
1157 if (sp >= &genbuf[LBSIZE])
1158 error(Q);
1159 }
1160 lp = loc2;
1161 loc2 = sp - genbuf + linebuf;
1162 while (*sp++ = *lp++)
1163 if (sp >= &genbuf[LBSIZE])
1164 error(Q);
1165 lp = linebuf;
1166 sp = genbuf;
1167 while (*lp++ = *sp++)
1168 ;
1169}
1170
1171char *
1172place(sp, l1, l2)
1173register char *sp, *l1, *l2;
1174{
1175
1176 while (l1 < l2) {
1177 *sp++ = *l1++;
1178 if (sp >= &genbuf[LBSIZE])
1179 error(Q);
1180 }
1181 return(sp);
1182}
1183
1184move(cflag)
1185{
1186 register int *adt, *ad1, *ad2;
1187 int getcopy();
1188
1189 setdot();
1190 nonzero();
1191 if ((adt = address())==0)
1192 error(Q);
1193 newline();
1194 if (cflag) {
1195 int *ozero, delta;
1196 ad1 = dol;
1197 ozero = zero;
1198 append(getcopy, ad1++);
1199 ad2 = dol;
1200 delta = zero - ozero;
1201 ad1 += delta;
1202 adt += delta;
1203 } else {
1204 ad2 = addr2;
1205 for (ad1 = addr1; ad1 <= ad2;)
1206 *ad1++ &= ~01;
1207 ad1 = addr1;
1208 }
1209 ad2++;
1210 if (adt<ad1) {
1211 dot = adt + (ad2-ad1);
1212 if ((++adt)==ad1)
1213 return;
1214 reverse(adt, ad1);
1215 reverse(ad1, ad2);
1216 reverse(adt, ad2);
1217 } else if (adt >= ad2) {
1218 dot = adt++;
1219 reverse(ad1, ad2);
1220 reverse(ad2, adt);
1221 reverse(ad1, adt);
1222 } else
1223 error(Q);
1224 fchange = 1;
1225}
1226
1227reverse(a1, a2)
1228register int *a1, *a2;
1229{
1230 register int t;
1231
1232 for (;;) {
1233 t = *--a2;
1234 if (a2 <= a1)
1235 return;
1236 *a2 = *a1;
1237 *a1++ = t;
1238 }
1239}
1240
1241getcopy()
1242{
1243 if (addr1 > addr2)
1244 return(EOF);
1245 getline(*addr1++);
1246 return(0);
1247}
1248
1249compile(aeof)
1250{
1251 register eof, c;
1252 register char *ep;
1253 char *lastep;
1254 char bracket[NBRA], *bracketp;
1255 int cclcnt;
1256
1257 ep = expbuf;
1258 eof = aeof;
1259 bracketp = bracket;
1260 if ((c = getchr()) == eof) {
1261 if (*ep==0)
1262 error(Q);
1263 return;
1264 }
1265 circfl = 0;
1266 nbra = 0;
1267 if (c=='^') {
1268 c = getchr();
1269 circfl++;
1270 }
1271 peekc = c;
1272 lastep = 0;
1273 for (;;) {
1274 if (ep >= &expbuf[ESIZE])
1275 goto cerror;
1276 c = getchr();
1277 if (c==eof) {
1278 if (bracketp != bracket)
1279 goto cerror;
1280 *ep++ = CEOF;
1281 return;
1282 }
1283 if (c!='*')
1284 lastep = ep;
1285 switch (c) {
1286
1287 case '\\':
1288 if ((c = getchr())=='(') {
1289 if (nbra >= NBRA)
1290 goto cerror;
1291 *bracketp++ = nbra;
1292 *ep++ = CBRA;
1293 *ep++ = nbra++;
1294 continue;
1295 }
1296 if (c == ')') {
1297 if (bracketp <= bracket)
1298 goto cerror;
1299 *ep++ = CKET;
1300 *ep++ = *--bracketp;
1301 continue;
1302 }
1303 if (c>='1' && c<'1'+NBRA) {
1304 *ep++ = CBACK;
1305 *ep++ = c-'1';
1306 continue;
1307 }
1308 *ep++ = CCHR;
1309 if (c=='\n')
1310 goto cerror;
1311 *ep++ = c;
1312 continue;
1313
1314 case '.':
1315 *ep++ = CDOT;
1316 continue;
1317
1318 case '\n':
1319 goto cerror;
1320
1321 case '*':
1322 if (lastep==0 || *lastep==CBRA || *lastep==CKET)
1323 goto defchar;
1324 *lastep |= STAR;
1325 continue;
1326
1327 case '$':
1328 if ((peekc=getchr()) != eof)
1329 goto defchar;
1330 *ep++ = CDOL;
1331 continue;
1332
1333 case '[':
1334 *ep++ = CCL;
1335 *ep++ = 0;
1336 cclcnt = 1;
1337 if ((c=getchr()) == '^') {
1338 c = getchr();
1339 ep[-2] = NCCL;
1340 }
1341 do {
1342 if (c=='\n')
1343 goto cerror;
1344 if (c=='-' && ep[-1]!=0) {
1345 if ((c=getchr())==']') {
1346 *ep++ = '-';
1347 cclcnt++;
1348 break;
1349 }
1350 while (ep[-1]<c) {
1351 *ep = ep[-1]+1;
1352 ep++;
1353 cclcnt++;
1354 if (ep>=&expbuf[ESIZE])
1355 goto cerror;
1356 }
1357 }
1358 *ep++ = c;
1359 cclcnt++;
1360 if (ep >= &expbuf[ESIZE])
1361 goto cerror;
1362 } while ((c = getchr()) != ']');
1363 lastep[1] = cclcnt;
1364 continue;
1365
1366 defchar:
1367 default:
1368 *ep++ = CCHR;
1369 *ep++ = c;
1370 }
1371 }
1372 cerror:
1373 expbuf[0] = 0;
1374 nbra = 0;
1375 error(Q);
1376}
1377
1378execute(gf, addr)
1379int *addr;
1380{
1381 register char *p1, *p2, c;
1382
1383 for (c=0; c<NBRA; c++) {
1384 braslist[c] = 0;
1385 braelist[c] = 0;
1386 }
1387 if (gf) {
1388 if (circfl)
1389 return(0);
1390 p1 = linebuf;
1391 p2 = genbuf;
1392 while (*p1++ = *p2++)
1393 ;
1394 locs = p1 = loc2;
1395 } else {
1396 if (addr==zero)
1397 return(0);
1398 p1 = getline(*addr);
1399 locs = 0;
1400 }
1401 p2 = expbuf;
1402 if (circfl) {
1403 loc1 = p1;
1404 return(advance(p1, p2));
1405 }
1406 /* fast check for first character */
1407 if (*p2==CCHR) {
1408 c = p2[1];
1409 do {
1410 if (*p1!=c)
1411 continue;
1412 if (advance(p1, p2)) {
1413 loc1 = p1;
1414 return(1);
1415 }
1416 } while (*p1++);
1417 return(0);
1418 }
1419 /* regular algorithm */
1420 do {
1421 if (advance(p1, p2)) {
1422 loc1 = p1;
1423 return(1);
1424 }
1425 } while (*p1++);
1426 return(0);
1427}
1428
1429advance(lp, ep)
1430register char *ep, *lp;
1431{
1432 register char *curlp;
1433 int i;
1434
1435 for (;;) switch (*ep++) {
1436
1437 case CCHR:
1438 if (*ep++ == *lp++)
1439 continue;
1440 return(0);
1441
1442 case CDOT:
1443 if (*lp++)
1444 continue;
1445 return(0);
1446
1447 case CDOL:
1448 if (*lp==0)
1449 continue;
1450 return(0);
1451
1452 case CEOF:
1453 loc2 = lp;
1454 return(1);
1455
1456 case CCL:
1457 if (cclass(ep, *lp++, 1)) {
1458 ep += *ep;
1459 continue;
1460 }
1461 return(0);
1462
1463 case NCCL:
1464 if (cclass(ep, *lp++, 0)) {
1465 ep += *ep;
1466 continue;
1467 }
1468 return(0);
1469
1470 case CBRA:
1471 braslist[*ep++] = lp;
1472 continue;
1473
1474 case CKET:
1475 braelist[*ep++] = lp;
1476 continue;
1477
1478 case CBACK:
1479 if (braelist[i = *ep++]==0)
1480 error(Q);
1481 if (backref(i, lp)) {
1482 lp += braelist[i] - braslist[i];
1483 continue;
1484 }
1485 return(0);
1486
1487 case CBACK|STAR:
1488 if (braelist[i = *ep++] == 0)
1489 error(Q);
1490 curlp = lp;
1491 while (backref(i, lp))
1492 lp += braelist[i] - braslist[i];
1493 while (lp >= curlp) {
1494 if (advance(lp, ep))
1495 return(1);
1496 lp -= braelist[i] - braslist[i];
1497 }
1498 continue;
1499
1500 case CDOT|STAR:
1501 curlp = lp;
1502 while (*lp++)
1503 ;
1504 goto star;
1505
1506 case CCHR|STAR:
1507 curlp = lp;
1508 while (*lp++ == *ep)
1509 ;
1510 ep++;
1511 goto star;
1512
1513 case CCL|STAR:
1514 case NCCL|STAR:
1515 curlp = lp;
1516 while (cclass(ep, *lp++, ep[-1]==(CCL|STAR)))
1517 ;
1518 ep += *ep;
1519 goto star;
1520
1521 star:
1522 do {
1523 lp--;
1524 if (lp==locs)
1525 break;
1526 if (advance(lp, ep))
1527 return(1);
1528 } while (lp > curlp);
1529 return(0);
1530
1531 default:
1532 error(Q);
1533 }
1534}
1535
1536backref(i, lp)
1537register i;
1538register char *lp;
1539{
1540 register char *bp;
1541
1542 bp = braslist[i];
1543 while (*bp++ == *lp++)
1544 if (bp >= braelist[i])
1545 return(1);
1546 return(0);
1547}
1548
1549cclass(set, c, af)
1550register char *set, c;
1551{
1552 register n;
1553
1554 if (c==0)
1555 return(0);
1556 n = *set++;
1557 while (--n)
1558 if (*set++ == c)
1559 return(af);
1560 return(!af);
1561}
1562
1563putd()
1564{
1565 register r;
1566
1567 r = count%10;
1568 count /= 10;
1569 if (count)
1570 putd();
1571 putchr(r + '0');
1572}
1573
1574puts(sp)
1575register char *sp;
1576{
1577 col = 0;
1578 while (*sp)
1579 putchr(*sp++);
1580 putchr('\n');
1581}
1582
1583char line[70];
1584char *linp = line;
1585
1586putchr(ac)
1587{
1588 register char *lp;
1589 register c;
1590
1591 lp = linp;
1592 c = ac;
1593 if (listf) {
1594 col++;
1595 if (col >= 72) {
1596 col = 0;
1597 *lp++ = '\\';
1598 *lp++ = '\n';
1599 }
1600 if (c=='\t') {
1601 c = '>';
1602 goto esc;
1603 }
1604 if (c=='\b') {
1605 c = '<';
1606 esc:
1607 *lp++ = '-';
1608 *lp++ = '\b';
1609 *lp++ = c;
1610 goto out;
1611 }
1612 if (c<' ' && c!= '\n') {
1613 *lp++ = '\\';
1614 *lp++ = (c>>3)+'0';
1615 *lp++ = (c&07)+'0';
1616 col += 2;
1617 goto out;
1618 }
1619 }
1620 *lp++ = c;
1621out:
1622 if(c == '\n' || lp >= &line[64]) {
1623 linp = line;
1624 write(1, line, lp-line);
1625 return;
1626 }
1627 linp = lp;
1628}
1629crblock(permp, buf, nchar, startn)
1630char *permp;
1631char *buf;
1632long startn;
1633{
1634 register char *p1;
1635 int n1;
1636 int n2;
1637 register char *t1, *t2, *t3;
1638
1639 t1 = permp;
1640 t2 = &permp[256];
1641 t3 = &permp[512];
1642
1643 n1 = startn&0377;
1644 n2 = (startn>>8)&0377;
1645 p1 = buf;
1646 while(nchar--) {
1647 *p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1;
1648 n1++;
1649 if(n1==256){
1650 n1 = 0;
1651 n2++;
1652 if(n2==256) n2 = 0;
1653 }
1654 p1++;
1655 }
1656}
1657
1658getkey()
1659{
1660 struct sgttyb b;
1661 int save;
1662 int (*sig)();
1663 register char *p;
1664 register c;
1665
1666 sig = signal(SIGINT, SIG_IGN);
1667 if (gtty(0, &b) == -1)
1668 error("Input not tty");
1669 save = b.sg_flags;
1670 b.sg_flags &= ~ECHO;
1671 stty(0, &b);
1672 puts("Key:");
1673 p = key;
1674 while(((c=getchr()) != EOF) && (c!='\n')) {
1675 if(p < &key[KSIZE])
1676 *p++ = c;
1677 }
1678 *p = 0;
1679 b.sg_flags = save;
1680 stty(0, &b);
1681 signal(SIGINT, sig);
1682 return(key[0] != 0);
1683}
1684
1685/*
1686 * Besides initializing the encryption machine, this routine
1687 * returns 0 if the key is null, and 1 if it is non-null.
1688 */
1689crinit(keyp, permp)
1690char *keyp, *permp;
1691{
1692 register char *t1, *t2, *t3;
1693 register i;
1694 int ic, k, temp, pf[2];
1695 unsigned random;
1696 char buf[13];
1697 long seed;
1698
1699 t1 = permp;
1700 t2 = &permp[256];
1701 t3 = &permp[512];
1702 if(*keyp == 0)
1703 return(0);
1704 strncpy(buf, keyp, 8);
1705 while (*keyp)
1706 *keyp++ = '\0';
1707 buf[8] = buf[0];
1708 buf[9] = buf[1];
1709 if (pipe(pf)<0)
1710 pf[0] = pf[1] = -1;
1711 if (fork()==0) {
1712 close(0);
1713 close(1);
1714 dup(pf[0]);
1715 dup(pf[1]);
1716 execl("/usr/lib/makekey", "-", 0);
1717 execl("/lib/makekey", "-", 0);
1718 exit(1);
1719 }
1720 write(pf[1], buf, 10);
1721 if (wait((int *)NULL)==-1 || read(pf[0], buf, 13)!=13)
1722 error("crypt: cannot generate key");
1723 close(pf[0]);
1724 close(pf[1]);
1725 seed = 123;
1726 for (i=0; i<13; i++)
1727 seed = seed*buf[i] + i;
1728 for(i=0;i<256;i++){
1729 t1[i] = i;
1730 t3[i] = 0;
1731 }
1732 for(i=0; i<256; i++) {
1733 seed = 5*seed + buf[i%13];
1734 random = seed % 65521;
1735 k = 256-1 - i;
1736 ic = (random&0377) % (k+1);
1737 random >>= 8;
1738 temp = t1[k];
1739 t1[k] = t1[ic];
1740 t1[ic] = temp;
1741 if(t3[k]!=0) continue;
1742 ic = (random&0377) % k;
1743 while(t3[ic]!=0) ic = (ic+1) % k;
1744 t3[k] = ic;
1745 t3[ic] = k;
1746 }
1747 for(i=0; i<256; i++)
1748 t2[t1[i]&0377] = i;
1749 return(1);
1750}
1751
1752makekey(a, b)
1753char *a, *b;
1754{
1755 register int i;
1756 long t;
1757 char temp[KSIZE + 1];
1758
1759 for(i = 0; i < KSIZE; i++)
1760 temp[i] = *a++;
1761 time(&t);
1762 t += getpid();
1763 for(i = 0; i < 4; i++)
1764 temp[i] ^= (t>>(8*i))&0377;
1765 crinit(temp, b);
1766}