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