[systemd-devel] [PATCH 2/5] hostnamed: watch for transient hostname changes
Michal Sekletar
msekleta at redhat.com
Mon Feb 24 06:59:28 PST 2014
hostnamed parses its state information at the startup time and doesn't update
it. This might lead to the situation when we are presenting administrator with
inaccurate information. We should watch for changes in the system and update our
state information accordingly.
---
src/hostname/hostnamed.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c
index e57891b..045f24d 100644
--- a/src/hostname/hostnamed.c
+++ b/src/hostname/hostnamed.c
@@ -24,6 +24,10 @@
#include <unistd.h>
#include <dlfcn.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
#include "util.h"
#include "strv.h"
#include "def.h"
@@ -46,8 +50,12 @@ enum {
typedef struct Context {
char *data[_PROP_MAX];
Hashmap *polkit_registry;
+ int hostnamefd;
+ sd_event_source *hostname_fd_event_source;
} Context;
+static const char *proc_hostname = "/proc/sys/kernel/hostname";
+
static void context_reset(Context *c) {
int p;
@@ -59,11 +67,21 @@ static void context_reset(Context *c) {
}
}
+static void context_init(Context *c) {
+ assert(c);
+
+ memzero(c, sizeof(*c));
+
+ c->hostnamefd = -1;
+}
+
static void context_free(Context *c, sd_bus *bus) {
assert(c);
context_reset(c);
bus_verify_polkit_async_registry_free(bus, c->polkit_registry);
+ sd_event_source_unref(c->hostname_fd_event_source);
+ close_nointr_nofail(c->hostnamefd);
}
static int context_read_data(Context *c) {
@@ -592,6 +610,70 @@ static int connect_bus(Context *c, sd_event *event, sd_bus **_bus) {
return 0;
}
+static int dispatch_hostname_change(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ int r = 0;
+ char hostname[HOST_NAME_MAX + 1] = {}, *t;
+ Context *context = (Context *) userdata;
+
+ r = lseek(fd, 0, SEEK_SET);
+ if (r < 0) {
+ log_error("Failed to seek to begining of the file : %m");
+ return -errno;
+ }
+
+ r = read(fd, hostname, HOST_NAME_MAX);
+ if (r < 0) {
+ log_error("Failed to read hostname : %m");
+ return -errno;
+ }
+
+ strstrip(hostname);
+
+ t = strdup(hostname);
+ if (!t)
+ return log_oom();
+ free(context->data[PROP_HOSTNAME]);
+ context->data[PROP_HOSTNAME] = t;
+
+ return r;
+}
+
+static int open_hostname(sd_event *event, Context *context) {
+ int r = 0, fd;
+
+ assert(event);
+ assert(context);
+
+ fd = open(proc_hostname, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
+ if (fd < 0) {
+ log_error("Failed to open %s : %m", proc_hostname);
+ return -errno;
+ }
+
+ context->hostnamefd = fd;
+
+ r = sd_event_add_io(event, &context->hostname_fd_event_source, fd, EPOLLHUP, dispatch_hostname_change, context);
+ if (r < 0) {
+ /* poll on /proc/sys/kernel/hostname not supported by kernel */
+ if (r == -EPERM) {
+ log_warning("Failed to register hostname fd in event loop: %m. Ignoring.");
+ close_nointr_nofail(fd);
+ return 0;
+ }
+
+ log_error("Failed to register hostname fd in event loop : %m");
+ return r;
+ }
+
+ r = sd_event_source_set_priority(context->hostname_fd_event_source, SD_EVENT_PRIORITY_IMPORTANT);
+ if (r < 0) {
+ log_error("Failed to set priority for hostname fd event source : %m");
+ return r;
+ }
+
+ return r;
+}
+
int main(int argc, char *argv[]) {
Context context = {};
@@ -621,6 +703,8 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ context_init(&context);
+
r = sd_event_default(&event);
if (r < 0) {
log_error("Failed to allocate event loop: %s", strerror(-r));
@@ -639,6 +723,10 @@ int main(int argc, char *argv[]) {
goto finish;
}
+ r = open_hostname(event, &context);
+ if (r < 0)
+ goto finish;
+
r = bus_event_loop_with_idle(event, bus, "org.freedesktop.hostname1", DEFAULT_EXIT_USEC, NULL, NULL);
if (r < 0) {
log_error("Failed to run event loop: %s", strerror(-r));
--
1.8.4.2
More information about the systemd-devel
mailing list