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