static int set_hostname(sd_bus *bus, char **args, unsigned n) { _cleanup_free_ char *h = NULL; char *hostname = args[1]; int r; assert(args); assert(n == 2); if (!arg_pretty && !arg_static && !arg_transient) arg_pretty = arg_static = arg_transient = true; if (arg_pretty) { const char *p; /* If the passed hostname is already valid, then * assume the user doesn't know anything about pretty * hostnames, so let's unset the pretty hostname, and * just set the passed hostname as static/dynamic * hostname. */ if (arg_static && hostname_is_valid(hostname, true)) { p = ""; /* maybe get rid of trailing dot */ hostname = hostname_cleanup(hostname); } else { p = h = strdup(hostname); if (!p) return log_oom(); hostname_cleanup(hostname); } r = set_simple_string(bus, "SetPrettyHostname", p); if (r < 0) return r; } if (arg_static) { r = set_simple_string(bus, "SetStaticHostname", hostname); if (r < 0) return r; } if (arg_transient) { r = set_simple_string(bus, "SetHostname", hostname); if (r < 0) return r; } return 0; }
int read_hostname_config(const char *path, char **hostname) { _cleanup_fclose_ FILE *f = NULL; char l[LINE_MAX]; char *name = NULL; assert(path); assert(hostname); f = fopen(path, "re"); if (!f) return -errno; /* may have comments, ignore them */ FOREACH_LINE(l, f, return -errno) { truncate_nl(l); if (l[0] != '\0' && l[0] != '#') { /* found line with value */ name = hostname_cleanup(l); name = strdup(name); if (!name) return -ENOMEM; break; } } if (!name) /* no non-empty line found */ return -ENOENT; *hostname = name; return 0; }
static int read_distro_hostname(char **hn) { #if defined(TARGET_ARCH) || defined(TARGET_GENTOO) || defined(TARGET_ALTLINUX) || defined(TARGET_MANDRIVA) || defined(TARGET_MAGEIA) int r; _cleanup_fclose_ FILE *f = NULL; assert(hn); f = fopen(FILENAME, "re"); if (!f) return -errno; for (;;) { char line[LINE_MAX]; char *s, *k; if (!fgets(line, sizeof(line), f)) { if (feof(f)) break; r = -errno; goto finish; } s = strstrip(line); if (!startswith_no_case(s, "HOSTNAME=")) continue; k = strdup(s+9); if (!k) { r = -ENOMEM; goto finish; } hostname_cleanup(k); if (isempty(k)) { free(k); r = -ENOENT; goto finish; } *hn = k; r = 0; goto finish; } r = -ENOENT; finish: return r; #elif defined(TARGET_SUSE) || defined(TARGET_SLACKWARE) return read_and_strip_hostname(FILENAME, hn); #else return -ENOENT; #endif }
static int set_hostname(int argc, char **argv, void *userdata) { _cleanup_free_ char *h = NULL; const char *hostname = argv[1]; sd_bus *bus = userdata; int r; if (!arg_pretty && !arg_static && !arg_transient) arg_pretty = arg_static = arg_transient = true; if (arg_pretty) { const char *p; /* If the passed hostname is already valid, then assume the user doesn't know anything about pretty * hostnames, so let's unset the pretty hostname, and just set the passed hostname as static/dynamic * hostname. */ if (arg_static && hostname_is_valid(hostname, true)) p = ""; /* No pretty hostname (as it is redundant), just a static one */ else p = hostname; /* Use the passed name as pretty hostname */ r = set_simple_string(bus, "SetPrettyHostname", p); if (r < 0) return r; /* Now that we set the pretty hostname, let's clean up the parameter and use that as static * hostname. If the hostname was already valid as static hostname, this will only chop off the trailing * dot if there is one. If it was not valid, then it will be made fully valid by truncating, dropping * multiple dots, and dropping weird chars. Note that we clean the name up only if we also are * supposed to set the pretty name. If the pretty name is not being set we assume the user knows what * he does and pass the name as-is. */ h = strdup(hostname); if (!h) return log_oom(); hostname = hostname_cleanup(h); /* Use the cleaned up name as static hostname */ } if (arg_static) { r = set_simple_string(bus, "SetStaticHostname", hostname); if (r < 0) return r; } if (arg_transient) { r = set_simple_string(bus, "SetHostname", hostname); if (r < 0) return r; } return 0; }
static int read_and_strip_hostname(const char *path, char **hn) { char *s; int r; assert(path); assert(hn); r = read_one_line_file(path, &s); if (r < 0) return r; hostname_cleanup(s); if (isempty(s)) { free(s); return -ENOENT; } *hn = s; return 0; }
static int prompt_hostname(void) { int r; if (arg_hostname) return 0; if (!arg_prompt_hostname) return 0; print_welcome(); putchar('\n'); for (;;) { _cleanup_free_ char *h = NULL; r = ask_string(&h, "%s Please enter hostname for new system (empty to skip): ", draw_special_char(DRAW_TRIANGULAR_BULLET)); if (r < 0) return log_error_errno(r, "Failed to query hostname: %m"); if (isempty(h)) { log_warning("No hostname entered, skipping."); break; } if (!hostname_is_valid(h, true)) { 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; } return 0; }
int read_etc_hostname_stream(FILE *f, char **ret) { int r; assert(f); assert(ret); for (;;) { _cleanup_free_ char *line = NULL; char *p; r = read_line(f, LONG_LINE_MAX, &line); if (r < 0) return r; if (r == 0) /* EOF without any hostname? the file is empty, let's treat that exactly like no file at all: ENOENT */ return -ENOENT; p = strstrip(line); /* File may have empty lines or comments, ignore them */ if (!IN_SET(*p, '\0', '#')) { char *copy; hostname_cleanup(p); /* normalize the hostname */ if (!hostname_is_valid(p, true)) /* check that the hostname we return is valid */ return -EBADMSG; copy = strdup(p); if (!copy) return -ENOMEM; *ret = copy; return 0; } } }
static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ROOT, ARG_LOCALE, ARG_LOCALE_MESSAGES, ARG_TIMEZONE, ARG_HOSTNAME, ARG_MACHINE_ID, ARG_ROOT_PASSWORD, ARG_ROOT_PASSWORD_FILE, ARG_PROMPT, ARG_PROMPT_LOCALE, ARG_PROMPT_TIMEZONE, ARG_PROMPT_HOSTNAME, ARG_PROMPT_ROOT_PASSWORD, ARG_COPY, ARG_COPY_LOCALE, ARG_COPY_TIMEZONE, ARG_COPY_ROOT_PASSWORD, ARG_SETUP_MACHINE_ID, }; static const struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, ARG_VERSION }, { "root", required_argument, NULL, ARG_ROOT }, { "locale", required_argument, NULL, ARG_LOCALE }, { "locale-messages", required_argument, NULL, ARG_LOCALE_MESSAGES }, { "timezone", required_argument, NULL, ARG_TIMEZONE }, { "hostname", required_argument, NULL, ARG_HOSTNAME }, { "machine-id", required_argument, NULL, ARG_MACHINE_ID }, { "root-password", required_argument, NULL, ARG_ROOT_PASSWORD }, { "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-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-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 }, {} }; int r, c; assert(argc >= 0); assert(argv); while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0) switch (c) { case 'h': help(); return 0; case ARG_VERSION: return version(); case ARG_ROOT: free(arg_root); arg_root = path_make_absolute_cwd(optarg); if (!arg_root) return log_oom(); path_kill_slashes(arg_root); if (path_equal(arg_root, "/")) arg_root = mfree(arg_root); break; case ARG_LOCALE: if (!locale_is_valid(optarg)) { log_error("Locale %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_locale, optarg); if (r < 0) return log_oom(); break; case ARG_LOCALE_MESSAGES: if (!locale_is_valid(optarg)) { log_error("Locale %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_locale_messages, optarg); if (r < 0) return log_oom(); break; case ARG_TIMEZONE: if (!timezone_is_valid(optarg)) { log_error("Timezone %s is not valid.", optarg); return -EINVAL; } r = free_and_strdup(&arg_timezone, optarg); if (r < 0) return log_oom(); break; case ARG_ROOT_PASSWORD: r = free_and_strdup(&arg_root_password, optarg); if (r < 0) return log_oom(); break; case ARG_ROOT_PASSWORD_FILE: arg_root_password = mfree(arg_root_password); r = read_one_line_file(optarg, &arg_root_password); if (r < 0) return log_error_errno(r, "Failed to read %s: %m", optarg); break; case ARG_HOSTNAME: if (!hostname_is_valid(optarg, true)) { log_error("Host name %s is not valid.", optarg); return -EINVAL; } hostname_cleanup(optarg); r = free_and_strdup(&arg_hostname, optarg); if (r < 0) return log_oom(); break; case ARG_MACHINE_ID: if (sd_id128_from_string(optarg, &arg_machine_id) < 0) { log_error("Failed to parse machine id %s.", optarg); return -EINVAL; } break; case ARG_PROMPT: arg_prompt_locale = arg_prompt_timezone = arg_prompt_hostname = arg_prompt_root_password = true; break; case ARG_PROMPT_LOCALE: arg_prompt_locale = true; break; case ARG_PROMPT_TIMEZONE: arg_prompt_timezone = true; break; case ARG_PROMPT_HOSTNAME: arg_prompt_hostname = true; break; case ARG_PROMPT_ROOT_PASSWORD: arg_prompt_root_password = true; break; case ARG_COPY: arg_copy_locale = arg_copy_timezone = arg_copy_root_password = true; break; case ARG_COPY_LOCALE: arg_copy_locale = true; break; case ARG_COPY_TIMEZONE: arg_copy_timezone = true; break; case ARG_COPY_ROOT_PASSWORD: arg_copy_root_password = true; break; case ARG_SETUP_MACHINE_ID: r = sd_id128_randomize(&arg_machine_id); if (r < 0) return log_error_errno(r, "Failed to generate randomized machine ID: %m"); break; case '?': return -EINVAL; default: assert_not_reached("Unhandled option"); } return 1; }
static void test_hostname_cleanup(void) { char *s; s = strdupa("foobar"); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa("foobar.com"); assert_se(streq(hostname_cleanup(s), "foobar.com")); s = strdupa("foobar.com."); assert_se(streq(hostname_cleanup(s), "foobar.com")); s = strdupa("fooBAR"); assert_se(streq(hostname_cleanup(s), "fooBAR")); s = strdupa("fooBAR.com"); assert_se(streq(hostname_cleanup(s), "fooBAR.com")); s = strdupa("fooBAR."); assert_se(streq(hostname_cleanup(s), "fooBAR")); s = strdupa("fooBAR.com."); assert_se(streq(hostname_cleanup(s), "fooBAR.com")); s = strdupa("fööbar"); assert_se(streq(hostname_cleanup(s), "fbar")); s = strdupa(""); assert_se(isempty(hostname_cleanup(s))); s = strdupa("."); assert_se(isempty(hostname_cleanup(s))); s = strdupa(".."); assert_se(isempty(hostname_cleanup(s))); s = strdupa("foobar."); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa(".foobar"); assert_se(streq(hostname_cleanup(s), "foobar")); s = strdupa("foo..bar"); assert_se(streq(hostname_cleanup(s), "foo.bar")); s = strdupa("foo.bar.."); assert_se(streq(hostname_cleanup(s), "foo.bar")); s = strdupa("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); assert_se(streq(hostname_cleanup(s), "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")); }
static int set_hostname(DBusConnection *bus, char **args, unsigned n) { _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; dbus_bool_t interactive = true; _cleanup_free_ char *h = NULL; const char *hostname = args[1]; int r; assert(args); assert(n == 2); polkit_agent_open_if_enabled(); if (arg_set_pretty) { const char *p; /* If the passed hostname is already valid, then * assume the user doesn't know anything about pretty * hostnames, so let's unset the pretty hostname, and * just set the passed hostname as static/dynamic * hostname. */ h = strdup(hostname); if (!h) return log_oom(); hostname_cleanup(h, true); if (arg_set_static && streq(h, hostname)) p = ""; else { p = hostname; hostname = h; } r = bus_method_call_with_reply( bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "SetPrettyHostname", &reply, NULL, DBUS_TYPE_STRING, &p, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); if (r < 0) return r; dbus_message_unref(reply); reply = NULL; } if (arg_set_static) { r = bus_method_call_with_reply( bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "SetStaticHostname", &reply, NULL, DBUS_TYPE_STRING, &hostname, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); if (r < 0) return r; dbus_message_unref(reply); reply = NULL; } if (arg_set_transient) { r = bus_method_call_with_reply( bus, "org.freedesktop.hostname1", "/org/freedesktop/hostname1", "org.freedesktop.hostname1", "SetHostname", &reply, NULL, DBUS_TYPE_STRING, &hostname, DBUS_TYPE_BOOLEAN, &interactive, DBUS_TYPE_INVALID); if (r < 0) return r; } return 0; }