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