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