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