summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2024-07-10 16:33:10 +0200
committerLennart Poettering <lennart@poettering.net>2024-07-19 11:41:43 +0200
commit63c631d7e26324d96c4f7f5161c0e48b8f7b4a9d (patch)
tree5b1874b9f76f28b6ae75ed923ea628423ef55111
parentterminal-util: add helper that queries terminal sizes via ANSI sequence (diff)
downloadsystemd-63c631d7e26324d96c4f7f5161c0e48b8f7b4a9d.tar.xz
systemd-63c631d7e26324d96c4f7f5161c0e48b8f7b4a9d.zip
terminal-util: add helper that adjust terminal width/height from data acquired via ANSI sequences
-rw-r--r--src/basic/terminal-util.c33
-rw-r--r--src/basic/terminal-util.h2
-rw-r--r--src/test/test-terminal-util.c12
3 files changed, 47 insertions, 0 deletions
diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c
index 1cfde3e3ad..e707adf694 100644
--- a/src/basic/terminal-util.c
+++ b/src/basic/terminal-util.c
@@ -2072,3 +2072,36 @@ finish:
RET_GATHER(r, RET_NERRNO(tcsetattr(input_fd, TCSADRAIN, &old_termios)));
return r;
}
+
+int terminal_fix_size(int input_fd, int output_fd) {
+ unsigned rows, columns;
+ int r;
+
+ /* Tries to update the current terminal dimensions to the ones reported via ANSI sequences */
+
+ r = terminal_verify_same(input_fd, output_fd);
+ if (r < 0)
+ return r;
+
+ struct winsize ws = {};
+ if (ioctl(output_fd, TIOCGWINSZ, &ws) < 0)
+ return log_debug_errno(errno, "Failed to query terminal dimensions, ignoring: %m");
+
+ r = terminal_get_size_by_dsr(input_fd, output_fd, &rows, &columns);
+ if (r < 0)
+ return log_debug_errno(r, "Failed to acquire terminal dimensions via ANSI sequences, not adjusting terminal dimensions: %m");
+
+ if (ws.ws_row == rows && ws.ws_col == columns) {
+ log_debug("Terminal dimensions reported via ANSI sequences match currently set terminal dimensions, not changing.");
+ return 0;
+ }
+
+ ws.ws_col = columns;
+ ws.ws_row = rows;
+
+ if (ioctl(output_fd, TIOCSWINSZ, &ws) < 0)
+ return log_debug_errno(errno, "Failed to update terminal dimensions, ignoring: %m");
+
+ log_debug("Fixed terminal dimensions to %ux%u based on ANSI sequence information.", columns, rows);
+ return 1;
+}
diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h
index e2c21f7fb7..1c47366eab 100644
--- a/src/basic/terminal-util.h
+++ b/src/basic/terminal-util.h
@@ -296,3 +296,5 @@ void termios_disable_echo(struct termios *termios);
int get_default_background_color(double *ret_red, double *ret_green, double *ret_blue);
int terminal_get_size_by_dsr(int input_fd, int output_fd, unsigned *ret_rows, unsigned *ret_columns);
+
+int terminal_fix_size(int input_fd, int output_fd);
diff --git a/src/test/test-terminal-util.c b/src/test/test-terminal-util.c
index 3d15d45558..9a89f55c80 100644
--- a/src/test/test-terminal-util.c
+++ b/src/test/test-terminal-util.c
@@ -197,6 +197,18 @@ TEST(terminal_get_size_by_dsr) {
}
}
+TEST(terminal_fix_size) {
+ int r;
+
+ r = terminal_fix_size(STDIN_FILENO, STDOUT_FILENO);
+ if (r < 0)
+ log_warning_errno(r, "Failed to fix terminal size: %m");
+ else if (r == 0)
+ log_notice("Not fixing terminal size, nothing to do.");
+ else
+ log_notice("Fixed terminal size.");
+}
+
static void test_get_color_mode_with_env(const char *key, const char *val, ColorMode expected) {
ASSERT_OK(setenv(key, val, true));
reset_terminal_feature_caches();