summaryrefslogtreecommitdiffstats
path: root/src/firstboot/firstboot.c
diff options
context:
space:
mode:
authorMichael Ferrari <nekkodroid404@gmail.com>2024-10-09 17:30:44 +0200
committerMichael Ferrari <nekkodroid404@gmail.com>2024-10-30 20:13:56 +0100
commit178d80d719a07515f52eb4fc9398ab5f656e55e4 (patch)
tree7b47408acabd647afb419dd688141cc849c6b9c9 /src/firstboot/firstboot.c
parentfirstboot: use consistent wording for prompts (diff)
downloadsystemd-178d80d719a07515f52eb4fc9398ab5f656e55e4.tar.xz
systemd-178d80d719a07515f52eb4fc9398ab5f656e55e4.zip
firstboot: generalize prompt_loop more
Allows unifying the custom logic for the hostname and root shell. Root password prompting remains separate as it's logic is substantially different to the other prompts.
Diffstat (limited to 'src/firstboot/firstboot.c')
-rw-r--r--src/firstboot/firstboot.c144
1 files changed, 62 insertions, 82 deletions
diff --git a/src/firstboot/firstboot.c b/src/firstboot/firstboot.c
index 4d8702c9aa..9be62b8df3 100644
--- a/src/firstboot/firstboot.c
+++ b/src/firstboot/firstboot.c
@@ -134,7 +134,7 @@ static void print_welcome(int rfd) {
done = true;
}
-static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*is_valid)(const char *name), char **ret) {
+static int prompt_loop(int rfd, const char *text, char **l, unsigned percentage, bool (*is_valid)(int rfd, const char *name), char **ret) {
int r;
assert(text);
@@ -145,7 +145,8 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
_cleanup_free_ char *p = NULL;
unsigned u;
- r = ask_string(&p, "%s %s (empty to skip, \"list\" to list options): ",
+ r = ask_string(&p, strv_isempty(l) ? "%s %s (empty to skip): "
+ : "%s %s (empty to skip, \"list\" to list options): ",
special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET), text);
if (r < 0)
return log_error_errno(r, "Failed to query user: %m");
@@ -155,27 +156,29 @@ static int prompt_loop(const char *text, char **l, unsigned percentage, bool (*i
return 0;
}
- if (streq(p, "list")) {
- r = show_menu(l, 3, 20, percentage);
- if (r < 0)
- return r;
-
- putchar('\n');
- continue;
- };
+ if (!strv_isempty(l)) {
+ if (streq(p, "list")) {
+ r = show_menu(l, 3, 20, percentage);
+ if (r < 0)
+ return r;
- r = safe_atou(p, &u);
- if (r >= 0) {
- if (u <= 0 || u > strv_length(l)) {
- log_error("Specified entry number out of range.");
+ putchar('\n');
continue;
}
- log_info("Selected '%s'.", l[u-1]);
- return free_and_strdup_warn(ret, l[u-1]);
+ r = safe_atou(p, &u);
+ if (r >= 0) {
+ if (u <= 0 || u > strv_length(l)) {
+ log_error("Specified entry number out of range.");
+ continue;
+ }
+
+ log_info("Selected '%s'.", l[u-1]);
+ return free_and_strdup_warn(ret, l[u-1]);
+ }
}
- if (is_valid(p))
+ if (is_valid(rfd, p))
return free_and_replace(*ret, p);
/* Be more helpful to the user, and give a hint what the user might have wanted to type. */
@@ -261,9 +264,15 @@ static bool locale_is_installed_bool(const char *name) {
}
static bool locale_is_ok(int rfd, const char *name) {
+ int r;
+
assert(rfd >= 0);
- return dir_fd_is_root(rfd) ? locale_is_installed_bool(name) : locale_is_valid(name);
+ r = dir_fd_is_root(rfd);
+ if (r < 0)
+ log_debug_errno(r, "Unable to determine if operating on host root directory, assuming we are: %m");
+
+ return r != 0 ? locale_is_installed_bool(name) : locale_is_valid(name);
}
static int prompt_locale(int rfd) {
@@ -318,21 +327,18 @@ static int prompt_locale(int rfd) {
/* Not setting arg_locale_message here, since it defaults to LANG anyway */
}
} else {
- bool (*is_valid)(const char *name) = dir_fd_is_root(rfd) ? locale_is_installed_bool
- : locale_is_valid;
-
print_welcome(rfd);
- r = prompt_loop("Please enter the new system locale name or number",
- locales, 60, is_valid, &arg_locale);
+ r = prompt_loop(rfd, "Please enter the new system locale name or number",
+ locales, 60, locale_is_ok, &arg_locale);
if (r < 0)
return r;
if (isempty(arg_locale))
return 0;
- r = prompt_loop("Please enter the new system message locale name or number",
- locales, 60, is_valid, &arg_locale_messages);
+ r = prompt_loop(rfd, "Please enter the new system message locale name or number",
+ locales, 60, locale_is_ok, &arg_locale_messages);
if (r < 0)
return r;
@@ -406,14 +412,16 @@ static bool keymap_exists_bool(const char *name) {
return keymap_exists(name) > 0;
}
-static typeof(&keymap_is_valid) determine_keymap_validity_func(int rfd) {
+static bool keymap_is_ok(int rfd, const char* name) {
int r;
+ assert(rfd >= 0);
+
r = dir_fd_is_root(rfd);
if (r < 0)
log_debug_errno(r, "Unable to determine if operating on host root directory, assuming we are: %m");
- return r != 0 ? keymap_exists_bool : keymap_is_valid;
+ return r != 0 ? keymap_exists_bool(name) : keymap_is_valid(name);
}
static int prompt_keymap(int rfd) {
@@ -446,8 +454,8 @@ static int prompt_keymap(int rfd) {
print_welcome(rfd);
- return prompt_loop("Please enter the new keymap name or number",
- kmaps, 60, determine_keymap_validity_func(rfd), &arg_keymap);
+ return prompt_loop(rfd, "Please enter the new keymap name or number",
+ kmaps, 60, keymap_is_ok, &arg_keymap);
}
static int process_keymap(int rfd) {
@@ -504,7 +512,9 @@ static int process_keymap(int rfd) {
return 1;
}
-static bool timezone_is_valid_log_debug(const char *name) {
+static bool timezone_is_ok(int rfd, const char *name) {
+ assert(rfd >= 0);
+
return timezone_is_valid(name, LOG_DEBUG);
}
@@ -536,12 +546,8 @@ static int prompt_timezone(int rfd) {
print_welcome(rfd);
- r = prompt_loop("Please enter the new timezone name or number",
- zones, 30, timezone_is_valid_log_debug, &arg_timezone);
- if (r < 0)
- return r;
-
- return 0;
+ return prompt_loop(rfd, "Please enter the new timezone name or number",
+ zones, 30, timezone_is_ok, &arg_timezone);
}
static int process_timezone(int rfd) {
@@ -602,6 +608,12 @@ static int process_timezone(int rfd) {
return 0;
}
+static bool hostname_is_ok(int rfd, const char *name) {
+ assert(rfd >= 0);
+
+ return hostname_is_valid(name, VALID_HOSTNAME_TRAILING_DOT);
+}
+
static int prompt_hostname(int rfd) {
int r;
@@ -617,30 +629,12 @@ static int prompt_hostname(int rfd) {
print_welcome(rfd);
- for (;;) {
- _cleanup_free_ char *h = NULL;
-
- r = ask_string(&h, "%s Please enter the new hostname (empty to skip): ",
- special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
- if (r < 0)
- return log_error_errno(r, "Failed to query hostname: %m");
-
- if (isempty(h)) {
- log_info("No hostname entered, skipping.");
- break;
- }
-
- if (!hostname_is_valid(h, VALID_HOSTNAME_TRAILING_DOT)) {
- log_error("Specified hostname invalid.");
- continue;
- }
-
- /* Get rid of the trailing dot that we allow, but don't want to see */
- arg_hostname = hostname_cleanup(h);
- h = NULL;
- break;
- }
+ r = prompt_loop(rfd, "Please enter the new hostname",
+ NULL, 0, hostname_is_ok, &arg_hostname);
+ if (r < 0)
+ return r;
+ hostname_cleanup(arg_hostname);
return 0;
}
@@ -800,6 +794,12 @@ static int find_shell(int rfd, const char *path) {
return 0;
}
+static bool shell_is_ok(int rfd, const char *path) {
+ assert(rfd >= 0);
+
+ return find_shell(rfd, path) >= 0;
+}
+
static int prompt_root_shell(int rfd) {
int r;
@@ -823,28 +823,8 @@ static int prompt_root_shell(int rfd) {
print_welcome(rfd);
- for (;;) {
- _cleanup_free_ char *s = NULL;
-
- r = ask_string(&s, "%s Please enter the new root shell (empty to skip): ",
- special_glyph(SPECIAL_GLYPH_TRIANGULAR_BULLET));
- if (r < 0)
- return log_error_errno(r, "Failed to query root shell: %m");
-
- if (isempty(s)) {
- log_info("No shell entered, skipping.");
- break;
- }
-
- r = find_shell(rfd, s);
- if (r < 0)
- continue;
-
- arg_root_shell = TAKE_PTR(s);
- break;
- }
-
- return 0;
+ return prompt_loop(rfd, "Please enter the new root shell",
+ NULL, 0, shell_is_ok, &arg_root_shell);
}
static int write_root_passwd(int rfd, int etc_fd, const char *password, const char *shell) {
@@ -1669,7 +1649,7 @@ static int run(int argc, char *argv[]) {
/* We check these conditions here instead of in parse_argv() so that we can take the root directory
* into account. */
- if (arg_keymap && !determine_keymap_validity_func(rfd)(arg_keymap))
+ if (arg_keymap && !keymap_is_ok(rfd, arg_keymap))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Keymap %s is not installed.", arg_keymap);
if (arg_locale && !locale_is_ok(rfd, arg_locale))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Locale %s is not installed.", arg_locale);