From b4112281990839a28d56684c75a9b7d3631291cf Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 17 Jul 2024 17:47:41 +0200 Subject: [PATCH] main: set $COLUMNS/$ROWS for PID 1 based on /dev/console data In PID 1 we write status information to /dev/console regularly, but we cannot keep it open continously, due to the kernel's SAK logic (which would kill PID 1 if user hits SAK). But closing/reopening it all the time really sucks for tty types that have no window size management (such as serial terminals/hvc0 and suchlike), because it also means the TTY is fully closed most of the time, and that resets the window sizes to 0/0. Now, we reinitialize the window size on every reopen, but that is a bit expensive for simple status output. Hence, cache the window size in the usualy $COLUMNS/$ROWS environment variables. We don't inherit these to our payloads anyway, hence these are free to us to use. --- src/core/main.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/core/main.c b/src/core/main.c index bc2476ed3a..e5c2dc914e 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -204,6 +204,43 @@ static int manager_find_user_config_paths(char ***ret_files, char ***ret_dirs) { return 0; } +static int save_console_winsize_in_environment(int tty_fd) { + int r; + + assert(tty_fd >= 0); + + struct winsize ws = {}; + if (ioctl(tty_fd, TIOCGWINSZ, &ws) < 0) { + log_debug_errno(errno, "Failed to acquire console window size, ignoring."); + goto unset; + } + + if (ws.ws_col <= 0 && ws.ws_row <= 0) { + log_debug("No console window size set, ignoring."); + goto unset; + } + + r = setenvf("COLUMNS", /* overwrite= */ true, "%u", ws.ws_col); + if (r < 0) { + log_debug_errno(r, "Failed to set $COLUMNS, ignoring: %m"); + goto unset; + } + + r = setenvf("LINES", /* overwrite= */ true, "%u", ws.ws_row); + if (r < 0) { + log_debug_errno(r, "Failed to set $LINES, ignoring: %m"); + goto unset; + } + + log_debug("Recorded console dimensions in environment: $COLUMNS=%u $LINES=%u.", ws.ws_col, ws.ws_row); + return 1; + +unset: + (void) unsetenv("COLUMNS"); + (void) unsetenv("LINES"); + return 0; +} + static int console_setup(void) { if (getpid_cached() != 1) @@ -217,6 +254,9 @@ static int console_setup(void) { /* We don't want to force text mode. Plymouth may be showing pictures already from initrd. */ reset_dev_console_fd(tty_fd, /* switch_to_text= */ false); + + save_console_winsize_in_environment(tty_fd); + return 0; } -- 2.25.1