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