xref: /freebsd/bin/ed/buf.c (revision 46be34b90213ebd9037cb2c24aec0009d7f2f5c1)
146be34b9SKris Kennaway /* buf.c: This file contains the scratch-file buffer routines for the
230154ac8SAndrew Moore    ed line editor. */
330154ac8SAndrew Moore /*-
495e6217eSAndrew Moore  * Copyright (c) 1993 Andrew Moore, Talke Studio.
530154ac8SAndrew Moore  * All rights reserved.
630154ac8SAndrew Moore  *
730154ac8SAndrew Moore  * Redistribution and use in source and binary forms, with or without
830154ac8SAndrew Moore  * modification, are permitted provided that the following conditions
930154ac8SAndrew Moore  * are met:
1030154ac8SAndrew Moore  * 1. Redistributions of source code must retain the above copyright
1130154ac8SAndrew Moore  *    notice, this list of conditions and the following disclaimer.
1230154ac8SAndrew Moore  * 2. Redistributions in binary form must reproduce the above copyright
1330154ac8SAndrew Moore  *    notice, this list of conditions and the following disclaimer in the
1430154ac8SAndrew Moore  *    documentation and/or other materials provided with the distribution.
1530154ac8SAndrew Moore  *
1695e6217eSAndrew Moore  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1730154ac8SAndrew Moore  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1830154ac8SAndrew Moore  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1995e6217eSAndrew Moore  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2030154ac8SAndrew Moore  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2130154ac8SAndrew Moore  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2230154ac8SAndrew Moore  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2330154ac8SAndrew Moore  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2430154ac8SAndrew Moore  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2530154ac8SAndrew Moore  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2630154ac8SAndrew Moore  * SUCH DAMAGE.
2730154ac8SAndrew Moore  */
285967604aSSteve Price 
2930154ac8SAndrew Moore #ifndef lint
305967604aSSteve Price #if 0
3178b09ffeSSteve Price static char * const rcsid = "@(#)buf.c,v 1.4 1994/02/01 00:34:35 alm Exp";
325967604aSSteve Price #else
335967604aSSteve Price static char * const rcsid =
3446be34b9SKris Kennaway 	"$Id: buf.c,v 1.15 1997/12/31 12:25:33 helbig Exp $";
355967604aSSteve Price #endif
3630154ac8SAndrew Moore #endif /* not lint */
3730154ac8SAndrew Moore 
3830154ac8SAndrew Moore #include <sys/file.h>
39d165d4acSAndrew Moore #include <sys/stat.h>
4030154ac8SAndrew Moore 
4130154ac8SAndrew Moore #include "ed.h"
4230154ac8SAndrew Moore 
4330154ac8SAndrew Moore 
4430154ac8SAndrew Moore FILE *sfp;				/* scratch file pointer */
4530154ac8SAndrew Moore off_t sfseek;				/* scratch file position */
4630154ac8SAndrew Moore int seek_write;				/* seek before writing */
4795e6217eSAndrew Moore line_t buffer_head;			/* incore buffer */
4830154ac8SAndrew Moore 
4995e6217eSAndrew Moore /* get_sbuf_line: get a line of text from the scratch file; return pointer
5030154ac8SAndrew Moore    to the text */
5130154ac8SAndrew Moore char *
5295e6217eSAndrew Moore get_sbuf_line(lp)
5330154ac8SAndrew Moore 	line_t *lp;
5430154ac8SAndrew Moore {
5595e6217eSAndrew Moore 	static char *sfbuf = NULL;	/* buffer */
5695e6217eSAndrew Moore 	static int sfbufsz = 0;		/* buffer size */
5795e6217eSAndrew Moore 
5830154ac8SAndrew Moore 	int len, ct;
5930154ac8SAndrew Moore 
6095e6217eSAndrew Moore 	if (lp == &buffer_head)
6130154ac8SAndrew Moore 		return NULL;
6230154ac8SAndrew Moore 	seek_write = 1;				/* force seek on write */
6330154ac8SAndrew Moore 	/* out of position */
6430154ac8SAndrew Moore 	if (sfseek != lp->seek) {
6530154ac8SAndrew Moore 		sfseek = lp->seek;
6630154ac8SAndrew Moore 		if (fseek(sfp, sfseek, SEEK_SET) < 0) {
6730154ac8SAndrew Moore 			fprintf(stderr, "%s\n", strerror(errno));
6830154ac8SAndrew Moore 			sprintf(errmsg, "cannot seek temp file");
6930154ac8SAndrew Moore 			return NULL;
7030154ac8SAndrew Moore 		}
7130154ac8SAndrew Moore 	}
7295e6217eSAndrew Moore 	len = lp->len;
7395e6217eSAndrew Moore 	REALLOC(sfbuf, sfbufsz, len + 1, NULL);
7430154ac8SAndrew Moore 	if ((ct = fread(sfbuf, sizeof(char), len, sfp)) <  0 || ct != len) {
7530154ac8SAndrew Moore 		fprintf(stderr, "%s\n", strerror(errno));
7630154ac8SAndrew Moore 		sprintf(errmsg, "cannot read temp file");
7730154ac8SAndrew Moore 		return NULL;
7830154ac8SAndrew Moore 	}
7930154ac8SAndrew Moore 	sfseek += len;				/* update file position */
8030154ac8SAndrew Moore 	sfbuf[len] = '\0';
8130154ac8SAndrew Moore 	return sfbuf;
8230154ac8SAndrew Moore }
8330154ac8SAndrew Moore 
8430154ac8SAndrew Moore 
8595e6217eSAndrew Moore /* put_sbuf_line: write a line of text to the scratch file and add a line node
8630154ac8SAndrew Moore    to the editor buffer;  return a pointer to the end of the text */
8730154ac8SAndrew Moore char *
8895e6217eSAndrew Moore put_sbuf_line(cs)
8930154ac8SAndrew Moore 	char *cs;
9030154ac8SAndrew Moore {
9130154ac8SAndrew Moore 	line_t *lp;
9230154ac8SAndrew Moore 	int len, ct;
9330154ac8SAndrew Moore 	char *s;
9430154ac8SAndrew Moore 
9530154ac8SAndrew Moore 	if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) {
9630154ac8SAndrew Moore 		fprintf(stderr, "%s\n", strerror(errno));
9730154ac8SAndrew Moore 		sprintf(errmsg, "out of memory");
9830154ac8SAndrew Moore 		return NULL;
9930154ac8SAndrew Moore 	}
10030154ac8SAndrew Moore 	/* assert: cs is '\n' terminated */
10130154ac8SAndrew Moore 	for (s = cs; *s != '\n'; s++)
10230154ac8SAndrew Moore 		;
10330154ac8SAndrew Moore 	if (s - cs >= LINECHARS) {
10430154ac8SAndrew Moore 		sprintf(errmsg, "line too long");
10530154ac8SAndrew Moore 		return NULL;
10630154ac8SAndrew Moore 	}
10795e6217eSAndrew Moore 	len = s - cs;
10830154ac8SAndrew Moore 	/* out of position */
10930154ac8SAndrew Moore 	if (seek_write) {
11030154ac8SAndrew Moore 		if (fseek(sfp, 0L, SEEK_END) < 0) {
11130154ac8SAndrew Moore 			fprintf(stderr, "%s\n", strerror(errno));
11230154ac8SAndrew Moore 			sprintf(errmsg, "cannot seek temp file");
11330154ac8SAndrew Moore 			return NULL;
11430154ac8SAndrew Moore 		}
11530154ac8SAndrew Moore 		sfseek = ftell(sfp);
11630154ac8SAndrew Moore 		seek_write = 0;
11730154ac8SAndrew Moore 	}
11895e6217eSAndrew Moore 	/* assert: SPL1() */
11930154ac8SAndrew Moore 	if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) {
12030154ac8SAndrew Moore 		sfseek = -1;
12130154ac8SAndrew Moore 		fprintf(stderr, "%s\n", strerror(errno));
12230154ac8SAndrew Moore 		sprintf(errmsg, "cannot write temp file");
12330154ac8SAndrew Moore 		return NULL;
12430154ac8SAndrew Moore 	}
12530154ac8SAndrew Moore 	lp->len = len;
12630154ac8SAndrew Moore 	lp->seek  = sfseek;
12795e6217eSAndrew Moore 	add_line_node(lp);
12830154ac8SAndrew Moore 	sfseek += len;			/* update file position */
12930154ac8SAndrew Moore 	return ++s;
13030154ac8SAndrew Moore }
13130154ac8SAndrew Moore 
13230154ac8SAndrew Moore 
13395e6217eSAndrew Moore /* add_line_node: add a line node in the editor buffer after the current line */
13430154ac8SAndrew Moore void
13595e6217eSAndrew Moore add_line_node(lp)
13630154ac8SAndrew Moore 	line_t *lp;
13730154ac8SAndrew Moore {
13830154ac8SAndrew Moore 	line_t *cp;
13930154ac8SAndrew Moore 
14095e6217eSAndrew Moore 	cp = get_addressed_line_node(current_addr);				/* this get_addressed_line_node last! */
141d165d4acSAndrew Moore 	INSQUE(lp, cp);
14295e6217eSAndrew Moore 	addr_last++;
14395e6217eSAndrew Moore 	current_addr++;
14430154ac8SAndrew Moore }
14530154ac8SAndrew Moore 
14630154ac8SAndrew Moore 
14795e6217eSAndrew Moore /* get_line_node_addr: return line number of pointer */
14830154ac8SAndrew Moore long
14995e6217eSAndrew Moore get_line_node_addr(lp)
15030154ac8SAndrew Moore 	line_t *lp;
15130154ac8SAndrew Moore {
15295e6217eSAndrew Moore 	line_t *cp = &buffer_head;
15330154ac8SAndrew Moore 	long n = 0;
15430154ac8SAndrew Moore 
15595e6217eSAndrew Moore 	while (cp != lp && (cp = cp->q_forw) != &buffer_head)
15630154ac8SAndrew Moore 		n++;
15795e6217eSAndrew Moore 	if (n && cp == &buffer_head) {
15810ca1c6cSAndrew Moore 		sprintf(errmsg, "invalid address");
15910ca1c6cSAndrew Moore 		return ERR;
16010ca1c6cSAndrew Moore 	 }
16110ca1c6cSAndrew Moore 	 return n;
16230154ac8SAndrew Moore }
16330154ac8SAndrew Moore 
16430154ac8SAndrew Moore 
16595e6217eSAndrew Moore /* get_addressed_line_node: return pointer to a line node in the editor buffer */
16630154ac8SAndrew Moore line_t *
16795e6217eSAndrew Moore get_addressed_line_node(n)
16830154ac8SAndrew Moore 	long n;
16930154ac8SAndrew Moore {
17095e6217eSAndrew Moore 	static line_t *lp = &buffer_head;
17130154ac8SAndrew Moore 	static long on = 0;
17230154ac8SAndrew Moore 
17395e6217eSAndrew Moore 	SPL1();
17430154ac8SAndrew Moore 	if (n > on)
17595e6217eSAndrew Moore 		if (n <= (on + addr_last) >> 1)
17630154ac8SAndrew Moore 			for (; on < n; on++)
17795e6217eSAndrew Moore 				lp = lp->q_forw;
17830154ac8SAndrew Moore 		else {
17995e6217eSAndrew Moore 			lp = buffer_head.q_back;
18095e6217eSAndrew Moore 			for (on = addr_last; on > n; on--)
18195e6217eSAndrew Moore 				lp = lp->q_back;
18230154ac8SAndrew Moore 		}
18330154ac8SAndrew Moore 	else
18430154ac8SAndrew Moore 		if (n >= on >> 1)
18530154ac8SAndrew Moore 			for (; on > n; on--)
18695e6217eSAndrew Moore 				lp = lp->q_back;
18730154ac8SAndrew Moore 		else {
18895e6217eSAndrew Moore 			lp = &buffer_head;
18930154ac8SAndrew Moore 			for (on = 0; on < n; on++)
19095e6217eSAndrew Moore 				lp = lp->q_forw;
19130154ac8SAndrew Moore 		}
19295e6217eSAndrew Moore 	SPL0();
19330154ac8SAndrew Moore 	return lp;
19430154ac8SAndrew Moore }
19530154ac8SAndrew Moore 
19630154ac8SAndrew Moore 
19795e6217eSAndrew Moore extern int newline_added;
19895e6217eSAndrew Moore 
19930154ac8SAndrew Moore char sfn[15] = "";				/* scratch file name */
20030154ac8SAndrew Moore 
20195e6217eSAndrew Moore /* open_sbuf: open scratch file */
20295e6217eSAndrew Moore int
20395e6217eSAndrew Moore open_sbuf()
20430154ac8SAndrew Moore {
205e38b5013SWarner Losh 	int fd = -1;
206d165d4acSAndrew Moore 	int u;
207d165d4acSAndrew Moore 
20895e6217eSAndrew Moore 	isbinary = newline_added = 0;
209d165d4acSAndrew Moore 	u = umask(077);
21030154ac8SAndrew Moore 	strcpy(sfn, "/tmp/ed.XXXXXX");
211f8ce2ec9SEivind Eklund 	if ((fd = mkstemp(sfn)) == -1 ||
212e38b5013SWarner Losh 	    (sfp = fdopen(fd, "w+")) == NULL) {
213e38b5013SWarner Losh 		if (fd != -1)
214e38b5013SWarner Losh 			close(fd);
215e38b5013SWarner Losh 		perror(sfn);
216e38b5013SWarner Losh 		strcpy(errmsg, "cannot open temp file");
217d165d4acSAndrew Moore 		umask(u);
21830154ac8SAndrew Moore 		return ERR;
21930154ac8SAndrew Moore 	}
220d165d4acSAndrew Moore 	umask(u);
22130154ac8SAndrew Moore 	return 0;
22230154ac8SAndrew Moore }
22330154ac8SAndrew Moore 
22430154ac8SAndrew Moore 
22595e6217eSAndrew Moore /* close_sbuf: close scratch file */
22695e6217eSAndrew Moore int
22795e6217eSAndrew Moore close_sbuf()
22830154ac8SAndrew Moore {
22930154ac8SAndrew Moore 	if (sfp) {
23030154ac8SAndrew Moore 		if (fclose(sfp) < 0) {
23130154ac8SAndrew Moore 			fprintf(stderr, "%s: %s\n", sfn, strerror(errno));
23230154ac8SAndrew Moore 			sprintf(errmsg, "cannot close temp file");
23330154ac8SAndrew Moore 			return ERR;
23430154ac8SAndrew Moore 		}
23530154ac8SAndrew Moore 		sfp = NULL;
23630154ac8SAndrew Moore 		unlink(sfn);
23730154ac8SAndrew Moore 	}
23830154ac8SAndrew Moore 	sfseek = seek_write = 0;
23930154ac8SAndrew Moore 	return 0;
24030154ac8SAndrew Moore }
24130154ac8SAndrew Moore 
24230154ac8SAndrew Moore 
24395e6217eSAndrew Moore /* quit: remove_lines scratch file and exit */
24430154ac8SAndrew Moore void
24530154ac8SAndrew Moore quit(n)
24630154ac8SAndrew Moore 	int n;
24730154ac8SAndrew Moore {
24830154ac8SAndrew Moore 	if (sfp) {
24930154ac8SAndrew Moore 		fclose(sfp);
25030154ac8SAndrew Moore 		unlink(sfn);
25130154ac8SAndrew Moore 	}
25230154ac8SAndrew Moore 	exit(n);
25330154ac8SAndrew Moore }
25495c745afSAndrew Moore 
25595c745afSAndrew Moore 
25695c745afSAndrew Moore unsigned char ctab[256];		/* character translation table */
25795c745afSAndrew Moore 
25895e6217eSAndrew Moore /* init_buffers: open scratch buffer; initialize line queue */
25995c745afSAndrew Moore void
26095e6217eSAndrew Moore init_buffers()
26195c745afSAndrew Moore {
26295c745afSAndrew Moore 	int i = 0;
26395c745afSAndrew Moore 
26495e6217eSAndrew Moore 	/* Read stdin one character at a time to avoid i/o contention
26595e6217eSAndrew Moore 	   with shell escapes invoked by nonterminal input, e.g.,
26695e6217eSAndrew Moore 	   ed - <<EOF
26795e6217eSAndrew Moore 	   !cat
26895e6217eSAndrew Moore 	   hello, world
26995e6217eSAndrew Moore 	   EOF */
27095e6217eSAndrew Moore 	setbuffer(stdin, stdinbuf, 1);
271fd0e1c25SWolfgang Helbig 
272fd0e1c25SWolfgang Helbig 	/* Ensure stdout is line buffered. This avoids bogus delays
273fd0e1c25SWolfgang Helbig 	   of output if stdout is piped through utilities to a terminal. */
274fd0e1c25SWolfgang Helbig 	setvbuf(stdout, NULL, _IOLBF, 0);
27595e6217eSAndrew Moore 	if (open_sbuf() < 0)
27695c745afSAndrew Moore 		quit(2);
27795e6217eSAndrew Moore 	REQUE(&buffer_head, &buffer_head);
27895c745afSAndrew Moore 	for (i = 0; i < 256; i++)
27995c745afSAndrew Moore 		ctab[i] = i;
28095c745afSAndrew Moore }
28195c745afSAndrew Moore 
28295c745afSAndrew Moore 
28395e6217eSAndrew Moore /* translit_text: translate characters in a string */
28495c745afSAndrew Moore char *
28595e6217eSAndrew Moore translit_text(s, len, from, to)
28695c745afSAndrew Moore 	char *s;
28795c745afSAndrew Moore 	int len;
28895c745afSAndrew Moore 	int from;
28995c745afSAndrew Moore 	int to;
29095c745afSAndrew Moore {
29195c745afSAndrew Moore 	static int i = 0;
29295c745afSAndrew Moore 
29395c745afSAndrew Moore 	unsigned char *us;
29495c745afSAndrew Moore 
29595c745afSAndrew Moore 	ctab[i] = i;			/* restore table to initial state */
29695c745afSAndrew Moore 	ctab[i = from] = to;
29795c745afSAndrew Moore 	for (us = (unsigned char *) s; len-- > 0; us++)
29895c745afSAndrew Moore 		*us = ctab[*us];
29995c745afSAndrew Moore 	return s;
30095c745afSAndrew Moore }
301