Extract function for setting shell modes

We do the same thing in several places, with lots of small differences.
Extract the most reasonable behavior and use it everywhere.  Note that
we had an explictly-motivated ENOTTY check; the motivating issues
doesn't seem to reproduce anymore here though I did not bisect yet.
This commit is contained in:
Johannes Altmanninger
2025-09-22 10:00:39 +02:00
parent 21150726d3
commit 6fdce59572
9 changed files with 47 additions and 64 deletions

View File

@@ -996,9 +996,6 @@ msgstr "Das aktuelle Arbeitsverzeichnis konnte nicht bestimmt werden. Ist die lo
msgid "Could not set terminal mode for new job"
msgstr "Konnte Terminalmodus für neuen Job nicht festlegen"
msgid "Could not set terminal mode for shell"
msgstr "Konnte Terminalmodus für neue Shell nicht festlegen"
msgid "Could not show help message"
msgstr "Hilfemeldung konnte nicht angezeigt werden"
@@ -1124,8 +1121,10 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr "Konnte Shell nicht einer eigenen Prozessgruppe zuweisen"
msgid "Failed to set startup terminal mode!"
msgstr "Konnte Terminalmodus nicht setzen"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"
msgstr "Konnte Kontrolle über das Terminal nicht übernehmen"

View File

@@ -994,9 +994,6 @@ msgstr ""
msgid "Could not set terminal mode for new job"
msgstr "Could not set terminal mode for new job"
msgid "Could not set terminal mode for shell"
msgstr "Could not set terminal mode for shell"
msgid "Could not show help message"
msgstr ""
@@ -1122,7 +1119,9 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr ""
msgid "Failed to set startup terminal mode!"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"

View File

@@ -1095,9 +1095,6 @@ msgstr "Impossible de déterminer le dossier de travail. Vos paramètres région
msgid "Could not set terminal mode for new job"
msgstr "Impossible de paramétrer le mode du terminal pour la nouvelle tâche"
msgid "Could not set terminal mode for shell"
msgstr "Impossible de paramétrer le mode du terminal pour le shell"
msgid "Could not show help message"
msgstr ""
@@ -1223,7 +1220,9 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr ""
msgid "Failed to set startup terminal mode!"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"

View File

@@ -990,9 +990,6 @@ msgstr ""
msgid "Could not set terminal mode for new job"
msgstr "Nie można ustawić trybu terminala dla nowego zadania"
msgid "Could not set terminal mode for shell"
msgstr ""
msgid "Could not show help message"
msgstr ""
@@ -1118,7 +1115,9 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr ""
msgid "Failed to set startup terminal mode!"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"

View File

@@ -995,9 +995,6 @@ msgstr ""
msgid "Could not set terminal mode for new job"
msgstr "Não foi possível definir modo do terminal para a nova tarefa"
msgid "Could not set terminal mode for shell"
msgstr "Não foi possível preparar modo do terminal para shell"
msgid "Could not show help message"
msgstr ""
@@ -1123,7 +1120,9 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr ""
msgid "Failed to set startup terminal mode!"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"

View File

@@ -991,9 +991,6 @@ msgstr ""
msgid "Could not set terminal mode for new job"
msgstr "Kunde inte återställa terminalen för nytt jobb"
msgid "Could not set terminal mode for shell"
msgstr "Kunde inte återställa terminalen till skalet"
msgid "Could not show help message"
msgstr ""
@@ -1119,7 +1116,9 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr ""
msgid "Failed to set startup terminal mode!"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"

View File

@@ -988,9 +988,6 @@ msgstr "无法确定当前工作目录 . 你的本地设置正确吗?"
msgid "Could not set terminal mode for new job"
msgstr "无法为新任务设置终端模式"
msgid "Could not set terminal mode for shell"
msgstr "无法为 shell 设置终端模式"
msgid "Could not show help message"
msgstr "无法显示帮助消息"
@@ -1116,8 +1113,10 @@ msgstr ""
msgid "Failed to assign shell to its own process group"
msgstr "无法将shell分配到它自己的进程组"
msgid "Failed to set startup terminal mode!"
msgstr "设置启动终端模式失败 !"
#
#, c-format
msgid "Failed to set terminal mode (%s)"
msgstr ""
msgid "Failed to take control of the terminal"
msgstr "控制终端失败"

View File

@@ -9,7 +9,7 @@
use std::{cell::RefCell, ops::ControlFlow, os::unix::prelude::OsStrExt};
use libc::{STDIN_FILENO, TCSANOW, VEOF, VINTR};
use libc::{STDIN_FILENO, VEOF, VINTR};
use once_cell::unsync::OnceCell;
#[allow(unused_imports)]
@@ -28,7 +28,7 @@
panic::panic_handler,
print_help::print_help,
proc::set_interactive_session,
reader::{check_exit_loop_maybe_warning, initial_query, reader_init},
reader::{check_exit_loop_maybe_warning, initial_query, reader_init, set_shell_modes},
signal::signal_set_handlers,
terminal::Capability,
threads,
@@ -155,7 +155,7 @@ fn setup_and_process_keys(
signal_set_handlers(true);
// We need to set the shell-modes for ICRNL,
// in fish-proper this is done once a command is run.
unsafe { libc::tcsetattr(0, TCSANOW, &*shell_modes()) };
set_shell_modes(STDIN_FILENO, "startup");
initialize_tty_metadata();
let blocking_query: OnceCell<RefCell<Option<TerminalQuery>>> = OnceCell::new();
initial_query(streams.stdin_fd, &blocking_query, streams.out, None);

View File

@@ -2231,15 +2231,7 @@ fn readline(&mut self, nchars: Option<NonZeroUsize>) -> Option<WString> {
unsafe { libc::tcgetattr(self.conf.inputfd, old_modes.as_mut_ptr()) } == 0;
// Set the new modes.
if unsafe { libc::tcsetattr(self.conf.inputfd, TCSANOW, &*shell_modes()) } == -1 {
let err = errno().0;
// This check is required to work around certain issues with fish's approach to
// terminal control when launching interactive processes while in non-interactive
// mode. See #4178 for one such example.
if err != ENOTTY || is_interactive_session() {
perror("tcsetattr");
}
}
set_shell_modes(self.conf.inputfd, "readline");
initial_query(
self.conf.inputfd,
@@ -2367,16 +2359,7 @@ fn run_input_command_scripts(&mut self, cmd: &wstr) {
// from a key binding. However we do NOT want to invoke term_donate(), because that will enable
// ECHO mode, causing a race between new input and restoring the mode (#7770). So we leave the
// tty alone, run the commands in shell mode, and then restore shell modes.
let mut res;
loop {
res = unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) };
if res >= 0 || errno().0 != EINTR {
break;
}
}
if res < 0 {
perror("tcsetattr");
}
set_shell_modes(STDIN_FILENO, "bind scripts");
termsize_invalidate_tty();
}
@@ -4396,19 +4379,29 @@ pub fn term_copy_modes() {
}
}
pub fn set_shell_modes(fd: RawFd, whence: &str) -> bool {
let ok = loop {
let ok = unsafe { libc::tcsetattr(fd, TCSANOW, &*shell_modes()) } != -1;
if ok || errno().0 != EINTR {
break ok;
}
};
if !ok {
perror("tcsetattr");
FLOG!(
warning,
wgettext_fmt!("Failed to set terminal mode (%s)", whence)
);
}
ok
}
/// Grab control of terminal.
fn term_steal(copy_modes: bool) {
if copy_modes {
term_copy_modes();
}
while unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) } == -1 {
if errno().0 != EINTR {
FLOG!(warning, wgettext!("Could not set terminal mode for shell"));
perror("tcsetattr");
break;
}
}
set_shell_modes(STDIN_FILENO, "shell");
termsize_invalidate_tty();
}
@@ -4541,10 +4534,7 @@ fn reader_interactive_init(parser: &Parser) {
}
// Configure terminal attributes
if unsafe { libc::tcsetattr(STDIN_FILENO, TCSANOW, &*shell_modes()) } == -1 {
FLOG!(warning, wgettext!("Failed to set startup terminal mode!"));
perror("tcsetattr");
}
set_shell_modes(STDIN_FILENO, "startup");
}
termsize_invalidate_tty();