From dbb74f87ba6ac89c13ca6826a7448004b019885a Mon Sep 17 00:00:00 2001 From: Fabian Homborg Date: Sat, 6 Mar 2021 09:24:54 +0100 Subject: [PATCH] Re-read terminal modes after config.fish Before now, we would be getting the terminal modes before config.fish, then running config.fish without any of the term "stealing" and modes copying. This meant that changes made to the terminal modes in there were simply lost. So, what we do is simply set the modes before config and then copy them after, once. Note that this does *not* turn off flow control again - if you turn it on in config.fish that should work. Fixes #7783. --- src/fish.cpp | 3 +++ src/reader.cpp | 22 +++++++++++++++------- src/reader.h | 1 + 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/fish.cpp b/src/fish.cpp index ed0c643bb..719777d65 100644 --- a/src/fish.cpp +++ b/src/fish.cpp @@ -491,6 +491,9 @@ int main(int argc, char **argv) { if (!opts.no_exec) { read_init(parser, paths); } + // Re-read the terminal modes after config, it might have changed them. + term_copy_modes(); + // Stomp the exit status of any initialization commands (issue #635). parser.set_last_statuses(statuses_t::just(STATUS_CMD_OK)); diff --git a/src/reader.cpp b/src/reader.cpp index c7b0c3204..6b466a789 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -839,13 +839,15 @@ static void redirect_tty_after_sighup() { } /// Give up control of terminal. -static void term_donate() { +static void term_donate(bool quiet = false) { while (true) { if (tcsetattr(STDIN_FILENO, TCSANOW, &tty_modes_for_external_cmds) == -1) { if (errno == EIO) redirect_tty_output(); if (errno != EINTR) { - FLOGF(warning, _(L"Could not set terminal mode for new job")); - wperror(L"tcsetattr"); + if (!quiet) { + FLOGF(warning, _(L"Could not set terminal mode for new job")); + wperror(L"tcsetattr"); + } break; } } else @@ -853,9 +855,8 @@ static void term_donate() { } } -/// Grab control of terminal. -static void term_steal() { - // Copy the (potentially changed) terminal modes and use them from now on. +/// Copy the (potentially changed) terminal modes and use them from now on. +void term_copy_modes() { struct termios modes; tcgetattr(STDIN_FILENO, &modes); std::memcpy(&tty_modes_for_external_cmds, &modes, sizeof tty_modes_for_external_cmds); @@ -872,8 +873,11 @@ static void term_steal() { } else { shell_modes.c_iflag &= ~IXOFF; } +} - +/// Grab control of terminal. +void term_steal() { + term_copy_modes(); while (true) { if (tcsetattr(STDIN_FILENO, TCSANOW, &shell_modes) == -1) { if (errno == EIO) redirect_tty_output(); @@ -1336,6 +1340,10 @@ void reader_init() { term_fix_modes(&shell_modes); + // Set up our fixed terminal modes once, + // so we don't get flow control just because we inherited it. + term_donate(/* quiet */ true); + // We do this not because we actually need the window size but for its side-effect of correctly // setting the COLUMNS and LINES env vars. termsize_container_t::shared().updating(parser); diff --git a/src/reader.h b/src/reader.h index b7e7a3e15..b861b830b 100644 --- a/src/reader.h +++ b/src/reader.h @@ -141,6 +141,7 @@ void reader_sighup(); /// Initialize the reader. void reader_init(); +void term_copy_modes(); /// Restore the term mode at startup. void restore_term_mode();