]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
terminal-util: add new helper terminal_reset_defensive() that combines reset-by-ioctl...
authorLennart Poettering <lennart@poettering.net>
Thu, 11 Jul 2024 07:26:07 +0000 (09:26 +0200)
committerLennart Poettering <lennart@poettering.net>
Fri, 19 Jul 2024 09:41:43 +0000 (11:41 +0200)
src/basic/terminal-util.c
src/basic/terminal-util.h
src/core/exec-invoke.c
src/core/execute.c
src/firstboot/firstboot.c
src/home/homectl.c
src/test/test-terminal-util.c
src/tty-ask-password-agent/tty-ask-password-agent.c

index 4c4a715ff66581c2084b17f042f5ae9242fbcaf2..9754b9900b62126dd6c636fe86281e8aefe37128 100644 (file)
@@ -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);
 
index df28af02d504cec64d92a6a5f623021c4409c013..c176933dd5cf5e76fb74af97034c3b538df81125 100644 (file)
@@ -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);
 
index 94c908afd781361508e3b19a1a200b0982b65f4a..f8c0a81153810d3dc51774c5f415f86194f3db72 100644 (file)
@@ -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;
 
index 18396db113cfb78fef71d7ab20cfe56fb9eed6cb..7590943179b5bec3c9e3c6d8f17b1456ba5e20f4 100644 (file)
@@ -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);
 
index 92b0289859ab025207bac5b1c488bd0a0b334e7f..615142cc1edb075694962a64aa284045fa4e1eb0 100644 (file)
@@ -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);
index 65431db8ee4591fe56bd0cd451f34d357b0b6df7..c64354141c57b99c25051732eab4851569851a7b 100644 (file)
@@ -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);
index 2f09ae9f71c8bd20bb44ac082852d330e7251ad0..fdd590107ee293d3b6815024c966853d89977265 100644 (file)
@@ -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);
index 84ce5e1940e0144f98215121cf5a084c1872a01d..b411c9c309d38d55c42fb654a3f003588c650491 100644 (file)
@@ -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);
         }