From: Daan De Meyer Date: Mon, 22 Apr 2024 20:58:49 +0000 (+0200) Subject: core: Limit terminal reset using ANSI sequences to /dev/console X-Git-Tag: v256-rc1~44 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=00bc83a275fa3ca8d90579fe9597d8b651d47332;p=thirdparty%2Fsystemd.git core: Limit terminal reset using ANSI sequences to /dev/console Doing this in reset_terminal_fd() is a bit too invasive, see https://github.com/systemd/systemd/pull/32406#issuecomment-2070923583. Let's only do this for /dev/console so that we work around weird firmwares disabling line-wrapping, but avoid messing too much with other things. While we're at it, let's handle more than just line wrapping, and do a more general reset of stuff to get the terminal into a sane state. --- diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 11c0da870c7..dda592089cb 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -306,29 +306,9 @@ int reset_terminal_fd(int fd, bool switch_to_text) { termios.c_cc[VMIN] = 1; r = RET_NERRNO(tcsetattr(fd, TCSANOW, &termios)); - if (r < 0) { + if (r < 0) log_debug_errno(r, "Failed to set terminal parameters: %m"); - goto finish; - } - - if (!terminal_is_dumb()) { - r = fd_nonblock(fd, true); - if (r < 0) { - log_debug_errno(r, "Failed to set terminal to non-blocking mode: %m"); - goto finish; - } - - /* Enable line wrapping. */ - (void) loop_write_full(fd, "\033[?7h", SIZE_MAX, 50 * USEC_PER_MSEC); - if (r > 0) { - r = fd_nonblock(fd, false); - if (r < 0) { - log_debug_errno(r, "Failed to set terminal back to blocking mode: %m"); - goto finish; - } - } - } finish: /* Just in case, flush all crap out */ (void) tcflush(fd, TCIOFLUSH); @@ -1565,6 +1545,37 @@ int set_terminal_cursor_position(int fd, unsigned int row, unsigned int column) return 0; } +int terminal_reset_ansi_seq(int fd) { + int r, k; + + assert(fd >= 0); + + if (getenv_terminal_is_dumb()) + return 0; + + r = fd_nonblock(fd, true); + if (r < 0) + return log_debug_errno(r, "Failed to set terminal to non-blocking mode: %m"); + + k = loop_write_full(fd, + "\033c" /* reset to initial state */ + "\033[!p" /* soft terminal reset */ + "\033]104\007" /* reset colors */ + "\033[?7h", /* enable line-wrapping */ + SIZE_MAX, + 50 * USEC_PER_MSEC); + if (k < 0) + log_debug_errno(k, "Failed to write to terminal: %m"); + + if (r > 0) { + r = fd_nonblock(fd, false); + if (r < 0) + log_debug_errno(r, "Failed to set terminal back to blocking mode: %m"); + } + + return k < 0 ? k : 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 2596752e562..ecfe574451e 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 set_terminal_cursor_position(int fd, unsigned int row, unsigned int column); +int terminal_reset_ansi_seq(int fd); int open_terminal(const char *name, int mode); diff --git a/src/core/main.c b/src/core/main.c index 83a2b5b6614..7362a6a8220 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -208,13 +208,17 @@ static int console_setup(void) { r = proc_cmdline_tty_size("/dev/console", &rows, &cols); if (r < 0) - log_warning_errno(r, "Failed to get terminal size, ignoring: %m"); + log_warning_errno(r, "Failed to get /dev/console size, ignoring: %m"); else { r = terminal_set_size_fd(tty_fd, NULL, rows, cols); if (r < 0) - log_warning_errno(r, "Failed to set terminal size, ignoring: %m"); + log_warning_errno(r, "Failed to set /dev/console size, ignoring: %m"); } + r = terminal_reset_ansi_seq(tty_fd); + if (r < 0) + log_warning_errno(r, "Failed to reset /dev/console using ANSI sequences, ignoring: %m"); + return 0; }