summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-07-11 09:26:07 +0200
committerLennart Poettering <lennart@poettering.net>2024-07-19 11:41:43 +0200
commitcfac09083b287c713a2bc3724eb71468a350321d (patch)
tree33bd60ef8d5067f682092e02c9081c3ae49530ba
parentterminal-util: add terminal_is_pty_fd() helper (diff)
downloadsystemd-cfac09083b287c713a2bc3724eb71468a350321d.tar.xz
systemd-cfac09083b287c713a2bc3724eb71468a350321d.zip
terminal-util: add new helper terminal_reset_defensive() that combines reset-by-ioctl and reset-by-sequence reasonably
-rw-r--r--src/basic/terminal-util.c21
-rw-r--r--src/basic/terminal-util.h1
-rw-r--r--src/core/exec-invoke.c4
-rw-r--r--src/core/execute.c2
-rw-r--r--src/firstboot/firstboot.c2
-rw-r--r--src/home/homectl.c2
-rw-r--r--src/test/test-terminal-util.c8
-rw-r--r--src/tty-ask-password-agent/tty-ask-password-agent.c4
8 files changed, 36 insertions, 8 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 4c4a715ff6..9754b9900b 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -1575,6 +1575,27 @@ int terminal_reset_ansi_seq(int fd) {
return k < 0 ? k : r;
}
+int terminal_reset_defensive(int fd, bool switch_to_text) {
+ int r = 0;
+
+ assert(fd >= 0);
+
+ /* Resets the terminal comprehensively, but defensively. i.e. both resets the tty via ioctl()s and
+ * via ANSI sequences, but avoids the latter in case we are talking to a pty. That's a safety measure
+ * because ptys might be connected to shell pipelines where we cannot expect such ansi sequences to
+ * work. Given that ptys are generally short-lived (and not recycled) this restriction shouldn't hurt
+ * much.
+ *
+ * The specified fd should be open for *writing*! */
+
+ RET_GATHER(r, reset_terminal_fd(fd, switch_to_text));
+
+ if (terminal_is_pty_fd(fd) == 0)
+ RET_GATHER(r, terminal_reset_ansi_seq(fd));
+
+ return r;
+}
+
void termios_disable_echo(struct termios *termios) {
assert(termios);
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index df28af02d5..c176933dd5 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -98,6 +98,7 @@ bool isatty_safe(int fd);
int reset_terminal_fd(int fd, bool switch_to_text);
int reset_terminal(const char *name);
int terminal_reset_ansi_seq(int fd);
+int terminal_reset_defensive(int fd, bool switch_to_text);
int terminal_set_cursor_position(int fd, unsigned row, unsigned column);
diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c
index 94c908afd7..f8c0a81153 100644
--- a/src/core/exec-invoke.c
+++ b/src/core/exec-invoke.c
@@ -358,7 +358,7 @@ static int setup_input(
(void) ioctl(STDIN_FILENO, TIOCSCTTY, context->std_input == EXEC_INPUT_TTY_FORCE);
if (context->tty_reset)
- (void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ true);
+ (void) terminal_reset_defensive(STDIN_FILENO, /* switch_to_text= */ true);
(void) exec_context_apply_tty_size(context, STDIN_FILENO, /* tty_path= */ NULL);
}
@@ -675,7 +675,7 @@ static int setup_confirm_stdio(
if (r < 0)
return r;
- r = reset_terminal_fd(fd, /* switch_to_text= */ true);
+ r = terminal_reset_defensive(fd, /* switch_to_text= */ true);
if (r < 0)
return r;
diff --git a/src/core/execute.c b/src/core/execute.c
index 18396db113..7590943179 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -172,7 +172,7 @@ void exec_context_tty_reset(const ExecContext *context, const ExecParameters *p)
(void) terminal_vhangup_fd(fd);
if (context->tty_reset)
- (void) reset_terminal_fd(fd, /* switch_to_text= */ true);
+ (void) terminal_reset_defensive(fd, /* switch_to_text= */ true);
(void) exec_context_apply_tty_size(context, fd, path);
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 92b0289859..615142cc1e 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -133,7 +133,7 @@ static void print_welcome(int rfd) {
pn = os_release_pretty_name(pretty_name, os_name);
ac = isempty(ansi_color) ? "0" : ansi_color;
- (void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ false);
+ (void) terminal_reset_defensive(STDIN_FILENO, /* switch_to_text= */ false);
if (colors_enabled())
printf("\nWelcome to your new installation of \x1B[%sm%s\x1B[0m!\n", ac, pn);
diff --git a/src/home/homectl.c b/src/home/homectl.c
index 65431db8ee..c64354141c 100644
--- a/src/home/homectl.c
+++ b/src/home/homectl.c
@@ -2438,7 +2438,7 @@ static int create_interactively(void) {
(void) polkit_agent_open_if_enabled(arg_transport, arg_ask_password);
- (void) reset_terminal_fd(STDIN_FILENO, /* switch_to_text= */ false);
+ (void) terminal_reset_defensive(STDIN_FILENO, /* switch_to_text= */ false);
for (;;) {
username = mfree(username);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index 2f09ae9f71..fdd590107e 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -282,4 +282,12 @@ TEST(get_color_mode) {
reset_terminal_feature_caches();
}
+TEST(terminal_reset_defensive) {
+ int r;
+
+ r = terminal_reset_defensive(STDIN_FILENO, /* switch_to_text= */ false);
+ if (r < 0)
+ log_notice_errno(r, "Failed to reset terminal: %m");
+}
+
DEFINE_TEST_MAIN(LOG_INFO);
diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c
index 84ce5e1940..b411c9c309 100644
--- a/src/tty-ask-password-agent/tty-ask-password-agent.c
+++ b/src/tty-ask-password-agent/tty-ask-password-agent.c
@@ -150,9 +150,7 @@ static int agent_ask_password_tty(
if (tty_fd < 0)
return log_error_errno(tty_fd, "Failed to acquire %s: %m", con);
- r = reset_terminal_fd(tty_fd, true);
- if (r < 0)
- log_warning_errno(r, "Failed to reset terminal, ignoring: %m");
+ (void) terminal_reset_defensive(tty_fd, /* switch_to_text= */ true);
log_info("Starting password query on %s.", con);
}