X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fcore%2Fdbus-service.c;h=696c4462fe257010dcd394afd4bea39e7060bdb6;hp=bbac1b816742e7d5577d9c55fbb58d32e8f62b21;hb=a6fde35332f5e7f78bff437d7b7bfded83debbaa;hpb=4ad490007b70e6ac18d3cb04fa2ed92eba1451fa diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index bbac1b816..696c4462f 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -21,6 +21,8 @@ #include +#include "strv.h" +#include "path-util.h" #include "dbus-unit.h" #include "dbus-execute.h" #include "dbus-kill.h" @@ -36,13 +38,15 @@ " \n" \ " \n" \ " \n" \ - " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ " \n" \ + BUS_UNIT_CGROUP_INTERFACE \ BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \ BUS_EXEC_COMMAND_INTERFACE("ExecStart") \ BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \ @@ -51,6 +55,7 @@ BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \ BUS_EXEC_CONTEXT_INTERFACE \ BUS_KILL_CONTEXT_INTERFACE \ + BUS_CGROUP_CONTEXT_INTERFACE \ " \n" \ " \n" \ " \n" \ @@ -108,7 +113,7 @@ static const BusProperty bus_exec_main_status_properties[] = { { "ExecMainPID", bus_property_append_pid, "u", offsetof(ExecStatus, pid) }, { "ExecMainCode", bus_property_append_int, "i", offsetof(ExecStatus, code) }, { "ExecMainStatus", bus_property_append_int, "i", offsetof(ExecStatus, status) }, - { NULL, } + {} }; static const BusProperty bus_service_properties[] = { @@ -117,7 +122,6 @@ static const BusProperty bus_service_properties[] = { { "PIDFile", bus_property_append_string, "s", offsetof(Service, pid_file), true }, { "NotifyAccess", bus_service_append_notify_access, "s", offsetof(Service, notify_access) }, { "RestartUSec", bus_property_append_usec, "t", offsetof(Service, restart_usec) }, - { "TimeoutUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) }, { "TimeoutStartUSec", bus_property_append_usec, "t", offsetof(Service, timeout_start_usec) }, { "TimeoutStopUSec", bus_property_append_usec, "t", offsetof(Service, timeout_stop_usec) }, { "WatchdogUSec", bus_property_append_usec, "t", offsetof(Service, watchdog_usec) }, @@ -141,7 +145,7 @@ static const BusProperty bus_service_properties[] = { { "BusName", bus_property_append_string, "s", offsetof(Service, bus_name), true }, { "StatusText", bus_property_append_string, "s", offsetof(Service, status_text), true }, { "Result", bus_service_append_service_result,"s", offsetof(Service, result) }, - { NULL, } + {} }; DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) { @@ -149,15 +153,184 @@ DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connectio const BusBoundProperties bps[] = { { "org.freedesktop.systemd1.Unit", bus_unit_properties, u }, + { "org.freedesktop.systemd1.Service", bus_unit_cgroup_properties, u }, { "org.freedesktop.systemd1.Service", bus_service_properties, s }, { "org.freedesktop.systemd1.Service", bus_exec_context_properties, &s->exec_context }, { "org.freedesktop.systemd1.Service", bus_kill_context_properties, &s->kill_context }, { "org.freedesktop.systemd1.Service", bus_cgroup_context_properties, &s->cgroup_context }, { "org.freedesktop.systemd1.Service", bus_exec_main_status_properties, &s->main_exec_status }, - { NULL, } + {} }; SELINUX_UNIT_ACCESS_CHECK(u, connection, message, "status"); return bus_default_message_handler(connection, message, INTROSPECTION, INTERFACES_LIST, bps); } + +static int bus_service_set_transient_property( + Service *s, + const char *name, + DBusMessageIter *i, + UnitSetPropertiesMode mode, + DBusError *error) { + + int r; + + assert(name); + assert(s); + assert(i); + + if (streq(name, "RemainAfterExit")) { + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) + return -EINVAL; + + if (mode != UNIT_CHECK) { + dbus_bool_t b; + + dbus_message_iter_get_basic(i, &b); + + s->remain_after_exit = b; + unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b)); + } + + return 1; + + } else if (streq(name, "ExecStart")) { + DBusMessageIter sub; + unsigned n = 0; + + if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY || + dbus_message_iter_get_element_type(i) != DBUS_TYPE_STRUCT) + return -EINVAL; + + dbus_message_iter_recurse(i, &sub); + while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) { + _cleanup_strv_free_ char **argv = NULL; + DBusMessageIter sub2; + dbus_bool_t ignore; + const char *path; + + dbus_message_iter_recurse(&sub, &sub2); + + if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0) + return -EINVAL; + + if (!path_is_absolute(path)) { + dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); + return -EINVAL; + } + + r = bus_parse_strv_iter(&sub2, &argv); + if (r < 0) + return r; + + dbus_message_iter_next(&sub2); + + if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0) + return -EINVAL; + + if (mode != UNIT_CHECK) { + ExecCommand *c; + + c = new0(ExecCommand, 1); + if (!c) + return -ENOMEM; + + c->path = strdup(path); + if (!c->path) { + free(c); + return -ENOMEM; + } + + c->argv = argv; + argv = NULL; + + c->ignore = ignore; + + path_kill_slashes(c->path); + exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c); + } + + n++; + dbus_message_iter_next(&sub); + } + + if (mode != UNIT_CHECK) { + _cleanup_free_ char *buf = NULL; + _cleanup_fclose_ FILE *f = NULL; + ExecCommand *c; + size_t size = 0; + + if (n == 0) { + exec_command_free_list(s->exec_command[SERVICE_EXEC_START]); + s->exec_command[SERVICE_EXEC_START] = NULL; + } + + f = open_memstream(&buf, &size); + if (!f) + return -ENOMEM; + + fputs("ExecStart=\n", f); + + LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) { + _cleanup_free_ char *a; + + a = strv_join_quoted(c->argv); + if (!a) + return -ENOMEM; + + fprintf(f, "ExecStart=%s@%s %s\n", + c->ignore ? "-" : "", + c->path, + a); + } + + fflush(f); + unit_write_drop_in_private(UNIT(s), mode, name, buf); + } + + return 1; + } + + return 0; +} + +int bus_service_set_property( + Unit *u, + const char *name, + DBusMessageIter *i, + UnitSetPropertiesMode mode, + DBusError *error) { + + Service *s = SERVICE(u); + int r; + + assert(name); + assert(u); + assert(i); + + r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error); + if (r != 0) + return r; + + if (u->transient && u->load_state == UNIT_STUB) { + /* This is a transient unit, let's load a little more */ + + r = bus_service_set_transient_property(s, name, i, mode, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, i, mode, error); + if (r != 0) + return r; + } + + return 0; +} + +int bus_service_commit_properties(Unit *u) { + assert(u); + + unit_realize_cgroup(u); + return 0; +}