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