|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid = "@(#)ex_temp.c 7.5 (Berkeley) 6/7/85";
9: #endif not lint
10:
11: #include "ex.h"
12: #include "ex_temp.h"
13: #include "ex_vis.h"
14: #include "ex_tty.h"
15:
16: /*
17: * Editor temporary file routines.
18: * Very similar to those of ed, except uses 2 input buffers.
19: */
20: #define READ 0
21: #define WRITE 1
22:
23: char tfname[40];
24: char rfname[40];
25: int havetmp;
26: short tfile = -1;
27: short rfile = -1;
28:
29: fileinit()
30: {
31: register char *p;
32: register int i, j;
33: struct stat stbuf;
34:
35: if (tline == INCRMT * (HBLKS+2))
36: return;
37: cleanup(0);
38: close(tfile);
39: tline = INCRMT * (HBLKS+2);
40: blocks[0] = HBLKS;
41: blocks[1] = HBLKS+1;
42: blocks[2] = -1;
43: dirtcnt = 0;
44: iblock = -1;
45: iblock2 = -1;
46: oblock = -1;
47: CP(tfname, svalue(DIRECTORY));
48: if (stat(tfname, &stbuf)) {
49: dumbness:
50: if (setexit() == 0)
51: filioerr(tfname);
52: else
53: putNFL();
54: cleanup(1);
55: exit(1);
56: }
57: if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
58: errno = ENOTDIR;
59: goto dumbness;
60: }
61: ichanged = 0;
62: ichang2 = 0;
63: ignore(strcat(tfname, "/ExXXXXX"));
64: for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
65: *--p = j % 10 | '0';
66: tfile = creat(tfname, 0600);
67: if (tfile < 0)
68: goto dumbness;
69: #ifdef VMUNIX
70: {
71: extern stilinc; /* see below */
72: stilinc = 0;
73: }
74: #endif
75: havetmp = 1;
76: close(tfile);
77: tfile = open(tfname, 2);
78: if (tfile < 0)
79: goto dumbness;
80: /* brk((char *)fendcore); */
81: }
82:
83: cleanup(all)
84: bool all;
85: {
86: if (all) {
87: putpad(TE);
88: flush();
89: }
90: if (havetmp)
91: unlink(tfname);
92: havetmp = 0;
93: if (all && rfile >= 0) {
94: unlink(rfname);
95: close(rfile);
96: rfile = -1;
97: }
98: }
99:
100: getline(tl)
101: line tl;
102: {
103: register char *bp, *lp;
104: register int nl;
105:
106: lp = linebuf;
107: bp = getblock(tl, READ);
108: nl = nleft;
109: tl &= ~OFFMSK;
110: while (*lp++ = *bp++)
111: if (--nl == 0) {
112: bp = getblock(tl += INCRMT, READ);
113: nl = nleft;
114: }
115: }
116:
117: putline()
118: {
119: register char *bp, *lp;
120: register int nl;
121: line tl;
122:
123: dirtcnt++;
124: lp = linebuf;
125: change();
126: tl = tline;
127: bp = getblock(tl, WRITE);
128: nl = nleft;
129: tl &= ~OFFMSK;
130: while (*bp = *lp++) {
131: if (*bp++ == '\n') {
132: *--bp = 0;
133: linebp = lp;
134: break;
135: }
136: if (--nl == 0) {
137: bp = getblock(tl += INCRMT, WRITE);
138: nl = nleft;
139: }
140: }
141: tl = tline;
142: tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
143: return (tl);
144: }
145:
146: int read();
147: int write();
148:
149: char *
150: getblock(atl, iof)
151: line atl;
152: int iof;
153: {
154: register int bno, off;
155: register char *p1, *p2;
156: register int n;
157:
158: bno = (atl >> OFFBTS) & BLKMSK;
159: off = (atl << SHFT) & LBTMSK;
160: if (bno >= NMBLKS)
161: error(" Tmp file too large");
162: nleft = BUFSIZ - off;
163: if (bno == iblock) {
164: ichanged |= iof;
165: hitin2 = 0;
166: return (ibuff + off);
167: }
168: if (bno == iblock2) {
169: ichang2 |= iof;
170: hitin2 = 1;
171: return (ibuff2 + off);
172: }
173: if (bno == oblock)
174: return (obuff + off);
175: if (iof == READ) {
176: if (hitin2 == 0) {
177: if (ichang2) {
178: #ifdef CRYPT
179: if(xtflag)
180: crblock(tperm, ibuff2, CRSIZE, (long)0);
181: #endif
182: blkio(iblock2, ibuff2, write);
183: }
184: ichang2 = 0;
185: iblock2 = bno;
186: blkio(bno, ibuff2, read);
187: #ifdef CRYPT
188: if(xtflag)
189: crblock(tperm, ibuff2, CRSIZE, (long)0);
190: #endif
191: hitin2 = 1;
192: return (ibuff2 + off);
193: }
194: hitin2 = 0;
195: if (ichanged) {
196: #ifdef CRYPT
197: if(xtflag)
198: crblock(tperm, ibuff, CRSIZE, (long)0);
199: #endif
200: blkio(iblock, ibuff, write);
201: }
202: ichanged = 0;
203: iblock = bno;
204: blkio(bno, ibuff, read);
205: #ifdef CRYPT
206: if(xtflag)
207: crblock(tperm, ibuff, CRSIZE, (long)0);
208: #endif
209: return (ibuff + off);
210: }
211: if (oblock >= 0) {
212: #ifdef CRYPT
213: if(xtflag) {
214: /*
215: * Encrypt block before writing, so some devious
216: * person can't look at temp file while editing.
217: */
218: p1 = obuff;
219: p2 = crbuf;
220: n = CRSIZE;
221: while(n--)
222: *p2++ = *p1++;
223: crblock(tperm, crbuf, CRSIZE, (long)0);
224: blkio(oblock, crbuf, write);
225: } else
226: #endif
227: blkio(oblock, obuff, write);
228: }
229: oblock = bno;
230: return (obuff + off);
231: }
232:
233: #ifdef VMUNIX
234: #define INCORB 64
235: char incorb[INCORB+1][BUFSIZ];
236: #define pagrnd(a) ((char *)(((int)a)&~(BUFSIZ-1)))
237: int stilinc; /* up to here not written yet */
238: #endif
239:
240: blkio(b, buf, iofcn)
241: short b;
242: char *buf;
243: int (*iofcn)();
244: {
245:
246: #ifdef VMUNIX
247: if (b < INCORB) {
248: if (iofcn == read) {
249: bcopy(pagrnd(incorb[b+1]), buf, BUFSIZ);
250: return;
251: }
252: bcopy(buf, pagrnd(incorb[b+1]), BUFSIZ);
253: if (laste) {
254: if (b >= stilinc)
255: stilinc = b + 1;
256: return;
257: }
258: } else if (stilinc)
259: tflush();
260: #endif
261: lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
262: if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
263: filioerr(tfname);
264: }
265:
266: #ifdef VMUNIX
267: tlaste()
268: {
269:
270: if (stilinc)
271: dirtcnt = 0;
272: }
273:
274: tflush()
275: {
276: int i = stilinc;
277:
278: stilinc = 0;
279: lseek(tfile, (long) 0, 0);
280: if (write(tfile, pagrnd(incorb[1]), i * BUFSIZ) != (i * BUFSIZ))
281: filioerr(tfname);
282: }
283: #endif
284:
285: /*
286: * Synchronize the state of the temporary file in case
287: * a crash occurs.
288: */
289: synctmp()
290: {
291: register int cnt;
292: register line *a;
293: register short *bp;
294:
295: #ifdef VMUNIX
296: if (stilinc)
297: return;
298: #endif
299: if (dol == zero)
300: return;
301: if (ichanged)
302: blkio(iblock, ibuff, write);
303: ichanged = 0;
304: if (ichang2)
305: blkio(iblock2, ibuff2, write);
306: ichang2 = 0;
307: if (oblock != -1)
308: blkio(oblock, obuff, write);
309: time(&H.Time);
310: uid = getuid();
311: *zero = (line) H.Time;
312: for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
313: if (*bp < 0) {
314: tline = (tline + OFFMSK) &~ OFFMSK;
315: *bp = ((tline >> OFFBTS) & BLKMSK);
316: if (*bp > NMBLKS)
317: error(" Tmp file too large");
318: tline += INCRMT;
319: oblock = *bp + 1;
320: bp[1] = -1;
321: }
322: lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
323: cnt = ((dol - a) + 2) * sizeof (line);
324: if (cnt > BUFSIZ)
325: cnt = BUFSIZ;
326: if (write(tfile, (char *) a, cnt) != cnt) {
327: oops:
328: *zero = 0;
329: filioerr(tfname);
330: }
331: *zero = 0;
332: }
333: flines = lineDOL();
334: lseek(tfile, 0l, 0);
335: if (write(tfile, (char *) &H, sizeof H) != sizeof H)
336: goto oops;
337: #ifdef notdef
338: /*
339: * This will insure that exrecover gets as much
340: * back after a crash as is absolutely possible,
341: * but can result in pregnant pauses between commands
342: * when the TSYNC call is made, so...
343: */
344: (void) fsync(tfile);
345: #endif
346: }
347:
348: TSYNC()
349: {
350:
351: if (dirtcnt > MAXDIRT) { /* mjm: 12 --> MAXDIRT */
352: #ifdef VMUNIX
353: if (stilinc)
354: tflush();
355: #endif
356: dirtcnt = 0;
357: synctmp();
358: }
359: }
360:
361: /*
362: * Named buffer routines.
363: * These are implemented differently than the main buffer.
364: * Each named buffer has a chain of blocks in the register file.
365: * Each block contains roughly 508 chars of text,
366: * and a previous and next block number. We also have information
367: * about which blocks came from deletes of multiple partial lines,
368: * e.g. deleting a sentence or a LISP object.
369: *
370: * We maintain a free map for the temp file. To free the blocks
371: * in a register we must read the blocks to find how they are chained
372: * together.
373: *
374: * BUG: The default savind of deleted lines in numbered
375: * buffers may be rather inefficient; it hasn't been profiled.
376: */
377: struct strreg {
378: short rg_flags;
379: short rg_nleft;
380: short rg_first;
381: short rg_last;
382: } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
383:
384: struct rbuf {
385: short rb_prev;
386: short rb_next;
387: char rb_text[BUFSIZ - 2 * sizeof (short)];
388: } *rbuf, KILLrbuf, putrbuf, YANKrbuf, regrbuf;
389: #ifdef VMUNIX
390: short rused[256];
391: #else
392: short rused[32];
393: #endif
394: short rnleft;
395: short rblock;
396: short rnext;
397: char *rbufcp;
398:
399: regio(b, iofcn)
400: short b;
401: int (*iofcn)();
402: {
403:
404: if (rfile == -1) {
405: CP(rfname, tfname);
406: *(strend(rfname) - 7) = 'R';
407: rfile = creat(rfname, 0600);
408: if (rfile < 0)
409: oops:
410: filioerr(rfname);
411: close(rfile);
412: rfile = open(rfname, 2);
413: if (rfile < 0)
414: goto oops;
415: }
416: lseek(rfile, (long) b * BUFSIZ, 0);
417: if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
418: goto oops;
419: rblock = b;
420: }
421:
422: REGblk()
423: {
424: register int i, j, m;
425:
426: for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
427: m = (rused[i] ^ 0177777) & 0177777;
428: if (i == 0)
429: m &= ~1;
430: if (m != 0) {
431: j = 0;
432: while ((m & 1) == 0)
433: j++, m >>= 1;
434: rused[i] |= (1 << j);
435: #ifdef RDEBUG
436: printf("allocating block %d\n", i * 16 + j);
437: #endif
438: return (i * 16 + j);
439: }
440: }
441: error("Out of register space (ugh)");
442: /*NOTREACHED*/
443: }
444:
445: struct strreg *
446: mapreg(c)
447: register int c;
448: {
449:
450: if (isupper(c))
451: c = tolower(c);
452: return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
453: }
454:
455: int shread();
456:
457: KILLreg(c)
458: register int c;
459: {
460: register struct strreg *sp;
461:
462: rbuf = &KILLrbuf;
463: sp = mapreg(c);
464: rblock = sp->rg_first;
465: sp->rg_first = sp->rg_last = 0;
466: sp->rg_flags = sp->rg_nleft = 0;
467: while (rblock != 0) {
468: #ifdef RDEBUG
469: printf("freeing block %d\n", rblock);
470: #endif
471: rused[rblock / 16] &= ~(1 << (rblock % 16));
472: regio(rblock, shread);
473: rblock = rbuf->rb_next;
474: }
475: }
476:
477: /*VARARGS*/
478: shread()
479: {
480: struct front { short a; short b; };
481:
482: if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
483: return (sizeof (struct rbuf));
484: return (0);
485: }
486:
487: int getREG();
488:
489: putreg(c)
490: char c;
491: {
492: register line *odot = dot;
493: register line *odol = dol;
494: register int cnt;
495:
496: deletenone();
497: appendnone();
498: rbuf = &putrbuf;
499: rnleft = 0;
500: rblock = 0;
501: rnext = mapreg(c)->rg_first;
502: if (rnext == 0) {
503: if (inopen) {
504: splitw++;
505: vclean();
506: vgoto(WECHO, 0);
507: }
508: vreg = -1;
509: error("Nothing in register %c", c);
510: }
511: if (inopen && partreg(c)) {
512: if (!FIXUNDO) {
513: splitw++; vclean(); vgoto(WECHO, 0); vreg = -1;
514: error("Can't put partial line inside macro");
515: }
516: squish();
517: addr1 = addr2 = dol;
518: }
519: cnt = append(getREG, addr2);
520: if (inopen && partreg(c)) {
521: unddol = dol;
522: dol = odol;
523: dot = odot;
524: pragged(0);
525: }
526: killcnt(cnt);
527: notecnt = cnt;
528: }
529:
530: partreg(c)
531: char c;
532: {
533:
534: return (mapreg(c)->rg_flags);
535: }
536:
537: notpart(c)
538: register int c;
539: {
540:
541: if (c)
542: mapreg(c)->rg_flags = 0;
543: }
544:
545: getREG()
546: {
547: register char *lp = linebuf;
548: register int c;
549:
550: for (;;) {
551: if (rnleft == 0) {
552: if (rnext == 0)
553: return (EOF);
554: regio(rnext, read);
555: rnext = rbuf->rb_next;
556: rbufcp = rbuf->rb_text;
557: rnleft = sizeof rbuf->rb_text;
558: }
559: c = *rbufcp;
560: if (c == 0)
561: return (EOF);
562: rbufcp++, --rnleft;
563: if (c == '\n') {
564: *lp++ = 0;
565: return (0);
566: }
567: *lp++ = c;
568: }
569: }
570:
571: YANKreg(c)
572: register int c;
573: {
574: register line *addr;
575: register struct strreg *sp;
576: char savelb[LBSIZE];
577:
578: if (isdigit(c))
579: kshift();
580: if (islower(c))
581: KILLreg(c);
582: strp = sp = mapreg(c);
583: sp->rg_flags = inopen && cursor && wcursor;
584: rbuf = &YANKrbuf;
585: if (sp->rg_last) {
586: regio(sp->rg_last, read);
587: rnleft = sp->rg_nleft;
588: rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
589: } else {
590: rblock = 0;
591: rnleft = 0;
592: }
593: CP(savelb,linebuf);
594: for (addr = addr1; addr <= addr2; addr++) {
595: getline(*addr);
596: if (sp->rg_flags) {
597: if (addr == addr2)
598: *wcursor = 0;
599: if (addr == addr1)
600: strcpy(linebuf, cursor);
601: }
602: YANKline();
603: }
604: rbflush();
605: killed();
606: CP(linebuf,savelb);
607: }
608:
609: kshift()
610: {
611: register int i;
612:
613: KILLreg('9');
614: for (i = '8'; i >= '0'; i--)
615: copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
616: }
617:
618: YANKline()
619: {
620: register char *lp = linebuf;
621: register struct rbuf *rp = rbuf;
622: register int c;
623:
624: do {
625: c = *lp++;
626: if (c == 0)
627: c = '\n';
628: if (rnleft == 0) {
629: rp->rb_next = REGblk();
630: rbflush();
631: rblock = rp->rb_next;
632: rp->rb_next = 0;
633: rp->rb_prev = rblock;
634: rnleft = sizeof rp->rb_text;
635: rbufcp = rp->rb_text;
636: }
637: *rbufcp++ = c;
638: --rnleft;
639: } while (c != '\n');
640: if (rnleft)
641: *rbufcp = 0;
642: }
643:
644: rbflush()
645: {
646: register struct strreg *sp = strp;
647:
648: if (rblock == 0)
649: return;
650: regio(rblock, write);
651: if (sp->rg_first == 0)
652: sp->rg_first = rblock;
653: sp->rg_last = rblock;
654: sp->rg_nleft = rnleft;
655: }
656:
657: /* Register c to char buffer buf of size buflen */
658: regbuf(c, buf, buflen)
659: char c;
660: char *buf;
661: int buflen;
662: {
663: register char *p, *lp;
664:
665: rbuf = ®rbuf;
666: rnleft = 0;
667: rblock = 0;
668: rnext = mapreg(c)->rg_first;
669: if (rnext==0) {
670: *buf = 0;
671: error("Nothing in register %c",c);
672: }
673: p = buf;
674: while (getREG()==0) {
675: for (lp=linebuf; *lp;) {
676: if (p >= &buf[buflen])
677: error("Register too long@to fit in memory");
678: *p++ = *lp++;
679: }
680: *p++ = '\n';
681: }
682: if (partreg(c)) p--;
683: *p = '\0';
684: getDOT();
685: }
686:
687: /*
688: * Encryption routines. These are essentially unmodified from ed.
689: */
690:
691: #ifdef CRYPT
692: /*
693: * crblock: encrypt/decrypt a block of text.
694: * buf is the buffer through which the text is both input and
695: * output. nchar is the size of the buffer. permp is a work
696: * buffer, and startn is the beginning of a sequence.
697: */
698: crblock(permp, buf, nchar, startn)
699: char *permp;
700: char *buf;
701: int nchar;
702: long startn;
703: {
704: register char *p1;
705: int n1;
706: int n2;
707: register char *t1, *t2, *t3;
708:
709: t1 = permp;
710: t2 = &permp[256];
711: t3 = &permp[512];
712:
713: n1 = startn&0377;
714: n2 = (startn>>8)&0377;
715: p1 = buf;
716: while(nchar--) {
717: *p1 = t2[(t3[(t1[(*p1+n1)&0377]+n2)&0377]-n2)&0377]-n1;
718: n1++;
719: if(n1==256){
720: n1 = 0;
721: n2++;
722: if(n2==256) n2 = 0;
723: }
724: p1++;
725: }
726: }
727:
728: /*
729: * makekey: initialize buffers based on user key a.
730: */
731: makekey(a, b)
732: char *a, *b;
733: {
734: register int i;
735: long t;
736: char temp[KSIZE + 1];
737:
738: for(i = 0; i < KSIZE; i++)
739: temp[i] = *a++;
740: time(&t);
741: t += getpid();
742: for(i = 0; i < 4; i++)
743: temp[i] ^= (t>>(8*i))&0377;
744: crinit(temp, b);
745: }
746:
747: /*
748: * crinit: besides initializing the encryption machine, this routine
749: * returns 0 if the key is null, and 1 if it is non-null.
750: */
751: crinit(keyp, permp)
752: char *keyp, *permp;
753: {
754: register char *t1, *t2, *t3;
755: register i;
756: int ic, k, temp;
757: unsigned random;
758: char buf[13];
759: long seed;
760:
761: t1 = permp;
762: t2 = &permp[256];
763: t3 = &permp[512];
764: if(*keyp == 0)
765: return(0);
766: strncpy(buf, keyp, 8);
767: while (*keyp)
768: *keyp++ = '\0';
769:
770: buf[8] = buf[0];
771: buf[9] = buf[1];
772: domakekey(buf);
773:
774: seed = 123;
775: for (i=0; i<13; i++)
776: seed = seed*buf[i] + i;
777: for(i=0;i<256;i++){
778: t1[i] = i;
779: t3[i] = 0;
780: }
781: for(i=0; i<256; i++) {
782: seed = 5*seed + buf[i%13];
783: random = seed % 65521;
784: k = 256-1 - i;
785: ic = (random&0377) % (k+1);
786: random >>= 8;
787: temp = t1[k];
788: t1[k] = t1[ic];
789: t1[ic] = temp;
790: if(t3[k]!=0) continue;
791: ic = (random&0377) % k;
792: while(t3[ic]!=0) ic = (ic+1) % k;
793: t3[k] = ic;
794: t3[ic] = k;
795: }
796: for(i=0; i<256; i++)
797: t2[t1[i]&0377] = i;
798: return(1);
799: }
800:
801: /*
802: * domakekey: the following is the major nonportable part of the encryption
803: * mechanism. A 10 character key is supplied in buffer.
804: * This string is fed to makekey (an external program) which
805: * responds with a 13 character result. This result is placed
806: * in buffer.
807: */
808: domakekey(buffer)
809: char *buffer;
810: {
811: int pf[2];
812:
813: if (pipe(pf)<0)
814: pf[0] = pf[1] = -1;
815: if (fork()==0) {
816: close(0);
817: close(1);
818: dup(pf[0]);
819: dup(pf[1]);
820: execl("/usr/lib/makekey", "-", 0);
821: execl("/lib/makekey", "-", 0);
822: exit(1);
823: }
824: write(pf[1], buffer, 10);
825: if (wait((int *)NULL)==-1 || read(pf[0], buffer, 13)!=13)
826: error("crypt: cannot generate key");
827: close(pf[0]);
828: close(pf[1]);
829: /* end of nonportable part */
830: }
831: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.