X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=dbus-manager.c;h=90ab8d1a0cab509b1d78270191962a65bf0a8842;hp=03a39300df53a6ff9d2268e880f39231c4302376;hb=67ef7823c651015929d4f20e4c9d59998c5bac7d;hpb=a7334b0952ab66c17ee787e36e6d2c5ceb387de6 diff --git a/dbus-manager.c b/dbus-manager.c index 03a39300d..90ab8d1a0 100644 --- a/dbus-manager.c +++ b/dbus-manager.c @@ -23,11 +23,13 @@ #include "dbus.h" #include "log.h" +#include "dbus-manager.h" +#include "strv.h" #define INTROSPECTION_BEGIN \ DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ "" \ - " " \ + " " \ " " \ " " \ " " \ @@ -38,15 +40,56 @@ " " \ " " \ " " \ - " " \ + " " \ " " \ " " \ " " \ - " " \ + " " \ " " \ " " \ " " \ " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ + " " \ " " \ BUS_PROPERTIES_INTERFACE \ BUS_INTROSPECTABLE_INTERFACE @@ -54,9 +97,84 @@ #define INTROSPECTION_END \ "" -DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusMessage *message, void *data) { - int r; +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) { 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 }, + { "org.freedesktop.systemd1.Manager", "Environment", bus_property_append_strv, "as", m->environment }, + { NULL, NULL, NULL, NULL, NULL } + }; + + int r; DBusError error; DBusMessage *reply = NULL; char * path = NULL; @@ -72,7 +190,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +216,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +227,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +242,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +268,14 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +286,16 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 *unit_path, *job_path; - const char *id, *description, *load_state, *active_state, *job_type; + char *u_path, *j_path; + 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,42 +304,44 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 (!(unit_path = unit_dbus_path(u))) + if (!(u_path = unit_dbus_path(u))) goto oom; if (u->meta.job) { job_id = (uint32_t) u->meta.job->id; - if (!(job_path = job_dbus_path(u->meta.job))) { - free(unit_path); + if (!(j_path = job_dbus_path(u->meta.job))) { + free(u_path); goto oom; } job_type = job_type_to_string(u->meta.job->type); } else { job_id = 0; - job_path = unit_path; + j_path = u_path; 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_OBJECT_PATH, &unit_path) || + !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) || - !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &job_path)) { - free(unit_path); + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path)) { + free(u_path); if (u->meta.job) - free(job_path); + free(j_path); goto oom; } - free(unit_path); + free(u_path); if (u->meta.job) - free(job_path); + free(j_path); if (!dbus_message_iter_close_container(&sub, &sub2)) goto oom; @@ -231,7 +350,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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; @@ -245,8 +364,8 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM goto oom; HASHMAP_FOREACH(j, m->jobs, i) { - char *unit_path, *job_path; - const char *unit, *state, *type; + char *u_path, *j_path; + const char *state, *type; uint32_t id; DBusMessageIter sub2; @@ -254,31 +373,30 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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); - if (!(job_path = job_dbus_path(j))) + if (!(j_path = job_dbus_path(j))) goto oom; - if (!(unit_path = unit_dbus_path(j->unit))) { - free(job_path); + if (!(u_path = unit_dbus_path(j->unit))) { + free(j_path); goto oom; } 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, &job_path) || - !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &unit_path)) { - free(job_path); - free(unit_path); + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &j_path) || + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &u_path)) { + free(j_path); + free(u_path); goto oom; } - free(job_path); - free(unit_path); + free(j_path); + free(u_path); if (!dbus_message_iter_close_container(&sub, &sub2)) goto oom; @@ -287,6 +405,90 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +514,7 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 +550,85 @@ DBusHandlerResult bus_manager_message_handler(DBusConnection *connection, DBusM 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 if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "SetEnvironment")) { + char **l = NULL, **e = NULL; + + if ((r = bus_parse_strv(message, &l)) < 0) { + if (r == -ENOMEM) + goto oom; + + return bus_send_error_reply(m, message, NULL, r); + } + + e = strv_env_merge(m->environment, l, NULL); + strv_free(l); + + if (!e) + goto oom; + + if (!(reply = dbus_message_new_method_return(message))) { + strv_free(e); + goto oom; + } + + strv_free(m->environment); + m->environment = e; + + } else if (dbus_message_is_method_call(message, "org.freedesktop.systemd1.Manager", "UnsetEnvironment")) { + char **l = NULL, **e = NULL; + + if ((r = bus_parse_strv(message, &l)) < 0) { + if (r == -ENOMEM) + goto oom; + + return bus_send_error_reply(m, message, NULL, r); + } + + e = strv_env_delete(m->environment, l, NULL); + strv_free(l); + + if (!e) + goto oom; + + if (!(reply = dbus_message_new_method_return(message))) + goto oom; + + strv_free(m->environment); + m->environment = e; + } else - return bus_default_message_handler(m, message, NULL, NULL); + return bus_default_message_handler(m, message, NULL, properties); free(path);