read.c revision 148834
1/*-
2 * Copyright (c) 1992, 1993
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Christos Zoulas of Cornell University.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 *	$NetBSD: read.c,v 1.39 2005/08/02 12:11:14 christos Exp $
33 */
34
35#if !defined(lint) && !defined(SCCSID)
36static char sccsid[] = "@(#)read.c	8.1 (Berkeley) 6/4/93";
37#endif /* not lint && not SCCSID */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: head/lib/libedit/read.c 148834 2005-08-07 20:55:59Z stefanf $");
40
41/*
42 * read.c: Clean this junk up! This is horrible code.
43 *	   Terminal read functions
44 */
45#include "sys.h"
46#include <errno.h>
47#include <fcntl.h>
48#include <unistd.h>
49#include <stdlib.h>
50#include "el.h"
51
52#define	OKCMD	-1
53
54private int	read__fixio(int, int);
55private int	read_preread(EditLine *);
56private int	read_char(EditLine *, char *);
57private int	read_getcmd(EditLine *, el_action_t *, char *);
58
59/* read_init():
60 *	Initialize the read stuff
61 */
62protected int
63read_init(EditLine *el)
64{
65	/* builtin read_char */
66	el->el_read.read_char = read_char;
67	return 0;
68}
69
70
71/* el_read_setfn():
72 *	Set the read char function to the one provided.
73 *	If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
74 */
75protected int
76el_read_setfn(EditLine *el, el_rfunc_t rc)
77{
78	el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
79	return 0;
80}
81
82
83/* el_read_getfn():
84 *	return the current read char function, or EL_BUILTIN_GETCFN
85 *	if it is the default one
86 */
87protected el_rfunc_t
88el_read_getfn(EditLine *el)
89{
90       return (el->el_read.read_char == read_char) ?
91	    EL_BUILTIN_GETCFN : el->el_read.read_char;
92}
93
94
95#ifndef MIN
96#define MIN(A,B) ((A) < (B) ? (A) : (B))
97#endif
98
99#ifdef DEBUG_EDIT
100private void
101read_debug(EditLine *el)
102{
103
104	if (el->el_line.cursor > el->el_line.lastchar)
105		(void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
106	if (el->el_line.cursor < el->el_line.buffer)
107		(void) fprintf(el->el_errfile, "cursor < buffer\r\n");
108	if (el->el_line.cursor > el->el_line.limit)
109		(void) fprintf(el->el_errfile, "cursor > limit\r\n");
110	if (el->el_line.lastchar > el->el_line.limit)
111		(void) fprintf(el->el_errfile, "lastchar > limit\r\n");
112	if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
113		(void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
114}
115#endif /* DEBUG_EDIT */
116
117
118/* read__fixio():
119 *	Try to recover from a read error
120 */
121/* ARGSUSED */
122private int
123read__fixio(int fd __unused, int e)
124{
125
126	switch (e) {
127	case -1:		/* Make sure that the code is reachable */
128
129#ifdef EWOULDBLOCK
130	case EWOULDBLOCK:
131#ifndef TRY_AGAIN
132#define	TRY_AGAIN
133#endif
134#endif /* EWOULDBLOCK */
135
136#if defined(POSIX) && defined(EAGAIN)
137#if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
138	case EAGAIN:
139#ifndef TRY_AGAIN
140#define	TRY_AGAIN
141#endif
142#endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
143#endif /* POSIX && EAGAIN */
144
145		e = 0;
146#ifdef TRY_AGAIN
147#if defined(F_SETFL) && defined(O_NDELAY)
148		if ((e = fcntl(fd, F_GETFL, 0)) == -1)
149			return (-1);
150
151		if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
152			return (-1);
153		else
154			e = 1;
155#endif /* F_SETFL && O_NDELAY */
156
157#ifdef FIONBIO
158		{
159			int zero = 0;
160
161			if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1)
162				return (-1);
163			else
164				e = 1;
165		}
166#endif /* FIONBIO */
167
168#endif /* TRY_AGAIN */
169		return (e ? 0 : -1);
170
171	case EINTR:
172		return (0);
173
174	default:
175		return (-1);
176	}
177}
178
179
180/* read_preread():
181 *	Try to read the stuff in the input queue;
182 */
183private int
184read_preread(EditLine *el)
185{
186	int chrs = 0;
187
188	if (el->el_tty.t_mode == ED_IO)
189		return (0);
190
191#ifdef FIONREAD
192	(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
193	if (chrs > 0) {
194		char buf[EL_BUFSIZ];
195
196		chrs = read(el->el_infd, buf,
197		    (size_t) MIN(chrs, EL_BUFSIZ - 1));
198		if (chrs > 0) {
199			buf[chrs] = '\0';
200			el_push(el, buf);
201		}
202	}
203#endif /* FIONREAD */
204
205	return (chrs > 0);
206}
207
208
209/* el_push():
210 *	Push a macro
211 */
212public void
213el_push(EditLine *el, char *str)
214{
215	c_macro_t *ma = &el->el_chared.c_macro;
216
217	if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
218		ma->level++;
219		if ((ma->macro[ma->level] = el_strdup(str)) != NULL)
220			return;
221		ma->level--;
222	}
223	term_beep(el);
224	term__flush();
225}
226
227
228/* read_getcmd():
229 *	Return next command from the input stream.
230 */
231private int
232read_getcmd(EditLine *el, el_action_t *cmdnum, char *ch)
233{
234	el_action_t cmd;
235	int num;
236
237	do {
238		if ((num = el_getc(el, ch)) != 1)	/* if EOF or error */
239			return (num);
240
241#ifdef	KANJI
242		if ((*ch & 0200)) {
243			el->el_state.metanext = 0;
244			cmd = CcViMap[' '];
245			break;
246		} else
247#endif /* KANJI */
248
249		if (el->el_state.metanext) {
250			el->el_state.metanext = 0;
251			*ch |= 0200;
252		}
253		cmd = el->el_map.current[(unsigned char) *ch];
254		if (cmd == ED_SEQUENCE_LEAD_IN) {
255			key_value_t val;
256			switch (key_get(el, ch, &val)) {
257			case XK_CMD:
258				cmd = val.cmd;
259				break;
260			case XK_STR:
261				el_push(el, val.str);
262				break;
263#ifdef notyet
264			case XK_EXE:
265				/* XXX: In the future to run a user function */
266				RunCommand(val.str);
267				break;
268#endif
269			default:
270				EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
271				break;
272			}
273		}
274		if (el->el_map.alt == NULL)
275			el->el_map.current = el->el_map.key;
276	} while (cmd == ED_SEQUENCE_LEAD_IN);
277	*cmdnum = cmd;
278	return (OKCMD);
279}
280
281
282/* read_char():
283 *	Read a character from the tty.
284 */
285private int
286read_char(EditLine *el, char *cp)
287{
288	int num_read;
289	int tried = 0;
290
291	while ((num_read = read(el->el_infd, cp, 1)) == -1)
292		if (!tried && read__fixio(el->el_infd, errno) == 0)
293			tried = 1;
294		else {
295			*cp = '\0';
296			return (-1);
297		}
298
299	return (num_read);
300}
301
302
303/* el_getc():
304 *	Read a character
305 */
306public int
307el_getc(EditLine *el, char *cp)
308{
309	int num_read;
310	c_macro_t *ma = &el->el_chared.c_macro;
311
312	term__flush();
313	for (;;) {
314		if (ma->level < 0) {
315			if (!read_preread(el))
316				break;
317		}
318		if (ma->level < 0)
319			break;
320
321		if (ma->macro[ma->level][ma->offset] == '\0') {
322			el_free(ma->macro[ma->level--]);
323			ma->offset = 0;
324			continue;
325		}
326		*cp = ma->macro[ma->level][ma->offset++] & 0377;
327		if (ma->macro[ma->level][ma->offset] == '\0') {
328			/* Needed for QuoteMode On */
329			el_free(ma->macro[ma->level--]);
330			ma->offset = 0;
331		}
332		return (1);
333	}
334
335#ifdef DEBUG_READ
336	(void) fprintf(el->el_errfile, "Turning raw mode on\n");
337#endif /* DEBUG_READ */
338	if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
339		return (0);
340
341#ifdef DEBUG_READ
342	(void) fprintf(el->el_errfile, "Reading a character\n");
343#endif /* DEBUG_READ */
344	num_read = (*el->el_read.read_char)(el, cp);
345#ifdef DEBUG_READ
346	(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
347#endif /* DEBUG_READ */
348	return (num_read);
349}
350
351protected void
352read_prepare(EditLine *el)
353{
354	if (el->el_flags & HANDLE_SIGNALS)
355		sig_set(el);
356	if (el->el_flags & NO_TTY)
357		return;
358	if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
359		tty_rawmode(el);
360
361	/* This is relatively cheap, and things go terribly wrong if
362	   we have the wrong size. */
363	el_resize(el);
364	re_clear_display(el);	/* reset the display stuff */
365	ch_reset(el, 0);
366	re_refresh(el);		/* print the prompt */
367
368	if (el->el_flags & UNBUFFERED)
369		term__flush();
370}
371
372protected void
373read_finish(EditLine *el)
374{
375	if ((el->el_flags & UNBUFFERED) == 0)
376		(void) tty_cookedmode(el);
377	if (el->el_flags & HANDLE_SIGNALS)
378		sig_clr(el);
379}
380
381public const char *
382el_gets(EditLine *el, int *nread)
383{
384	int retval;
385	el_action_t cmdnum = 0;
386	int num;		/* how many chars we have read at NL */
387	char ch;
388	int crlf = 0;
389#ifdef FIONREAD
390	c_macro_t *ma = &el->el_chared.c_macro;
391#endif /* FIONREAD */
392
393	if (el->el_flags & NO_TTY) {
394		char *cp = el->el_line.buffer;
395		size_t idx;
396
397		while ((*el->el_read.read_char)(el, cp) == 1) {
398			/* make sure there is space for next character */
399			if (cp + 1 >= el->el_line.limit) {
400				idx = (cp - el->el_line.buffer);
401				if (!ch_enlargebufs(el, 2))
402					break;
403				cp = &el->el_line.buffer[idx];
404			}
405			cp++;
406			if (el->el_flags & UNBUFFERED)
407				break;
408			if (cp[-1] == '\r' || cp[-1] == '\n')
409				break;
410		}
411
412		el->el_line.cursor = el->el_line.lastchar = cp;
413		*cp = '\0';
414		if (nread)
415			*nread = el->el_line.cursor - el->el_line.buffer;
416		return (el->el_line.buffer);
417	}
418
419
420#ifdef FIONREAD
421	if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
422		long chrs = 0;
423
424		(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
425		if (chrs == 0) {
426			if (tty_rawmode(el) < 0) {
427				if (nread)
428					*nread = 0;
429				return (NULL);
430			}
431		}
432	}
433#endif /* FIONREAD */
434
435	if ((el->el_flags & UNBUFFERED) == 0)
436		read_prepare(el);
437
438	if (el->el_flags & EDIT_DISABLED) {
439		char *cp;
440		size_t idx;
441		if ((el->el_flags & UNBUFFERED) == 0)
442			cp = el->el_line.buffer;
443		else
444			cp = el->el_line.lastchar;
445
446		term__flush();
447
448		while ((*el->el_read.read_char)(el, cp) == 1) {
449			/* make sure there is space next character */
450			if (cp + 1 >= el->el_line.limit) {
451				idx = (cp - el->el_line.buffer);
452				if (!ch_enlargebufs(el, 2))
453					break;
454				cp = &el->el_line.buffer[idx];
455			}
456			if (*cp == 4)	/* ought to be stty eof */
457				break;
458			cp++;
459			crlf = cp[-1] == '\r' || cp[-1] == '\n';
460			if (el->el_flags & UNBUFFERED)
461				break;
462			if (crlf)
463				break;
464		}
465
466		el->el_line.cursor = el->el_line.lastchar = cp;
467		*cp = '\0';
468		if (nread)
469			*nread = el->el_line.cursor - el->el_line.buffer;
470		return (el->el_line.buffer);
471	}
472
473	for (num = OKCMD; num == OKCMD;) {	/* while still editing this
474						 * line */
475#ifdef DEBUG_EDIT
476		read_debug(el);
477#endif /* DEBUG_EDIT */
478		/* if EOF or error */
479		if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
480#ifdef DEBUG_READ
481			(void) fprintf(el->el_errfile,
482			    "Returning from el_gets %d\n", num);
483#endif /* DEBUG_READ */
484			break;
485		}
486		if ((unsigned int)cmdnum >= el->el_map.nfunc) {	/* BUG CHECK command */
487#ifdef DEBUG_EDIT
488			(void) fprintf(el->el_errfile,
489			    "ERROR: illegal command from key 0%o\r\n", ch);
490#endif /* DEBUG_EDIT */
491			continue;	/* try again */
492		}
493		/* now do the real command */
494#ifdef DEBUG_READ
495		{
496			el_bindings_t *b;
497			for (b = el->el_map.help; b->name; b++)
498				if (b->func == cmdnum)
499					break;
500			if (b->name)
501				(void) fprintf(el->el_errfile,
502				    "Executing %s\n", b->name);
503			else
504				(void) fprintf(el->el_errfile,
505				    "Error command = %d\n", cmdnum);
506		}
507#endif /* DEBUG_READ */
508		/* vi redo needs these way down the levels... */
509		el->el_state.thiscmd = cmdnum;
510		el->el_state.thisch = ch;
511		if (el->el_map.type == MAP_VI &&
512		    el->el_map.current == el->el_map.key &&
513		    el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
514			if (cmdnum == VI_DELETE_PREV_CHAR &&
515			    el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
516			    && isprint((unsigned char)el->el_chared.c_redo.pos[-1]))
517				el->el_chared.c_redo.pos--;
518			else
519				*el->el_chared.c_redo.pos++ = ch;
520		}
521		retval = (*el->el_map.func[cmdnum]) (el, ch);
522#ifdef DEBUG_READ
523		(void) fprintf(el->el_errfile,
524			"Returned state %d\n", retval );
525#endif /* DEBUG_READ */
526
527		/* save the last command here */
528		el->el_state.lastcmd = cmdnum;
529
530		/* use any return value */
531		switch (retval) {
532		case CC_CURSOR:
533			re_refresh_cursor(el);
534			break;
535
536		case CC_REDISPLAY:
537			re_clear_lines(el);
538			re_clear_display(el);
539			/* FALLTHROUGH */
540
541		case CC_REFRESH:
542			re_refresh(el);
543			break;
544
545		case CC_REFRESH_BEEP:
546			re_refresh(el);
547			term_beep(el);
548			break;
549
550		case CC_NORM:	/* normal char */
551			break;
552
553		case CC_ARGHACK:	/* Suggested by Rich Salz */
554			/* <rsalz@pineapple.bbn.com> */
555			continue;	/* keep going... */
556
557		case CC_EOF:	/* end of file typed */
558			if ((el->el_flags & UNBUFFERED) == 0)
559				num = 0;
560			else if (num == -1) {
561				*el->el_line.lastchar++ = CONTROL('d');
562				el->el_line.cursor = el->el_line.lastchar;
563				num = 1;
564			}
565			break;
566
567		case CC_NEWLINE:	/* normal end of line */
568			num = el->el_line.lastchar - el->el_line.buffer;
569			break;
570
571		case CC_FATAL:	/* fatal error, reset to known state */
572#ifdef DEBUG_READ
573			(void) fprintf(el->el_errfile,
574			    "*** editor fatal ERROR ***\r\n\n");
575#endif /* DEBUG_READ */
576			/* put (real) cursor in a known place */
577			re_clear_display(el);	/* reset the display stuff */
578			ch_reset(el, 1);	/* reset the input pointers */
579			re_refresh(el);	/* print the prompt again */
580			break;
581
582		case CC_ERROR:
583		default:	/* functions we don't know about */
584#ifdef DEBUG_READ
585			(void) fprintf(el->el_errfile,
586			    "*** editor ERROR ***\r\n\n");
587#endif /* DEBUG_READ */
588			term_beep(el);
589			term__flush();
590			break;
591		}
592		el->el_state.argument = 1;
593		el->el_state.doingarg = 0;
594		el->el_chared.c_vcmd.action = NOP;
595		if (el->el_flags & UNBUFFERED)
596			break;
597	}
598
599	term__flush();		/* flush any buffered output */
600	/* make sure the tty is set up correctly */
601	if ((el->el_flags & UNBUFFERED) == 0) {
602		read_finish(el);
603		if (nread)
604			*nread = num;
605	} else {
606		if (nread)
607			*nread = el->el_line.lastchar - el->el_line.buffer;
608	}
609	return (num ? el->el_line.buffer : NULL);
610}
611