rltty.c revision 26497
1/* rltty.c -- functions to prepare and restore the terminal for readline's 2 use. */ 3 4/* Copyright (C) 1992 Free Software Foundation, Inc. 5 6 This file is part of the GNU Readline Library, a library for 7 reading lines of text with interactive input and history editing. 8 9 The GNU Readline Library is free software; you can redistribute it 10 and/or modify it under the terms of the GNU General Public License 11 as published by the Free Software Foundation; either version 1, or 12 (at your option) any later version. 13 14 The GNU Readline Library is distributed in the hope that it will be 15 useful, but WITHOUT ANY WARRANTY; without even the implied warranty 16 of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18 19 The GNU General Public License is often shipped with GNU software, and 20 is generally kept in a file called COPYING or LICENSE. If you do not 21 have a copy of the license, write to the Free Software Foundation, 22 675 Mass Ave, Cambridge, MA 02139, USA. */ 23#define READLINE_LIBRARY 24 25#if defined (HAVE_CONFIG_H) 26# include <config.h> 27#endif 28 29#include <sys/types.h> 30#include <signal.h> 31#include <errno.h> 32#include <stdio.h> 33 34#if defined (HAVE_UNISTD_H) 35# include <unistd.h> 36#endif /* HAVE_UNISTD_H */ 37 38#include "rldefs.h" 39 40#if !defined (SHELL) && defined (GWINSZ_IN_SYS_IOCTL) 41# include <sys/ioctl.h> 42#endif /* !SHELL && GWINSZ_IN_SYS_IOCTL */ 43 44#include "rltty.h" 45#include "readline.h" 46 47#if !defined (errno) 48extern int errno; 49#endif /* !errno */ 50 51extern int readline_echoing_p; 52extern int _rl_eof_char; 53 54extern int _rl_enable_keypad, _rl_enable_meta; 55 56extern void _rl_control_keypad (); 57 58#if defined (__GO32__) 59# include <pc.h> 60# undef HANDLE_SIGNALS 61#endif /* __GO32__ */ 62 63/* Indirect functions to allow apps control over terminal management. */ 64extern void rl_prep_terminal (), rl_deprep_terminal (); 65 66VFunction *rl_prep_term_function = rl_prep_terminal; 67VFunction *rl_deprep_term_function = rl_deprep_terminal; 68 69/* **************************************************************** */ 70/* */ 71/* Signal Management */ 72/* */ 73/* **************************************************************** */ 74 75#if defined (HAVE_POSIX_SIGNALS) 76static sigset_t sigint_set, sigint_oset; 77#else /* !HAVE_POSIX_SIGNALS */ 78# if defined (HAVE_BSD_SIGNALS) 79static int sigint_oldmask; 80# endif /* HAVE_BSD_SIGNALS */ 81#endif /* !HAVE_POSIX_SIGNALS */ 82 83static int sigint_blocked; 84 85/* Cause SIGINT to not be delivered until the corresponding call to 86 release_sigint(). */ 87static void 88block_sigint () 89{ 90 if (sigint_blocked) 91 return; 92 93#if defined (HAVE_POSIX_SIGNALS) 94 sigemptyset (&sigint_set); 95 sigemptyset (&sigint_oset); 96 sigaddset (&sigint_set, SIGINT); 97 sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset); 98#else /* !HAVE_POSIX_SIGNALS */ 99# if defined (HAVE_BSD_SIGNALS) 100 sigint_oldmask = sigblock (sigmask (SIGINT)); 101# else /* !HAVE_BSD_SIGNALS */ 102# if defined (HAVE_USG_SIGHOLD) 103 sighold (SIGINT); 104# endif /* HAVE_USG_SIGHOLD */ 105# endif /* !HAVE_BSD_SIGNALS */ 106#endif /* !HAVE_POSIX_SIGNALS */ 107 sigint_blocked = 1; 108} 109 110/* Allow SIGINT to be delivered. */ 111static void 112release_sigint () 113{ 114 if (!sigint_blocked) 115 return; 116 117#if defined (HAVE_POSIX_SIGNALS) 118 sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL); 119#else 120# if defined (HAVE_BSD_SIGNALS) 121 sigsetmask (sigint_oldmask); 122# else /* !HAVE_BSD_SIGNALS */ 123# if defined (HAVE_USG_SIGHOLD) 124 sigrelse (SIGINT); 125# endif /* HAVE_USG_SIGHOLD */ 126# endif /* !HAVE_BSD_SIGNALS */ 127#endif /* !HAVE_POSIX_SIGNALS */ 128 129 sigint_blocked = 0; 130} 131 132/* **************************************************************** */ 133/* */ 134/* Saving and Restoring the TTY */ 135/* */ 136/* **************************************************************** */ 137 138/* Non-zero means that the terminal is in a prepped state. */ 139static int terminal_prepped; 140 141/* If non-zero, means that this process has called tcflow(fd, TCOOFF) 142 and output is suspended. */ 143#if defined (__ksr1__) 144static int ksrflow; 145#endif 146 147#if !defined (SHELL) && defined (TIOCGWINSZ) 148/* Dummy call to force a backgrounded readline to stop before it tries 149 to get the tty settings. */ 150static void 151set_winsize (tty) 152 int tty; 153{ 154 struct winsize w; 155 156 if (ioctl (tty, TIOCGWINSZ, &w) == 0) 157 (void) ioctl (tty, TIOCSWINSZ, &w); 158} 159#else /* SHELL || !TIOCGWINSZ */ 160# define set_winsize(tty) 161#endif /* SHELL || !TIOCGWINSZ */ 162 163#if defined (NEW_TTY_DRIVER) 164 165/* Values for the `flags' field of a struct bsdtty. This tells which 166 elements of the struct bsdtty have been fetched from the system and 167 are valid. */ 168#define SGTTY_SET 0x01 169#define LFLAG_SET 0x02 170#define TCHARS_SET 0x04 171#define LTCHARS_SET 0x08 172 173struct bsdtty { 174 struct sgttyb sgttyb; /* Basic BSD tty driver information. */ 175 int lflag; /* Local mode flags, like LPASS8. */ 176#if defined (TIOCGETC) 177 struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */ 178#endif 179#if defined (TIOCGLTC) 180 struct ltchars ltchars; /* 4.2 BSD editing characters */ 181#endif 182 int flags; /* Bitmap saying which parts of the struct are valid. */ 183}; 184 185#define TIOTYPE struct bsdtty 186 187static TIOTYPE otio; 188 189static int 190get_tty_settings (tty, tiop) 191 int tty; 192 TIOTYPE *tiop; 193{ 194 set_winsize (tty); 195 196 tiop->flags = tiop->lflag = 0; 197 198 ioctl (tty, TIOCGETP, &(tiop->sgttyb)); 199 tiop->flags |= SGTTY_SET; 200 201#if defined (TIOCLGET) 202 ioctl (tty, TIOCLGET, &(tiop->lflag)); 203 tiop->flags |= LFLAG_SET; 204#endif 205 206#if defined (TIOCGETC) 207 ioctl (tty, TIOCGETC, &(tiop->tchars)); 208 tiop->flags |= TCHARS_SET; 209#endif 210 211#if defined (TIOCGLTC) 212 ioctl (tty, TIOCGLTC, &(tiop->ltchars)); 213 tiop->flags |= LTCHARS_SET; 214#endif 215 216 return 0; 217} 218 219static int 220set_tty_settings (tty, tiop) 221 int tty; 222 TIOTYPE *tiop; 223{ 224 if (tiop->flags & SGTTY_SET) 225 { 226 ioctl (tty, TIOCSETN, &(tiop->sgttyb)); 227 tiop->flags &= ~SGTTY_SET; 228 } 229 readline_echoing_p = 1; 230 231#if defined (TIOCLSET) 232 if (tiop->flags & LFLAG_SET) 233 { 234 ioctl (tty, TIOCLSET, &(tiop->lflag)); 235 tiop->flags &= ~LFLAG_SET; 236 } 237#endif 238 239#if defined (TIOCSETC) 240 if (tiop->flags & TCHARS_SET) 241 { 242 ioctl (tty, TIOCSETC, &(tiop->tchars)); 243 tiop->flags &= ~TCHARS_SET; 244 } 245#endif 246 247#if defined (TIOCSLTC) 248 if (tiop->flags & LTCHARS_SET) 249 { 250 ioctl (tty, TIOCSLTC, &(tiop->ltchars)); 251 tiop->flags &= ~LTCHARS_SET; 252 } 253#endif 254 255 return 0; 256} 257 258static void 259prepare_terminal_settings (meta_flag, otio, tiop) 260 int meta_flag; 261 TIOTYPE otio, *tiop; 262{ 263#if !defined (__GO32__) 264 readline_echoing_p = (otio.sgttyb.sg_flags & ECHO); 265 266 /* Copy the original settings to the structure we're going to use for 267 our settings. */ 268 tiop->sgttyb = otio.sgttyb; 269 tiop->lflag = otio.lflag; 270#if defined (TIOCGETC) 271 tiop->tchars = otio.tchars; 272#endif 273#if defined (TIOCGLTC) 274 tiop->ltchars = otio.ltchars; 275#endif 276 tiop->flags = otio.flags; 277 278 /* First, the basic settings to put us into character-at-a-time, no-echo 279 input mode. */ 280 tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD); 281 tiop->sgttyb.sg_flags |= CBREAK; 282 283 /* If this terminal doesn't care how the 8th bit is used, then we can 284 use it for the meta-key. If only one of even or odd parity is 285 specified, then the terminal is using parity, and we cannot. */ 286#if !defined (ANYP) 287# define ANYP (EVENP | ODDP) 288#endif 289 if (((otio.sgttyb.sg_flags & ANYP) == ANYP) || 290 ((otio.sgttyb.sg_flags & ANYP) == 0)) 291 { 292 tiop->sgttyb.sg_flags |= ANYP; 293 294 /* Hack on local mode flags if we can. */ 295#if defined (TIOCLGET) 296# if defined (LPASS8) 297 tiop->lflag |= LPASS8; 298# endif /* LPASS8 */ 299#endif /* TIOCLGET */ 300 } 301 302#if defined (TIOCGETC) 303# if defined (USE_XON_XOFF) 304 /* Get rid of terminal output start and stop characters. */ 305 tiop->tchars.t_stopc = -1; /* C-s */ 306 tiop->tchars.t_startc = -1; /* C-q */ 307 308 /* If there is an XON character, bind it to restart the output. */ 309 if (otio.tchars.t_startc != -1) 310 rl_bind_key (otio.tchars.t_startc, rl_restart_output); 311# endif /* USE_XON_XOFF */ 312 313 /* If there is an EOF char, bind _rl_eof_char to it. */ 314 if (otio.tchars.t_eofc != -1) 315 _rl_eof_char = otio.tchars.t_eofc; 316 317# if defined (NO_KILL_INTR) 318 /* Get rid of terminal-generated SIGQUIT and SIGINT. */ 319 tiop->tchars.t_quitc = -1; /* C-\ */ 320 tiop->tchars.t_intrc = -1; /* C-c */ 321# endif /* NO_KILL_INTR */ 322#endif /* TIOCGETC */ 323 324#if defined (TIOCGLTC) 325 /* Make the interrupt keys go away. Just enough to make people happy. */ 326 tiop->ltchars.t_dsuspc = -1; /* C-y */ 327 tiop->ltchars.t_lnextc = -1; /* C-v */ 328#endif /* TIOCGLTC */ 329#endif /* !__GO32__ */ 330} 331 332#else /* !defined (NEW_TTY_DRIVER) */ 333 334#if !defined (VMIN) 335# define VMIN VEOF 336#endif 337 338#if !defined (VTIME) 339# define VTIME VEOL 340#endif 341 342#if defined (TERMIOS_TTY_DRIVER) 343# define TIOTYPE struct termios 344# define DRAIN_OUTPUT(fd) tcdrain (fd) 345# define GETATTR(tty, tiop) (tcgetattr (tty, tiop)) 346# ifdef M_UNIX 347# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop)) 348# else 349# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop)) 350# endif /* !M_UNIX */ 351#else 352# define TIOTYPE struct termio 353# define DRAIN_OUTPUT(fd) 354# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop)) 355# define SETATTR(tty, tiop) (ioctl (tty, TCSETA, tiop)) 356#endif /* !TERMIOS_TTY_DRIVER */ 357 358static TIOTYPE otio; 359 360#if defined (FLUSHO) 361# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO) 362#else 363# define OUTPUT_BEING_FLUSHED(tp) 0 364#endif 365 366static void 367rltty_warning (msg) 368 char *msg; 369{ 370 fprintf (stderr, "readline: warning: %s\n", msg); 371} 372 373#if defined (_AIX) 374void 375setopost(tp) 376TIOTYPE *tp; 377{ 378 if ((tp->c_oflag & OPOST) == 0) 379 { 380 rltty_warning ("turning on OPOST for terminal\r"); 381 tp->c_oflag |= OPOST|ONLCR; 382 } 383} 384#endif 385 386static int 387get_tty_settings (tty, tiop) 388 int tty; 389 TIOTYPE *tiop; 390{ 391 int ioctl_ret; 392 set_winsize (tty); 393 394 while (1) 395 { 396 ioctl_ret = GETATTR (tty, tiop); 397 if (ioctl_ret < 0) 398 { 399 if (errno != EINTR) 400 return -1; 401 else 402 continue; 403 } 404 if (OUTPUT_BEING_FLUSHED (tiop)) 405 { 406#if defined (FLUSHO) && defined (_AIX41) 407 rltty_warning ("turning off output flushing"); 408 tiop->c_lflag &= ~FLUSHO; 409 break; 410#else 411 continue; 412#endif 413 } 414 break; 415 } 416 417#if defined (_AIX) 418 setopost(tiop); 419#endif 420 421 return 0; 422} 423 424static int 425set_tty_settings (tty, tiop) 426 int tty; 427 TIOTYPE *tiop; 428{ 429 while (SETATTR (tty, tiop) < 0) 430 { 431 if (errno != EINTR) 432 return -1; 433 errno = 0; 434 } 435 436#if 0 437 438#if defined (TERMIOS_TTY_DRIVER) 439# if defined (__ksr1__) 440 if (ksrflow) 441 { 442 ksrflow = 0; 443 tcflow (tty, TCOON); 444 } 445# else /* !ksr1 */ 446 tcflow (tty, TCOON); /* Simulate a ^Q. */ 447# endif /* !ksr1 */ 448#else 449 ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */ 450#endif /* !TERMIOS_TTY_DRIVER */ 451 452#endif 453 454 return 0; 455} 456 457static void 458prepare_terminal_settings (meta_flag, otio, tiop) 459 int meta_flag; 460 TIOTYPE otio, *tiop; 461{ 462 readline_echoing_p = (otio.c_lflag & ECHO); 463 464 tiop->c_lflag &= ~(ICANON | ECHO); 465 466 if ((unsigned char) otio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE) 467 _rl_eof_char = otio.c_cc[VEOF]; 468 469#if defined (USE_XON_XOFF) 470#if defined (IXANY) 471 tiop->c_iflag &= ~(IXON | IXOFF | IXANY); 472#else 473 /* `strict' Posix systems do not define IXANY. */ 474 tiop->c_iflag &= ~(IXON | IXOFF); 475#endif /* IXANY */ 476#endif /* USE_XON_XOFF */ 477 478 /* Only turn this off if we are using all 8 bits. */ 479 if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag) 480 tiop->c_iflag &= ~(ISTRIP | INPCK); 481 482 /* Make sure we differentiate between CR and NL on input. */ 483 tiop->c_iflag &= ~(ICRNL | INLCR); 484 485#if !defined (HANDLE_SIGNALS) 486 tiop->c_lflag &= ~ISIG; 487#else 488 tiop->c_lflag |= ISIG; 489#endif 490 491 tiop->c_cc[VMIN] = 1; 492 tiop->c_cc[VTIME] = 0; 493 494#if defined (FLUSHO) 495 if (OUTPUT_BEING_FLUSHED (tiop)) 496 { 497 tiop->c_lflag &= ~FLUSHO; 498 otio.c_lflag &= ~FLUSHO; 499 } 500#endif 501 502 /* Turn off characters that we need on Posix systems with job control, 503 just to be sure. This includes ^Y and ^V. This should not really 504 be necessary. */ 505#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE) 506 507#if defined (VLNEXT) 508 tiop->c_cc[VLNEXT] = _POSIX_VDISABLE; 509#endif 510 511#if defined (VDSUSP) 512 tiop->c_cc[VDSUSP] = _POSIX_VDISABLE; 513#endif 514 515#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */ 516} 517#endif /* NEW_TTY_DRIVER */ 518 519/* Put the terminal in CBREAK mode so that we can detect key presses. */ 520void 521rl_prep_terminal (meta_flag) 522 int meta_flag; 523{ 524#if !defined (__GO32__) 525 int tty; 526 TIOTYPE tio; 527 528 if (terminal_prepped) 529 return; 530 531 /* Try to keep this function from being INTerrupted. */ 532 block_sigint (); 533 534 tty = fileno (rl_instream); 535 536 if (get_tty_settings (tty, &tio) < 0) 537 { 538 release_sigint (); 539 return; 540 } 541 542 otio = tio; 543 544 prepare_terminal_settings (meta_flag, otio, &tio); 545 546 if (set_tty_settings (tty, &tio) < 0) 547 { 548 release_sigint (); 549 return; 550 } 551 552 if (_rl_enable_keypad) 553 _rl_control_keypad (1); 554 555 fflush (rl_outstream); 556 terminal_prepped = 1; 557 558 release_sigint (); 559#endif /* !__GO32__ */ 560} 561 562/* Restore the terminal's normal settings and modes. */ 563void 564rl_deprep_terminal () 565{ 566#if !defined (__GO32__) 567 int tty; 568 569 if (!terminal_prepped) 570 return; 571 572 /* Try to keep this function from being interrupted. */ 573 block_sigint (); 574 575 tty = fileno (rl_instream); 576 577 if (_rl_enable_keypad) 578 _rl_control_keypad (0); 579 580 fflush (rl_outstream); 581 582 if (set_tty_settings (tty, &otio) < 0) 583 { 584 release_sigint (); 585 return; 586 } 587 588 terminal_prepped = 0; 589 590 release_sigint (); 591#endif /* !__GO32__ */ 592} 593 594/* **************************************************************** */ 595/* */ 596/* Bogus Flow Control */ 597/* */ 598/* **************************************************************** */ 599 600int 601rl_restart_output (count, key) 602 int count, key; 603{ 604 int fildes = fileno (rl_outstream); 605#if defined (TIOCSTART) 606#if defined (apollo) 607 ioctl (&fildes, TIOCSTART, 0); 608#else 609 ioctl (fildes, TIOCSTART, 0); 610#endif /* apollo */ 611 612#else /* !TIOCSTART */ 613# if defined (TERMIOS_TTY_DRIVER) 614# if defined (__ksr1__) 615 if (ksrflow) 616 { 617 ksrflow = 0; 618 tcflow (fildes, TCOON); 619 } 620# else /* !ksr1 */ 621 tcflow (fildes, TCOON); /* Simulate a ^Q. */ 622# endif /* !ksr1 */ 623# else /* !TERMIOS_TTY_DRIVER */ 624# if defined (TCXONC) 625 ioctl (fildes, TCXONC, TCOON); 626# endif /* TCXONC */ 627# endif /* !TERMIOS_TTY_DRIVER */ 628#endif /* !TIOCSTART */ 629 630 return 0; 631} 632 633int 634rl_stop_output (count, key) 635 int count, key; 636{ 637 int fildes = fileno (rl_instream); 638 639#if defined (TIOCSTOP) 640# if defined (apollo) 641 ioctl (&fildes, TIOCSTOP, 0); 642# else 643 ioctl (fildes, TIOCSTOP, 0); 644# endif /* apollo */ 645#else /* !TIOCSTOP */ 646# if defined (TERMIOS_TTY_DRIVER) 647# if defined (__ksr1__) 648 ksrflow = 1; 649# endif /* ksr1 */ 650 tcflow (fildes, TCOOFF); 651# else 652# if defined (TCXONC) 653 ioctl (fildes, TCXONC, TCOON); 654# endif /* TCXONC */ 655# endif /* !TERMIOS_TTY_DRIVER */ 656#endif /* !TIOCSTOP */ 657 658 return 0; 659} 660 661/* **************************************************************** */ 662/* */ 663/* Default Key Bindings */ 664/* */ 665/* **************************************************************** */ 666void 667rltty_set_default_bindings (kmap) 668 Keymap kmap; 669{ 670 TIOTYPE ttybuff; 671 int tty = fileno (rl_instream); 672 673#if defined (NEW_TTY_DRIVER) 674 675#define SET_SPECIAL(sc, func) \ 676 do \ 677 { \ 678 int ic; \ 679 ic = sc; \ 680 if (ic != -1 && kmap[ic].type == ISFUNC) \ 681 kmap[ic].function = func; \ 682 } \ 683 while (0) 684 685 if (get_tty_settings (tty, &ttybuff) == 0) 686 { 687 if (ttybuff.flags & SGTTY_SET) 688 { 689 SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout); 690 SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard); 691 } 692 693# if defined (TIOCGLTC) 694 if (ttybuff.flags & LTCHARS_SET) 695 { 696 SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout); 697 SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert); 698 } 699# endif /* TIOCGLTC */ 700 } 701 702#else /* !NEW_TTY_DRIVER */ 703 704#define SET_SPECIAL(sc, func) \ 705 do \ 706 { \ 707 unsigned char uc; \ 708 uc = ttybuff.c_cc[sc]; \ 709 if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \ 710 kmap[uc].function = func; \ 711 } \ 712 while (0) 713 714 if (get_tty_settings (tty, &ttybuff) == 0) 715 { 716 SET_SPECIAL (VERASE, rl_rubout); 717 SET_SPECIAL (VKILL, rl_unix_line_discard); 718 719# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER) 720 SET_SPECIAL (VLNEXT, rl_quoted_insert); 721# endif /* VLNEXT && TERMIOS_TTY_DRIVER */ 722 723# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER) 724 SET_SPECIAL (VWERASE, rl_unix_word_rubout); 725# endif /* VWERASE && TERMIOS_TTY_DRIVER */ 726 } 727#endif /* !NEW_TTY_DRIVER */ 728} 729