xref: /openbsd/lib/libedit/read.c (revision a6445c1d)
1 /*	$OpenBSD: read.c,v 1.15 2014/10/17 06:07:50 deraadt Exp $	*/
2 /*	$NetBSD: read.c,v 1.57 2010/07/21 18:18:52 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 <limits.h>
47 #include "el.h"
48 
49 #define	OKCMD	-1	/* must be -1! */
50 
51 private int	read__fixio(int, int);
52 private int	read_preread(EditLine *);
53 private int	read_char(EditLine *, Char *);
54 private int	read_getcmd(EditLine *, el_action_t *, Char *);
55 private void	read_pop(c_macro_t *);
56 
57 /* read_init():
58  *	Initialize the read stuff
59  */
60 protected int
61 read_init(EditLine *el)
62 {
63 	/* builtin read_char */
64 	el->el_read.read_char = read_char;
65 	return 0;
66 }
67 
68 
69 /* el_read_setfn():
70  *	Set the read char function to the one provided.
71  *	If it is set to EL_BUILTIN_GETCFN, then reset to the builtin one.
72  */
73 protected int
74 el_read_setfn(EditLine *el, el_rfunc_t rc)
75 {
76 	el->el_read.read_char = (rc == EL_BUILTIN_GETCFN) ? read_char : rc;
77 	return 0;
78 }
79 
80 
81 /* el_read_getfn():
82  *	return the current read char function, or EL_BUILTIN_GETCFN
83  *	if it is the default one
84  */
85 protected el_rfunc_t
86 el_read_getfn(EditLine *el)
87 {
88        return (el->el_read.read_char == read_char) ?
89 	    EL_BUILTIN_GETCFN : el->el_read.read_char;
90 }
91 
92 
93 #ifndef MIN
94 #define MIN(A,B) ((A) < (B) ? (A) : (B))
95 #endif
96 
97 #ifdef DEBUG_EDIT
98 private void
99 read_debug(EditLine *el)
100 {
101 
102 	if (el->el_line.cursor > el->el_line.lastchar)
103 		(void) fprintf(el->el_errfile, "cursor > lastchar\r\n");
104 	if (el->el_line.cursor < el->el_line.buffer)
105 		(void) fprintf(el->el_errfile, "cursor < buffer\r\n");
106 	if (el->el_line.cursor > el->el_line.limit)
107 		(void) fprintf(el->el_errfile, "cursor > limit\r\n");
108 	if (el->el_line.lastchar > el->el_line.limit)
109 		(void) fprintf(el->el_errfile, "lastchar > limit\r\n");
110 	if (el->el_line.limit != &el->el_line.buffer[EL_BUFSIZ - 2])
111 		(void) fprintf(el->el_errfile, "limit != &buffer[EL_BUFSIZ-2]\r\n");
112 }
113 #endif /* DEBUG_EDIT */
114 
115 
116 /* read__fixio():
117  *	Try to recover from a read error
118  */
119 /* ARGSUSED */
120 private int
121 read__fixio(int fd __attribute__((__unused__)), int e)
122 {
123 
124 	switch (e) {
125 	case -1:		/* Make sure that the code is reachable */
126 
127 #ifdef EWOULDBLOCK
128 	case EWOULDBLOCK:
129 #ifndef TRY_AGAIN
130 #define	TRY_AGAIN
131 #endif
132 #endif /* EWOULDBLOCK */
133 
134 #if defined(POSIX) && defined(EAGAIN)
135 #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN
136 	case EAGAIN:
137 #ifndef TRY_AGAIN
138 #define	TRY_AGAIN
139 #endif
140 #endif /* EWOULDBLOCK && EWOULDBLOCK != EAGAIN */
141 #endif /* POSIX && EAGAIN */
142 
143 		e = 0;
144 #ifdef TRY_AGAIN
145 #if defined(F_SETFL) && defined(O_NDELAY)
146 		if ((e = fcntl(fd, F_GETFL, 0)) == -1)
147 			return (-1);
148 
149 		if (fcntl(fd, F_SETFL, e & ~O_NDELAY) == -1)
150 			return (-1);
151 		else
152 			e = 1;
153 #endif /* F_SETFL && O_NDELAY */
154 
155 #ifdef FIONBIO
156 		{
157 			int zero = 0;
158 
159 			if (ioctl(fd, FIONBIO, (ioctl_t) & zero) == -1)
160 				return (-1);
161 			else
162 				e = 1;
163 		}
164 #endif /* FIONBIO */
165 
166 #endif /* TRY_AGAIN */
167 		return (e ? 0 : -1);
168 
169 	case EINTR:
170 		return (0);
171 
172 	default:
173 		return (-1);
174 	}
175 }
176 
177 
178 /* read_preread():
179  *	Try to read the stuff in the input queue;
180  */
181 private int
182 read_preread(EditLine *el)
183 {
184 	int chrs = 0;
185 
186 	if (el->el_tty.t_mode == ED_IO)
187 		return (0);
188 
189 #ifndef WIDECHAR
190 /* FIONREAD attempts to buffer up multiple bytes, and to make that work
191  * properly with partial wide/UTF-8 characters would need some careful work. */
192 #ifdef FIONREAD
193 	(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
194 	if (chrs > 0) {
195 		char buf[EL_BUFSIZ];
196 
197 		chrs = read(el->el_infd, buf,
198 		    (size_t) MIN(chrs, EL_BUFSIZ - 1));
199 		if (chrs > 0) {
200 			buf[chrs] = '\0';
201 			el_push(el, buf);
202 		}
203 	}
204 #endif /* FIONREAD */
205 #endif
206 	return (chrs > 0);
207 }
208 
209 
210 /* el_push():
211  *	Push a macro
212  */
213 public void
214 FUN(el,push)(EditLine *el, const Char *str)
215 {
216 	c_macro_t *ma = &el->el_chared.c_macro;
217 
218 	if (str != NULL && ma->level + 1 < EL_MAXMACRO) {
219 		ma->level++;
220 		if ((ma->macro[ma->level] = Strdup(str)) != NULL)
221 			return;
222 		ma->level--;
223 	}
224 	term_beep(el);
225 	term__flush(el);
226 }
227 
228 
229 /* read_getcmd():
230  *	Return next command from the input stream.
231  *	Character values > 255 are not looked up in the map, but inserted.
232  */
233 private int
234 read_getcmd(EditLine *el, el_action_t *cmdnum, Char *ch)
235 {
236 	el_action_t cmd;
237 	int num;
238 
239 	el->el_errno = 0;
240 	do {
241 		if ((num = FUN(el,getc)(el, ch)) != 1) {/* if EOF or error */
242 			el->el_errno = num == 0 ? 0 : errno;
243 			return (num);
244 		}
245 
246 #ifdef	KANJI
247 		if ((*ch & 0200)) {
248 			el->el_state.metanext = 0;
249 			cmd = CcViMap[' '];
250 			break;
251 		} else
252 #endif /* KANJI */
253 
254 		if (el->el_state.metanext) {
255 			el->el_state.metanext = 0;
256 			*ch |= 0200;
257 		}
258 #ifdef WIDECHAR
259                 if (*ch >= N_KEYS)
260                         cmd = ED_INSERT;
261 		else
262 #endif
263                         cmd = el->el_map.current[(unsigned char) *ch];
264 		if (cmd == ED_SEQUENCE_LEAD_IN) {
265 			key_value_t val;
266 			switch (key_get(el, ch, &val)) {
267 			case XK_CMD:
268 				cmd = val.cmd;
269 				break;
270 			case XK_STR:
271 				FUN(el,push)(el, val.str);
272 				break;
273 #ifdef notyet
274 			case XK_EXE:
275 				/* XXX: In the future to run a user function */
276 				RunCommand(val.str);
277 				break;
278 #endif
279 			default:
280 				EL_ABORT((el->el_errfile, "Bad XK_ type \n"));
281 				break;
282 			}
283 		}
284 		if (el->el_map.alt == NULL)
285 			el->el_map.current = el->el_map.key;
286 	} while (cmd == ED_SEQUENCE_LEAD_IN);
287 	*cmdnum = cmd;
288 	return (OKCMD);
289 }
290 
291 #ifdef WIDECHAR
292 /* utf8_islead():
293  *      Test whether a byte is a leading byte of a UTF-8 sequence.
294  */
295 private int
296 utf8_islead(unsigned char c)
297 {
298         return (c < 0x80) ||             /* single byte char */
299                (c >= 0xc2 && c <= 0xf4); /* start of multibyte sequence */
300 }
301 #endif
302 
303 /* read_char():
304  *	Read a character from the tty.
305  */
306 private int
307 read_char(EditLine *el, Char *cp)
308 {
309 	ssize_t num_read;
310 	int tried = 0;
311         char cbuf[MB_LEN_MAX];
312         int cbp = 0;
313         int bytes = 0;
314 
315  again:
316 	el->el_signal->sig_no = 0;
317 	while ((num_read = read(el->el_infd, cbuf + cbp, 1)) == -1) {
318 		switch (el->el_signal->sig_no) {
319 		case SIGCONT:
320 			el_set(el, EL_REFRESH);
321 			/*FALLTHROUGH*/
322 		case SIGWINCH:
323 			sig_set(el);
324 			goto again;
325 		default:
326 			break;
327 		}
328 		if (!tried && read__fixio(el->el_infd, errno) == 0)
329 			tried = 1;
330 		else {
331 			*cp = '\0';
332 			return (-1);
333 		}
334 	}
335 
336 #ifdef WIDECHAR
337 	if (el->el_flags & CHARSET_IS_UTF8) {
338 		if (!utf8_islead((unsigned char)cbuf[0]))
339 			goto again; /* discard the byte we read and try again */
340 		++cbp;
341 		if ((bytes = ct_mbtowc(cp, cbuf, cbp)) == -1) {
342 			ct_mbtowc_reset;
343 			if (cbp >= MB_LEN_MAX) { /* "shouldn't happen" */
344 				*cp = '\0';
345 				return (-1);
346 			}
347 			goto again;
348 		}
349 	} else  /* we don't support other multibyte charsets */
350 #endif
351 		*cp = (unsigned char)cbuf[0];
352 
353 	if ((el->el_flags & IGNORE_EXTCHARS) && bytes > 1) {
354 		cbp = 0; /* skip this character */
355 		goto again;
356 	}
357 
358 	return (int)num_read;
359 }
360 
361 /* read_pop():
362  *	Pop a macro from the stack
363  */
364 private void
365 read_pop(c_macro_t *ma)
366 {
367 	int i;
368 
369 	free(ma->macro[0]);
370 	for (i = 0; i < ma->level; i++)
371 		ma->macro[i] = ma->macro[i + 1];
372 	ma->level--;
373 	ma->offset = 0;
374 }
375 
376 /* el_getc():
377  *	Read a character
378  */
379 public int
380 FUN(el,getc)(EditLine *el, Char *cp)
381 {
382 	int num_read;
383 	c_macro_t *ma = &el->el_chared.c_macro;
384 
385 	term__flush(el);
386 	for (;;) {
387 		if (ma->level < 0) {
388 			if (!read_preread(el))
389 				break;
390 		}
391 
392 		if (ma->level < 0)
393 			break;
394 
395 		if (ma->macro[0][ma->offset] == '\0') {
396 			read_pop(ma);
397 			continue;
398 		}
399 
400 		*cp = ma->macro[0][ma->offset++];
401 
402 		if (ma->macro[0][ma->offset] == '\0') {
403 			/* Needed for QuoteMode On */
404 			read_pop(ma);
405 		}
406 
407 		return (1);
408 	}
409 
410 #ifdef DEBUG_READ
411 	(void) fprintf(el->el_errfile, "Turning raw mode on\n");
412 #endif /* DEBUG_READ */
413 	if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */
414 		return (0);
415 
416 #ifdef DEBUG_READ
417 	(void) fprintf(el->el_errfile, "Reading a character\n");
418 #endif /* DEBUG_READ */
419 	num_read = (*el->el_read.read_char)(el, cp);
420 #ifdef WIDECHAR
421 	if (el->el_flags & NARROW_READ)
422 		*cp = *(char *)(void *)cp;
423 #endif
424 #ifdef DEBUG_READ
425 	(void) fprintf(el->el_errfile, "Got it %c\n", *cp);
426 #endif /* DEBUG_READ */
427 	return (num_read);
428 }
429 
430 protected void
431 read_prepare(EditLine *el)
432 {
433 	if (el->el_flags & HANDLE_SIGNALS)
434 		sig_set(el);
435 	if (el->el_flags & NO_TTY)
436 		return;
437 	if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED)
438 		tty_rawmode(el);
439 
440 	/* This is relatively cheap, and things go terribly wrong if
441 	   we have the wrong size. */
442 	el_resize(el);
443 	re_clear_display(el);	/* reset the display stuff */
444 	ch_reset(el, 0);
445 	re_refresh(el);		/* print the prompt */
446 
447 	if (el->el_flags & UNBUFFERED)
448 		term__flush(el);
449 }
450 
451 protected void
452 read_finish(EditLine *el)
453 {
454 	if ((el->el_flags & UNBUFFERED) == 0)
455 		(void) tty_cookedmode(el);
456 	if (el->el_flags & HANDLE_SIGNALS)
457 		sig_clr(el);
458 }
459 
460 public const Char *
461 FUN(el,gets)(EditLine *el, int *nread)
462 {
463 	int retval;
464 	el_action_t cmdnum = 0;
465 	int num;		/* how many chars we have read at NL */
466 	Char ch, *cp;
467 	int crlf = 0;
468 	int nrb;
469 #ifdef FIONREAD
470 	c_macro_t *ma = &el->el_chared.c_macro;
471 #endif /* FIONREAD */
472 
473 	if (nread == NULL)
474 		nread = &nrb;
475 	*nread = 0;
476 
477 	if (el->el_flags & NO_TTY) {
478 		size_t idx;
479 
480 		cp = el->el_line.buffer;
481 		while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
482 			/* make sure there is space for next character */
483 			if (cp + 1 >= el->el_line.limit) {
484 				idx = (cp - el->el_line.buffer);
485 				if (!ch_enlargebufs(el, 2))
486 					break;
487 				cp = &el->el_line.buffer[idx];
488 			}
489 			cp++;
490 			if (el->el_flags & UNBUFFERED)
491 				break;
492 			if (cp[-1] == '\r' || cp[-1] == '\n')
493 				break;
494 		}
495 		if (num == -1) {
496 			if (errno == EINTR)
497 				cp = el->el_line.buffer;
498 			el->el_errno = errno;
499 		}
500 
501 		goto noedit;
502 	}
503 
504 
505 #ifdef FIONREAD
506 	if (el->el_tty.t_mode == EX_IO && ma->level < 0) {
507 		long chrs = 0;
508 
509 		(void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs);
510 		if (chrs == 0) {
511 			if (tty_rawmode(el) < 0) {
512 				errno = 0;
513 				*nread = 0;
514 				return (NULL);
515 			}
516 		}
517 	}
518 #endif /* FIONREAD */
519 
520 	if ((el->el_flags & UNBUFFERED) == 0)
521 		read_prepare(el);
522 
523 	if (el->el_flags & EDIT_DISABLED) {
524 		size_t idx;
525 
526 		if ((el->el_flags & UNBUFFERED) == 0)
527 			cp = el->el_line.buffer;
528 		else
529 			cp = el->el_line.lastchar;
530 
531 		term__flush(el);
532 
533 		while ((num = (*el->el_read.read_char)(el, cp)) == 1) {
534 			/* make sure there is space next character */
535 			if (cp + 1 >= el->el_line.limit) {
536 				idx = (cp - el->el_line.buffer);
537 				if (!ch_enlargebufs(el, 2))
538 					break;
539 				cp = &el->el_line.buffer[idx];
540 			}
541 			cp++;
542 			crlf = cp[-1] == '\r' || cp[-1] == '\n';
543 			if (el->el_flags & UNBUFFERED)
544 				break;
545 			if (crlf)
546 				break;
547 		}
548 
549 		if (num == -1) {
550 			if (errno == EINTR)
551 				cp = el->el_line.buffer;
552 			el->el_errno = errno;
553 		}
554 
555 		goto noedit;
556 	}
557 
558 	for (num = OKCMD; num == OKCMD;) {	/* while still editing this
559 						 * line */
560 #ifdef DEBUG_EDIT
561 		read_debug(el);
562 #endif /* DEBUG_EDIT */
563 		/* if EOF or error */
564 		if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) {
565 #ifdef DEBUG_READ
566 			(void) fprintf(el->el_errfile,
567 			    "Returning from el_gets %d\n", num);
568 #endif /* DEBUG_READ */
569 			break;
570 		}
571 		if (el->el_errno == EINTR) {
572 			el->el_line.buffer[0] = '\0';
573 			el->el_line.lastchar =
574 			    el->el_line.cursor = el->el_line.buffer;
575 			break;
576 		}
577 		if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) {	/* BUG CHECK command */
578 #ifdef DEBUG_EDIT
579 			(void) fprintf(el->el_errfile,
580 			    "ERROR: illegal command from key 0%o\r\n", ch);
581 #endif /* DEBUG_EDIT */
582 			continue;	/* try again */
583 		}
584 		/* now do the real command */
585 #ifdef DEBUG_READ
586 		{
587 			el_bindings_t *b;
588 			for (b = el->el_map.help; b->name; b++)
589 				if (b->func == cmdnum)
590 					break;
591 			if (b->name)
592 				(void) fprintf(el->el_errfile,
593 				    "Executing %s\n", b->name);
594 			else
595 				(void) fprintf(el->el_errfile,
596 				    "Error command = %d\n", cmdnum);
597 		}
598 #endif /* DEBUG_READ */
599 		/* vi redo needs these way down the levels... */
600 		el->el_state.thiscmd = cmdnum;
601 		el->el_state.thisch = ch;
602 		if (el->el_map.type == MAP_VI &&
603 		    el->el_map.current == el->el_map.key &&
604 		    el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) {
605 			if (cmdnum == VI_DELETE_PREV_CHAR &&
606 			    el->el_chared.c_redo.pos != el->el_chared.c_redo.buf
607 			    && Isprint(el->el_chared.c_redo.pos[-1]))
608 				el->el_chared.c_redo.pos--;
609 			else
610 				*el->el_chared.c_redo.pos++ = ch;
611 		}
612 		retval = (*el->el_map.func[cmdnum]) (el, ch);
613 #ifdef DEBUG_READ
614 		(void) fprintf(el->el_errfile,
615 			"Returned state %d\n", retval );
616 #endif /* DEBUG_READ */
617 
618 		/* save the last command here */
619 		el->el_state.lastcmd = cmdnum;
620 
621 		/* use any return value */
622 		switch (retval) {
623 		case CC_CURSOR:
624 			re_refresh_cursor(el);
625 			break;
626 
627 		case CC_REDISPLAY:
628 			re_clear_lines(el);
629 			re_clear_display(el);
630 			/* FALLTHROUGH */
631 
632 		case CC_REFRESH:
633 			re_refresh(el);
634 			break;
635 
636 		case CC_REFRESH_BEEP:
637 			re_refresh(el);
638 			term_beep(el);
639 			break;
640 
641 		case CC_NORM:	/* normal char */
642 			break;
643 
644 		case CC_ARGHACK:	/* Suggested by Rich Salz */
645 			/* <rsalz@pineapple.bbn.com> */
646 			continue;	/* keep going... */
647 
648 		case CC_EOF:	/* end of file typed */
649 			if ((el->el_flags & UNBUFFERED) == 0)
650 				num = 0;
651 			else if (num == -1) {
652 				*el->el_line.lastchar++ = CONTROL('d');
653 				el->el_line.cursor = el->el_line.lastchar;
654 				num = 1;
655 			}
656 			break;
657 
658 		case CC_NEWLINE:	/* normal end of line */
659 			num = (int)(el->el_line.lastchar - el->el_line.buffer);
660 			break;
661 
662 		case CC_FATAL:	/* fatal error, reset to known state */
663 #ifdef DEBUG_READ
664 			(void) fprintf(el->el_errfile,
665 			    "*** editor fatal ERROR ***\r\n\n");
666 #endif /* DEBUG_READ */
667 			/* put (real) cursor in a known place */
668 			re_clear_display(el);	/* reset the display stuff */
669 			ch_reset(el, 1);	/* reset the input pointers */
670 			re_refresh(el);	/* print the prompt again */
671 			break;
672 
673 		case CC_ERROR:
674 		default:	/* functions we don't know about */
675 #ifdef DEBUG_READ
676 			(void) fprintf(el->el_errfile,
677 			    "*** editor ERROR ***\r\n\n");
678 #endif /* DEBUG_READ */
679 			term_beep(el);
680 			term__flush(el);
681 			break;
682 		}
683 		el->el_state.argument = 1;
684 		el->el_state.doingarg = 0;
685 		el->el_chared.c_vcmd.action = NOP;
686 		if (el->el_flags & UNBUFFERED)
687 			break;
688 	}
689 
690 	term__flush(el);		/* flush any buffered output */
691 	/* make sure the tty is set up correctly */
692 	if ((el->el_flags & UNBUFFERED) == 0) {
693 		read_finish(el);
694 		*nread = num != -1 ? num : 0;
695 	} else {
696 		*nread = (int)(el->el_line.lastchar - el->el_line.buffer);
697 	}
698 	goto done;
699 noedit:
700 	el->el_line.cursor = el->el_line.lastchar = cp;
701 	*cp = '\0';
702 	*nread = (int)(el->el_line.cursor - el->el_line.buffer);
703 done:
704 	if (*nread == 0) {
705 		if (num == -1) {
706 			*nread = -1;
707 			errno = el->el_errno;
708 		}
709 		return NULL;
710 	} else
711 		return el->el_line.buffer;
712 }
713