diff options
author | tblume <Thomas.Blume@suse.com> | 2017-11-10 10:31:44 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2017-11-10 10:31:44 +0100 |
commit | ed457f1380d690e26163fd3ad6aff946048e1064 (patch) | |
tree | 07c2a15860d38190ffb4457e31fa4ff741c4042c /src/firstboot | |
parent | c54515b1e42384ad4c582f7fb13434f9224c148f (diff) | |
download | systemd-ed457f1380d690e26163fd3ad6aff946048e1064.tar.gz |
systemd-firstboot: add vconsole keymap support (#7035)
Enable systemd-firstboot to set the keymap.
RFE:
https://github.com/systemd/systemd/issues/6346
Diffstat (limited to 'src/firstboot')
-rw-r--r-- | src/firstboot/firstboot.c | 121 |
1 files changed, 118 insertions, 3 deletions
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c index 586674d458..81f297c5ec 100644 --- a/src/firstboot/firstboot.c +++ b/src/firstboot/firstboot.c @@ -44,16 +44,19 @@ static char *arg_root = NULL; static char *arg_locale = NULL; /* $LANG */ +static char *arg_keymap = NULL; static char *arg_locale_messages = NULL; /* $LC_MESSAGES */ static char *arg_timezone = NULL; static char *arg_hostname = NULL; static sd_id128_t arg_machine_id = {}; static char *arg_root_password = NULL; static bool arg_prompt_locale = false; +static bool arg_prompt_keymap = false; static bool arg_prompt_timezone = false; static bool arg_prompt_hostname = false; static bool arg_prompt_root_password = false; static bool arg_copy_locale = false; +static bool arg_copy_keymap = false; static bool arg_copy_timezone = false; static bool arg_copy_root_password = false; @@ -285,6 +288,84 @@ static int process_locale(void) { return 0; } +static int prompt_keymap(void) { + _cleanup_strv_free_ char **kmaps = NULL; + int r; + + if (arg_keymap) + return 0; + + if (!arg_prompt_keymap) + return 0; + + r = get_keymaps(&kmaps); + if (r == -ENOENT) /* no keymaps installed */ + return r; + if (r < 0) + return log_error_errno(r, "Failed to read keymaps: %m"); + + print_welcome(); + + printf("\nAvailable keymaps:\n\n"); + r = show_menu(kmaps, 3, 22, 60); + if (r < 0) + return r; + + putchar('\n'); + + r = prompt_loop("Please enter system keymap name or number", kmaps, keymap_is_valid, &arg_keymap); + if (r < 0) + return r; + + if (isempty(arg_keymap)) + return 0; + + return 0; +} + +static int process_keymap(void) { + const char *etc_vconsoleconf; + char **keymap; + int r; + + etc_vconsoleconf = prefix_roota(arg_root, "/etc/vconsole.conf"); + if (laccess(etc_vconsoleconf, F_OK) >= 0) + return 0; + + if (arg_copy_keymap && arg_root) { + + mkdir_parents(etc_vconsoleconf, 0755); + r = copy_file("/etc/vconsole.conf", etc_vconsoleconf, 0, 0644, 0, COPY_REFLINK); + if (r != -ENOENT) { + if (r < 0) + return log_error_errno(r, "Failed to copy %s: %m", etc_vconsoleconf); + + log_info("%s copied.", etc_vconsoleconf); + return 0; + } + } + + r = prompt_keymap(); + if (r == -ENOENT) + return 0; /* don't fail if no keymaps are installed */ + if (r < 0) + return r; + + if (!isempty(arg_keymap)) + keymap = STRV_MAKE(strjoina("KEYMAP=", arg_keymap)); + + if (!keymap) + return 0; + + mkdir_parents(etc_vconsoleconf, 0755); + r = write_env_file(etc_vconsoleconf, keymap); + if (r < 0) + return log_error_errno(r, "Failed to write %s: %m", etc_vconsoleconf); + + log_info("%s written.", etc_vconsoleconf); + return 0; +} + static int prompt_timezone(void) { _cleanup_strv_free_ char **zones = NULL; int r; @@ -613,20 +694,23 @@ static void help(void) { " --root=PATH Operate on an alternate filesystem root\n" " --locale=LOCALE Set primary locale (LANG=)\n" " --locale-messages=LOCALE Set message locale (LC_MESSAGES=)\n" + " --keymap=KEYMAP Set keymap\n" " --timezone=TIMEZONE Set timezone\n" " --hostname=NAME Set host name\n" " --machine-ID=ID Set machine ID\n" " --root-password=PASSWORD Set root password\n" " --root-password-file=FILE Set root password from file\n" " --prompt-locale Prompt the user for locale settings\n" + " --prompt-keymap Prompt the user for keymap settings\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" " --prompt Prompt for all of the above\n" " --copy-locale Copy locale from host\n" + " --copy-keymap Copy keymap from host\n" " --copy-timezone Copy timezone from host\n" " --copy-root-password Copy root password from host\n" - " --copy Copy locale, timezone, root password\n" + " --copy Copy locale, keymap, timezone, root password\n" " --setup-machine-id Generate a new random machine ID\n" , program_invocation_short_name); } @@ -638,6 +722,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_ROOT, ARG_LOCALE, ARG_LOCALE_MESSAGES, + ARG_KEYMAP, ARG_TIMEZONE, ARG_HOSTNAME, ARG_MACHINE_ID, @@ -645,11 +730,13 @@ static int parse_argv(int argc, char *argv[]) { ARG_ROOT_PASSWORD_FILE, ARG_PROMPT, ARG_PROMPT_LOCALE, + ARG_PROMPT_KEYMAP, ARG_PROMPT_TIMEZONE, ARG_PROMPT_HOSTNAME, ARG_PROMPT_ROOT_PASSWORD, ARG_COPY, ARG_COPY_LOCALE, + ARG_COPY_KEYMAP, ARG_COPY_TIMEZONE, ARG_COPY_ROOT_PASSWORD, ARG_SETUP_MACHINE_ID, @@ -661,6 +748,7 @@ static int parse_argv(int argc, char *argv[]) { { "root", required_argument, NULL, ARG_ROOT }, { "locale", required_argument, NULL, ARG_LOCALE }, { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, + { "keymap", required_argument, NULL, ARG_KEYMAP }, { "timezone", required_argument, NULL, ARG_TIMEZONE }, { "hostname", required_argument, NULL, ARG_HOSTNAME }, { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, @@ -668,11 +756,13 @@ static int parse_argv(int argc, char *argv[]) { { "root-password-file", required_argument, NULL, ARG_ROOT_PASSWORD_FILE }, { "prompt", no_argument, NULL, ARG_PROMPT }, { "prompt-locale", no_argument, NULL, ARG_PROMPT_LOCALE }, + { "prompt-keymap", no_argument, NULL, ARG_PROMPT_KEYMAP }, { "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 }, { "copy", no_argument, NULL, ARG_COPY }, { "copy-locale", no_argument, NULL, ARG_COPY_LOCALE }, + { "copy-keymap", no_argument, NULL, ARG_COPY_KEYMAP }, { "copy-timezone", no_argument, NULL, ARG_COPY_TIMEZONE }, { "copy-root-password", no_argument, NULL, ARG_COPY_ROOT_PASSWORD }, { "setup-machine-id", no_argument, NULL, ARG_SETUP_MACHINE_ID }, @@ -725,6 +815,18 @@ static int parse_argv(int argc, char *argv[]) { break; + case ARG_KEYMAP: + if (!keymap_is_valid(optarg)) { + log_error("Keymap %s is not valid.", optarg); + return -EINVAL; + } + + r = free_and_strdup(&arg_keymap, optarg); + if (r < 0) + return log_oom(); + + break; + case ARG_TIMEZONE: if (!timezone_is_valid(optarg)) { log_error("Timezone %s is not valid.", optarg); @@ -774,13 +876,17 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_PROMPT: - arg_prompt_locale = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; + arg_prompt_locale = arg_prompt_keymap = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; break; case ARG_PROMPT_LOCALE: arg_prompt_locale = true; break; + case ARG_PROMPT_KEYMAP: + arg_prompt_keymap = true; + break; + case ARG_PROMPT_TIMEZONE: arg_prompt_timezone = true; break; @@ -794,13 +900,17 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_COPY: - arg_copy_locale = arg_copy_timezone = arg_copy_root_password = true; + arg_copy_locale = arg_copy_keymap = arg_copy_timezone = arg_copy_root_password = true; break; case ARG_COPY_LOCALE: arg_copy_locale = true; break; + case ARG_COPY_KEYMAP: + arg_copy_keymap = true; + break; + case ARG_COPY_TIMEZONE: arg_copy_timezone = true; break; @@ -855,6 +965,10 @@ int main(int argc, char *argv[]) { if (r < 0) goto finish; + r = process_keymap(); + if (r < 0) + goto finish; + r = process_timezone(); if (r < 0) goto finish; @@ -875,6 +989,7 @@ finish: free(arg_root); free(arg_locale); free(arg_locale_messages); + free(arg_keymap); free(arg_timezone); free(arg_hostname); string_erase(arg_root_password); |