X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=dbus-manager.c;h=47fb403f11b1d2521c55ed59e9b83c3003c852e9;hp=bdc82df070aeaff9c8ea205134d2c0378e528107;hb=6c78be3c3c63b59f18311b2d2b0e8d745f6ba131;hpb=47be870bd83fb3719dffc3ee9348a409ab762a14 diff --git a/dbus-manager.c b/dbus-manager.c index bdc82df07..47fb403f1 100644 --- a/dbus-manager.c +++ b/dbus-manager.c @@ -23,11 +23,12 @@ #include "dbus.h" #include "log.h" +#include "dbus-manager.h" #define INTROSPECTION_BEGIN \ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ "" \ - " " \ + " " \ " " \ " " \ " " \ @@ -38,15 +39,49 @@ " " \ " " \ " " \ - " " \ + " " \ " " \ " " \ " " \ - " " \ + " " \ " " \ " " \ " " \ " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ " " \ BUS_PROPERTIES_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE @@ -54,9 +89,83 @@ #define INTROSPECTION_END \ "" +static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_running_as, manager_running_as, ManagerRunningAs); + +static int bus_manager_append_log_target(Manager *m, DBusMessageIter *i, const char *property, void *data) { + const char *t; + + assert(m); + assert(i); + assert(property); + + t = log_target_to_string(log_get_target()); + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t)) + return -ENOMEM; + + return 0; +} + +static int bus_manager_append_log_level(Manager *m, DBusMessageIter *i, const char *property, void *data) { + const char *t; + + assert(m); + assert(i); + assert(property); + + t = log_level_to_string(log_get_max_level()); + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t)) + return -ENOMEM; + + return 0; +} + +static int bus_manager_append_n_names(Manager *m, DBusMessageIter *i, const char *property, void *data) { + uint32_t u; + + assert(m); + assert(i); + assert(property); + + u = hashmap_size(m->units); + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u)) + return -ENOMEM; + + return 0; +} + +static int bus_manager_append_n_jobs(Manager *m, DBusMessageIter *i, const char *property, void *data) { + uint32_t u; + + assert(m); + assert(i); + assert(property); + + u = hashmap_size(m->jobs); + + if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT32, &u)) + return -ENOMEM; + + return 0; +} + static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) { - int r; Manager *m = data; + + const BusProperty properties[] = { + { "org.freedesktop.systemd1.Manager", "Version", bus_property_append_string, "s", PACKAGE_STRING }, + { "org.freedesktop.systemd1.Manager", "RunningAs", bus_manager_append_running_as, "s", &m->running_as }, + { "org.freedesktop.systemd1.Manager", "BootTimestamp", bus_property_append_uint64, "t", &m->boot_timestamp }, + { "org.freedesktop.systemd1.Manager", "LogLevel", bus_manager_append_log_level, "s", NULL }, + { "org.freedesktop.systemd1.Manager", "LogTarget", bus_manager_append_log_target, "s", NULL }, + { "org.freedesktop.systemd1.Manager", "NNames", bus_manager_append_n_names, "u", NULL }, + { "org.freedesktop.systemd1.Manager", "NJobs", bus_manager_append_n_jobs, "u", NULL }, + { NULL, NULL, NULL, NULL, NULL } + }; + + int r; DBusError error; DBusMessage *reply = NULL; char * path = NULL; @@ -72,7 +181,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection dbus_message_get_member(message), dbus_message_get_path(message)); - if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "GetUnit")) { + if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetUnit")) { const char *name; Unit *u; @@ -98,7 +207,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection DBUS_TYPE_INVALID)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "LoadUnit")) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "LoadUnit")) { const char *name; Unit *u; @@ -109,7 +218,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection DBUS_TYPE_INVALID)) return bus_send_error_reply(m, message, &error, -EINVAL); - if ((r = manager_load_unit(m, name, &u)) < 0) + if ((r = manager_load_unit(m, name, NULL, &u)) < 0) return bus_send_error_reply(m, message, NULL, r); if (!(reply = dbus_message_new_method_return(message))) @@ -124,7 +233,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection DBUS_TYPE_INVALID)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "GetJob")) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "GetJob")) { uint32_t id; Job *j; @@ -150,14 +259,14 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection DBUS_TYPE_INVALID)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "ClearJobs")) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ClearJobs")) { manager_clear_jobs(m); if (!(reply = dbus_message_new_method_return(message))) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "ListUnits")) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListUnits")) { DBusMessageIter iter, sub; Iterator i; Unit *u; @@ -168,17 +277,16 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection dbus_message_iter_init_append(reply, &iter); - if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssouso)", &sub)) + if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(sssssouso)", &sub)) goto oom; HASHMAP_FOREACH_KEY(u, k, m->units, i) { char *u_path, *j_path; - const char *id, *description, *load_state, *active_state, *job_type; + const char *description, *load_state, *active_state, *sub_state, *job_type; DBusMessageIter sub2; uint32_t job_id; - id = unit_id(u); - if (k != id) + if (k != u->meta.id) continue; if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2)) @@ -187,6 +295,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection description = unit_description(u); load_state = unit_load_state_to_string(u->meta.load_state); active_state = unit_active_state_to_string(unit_active_state(u)); + sub_state = unit_sub_state_to_string(u); if (!(u_path = unit_dbus_path(u))) goto oom; @@ -206,10 +315,11 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection job_type = ""; } - if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &id) || + if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &u->meta.id) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &description) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &load_state) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &active_state) || + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &sub_state) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &job_id) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &job_type) || @@ -231,7 +341,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection if (!dbus_message_iter_close_container(&iter, &sub)) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1", "ListJobs")) { + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "ListJobs")) { DBusMessageIter iter, sub; Iterator i; Job *j; @@ -246,7 +356,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection HASHMAP_FOREACH(j, m->jobs, i) { char *u_path, *j_path; - const char *unit, *state, *type; + const char *state, *type; uint32_t id; DBusMessageIter sub2; @@ -254,7 +364,6 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection goto oom; id = (uint32_t) j->id; - unit = unit_id(j->unit); state = job_state_to_string(j->state); type = job_type_to_string(j->type); @@ -267,7 +376,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection } if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &id) || - !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &unit) || + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &j->unit->meta.id) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &type) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &state) || !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) || @@ -287,6 +396,90 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection if (!dbus_message_iter_close_container(&iter, &sub)) goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Subscribe")) { + char *client; + + if (!(client = strdup(dbus_message_get_sender(message)))) + goto oom; + + r = set_put(m->subscribed, client); + + if (r < 0) + return bus_send_error_reply(m, message, NULL, r); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Unsubscribe")) { + char *client; + + if (!(client = set_remove(m->subscribed, (char*) dbus_message_get_sender(message)))) + return bus_send_error_reply(m, message, NULL, -ENOENT); + + free(client); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Dump")) { + FILE *f; + char *dump = NULL; + size_t size; + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + if (!(f = open_memstream(&dump, &size))) + goto oom; + + manager_dump_units(m, f, NULL); + manager_dump_jobs(m, f, NULL); + + if (ferror(f)) { + fclose(f); + free(dump); + goto oom; + } + + fclose(f); + + if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &dump, DBUS_TYPE_INVALID)) { + free(dump); + goto oom; + } + + free(dump); + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "CreateSnapshot")) { + const char *name; + dbus_bool_t cleanup; + Snapshot *s; + + if (!dbus_message_get_args( + message, + &error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_BOOLEAN, &cleanup, + DBUS_TYPE_INVALID)) + return bus_send_error_reply(m, message, &error, -EINVAL); + + if (name && name[0] == 0) + name = NULL; + + if ((r = snapshot_create(m, name, cleanup, &s)) < 0) + return bus_send_error_reply(m, message, NULL, r); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + if (!(path = unit_dbus_path(UNIT(s)))) + goto oom; + + if (!dbus_message_append_args( + reply, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_INVALID)) + goto oom; + } else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) { char *introspection = NULL; FILE *f; @@ -312,7 +505,7 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection HASHMAP_FOREACH_KEY(u, k, m->units, i) { char *p; - if (k != unit_id(u)) + if (k != u->meta.id) continue; if (!(p = bus_path_escape(k))) { @@ -348,8 +541,39 @@ static DBusHandlerResult bus_manager_message_handler(DBusConnection *connection free(introspection); + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reload")) { + + assert(!m->queued_message); + + /* Instead of sending the reply back right away, we + * just remember that we need to and then send it + * after the reload is finished. That way the caller + * knows when the reload finished. */ + + if (!(m->queued_message = dbus_message_new_method_return(message))) + goto oom; + + m->exit_code = MANAGER_RELOAD; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Reexecute")) { + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + m->exit_code = MANAGER_REEXECUTE; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "Exit")) { + + if (m->running_as == MANAGER_INIT) + return bus_send_error_reply(m, message, NULL, -ENOTSUP); + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + m->exit_code = MANAGER_EXIT; + } else - return bus_default_message_handler(m, message, NULL, NULL); + return bus_default_message_handler(m, message, NULL, properties); free(path);