4a11f20659
This patch syncs our upstream copy of readline from version 6.2 to the latest version, 7.0 alpha (released July 10 2015). I essentially copied what was done the last time readline was synced, when Jan updated to readline 6.2 in 2011: http://sourceware.org/ml/gdb-patches/2011-05/msg00003.html Procedure: 1. I extracted the readline-7.0-alpha tarball on top of readline/. 2. I deleted all the new files under doc/ that were deliberately omitted before. 3. I regenerated readline/configure and readline/examples/rlfe/configure using autoconf 2.64. No other configure files need regenerating. 4. I updated the function gdb_printable_part in completer.c with a trivial change made to the readline function it is based off of, printable_part in readline/complete.c. There is more work to be done in completer.c to sync it with readline/complete.c, but it is non-trivial and should probably be done separately anyway. Local patches that had to be reapplied: None. readline 7.0 alpha contains all of our local readline patches. New files in readline/: colors.{c,h} examples/{hist_erasedups,hist_purgecmd,rl-callbacktest,rlbasic}.c parse-colors.{c,h} readline.pc.in configure.ac Deleted files in readline/: configure.in Regressions: After the sync there is one testsuite regression, the test "signal SIGINT" in gdb.gdb/selftest.exp which now FAILs. Previously, the readline 6.2 SIGINT handler would temporarily reinstall the underlying application's SIGINT handler and immediately re-raise SIGINT so that the orginal handler gets invoked. But now (since readline 6.3) its SIGINT handler does not re-raise SIGINT or directly invoke the original handler; it now sets a flag marking that SIGINT was raised, and waits until readline explicitly has control to call the application's SIGINT handler. Anyway, because SIGINT is no longer re-raised from within readline's SIGINT handler, doing "signal SIGINT" with a stopped inferior gdb process will no longer resume and then immediately stop the process (since there is no 2nd SIGINT to immediately catch). Instead, the inferior gdb process will now just print "Quit" and continue to run. So with this commit, this particular test case is adjusted to reflect this change in behavior (we now have to send a 2nd SIGINT manually to stop it). Aside from this one testsuite regression, I personally noticed no regression in user-visible behavior. Though I only tested on x86_64 and on i686 Debian Stretch. Getting this kind of change in at the start of the GDB 7.11 development cycle will allow us to get a lot of passive testing from developers and from bleeding-edge users. readline/ChangeLog.gdb: Import readline 7.0 alpha * configure: Regenerate. * examples/rlfe/configure: Regenerate. gdb/ChangeLog: * completer.c (gdb_printable_part): Sync with readline function it is based off of. gdb/testsuite/ChangeLog: * gdb.gdb/selftest.exp (test_with_self): Update test to now expect the GDB inferior to no longer immediately stop after being resumed with "signal SIGINT".
992 lines
23 KiB
C
992 lines
23 KiB
C
/* rltty.c -- functions to prepare and restore the terminal for readline's
|
||
use. */
|
||
|
||
/* Copyright (C) 1992-2005 Free Software Foundation, Inc.
|
||
|
||
This file is part of the GNU Readline Library (Readline), a library
|
||
for reading lines of text with interactive input and history editing.
|
||
|
||
Readline is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
Readline is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU General Public License for more details.
|
||
|
||
You should have received a copy of the GNU General Public License
|
||
along with Readline. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#define READLINE_LIBRARY
|
||
|
||
#if defined (HAVE_CONFIG_H)
|
||
# include <config.h>
|
||
#endif
|
||
|
||
#include <sys/types.h>
|
||
#include <signal.h>
|
||
#include <errno.h>
|
||
#include <stdio.h>
|
||
|
||
#if defined (HAVE_UNISTD_H)
|
||
# include <unistd.h>
|
||
#endif /* HAVE_UNISTD_H */
|
||
|
||
#include "rldefs.h"
|
||
|
||
#include "rltty.h"
|
||
#if defined (HAVE_SYS_IOCTL_H)
|
||
# include <sys/ioctl.h> /* include for declaration of ioctl */
|
||
#endif
|
||
|
||
#include "readline.h"
|
||
#include "rlprivate.h"
|
||
|
||
#if !defined (errno)
|
||
extern int errno;
|
||
#endif /* !errno */
|
||
|
||
rl_vintfunc_t *rl_prep_term_function = rl_prep_terminal;
|
||
rl_voidfunc_t *rl_deprep_term_function = rl_deprep_terminal;
|
||
|
||
static void set_winsize PARAMS((int));
|
||
|
||
/* **************************************************************** */
|
||
/* */
|
||
/* Saving and Restoring the TTY */
|
||
/* */
|
||
/* **************************************************************** */
|
||
|
||
/* Non-zero means that the terminal is in a prepped state. There are several
|
||
flags that are OR'd in to denote whether or not we have sent various
|
||
init strings to the terminal. */
|
||
#define TPX_PREPPED 0x01
|
||
#define TPX_BRACKPASTE 0x02
|
||
#define TPX_METAKEY 0x04
|
||
|
||
static int terminal_prepped;
|
||
|
||
static _RL_TTY_CHARS _rl_tty_chars, _rl_last_tty_chars;
|
||
|
||
/* If non-zero, means that this process has called tcflow(fd, TCOOFF)
|
||
and output is suspended. */
|
||
#if defined (__ksr1__)
|
||
static int ksrflow;
|
||
#endif
|
||
|
||
/* Dummy call to force a backgrounded readline to stop before it tries
|
||
to get the tty settings. */
|
||
static void
|
||
set_winsize (tty)
|
||
int tty;
|
||
{
|
||
#if defined (TIOCGWINSZ)
|
||
struct winsize w;
|
||
|
||
if (ioctl (tty, TIOCGWINSZ, &w) == 0)
|
||
(void) ioctl (tty, TIOCSWINSZ, &w);
|
||
#endif /* TIOCGWINSZ */
|
||
}
|
||
|
||
#if defined (NO_TTY_DRIVER)
|
||
/* Nothing */
|
||
#elif defined (NEW_TTY_DRIVER)
|
||
|
||
/* Values for the `flags' field of a struct bsdtty. This tells which
|
||
elements of the struct bsdtty have been fetched from the system and
|
||
are valid. */
|
||
#define SGTTY_SET 0x01
|
||
#define LFLAG_SET 0x02
|
||
#define TCHARS_SET 0x04
|
||
#define LTCHARS_SET 0x08
|
||
|
||
struct bsdtty {
|
||
struct sgttyb sgttyb; /* Basic BSD tty driver information. */
|
||
int lflag; /* Local mode flags, like LPASS8. */
|
||
#if defined (TIOCGETC)
|
||
struct tchars tchars; /* Terminal special characters, including ^S and ^Q. */
|
||
#endif
|
||
#if defined (TIOCGLTC)
|
||
struct ltchars ltchars; /* 4.2 BSD editing characters */
|
||
#endif
|
||
int flags; /* Bitmap saying which parts of the struct are valid. */
|
||
};
|
||
|
||
#define TIOTYPE struct bsdtty
|
||
|
||
static TIOTYPE otio;
|
||
|
||
static void save_tty_chars PARAMS((TIOTYPE *));
|
||
static int _get_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int get_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int _set_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int set_tty_settings PARAMS((int, TIOTYPE *));
|
||
|
||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||
|
||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
|
||
|
||
static void
|
||
save_tty_chars (tiop)
|
||
TIOTYPE *tiop;
|
||
{
|
||
_rl_last_tty_chars = _rl_tty_chars;
|
||
|
||
if (tiop->flags & SGTTY_SET)
|
||
{
|
||
_rl_tty_chars.t_erase = tiop->sgttyb.sg_erase;
|
||
_rl_tty_chars.t_kill = tiop->sgttyb.sg_kill;
|
||
}
|
||
|
||
if (tiop->flags & TCHARS_SET)
|
||
{
|
||
_rl_intr_char = _rl_tty_chars.t_intr = tiop->tchars.t_intrc;
|
||
_rl_quit_char = _rl_tty_chars.t_quit = tiop->tchars.t_quitc;
|
||
|
||
_rl_tty_chars.t_start = tiop->tchars.t_startc;
|
||
_rl_tty_chars.t_stop = tiop->tchars.t_stopc;
|
||
_rl_tty_chars.t_eof = tiop->tchars.t_eofc;
|
||
_rl_tty_chars.t_eol = '\n';
|
||
_rl_tty_chars.t_eol2 = tiop->tchars.t_brkc;
|
||
}
|
||
|
||
if (tiop->flags & LTCHARS_SET)
|
||
{
|
||
_rl_susp_char = _rl_tty_chars.t_susp = tiop->ltchars.t_suspc;
|
||
|
||
_rl_tty_chars.t_dsusp = tiop->ltchars.t_dsuspc;
|
||
_rl_tty_chars.t_reprint = tiop->ltchars.t_rprntc;
|
||
_rl_tty_chars.t_flush = tiop->ltchars.t_flushc;
|
||
_rl_tty_chars.t_werase = tiop->ltchars.t_werasc;
|
||
_rl_tty_chars.t_lnext = tiop->ltchars.t_lnextc;
|
||
}
|
||
|
||
_rl_tty_chars.t_status = -1;
|
||
}
|
||
|
||
static int
|
||
get_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
set_winsize (tty);
|
||
|
||
tiop->flags = tiop->lflag = 0;
|
||
|
||
errno = 0;
|
||
if (ioctl (tty, TIOCGETP, &(tiop->sgttyb)) < 0)
|
||
return -1;
|
||
tiop->flags |= SGTTY_SET;
|
||
|
||
#if defined (TIOCLGET)
|
||
if (ioctl (tty, TIOCLGET, &(tiop->lflag)) == 0)
|
||
tiop->flags |= LFLAG_SET;
|
||
#endif
|
||
|
||
#if defined (TIOCGETC)
|
||
if (ioctl (tty, TIOCGETC, &(tiop->tchars)) == 0)
|
||
tiop->flags |= TCHARS_SET;
|
||
#endif
|
||
|
||
#if defined (TIOCGLTC)
|
||
if (ioctl (tty, TIOCGLTC, &(tiop->ltchars)) == 0)
|
||
tiop->flags |= LTCHARS_SET;
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
set_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
if (tiop->flags & SGTTY_SET)
|
||
{
|
||
ioctl (tty, TIOCSETN, &(tiop->sgttyb));
|
||
tiop->flags &= ~SGTTY_SET;
|
||
}
|
||
_rl_echoing_p = 1;
|
||
|
||
#if defined (TIOCLSET)
|
||
if (tiop->flags & LFLAG_SET)
|
||
{
|
||
ioctl (tty, TIOCLSET, &(tiop->lflag));
|
||
tiop->flags &= ~LFLAG_SET;
|
||
}
|
||
#endif
|
||
|
||
#if defined (TIOCSETC)
|
||
if (tiop->flags & TCHARS_SET)
|
||
{
|
||
ioctl (tty, TIOCSETC, &(tiop->tchars));
|
||
tiop->flags &= ~TCHARS_SET;
|
||
}
|
||
#endif
|
||
|
||
#if defined (TIOCSLTC)
|
||
if (tiop->flags & LTCHARS_SET)
|
||
{
|
||
ioctl (tty, TIOCSLTC, &(tiop->ltchars));
|
||
tiop->flags &= ~LTCHARS_SET;
|
||
}
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void
|
||
prepare_terminal_settings (meta_flag, oldtio, tiop)
|
||
int meta_flag;
|
||
TIOTYPE oldtio, *tiop;
|
||
{
|
||
_rl_echoing_p = (oldtio.sgttyb.sg_flags & ECHO);
|
||
_rl_echoctl = (oldtio.sgttyb.sg_flags & ECHOCTL);
|
||
|
||
/* Copy the original settings to the structure we're going to use for
|
||
our settings. */
|
||
tiop->sgttyb = oldtio.sgttyb;
|
||
tiop->lflag = oldtio.lflag;
|
||
#if defined (TIOCGETC)
|
||
tiop->tchars = oldtio.tchars;
|
||
#endif
|
||
#if defined (TIOCGLTC)
|
||
tiop->ltchars = oldtio.ltchars;
|
||
#endif
|
||
tiop->flags = oldtio.flags;
|
||
|
||
/* First, the basic settings to put us into character-at-a-time, no-echo
|
||
input mode. */
|
||
tiop->sgttyb.sg_flags &= ~(ECHO | CRMOD);
|
||
tiop->sgttyb.sg_flags |= CBREAK;
|
||
|
||
/* If this terminal doesn't care how the 8th bit is used, then we can
|
||
use it for the meta-key. If only one of even or odd parity is
|
||
specified, then the terminal is using parity, and we cannot. */
|
||
#if !defined (ANYP)
|
||
# define ANYP (EVENP | ODDP)
|
||
#endif
|
||
if (((oldtio.sgttyb.sg_flags & ANYP) == ANYP) ||
|
||
((oldtio.sgttyb.sg_flags & ANYP) == 0))
|
||
{
|
||
tiop->sgttyb.sg_flags |= ANYP;
|
||
|
||
/* Hack on local mode flags if we can. */
|
||
#if defined (TIOCLGET)
|
||
# if defined (LPASS8)
|
||
tiop->lflag |= LPASS8;
|
||
# endif /* LPASS8 */
|
||
#endif /* TIOCLGET */
|
||
}
|
||
|
||
#if defined (TIOCGETC)
|
||
# if defined (USE_XON_XOFF)
|
||
/* Get rid of terminal output start and stop characters. */
|
||
tiop->tchars.t_stopc = -1; /* C-s */
|
||
tiop->tchars.t_startc = -1; /* C-q */
|
||
|
||
/* If there is an XON character, bind it to restart the output. */
|
||
if (oldtio.tchars.t_startc != -1)
|
||
rl_bind_key (oldtio.tchars.t_startc, rl_restart_output);
|
||
# endif /* USE_XON_XOFF */
|
||
|
||
/* If there is an EOF char, bind _rl_eof_char to it. */
|
||
if (oldtio.tchars.t_eofc != -1)
|
||
_rl_eof_char = oldtio.tchars.t_eofc;
|
||
|
||
# if defined (NO_KILL_INTR)
|
||
/* Get rid of terminal-generated SIGQUIT and SIGINT. */
|
||
tiop->tchars.t_quitc = -1; /* C-\ */
|
||
tiop->tchars.t_intrc = -1; /* C-c */
|
||
# endif /* NO_KILL_INTR */
|
||
#endif /* TIOCGETC */
|
||
|
||
#if defined (TIOCGLTC)
|
||
/* Make the interrupt keys go away. Just enough to make people happy. */
|
||
tiop->ltchars.t_dsuspc = -1; /* C-y */
|
||
tiop->ltchars.t_lnextc = -1; /* C-v */
|
||
#endif /* TIOCGLTC */
|
||
}
|
||
|
||
#else /* !defined (NEW_TTY_DRIVER) */
|
||
|
||
#if !defined (VMIN)
|
||
# define VMIN VEOF
|
||
#endif
|
||
|
||
#if !defined (VTIME)
|
||
# define VTIME VEOL
|
||
#endif
|
||
|
||
#if defined (TERMIOS_TTY_DRIVER)
|
||
# define TIOTYPE struct termios
|
||
# define DRAIN_OUTPUT(fd) tcdrain (fd)
|
||
# define GETATTR(tty, tiop) (tcgetattr (tty, tiop))
|
||
# ifdef M_UNIX
|
||
# define SETATTR(tty, tiop) (tcsetattr (tty, TCSANOW, tiop))
|
||
# else
|
||
# define SETATTR(tty, tiop) (tcsetattr (tty, TCSADRAIN, tiop))
|
||
# endif /* !M_UNIX */
|
||
#else
|
||
# define TIOTYPE struct termio
|
||
# define DRAIN_OUTPUT(fd)
|
||
# define GETATTR(tty, tiop) (ioctl (tty, TCGETA, tiop))
|
||
# define SETATTR(tty, tiop) (ioctl (tty, TCSETAW, tiop))
|
||
#endif /* !TERMIOS_TTY_DRIVER */
|
||
|
||
static TIOTYPE otio;
|
||
|
||
static void save_tty_chars PARAMS((TIOTYPE *));
|
||
static int _get_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int get_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int _set_tty_settings PARAMS((int, TIOTYPE *));
|
||
static int set_tty_settings PARAMS((int, TIOTYPE *));
|
||
|
||
static void prepare_terminal_settings PARAMS((int, TIOTYPE, TIOTYPE *));
|
||
|
||
static void set_special_char PARAMS((Keymap, TIOTYPE *, int, rl_command_func_t *));
|
||
static void _rl_bind_tty_special_chars PARAMS((Keymap, TIOTYPE));
|
||
|
||
#if defined (FLUSHO)
|
||
# define OUTPUT_BEING_FLUSHED(tp) (tp->c_lflag & FLUSHO)
|
||
#else
|
||
# define OUTPUT_BEING_FLUSHED(tp) 0
|
||
#endif
|
||
|
||
static void
|
||
save_tty_chars (tiop)
|
||
TIOTYPE *tiop;
|
||
{
|
||
_rl_last_tty_chars = _rl_tty_chars;
|
||
|
||
_rl_tty_chars.t_eof = tiop->c_cc[VEOF];
|
||
_rl_tty_chars.t_eol = tiop->c_cc[VEOL];
|
||
#ifdef VEOL2
|
||
_rl_tty_chars.t_eol2 = tiop->c_cc[VEOL2];
|
||
#endif
|
||
_rl_tty_chars.t_erase = tiop->c_cc[VERASE];
|
||
#ifdef VWERASE
|
||
_rl_tty_chars.t_werase = tiop->c_cc[VWERASE];
|
||
#endif
|
||
_rl_tty_chars.t_kill = tiop->c_cc[VKILL];
|
||
#ifdef VREPRINT
|
||
_rl_tty_chars.t_reprint = tiop->c_cc[VREPRINT];
|
||
#endif
|
||
_rl_intr_char = _rl_tty_chars.t_intr = tiop->c_cc[VINTR];
|
||
_rl_quit_char = _rl_tty_chars.t_quit = tiop->c_cc[VQUIT];
|
||
#ifdef VSUSP
|
||
_rl_susp_char = _rl_tty_chars.t_susp = tiop->c_cc[VSUSP];
|
||
#endif
|
||
#ifdef VDSUSP
|
||
_rl_tty_chars.t_dsusp = tiop->c_cc[VDSUSP];
|
||
#endif
|
||
#ifdef VSTART
|
||
_rl_tty_chars.t_start = tiop->c_cc[VSTART];
|
||
#endif
|
||
#ifdef VSTOP
|
||
_rl_tty_chars.t_stop = tiop->c_cc[VSTOP];
|
||
#endif
|
||
#ifdef VLNEXT
|
||
_rl_tty_chars.t_lnext = tiop->c_cc[VLNEXT];
|
||
#endif
|
||
#ifdef VDISCARD
|
||
_rl_tty_chars.t_flush = tiop->c_cc[VDISCARD];
|
||
#endif
|
||
#ifdef VSTATUS
|
||
_rl_tty_chars.t_status = tiop->c_cc[VSTATUS];
|
||
#endif
|
||
}
|
||
|
||
#if defined (_AIX) || defined (_AIX41)
|
||
/* Currently this is only used on AIX */
|
||
static void
|
||
rltty_warning (msg)
|
||
char *msg;
|
||
{
|
||
_rl_errmsg ("warning: %s", msg);
|
||
}
|
||
#endif
|
||
|
||
#if defined (_AIX)
|
||
void
|
||
setopost(tp)
|
||
TIOTYPE *tp;
|
||
{
|
||
if ((tp->c_oflag & OPOST) == 0)
|
||
{
|
||
_rl_errmsg ("warning: turning on OPOST for terminal\r");
|
||
tp->c_oflag |= OPOST|ONLCR;
|
||
}
|
||
}
|
||
#endif
|
||
|
||
static int
|
||
_get_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
int ioctl_ret;
|
||
|
||
while (1)
|
||
{
|
||
ioctl_ret = GETATTR (tty, tiop);
|
||
if (ioctl_ret < 0)
|
||
{
|
||
if (errno != EINTR)
|
||
return -1;
|
||
else
|
||
continue;
|
||
}
|
||
if (OUTPUT_BEING_FLUSHED (tiop))
|
||
{
|
||
#if defined (FLUSHO)
|
||
_rl_errmsg ("warning: turning off output flushing");
|
||
tiop->c_lflag &= ~FLUSHO;
|
||
break;
|
||
#else
|
||
continue;
|
||
#endif
|
||
}
|
||
break;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
get_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
set_winsize (tty);
|
||
|
||
errno = 0;
|
||
if (_get_tty_settings (tty, tiop) < 0)
|
||
return -1;
|
||
|
||
#if defined (_AIX)
|
||
setopost(tiop);
|
||
#endif
|
||
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
_set_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
while (SETATTR (tty, tiop) < 0)
|
||
{
|
||
if (errno != EINTR)
|
||
return -1;
|
||
errno = 0;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
static int
|
||
set_tty_settings (tty, tiop)
|
||
int tty;
|
||
TIOTYPE *tiop;
|
||
{
|
||
if (_set_tty_settings (tty, tiop) < 0)
|
||
return -1;
|
||
|
||
#if 0
|
||
|
||
#if defined (TERMIOS_TTY_DRIVER)
|
||
# if defined (__ksr1__)
|
||
if (ksrflow)
|
||
{
|
||
ksrflow = 0;
|
||
tcflow (tty, TCOON);
|
||
}
|
||
# else /* !ksr1 */
|
||
tcflow (tty, TCOON); /* Simulate a ^Q. */
|
||
# endif /* !ksr1 */
|
||
#else
|
||
ioctl (tty, TCXONC, 1); /* Simulate a ^Q. */
|
||
#endif /* !TERMIOS_TTY_DRIVER */
|
||
|
||
#endif /* 0 */
|
||
|
||
return 0;
|
||
}
|
||
|
||
static void
|
||
prepare_terminal_settings (meta_flag, oldtio, tiop)
|
||
int meta_flag;
|
||
TIOTYPE oldtio, *tiop;
|
||
{
|
||
_rl_echoing_p = (oldtio.c_lflag & ECHO);
|
||
#if defined (ECHOCTL)
|
||
_rl_echoctl = (oldtio.c_lflag & ECHOCTL);
|
||
#endif
|
||
|
||
tiop->c_lflag &= ~(ICANON | ECHO);
|
||
|
||
if ((unsigned char) oldtio.c_cc[VEOF] != (unsigned char) _POSIX_VDISABLE)
|
||
_rl_eof_char = oldtio.c_cc[VEOF];
|
||
|
||
#if defined (USE_XON_XOFF)
|
||
#if defined (IXANY)
|
||
tiop->c_iflag &= ~(IXON | IXANY);
|
||
#else
|
||
/* `strict' Posix systems do not define IXANY. */
|
||
tiop->c_iflag &= ~IXON;
|
||
#endif /* IXANY */
|
||
#endif /* USE_XON_XOFF */
|
||
|
||
/* Only turn this off if we are using all 8 bits. */
|
||
if (((tiop->c_cflag & CSIZE) == CS8) || meta_flag)
|
||
tiop->c_iflag &= ~(ISTRIP | INPCK);
|
||
|
||
/* Make sure we differentiate between CR and NL on input. */
|
||
tiop->c_iflag &= ~(ICRNL | INLCR);
|
||
|
||
#if !defined (HANDLE_SIGNALS)
|
||
tiop->c_lflag &= ~ISIG;
|
||
#else
|
||
tiop->c_lflag |= ISIG;
|
||
#endif
|
||
|
||
tiop->c_cc[VMIN] = 1;
|
||
tiop->c_cc[VTIME] = 0;
|
||
|
||
#if defined (FLUSHO)
|
||
if (OUTPUT_BEING_FLUSHED (tiop))
|
||
{
|
||
tiop->c_lflag &= ~FLUSHO;
|
||
oldtio.c_lflag &= ~FLUSHO;
|
||
}
|
||
#endif
|
||
|
||
/* Turn off characters that we need on Posix systems with job control,
|
||
just to be sure. This includes ^Y and ^V. This should not really
|
||
be necessary. */
|
||
#if defined (TERMIOS_TTY_DRIVER) && defined (_POSIX_VDISABLE)
|
||
|
||
#if defined (VLNEXT)
|
||
tiop->c_cc[VLNEXT] = _POSIX_VDISABLE;
|
||
#endif
|
||
|
||
#if defined (VDSUSP)
|
||
tiop->c_cc[VDSUSP] = _POSIX_VDISABLE;
|
||
#endif
|
||
|
||
#endif /* TERMIOS_TTY_DRIVER && _POSIX_VDISABLE */
|
||
}
|
||
#endif /* !NEW_TTY_DRIVER */
|
||
|
||
/* Put the terminal in CBREAK mode so that we can detect key presses. */
|
||
#if defined (NO_TTY_DRIVER)
|
||
void
|
||
rl_prep_terminal (meta_flag)
|
||
int meta_flag;
|
||
{
|
||
_rl_echoing_p = 1;
|
||
}
|
||
|
||
void
|
||
rl_deprep_terminal ()
|
||
{
|
||
}
|
||
|
||
#else /* ! NO_TTY_DRIVER */
|
||
void
|
||
rl_prep_terminal (meta_flag)
|
||
int meta_flag;
|
||
{
|
||
int tty, nprep;
|
||
TIOTYPE tio;
|
||
|
||
if (terminal_prepped)
|
||
return;
|
||
|
||
/* Try to keep this function from being INTerrupted. */
|
||
_rl_block_sigint ();
|
||
|
||
tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
|
||
|
||
if (get_tty_settings (tty, &tio) < 0)
|
||
{
|
||
#if defined (ENOTSUP)
|
||
/* MacOS X and Linux, at least, lie about the value of errno if
|
||
tcgetattr fails. */
|
||
if (errno == ENOTTY || errno == EINVAL || errno == ENOTSUP)
|
||
#else
|
||
if (errno == ENOTTY || errno == EINVAL)
|
||
#endif
|
||
_rl_echoing_p = 1; /* XXX */
|
||
|
||
_rl_release_sigint ();
|
||
return;
|
||
}
|
||
|
||
otio = tio;
|
||
|
||
if (_rl_bind_stty_chars)
|
||
{
|
||
#if defined (VI_MODE)
|
||
/* If editing in vi mode, make sure we restore the bindings in the
|
||
insertion keymap no matter what keymap we ended up in. */
|
||
if (rl_editing_mode == vi_mode)
|
||
rl_tty_unset_default_bindings (vi_insertion_keymap);
|
||
else
|
||
#endif
|
||
rl_tty_unset_default_bindings (_rl_keymap);
|
||
}
|
||
save_tty_chars (&otio);
|
||
RL_SETSTATE(RL_STATE_TTYCSAVED);
|
||
if (_rl_bind_stty_chars)
|
||
{
|
||
#if defined (VI_MODE)
|
||
/* If editing in vi mode, make sure we set the bindings in the
|
||
insertion keymap no matter what keymap we ended up in. */
|
||
if (rl_editing_mode == vi_mode)
|
||
_rl_bind_tty_special_chars (vi_insertion_keymap, tio);
|
||
else
|
||
#endif
|
||
_rl_bind_tty_special_chars (_rl_keymap, tio);
|
||
}
|
||
|
||
prepare_terminal_settings (meta_flag, otio, &tio);
|
||
|
||
if (set_tty_settings (tty, &tio) < 0)
|
||
{
|
||
_rl_release_sigint ();
|
||
return;
|
||
}
|
||
|
||
if (_rl_enable_keypad)
|
||
_rl_control_keypad (1);
|
||
|
||
nprep = TPX_PREPPED;
|
||
|
||
if (_rl_enable_bracketed_paste)
|
||
{
|
||
fprintf (rl_outstream, BRACK_PASTE_INIT);
|
||
nprep |= TPX_BRACKPASTE;
|
||
}
|
||
|
||
fflush (rl_outstream);
|
||
terminal_prepped = nprep;
|
||
RL_SETSTATE(RL_STATE_TERMPREPPED);
|
||
|
||
_rl_release_sigint ();
|
||
}
|
||
|
||
/* Restore the terminal's normal settings and modes. */
|
||
void
|
||
rl_deprep_terminal ()
|
||
{
|
||
int tty;
|
||
|
||
if (terminal_prepped == 0)
|
||
return;
|
||
|
||
/* Try to keep this function from being interrupted. */
|
||
_rl_block_sigint ();
|
||
|
||
tty = rl_instream ? fileno (rl_instream) : fileno (stdin);
|
||
|
||
if (terminal_prepped & TPX_BRACKPASTE)
|
||
fprintf (rl_outstream, BRACK_PASTE_FINI);
|
||
|
||
if (_rl_enable_keypad)
|
||
_rl_control_keypad (0);
|
||
|
||
fflush (rl_outstream);
|
||
|
||
if (set_tty_settings (tty, &otio) < 0)
|
||
{
|
||
_rl_release_sigint ();
|
||
return;
|
||
}
|
||
|
||
terminal_prepped = 0;
|
||
RL_UNSETSTATE(RL_STATE_TERMPREPPED);
|
||
|
||
_rl_release_sigint ();
|
||
}
|
||
#endif /* !NO_TTY_DRIVER */
|
||
|
||
/* **************************************************************** */
|
||
/* */
|
||
/* Bogus Flow Control */
|
||
/* */
|
||
/* **************************************************************** */
|
||
|
||
int
|
||
rl_restart_output (count, key)
|
||
int count, key;
|
||
{
|
||
#if defined (__MINGW32__)
|
||
return 0;
|
||
#else /* !__MING32__ */
|
||
|
||
int fildes = fileno (rl_outstream);
|
||
#if defined (TIOCSTART)
|
||
#if defined (apollo)
|
||
ioctl (&fildes, TIOCSTART, 0);
|
||
#else
|
||
ioctl (fildes, TIOCSTART, 0);
|
||
#endif /* apollo */
|
||
|
||
#else /* !TIOCSTART */
|
||
# if defined (TERMIOS_TTY_DRIVER)
|
||
# if defined (__ksr1__)
|
||
if (ksrflow)
|
||
{
|
||
ksrflow = 0;
|
||
tcflow (fildes, TCOON);
|
||
}
|
||
# else /* !ksr1 */
|
||
tcflow (fildes, TCOON); /* Simulate a ^Q. */
|
||
# endif /* !ksr1 */
|
||
# else /* !TERMIOS_TTY_DRIVER */
|
||
# if defined (TCXONC)
|
||
ioctl (fildes, TCXONC, TCOON);
|
||
# endif /* TCXONC */
|
||
# endif /* !TERMIOS_TTY_DRIVER */
|
||
#endif /* !TIOCSTART */
|
||
|
||
return 0;
|
||
#endif /* !__MINGW32__ */
|
||
}
|
||
|
||
int
|
||
rl_stop_output (count, key)
|
||
int count, key;
|
||
{
|
||
#if defined (__MINGW32__)
|
||
return 0;
|
||
#else
|
||
|
||
int fildes = fileno (rl_instream);
|
||
|
||
#if defined (TIOCSTOP)
|
||
# if defined (apollo)
|
||
ioctl (&fildes, TIOCSTOP, 0);
|
||
# else
|
||
ioctl (fildes, TIOCSTOP, 0);
|
||
# endif /* apollo */
|
||
#else /* !TIOCSTOP */
|
||
# if defined (TERMIOS_TTY_DRIVER)
|
||
# if defined (__ksr1__)
|
||
ksrflow = 1;
|
||
# endif /* ksr1 */
|
||
tcflow (fildes, TCOOFF);
|
||
# else
|
||
# if defined (TCXONC)
|
||
ioctl (fildes, TCXONC, TCOON);
|
||
# endif /* TCXONC */
|
||
# endif /* !TERMIOS_TTY_DRIVER */
|
||
#endif /* !TIOCSTOP */
|
||
|
||
return 0;
|
||
#endif /* !__MINGW32__ */
|
||
}
|
||
|
||
/* **************************************************************** */
|
||
/* */
|
||
/* Default Key Bindings */
|
||
/* */
|
||
/* **************************************************************** */
|
||
|
||
#if !defined (NO_TTY_DRIVER)
|
||
#define SET_SPECIAL(sc, func) set_special_char(kmap, &ttybuff, sc, func)
|
||
#endif
|
||
|
||
#if defined (NO_TTY_DRIVER)
|
||
|
||
#define SET_SPECIAL(sc, func)
|
||
#define RESET_SPECIAL(c)
|
||
|
||
#elif defined (NEW_TTY_DRIVER)
|
||
static void
|
||
set_special_char (kmap, tiop, sc, func)
|
||
Keymap kmap;
|
||
TIOTYPE *tiop;
|
||
int sc;
|
||
rl_command_func_t *func;
|
||
{
|
||
if (sc != -1 && kmap[(unsigned char)sc].type == ISFUNC)
|
||
kmap[(unsigned char)sc].function = func;
|
||
}
|
||
|
||
#define RESET_SPECIAL(c) \
|
||
if (c != -1 && kmap[(unsigned char)c].type == ISFUNC) \
|
||
kmap[(unsigned char)c].function = rl_insert;
|
||
|
||
static void
|
||
_rl_bind_tty_special_chars (kmap, ttybuff)
|
||
Keymap kmap;
|
||
TIOTYPE ttybuff;
|
||
{
|
||
if (ttybuff.flags & SGTTY_SET)
|
||
{
|
||
SET_SPECIAL (ttybuff.sgttyb.sg_erase, rl_rubout);
|
||
SET_SPECIAL (ttybuff.sgttyb.sg_kill, rl_unix_line_discard);
|
||
}
|
||
|
||
# if defined (TIOCGLTC)
|
||
if (ttybuff.flags & LTCHARS_SET)
|
||
{
|
||
SET_SPECIAL (ttybuff.ltchars.t_werasc, rl_unix_word_rubout);
|
||
SET_SPECIAL (ttybuff.ltchars.t_lnextc, rl_quoted_insert);
|
||
}
|
||
# endif /* TIOCGLTC */
|
||
}
|
||
|
||
#else /* !NEW_TTY_DRIVER */
|
||
static void
|
||
set_special_char (kmap, tiop, sc, func)
|
||
Keymap kmap;
|
||
TIOTYPE *tiop;
|
||
int sc;
|
||
rl_command_func_t *func;
|
||
{
|
||
unsigned char uc;
|
||
|
||
uc = tiop->c_cc[sc];
|
||
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC)
|
||
kmap[uc].function = func;
|
||
}
|
||
|
||
/* used later */
|
||
#define RESET_SPECIAL(uc) \
|
||
if (uc != (unsigned char)_POSIX_VDISABLE && kmap[uc].type == ISFUNC) \
|
||
kmap[uc].function = rl_insert;
|
||
|
||
static void
|
||
_rl_bind_tty_special_chars (kmap, ttybuff)
|
||
Keymap kmap;
|
||
TIOTYPE ttybuff;
|
||
{
|
||
SET_SPECIAL (VERASE, rl_rubout);
|
||
SET_SPECIAL (VKILL, rl_unix_line_discard);
|
||
|
||
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
|
||
SET_SPECIAL (VLNEXT, rl_quoted_insert);
|
||
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
|
||
|
||
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
|
||
SET_SPECIAL (VWERASE, rl_unix_word_rubout);
|
||
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
|
||
}
|
||
|
||
#endif /* !NEW_TTY_DRIVER */
|
||
|
||
/* Set the system's default editing characters to their readline equivalents
|
||
in KMAP. Should be static, now that we have rl_tty_set_default_bindings. */
|
||
void
|
||
rltty_set_default_bindings (kmap)
|
||
Keymap kmap;
|
||
{
|
||
#if !defined (NO_TTY_DRIVER)
|
||
TIOTYPE ttybuff;
|
||
int tty;
|
||
|
||
tty = fileno (rl_instream);
|
||
|
||
if (get_tty_settings (tty, &ttybuff) == 0)
|
||
_rl_bind_tty_special_chars (kmap, ttybuff);
|
||
#endif
|
||
}
|
||
|
||
/* New public way to set the system default editing chars to their readline
|
||
equivalents. */
|
||
void
|
||
rl_tty_set_default_bindings (kmap)
|
||
Keymap kmap;
|
||
{
|
||
rltty_set_default_bindings (kmap);
|
||
}
|
||
|
||
/* Rebind all of the tty special chars that readline worries about back
|
||
to self-insert. Call this before saving the current terminal special
|
||
chars with save_tty_chars(). This only works on POSIX termios or termio
|
||
systems. */
|
||
void
|
||
rl_tty_unset_default_bindings (kmap)
|
||
Keymap kmap;
|
||
{
|
||
/* Don't bother before we've saved the tty special chars at least once. */
|
||
if (RL_ISSTATE(RL_STATE_TTYCSAVED) == 0)
|
||
return;
|
||
|
||
RESET_SPECIAL (_rl_tty_chars.t_erase);
|
||
RESET_SPECIAL (_rl_tty_chars.t_kill);
|
||
|
||
# if defined (VLNEXT) && defined (TERMIOS_TTY_DRIVER)
|
||
RESET_SPECIAL (_rl_tty_chars.t_lnext);
|
||
# endif /* VLNEXT && TERMIOS_TTY_DRIVER */
|
||
|
||
# if defined (VWERASE) && defined (TERMIOS_TTY_DRIVER)
|
||
RESET_SPECIAL (_rl_tty_chars.t_werase);
|
||
# endif /* VWERASE && TERMIOS_TTY_DRIVER */
|
||
}
|
||
|
||
#if defined (HANDLE_SIGNALS)
|
||
|
||
#if defined (NEW_TTY_DRIVER) || defined (NO_TTY_DRIVER)
|
||
int
|
||
_rl_disable_tty_signals ()
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
int
|
||
_rl_restore_tty_signals ()
|
||
{
|
||
return 0;
|
||
}
|
||
#else
|
||
|
||
static TIOTYPE sigstty, nosigstty;
|
||
static int tty_sigs_disabled = 0;
|
||
|
||
int
|
||
_rl_disable_tty_signals ()
|
||
{
|
||
if (tty_sigs_disabled)
|
||
return 0;
|
||
|
||
if (_get_tty_settings (fileno (rl_instream), &sigstty) < 0)
|
||
return -1;
|
||
|
||
nosigstty = sigstty;
|
||
|
||
nosigstty.c_lflag &= ~ISIG;
|
||
nosigstty.c_iflag &= ~IXON;
|
||
|
||
if (_set_tty_settings (fileno (rl_instream), &nosigstty) < 0)
|
||
return (_set_tty_settings (fileno (rl_instream), &sigstty));
|
||
|
||
tty_sigs_disabled = 1;
|
||
return 0;
|
||
}
|
||
|
||
int
|
||
_rl_restore_tty_signals ()
|
||
{
|
||
int r;
|
||
|
||
if (tty_sigs_disabled == 0)
|
||
return 0;
|
||
|
||
r = _set_tty_settings (fileno (rl_instream), &sigstty);
|
||
|
||
if (r == 0)
|
||
tty_sigs_disabled = 0;
|
||
|
||
return r;
|
||
}
|
||
#endif /* !NEW_TTY_DRIVER */
|
||
|
||
#endif /* HANDLE_SIGNALS */
|