X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fdbus.c;h=65e4daa01cb55ddd570b843c7dc92d45968b1691;hb=b410e6b951695847619d18952bb9e2622c8b2bbf;hp=6dd495d4df6be3ea542f87bae2f2006bafa57f32;hpb=871d7de47c13ee6cd78b8eefdf9128be3c740ac0;p=elogind.git diff --git a/src/dbus.c b/src/dbus.c index 6dd495d4d..65e4daa01 100644 --- a/src/dbus.c +++ b/src/dbus.c @@ -41,6 +41,7 @@ #include "dbus-snapshot.h" #include "dbus-swap.h" #include "dbus-timer.h" +#include "dbus-path.h" static const char bus_properties_interface[] = BUS_PROPERTIES_INTERFACE; static const char bus_introspectable_interface[] = BUS_INTROSPECTABLE_INTERFACE; @@ -60,9 +61,12 @@ const char *const bus_interface_table[] = { "org.freedesktop.systemd1.Snapshot", bus_snapshot_interface, "org.freedesktop.systemd1.Swap", bus_swap_interface, "org.freedesktop.systemd1.Timer", bus_timer_interface, + "org.freedesktop.systemd1.Path", bus_path_interface, NULL }; +static const char *error_to_dbus(int error); + static void api_bus_dispatch_status(DBusConnection *bus, DBusDispatchStatus status, void *data) { Manager *m = data; @@ -331,6 +335,7 @@ static void bus_toggle_timeout(DBusTimeout *timeout, void *data) { static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) { Manager *m = data; DBusError error; + DBusMessage *reply = NULL; assert(connection); assert(message); @@ -368,10 +373,65 @@ static DBusHandlerResult api_bus_message_filter(DBusConnection *connection, DBu manager_dispatch_bus_name_owner_changed(m, name, old_owner, new_owner); } + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Activator", "ActivationRequest")) { + const char *name; + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) + log_error("Failed to parse ActivationRequest message: %s", error.message); + else { + int r; + Unit *u; + + r = manager_load_unit(m, name, NULL, &u); + + if (r >= 0 && u->meta.only_by_dependency) + r = -EPERM; + + if (r >= 0) + r = manager_add_job(m, JOB_START, u, JOB_REPLACE, true, NULL); + + if (r < 0) { + const char *id, *text; + + if (!(reply = dbus_message_new_signal("/org/freedesktop/systemd1", "org.freedesktop.systemd1.Activator", "ActivationFailure"))) + goto oom; + + id = error_to_dbus(r); + text = strerror(-r); + + if (!dbus_message_set_destination(reply, DBUS_SERVICE_DBUS) || + !dbus_message_append_args(reply, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_STRING, &id, + DBUS_TYPE_STRING, &text, + DBUS_TYPE_INVALID)) + goto oom; + } + + /* On success we don't do anything, the service will be spwaned now */ + } } dbus_error_free(&error); + + if (reply) { + if (!dbus_connection_send(connection, reply, NULL)) + goto oom; + + dbus_message_unref(reply); + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + +oom: + if (reply) + dbus_message_unref(reply); + + dbus_error_free(&error); + + return DBUS_HANDLER_RESULT_NEED_MEMORY; } static DBusHandlerResult system_bus_message_filter(DBusConnection *connection, DBusMessage *message, void *data) { @@ -640,6 +700,7 @@ int bus_init_api(Manager *m) { return -ENOMEM; } + /* Get NameOwnerChange messages */ dbus_bus_add_match(m->api_bus, "type='signal'," "sender='"DBUS_SERVICE_DBUS"'," @@ -654,6 +715,21 @@ int bus_init_api(Manager *m) { return -ENOMEM; } + /* Get activation requests */ + dbus_bus_add_match(m->api_bus, + "type='signal'," + "sender='"DBUS_SERVICE_DBUS"'," + "interface='org.freedesktop.systemd1.Activator'," + "path='"DBUS_PATH_DBUS"'", + &error); + + if (dbus_error_is_set(&error)) { + log_error("Failed to register match: %s", error.message); + dbus_error_free(&error); + bus_done_api(m); + return -ENOMEM; + } + if ((r = request_name(m)) < 0) { bus_done_api(m); return r;