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=32971736534a6e262f0375c6792e904fdb5accfb;hp=e93ac55115baa428ff5eb96818e6fb7c411622ff;hb=fa28bc2df724e4aff46d19cb7aa732cc64c71061;hpb=64fad95a324fde85aeb2dd6f3291a55374ee0113 diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index e93ac5511..329717365 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -19,197 +19,128 @@ along with systemd; If not, see . ***/ -#include - #include "strv.h" #include "path-util.h" +#include "unit.h" +#include "service.h" #include "dbus-unit.h" #include "dbus-execute.h" #include "dbus-kill.h" #include "dbus-cgroup.h" -#include "dbus-common.h" -#include "selinux-access.h" #include "dbus-service.h" - -#define BUS_SERVICE_INTERFACE \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - BUS_EXEC_COMMAND_INTERFACE("ExecStartPre") \ - BUS_EXEC_COMMAND_INTERFACE("ExecStart") \ - BUS_EXEC_COMMAND_INTERFACE("ExecStartPost") \ - BUS_EXEC_COMMAND_INTERFACE("ExecReload") \ - BUS_EXEC_COMMAND_INTERFACE("ExecStop") \ - BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \ - BUS_EXEC_CONTEXT_INTERFACE \ - BUS_KILL_CONTEXT_INTERFACE \ - " \n" \ - " \n" \ - " \n" \ - BUS_EXEC_STATUS_INTERFACE("ExecMain") \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" \ - " \n" - -#define INTROSPECTION \ - DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ - "\n" \ - BUS_UNIT_INTERFACE \ - BUS_SERVICE_INTERFACE \ - BUS_PROPERTIES_INTERFACE \ - BUS_PEER_INTERFACE \ - BUS_INTROSPECTABLE_INTERFACE \ - "\n" - -#define INTERFACES_LIST \ - BUS_UNIT_INTERFACES_LIST \ - "org.freedesktop.systemd1.Service\0" - -const char bus_service_interface[] _introspect_("Service") = BUS_SERVICE_INTERFACE; - -const char bus_service_invalidating_properties[] = - "ExecStartPre\0" - "ExecStart\0" - "ExecStartPost\0" - "ExecReload\0" - "ExecStop\0" - "ExecStopPost\0" - "ExecMain\0" - "WatchdogTimestamp\0" - "WatchdogTimestampMonotonic\0" - "MainPID\0" - "ControlPID\0" - "StatusText\0" - "Result\0"; - -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_type, service_type, ServiceType); -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_restart, service_restart, ServiceRestart); -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_notify_access, notify_access, NotifyAccess); -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_service_result, service_result, ServiceResult); -static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_service_append_start_limit_action, start_limit_action, StartLimitAction); -static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_limit_action, StartLimitAction); - -static const BusProperty bus_exec_main_status_properties[] = { - { "ExecMainStartTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.realtime) }, - { "ExecMainStartTimestampMonotonic",bus_property_append_usec, "t", offsetof(ExecStatus, start_timestamp.monotonic) }, - { "ExecMainExitTimestamp", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.realtime) }, - { "ExecMainExitTimestampMonotonic", bus_property_append_usec, "t", offsetof(ExecStatus, exit_timestamp.monotonic) }, - { "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) }, - {} +#include "bus-util.h" + +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess); +static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction); + +const sd_bus_vtable bus_service_vtable[] = { + SD_BUS_VTABLE_START(0), + SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), 0), + SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), 0), + SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), 0), + SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), 0), + SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), 0), + SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), 0), + SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), 0), + SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), 0), + BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0), + SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), 0), + SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), 0), + SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), 0), + SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), 0), + SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), 0), + SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), 0), + SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), 0), + SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), 0), + SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0), + BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), 0), + SD_BUS_VTABLE_END }; -static const BusProperty bus_service_properties[] = { - { "Type", bus_service_append_type, "s", offsetof(Service, type) }, - { "Restart", bus_service_append_restart, "s", offsetof(Service, restart) }, - { "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) }, - { "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) }, - { "WatchdogTimestamp", bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.realtime) }, - { "WatchdogTimestampMonotonic",bus_property_append_usec, "t", offsetof(Service, watchdog_timestamp.monotonic) }, - { "StartLimitInterval", bus_property_append_usec, "t", offsetof(Service, start_limit.interval) }, - { "StartLimitBurst", bus_property_append_uint32, "u", offsetof(Service, start_limit.burst) }, - { "StartLimitAction", bus_service_append_start_limit_action,"s", offsetof(Service, start_limit_action), false, bus_service_set_start_limit_action}, - BUS_EXEC_COMMAND_PROPERTY("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), true ), - BUS_EXEC_COMMAND_PROPERTY("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), true ), - BUS_EXEC_COMMAND_PROPERTY("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), true ), - BUS_EXEC_COMMAND_PROPERTY("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), true ), - BUS_EXEC_COMMAND_PROPERTY("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), true ), - BUS_EXEC_COMMAND_PROPERTY("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), true ), - { "PermissionsStartOnly", bus_property_append_bool, "b", offsetof(Service, permissions_start_only) }, - { "RootDirectoryStartOnly", bus_property_append_bool, "b", offsetof(Service, root_directory_start_only) }, - { "RemainAfterExit", bus_property_append_bool, "b", offsetof(Service, remain_after_exit) }, - { "GuessMainPID", bus_property_append_bool, "b", offsetof(Service, guess_main_pid) }, - { "MainPID", bus_property_append_pid, "u", offsetof(Service, main_pid) }, - { "ControlPID", bus_property_append_pid, "u", offsetof(Service, control_pid) }, - { "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) }, - {} +const char* const bus_service_changing_properties[] = { + "ExecMainStartTimestamp", + "ExecMainStartTimestampMonotonic", + "ExecMainExitTimestamp", + "ExecMainExitTimestampMonotonic", + "ExecMainPID", + "ExecMainCode", + "ExecMainStatus", + "MainPID", + "ControlPID", + "StatusText", + "Result", + NULL }; -DBusHandlerResult bus_service_message_handler(Unit *u, DBusConnection *connection, DBusMessage *message) { - Service *s = SERVICE(u); - - const BusBoundProperties bps[] = { - { "org.freedesktop.systemd1.Unit", bus_unit_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 }, - {} - }; - - 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_properties( +static int bus_service_set_transient_property( Service *s, const char *name, - DBusMessageIter *i, + sd_bus_message *message, UnitSetPropertiesMode mode, - DBusError *error) { + sd_bus_error *error) { int r; - assert(name); assert(s); - assert(i); + assert(name); + assert(message); - if (streq(name, "ExecStart")) { - DBusMessageIter sub; + if (streq(name, "RemainAfterExit")) { + int b; + + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; + + if (mode != UNIT_CHECK) { + 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")) { 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; + r = sd_bus_message_enter_container(message, 'a', "(sasb)"); + if (r < 0) + return r; - dbus_message_iter_recurse(i, &sub); - while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) { + while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) { _cleanup_strv_free_ char **argv = NULL; - DBusMessageIter sub2; - dbus_bool_t ignore; const char *path; + int b; - dbus_message_iter_recurse(&sub, &sub2); - - if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0) - return -EINVAL; + r = sd_bus_message_read(message, "s", &path); + if (r < 0) + return r; - if (!path_is_absolute(path)) { - dbus_set_error(error, DBUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path); - return -EINVAL; - } + if (!path_is_absolute(path)) + return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path); - r = bus_parse_strv_iter(&sub2, &argv); + r = sd_bus_message_read_strv(message, &argv); if (r < 0) return r; - dbus_message_iter_next(&sub2); + r = sd_bus_message_read(message, "b", &b); + if (r < 0) + return r; - if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &ignore, false) < 0) - return -EINVAL; + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; if (mode != UNIT_CHECK) { ExecCommand *c; @@ -227,15 +158,20 @@ static int bus_service_set_transient_properties( c->argv = argv; argv = NULL; - c->ignore = ignore; + c->ignore = b; path_kill_slashes(c->path); exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c); } n++; - dbus_message_iter_next(&sub); } + if (r < 0) + return r; + + r = sd_bus_message_exit_container(message); + if (r < 0) + return r; if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; @@ -255,25 +191,20 @@ static int bus_service_set_transient_properties( fputs("ExecStart=\n", f); LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) { - char **a; - fputs("ExecStart=", f); + _cleanup_free_ char *a; - if (c->ignore) - fputc('-', f); - - fputc('@', f); - fputs(c->path, f); - - STRV_FOREACH(a, c->argv) { - fputc(' ', f); - fputs(*a, f); - } + a = strv_join_quoted(c->argv); + if (!a) + return -ENOMEM; - fputc('\n', f); + fprintf(f, "ExecStart=%s@%s %s\n", + c->ignore ? "-" : "", + c->path, + a); } fflush(f); - unit_write_drop_in_private_section(UNIT(s), mode, "exec-start", buf); + unit_write_drop_in_private(UNIT(s), mode, name, buf); } return 1; @@ -285,25 +216,29 @@ static int bus_service_set_transient_properties( int bus_service_set_property( Unit *u, const char *name, - DBusMessageIter *i, + sd_bus_message *message, UnitSetPropertiesMode mode, - DBusError *error) { + sd_bus_error *error) { Service *s = SERVICE(u); int r; + assert(s); assert(name); - assert(u); - assert(i); + assert(message); - r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error); + r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, 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_properties(s, name, i, mode, error); + r = bus_service_set_transient_property(s, name, message, mode, error); + if (r != 0) + return r; + + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error); if (r != 0) return r; }