X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fdbus.c;h=5180d89b2ce84319af4a1f83d0fb20536c4f4ebf;hb=6fa4853328e3d78d092172fa54effb7e785d0a85;hp=f05f610718e5beb50f72482c429a3e7dd6508844;hpb=4db17f291c627c885de668200ff8cce2e57c933f;p=elogind.git diff --git a/src/core/dbus.c b/src/core/dbus.c index f05f61071..5180d89b2 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -28,7 +28,6 @@ #include "dbus.h" #include "log.h" #include "strv.h" -#include "cgroup.h" #include "mkdir.h" #include "missing.h" #include "dbus-unit.h" @@ -48,7 +47,7 @@ #include "special.h" #include "dbus-common.h" -#define CONNECTIONS_MAX 52 +#define CONNECTIONS_MAX 512 /* Well-known address (http://dbus.freedesktop.org/doc/dbus-specification.html#message-bus-types) */ #define DBUS_SYSTEM_BUS_DEFAULT_ADDRESS "unix:path=/var/run/dbus/system_bus_socket" @@ -203,13 +202,11 @@ static void bus_toggle_watch(DBusWatch *bus_watch, void *data) { } static int bus_timeout_arm(Manager *m, Watch *w) { - struct itimerspec its; + struct itimerspec its = {}; assert(m); assert(w); - zero(its); - if (dbus_timeout_get_enabled(w->data.bus_timeout)) { timespec_store(&its.it_value, dbus_timeout_get_interval(w->data.bus_timeout) * USEC_PER_MSEC); its.it_interval = its.it_value; @@ -365,8 +362,8 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBus log_debug("Got D-Bus activation request for %s", name); - if (manager_unit_pending_inactive(m, SPECIAL_DBUS_SERVICE) || - manager_unit_pending_inactive(m, SPECIAL_DBUS_SOCKET)) { + if (manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SERVICE) || + manager_unit_inactive_or_pending(m, SPECIAL_DBUS_SOCKET)) { r = -EADDRNOTAVAIL; dbus_set_error(&error, BUS_ERROR_SHUTTING_DOWN, "Refusing activation, D-Bus is shutting down."); } else { @@ -406,7 +403,7 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBus dbus_error_free(&error); if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; dbus_message_unref(reply); @@ -445,7 +442,7 @@ static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, D log_debug("System D-Bus connection terminated."); bus_done_system(m); - } else if (m->running_as != MANAGER_SYSTEM && + } else if (m->running_as != SYSTEMD_SYSTEM && dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) { const char *cgroup; @@ -455,7 +452,7 @@ static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, D DBUS_TYPE_INVALID)) log_error("Failed to parse Released message: %s", bus_error_message(&error)); else - cgroup_notify_empty(m, cgroup); + manager_notify_cgroup_empty(m, cgroup); } dbus_error_free(&error); @@ -481,7 +478,7 @@ static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, if (dbus_message_is_signal(message, DBUS_INTERFACE_LOCAL, "Disconnected")) shutdown_connection(m, connection); - else if (m->running_as == MANAGER_SYSTEM && + else if (m->running_as == SYSTEMD_SYSTEM && dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) { const char *cgroup; @@ -491,7 +488,7 @@ static DBusHandlerResult private_bus_message_filter(DBusConnection *connection, DBUS_TYPE_INVALID)) log_error("Failed to parse Released message: %s", bus_error_message(&error)); else - cgroup_notify_empty(m, cgroup); + manager_notify_cgroup_empty(m, cgroup); /* Forward the message to the system bus, so that user * instances are notified as well */ @@ -776,7 +773,7 @@ static int init_registered_system_bus(Manager *m) { if (!dbus_connection_add_filter(m->system_bus, system_bus_message_filter, m, NULL)) return log_oom(); - if (m->running_as != MANAGER_SYSTEM) { + if (m->running_as != SYSTEMD_SYSTEM) { DBusError error; dbus_error_init(&error); @@ -838,7 +835,7 @@ static int init_registered_api_bus(Manager *m) { if (r < 0) return r; - if (m->running_as == MANAGER_USER) { + if (m->running_as == SYSTEMD_USER) { char *id; log_debug("Successfully connected to API D-Bus bus %s as %s", strnull((id = dbus_connection_get_server_id(m->api_bus))), @@ -889,7 +886,7 @@ static void bus_register_cb(DBusPendingCall *pending, void *userdata) { if (conn == &m->system_bus) { r = init_registered_system_bus(m); - if (r == 0 && m->running_as == MANAGER_SYSTEM) + if (r == 0 && m->running_as == SYSTEMD_SYSTEM) r = init_registered_api_bus(m); } else r = init_registered_api_bus(m); @@ -978,9 +975,8 @@ static DBusConnection* manager_bus_connect_private(Manager *m, DBusBusType type) } return connection; + fail: - if (connection) - dbus_connection_close(connection); dbus_error_free(&error); return NULL; } @@ -1019,7 +1015,7 @@ static int bus_init_api(Manager *m) { if (m->api_bus) return 0; - if (m->running_as == MANAGER_SYSTEM) { + if (m->running_as == SYSTEMD_SYSTEM) { m->api_bus = m->system_bus; /* In this mode there is no distinct connection to the API bus, * the API is published on the system bus. @@ -1054,7 +1050,7 @@ fail: static int bus_init_private(Manager *m) { DBusError error; int r; - const char *const external_only[] = { + static const char *const external_only[] = { "EXTERNAL", NULL }; @@ -1066,7 +1062,7 @@ static int bus_init_private(Manager *m) { if (m->private_bus) return 0; - if (m->running_as == MANAGER_SYSTEM) { + if (m->running_as == SYSTEMD_SYSTEM) { /* We want the private bus only when running as init */ if (getpid() != 1) @@ -1077,18 +1073,33 @@ static int bus_init_private(Manager *m) { } else { const char *e; char *p; + char *escaped; e = secure_getenv("XDG_RUNTIME_DIR"); if (!e) return 0; - if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) { + if (asprintf(&p, "%s/systemd/private", e) < 0) { r = log_oom(); goto fail; } - mkdir_parents_label(p+10, 0755); - unlink(p+10); + mkdir_parents_label(p, 0755); + unlink(p); + free(p); + + escaped = dbus_address_escape_value(e); + if (!escaped) { + r = log_oom(); + goto fail; + } + if (asprintf(&p, "unix:path=%s/systemd/private", escaped) < 0) { + dbus_free(escaped); + r = log_oom(); + goto fail; + } + dbus_free(escaped); + m->private_bus = dbus_server_listen(p, &error); free(p); } @@ -1124,19 +1135,19 @@ int bus_init(Manager *m, bool try_bus_connect) { if (set_ensure_allocated(&m->bus_connections, trivial_hash_func, trivial_compare_func) < 0 || set_ensure_allocated(&m->bus_connections_for_dispatch, trivial_hash_func, trivial_compare_func) < 0) - goto oom; + return log_oom(); if (m->name_data_slot < 0) if (!dbus_pending_call_allocate_data_slot(&m->name_data_slot)) - goto oom; + return log_oom(); if (m->conn_data_slot < 0) if (!dbus_pending_call_allocate_data_slot(&m->conn_data_slot)) - goto oom; + return log_oom(); if (m->subscribed_data_slot < 0) if (!dbus_connection_allocate_data_slot(&m->subscribed_data_slot)) - goto oom; + return log_oom(); if (try_bus_connect) { if ((r = bus_init_system(m)) < 0 || @@ -1144,16 +1155,14 @@ int bus_init(Manager *m, bool try_bus_connect) { return r; } - if ((r = bus_init_private(m)) < 0) + r = bus_init_private(m); + if (r < 0) return r; return 0; -oom: - return log_oom(); } static void shutdown_connection(Manager *m, DBusConnection *c) { - Set *s; Job *j; Iterator i; @@ -1169,15 +1178,7 @@ static void shutdown_connection(Manager *m, DBusConnection *c) { set_remove(m->bus_connections, c); set_remove(m->bus_connections_for_dispatch, c); - - if ((s = BUS_CONNECTION_SUBSCRIBED(m, c))) { - char *t; - - while ((t = set_steal_first(s))) - free(t); - - set_free(s); - } + set_free_free(BUS_CONNECTION_SUBSCRIBED(m, c)); if (m->queued_message_connection == c) { m->queued_message_connection = NULL; @@ -1190,7 +1191,7 @@ static void shutdown_connection(Manager *m, DBusConnection *c) { dbus_connection_set_dispatch_status_function(c, NULL, NULL, NULL); /* system manager cannot afford to block on DBus */ - if (m->running_as != MANAGER_SYSTEM) + if (m->running_as != SYSTEMD_SYSTEM) dbus_connection_flush(c); dbus_connection_close(c); dbus_connection_unref(c); @@ -1200,7 +1201,7 @@ static void bus_done_api(Manager *m) { if (!m->api_bus) return; - if (m->running_as == MANAGER_USER) + if (m->running_as == SYSTEMD_USER) shutdown_connection(m, m->api_bus); m->api_bus = NULL; @@ -1215,7 +1216,7 @@ static void bus_done_system(Manager *m) { if (!m->system_bus) return; - if (m->running_as == MANAGER_SYSTEM) + if (m->running_as == SYSTEMD_SYSTEM) bus_done_api(m); shutdown_connection(m, m->system_bus); @@ -1248,10 +1249,10 @@ void bus_done(Manager *m) { set_free(m->bus_connections_for_dispatch); if (m->name_data_slot >= 0) - dbus_pending_call_free_data_slot(&m->name_data_slot); + dbus_pending_call_free_data_slot(&m->name_data_slot); if (m->conn_data_slot >= 0) - dbus_pending_call_free_data_slot(&m->conn_data_slot); + dbus_pending_call_free_data_slot(&m->conn_data_slot); if (m->subscribed_data_slot >= 0) dbus_connection_free_data_slot(&m->subscribed_data_slot); @@ -1362,11 +1363,11 @@ int bus_broadcast(Manager *m, DBusMessage *message) { assert(message); SET_FOREACH(c, m->bus_connections_for_dispatch, i) - if (c != m->system_bus || m->running_as == MANAGER_SYSTEM) + if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM) oom = !dbus_connection_send(c, message, NULL); SET_FOREACH(c, m->bus_connections, i) - if (c != m->system_bus || m->running_as == MANAGER_SYSTEM) + if (c != m->system_bus || m->running_as == SYSTEMD_SYSTEM) oom = !dbus_connection_send(c, message, NULL); return oom ? -ENOMEM : 0; @@ -1477,3 +1478,69 @@ finish: if (message) dbus_message_unref(message); } + +Set *bus_acquire_subscribed(Manager *m, DBusConnection *c) { + Set *s; + + assert(m); + assert(c); + + s = BUS_CONNECTION_SUBSCRIBED(m, c); + if (s) + return s; + + s = set_new(string_hash_func, string_compare_func); + if (!s) + return NULL; + + if (!dbus_connection_set_data(c, m->subscribed_data_slot, s, NULL)) { + set_free(s); + return NULL; + } + + return s; +} + +void bus_serialize(Manager *m, FILE *f) { + char *client; + Iterator i; + Set *s; + + assert(m); + assert(f); + + if (!m->api_bus) + return; + + s = BUS_CONNECTION_SUBSCRIBED(m, m->api_bus); + SET_FOREACH(client, s, i) + fprintf(f, "subscribed=%s\n", client); +} + +int bus_deserialize_item(Manager *m, const char *line) { + const char *e; + char *b; + Set *s; + + assert(m); + assert(line); + + if (!m->api_bus) + return 0; + + e = startswith(line, "subscribed="); + if (!e) + return 0; + + s = bus_acquire_subscribed(m, m->api_bus); + if (!s) + return -ENOMEM; + + b = strdup(e); + if (!b) + return -ENOMEM; + + set_consume(s, b); + + return 1; +}