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