1 /* $NetBSD: read.c,v 1.51 2009/06/09 13:04:33 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.51 2009/06/09 13:04:33 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 426 if (el->el_flags & NO_TTY) { 427 char *cp = el->el_line.buffer; 428 size_t idx; 429 430 while ((num = (*el->el_read.read_char)(el, cp)) == 1) { 431 /* make sure there is space for next character */ 432 if (cp + 1 >= el->el_line.limit) { 433 idx = (cp - el->el_line.buffer); 434 if (!ch_enlargebufs(el, 2)) 435 break; 436 cp = &el->el_line.buffer[idx]; 437 } 438 cp++; 439 if (el->el_flags & UNBUFFERED) 440 break; 441 if (cp[-1] == '\r' || cp[-1] == '\n') 442 break; 443 } 444 if (num == -1) { 445 if (errno == EINTR) 446 cp = el->el_line.buffer; 447 el->el_errno = errno; 448 } 449 450 el->el_line.cursor = el->el_line.lastchar = cp; 451 *cp = '\0'; 452 *nread = (int)(el->el_line.cursor - el->el_line.buffer); 453 goto done; 454 } 455 456 457 #ifdef FIONREAD 458 if (el->el_tty.t_mode == EX_IO && ma->level < 0) { 459 long chrs = 0; 460 461 (void) ioctl(el->el_infd, FIONREAD, (ioctl_t) & chrs); 462 if (chrs == 0) { 463 if (tty_rawmode(el) < 0) { 464 errno = 0; 465 *nread = 0; 466 return (NULL); 467 } 468 } 469 } 470 #endif /* FIONREAD */ 471 472 if ((el->el_flags & UNBUFFERED) == 0) 473 read_prepare(el); 474 475 if (el->el_flags & EDIT_DISABLED) { 476 char *cp; 477 size_t idx; 478 479 if ((el->el_flags & UNBUFFERED) == 0) 480 cp = el->el_line.buffer; 481 else 482 cp = el->el_line.lastchar; 483 484 term__flush(el); 485 486 while ((num = (*el->el_read.read_char)(el, cp)) == 1) { 487 /* make sure there is space next character */ 488 if (cp + 1 >= el->el_line.limit) { 489 idx = (cp - el->el_line.buffer); 490 if (!ch_enlargebufs(el, 2)) 491 break; 492 cp = &el->el_line.buffer[idx]; 493 } 494 cp++; 495 crlf = cp[-1] == '\r' || cp[-1] == '\n'; 496 if (el->el_flags & UNBUFFERED) 497 break; 498 if (crlf) 499 break; 500 } 501 502 if (num == -1) { 503 if (errno == EINTR) 504 cp = el->el_line.buffer; 505 el->el_errno = errno; 506 } 507 508 el->el_line.cursor = el->el_line.lastchar = cp; 509 *cp = '\0'; 510 goto done; 511 } 512 513 for (num = OKCMD; num == OKCMD;) { /* while still editing this 514 * line */ 515 #ifdef DEBUG_EDIT 516 read_debug(el); 517 #endif /* DEBUG_EDIT */ 518 /* if EOF or error */ 519 if ((num = read_getcmd(el, &cmdnum, &ch)) != OKCMD) { 520 #ifdef DEBUG_READ 521 (void) fprintf(el->el_errfile, 522 "Returning from el_gets %d\n", num); 523 #endif /* DEBUG_READ */ 524 break; 525 } 526 if (el->el_errno == EINTR) { 527 el->el_line.buffer[0] = '\0'; 528 el->el_line.lastchar = 529 el->el_line.cursor = el->el_line.buffer; 530 break; 531 } 532 if ((unsigned int)cmdnum >= (unsigned int)el->el_map.nfunc) { /* BUG CHECK command */ 533 #ifdef DEBUG_EDIT 534 (void) fprintf(el->el_errfile, 535 "ERROR: illegal command from key 0%o\r\n", ch); 536 #endif /* DEBUG_EDIT */ 537 continue; /* try again */ 538 } 539 /* now do the real command */ 540 #ifdef DEBUG_READ 541 { 542 el_bindings_t *b; 543 for (b = el->el_map.help; b->name; b++) 544 if (b->func == cmdnum) 545 break; 546 if (b->name) 547 (void) fprintf(el->el_errfile, 548 "Executing %s\n", b->name); 549 else 550 (void) fprintf(el->el_errfile, 551 "Error command = %d\n", cmdnum); 552 } 553 #endif /* DEBUG_READ */ 554 /* vi redo needs these way down the levels... */ 555 el->el_state.thiscmd = cmdnum; 556 el->el_state.thisch = ch; 557 if (el->el_map.type == MAP_VI && 558 el->el_map.current == el->el_map.key && 559 el->el_chared.c_redo.pos < el->el_chared.c_redo.lim) { 560 if (cmdnum == VI_DELETE_PREV_CHAR && 561 el->el_chared.c_redo.pos != el->el_chared.c_redo.buf 562 && isprint((unsigned char)el->el_chared.c_redo.pos[-1])) 563 el->el_chared.c_redo.pos--; 564 else 565 *el->el_chared.c_redo.pos++ = ch; 566 } 567 retval = (*el->el_map.func[cmdnum]) (el, ch); 568 #ifdef DEBUG_READ 569 (void) fprintf(el->el_errfile, 570 "Returned state %d\n", retval ); 571 #endif /* DEBUG_READ */ 572 573 /* save the last command here */ 574 el->el_state.lastcmd = cmdnum; 575 576 /* use any return value */ 577 switch (retval) { 578 case CC_CURSOR: 579 re_refresh_cursor(el); 580 break; 581 582 case CC_REDISPLAY: 583 re_clear_lines(el); 584 re_clear_display(el); 585 /* FALLTHROUGH */ 586 587 case CC_REFRESH: 588 re_refresh(el); 589 break; 590 591 case CC_REFRESH_BEEP: 592 re_refresh(el); 593 term_beep(el); 594 break; 595 596 case CC_NORM: /* normal char */ 597 break; 598 599 case CC_ARGHACK: /* Suggested by Rich Salz */ 600 /* <rsalz@pineapple.bbn.com> */ 601 continue; /* keep going... */ 602 603 case CC_EOF: /* end of file typed */ 604 if ((el->el_flags & UNBUFFERED) == 0) 605 num = 0; 606 else if (num == -1) { 607 *el->el_line.lastchar++ = CONTROL('d'); 608 el->el_line.cursor = el->el_line.lastchar; 609 num = 1; 610 } 611 break; 612 613 case CC_NEWLINE: /* normal end of line */ 614 num = (int)(el->el_line.lastchar - el->el_line.buffer); 615 break; 616 617 case CC_FATAL: /* fatal error, reset to known state */ 618 #ifdef DEBUG_READ 619 (void) fprintf(el->el_errfile, 620 "*** editor fatal ERROR ***\r\n\n"); 621 #endif /* DEBUG_READ */ 622 /* put (real) cursor in a known place */ 623 re_clear_display(el); /* reset the display stuff */ 624 ch_reset(el, 1); /* reset the input pointers */ 625 re_refresh(el); /* print the prompt again */ 626 break; 627 628 case CC_ERROR: 629 default: /* functions we don't know about */ 630 #ifdef DEBUG_READ 631 (void) fprintf(el->el_errfile, 632 "*** editor ERROR ***\r\n\n"); 633 #endif /* DEBUG_READ */ 634 term_beep(el); 635 term__flush(el); 636 break; 637 } 638 el->el_state.argument = 1; 639 el->el_state.doingarg = 0; 640 el->el_chared.c_vcmd.action = NOP; 641 if (el->el_flags & UNBUFFERED) 642 break; 643 } 644 645 term__flush(el); /* flush any buffered output */ 646 /* make sure the tty is set up correctly */ 647 if ((el->el_flags & UNBUFFERED) == 0) { 648 read_finish(el); 649 *nread = num != -1 ? num : 0; 650 } else { 651 *nread = (int)(el->el_line.lastchar - el->el_line.buffer); 652 } 653 done: 654 if (*nread == 0) { 655 if (num == -1) { 656 *nread = -1; 657 errno = el->el_errno; 658 } 659 return NULL; 660 } else 661 return el->el_line.buffer; 662 } 663