1 /* $NetBSD: read.c,v 1.49 2009/03/10 20:46:15 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.49 2009/03/10 20:46:15 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 = ma->level--; i > 0; i--) 325 ma->macro[i - 1] = ma->macro[i]; 326 ma->offset = 0; 327 } 328 329 /* el_getc(): 330 * Read a character 331 */ 332 public int 333 el_getc(EditLine *el, char *cp) 334 { 335 int num_read; 336 c_macro_t *ma = &el->el_chared.c_macro; 337 338 term__flush(el); 339 for (;;) { 340 if (ma->level < 0) { 341 if (!read_preread(el)) 342 break; 343 } 344 345 if (ma->level < 0) 346 break; 347 348 if (ma->macro[0][ma->offset] == '\0') { 349 read_pop(ma); 350 continue; 351 } 352 353 *cp = ma->macro[0][ma->offset++] & 0377; 354 355 if (ma->macro[0][ma->offset] == '\0') { 356 /* Needed for QuoteMode On */ 357 read_pop(ma); 358 } 359 360 return (1); 361 } 362 363 #ifdef DEBUG_READ 364 (void) fprintf(el->el_errfile, "Turning raw mode on\n"); 365 #endif /* DEBUG_READ */ 366 if (tty_rawmode(el) < 0)/* make sure the tty is set up correctly */ 367 return (0); 368 369 #ifdef DEBUG_READ 370 (void) fprintf(el->el_errfile, "Reading a character\n"); 371 #endif /* DEBUG_READ */ 372 num_read = (*el->el_read.read_char)(el, cp); 373 #ifdef DEBUG_READ 374 (void) fprintf(el->el_errfile, "Got it %c\n", *cp); 375 #endif /* DEBUG_READ */ 376 return (num_read); 377 } 378 379 protected void 380 read_prepare(EditLine *el) 381 { 382 if (el->el_flags & HANDLE_SIGNALS) 383 sig_set(el); 384 if (el->el_flags & NO_TTY) 385 return; 386 if ((el->el_flags & (UNBUFFERED|EDIT_DISABLED)) == UNBUFFERED) 387 tty_rawmode(el); 388 389 /* This is relatively cheap, and things go terribly wrong if 390 we have the wrong size. */ 391 el_resize(el); 392 re_clear_display(el); /* reset the display stuff */ 393 ch_reset(el, 0); 394 re_refresh(el); /* print the prompt */ 395 396 if (el->el_flags & UNBUFFERED) 397 term__flush(el); 398 } 399 400 protected void 401 read_finish(EditLine *el) 402 { 403 if ((el->el_flags & UNBUFFERED) == 0) 404 (void) tty_cookedmode(el); 405 if (el->el_flags & HANDLE_SIGNALS) 406 sig_clr(el); 407 } 408 409 public const char * 410 el_gets(EditLine *el, int *nread) 411 { 412 int retval; 413 el_action_t cmdnum = 0; 414 int num; /* how many chars we have read at NL */ 415 char ch; 416 int crlf = 0; 417 int nrb; 418 #ifdef FIONREAD 419 c_macro_t *ma = &el->el_chared.c_macro; 420 #endif /* FIONREAD */ 421 422 if (nread == NULL) 423 nread = &nrb; 424 425 if (el->el_flags & NO_TTY) { 426 char *cp = el->el_line.buffer; 427 size_t idx; 428 429 while ((num = (*el->el_read.read_char)(el, cp)) == 1) { 430 /* make sure there is space for next character */ 431 if (cp + 1 >= el->el_line.limit) { 432 idx = (cp - el->el_line.buffer); 433 if (!ch_enlargebufs(el, 2)) 434 break; 435 cp = &el->el_line.buffer[idx]; 436 } 437 cp++; 438 if (el->el_flags & UNBUFFERED) 439 break; 440 if (cp[-1] == '\r' || cp[-1] == '\n') 441 break; 442 } 443 if (num == -1) { 444 if (errno == EINTR) 445 cp = el->el_line.buffer; 446 el->el_errno = errno; 447 } 448 449 el->el_line.cursor = el->el_line.lastchar = cp; 450 *cp = '\0'; 451 *nread = (int)(el->el_line.cursor - el->el_line.buffer); 452 goto done; 453 } 454 455 456 #ifdef FIONREAD 457 if (el->el_tty.t_mode == EX_IO && ma->level < 0) { 458 long chrs = 0; 459 460 (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); 461 if (chrs == 0) { 462 if (tty_rawmode(el) < 0) { 463 errno = 0; 464 *nread = 0; 465 return (NULL); 466 } 467 } 468 } 469 #endif /* FIONREAD */ 470 471 if ((el->el_flags & UNBUFFERED) == 0) 472 read_prepare(el); 473 474 if (el->el_flags & EDIT_DISABLED) { 475 char *cp; 476 size_t idx; 477 478 if ((el->el_flags & UNBUFFERED) == 0) 479 cp = el->el_line.buffer; 480 else 481 cp = el->el_line.lastchar; 482 483 term__flush(el); 484 485 while ((num = (*el->el_read.read_char)(el, cp)) == 1) { 486 /* make sure there is space next character */ 487 if (cp + 1 >= el->el_line.limit) { 488 idx = (cp - el->el_line.buffer); 489 if (!ch_enlargebufs(el, 2)) 490 break; 491 cp = &el->el_line.buffer[idx]; 492 } 493 cp++; 494 crlf = cp[-1] == '\r' || cp[-1] == '\n'; 495 if (el->el_flags & UNBUFFERED) 496 break; 497 if (crlf) 498 break; 499 } 500 501 if (num == -1) { 502 if (errno == EINTR) 503 cp = el->el_line.buffer; 504 el->el_errno = errno; 505 } 506 507 el->el_line.cursor = el->el_line.lastchar = cp; 508 *cp = '\0'; 509 goto done; 510 } 511 512 for (num = OKCMD; num == OKCMD;) { /* while still editing this 513 * line */ 514 #ifdef DEBUG_EDIT 515 read_debug(el); 516 #endif /* DEBUG_EDIT */ 517 /* if EOF or error */ 518 if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) { 519 #ifdef DEBUG_READ 520 (void) fprintf(el->el_errfile, 521 "Returning from el_gets %d\n", num); 522 #endif /* DEBUG_READ */ 523 break; 524 } 525 if (el->el_errno == EINTR) { 526 el->el_line.buffer[0] = '\0'; 527 el->el_line.lastchar = 528 el->el_line.cursor = el->el_line.buffer; 529 break; 530 } 531 if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) { /* BUG CHECK command */ 532 #ifdef DEBUG_EDIT 533 (void) fprintf(el->el_errfile, 534 "ERROR: illegal command from key 0%o\r\n", ch); 535 #endif /* DEBUG_EDIT */ 536 continue; /* try again */ 537 } 538 /* now do the real command */ 539 #ifdef DEBUG_READ 540 { 541 el_bindings_t *b; 542 for (b = el->el_map.help; b->name; b++) 543 if (b->func == cmdnum) 544 break; 545 if (b->name) 546 (void) fprintf(el->el_errfile, 547 "Executing %s\n", b->name); 548 else 549 (void) fprintf(el->el_errfile, 550 "Error command = %d\n", cmdnum); 551 } 552 #endif /* DEBUG_READ */ 553 /* vi redo needs these way down the levels... */ 554 el->el_state.thiscmd = cmdnum; 555 el->el_state.thisch = ch; 556 if (el->el_map.type == MAP_VI && 557 el->el_map.current == el->el_map.key && 558 el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { 559 if (cmdnum == VI_DELETE_PREV_CHAR && 560 el->el_chared.c_redo.pos != el->el_chared.c_redo.buf 561 && isprint((unsigned char)el->el_chared.c_redo.pos[-1])) 562 el->el_chared.c_redo.pos--; 563 else 564 *el->el_chared.c_redo.pos++ = ch; 565 } 566 retval = (*el->el_map.func[cmdnum]) (el, ch); 567 #ifdef DEBUG_READ 568 (void) fprintf(el->el_errfile, 569 "Returned state %d\n", retval ); 570 #endif /* DEBUG_READ */ 571 572 /* save the last command here */ 573 el->el_state.lastcmd = cmdnum; 574 575 /* use any return value */ 576 switch (retval) { 577 case CC_CURSOR: 578 re_refresh_cursor(el); 579 break; 580 581 case CC_REDISPLAY: 582 re_clear_lines(el); 583 re_clear_display(el); 584 /* FALLTHROUGH */ 585 586 case CC_REFRESH: 587 re_refresh(el); 588 break; 589 590 case CC_REFRESH_BEEP: 591 re_refresh(el); 592 term_beep(el); 593 break; 594 595 case CC_NORM: /* normal char */ 596 break; 597 598 case CC_ARGHACK: /* Suggested by Rich Salz */ 599 /* <rsalz@pineapple.bbn.com> */ 600 continue; /* keep going... */ 601 602 case CC_EOF: /* end of file typed */ 603 if ((el->el_flags & UNBUFFERED) == 0) 604 num = 0; 605 else if (num == -1) { 606 *el->el_line.lastchar++ = CONTROL('d'); 607 el->el_line.cursor = el->el_line.lastchar; 608 num = 1; 609 } 610 break; 611 612 case CC_NEWLINE: /* normal end of line */ 613 num = (int)(el->el_line.lastchar - el->el_line.buffer); 614 break; 615 616 case CC_FATAL: /* fatal error, reset to known state */ 617 #ifdef DEBUG_READ 618 (void) fprintf(el->el_errfile, 619 "*** editor fatal ERROR ***\r\n\n"); 620 #endif /* DEBUG_READ */ 621 /* put (real) cursor in a known place */ 622 re_clear_display(el); /* reset the display stuff */ 623 ch_reset(el, 1); /* reset the input pointers */ 624 re_refresh(el); /* print the prompt again */ 625 break; 626 627 case CC_ERROR: 628 default: /* functions we don't know about */ 629 #ifdef DEBUG_READ 630 (void) fprintf(el->el_errfile, 631 "*** editor ERROR ***\r\n\n"); 632 #endif /* DEBUG_READ */ 633 term_beep(el); 634 term__flush(el); 635 break; 636 } 637 el->el_state.argument = 1; 638 el->el_state.doingarg = 0; 639 el->el_chared.c_vcmd.action = NOP; 640 if (el->el_flags & UNBUFFERED) 641 break; 642 } 643 644 term__flush(el); /* flush any buffered output */ 645 /* make sure the tty is set up correctly */ 646 if ((el->el_flags & UNBUFFERED) == 0) { 647 read_finish(el); 648 *nread = num != -1 ? num : 0; 649 } else { 650 *nread = (int)(el->el_line.lastchar - el->el_line.buffer); 651 } 652 done: 653 if (*nread == 0) { 654 if (num == -1) { 655 *nread = -1; 656 errno = el->el_errno; 657 } 658 return NULL; 659 } else 660 return el->el_line.buffer; 661 } 662