xref: /freebsd-12.1/lib/libedit/read.c (revision dfd1ff19)
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)
36 static char sccsid[] = "@(#)read.c	8.1 (Berkeley) 6/4/93";
37 #endif /* not lint && not SCCSID */
38 #include <sys/cdefs.h>
39 __FBSDID("$FreeBSD$");
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 
54 private int	read__fixio(int, int);
55 private int	read_preread(EditLine *);
56 private int	read_char(EditLine *, char *);
57 private int	read_getcmd(EditLine *, el_action_t *, char *);
58 
59 /* read_init():
60  *	Initialize the read stuff
61  */
62 protected int
63 read_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  */
75 protected int
76 el_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  */
87 protected el_rfunc_t
88 el_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
100 private void
101 read_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 */
122 private int
123 read__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  */
183 private int
184 read_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  */
212 public void
213 el_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  */
231 private int
232 read_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  */
285 private int
286 read_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  */
306 public int
307 el_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 
351 protected void
352 read_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 
372 protected void
373 read_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 
381 public const char *
382 el_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 			/* <[email protected]> */
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