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 30a4616748SMike Barcroft static const char rcsid[] = 312a456239SPeter Wemm "$FreeBSD$"; 3230154ac8SAndrew Moore #endif /* not lint */ 3330154ac8SAndrew Moore 3430154ac8SAndrew Moore #include <sys/file.h> 35d165d4acSAndrew Moore #include <sys/stat.h> 3630154ac8SAndrew Moore 3730154ac8SAndrew Moore #include "ed.h" 3830154ac8SAndrew Moore 3930154ac8SAndrew Moore 4030154ac8SAndrew Moore FILE *sfp; /* scratch file pointer */ 4130154ac8SAndrew Moore off_t sfseek; /* scratch file position */ 4230154ac8SAndrew Moore int seek_write; /* seek before writing */ 4395e6217eSAndrew Moore line_t buffer_head; /* incore buffer */ 4430154ac8SAndrew Moore 4595e6217eSAndrew Moore /* get_sbuf_line: get a line of text from the scratch file; return pointer 4630154ac8SAndrew Moore to the text */ 4730154ac8SAndrew Moore char * 4895e6217eSAndrew Moore get_sbuf_line(lp) 4930154ac8SAndrew Moore line_t *lp; 5030154ac8SAndrew Moore { 5195e6217eSAndrew Moore static char *sfbuf = NULL; /* buffer */ 5295e6217eSAndrew Moore static int sfbufsz = 0; /* buffer size */ 5395e6217eSAndrew Moore 5430154ac8SAndrew Moore int len, ct; 5530154ac8SAndrew Moore 5695e6217eSAndrew Moore if (lp == &buffer_head) 5730154ac8SAndrew Moore return NULL; 5830154ac8SAndrew Moore seek_write = 1; /* force seek on write */ 5930154ac8SAndrew Moore /* out of position */ 6030154ac8SAndrew Moore if (sfseek != lp->seek) { 6130154ac8SAndrew Moore sfseek = lp->seek; 6230154ac8SAndrew Moore if (fseek(sfp, sfseek, SEEK_SET) < 0) { 6330154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 64a4616748SMike Barcroft errmsg = "cannot seek temp file"; 6530154ac8SAndrew Moore return NULL; 6630154ac8SAndrew Moore } 6730154ac8SAndrew Moore } 6895e6217eSAndrew Moore len = lp->len; 6995e6217eSAndrew Moore REALLOC(sfbuf, sfbufsz, len + 1, NULL); 7030154ac8SAndrew Moore if ((ct = fread(sfbuf, sizeof(char), len, sfp)) < 0 || ct != len) { 7130154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 72a4616748SMike Barcroft errmsg = "cannot read temp file"; 7330154ac8SAndrew Moore return NULL; 7430154ac8SAndrew Moore } 7530154ac8SAndrew Moore sfseek += len; /* update file position */ 7630154ac8SAndrew Moore sfbuf[len] = '\0'; 7730154ac8SAndrew Moore return sfbuf; 7830154ac8SAndrew Moore } 7930154ac8SAndrew Moore 8030154ac8SAndrew Moore 8195e6217eSAndrew Moore /* put_sbuf_line: write a line of text to the scratch file and add a line node 8230154ac8SAndrew Moore to the editor buffer; return a pointer to the end of the text */ 83a4616748SMike Barcroft const char * 8495e6217eSAndrew Moore put_sbuf_line(cs) 85a4616748SMike Barcroft const char *cs; 8630154ac8SAndrew Moore { 8730154ac8SAndrew Moore line_t *lp; 8830154ac8SAndrew Moore int len, ct; 89a4616748SMike Barcroft const char *s; 9030154ac8SAndrew Moore 9130154ac8SAndrew Moore if ((lp = (line_t *) malloc(sizeof(line_t))) == NULL) { 9230154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 93a4616748SMike Barcroft errmsg = "out of memory"; 9430154ac8SAndrew Moore return NULL; 9530154ac8SAndrew Moore } 9630154ac8SAndrew Moore /* assert: cs is '\n' terminated */ 9730154ac8SAndrew Moore for (s = cs; *s != '\n'; s++) 9830154ac8SAndrew Moore ; 9930154ac8SAndrew Moore if (s - cs >= LINECHARS) { 100a4616748SMike Barcroft errmsg = "line too long"; 10130154ac8SAndrew Moore return NULL; 10230154ac8SAndrew Moore } 10395e6217eSAndrew Moore len = s - cs; 10430154ac8SAndrew Moore /* out of position */ 10530154ac8SAndrew Moore if (seek_write) { 10630154ac8SAndrew Moore if (fseek(sfp, 0L, SEEK_END) < 0) { 10730154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 108a4616748SMike Barcroft errmsg = "cannot seek temp file"; 10930154ac8SAndrew Moore return NULL; 11030154ac8SAndrew Moore } 11130154ac8SAndrew Moore sfseek = ftell(sfp); 11230154ac8SAndrew Moore seek_write = 0; 11330154ac8SAndrew Moore } 11495e6217eSAndrew Moore /* assert: SPL1() */ 11530154ac8SAndrew Moore if ((ct = fwrite(cs, sizeof(char), len, sfp)) < 0 || ct != len) { 11630154ac8SAndrew Moore sfseek = -1; 11730154ac8SAndrew Moore fprintf(stderr, "%s\n", strerror(errno)); 118a4616748SMike Barcroft errmsg = "cannot write temp file"; 11930154ac8SAndrew Moore return NULL; 12030154ac8SAndrew Moore } 12130154ac8SAndrew Moore lp->len = len; 12230154ac8SAndrew Moore lp->seek = sfseek; 12395e6217eSAndrew Moore add_line_node(lp); 12430154ac8SAndrew Moore sfseek += len; /* update file position */ 12530154ac8SAndrew Moore return ++s; 12630154ac8SAndrew Moore } 12730154ac8SAndrew Moore 12830154ac8SAndrew Moore 12995e6217eSAndrew Moore /* add_line_node: add a line node in the editor buffer after the current line */ 13030154ac8SAndrew Moore void 13195e6217eSAndrew Moore add_line_node(lp) 13230154ac8SAndrew Moore line_t *lp; 13330154ac8SAndrew Moore { 13430154ac8SAndrew Moore line_t *cp; 13530154ac8SAndrew Moore 13695e6217eSAndrew Moore cp = get_addressed_line_node(current_addr); /* this get_addressed_line_node last! */ 137d165d4acSAndrew Moore INSQUE(lp, cp); 13895e6217eSAndrew Moore addr_last++; 13995e6217eSAndrew Moore current_addr++; 14030154ac8SAndrew Moore } 14130154ac8SAndrew Moore 14230154ac8SAndrew Moore 14395e6217eSAndrew Moore /* get_line_node_addr: return line number of pointer */ 14430154ac8SAndrew Moore long 14595e6217eSAndrew Moore get_line_node_addr(lp) 14630154ac8SAndrew Moore line_t *lp; 14730154ac8SAndrew Moore { 14895e6217eSAndrew Moore line_t *cp = &buffer_head; 14930154ac8SAndrew Moore long n = 0; 15030154ac8SAndrew Moore 15195e6217eSAndrew Moore while (cp != lp && (cp = cp->q_forw) != &buffer_head) 15230154ac8SAndrew Moore n++; 15395e6217eSAndrew Moore if (n && cp == &buffer_head) { 154a4616748SMike Barcroft errmsg = "invalid address"; 15510ca1c6cSAndrew Moore return ERR; 15610ca1c6cSAndrew Moore } 15710ca1c6cSAndrew Moore return n; 15830154ac8SAndrew Moore } 15930154ac8SAndrew Moore 16030154ac8SAndrew Moore 16195e6217eSAndrew Moore /* get_addressed_line_node: return pointer to a line node in the editor buffer */ 16230154ac8SAndrew Moore line_t * 16395e6217eSAndrew Moore get_addressed_line_node(n) 16430154ac8SAndrew Moore long n; 16530154ac8SAndrew Moore { 16695e6217eSAndrew Moore static line_t *lp = &buffer_head; 16730154ac8SAndrew Moore static long on = 0; 16830154ac8SAndrew Moore 16995e6217eSAndrew Moore SPL1(); 17030154ac8SAndrew Moore if (n > on) 17195e6217eSAndrew Moore if (n <= (on + addr_last) >> 1) 17230154ac8SAndrew Moore for (; on < n; on++) 17395e6217eSAndrew Moore lp = lp->q_forw; 17430154ac8SAndrew Moore else { 17595e6217eSAndrew Moore lp = buffer_head.q_back; 17695e6217eSAndrew Moore for (on = addr_last; on > n; on--) 17795e6217eSAndrew Moore lp = lp->q_back; 17830154ac8SAndrew Moore } 17930154ac8SAndrew Moore else 18030154ac8SAndrew Moore if (n >= on >> 1) 18130154ac8SAndrew Moore for (; on > n; on--) 18295e6217eSAndrew Moore lp = lp->q_back; 18330154ac8SAndrew Moore else { 18495e6217eSAndrew Moore lp = &buffer_head; 18530154ac8SAndrew Moore for (on = 0; on < n; on++) 18695e6217eSAndrew Moore lp = lp->q_forw; 18730154ac8SAndrew Moore } 18895e6217eSAndrew Moore SPL0(); 18930154ac8SAndrew Moore return lp; 19030154ac8SAndrew Moore } 19130154ac8SAndrew Moore 19230154ac8SAndrew Moore 19395e6217eSAndrew Moore extern int newline_added; 19495e6217eSAndrew Moore 19530154ac8SAndrew Moore char sfn[15] = ""; /* scratch file name */ 19630154ac8SAndrew Moore 19795e6217eSAndrew Moore /* open_sbuf: open scratch file */ 19895e6217eSAndrew Moore int 19995e6217eSAndrew Moore open_sbuf() 20030154ac8SAndrew Moore { 201e38b5013SWarner Losh int fd = -1; 202d165d4acSAndrew Moore int u; 203d165d4acSAndrew Moore 20495e6217eSAndrew Moore isbinary = newline_added = 0; 205d165d4acSAndrew Moore u = umask(077); 20630154ac8SAndrew Moore strcpy(sfn, "/tmp/ed.XXXXXX"); 207f8ce2ec9SEivind Eklund if ((fd = mkstemp(sfn)) == -1 || 208e38b5013SWarner Losh (sfp = fdopen(fd, "w+")) == NULL) { 209e38b5013SWarner Losh if (fd != -1) 210e38b5013SWarner Losh close(fd); 211e38b5013SWarner Losh perror(sfn); 212a4616748SMike Barcroft errmsg = "cannot open temp file"; 213d165d4acSAndrew Moore umask(u); 21430154ac8SAndrew Moore return ERR; 21530154ac8SAndrew Moore } 216d165d4acSAndrew Moore umask(u); 21730154ac8SAndrew Moore return 0; 21830154ac8SAndrew Moore } 21930154ac8SAndrew Moore 22030154ac8SAndrew Moore 22195e6217eSAndrew Moore /* close_sbuf: close scratch file */ 22295e6217eSAndrew Moore int 22395e6217eSAndrew Moore close_sbuf() 22430154ac8SAndrew Moore { 22530154ac8SAndrew Moore if (sfp) { 22630154ac8SAndrew Moore if (fclose(sfp) < 0) { 22730154ac8SAndrew Moore fprintf(stderr, "%s: %s\n", sfn, strerror(errno)); 228a4616748SMike Barcroft errmsg = "cannot close temp file"; 22930154ac8SAndrew Moore return ERR; 23030154ac8SAndrew Moore } 23130154ac8SAndrew Moore sfp = NULL; 23230154ac8SAndrew Moore unlink(sfn); 23330154ac8SAndrew Moore } 23430154ac8SAndrew Moore sfseek = seek_write = 0; 23530154ac8SAndrew Moore return 0; 23630154ac8SAndrew Moore } 23730154ac8SAndrew Moore 23830154ac8SAndrew Moore 23995e6217eSAndrew Moore /* quit: remove_lines scratch file and exit */ 24030154ac8SAndrew Moore void 24130154ac8SAndrew Moore quit(n) 24230154ac8SAndrew Moore int n; 24330154ac8SAndrew Moore { 24430154ac8SAndrew Moore if (sfp) { 24530154ac8SAndrew Moore fclose(sfp); 24630154ac8SAndrew Moore unlink(sfn); 24730154ac8SAndrew Moore } 24830154ac8SAndrew Moore exit(n); 24930154ac8SAndrew Moore } 25095c745afSAndrew Moore 25195c745afSAndrew Moore 25295c745afSAndrew Moore unsigned char ctab[256]; /* character translation table */ 25395c745afSAndrew Moore 25495e6217eSAndrew Moore /* init_buffers: open scratch buffer; initialize line queue */ 25595c745afSAndrew Moore void 25695e6217eSAndrew Moore init_buffers() 25795c745afSAndrew Moore { 25895c745afSAndrew Moore int i = 0; 25995c745afSAndrew Moore 26095e6217eSAndrew Moore /* Read stdin one character at a time to avoid i/o contention 26195e6217eSAndrew Moore with shell escapes invoked by nonterminal input, e.g., 26295e6217eSAndrew Moore ed - <<EOF 26395e6217eSAndrew Moore !cat 26495e6217eSAndrew Moore hello, world 26595e6217eSAndrew Moore EOF */ 26695e6217eSAndrew Moore setbuffer(stdin, stdinbuf, 1); 267fd0e1c25SWolfgang Helbig 268fd0e1c25SWolfgang Helbig /* Ensure stdout is line buffered. This avoids bogus delays 269fd0e1c25SWolfgang Helbig of output if stdout is piped through utilities to a terminal. */ 270fd0e1c25SWolfgang Helbig setvbuf(stdout, NULL, _IOLBF, 0); 27195e6217eSAndrew Moore if (open_sbuf() < 0) 27295c745afSAndrew Moore quit(2); 27395e6217eSAndrew Moore REQUE(&buffer_head, &buffer_head); 27495c745afSAndrew Moore for (i = 0; i < 256; i++) 27595c745afSAndrew Moore ctab[i] = i; 27695c745afSAndrew Moore } 27795c745afSAndrew Moore 27895c745afSAndrew Moore 27995e6217eSAndrew Moore /* translit_text: translate characters in a string */ 28095c745afSAndrew Moore char * 28195e6217eSAndrew Moore translit_text(s, len, from, to) 28295c745afSAndrew Moore char *s; 28395c745afSAndrew Moore int len; 28495c745afSAndrew Moore int from; 28595c745afSAndrew Moore int to; 28695c745afSAndrew Moore { 28795c745afSAndrew Moore static int i = 0; 28895c745afSAndrew Moore 28995c745afSAndrew Moore unsigned char *us; 29095c745afSAndrew Moore 29195c745afSAndrew Moore ctab[i] = i; /* restore table to initial state */ 29295c745afSAndrew Moore ctab[i = from] = to; 29395c745afSAndrew Moore for (us = (unsigned char *) s; len-- > 0; us++) 29495c745afSAndrew Moore *us = ctab[*us]; 29595c745afSAndrew Moore return s; 29695c745afSAndrew Moore } 297