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