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.
This commit is contained in:
Lennart Poettering
2024-07-19 11:44:04 +02:00
parent 0ea4198f0a
commit b411228199
+40
View File
@@ -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;
}