121308Sache/* rltty.c -- functions to prepare and restore the terminal for readline's
221308Sache   use. */
321308Sache
4157184Sache/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
521308Sache
621308Sache   This file is part of the GNU Readline Library, a library for
721308Sache   reading lines of text with interactive input and history editing.
821308Sache
921308Sache   The GNU Readline Library is free software; you can redistribute it
1021308Sache   and/or modify it under the terms of the GNU General Public License
1158310Sache   as published by the Free Software Foundation; either version 2, or
1221308Sache   (at your option) any later version.
1321308Sache
1421308Sache   The GNU Readline Library is distributed in the hope that it will be
1521308Sache   useful, but WITHOUT ANY WARRANTY; without even the implied warranty
1621308Sache   of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1721308Sache   GNU General Public License for more details.
1821308Sache
1921308Sache   The GNU General Public License is often shipped with GNU software, and
2021308Sache   is generally kept in a file called COPYING or LICENSE.  If you do not
2121308Sache   have a copy of the license, write to the Free Software Foundation,
2258310Sache   59 Temple Place, Suite 330, Boston, MA 02111 USA. */
2321308Sache#define READLINE_LIBRARY
2421308Sache
2521308Sache#if defined (HAVE_CONFIG_H)
2621308Sache#  include <config.h>
2721308Sache#endif
2821308Sache
2921308Sache#include <sys/types.h>
3021308Sache#include <signal.h>
3121308Sache#include <errno.h>
3221308Sache#include <stdio.h>
3321308Sache
3421308Sache#if defined (HAVE_UNISTD_H)
3521308Sache#  include <unistd.h>
3621308Sache#endif /* HAVE_UNISTD_H */
3721308Sache
3821308Sache#include "rldefs.h"
3921308Sache
4047558Sache#if defined (GWINSZ_IN_SYS_IOCTL)
4121308Sache#  include <sys/ioctl.h>
4247558Sache#endif /* GWINSZ_IN_SYS_IOCTL */
4321308Sache
4421308Sache#include "rltty.h"
4521308Sache#include "readline.h"
4658310Sache#include "rlprivate.h"
4721308Sache
4821308Sache#if !defined (errno)
4921308Sacheextern int errno;
5021308Sache#endif /* !errno */
5121308Sache
5275406Sacherl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
5375406Sacherl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
5421308Sache
55119610Sachestatic void block_sigint PARAMS((void));
56119610Sachestatic void release_sigint PARAMS((void));
57119610Sache
58119610Sachestatic void set_winsize PARAMS((int));
59119610Sache
6021308Sache/* **************************************************************** */
6121308Sache/*								    */
6221308Sache/*			   Signal Management			    */
6321308Sache/*								    */
6421308Sache/* **************************************************************** */
6521308Sache
6621308Sache#if defined (HAVE_POSIX_SIGNALS)
6721308Sachestatic sigset_t sigint_set, sigint_oset;
6821308Sache#else /* !HAVE_POSIX_SIGNALS */
6921308Sache#  if defined (HAVE_BSD_SIGNALS)
7021308Sachestatic int sigint_oldmask;
7121308Sache#  endif /* HAVE_BSD_SIGNALS */
7221308Sache#endif /* !HAVE_POSIX_SIGNALS */
7321308Sache
7421308Sachestatic int sigint_blocked;
7521308Sache
7621308Sache/* Cause SIGINT to not be delivered until the corresponding call to
7721308Sache   release_sigint(). */
7821308Sachestatic void
7921308Sacheblock_sigint ()
8021308Sache{
8121308Sache  if (sigint_blocked)
8221308Sache    return;
8321308Sache
8421308Sache#if defined (HAVE_POSIX_SIGNALS)
8521308Sache  sigemptyset (&sigint_set);
8621308Sache  sigemptyset (&sigint_oset);
8721308Sache  sigaddset (&sigint_set, SIGINT);
8821308Sache  sigprocmask (SIG_BLOCK, &sigint_set, &sigint_oset);
8921308Sache#else /* !HAVE_POSIX_SIGNALS */
9021308Sache#  if defined (HAVE_BSD_SIGNALS)
9121308Sache  sigint_oldmask = sigblock (sigmask (SIGINT));
9221308Sache#  else /* !HAVE_BSD_SIGNALS */
9321308Sache#    if defined (HAVE_USG_SIGHOLD)
9421308Sache  sighold (SIGINT);
9521308Sache#    endif /* HAVE_USG_SIGHOLD */
9621308Sache#  endif /* !HAVE_BSD_SIGNALS */
9721308Sache#endif /* !HAVE_POSIX_SIGNALS */
9858310Sache
9921308Sache  sigint_blocked = 1;
10021308Sache}
10121308Sache
10221308Sache/* Allow SIGINT to be delivered. */
10321308Sachestatic void
10421308Sacherelease_sigint ()
10521308Sache{
10658310Sache  if (sigint_blocked == 0)
10721308Sache    return;
10821308Sache
10921308Sache#if defined (HAVE_POSIX_SIGNALS)
11021308Sache  sigprocmask (SIG_SETMASK, &sigint_oset, (sigset_t *)NULL);
11121308Sache#else
11221308Sache#  if defined (HAVE_BSD_SIGNALS)
11321308Sache  sigsetmask (sigint_oldmask);
11421308Sache#  else /* !HAVE_BSD_SIGNALS */
11521308Sache#    if defined (HAVE_USG_SIGHOLD)
11621308Sache  sigrelse (SIGINT);
11721308Sache#    endif /* HAVE_USG_SIGHOLD */
11821308Sache#  endif /* !HAVE_BSD_SIGNALS */
11921308Sache#endif /* !HAVE_POSIX_SIGNALS */
12021308Sache
12121308Sache  sigint_blocked = 0;
12221308Sache}
12321308Sache
12421308Sache/* **************************************************************** */
12521308Sache/*								    */
12621308Sache/*		      Saving and Restoring the TTY	    	    */
12721308Sache/*								    */
12821308Sache/* **************************************************************** */
12921308Sache
13021308Sache/* Non-zero means that the terminal is in a prepped state. */
13121308Sachestatic int terminal_prepped;
13221308Sache
13358310Sachestatic _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
13458310Sache
13521308Sache/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
13621308Sache   and output is suspended. */
13721308Sache#if defined (__ksr1__)
13821308Sachestatic int ksrflow;
13921308Sache#endif
14021308Sache
14121308Sache/* Dummy call to force a backgrounded readline to stop before it tries
14221308Sache   to get the tty settings. */
14321308Sachestatic void
14421308Sacheset_winsize (tty)
14521308Sache     int tty;
14621308Sache{
14758310Sache#if defined (TIOCGWINSZ)
14821308Sache  struct winsize w;
14921308Sache
15021308Sache  if (ioctl (tty, TIOCGWINSZ, &w) == 0)
15121308Sache      (void) ioctl (tty, TIOCSWINSZ, &w);
15258310Sache#endif /* TIOCGWINSZ */
15321308Sache}
15421308Sache
155157184Sache#if defined (NO_TTY_DRIVER)
156157184Sache/* Nothing */
157157184Sache#elif defined (NEW_TTY_DRIVER)
15821308Sache
15921308Sache/* Values for the `flags' field of a struct bsdtty.  This tells which
16021308Sache   elements of the struct bsdtty have been fetched from the system and
16121308Sache   are valid. */
16221308Sache#define SGTTY_SET	0x01
16321308Sache#define LFLAG_SET	0x02
16421308Sache#define TCHARS_SET	0x04
16521308Sache#define LTCHARS_SET	0x08
16621308Sache
16721308Sachestruct bsdtty {
16821308Sache  struct sgttyb sgttyb;	/* Basic BSD tty driver information. */
16921308Sache  int lflag;		/* Local mode flags, like LPASS8. */
17021308Sache#if defined (TIOCGETC)
17121308Sache  struct tchars tchars;	/* Terminal special characters, including ^S and ^Q. */
17221308Sache#endif
17321308Sache#if defined (TIOCGLTC)
17421308Sache  struct ltchars ltchars; /* 4.2 BSD editing characters */
17521308Sache#endif
17621308Sache  int flags;		/* Bitmap saying which parts of the struct are valid. */
17721308Sache};
17821308Sache
17921308Sache#define TIOTYPE struct bsdtty
18021308Sache
18121308Sachestatic TIOTYPE otio;
18221308Sache
183119610Sachestatic void save_tty_chars PARAMS((TIOTYPE *));
184119610Sachestatic int _get_tty_settings PARAMS((int, TIOTYPE *));
185119610Sachestatic int get_tty_settings PARAMS((int, TIOTYPE *));
186119610Sachestatic int _set_tty_settings PARAMS((int, TIOTYPE *));
187119610Sachestatic int set_tty_settings PARAMS((int, TIOTYPE *));
188119610Sache
189119610Sachestatic void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
190119610Sache
191136644Sachestatic void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
192136644Sache
19358310Sachestatic void
19458310Sachesave_tty_chars (tiop)
19558310Sache     TIOTYPE *tiop;
19658310Sache{
19758310Sache  _rl_last_tty_chars = _rl_tty_chars;
19858310Sache
19958310Sache  if (tiop->flags & SGTTY_SET)
20058310Sache    {
20158310Sache      _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
20258310Sache      _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
20358310Sache    }
20458310Sache
20558310Sache  if (tiop->flags & TCHARS_SET)
20658310Sache    {
20758310Sache      _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
20858310Sache      _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
20958310Sache      _rl_tty_chars.t_start = tiop->tchars.t_startc;
21075406Sache      _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
21158310Sache      _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
21258310Sache      _rl_tty_chars.t_eol = '\n';
21358310Sache      _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
21458310Sache    }
21558310Sache
21658310Sache  if (tiop->flags & LTCHARS_SET)
21758310Sache    {
21858310Sache      _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
21958310Sache      _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
22058310Sache      _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
22158310Sache      _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
22258310Sache      _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
22358310Sache      _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
22458310Sache    }
22558310Sache
22658310Sache  _rl_tty_chars.t_status = -1;
22758310Sache}
22858310Sache
22921308Sachestatic int
23021308Sacheget_tty_settings (tty, tiop)
23121308Sache     int tty;
23221308Sache     TIOTYPE *tiop;
23321308Sache{
23421308Sache  set_winsize (tty);
23521308Sache
23621308Sache  tiop->flags = tiop->lflag = 0;
23721308Sache
238157184Sache  errno = 0;
23975406Sache  if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
24075406Sache    return -1;
24121308Sache  tiop->flags |= SGTTY_SET;
24221308Sache
24321308Sache#if defined (TIOCLGET)
24475406Sache  if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
24575406Sache    tiop->flags |= LFLAG_SET;
24621308Sache#endif
24721308Sache
24821308Sache#if defined (TIOCGETC)
24975406Sache  if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
25075406Sache    tiop->flags |= TCHARS_SET;
25121308Sache#endif
25221308Sache
25321308Sache#if defined (TIOCGLTC)
25475406Sache  if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
25575406Sache    tiop->flags |= LTCHARS_SET;
25621308Sache#endif
25721308Sache
25821308Sache  return 0;
25921308Sache}
26021308Sache
26121308Sachestatic int
26221308Sacheset_tty_settings (tty, tiop)
26321308Sache     int tty;
26421308Sache     TIOTYPE *tiop;
26521308Sache{
26621308Sache  if (tiop->flags & SGTTY_SET)
26721308Sache    {
26821308Sache      ioctl (tty, TIOCSETN, &(tiop->sgttyb));
26921308Sache      tiop->flags &= ~SGTTY_SET;
27021308Sache    }
27121308Sache  readline_echoing_p = 1;
27221308Sache
27321308Sache#if defined (TIOCLSET)
27421308Sache  if (tiop->flags & LFLAG_SET)
27521308Sache    {
27621308Sache      ioctl (tty, TIOCLSET, &(tiop->lflag));
27721308Sache      tiop->flags &= ~LFLAG_SET;
27821308Sache    }
27921308Sache#endif
28021308Sache
28121308Sache#if defined (TIOCSETC)
28221308Sache  if (tiop->flags & TCHARS_SET)
28321308Sache    {
28421308Sache      ioctl (tty, TIOCSETC, &(tiop->tchars));
28521308Sache      tiop->flags &= ~TCHARS_SET;
28621308Sache    }
28721308Sache#endif
28821308Sache
28921308Sache#if defined (TIOCSLTC)
29021308Sache  if (tiop->flags & LTCHARS_SET)
29121308Sache    {
29221308Sache      ioctl (tty, TIOCSLTC, &(tiop->ltchars));
29321308Sache      tiop->flags &= ~LTCHARS_SET;
29421308Sache    }
29521308Sache#endif
29621308Sache
29721308Sache  return 0;
29821308Sache}
29921308Sache
30021308Sachestatic void
30175406Sacheprepare_terminal_settings (meta_flag, oldtio, tiop)
30221308Sache     int meta_flag;
30375406Sache     TIOTYPE oldtio, *tiop;
30421308Sache{
30575406Sache  readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
30621308Sache
30721308Sache  /* Copy the original settings to the structure we're going to use for
30821308Sache     our settings. */
30975406Sache  tiop->sgttyb = oldtio.sgttyb;
31075406Sache  tiop->lflag = oldtio.lflag;
31121308Sache#if defined (TIOCGETC)
31275406Sache  tiop->tchars = oldtio.tchars;
31321308Sache#endif
31421308Sache#if defined (TIOCGLTC)
31575406Sache  tiop->ltchars = oldtio.ltchars;
31621308Sache#endif
31775406Sache  tiop->flags = oldtio.flags;
31821308Sache
31921308Sache  /* First, the basic settings to put us into character-at-a-time, no-echo
32021308Sache     input mode. */
32121308Sache  tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
32221308Sache  tiop->sgttyb.sg_flags |= CBREAK;
32321308Sache
32421308Sache  /* If this terminal doesn't care how the 8th bit is used, then we can
32521308Sache     use it for the meta-key.  If only one of even or odd parity is
32621308Sache     specified, then the terminal is using parity, and we cannot. */
32721308Sache#if !defined (ANYP)
32821308Sache#  define ANYP (EVENP | ODDP)
32921308Sache#endif
33075406Sache  if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
33175406Sache      ((oldtio.sgttyb.sg_flags & ANYP) == 0))
33221308Sache    {
33321308Sache      tiop->sgttyb.sg_flags |= ANYP;
33421308Sache
33521308Sache      /* Hack on local mode flags if we can. */
33621308Sache#if defined (TIOCLGET)
33721308Sache#  if defined (LPASS8)
33821308Sache      tiop->lflag |= LPASS8;
33921308Sache#  endif /* LPASS8 */
34021308Sache#endif /* TIOCLGET */
34121308Sache    }
34221308Sache
34321308Sache#if defined (TIOCGETC)
34421308Sache#  if defined (USE_XON_XOFF)
34521308Sache  /* Get rid of terminal output start and stop characters. */
34621308Sache  tiop->tchars.t_stopc = -1; /* C-s */
34721308Sache  tiop->tchars.t_startc = -1; /* C-q */
34821308Sache
34921308Sache  /* If there is an XON character, bind it to restart the output. */
35075406Sache  if (oldtio.tchars.t_startc != -1)
35175406Sache    rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
35221308Sache#  endif /* USE_XON_XOFF */
35321308Sache
35421308Sache  /* If there is an EOF char, bind _rl_eof_char to it. */
35575406Sache  if (oldtio.tchars.t_eofc != -1)
35675406Sache    _rl_eof_char = oldtio.tchars.t_eofc;
35721308Sache
35821308Sache#  if defined (NO_KILL_INTR)
35921308Sache  /* Get rid of terminal-generated SIGQUIT and SIGINT. */
36021308Sache  tiop->tchars.t_quitc = -1; /* C-\ */
36121308Sache  tiop->tchars.t_intrc = -1; /* C-c */
36221308Sache#  endif /* NO_KILL_INTR */
36321308Sache#endif /* TIOCGETC */
36421308Sache
36521308Sache#if defined (TIOCGLTC)
36621308Sache  /* Make the interrupt keys go away.  Just enough to make people happy. */
36721308Sache  tiop->ltchars.t_dsuspc = -1;	/* C-y */
36821308Sache  tiop->ltchars.t_lnextc = -1;	/* C-v */
36921308Sache#endif /* TIOCGLTC */
37021308Sache}
37121308Sache
37221308Sache#else  /* !defined (NEW_TTY_DRIVER) */
37321308Sache
37421308Sache#if !defined (VMIN)
37521308Sache#  define VMIN VEOF
37621308Sache#endif
37721308Sache
37821308Sache#if !defined (VTIME)
37921308Sache#  define VTIME VEOL
38021308Sache#endif
38121308Sache
38221308Sache#if defined (TERMIOS_TTY_DRIVER)
38321308Sache#  define TIOTYPE struct termios
38421308Sache#  define DRAIN_OUTPUT(fd)	tcdrain (fd)
38521308Sache#  define GETATTR(tty, tiop)	(tcgetattr (tty, tiop))
38621308Sache#  ifdef M_UNIX
38721308Sache#    define SETATTR(tty, tiop)	(tcsetattr (tty, TCSANOW, tiop))
38821308Sache#  else
38921308Sache#    define SETATTR(tty, tiop)	(tcsetattr (tty, TCSADRAIN, tiop))
39021308Sache#  endif /* !M_UNIX */
39121308Sache#else
39221308Sache#  define TIOTYPE struct termio
39321308Sache#  define DRAIN_OUTPUT(fd)
39421308Sache#  define GETATTR(tty, tiop)	(ioctl (tty, TCGETA, tiop))
39575406Sache#  define SETATTR(tty, tiop)	(ioctl (tty, TCSETAW, tiop))
39621308Sache#endif /* !TERMIOS_TTY_DRIVER */
39721308Sache
39821308Sachestatic TIOTYPE otio;
39921308Sache
400119610Sachestatic void save_tty_chars PARAMS((TIOTYPE *));
401119610Sachestatic int _get_tty_settings PARAMS((int, TIOTYPE *));
402119610Sachestatic int get_tty_settings PARAMS((int, TIOTYPE *));
403119610Sachestatic int _set_tty_settings PARAMS((int, TIOTYPE *));
404119610Sachestatic int set_tty_settings PARAMS((int, TIOTYPE *));
405119610Sache
406119610Sachestatic void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
407119610Sache
408136644Sachestatic void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t));
409136644Sachestatic void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
410136644Sache
41121308Sache#if defined (FLUSHO)
41221308Sache#  define OUTPUT_BEING_FLUSHED(tp)  (tp->c_lflag & FLUSHO)
41321308Sache#else
41421308Sache#  define OUTPUT_BEING_FLUSHED(tp)  0
41521308Sache#endif
41621308Sache
41721308Sachestatic void
41858310Sachesave_tty_chars (tiop)
41958310Sache     TIOTYPE *tiop;
42058310Sache{
42158310Sache  _rl_last_tty_chars = _rl_tty_chars;
42258310Sache
42358310Sache  _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
42458310Sache  _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
42558310Sache#ifdef VEOL2
42658310Sache  _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
42758310Sache#endif
42858310Sache  _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
42958310Sache#ifdef VWERASE
43058310Sache  _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
43158310Sache#endif
43258310Sache  _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
43358310Sache#ifdef VREPRINT
43458310Sache  _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
43558310Sache#endif
43658310Sache  _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
43758310Sache  _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
43858310Sache#ifdef VSUSP
43958310Sache  _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
44058310Sache#endif
44158310Sache#ifdef VDSUSP
44258310Sache  _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
44358310Sache#endif
44458310Sache#ifdef VSTART
44558310Sache  _rl_tty_chars.t_start = tiop->c_cc[VSTART];
44658310Sache#endif
44758310Sache#ifdef VSTOP
44858310Sache  _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
44958310Sache#endif
45058310Sache#ifdef VLNEXT
45158310Sache  _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
45258310Sache#endif
45358310Sache#ifdef VDISCARD
45458310Sache  _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
45558310Sache#endif
45658310Sache#ifdef VSTATUS
45758310Sache  _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
45858310Sache#endif
45958310Sache}
46058310Sache
46158310Sache#if defined (_AIX) || defined (_AIX41)
46258310Sache/* Currently this is only used on AIX */
46358310Sachestatic void
46421308Sacherltty_warning (msg)
46521308Sache     char *msg;
46621308Sache{
46721308Sache  fprintf (stderr, "readline: warning: %s\n", msg);
46821308Sache}
46958310Sache#endif
47021308Sache
47121308Sache#if defined (_AIX)
47221308Sachevoid
47321308Sachesetopost(tp)
47421308SacheTIOTYPE *tp;
47521308Sache{
47621308Sache  if ((tp->c_oflag & OPOST) == 0)
47721308Sache    {
47821308Sache      rltty_warning ("turning on OPOST for terminal\r");
47921308Sache      tp->c_oflag |= OPOST|ONLCR;
48021308Sache    }
48121308Sache}
48221308Sache#endif
48321308Sache
48421308Sachestatic int
48558310Sache_get_tty_settings (tty, tiop)
48621308Sache     int tty;
48721308Sache     TIOTYPE *tiop;
48821308Sache{
48921308Sache  int ioctl_ret;
49047558Sache
49121308Sache  while (1)
49221308Sache    {
49321308Sache      ioctl_ret = GETATTR (tty, tiop);
49421308Sache      if (ioctl_ret < 0)
49521308Sache	{
49621308Sache	  if (errno != EINTR)
49721308Sache	    return -1;
49821308Sache	  else
49921308Sache	    continue;
50021308Sache	}
50121308Sache      if (OUTPUT_BEING_FLUSHED (tiop))
50221308Sache	{
50321308Sache#if defined (FLUSHO) && defined (_AIX41)
50421308Sache	  rltty_warning ("turning off output flushing");
50521308Sache	  tiop->c_lflag &= ~FLUSHO;
50621308Sache	  break;
50721308Sache#else
50821308Sache	  continue;
50921308Sache#endif
51021308Sache	}
51121308Sache      break;
51221308Sache    }
51321308Sache
51458310Sache  return 0;
51558310Sache}
51658310Sache
51758310Sachestatic int
51858310Sacheget_tty_settings (tty, tiop)
51958310Sache     int tty;
52058310Sache     TIOTYPE *tiop;
52158310Sache{
52258310Sache  set_winsize (tty);
52358310Sache
524157184Sache  errno = 0;
52558310Sache  if (_get_tty_settings (tty, tiop) < 0)
52658310Sache    return -1;
52758310Sache
52821308Sache#if defined (_AIX)
52921308Sache  setopost(tiop);
53021308Sache#endif
53121308Sache
53221308Sache  return 0;
53321308Sache}
53421308Sache
53521308Sachestatic int
53658310Sache_set_tty_settings (tty, tiop)
53721308Sache     int tty;
53821308Sache     TIOTYPE *tiop;
53921308Sache{
54021308Sache  while (SETATTR (tty, tiop) < 0)
54121308Sache    {
54221308Sache      if (errno != EINTR)
54321308Sache	return -1;
54421308Sache      errno = 0;
54521308Sache    }
54658310Sache  return 0;
54758310Sache}
54821308Sache
54958310Sachestatic int
55058310Sacheset_tty_settings (tty, tiop)
55158310Sache     int tty;
55258310Sache     TIOTYPE *tiop;
55358310Sache{
55458310Sache  if (_set_tty_settings (tty, tiop) < 0)
55558310Sache    return -1;
55658310Sache
55721308Sache#if 0
55821308Sache
55921308Sache#if defined (TERMIOS_TTY_DRIVER)
56021308Sache#  if defined (__ksr1__)
56121308Sache  if (ksrflow)
56221308Sache    {
56321308Sache      ksrflow = 0;
56421308Sache      tcflow (tty, TCOON);
56521308Sache    }
56621308Sache#  else /* !ksr1 */
56721308Sache  tcflow (tty, TCOON);		/* Simulate a ^Q. */
56821308Sache#  endif /* !ksr1 */
56921308Sache#else
57021308Sache  ioctl (tty, TCXONC, 1);	/* Simulate a ^Q. */
57121308Sache#endif /* !TERMIOS_TTY_DRIVER */
57221308Sache
57358310Sache#endif /* 0 */
57421308Sache
57521308Sache  return 0;
57621308Sache}
57721308Sache
57821308Sachestatic void
57975406Sacheprepare_terminal_settings (meta_flag, oldtio, tiop)
58021308Sache     int meta_flag;
58175406Sache     TIOTYPE oldtio, *tiop;
58221308Sache{
58375406Sache  readline_echoing_p = (oldtio.c_lflag & ECHO);
58421308Sache
58521308Sache  tiop->c_lflag &= ~(ICANON | ECHO);
58621308Sache
58775406Sache  if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
58875406Sache    _rl_eof_char = oldtio.c_cc[VEOF];
58921308Sache
59021308Sache#if defined (USE_XON_XOFF)
59121308Sache#if defined (IXANY)
59221308Sache  tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
59321308Sache#else
59421308Sache  /* `strict' Posix systems do not define IXANY. */
59521308Sache  tiop->c_iflag &= ~(IXON | IXOFF);
59621308Sache#endif /* IXANY */
59721308Sache#endif /* USE_XON_XOFF */
59821308Sache
59921308Sache  /* Only turn this off if we are using all 8 bits. */
60021308Sache  if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
60121308Sache    tiop->c_iflag &= ~(ISTRIP | INPCK);
60221308Sache
60321308Sache  /* Make sure we differentiate between CR and NL on input. */
60421308Sache  tiop->c_iflag &= ~(ICRNL | INLCR);
60521308Sache
60621308Sache#if !defined (HANDLE_SIGNALS)
60721308Sache  tiop->c_lflag &= ~ISIG;
60821308Sache#else
60921308Sache  tiop->c_lflag |= ISIG;
61021308Sache#endif
61121308Sache
61221308Sache  tiop->c_cc[VMIN] = 1;
61321308Sache  tiop->c_cc[VTIME] = 0;
61421308Sache
61521308Sache#if defined (FLUSHO)
61621308Sache  if (OUTPUT_BEING_FLUSHED (tiop))
61721308Sache    {
61821308Sache      tiop->c_lflag &= ~FLUSHO;
61975406Sache      oldtio.c_lflag &= ~FLUSHO;
62021308Sache    }
62121308Sache#endif
62221308Sache
62321308Sache  /* Turn off characters that we need on Posix systems with job control,
62421308Sache     just to be sure.  This includes ^Y and ^V.  This should not really
62521308Sache     be necessary.  */
62621308Sache#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
62721308Sache
62821308Sache#if defined (VLNEXT)
62921308Sache  tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
63021308Sache#endif
63121308Sache
63221308Sache#if defined (VDSUSP)
63321308Sache  tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
63421308Sache#endif
63521308Sache
63621308Sache#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
63721308Sache}
638157184Sache#endif  /* !NEW_TTY_DRIVER */
63921308Sache
64021308Sache/* Put the terminal in CBREAK mode so that we can detect key presses. */
641157184Sache#if defined (NO_TTY_DRIVER)
64221308Sachevoid
64321308Sacherl_prep_terminal (meta_flag)
64421308Sache     int meta_flag;
64521308Sache{
646157184Sache  readline_echoing_p = 1;
647157184Sache}
648157184Sache
649157184Sachevoid
650157184Sacherl_deprep_terminal ()
651157184Sache{
652157184Sache}
653157184Sache
654157184Sache#else /* ! NO_TTY_DRIVER */
655157184Sachevoid
656157184Sacherl_prep_terminal (meta_flag)
657157184Sache     int meta_flag;
658157184Sache{
65921308Sache  int tty;
66021308Sache  TIOTYPE tio;
66121308Sache
66221308Sache  if (terminal_prepped)
66321308Sache    return;
66421308Sache
66521308Sache  /* Try to keep this function from being INTerrupted. */
66621308Sache  block_sigint ();
66721308Sache
66821308Sache  tty = fileno (rl_instream);
66921308Sache
67021308Sache  if (get_tty_settings (tty, &tio) < 0)
67121308Sache    {
672157184Sache#if defined (ENOTSUP)
673157184Sache      /* MacOS X, at least, lies about the value of errno if tcgetattr fails. */
674157184Sache      if (errno == ENOTTY || errno == ENOTSUP)
675157184Sache#else
676157184Sache      if (errno == ENOTTY)
677157184Sache#endif
678157184Sache	readline_echoing_p = 1;		/* XXX */
67921308Sache      release_sigint ();
68021308Sache      return;
68121308Sache    }
68221308Sache
68321308Sache  otio = tio;
68421308Sache
685157184Sache  if (_rl_bind_stty_chars)
686157184Sache    {
687157184Sache#if defined (VI_MODE)
688157184Sache      /* If editing in vi mode, make sure we restore the bindings in the
689157184Sache	 insertion keymap no matter what keymap we ended up in. */
690157184Sache      if (rl_editing_mode == vi_mode)
691157184Sache	rl_tty_unset_default_bindings (vi_insertion_keymap);
692157184Sache      else
693157184Sache#endif
694157184Sache	rl_tty_unset_default_bindings (_rl_keymap);
695157184Sache    }
69658310Sache  save_tty_chars (&otio);
697136644Sache  RL_SETSTATE(RL_STATE_TTYCSAVED);
698157184Sache  if (_rl_bind_stty_chars)
699157184Sache    {
700157184Sache#if defined (VI_MODE)
701157184Sache      /* If editing in vi mode, make sure we set the bindings in the
702157184Sache	 insertion keymap no matter what keymap we ended up in. */
703157184Sache      if (rl_editing_mode == vi_mode)
704157184Sache	_rl_bind_tty_special_chars (vi_insertion_keymap, tio);
705157184Sache      else
706157184Sache#endif
707157184Sache	_rl_bind_tty_special_chars (_rl_keymap, tio);
708157184Sache    }
70958310Sache
71021308Sache  prepare_terminal_settings (meta_flag, otio, &tio);
71121308Sache
71221308Sache  if (set_tty_settings (tty, &tio) < 0)
71321308Sache    {
71421308Sache      release_sigint ();
71521308Sache      return;
71621308Sache    }
71721308Sache
71821308Sache  if (_rl_enable_keypad)
71921308Sache    _rl_control_keypad (1);
72021308Sache
72121308Sache  fflush (rl_outstream);
72221308Sache  terminal_prepped = 1;
72375406Sache  RL_SETSTATE(RL_STATE_TERMPREPPED);
72421308Sache
72521308Sache  release_sigint ();
72621308Sache}
72721308Sache
72821308Sache/* Restore the terminal's normal settings and modes. */
72921308Sachevoid
73021308Sacherl_deprep_terminal ()
73121308Sache{
73221308Sache  int tty;
73321308Sache
73421308Sache  if (!terminal_prepped)
73521308Sache    return;
73621308Sache
73721308Sache  /* Try to keep this function from being interrupted. */
73821308Sache  block_sigint ();
73921308Sache
74021308Sache  tty = fileno (rl_instream);
74121308Sache
74221308Sache  if (_rl_enable_keypad)
74321308Sache    _rl_control_keypad (0);
74421308Sache
74521308Sache  fflush (rl_outstream);
74621308Sache
74721308Sache  if (set_tty_settings (tty, &otio) < 0)
74821308Sache    {
74921308Sache      release_sigint ();
75021308Sache      return;
75121308Sache    }
75221308Sache
75321308Sache  terminal_prepped = 0;
75475406Sache  RL_UNSETSTATE(RL_STATE_TERMPREPPED);
75521308Sache
75621308Sache  release_sigint ();
75721308Sache}
758157184Sache#endif /* !NO_TTY_DRIVER */
75921308Sache
76021308Sache/* **************************************************************** */
76121308Sache/*								    */
76221308Sache/*			Bogus Flow Control      		    */
76321308Sache/*								    */
76421308Sache/* **************************************************************** */
76521308Sache
76621308Sacheint
76721308Sacherl_restart_output (count, key)
76821308Sache     int count, key;
76921308Sache{
770157184Sache#if defined (__MINGW32__)
771157184Sache  return 0;
772157184Sache#else /* !__MING32__ */
773157184Sache
77421308Sache  int fildes = fileno (rl_outstream);
77521308Sache#if defined (TIOCSTART)
77621308Sache#if defined (apollo)
77721308Sache  ioctl (&fildes, TIOCSTART, 0);
77821308Sache#else
77921308Sache  ioctl (fildes, TIOCSTART, 0);
78021308Sache#endif /* apollo */
78121308Sache
78221308Sache#else /* !TIOCSTART */
78321308Sache#  if defined (TERMIOS_TTY_DRIVER)
78421308Sache#    if defined (__ksr1__)
78521308Sache  if (ksrflow)
78621308Sache    {
78721308Sache      ksrflow = 0;
78821308Sache      tcflow (fildes, TCOON);
78921308Sache    }
79021308Sache#    else /* !ksr1 */
79121308Sache  tcflow (fildes, TCOON);		/* Simulate a ^Q. */
79221308Sache#    endif /* !ksr1 */
79321308Sache#  else /* !TERMIOS_TTY_DRIVER */
79421308Sache#    if defined (TCXONC)
79521308Sache  ioctl (fildes, TCXONC, TCOON);
79621308Sache#    endif /* TCXONC */
79721308Sache#  endif /* !TERMIOS_TTY_DRIVER */
79821308Sache#endif /* !TIOCSTART */
79921308Sache
80021308Sache  return 0;
801157184Sache#endif /* !__MINGW32__ */
80221308Sache}
80321308Sache
80421308Sacheint
80521308Sacherl_stop_output (count, key)
80621308Sache     int count, key;
80721308Sache{
808157184Sache#if defined (__MINGW32__)
809157184Sache  return 0;
810157184Sache#else
811157184Sache
81221308Sache  int fildes = fileno (rl_instream);
81321308Sache
81421308Sache#if defined (TIOCSTOP)
81521308Sache# if defined (apollo)
81621308Sache  ioctl (&fildes, TIOCSTOP, 0);
81721308Sache# else
81821308Sache  ioctl (fildes, TIOCSTOP, 0);
81921308Sache# endif /* apollo */
82021308Sache#else /* !TIOCSTOP */
82121308Sache# if defined (TERMIOS_TTY_DRIVER)
82221308Sache#  if defined (__ksr1__)
82321308Sache  ksrflow = 1;
82421308Sache#  endif /* ksr1 */
82521308Sache  tcflow (fildes, TCOOFF);
82621308Sache# else
82721308Sache#   if defined (TCXONC)
82821308Sache  ioctl (fildes, TCXONC, TCOON);
82921308Sache#   endif /* TCXONC */
83021308Sache# endif /* !TERMIOS_TTY_DRIVER */
83121308Sache#endif /* !TIOCSTOP */
83221308Sache
83321308Sache  return 0;
834157184Sache#endif /* !__MINGW32__ */
83521308Sache}
83621308Sache
83721308Sache/* **************************************************************** */
83821308Sache/*								    */
83921308Sache/*			Default Key Bindings			    */
84021308Sache/*								    */
84121308Sache/* **************************************************************** */
84275406Sache
843157184Sache#if !defined (NO_TTY_DRIVER)
844136644Sache#define SET_SPECIAL(sc, func)	set_special_char(kmap, &ttybuff, sc, func)
845157184Sache#endif
846136644Sache
847157184Sache#if defined (NO_TTY_DRIVER)
848157184Sache
849157184Sache#define SET_SPECIAL(sc, func)
850157184Sache#define RESET_SPECIAL(c)
851157184Sache
852157184Sache#elif defined (NEW_TTY_DRIVER)
853136644Sachestatic void
854136644Sacheset_special_char (kmap, tiop, sc, func)
85521308Sache     Keymap kmap;
856136644Sache     TIOTYPE *tiop;
857136644Sache     int sc;
858136644Sache     rl_command_func_t *func;
85921308Sache{
860136644Sache  if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
861136644Sache    kmap[(unsigned char)sc].function = func;
862136644Sache}
86321308Sache
864136644Sache#define RESET_SPECIAL(c) \
865136644Sache  if (c != -1 && kmap[(unsigned char)c].type == ISFUNC)
866136644Sache    kmap[(unsigned char)c].function = rl_insert;
86721308Sache
868136644Sachestatic void
869136644Sache_rl_bind_tty_special_chars (kmap, ttybuff)
870136644Sache     Keymap kmap;
871136644Sache     TIOTYPE ttybuff;
872136644Sache{
873136644Sache  if (ttybuff.flags & SGTTY_SET)
87421308Sache    {
875136644Sache      SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
876136644Sache      SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
877136644Sache    }
87821308Sache
87921308Sache#  if defined (TIOCGLTC)
880136644Sache  if (ttybuff.flags & LTCHARS_SET)
881136644Sache    {
882136644Sache      SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
883136644Sache      SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
884136644Sache    }
88521308Sache#  endif /* TIOCGLTC */
886136644Sache}
88721308Sache
88821308Sache#else /* !NEW_TTY_DRIVER */
889136644Sachestatic void
890136644Sacheset_special_char (kmap, tiop, sc, func)
891136644Sache     Keymap kmap;
892136644Sache     TIOTYPE *tiop;
893136644Sache     int sc;
894136644Sache     rl_command_func_t *func;
895136644Sache{
896136644Sache  unsigned char uc;
89721308Sache
898136644Sache  uc = tiop->c_cc[sc];
899136644Sache  if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
900136644Sache    kmap[uc].function = func;
901136644Sache}
90221308Sache
903136644Sache/* used later */
904136644Sache#define RESET_SPECIAL(uc) \
905136644Sache  if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
906136644Sache    kmap[uc].function = rl_insert;
90721308Sache
908136644Sachestatic void
909136644Sache_rl_bind_tty_special_chars (kmap, ttybuff)
910136644Sache     Keymap kmap;
911136644Sache     TIOTYPE ttybuff;
912136644Sache{
913136644Sache  SET_SPECIAL (VERASE, rl_rubout);
914136644Sache  SET_SPECIAL (VKILL, rl_unix_line_discard);
915136644Sache
91621308Sache#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
917136644Sache  SET_SPECIAL (VLNEXT, rl_quoted_insert);
91821308Sache#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
91921308Sache
92021308Sache#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
921136644Sache  SET_SPECIAL (VWERASE, rl_unix_word_rubout);
92221308Sache#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
923136644Sache}
924136644Sache
92521308Sache#endif /* !NEW_TTY_DRIVER */
926136644Sache
927136644Sache/* Set the system's default editing characters to their readline equivalents
928136644Sache   in KMAP.  Should be static, now that we have rl_tty_set_default_bindings. */
929136644Sachevoid
930136644Sacherltty_set_default_bindings (kmap)
931136644Sache     Keymap kmap;
932136644Sache{
933157184Sache#if !defined (NO_TTY_DRIVER)
934136644Sache  TIOTYPE ttybuff;
935136644Sache  int tty;
936136644Sache
937136644Sache  tty = fileno (rl_instream);
938136644Sache
939136644Sache  if (get_tty_settings (tty, &ttybuff) == 0)
940136644Sache    _rl_bind_tty_special_chars (kmap, ttybuff);
941157184Sache#endif
94221308Sache}
94358310Sache
94475406Sache/* New public way to set the system default editing chars to their readline
94575406Sache   equivalents. */
94675406Sachevoid
94775406Sacherl_tty_set_default_bindings (kmap)
94875406Sache     Keymap kmap;
94975406Sache{
95075406Sache  rltty_set_default_bindings (kmap);
95175406Sache}
95275406Sache
953136644Sache/* Rebind all of the tty special chars that readline worries about back
954136644Sache   to self-insert.  Call this before saving the current terminal special
955136644Sache   chars with save_tty_chars().  This only works on POSIX termios or termio
956136644Sache   systems. */
957136644Sachevoid
958136644Sacherl_tty_unset_default_bindings (kmap)
959136644Sache     Keymap kmap;
960136644Sache{
961136644Sache  /* Don't bother before we've saved the tty special chars at least once. */
962136644Sache  if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
963136644Sache    return;
964136644Sache
965136644Sache  RESET_SPECIAL (_rl_tty_chars.t_erase);
966136644Sache  RESET_SPECIAL (_rl_tty_chars.t_kill);
967136644Sache
968136644Sache#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
969136644Sache  RESET_SPECIAL (_rl_tty_chars.t_lnext);
970136644Sache#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
971136644Sache
972136644Sache#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
973136644Sache  RESET_SPECIAL (_rl_tty_chars.t_werase);
974136644Sache#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
975136644Sache}
976136644Sache
97758310Sache#if defined (HANDLE_SIGNALS)
97858310Sache
979157184Sache#if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER)
98058310Sacheint
98158310Sache_rl_disable_tty_signals ()
98258310Sache{
98358310Sache  return 0;
98458310Sache}
98558310Sache
98658310Sacheint
98758310Sache_rl_restore_tty_signals ()
98858310Sache{
98958310Sache  return 0;
99058310Sache}
99158310Sache#else
99258310Sache
99358310Sachestatic TIOTYPE sigstty, nosigstty;
99458310Sachestatic int tty_sigs_disabled = 0;
99558310Sache
99658310Sacheint
99758310Sache_rl_disable_tty_signals ()
99858310Sache{
99958310Sache  if (tty_sigs_disabled)
100058310Sache    return 0;
100158310Sache
100258310Sache  if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
100358310Sache    return -1;
100458310Sache
100558310Sache  nosigstty = sigstty;
100658310Sache
100758310Sache  nosigstty.c_lflag &= ~ISIG;
1008119610Sache  nosigstty.c_iflag &= ~IXON;
100958310Sache
101058310Sache  if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
101158310Sache    return (_set_tty_settings (fileno (rl_instream), &sigstty));
101258310Sache
101358310Sache  tty_sigs_disabled = 1;
101458310Sache  return 0;
101558310Sache}
101658310Sache
101758310Sacheint
101858310Sache_rl_restore_tty_signals ()
101958310Sache{
1020119610Sache  int r;
1021119610Sache
102258310Sache  if (tty_sigs_disabled == 0)
102358310Sache    return 0;
102458310Sache
1025119610Sache  r = _set_tty_settings (fileno (rl_instream), &sigstty);
1026119610Sache
1027119610Sache  if (r == 0)
1028119610Sache    tty_sigs_disabled = 0;
1029119610Sache
1030119610Sache  return r;
103158310Sache}
103258310Sache#endif /* !NEW_TTY_DRIVER */
103358310Sache
103458310Sache#endif /* HANDLE_SIGNALS */
1035