chiark / gitweb /
core: add new "scope" unit type for making a unit of pre-existing processes
[elogind.git] / src / core / dbus-scope.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <errno.h>
23
24 #include "dbus-unit.h"
25 #include "dbus-common.h"
26 #include "dbus-cgroup.h"
27 #include "dbus-kill.h"
28 #include "selinux-access.h"
29 #include "dbus-scope.h"
30
31 #define BUS_SCOPE_INTERFACE                                             \
32         " <interface name=\"org.freedesktop.systemd1.Scope\">\n"        \
33         "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
34         BUS_KILL_CONTEXT_INTERFACE                                      \
35         BUS_CGROUP_CONTEXT_INTERFACE                                    \
36         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
37         " </interface>\n"
38
39 #define INTROSPECTION                                                   \
40         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
41         "<node>\n"                                                      \
42         BUS_UNIT_INTERFACE                                              \
43         BUS_SCOPE_INTERFACE                                             \
44         BUS_PROPERTIES_INTERFACE                                        \
45         BUS_PEER_INTERFACE                                              \
46         BUS_INTROSPECTABLE_INTERFACE                                    \
47         "</node>\n"
48
49 #define INTERFACES_LIST                              \
50         BUS_UNIT_INTERFACES_LIST                     \
51         "org.freedesktop.systemd1.Scope\0"
52
53 const char bus_scope_interface[] _introspect_("Scope") = BUS_SCOPE_INTERFACE;
54
55 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_scope_append_scope_result, scope_result, ScopeResult);
56
57 static const BusProperty bus_scope_properties[] = {
58         { "TimeoutStopUSec",        bus_property_append_usec,      "t", offsetof(Scope, timeout_stop_usec) },
59         { "Result",                 bus_scope_append_scope_result, "s", offsetof(Scope, result)            },
60         {}
61 };
62
63 DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
64         Scope *s = SCOPE(u);
65
66         const BusBoundProperties bps[] = {
67                 { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
68                 { "org.freedesktop.systemd1.Scope", bus_scope_properties,          s },
69                 { "org.freedesktop.systemd1.Scope", bus_cgroup_context_properties, &s->cgroup_context },
70                 { "org.freedesktop.systemd1.Scope", bus_kill_context_properties,   &s->kill_context   },
71                 {}
72         };
73
74         SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
75
76         return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
77 }
78
79 static int bus_scope_set_transient_properties(
80                 Scope *s,
81                 const char *name,
82                 DBusMessageIter *i,
83                 UnitSetPropertiesMode mode,
84                 DBusError *error) {
85
86         int r;
87
88         assert(name);
89         assert(s);
90         assert(i);
91
92         if (streq(name, "PIDs")) {
93                 DBusMessageIter sub;
94
95                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
96                     dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
97                         return -EINVAL;
98
99                 r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
100                 if (r < 0)
101                         return r;
102
103                 dbus_message_iter_recurse(i, &sub);
104                 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
105                         uint32_t pid;
106
107                         dbus_message_iter_get_basic(&sub, &pid);
108
109                         if (pid <= 1)
110                                 return -EINVAL;
111
112                         r = set_put(s->pids, LONG_TO_PTR(pid));
113                         if (r < 0 && r != -EEXIST)
114                                 return r;
115
116                         dbus_message_iter_next(&sub);
117                 }
118
119                 if (set_size(s->pids) <= 0)
120                         return -EINVAL;
121
122                 return 1;
123         }
124
125         return 0;
126 }
127
128 int bus_scope_set_property(
129                 Unit *u,
130                 const char *name,
131                 DBusMessageIter *i,
132                 UnitSetPropertiesMode mode,
133                 DBusError *error) {
134
135         Scope *s = SCOPE(u);
136         int r;
137
138         assert(name);
139         assert(u);
140         assert(i);
141
142         r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
143         if (r != 0)
144                 return r;
145
146         if (u->load_state == UNIT_STUB) {
147                 /* While we are created we still accept PIDs */
148
149                 r = bus_scope_set_transient_properties(s, name, i, mode, error);
150                 if (r != 0)
151                         return r;
152         }
153
154         return 0;
155 }
156
157 int bus_scope_commit_properties(Unit *u) {
158         assert(u);
159
160         unit_realize_cgroup(u);
161         return 0;
162 }