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