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;
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);
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;