diff --git a/man/systemd-firstboot.xml b/man/systemd-firstboot.xml
index cc4ddc0cf6..26ce757174 100644
--- a/man/systemd-firstboot.xml
+++ b/man/systemd-firstboot.xml
@@ -271,6 +271,17 @@
+
+
+
+ If invoked from a virtual terminal TTY equivalent to
+ , otherwise has no effect. Or in other words, only prompts
+ interactively for a keymap if a local keyboard is used for interactivity that requires it.
+
+
+
+
+
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 9637d9f8f6..9f237dc266 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -71,6 +71,7 @@ static char *arg_root_shell = NULL;
static char *arg_kernel_cmdline = NULL;
static bool arg_prompt_locale = false;
static bool arg_prompt_keymap = false;
+static bool arg_prompt_keymap_auto = false;
static bool arg_prompt_timezone = false;
static bool arg_prompt_hostname = false;
static bool arg_prompt_root_password = false;
@@ -415,7 +416,21 @@ static int prompt_keymap(int rfd, sd_varlink **mute_console_link) {
return 0;
}
- if (!arg_prompt_keymap) {
+ bool b;
+ if (arg_prompt_keymap_auto) {
+ _cleanup_free_ char *ttyname = NULL;
+
+ r = getttyname_harder(STDOUT_FILENO, &ttyname);
+ if (r < 0) {
+ log_debug_errno(r, "Cannot determine TTY we are connected, ignoring: %m");
+ b = false; /* if we can't resolve this, it's probably not a VT */
+ } else {
+ b = tty_is_vc_resolve(ttyname);
+ log_debug("Detected connection to local console: %s", yes_no(b));
+ }
+ } else
+ b = arg_prompt_keymap;
+ if (!b) {
log_debug("Prompting for keymap was not requested.");
return 0;
}
@@ -1234,6 +1249,8 @@ static int help(void) {
" Set kernel command line\n"
" --prompt-locale Prompt the user for locale settings\n"
" --prompt-keymap Prompt the user for keymap settings\n"
+ " --prompt-keymap-auto Prompt the user for keymap settings if invoked\n"
+ " on local console\n"
" --prompt-timezone Prompt the user for timezone\n"
" --prompt-hostname Prompt the user for hostname\n"
" --prompt-root-password Prompt the user for root password\n"
@@ -1284,6 +1301,7 @@ static int parse_argv(int argc, char *argv[]) {
ARG_PROMPT,
ARG_PROMPT_LOCALE,
ARG_PROMPT_KEYMAP,
+ ARG_PROMPT_KEYMAP_AUTO,
ARG_PROMPT_TIMEZONE,
ARG_PROMPT_HOSTNAME,
ARG_PROMPT_ROOT_PASSWORD,
@@ -1323,6 +1341,7 @@ static int parse_argv(int argc, char *argv[]) {
{ "prompt", no_argument, NULL, ARG_PROMPT },
{ "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE },
{ "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP },
+ { "prompt-keymap-auto", no_argument, NULL, ARG_PROMPT_KEYMAP_AUTO },
{ "prompt-timezone", no_argument, NULL, ARG_PROMPT_TIMEZONE },
{ "prompt-hostname", no_argument, NULL, ARG_PROMPT_HOSTNAME },
{ "prompt-root-password", no_argument, NULL, ARG_PROMPT_ROOT_PASSWORD },
@@ -1480,6 +1499,7 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_PROMPT:
arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname =
arg_prompt_root_password = arg_prompt_root_shell = true;
+ arg_prompt_keymap_auto = false;
break;
case ARG_PROMPT_LOCALE:
@@ -1488,6 +1508,11 @@ static int parse_argv(int argc, char *argv[]) {
case ARG_PROMPT_KEYMAP:
arg_prompt_keymap = true;
+ arg_prompt_keymap_auto = false;
+ break;
+
+ case ARG_PROMPT_KEYMAP_AUTO:
+ arg_prompt_keymap_auto = true;
break;
case ARG_PROMPT_TIMEZONE:
@@ -1668,7 +1693,7 @@ static int run(int argc, char *argv[]) {
return log_error_errno(r, "Failed to parse systemd.firstboot= kernel command line argument, ignoring: %m");
if (r > 0 && !enabled) {
log_debug("Found systemd.firstboot=no kernel command line argument, turning off all prompts.");
- arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = arg_prompt_root_shell = false;
+ arg_prompt_locale = arg_prompt_keymap = arg_prompt_keymap_auto = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = arg_prompt_root_shell = false;
}
}
diff --git a/test/units/TEST-74-AUX-UTILS.firstboot.sh b/test/units/TEST-74-AUX-UTILS.firstboot.sh
index 5f7209231a..d6946ba4ee 100755
--- a/test/units/TEST-74-AUX-UTILS.firstboot.sh
+++ b/test/units/TEST-74-AUX-UTILS.firstboot.sh
@@ -221,6 +221,10 @@ grep -q "LC_MESSAGES=bar" "$ROOT$LOCALE_PATH"
if [ -d "/usr/share/keymaps/" ] || [ -d "/usr/share/kbd/keymaps/" ] || [ -d "/usr/lib/kbd/keymaps/" ] ; then
echo -ne "foo\n" | systemd-firstboot --root="$ROOT" --prompt-keymap
grep -q "KEYMAP=foo" "$ROOT/etc/vconsole.conf"
+
+ rm "$ROOT/etc/vconsole.conf"
+ # this should be a NOP, given that stdout is connected to /dev/null, and hence not a VT
+ systemd-firstboot --root="$ROOT" --prompt-keymap-auto > /dev/null
fi
echo -ne "Europe/Berlin\n" | systemd-firstboot --root="$ROOT" --prompt-timezone
readlink "$ROOT/etc/localtime" | grep -q "Europe/Berlin$"
diff --git a/units/systemd-firstboot.service b/units/systemd-firstboot.service
index 5ba9c8ba03..fb1c59ad6f 100644
--- a/units/systemd-firstboot.service
+++ b/units/systemd-firstboot.service
@@ -32,7 +32,7 @@ Before=shutdown.target
[Service]
Type=oneshot
RemainAfterExit=yes
-ExecStart=systemd-firstboot --prompt-locale --prompt-keymap --prompt-timezone --prompt-root-password --mute-console=yes
+ExecStart=systemd-firstboot --prompt-locale --prompt-keymap-auto --prompt-timezone --prompt-root-password --mute-console=yes
StandardOutput=tty
StandardInput=tty
StandardError=tty