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