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