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