+static int determine_hostname(char **ret) {
+ _cleanup_free_ char *h = NULL, *n = NULL;
+ int r;
+
+ assert(ret);
+
+ h = gethostname_malloc();
+ if (!h)
+ return log_oom();
+
+ if (!utf8_is_valid(h)) {
+ log_error("System hostname is not UTF-8 clean.");
+ return -EINVAL;
+ }
+
+ r = dns_name_normalize(h, &n);
+ if (r < 0) {
+ log_error("System hostname '%s' cannot be normalized.", h);
+ return r;
+ }
+
+ *ret = n;
+ n = NULL;
+
+ return 0;
+}
+
+static int on_hostname_change(sd_event_source *es, int fd, uint32_t revents, void *userdata) {
+ _cleanup_free_ char *h = NULL;
+ Manager *m = userdata;
+ int r;
+
+ assert(m);
+
+ r = determine_hostname(&h);
+ if (r < 0)
+ return 0; /* ignore invalid hostnames */
+
+ if (streq(h, m->hostname))
+ return 0;
+
+ log_info("System hostname changed to '%s'.", h);
+ free(m->hostname);
+ m->hostname = h;
+ h = NULL;
+
+ manager_refresh_rrs(m);
+
+ return 0;
+}
+
+static int manager_watch_hostname(Manager *m) {
+ _cleanup_free_ char *h = NULL;
+ int r;
+
+ assert(m);
+
+ m->hostname_fd = open("/proc/sys/kernel/hostname", O_RDONLY|O_CLOEXEC|O_NDELAY|O_NOCTTY);
+ if (m->hostname_fd < 0) {
+ log_warning("Failed to watch hostname: %m");
+ return 0;
+ }
+
+ r = sd_event_add_io(m->event, &m->hostname_event_source, m->hostname_fd, 0, on_hostname_change, m);
+ if (r < 0) {
+ if (r == -EPERM)
+ /* kernels prior to 3.2 don't support polling this file. Ignore the failure. */
+ m->hostname_fd = safe_close(m->hostname_fd);
+ else {
+ log_error("Failed to add hostname event source: %s", strerror(-r));
+ return r;
+ }
+ }
+
+ r = determine_hostname(&m->hostname);
+ if (r < 0) {
+ log_info("Defaulting to hostname 'linux'.");
+ m->hostname = strdup("linux");
+ if (!m->hostname)
+ return log_oom();
+ } else
+ log_info("Using system hostname '%s'.", m->hostname);
+
+ return 0;
+}
+