4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /* Copyright (c) 1981 Regents of the University of California */
39 * Editor temporary file routines.
40 * Very similar to those of ed, except uses 2 input buffers.
45 unsigned char tfname
[PATH_MAX
+1];
46 static unsigned char rfname
[PATH_MAX
+1];
47 static unsigned char tempname
[PATH_MAX
+1];
50 static short rfile
= -1;
62 if (tline
== INCRMT
* (HBLKS
+2))
67 tline
= INCRMT
* (HBLKS
+2);
75 if (strlen(svalue(vi_DIRECTORY
)) > (PATH_MAX
-13))
76 error(gettext("User set directory too long"));
77 CP(tfname
, svalue(vi_DIRECTORY
));
78 if (stat64((char *)tfname
, &stbuf
)) {
94 (void) strcat(tfname
, "/ExXXXXXX");
95 if ((tfile
= mkstemp((char *)tfname
)) < 0)
99 extern int stilinc
; /* see below */
104 /* brk((unsigned char *)fendcore); */
116 putpad((unsigned char *)exit_ca_mode
);
118 if (ioctl(2, TIOCGPGRP
, &pgrp
) == 0) {
119 if (pgrp
== getpgid(0)) {
121 if (envlines
!= -1 || envcolumns
!= -1) {
123 jwin
.ws_row
= oldlines
;
124 jwin
.ws_col
= oldcolumns
;
125 ioctl(0, TIOCSWINSZ
, &jwin
);
133 if (envlines
!= -1 || envcolumns
!= -1) {
135 jwin
.ws_row
= oldlines
;
136 jwin
.ws_col
= oldcolumns
;
137 ioctl(0, TIOCSWINSZ
, &jwin
);
145 unlink((char *)tfname
);
147 if (all
&& rfile
>= 0) {
148 unlink((char *)rfname
);
159 unsigned char *bp
, *lp
;
163 bp
= getblock(tl
, READ
);
166 while (*lp
++ = *bp
++)
168 bp
= getblock(tl
+= INCRMT
, READ
);
176 unsigned char *bp
, *lp
;
185 bp
= getblock(tl
, WRITE
);
188 while (*bp
= *lp
++) {
194 } else if (junk(*bp
++)) {
199 bp
= getblock(tl
+= INCRMT
, WRITE
);
204 tline
+= (((lp
- linebuf
) + BNDRY
- 1) >> SHFT
) & 077776;
212 getblock(line atl
, int iof
)
215 unsigned char *p1
, *p2
;
219 bno
= (atl
>> OFFBTS
) & BLKMSK
;
220 off
= (atl
<< SHFT
) & LBTMSK
;
223 * When we overflow tmpfile buffers,
224 * throw away line which could not be
227 for (tmpptr
= dot
; tmpptr
< unddol
; tmpptr
++)
228 *tmpptr
= *(tmpptr
+1);
233 error(gettext(" Tmp file too large"));
235 nleft
= BUFSIZE
- off
;
239 return (ibuff
+ off
);
241 if (bno
== iblock2
) {
244 return (ibuff2
+ off
);
247 return (obuff
+ off
);
252 if (run_crypt(0L, ibuff2
,
253 CRSIZE
, tperm
) == -1) {
257 blkio(iblock2
, ibuff2
, write
);
261 blkio(bno
, ibuff2
, read
);
263 if (run_crypt(0L, ibuff2
, CRSIZE
, tperm
) == -1)
266 return (ibuff2
+ off
);
271 if (run_crypt(0L, ibuff
, CRSIZE
, tperm
) == -1)
273 blkio(iblock
, ibuff
, write
);
277 blkio(bno
, ibuff
, read
);
279 if (run_crypt(0L, ibuff
, CRSIZE
, tperm
) == -1)
281 return (ibuff
+ off
);
286 * Encrypt block before writing, so some devious
287 * person can't look at temp file while editing.
294 if (run_crypt(0L, crbuf
, CRSIZE
, tperm
) == -1)
296 blkio(oblock
, crbuf
, write
);
298 blkio(oblock
, obuff
, write
);
301 return (obuff
+ off
);
306 unsigned char incorb
[INCORB
+1][BUFSIZE
];
307 #define pagrnd(a) ((unsigned char *)(((int)a)&~(BUFSIZE-1)))
308 int stilinc
; /* up to here not written yet */
312 blkio(short b
, unsigned char *buf
, int (*iofcn
)())
318 bcopy(pagrnd(incorb
[b
+1]), buf
, BUFSIZE
);
321 bcopy(buf
, pagrnd(incorb
[b
+1]), BUFSIZE
);
330 lseek(tfile
, (long)(unsigned)b
* BUFSIZE
, 0);
331 if ((*iofcn
)(tfile
, buf
, BUFSIZE
) != BUFSIZE
)
350 lseek(tfile
, (long)0, 0);
351 if (write(tfile
, pagrnd(incorb
[1]), i
* BUFSIZE
) != (i
* BUFSIZE
))
357 * Synchronize the state of the temporary file in case
366 unsigned char *p1
, *p2
;
376 * In theory, we need to encrypt iblock and iblock2 before writing
377 * them out, as well as oblock, but in practice ichanged and ichang2
378 * can never be set, so this isn't really needed. Likewise, the
379 * code in getblock above for iblock+iblock2 isn't needed.
382 blkio(iblock
, ibuff
, write
);
385 blkio(iblock2
, ibuff2
, write
);
390 * Encrypt block before writing, so some devious
391 * person can't look at temp file while editing.
398 if (run_crypt(0L, crbuf
, CRSIZE
, tperm
) == -1)
400 blkio(oblock
, crbuf
, write
);
402 blkio(oblock
, obuff
, write
);
409 *zero
= (line
) H
.Time
;
410 for (a
= zero
, bp
= blocks
; a
<= dol
;
411 a
+= BUFSIZE
/ sizeof (*a
), bp
++) {
412 if (bp
>= &H
.Blocks
[LBLKS
-1])
414 "file too large to recover with -r option"));
416 tline
= (tline
+ OFFMSK
) &~ OFFMSK
;
417 *bp
= ((tline
>> OFFBTS
) & BLKMSK
);
419 error(gettext(" Tmp file too large"));
424 lseek(tfile
, (long)(unsigned)*bp
* BUFSIZE
, 0);
425 cnt
= ((dol
- a
) + 2) * sizeof (line
);
428 if (write(tfile
, (char *)a
, cnt
) != cnt
) {
437 if (write(tfile
, (char *)&H
, sizeof (H
)) != sizeof (H
))
445 if (dirtcnt
> MAXDIRT
) {
456 * Named buffer routines.
457 * These are implemented differently than the main buffer.
458 * Each named buffer has a chain of blocks in the register file.
459 * Each block contains roughly 508 chars of text,
460 * and a previous and next block number. We also have information
461 * about which blocks came from deletes of multiple partial lines,
462 * e.g. deleting a sentence or a LISP object.
464 * We maintain a free map for the temp file. To free the blocks
465 * in a register we must read the blocks to find how they are chained
468 * BUG: The default savind of deleted lines in numbered
469 * buffers may be rather inefficient; it hasn't been profiled.
476 } strregs
[('z'-'a'+1) + ('9'-'0'+1)], *strp
;
481 unsigned char rb_text
[BUFSIZE
- 2 * sizeof (short)];
482 } *rbuf
, KILLrbuf
, putrbuf
, YANKrbuf
, regrbuf
;
491 unsigned char *rbufcp
;
494 regio(short b
, int (*iofcn
)())
498 CP(rfname
, tempname
);
499 (void) strcat(rfname
, "/RxXXXXXX");
500 if ((rfile
= mkstemp((char *)rfname
)) < 0)
503 lseek(rfile
, (long)b
* BUFSIZE
, 0);
504 if ((*iofcn
)(rfile
, rbuf
, BUFSIZE
) != BUFSIZE
)
514 for (i
= 0; i
< sizeof (rused
) / sizeof (rused
[0]); i
++) {
515 m
= (rused
[i
] ^ 0177777) & 0177777;
522 rused
[i
] |= (1 << j
);
524 viprintf("allocating block %d\n", i
* 16 + j
);
529 error(gettext("Out of register space (ugh)"));
540 return (isdigit(c
) ? &strregs
[('z'-'a'+1)+(c
-'0')] : &strregs
[c
-'a']);
552 rblock
= sp
->rg_first
;
553 sp
->rg_first
= sp
->rg_last
= 0;
554 sp
->rg_flags
= sp
->rg_nleft
= 0;
555 while (rblock
!= 0) {
557 viprintf("freeing block %d\n", rblock
);
559 rused
[rblock
/ 16] &= ~(1 << (rblock
% 16));
560 regio(rblock
, shread
);
561 rblock
= rbuf
->rb_next
;
569 struct front
{ short a
; short b
; };
571 if (read(rfile
, (char *)rbuf
, sizeof (struct front
)) ==
572 sizeof (struct front
))
573 return (sizeof (struct rbuf
));
580 putreg(unsigned char c
)
591 rnext
= mapreg(c
)->rg_first
;
599 error(gettext("Nothing in register %c"), c
);
601 if (inopen
&& partreg(c
)) {
603 splitw
++; vclean(); vgoto(WECHO
, 0); vreg
= -1;
604 error(gettext("Can't put partial line inside macro"));
609 cnt
= append(getREG
, addr2
);
610 if (inopen
&& partreg(c
)) {
622 partreg(unsigned char c
)
625 return (mapreg(c
)->rg_flags
);
633 mapreg(c
)->rg_flags
= 0;
639 unsigned char *lp
= linebuf
;
647 rnext
= rbuf
->rb_next
;
648 rbufcp
= rbuf
->rb_text
;
649 rnleft
= sizeof (rbuf
->rb_text
);
668 unsigned char savelb
[LBSIZE
];
674 strp
= sp
= mapreg(c
);
675 sp
->rg_flags
= inopen
&& cursor
&& wcursor
;
678 regio(sp
->rg_last
, read
);
679 rnleft
= sp
->rg_nleft
;
680 rbufcp
= &rbuf
->rb_text
[sizeof (rbuf
->rb_text
) - rnleft
];
686 for (addr
= addr1
; addr
<= addr2
; addr
++) {
692 strcpy(linebuf
, cursor
);
708 for (i
= '8'; i
>= '0'; i
--)
709 copy(mapreg(i
+1), mapreg(i
), sizeof (struct strreg
));
715 unsigned char *lp
= linebuf
;
716 struct rbuf
*rp
= rbuf
;
724 rp
->rb_next
= REGblk();
726 rblock
= rp
->rb_next
;
728 rp
->rb_prev
= rblock
;
729 rnleft
= sizeof (rp
->rb_text
);
730 rbufcp
= rp
->rb_text
;
742 struct strreg
*sp
= strp
;
746 regio(rblock
, write
);
747 if (sp
->rg_first
== 0)
748 sp
->rg_first
= rblock
;
749 sp
->rg_last
= rblock
;
750 sp
->rg_nleft
= rnleft
;
753 /* Register c to char buffer buf of size buflen */
755 regbuf(unsigned char c
, unsigned char *buf
, int buflen
)
757 unsigned char *p
, *lp
;
762 rnext
= mapreg(c
)->rg_first
;
765 error(gettext("Nothing in register %c"), c
);
768 while (getREG() == 0) {
771 if (p
>= &buf
[buflen
])
772 error(value(vi_TERSE
) ?
773 gettext("Register too long") : gettext("Register too long to fit in memory"));
786 * Test code for displaying named registers.
793 viprintf("\nRegister Contents\n");
794 viprintf("======== ========\n");
795 for (k
= 'a'; k
<= 'z'; k
++) {
799 rnext
= mapreg(k
)->rg_first
;
802 viprintf("\t\tNothing in register.\n");
803 while (getREG() == 0) {
804 viprintf("\t\t%s\n", linebuf
);
811 * Test code for displaying numbered registers.
818 viprintf("\nRegister Contents\n");
819 viprintf("======== ========\n");
820 for (k
= '1'; k
<= '9'; k
++) {
824 rnext
= mapreg(k
)->rg_first
;
827 viprintf("\t\tNothing in register.\n");
828 while (getREG() == 0) {
829 viprintf("\t\t%s\n", linebuf
);