rltty.c revision 119610
121308Sache/* rltty.c -- functions to prepare and restore the terminal for readline's
221308Sache   use. */
321308Sache
421308Sache/* Copyright (C) 1992 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
15521308Sache#if defined (NEW_TTY_DRIVER)
15621308Sache
15721308Sache/* Values for the `flags' field of a struct bsdtty.  This tells which
15821308Sache   elements of the struct bsdtty have been fetched from the system and
15921308Sache   are valid. */
16021308Sache#define SGTTY_SET	0x01
16121308Sache#define LFLAG_SET	0x02
16221308Sache#define TCHARS_SET	0x04
16321308Sache#define LTCHARS_SET	0x08
16421308Sache
16521308Sachestruct bsdtty {
16621308Sache  struct sgttyb sgttyb;	/* Basic BSD tty driver information. */
16721308Sache  int lflag;		/* Local mode flags, like LPASS8. */
16821308Sache#if defined (TIOCGETC)
16921308Sache  struct tchars tchars;	/* Terminal special characters, including ^S and ^Q. */
17021308Sache#endif
17121308Sache#if defined (TIOCGLTC)
17221308Sache  struct ltchars ltchars; /* 4.2 BSD editing characters */
17321308Sache#endif
17421308Sache  int flags;		/* Bitmap saying which parts of the struct are valid. */
17521308Sache};
17621308Sache
17721308Sache#define TIOTYPE struct bsdtty
17821308Sache
17921308Sachestatic TIOTYPE otio;
18021308Sache
181119610Sachestatic void save_tty_chars PARAMS((TIOTYPE *));
182119610Sachestatic int _get_tty_settings PARAMS((int, TIOTYPE *));
183119610Sachestatic int get_tty_settings PARAMS((int, TIOTYPE *));
184119610Sachestatic int _set_tty_settings PARAMS((int, TIOTYPE *));
185119610Sachestatic int set_tty_settings PARAMS((int, TIOTYPE *));
186119610Sache
187119610Sachestatic void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
188119610Sache
18958310Sachestatic void
19058310Sachesave_tty_chars (tiop)
19158310Sache     TIOTYPE *tiop;
19258310Sache{
19358310Sache  _rl_last_tty_chars = _rl_tty_chars;
19458310Sache
19558310Sache  if (tiop->flags & SGTTY_SET)
19658310Sache    {
19758310Sache      _rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
19858310Sache      _rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
19958310Sache    }
20058310Sache
20158310Sache  if (tiop->flags & TCHARS_SET)
20258310Sache    {
20358310Sache      _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
20458310Sache      _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
20558310Sache      _rl_tty_chars.t_start = tiop->tchars.t_startc;
20675406Sache      _rl_tty_chars.t_stop = tiop->tchars.t_stopc;
20758310Sache      _rl_tty_chars.t_eof = tiop->tchars.t_eofc;
20858310Sache      _rl_tty_chars.t_eol = '\n';
20958310Sache      _rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
21058310Sache    }
21158310Sache
21258310Sache  if (tiop->flags & LTCHARS_SET)
21358310Sache    {
21458310Sache      _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
21558310Sache      _rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
21658310Sache      _rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
21758310Sache      _rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
21858310Sache      _rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
21958310Sache      _rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
22058310Sache    }
22158310Sache
22258310Sache  _rl_tty_chars.t_status = -1;
22358310Sache}
22458310Sache
22521308Sachestatic int
22621308Sacheget_tty_settings (tty, tiop)
22721308Sache     int tty;
22821308Sache     TIOTYPE *tiop;
22921308Sache{
23021308Sache  set_winsize (tty);
23121308Sache
23221308Sache  tiop->flags = tiop->lflag = 0;
23321308Sache
23475406Sache  if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
23575406Sache    return -1;
23621308Sache  tiop->flags |= SGTTY_SET;
23721308Sache
23821308Sache#if defined (TIOCLGET)
23975406Sache  if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
24075406Sache    tiop->flags |= LFLAG_SET;
24121308Sache#endif
24221308Sache
24321308Sache#if defined (TIOCGETC)
24475406Sache  if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
24575406Sache    tiop->flags |= TCHARS_SET;
24621308Sache#endif
24721308Sache
24821308Sache#if defined (TIOCGLTC)
24975406Sache  if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
25075406Sache    tiop->flags |= LTCHARS_SET;
25121308Sache#endif
25221308Sache
25321308Sache  return 0;
25421308Sache}
25521308Sache
25621308Sachestatic int
25721308Sacheset_tty_settings (tty, tiop)
25821308Sache     int tty;
25921308Sache     TIOTYPE *tiop;
26021308Sache{
26121308Sache  if (tiop->flags & SGTTY_SET)
26221308Sache    {
26321308Sache      ioctl (tty, TIOCSETN, &(tiop->sgttyb));
26421308Sache      tiop->flags &= ~SGTTY_SET;
26521308Sache    }
26621308Sache  readline_echoing_p = 1;
26721308Sache
26821308Sache#if defined (TIOCLSET)
26921308Sache  if (tiop->flags & LFLAG_SET)
27021308Sache    {
27121308Sache      ioctl (tty, TIOCLSET, &(tiop->lflag));
27221308Sache      tiop->flags &= ~LFLAG_SET;
27321308Sache    }
27421308Sache#endif
27521308Sache
27621308Sache#if defined (TIOCSETC)
27721308Sache  if (tiop->flags & TCHARS_SET)
27821308Sache    {
27921308Sache      ioctl (tty, TIOCSETC, &(tiop->tchars));
28021308Sache      tiop->flags &= ~TCHARS_SET;
28121308Sache    }
28221308Sache#endif
28321308Sache
28421308Sache#if defined (TIOCSLTC)
28521308Sache  if (tiop->flags & LTCHARS_SET)
28621308Sache    {
28721308Sache      ioctl (tty, TIOCSLTC, &(tiop->ltchars));
28821308Sache      tiop->flags &= ~LTCHARS_SET;
28921308Sache    }
29021308Sache#endif
29121308Sache
29221308Sache  return 0;
29321308Sache}
29421308Sache
29521308Sachestatic void
29675406Sacheprepare_terminal_settings (meta_flag, oldtio, tiop)
29721308Sache     int meta_flag;
29875406Sache     TIOTYPE oldtio, *tiop;
29921308Sache{
30075406Sache  readline_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
30121308Sache
30221308Sache  /* Copy the original settings to the structure we're going to use for
30321308Sache     our settings. */
30475406Sache  tiop->sgttyb = oldtio.sgttyb;
30575406Sache  tiop->lflag = oldtio.lflag;
30621308Sache#if defined (TIOCGETC)
30775406Sache  tiop->tchars = oldtio.tchars;
30821308Sache#endif
30921308Sache#if defined (TIOCGLTC)
31075406Sache  tiop->ltchars = oldtio.ltchars;
31121308Sache#endif
31275406Sache  tiop->flags = oldtio.flags;
31321308Sache
31421308Sache  /* First, the basic settings to put us into character-at-a-time, no-echo
31521308Sache     input mode. */
31621308Sache  tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
31721308Sache  tiop->sgttyb.sg_flags |= CBREAK;
31821308Sache
31921308Sache  /* If this terminal doesn't care how the 8th bit is used, then we can
32021308Sache     use it for the meta-key.  If only one of even or odd parity is
32121308Sache     specified, then the terminal is using parity, and we cannot. */
32221308Sache#if !defined (ANYP)
32321308Sache#  define ANYP (EVENP | ODDP)
32421308Sache#endif
32575406Sache  if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
32675406Sache      ((oldtio.sgttyb.sg_flags & ANYP) == 0))
32721308Sache    {
32821308Sache      tiop->sgttyb.sg_flags |= ANYP;
32921308Sache
33021308Sache      /* Hack on local mode flags if we can. */
33121308Sache#if defined (TIOCLGET)
33221308Sache#  if defined (LPASS8)
33321308Sache      tiop->lflag |= LPASS8;
33421308Sache#  endif /* LPASS8 */
33521308Sache#endif /* TIOCLGET */
33621308Sache    }
33721308Sache
33821308Sache#if defined (TIOCGETC)
33921308Sache#  if defined (USE_XON_XOFF)
34021308Sache  /* Get rid of terminal output start and stop characters. */
34121308Sache  tiop->tchars.t_stopc = -1; /* C-s */
34221308Sache  tiop->tchars.t_startc = -1; /* C-q */
34321308Sache
34421308Sache  /* If there is an XON character, bind it to restart the output. */
34575406Sache  if (oldtio.tchars.t_startc != -1)
34675406Sache    rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
34721308Sache#  endif /* USE_XON_XOFF */
34821308Sache
34921308Sache  /* If there is an EOF char, bind _rl_eof_char to it. */
35075406Sache  if (oldtio.tchars.t_eofc != -1)
35175406Sache    _rl_eof_char = oldtio.tchars.t_eofc;
35221308Sache
35321308Sache#  if defined (NO_KILL_INTR)
35421308Sache  /* Get rid of terminal-generated SIGQUIT and SIGINT. */
35521308Sache  tiop->tchars.t_quitc = -1; /* C-\ */
35621308Sache  tiop->tchars.t_intrc = -1; /* C-c */
35721308Sache#  endif /* NO_KILL_INTR */
35821308Sache#endif /* TIOCGETC */
35921308Sache
36021308Sache#if defined (TIOCGLTC)
36121308Sache  /* Make the interrupt keys go away.  Just enough to make people happy. */
36221308Sache  tiop->ltchars.t_dsuspc = -1;	/* C-y */
36321308Sache  tiop->ltchars.t_lnextc = -1;	/* C-v */
36421308Sache#endif /* TIOCGLTC */
36521308Sache}
36621308Sache
36721308Sache#else  /* !defined (NEW_TTY_DRIVER) */
36821308Sache
36921308Sache#if !defined (VMIN)
37021308Sache#  define VMIN VEOF
37121308Sache#endif
37221308Sache
37321308Sache#if !defined (VTIME)
37421308Sache#  define VTIME VEOL
37521308Sache#endif
37621308Sache
37721308Sache#if defined (TERMIOS_TTY_DRIVER)
37821308Sache#  define TIOTYPE struct termios
37921308Sache#  define DRAIN_OUTPUT(fd)	tcdrain (fd)
38021308Sache#  define GETATTR(tty, tiop)	(tcgetattr (tty, tiop))
38121308Sache#  ifdef M_UNIX
38221308Sache#    define SETATTR(tty, tiop)	(tcsetattr (tty, TCSANOW, tiop))
38321308Sache#  else
38421308Sache#    define SETATTR(tty, tiop)	(tcsetattr (tty, TCSADRAIN, tiop))
38521308Sache#  endif /* !M_UNIX */
38621308Sache#else
38721308Sache#  define TIOTYPE struct termio
38821308Sache#  define DRAIN_OUTPUT(fd)
38921308Sache#  define GETATTR(tty, tiop)	(ioctl (tty, TCGETA, tiop))
39075406Sache#  define SETATTR(tty, tiop)	(ioctl (tty, TCSETAW, tiop))
39121308Sache#endif /* !TERMIOS_TTY_DRIVER */
39221308Sache
39321308Sachestatic TIOTYPE otio;
39421308Sache
395119610Sachestatic void save_tty_chars PARAMS((TIOTYPE *));
396119610Sachestatic int _get_tty_settings PARAMS((int, TIOTYPE *));
397119610Sachestatic int get_tty_settings PARAMS((int, TIOTYPE *));
398119610Sachestatic int _set_tty_settings PARAMS((int, TIOTYPE *));
399119610Sachestatic int set_tty_settings PARAMS((int, TIOTYPE *));
400119610Sache
401119610Sachestatic void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
402119610Sache
40321308Sache#if defined (FLUSHO)
40421308Sache#  define OUTPUT_BEING_FLUSHED(tp)  (tp->c_lflag & FLUSHO)
40521308Sache#else
40621308Sache#  define OUTPUT_BEING_FLUSHED(tp)  0
40721308Sache#endif
40821308Sache
40921308Sachestatic void
41058310Sachesave_tty_chars (tiop)
41158310Sache     TIOTYPE *tiop;
41258310Sache{
41358310Sache  _rl_last_tty_chars = _rl_tty_chars;
41458310Sache
41558310Sache  _rl_tty_chars.t_eof = tiop->c_cc[VEOF];
41658310Sache  _rl_tty_chars.t_eol = tiop->c_cc[VEOL];
41758310Sache#ifdef VEOL2
41858310Sache  _rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
41958310Sache#endif
42058310Sache  _rl_tty_chars.t_erase = tiop->c_cc[VERASE];
42158310Sache#ifdef VWERASE
42258310Sache  _rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
42358310Sache#endif
42458310Sache  _rl_tty_chars.t_kill = tiop->c_cc[VKILL];
42558310Sache#ifdef VREPRINT
42658310Sache  _rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
42758310Sache#endif
42858310Sache  _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
42958310Sache  _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
43058310Sache#ifdef VSUSP
43158310Sache  _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
43258310Sache#endif
43358310Sache#ifdef VDSUSP
43458310Sache  _rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
43558310Sache#endif
43658310Sache#ifdef VSTART
43758310Sache  _rl_tty_chars.t_start = tiop->c_cc[VSTART];
43858310Sache#endif
43958310Sache#ifdef VSTOP
44058310Sache  _rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
44158310Sache#endif
44258310Sache#ifdef VLNEXT
44358310Sache  _rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
44458310Sache#endif
44558310Sache#ifdef VDISCARD
44658310Sache  _rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
44758310Sache#endif
44858310Sache#ifdef VSTATUS
44958310Sache  _rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
45058310Sache#endif
45158310Sache}
45258310Sache
45358310Sache#if defined (_AIX) || defined (_AIX41)
45458310Sache/* Currently this is only used on AIX */
45558310Sachestatic void
45621308Sacherltty_warning (msg)
45721308Sache     char *msg;
45821308Sache{
45921308Sache  fprintf (stderr, "readline: warning: %s\n", msg);
46021308Sache}
46158310Sache#endif
46221308Sache
46321308Sache#if defined (_AIX)
46421308Sachevoid
46521308Sachesetopost(tp)
46621308SacheTIOTYPE *tp;
46721308Sache{
46821308Sache  if ((tp->c_oflag & OPOST) == 0)
46921308Sache    {
47021308Sache      rltty_warning ("turning on OPOST for terminal\r");
47121308Sache      tp->c_oflag |= OPOST|ONLCR;
47221308Sache    }
47321308Sache}
47421308Sache#endif
47521308Sache
47621308Sachestatic int
47758310Sache_get_tty_settings (tty, tiop)
47821308Sache     int tty;
47921308Sache     TIOTYPE *tiop;
48021308Sache{
48121308Sache  int ioctl_ret;
48247558Sache
48321308Sache  while (1)
48421308Sache    {
48521308Sache      ioctl_ret = GETATTR (tty, tiop);
48621308Sache      if (ioctl_ret < 0)
48721308Sache	{
48821308Sache	  if (errno != EINTR)
48921308Sache	    return -1;
49021308Sache	  else
49121308Sache	    continue;
49221308Sache	}
49321308Sache      if (OUTPUT_BEING_FLUSHED (tiop))
49421308Sache	{
49521308Sache#if defined (FLUSHO) && defined (_AIX41)
49621308Sache	  rltty_warning ("turning off output flushing");
49721308Sache	  tiop->c_lflag &= ~FLUSHO;
49821308Sache	  break;
49921308Sache#else
50021308Sache	  continue;
50121308Sache#endif
50221308Sache	}
50321308Sache      break;
50421308Sache    }
50521308Sache
50658310Sache  return 0;
50758310Sache}
50858310Sache
50958310Sachestatic int
51058310Sacheget_tty_settings (tty, tiop)
51158310Sache     int tty;
51258310Sache     TIOTYPE *tiop;
51358310Sache{
51458310Sache  set_winsize (tty);
51558310Sache
51658310Sache  if (_get_tty_settings (tty, tiop) < 0)
51758310Sache    return -1;
51858310Sache
51921308Sache#if defined (_AIX)
52021308Sache  setopost(tiop);
52121308Sache#endif
52221308Sache
52321308Sache  return 0;
52421308Sache}
52521308Sache
52621308Sachestatic int
52758310Sache_set_tty_settings (tty, tiop)
52821308Sache     int tty;
52921308Sache     TIOTYPE *tiop;
53021308Sache{
53121308Sache  while (SETATTR (tty, tiop) < 0)
53221308Sache    {
53321308Sache      if (errno != EINTR)
53421308Sache	return -1;
53521308Sache      errno = 0;
53621308Sache    }
53758310Sache  return 0;
53858310Sache}
53921308Sache
54058310Sachestatic int
54158310Sacheset_tty_settings (tty, tiop)
54258310Sache     int tty;
54358310Sache     TIOTYPE *tiop;
54458310Sache{
54558310Sache  if (_set_tty_settings (tty, tiop) < 0)
54658310Sache    return -1;
54758310Sache
54821308Sache#if 0
54921308Sache
55021308Sache#if defined (TERMIOS_TTY_DRIVER)
55121308Sache#  if defined (__ksr1__)
55221308Sache  if (ksrflow)
55321308Sache    {
55421308Sache      ksrflow = 0;
55521308Sache      tcflow (tty, TCOON);
55621308Sache    }
55721308Sache#  else /* !ksr1 */
55821308Sache  tcflow (tty, TCOON);		/* Simulate a ^Q. */
55921308Sache#  endif /* !ksr1 */
56021308Sache#else
56121308Sache  ioctl (tty, TCXONC, 1);	/* Simulate a ^Q. */
56221308Sache#endif /* !TERMIOS_TTY_DRIVER */
56321308Sache
56458310Sache#endif /* 0 */
56521308Sache
56621308Sache  return 0;
56721308Sache}
56821308Sache
56921308Sachestatic void
57075406Sacheprepare_terminal_settings (meta_flag, oldtio, tiop)
57121308Sache     int meta_flag;
57275406Sache     TIOTYPE oldtio, *tiop;
57321308Sache{
57475406Sache  readline_echoing_p = (oldtio.c_lflag & ECHO);
57521308Sache
57621308Sache  tiop->c_lflag &= ~(ICANON | ECHO);
57721308Sache
57875406Sache  if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
57975406Sache    _rl_eof_char = oldtio.c_cc[VEOF];
58021308Sache
58121308Sache#if defined (USE_XON_XOFF)
58221308Sache#if defined (IXANY)
58321308Sache  tiop->c_iflag &= ~(IXON | IXOFF | IXANY);
58421308Sache#else
58521308Sache  /* `strict' Posix systems do not define IXANY. */
58621308Sache  tiop->c_iflag &= ~(IXON | IXOFF);
58721308Sache#endif /* IXANY */
58821308Sache#endif /* USE_XON_XOFF */
58921308Sache
59021308Sache  /* Only turn this off if we are using all 8 bits. */
59121308Sache  if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
59221308Sache    tiop->c_iflag &= ~(ISTRIP | INPCK);
59321308Sache
59421308Sache  /* Make sure we differentiate between CR and NL on input. */
59521308Sache  tiop->c_iflag &= ~(ICRNL | INLCR);
59621308Sache
59721308Sache#if !defined (HANDLE_SIGNALS)
59821308Sache  tiop->c_lflag &= ~ISIG;
59921308Sache#else
60021308Sache  tiop->c_lflag |= ISIG;
60121308Sache#endif
60221308Sache
60321308Sache  tiop->c_cc[VMIN] = 1;
60421308Sache  tiop->c_cc[VTIME] = 0;
60521308Sache
60621308Sache#if defined (FLUSHO)
60721308Sache  if (OUTPUT_BEING_FLUSHED (tiop))
60821308Sache    {
60921308Sache      tiop->c_lflag &= ~FLUSHO;
61075406Sache      oldtio.c_lflag &= ~FLUSHO;
61121308Sache    }
61221308Sache#endif
61321308Sache
61421308Sache  /* Turn off characters that we need on Posix systems with job control,
61521308Sache     just to be sure.  This includes ^Y and ^V.  This should not really
61621308Sache     be necessary.  */
61721308Sache#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
61821308Sache
61921308Sache#if defined (VLNEXT)
62021308Sache  tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
62121308Sache#endif
62221308Sache
62321308Sache#if defined (VDSUSP)
62421308Sache  tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
62521308Sache#endif
62621308Sache
62721308Sache#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
62821308Sache}
62921308Sache#endif  /* NEW_TTY_DRIVER */
63021308Sache
63121308Sache/* Put the terminal in CBREAK mode so that we can detect key presses. */
63221308Sachevoid
63321308Sacherl_prep_terminal (meta_flag)
63421308Sache     int meta_flag;
63521308Sache{
63621308Sache  int tty;
63721308Sache  TIOTYPE tio;
63821308Sache
63921308Sache  if (terminal_prepped)
64021308Sache    return;
64121308Sache
64221308Sache  /* Try to keep this function from being INTerrupted. */
64321308Sache  block_sigint ();
64421308Sache
64521308Sache  tty = fileno (rl_instream);
64621308Sache
64721308Sache  if (get_tty_settings (tty, &tio) < 0)
64821308Sache    {
64921308Sache      release_sigint ();
65021308Sache      return;
65121308Sache    }
65221308Sache
65321308Sache  otio = tio;
65421308Sache
65558310Sache  save_tty_chars (&otio);
65658310Sache
65721308Sache  prepare_terminal_settings (meta_flag, otio, &tio);
65821308Sache
65921308Sache  if (set_tty_settings (tty, &tio) < 0)
66021308Sache    {
66121308Sache      release_sigint ();
66221308Sache      return;
66321308Sache    }
66421308Sache
66521308Sache  if (_rl_enable_keypad)
66621308Sache    _rl_control_keypad (1);
66721308Sache
66821308Sache  fflush (rl_outstream);
66921308Sache  terminal_prepped = 1;
67075406Sache  RL_SETSTATE(RL_STATE_TERMPREPPED);
67121308Sache
67221308Sache  release_sigint ();
67321308Sache}
67421308Sache
67521308Sache/* Restore the terminal's normal settings and modes. */
67621308Sachevoid
67721308Sacherl_deprep_terminal ()
67821308Sache{
67921308Sache  int tty;
68021308Sache
68121308Sache  if (!terminal_prepped)
68221308Sache    return;
68321308Sache
68421308Sache  /* Try to keep this function from being interrupted. */
68521308Sache  block_sigint ();
68621308Sache
68721308Sache  tty = fileno (rl_instream);
68821308Sache
68921308Sache  if (_rl_enable_keypad)
69021308Sache    _rl_control_keypad (0);
69121308Sache
69221308Sache  fflush (rl_outstream);
69321308Sache
69421308Sache  if (set_tty_settings (tty, &otio) < 0)
69521308Sache    {
69621308Sache      release_sigint ();
69721308Sache      return;
69821308Sache    }
69921308Sache
70021308Sache  terminal_prepped = 0;
70175406Sache  RL_UNSETSTATE(RL_STATE_TERMPREPPED);
70221308Sache
70321308Sache  release_sigint ();
70421308Sache}
70521308Sache
70621308Sache/* **************************************************************** */
70721308Sache/*								    */
70821308Sache/*			Bogus Flow Control      		    */
70921308Sache/*								    */
71021308Sache/* **************************************************************** */
71121308Sache
71221308Sacheint
71321308Sacherl_restart_output (count, key)
71421308Sache     int count, key;
71521308Sache{
71621308Sache  int fildes = fileno (rl_outstream);
71721308Sache#if defined (TIOCSTART)
71821308Sache#if defined (apollo)
71921308Sache  ioctl (&fildes, TIOCSTART, 0);
72021308Sache#else
72121308Sache  ioctl (fildes, TIOCSTART, 0);
72221308Sache#endif /* apollo */
72321308Sache
72421308Sache#else /* !TIOCSTART */
72521308Sache#  if defined (TERMIOS_TTY_DRIVER)
72621308Sache#    if defined (__ksr1__)
72721308Sache  if (ksrflow)
72821308Sache    {
72921308Sache      ksrflow = 0;
73021308Sache      tcflow (fildes, TCOON);
73121308Sache    }
73221308Sache#    else /* !ksr1 */
73321308Sache  tcflow (fildes, TCOON);		/* Simulate a ^Q. */
73421308Sache#    endif /* !ksr1 */
73521308Sache#  else /* !TERMIOS_TTY_DRIVER */
73621308Sache#    if defined (TCXONC)
73721308Sache  ioctl (fildes, TCXONC, TCOON);
73821308Sache#    endif /* TCXONC */
73921308Sache#  endif /* !TERMIOS_TTY_DRIVER */
74021308Sache#endif /* !TIOCSTART */
74121308Sache
74221308Sache  return 0;
74321308Sache}
74421308Sache
74521308Sacheint
74621308Sacherl_stop_output (count, key)
74721308Sache     int count, key;
74821308Sache{
74921308Sache  int fildes = fileno (rl_instream);
75021308Sache
75121308Sache#if defined (TIOCSTOP)
75221308Sache# if defined (apollo)
75321308Sache  ioctl (&fildes, TIOCSTOP, 0);
75421308Sache# else
75521308Sache  ioctl (fildes, TIOCSTOP, 0);
75621308Sache# endif /* apollo */
75721308Sache#else /* !TIOCSTOP */
75821308Sache# if defined (TERMIOS_TTY_DRIVER)
75921308Sache#  if defined (__ksr1__)
76021308Sache  ksrflow = 1;
76121308Sache#  endif /* ksr1 */
76221308Sache  tcflow (fildes, TCOOFF);
76321308Sache# else
76421308Sache#   if defined (TCXONC)
76521308Sache  ioctl (fildes, TCXONC, TCOON);
76621308Sache#   endif /* TCXONC */
76721308Sache# endif /* !TERMIOS_TTY_DRIVER */
76821308Sache#endif /* !TIOCSTOP */
76921308Sache
77021308Sache  return 0;
77121308Sache}
77221308Sache
77321308Sache/* **************************************************************** */
77421308Sache/*								    */
77521308Sache/*			Default Key Bindings			    */
77621308Sache/*								    */
77721308Sache/* **************************************************************** */
77875406Sache
77975406Sache/* Set the system's default editing characters to their readline equivalents
78075406Sache   in KMAP.  Should be static, now that we have rl_tty_set_default_bindings. */
78121308Sachevoid
78221308Sacherltty_set_default_bindings (kmap)
78321308Sache     Keymap kmap;
78421308Sache{
78521308Sache  TIOTYPE ttybuff;
78621308Sache  int tty = fileno (rl_instream);
78721308Sache
78821308Sache#if defined (NEW_TTY_DRIVER)
78921308Sache
79021308Sache#define SET_SPECIAL(sc, func) \
79121308Sache  do \
79221308Sache    { \
79321308Sache      int ic; \
79421308Sache      ic = sc; \
795119610Sache      if (ic != -1 && kmap[(unsigned char)ic].type == ISFUNC) \
796119610Sache	kmap[(unsigned char)ic].function = func; \
79721308Sache    } \
79821308Sache  while (0)
79921308Sache
80021308Sache  if (get_tty_settings (tty, &ttybuff) == 0)
80121308Sache    {
80221308Sache      if (ttybuff.flags & SGTTY_SET)
80321308Sache	{
80421308Sache	  SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
80521308Sache	  SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
80621308Sache	}
80721308Sache
80821308Sache#  if defined (TIOCGLTC)
80921308Sache      if (ttybuff.flags & LTCHARS_SET)
81021308Sache	{
81121308Sache	  SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
81221308Sache	  SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
81321308Sache	}
81421308Sache#  endif /* TIOCGLTC */
81521308Sache    }
81621308Sache
81721308Sache#else /* !NEW_TTY_DRIVER */
81821308Sache
81921308Sache#define SET_SPECIAL(sc, func) \
82021308Sache  do \
82121308Sache    { \
82221308Sache      unsigned char uc; \
82321308Sache      uc = ttybuff.c_cc[sc]; \
82421308Sache      if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
82521308Sache	kmap[uc].function = func; \
82621308Sache    } \
82721308Sache  while (0)
82821308Sache
82921308Sache  if (get_tty_settings (tty, &ttybuff) == 0)
83021308Sache    {
83121308Sache      SET_SPECIAL (VERASE, rl_rubout);
83221308Sache      SET_SPECIAL (VKILL, rl_unix_line_discard);
83321308Sache
83421308Sache#  if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
83521308Sache      SET_SPECIAL (VLNEXT, rl_quoted_insert);
83621308Sache#  endif /* VLNEXT && TERMIOS_TTY_DRIVER */
83721308Sache
83821308Sache#  if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
83921308Sache      SET_SPECIAL (VWERASE, rl_unix_word_rubout);
84021308Sache#  endif /* VWERASE && TERMIOS_TTY_DRIVER */
84121308Sache    }
84221308Sache#endif /* !NEW_TTY_DRIVER */
84321308Sache}
84458310Sache
84575406Sache/* New public way to set the system default editing chars to their readline
84675406Sache   equivalents. */
84775406Sachevoid
84875406Sacherl_tty_set_default_bindings (kmap)
84975406Sache     Keymap kmap;
85075406Sache{
85175406Sache  rltty_set_default_bindings (kmap);
85275406Sache}
85375406Sache
85458310Sache#if defined (HANDLE_SIGNALS)
85558310Sache
85658310Sache#if defined (NEW_TTY_DRIVER)
85758310Sacheint
85858310Sache_rl_disable_tty_signals ()
85958310Sache{
86058310Sache  return 0;
86158310Sache}
86258310Sache
86358310Sacheint
86458310Sache_rl_restore_tty_signals ()
86558310Sache{
86658310Sache  return 0;
86758310Sache}
86858310Sache#else
86958310Sache
87058310Sachestatic TIOTYPE sigstty, nosigstty;
87158310Sachestatic int tty_sigs_disabled = 0;
87258310Sache
87358310Sacheint
87458310Sache_rl_disable_tty_signals ()
87558310Sache{
87658310Sache  if (tty_sigs_disabled)
87758310Sache    return 0;
87858310Sache
87958310Sache  if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
88058310Sache    return -1;
88158310Sache
88258310Sache  nosigstty = sigstty;
88358310Sache
88458310Sache  nosigstty.c_lflag &= ~ISIG;
885119610Sache  nosigstty.c_iflag &= ~IXON;
88658310Sache
88758310Sache  if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
88858310Sache    return (_set_tty_settings (fileno (rl_instream), &sigstty));
88958310Sache
89058310Sache  tty_sigs_disabled = 1;
89158310Sache  return 0;
89258310Sache}
89358310Sache
89458310Sacheint
89558310Sache_rl_restore_tty_signals ()
89658310Sache{
897119610Sache  int r;
898119610Sache
89958310Sache  if (tty_sigs_disabled == 0)
90058310Sache    return 0;
90158310Sache
902119610Sache  r = _set_tty_settings (fileno (rl_instream), &sigstty);
903119610Sache
904119610Sache  if (r == 0)
905119610Sache    tty_sigs_disabled = 0;
906119610Sache
907119610Sache  return r;
90858310Sache}
90958310Sache#endif /* !NEW_TTY_DRIVER */
91058310Sache
91158310Sache#endif /* HANDLE_SIGNALS */
912