diff --git a/src/basic/terminal-util.c b/src/basic/terminal-util.c index 2da4f1c2fb..ecdc241247 100644 --- a/src/basic/terminal-util.c +++ b/src/basic/terminal-util.c @@ -1713,6 +1713,16 @@ static bool on_dev_null(void) { return cached_on_dev_null; } +bool term_env_valid(const char *term) { + /* Checks if the specified $TERM value is suitable for propagation, i.e. is not empty, not set to + * "unknown" (as is common in CI), and only contains characters valid in terminal type names. + * Valid $TERM values are things like "xterm-256color", "linux", "screen.xterm-256color", i.e. + * alphanumeric characters, hyphens, underscores, dots, and plus signs. */ + return !isempty(term) && + !streq(term, "unknown") && + in_charset(term, ALPHANUMERICAL "-_+."); +} + bool getenv_terminal_is_dumb(void) { const char *e; diff --git a/src/basic/terminal-util.h b/src/basic/terminal-util.h index dde1430243..7ac5661104 100644 --- a/src/basic/terminal-util.h +++ b/src/basic/terminal-util.h @@ -118,6 +118,7 @@ void columns_lines_cache_reset(int _unused_ signum); void reset_terminal_feature_caches(void); bool on_tty(void); +bool term_env_valid(const char *term); bool getenv_terminal_is_dumb(void); bool terminal_is_dumb(void); diff --git a/src/vmspawn/vmspawn.c b/src/vmspawn/vmspawn.c index 73df1cbadd..1891ac8bad 100644 --- a/src/vmspawn/vmspawn.c +++ b/src/vmspawn/vmspawn.c @@ -3031,6 +3031,24 @@ static int run_virtual_machine(int kvm_device_fd, int vhost_device_fd) { r = strv_prepend(&arg_kernel_cmdline_extra, "console=hvc0"); if (r < 0) return log_oom(); + + /* Propagate the host's $TERM into the VM via the kernel command line. TERM= is + * picked up by PID 1 and inherited by services on /dev/console, and + * systemd.tty.term.hvc0= is used by services directly attached to /dev/hvc0 (such + * as serial-getty). While systemd can auto-detect the terminal type via DCS + * XTGETTCAP, not all terminal emulators implement this, so let's always propagate + * $TERM if we have it. */ + const char *term = getenv("TERM"); + if (term_env_valid(term)) { + FOREACH_STRING(tty_key, "systemd.tty.term.hvc0", "TERM") { + _cleanup_free_ char *p = strjoin(tty_key, "=", term); + if (!p) + return log_oom(); + + if (strv_consume_prepend(&arg_kernel_cmdline_extra, TAKE_PTR(p)) < 0) + return log_oom(); + } + } } _cleanup_free_ char *fstab_extra = NULL;