vmspawn: propagate $TERM from host into VM via kernel command line
When running in a console mode (interactive, native, or read-only), propagate the host's $TERM into the VM by adding TERM= and systemd.tty.term.hvc0= to the kernel command line. TERM= is picked up by PID 1 and inherited by services on /dev/console (such as emergency.service). systemd.tty.term.hvc0= is used by services directly attached to /dev/hvc0 (such as serial-getty@hvc0.service) which look up $TERM via the systemd.tty.term.<tty> kernel command line parameter. While systemd can auto-detect the terminal type via DCS XTGETTCAP, not all terminal emulators implement this, so explicitly propagating $TERM provides a more reliable experience. We skip propagation when $TERM is unset or set to "unknown" (as is the case in GitHub Actions and some other CI environments). Previously this was handled by mkosi synthesizing the corresponding kernel command line parameters externally. Co-developed-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
committed by
Daan De Meyer
parent
214f7f0b8a
commit
dcce04e649
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user