chiark / gitweb /
30b9c00335bb740ed1f29a7102008473c110ab99
[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         BUS_UNIT_CGROUP_INTERFACE                                       \
34         "  <property name=\"TimeoutStopUSec\" type=\"t\" access=\"read\"/>\n" \
35         BUS_KILL_CONTEXT_INTERFACE                                      \
36         BUS_CGROUP_CONTEXT_INTERFACE                                    \
37         "  <property name=\"Result\" type=\"s\" access=\"read\"/>\n"    \
38         " </interface>\n"
39
40 #define INTROSPECTION                                                   \
41         DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE                       \
42         "<node>\n"                                                      \
43         BUS_UNIT_INTERFACE                                              \
44         BUS_SCOPE_INTERFACE                                             \
45         BUS_PROPERTIES_INTERFACE                                        \
46         BUS_PEER_INTERFACE                                              \
47         BUS_INTROSPECTABLE_INTERFACE                                    \
48         "</node>\n"
49
50 #define INTERFACES_LIST                              \
51         BUS_UNIT_INTERFACES_LIST                     \
52         "org.freedesktop.systemd1.Scope\0"
53
54 const char bus_scope_interface[] _introspect_("Scope") = BUS_SCOPE_INTERFACE;
55
56 static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_scope_append_scope_result, scope_result, ScopeResult);
57
58 static const BusProperty bus_scope_properties[] = {
59         { "TimeoutStopUSec",        bus_property_append_usec,      "t", offsetof(Scope, timeout_stop_usec) },
60         { "Result",                 bus_scope_append_scope_result, "s", offsetof(Scope, result)            },
61         {}
62 };
63
64 DBusHandlerResult bus_scope_message_handler(Unit *u, DBusConnection *c, DBusMessage *message) {
65         Scope *s = SCOPE(u);
66
67         const BusBoundProperties bps[] = {
68                 { "org.freedesktop.systemd1.Unit",  bus_unit_properties,           u },
69                 { "org.freedesktop.systemd1.Scope", bus_unit_cgroup_properties,    u },
70                 { "org.freedesktop.systemd1.Scope", bus_scope_properties,          s },
71                 { "org.freedesktop.systemd1.Scope", bus_cgroup_context_properties, &s->cgroup_context },
72                 { "org.freedesktop.systemd1.Scope", bus_kill_context_properties,   &s->kill_context   },
73                 {}
74         };
75
76         SELINUX_UNIT_ACCESS_CHECK(u, c, message, "status");
77
78         return bus_default_message_handler(c, message, INTROSPECTION, INTERFACES_LIST, bps);
79 }
80
81 static int bus_scope_set_transient_property(
82                 Scope *s,
83                 const char *name,
84                 DBusMessageIter *i,
85                 UnitSetPropertiesMode mode,
86                 DBusError *error) {
87
88         int r;
89
90         assert(name);
91         assert(s);
92         assert(i);
93
94         if (streq(name, "PIDs")) {
95                 DBusMessageIter sub;
96
97                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
98                     dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
99                         return -EINVAL;
100
101                 r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
102                 if (r < 0)
103                         return r;
104
105                 dbus_message_iter_recurse(i, &sub);
106                 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
107                         uint32_t pid;
108
109                         dbus_message_iter_get_basic(&sub, &pid);
110
111                         if (pid <= 1)
112                                 return -EINVAL;
113
114                         r = set_put(s->pids, LONG_TO_PTR(pid));
115                         if (r < 0 && r != -EEXIST)
116                                 return r;
117
118                         dbus_message_iter_next(&sub);
119                 }
120
121                 if (set_size(s->pids) <= 0)
122                         return -EINVAL;
123
124                 return 1;
125         }
126
127         return 0;
128 }
129
130 int bus_scope_set_property(
131                 Unit *u,
132                 const char *name,
133                 DBusMessageIter *i,
134                 UnitSetPropertiesMode mode,
135                 DBusError *error) {
136
137         Scope *s = SCOPE(u);
138         int r;
139
140         assert(name);
141         assert(u);
142         assert(i);
143
144         r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
145         if (r != 0)
146                 return r;
147
148         if (u->load_state == UNIT_STUB) {
149                 /* While we are created we still accept PIDs */
150
151                 r = bus_scope_set_transient_property(s, name, i, mode, error);
152                 if (r != 0)
153                         return r;
154         }
155
156         return 0;
157 }
158
159 int bus_scope_commit_properties(Unit *u) {
160         assert(u);
161
162         unit_realize_cgroup(u);
163         return 0;
164 }