X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fdbus-service.c;h=696c4462fe257010dcd394afd4bea39e7060bdb6;hb=a0a6408e31fef4618e27fafba416b9858f66a8e3;hp=d84041541735dad4b6a6564fc2a58e2e5642a23c;hpb=b30e2f4c18ad81b04e4314fd191a5d458553773c;p=elogind.git
diff --git a/src/core/dbus-service.c b/src/core/dbus-service.c
index d84041541..696c4462f 100644
--- a/src/core/dbus-service.c
+++ b/src/core/dbus-service.c
@@ -6,34 +6,30 @@
Copyright 2010 Lennart Poettering
systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ under the terms of the GNU Lesser General Public License as published by
+ the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
+ Lesser General Public License for more details.
- You should have received a copy of the GNU General Public License
+ You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see .
***/
#include
+#include "strv.h"
+#include "path-util.h"
#include "dbus-unit.h"
#include "dbus-execute.h"
-#include "dbus-service.h"
+#include "dbus-kill.h"
+#include "dbus-cgroup.h"
#include "dbus-common.h"
-
-#ifdef HAVE_SYSV_COMPAT
-#define BUS_SERVICE_SYSV_INTERFACE_FRAGMENT \
- " \n" \
- " \n" \
- " \n"
-#else
-#define BUS_SERVICE_SYSV_INTERFACE_FRAGMENT ""
-#endif
+#include "selinux-access.h"
+#include "dbus-service.h"
#define BUS_SERVICE_INTERFACE \
" \n" \
@@ -42,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") \
@@ -56,6 +54,8 @@
BUS_EXEC_COMMAND_INTERFACE("ExecStop") \
BUS_EXEC_COMMAND_INTERFACE("ExecStopPost") \
BUS_EXEC_CONTEXT_INTERFACE \
+ BUS_KILL_CONTEXT_INTERFACE \
+ BUS_CGROUP_CONTEXT_INTERFACE \
" \n" \
" \n" \
" \n" \
@@ -64,9 +64,7 @@
" \n" \
" \n" \
" \n" \
- " \n" \
" \n" \
- BUS_SERVICE_SYSV_INTERFACE_FRAGMENT \
" \n"
#define INTROSPECTION \
@@ -110,12 +108,12 @@ static DEFINE_BUS_PROPERTY_SET_ENUM(bus_service_set_start_limit_action, start_li
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, start_timestamp.realtime) },
- { "ExecMainExitTimestampMonotonic", 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) },
- { NULL, }
+ {}
};
static const BusProperty bus_service_properties[] = {
@@ -124,7 +122,8 @@ 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_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) },
@@ -145,25 +144,193 @@ static const BusProperty bus_service_properties[] = {
{ "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 },
-#ifdef HAVE_SYSV_COMPAT
- { "SysVRunLevels", bus_property_append_string, "s", offsetof(Service, sysv_runlevels), true },
- { "SysVStartPriority", bus_property_append_int, "i", offsetof(Service, sysv_start_priority) },
- { "SysVPath", bus_property_append_string, "s", offsetof(Service, sysv_path), true },
-#endif
- { "FsckPassNo", bus_property_append_int, "i", offsetof(Service, fsck_passno) },
{ "Result", bus_service_append_service_result,"s", offsetof(Service, 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 },
- { 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;
+}