read.c revision 296435
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 38static 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: head/lib/libedit/read.c 296435 2016-03-06 21:32:54Z pfg $"); 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 59private int read__fixio(int, int); 60private int read_preread(EditLine *); 61private int read_char(EditLine *, Char *); 62private int read_getcmd(EditLine *, el_action_t *, Char *); 63private void read_pop(c_macro_t *); 64 65/* read_init(): 66 * Initialize the read stuff 67 */ 68protected int 69read_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 */ 81protected int 82el_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 */ 93protected el_rfunc_t 94el_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 106private void 107read_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 */ 128private int 129read__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 */ 189private int 190read_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 */ 221public void 222FUN(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 */ 241private int 242read_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 */ 303private int 304utf8_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 */ 314private int 315read_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 */ 386private void 387read_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 */ 401public int 402FUN(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 454protected void 455read_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 475protected void 476read_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 484public const Char * 485FUN(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; 724noedit: 725 el->el_line.cursor = el->el_line.lastchar = cp; 726 *cp = '\0'; 727 *nread = (int)(el->el_line.cursor - el->el_line.buffer); 728done: 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