diff options
author | Lennart Poettering <lennart@poettering.net> | 2013-11-19 21:12:59 +0100 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2013-11-20 20:52:36 +0100 |
commit | 718db96199eb307751264e4163555662c9a389fa (patch) | |
tree | 9ec8467596ba1acba76bb6273c7797baf68c1a00 /src/core/dbus-service.c | |
parent | 3febea3a0b0a968ea281e7959c1654cbaf95c9bf (diff) |
core: convert PID 1 to libsystemd-bus
This patch converts PID 1 to libsystemd-bus and thus drops the
dependency on libdbus. The only remaining code using libdbus is a test
case that validates our bus marshalling against libdbus' marshalling,
and this dependency can be turned off.
This patch also adds a couple of things to libsystem-bus, that are
necessary to make the port work:
- Synthesizing of "Disconnected" messages when bus connections are
severed.
- Support for attaching multiple vtables for the same interface on the
same path.
This patch also fixes the SetDefaultTarget() and GetDefaultTarget() bus
calls which used an inappropriate signature.
As a side effect we will now generate PropertiesChanged messages which
carry property contents, rather than just invalidation information.
Diffstat (limited to 'src/core/dbus-service.c')
-rw-r--r-- | src/core/dbus-service.c | 266 |
1 files changed, 90 insertions, 176 deletions
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c index c888570c4b..c4bfa2c38f 100644 --- a/src/core/dbus-service.c +++ b/src/core/dbus-service.c @@ -19,176 +19,92 @@ along with systemd; If not, see <http://www.gnu.org/licenses/>. ***/ -#include <errno.h> - #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 \ - " <interface name=\"org.freedesktop.systemd1.Service\">\n" \ - " <property name=\"Type\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"Restart\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"PIDFile\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"NotifyAccess\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"RestartUSec\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"TimeoutStartUSec\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"WatchdogUSec\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"WatchdogTimestamp\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"WatchdogTimestampMonotonic\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"StartLimitInterval\" type=\"t\" access=\"read\"/>\n" \ - " <property name=\"StartLimitBurst\" type=\"u\" access=\"read\"/>\n" \ - " <property name=\"StartLimitAction\" type=\"s\" access=\"readwrite\"/>\n" \ - BUS_UNIT_CGROUP_INTERFACE \ - 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 \ - BUS_CGROUP_CONTEXT_INTERFACE \ - " <property name=\"PermissionsStartOnly\" type=\"b\" access=\"read\"/>\n" \ - " <property name=\"RootDirectoryStartOnly\" type=\"b\" access=\"read\"/>\n" \ - " <property name=\"RemainAfterExit\" type=\"b\" access=\"read\"/>\n" \ - BUS_EXEC_STATUS_INTERFACE("ExecMain") \ - " <property name=\"MainPID\" type=\"u\" access=\"read\"/>\n" \ - " <property name=\"ControlPID\" type=\"u\" access=\"read\"/>\n" \ - " <property name=\"BusName\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"StatusText\" type=\"s\" access=\"read\"/>\n" \ - " <property name=\"Result\" type=\"s\" access=\"read\"/>\n" \ - " </interface>\n" - -#define INTROSPECTION \ - DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \ - "<node>\n" \ - BUS_UNIT_INTERFACE \ - BUS_SERVICE_INTERFACE \ - BUS_PROPERTIES_INTERFACE \ - BUS_PEER_INTERFACE \ - BUS_INTROSPECTABLE_INTERFACE \ - "</node>\n" - -#define INTERFACES_LIST \ - BUS_UNIT_INTERFACES_LIST \ - "org.freedesktop.systemd1.Service\0" - -const char bus_service_interface[] = 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_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0), + BUS_EXEC_COMMAND_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0), + BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0), + BUS_EXEC_COMMAND_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0), + BUS_EXEC_COMMAND_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0), + BUS_EXEC_COMMAND_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_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 }, - {} - }; - - 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, + 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, "RemainAfterExit")) { - if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_BOOLEAN) - return -EINVAL; + int b; - if (mode != UNIT_CHECK) { - dbus_bool_t b; - - dbus_message_iter_get_basic(i, &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)); } @@ -196,38 +112,35 @@ static int bus_service_set_transient_property( 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; + 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; @@ -245,15 +158,16 @@ static int bus_service_set_transient_property( 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; if (mode != UNIT_CHECK) { _cleanup_free_ char *buf = NULL; @@ -298,29 +212,29 @@ static int bus_service_set_transient_property( 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_property(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, i, mode, error); + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error); if (r != 0) return r; } |