chiark / gitweb /
bddf8f4753ca57332f572922a21a6d7d6462075c
[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                 unsigned n;
97
98                 if (dbus_message_iter_get_arg_type(i) != DBUS_TYPE_ARRAY ||
99                     dbus_message_iter_get_element_type(i) != DBUS_TYPE_UINT32)
100                         return -EINVAL;
101
102                 r = set_ensure_allocated(&s->pids, trivial_hash_func, trivial_compare_func);
103                 if (r < 0)
104                         return r;
105
106                 dbus_message_iter_recurse(i, &sub);
107                 while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32) {
108                         uint32_t pid;
109
110                         dbus_message_iter_get_basic(&sub, &pid);
111
112                         if (pid <= 1)
113                                 return -EINVAL;
114
115                         if (mode != UNIT_CHECK) {
116                                 r = set_put(s->pids, LONG_TO_PTR(pid));
117                                 if (r < 0 && r != -EEXIST)
118                                         return r;
119                         }
120
121                         dbus_message_iter_next(&sub);
122                         n++;
123                 }
124
125                 if (n <= 0)
126                         return -EINVAL;
127
128                 return 1;
129         }
130
131         return 0;
132 }
133
134 int bus_scope_set_property(
135                 Unit *u,
136                 const char *name,
137                 DBusMessageIter *i,
138                 UnitSetPropertiesMode mode,
139                 DBusError *error) {
140
141         Scope *s = SCOPE(u);
142         int r;
143
144         assert(name);
145         assert(u);
146         assert(i);
147
148         r = bus_cgroup_set_property(u, &s->cgroup_context, name, i, mode, error);
149         if (r != 0)
150                 return r;
151
152         if (u->load_state == UNIT_STUB) {
153                 /* While we are created we still accept PIDs */
154
155                 r = bus_scope_set_transient_property(s, name, i, mode, error);
156                 if (r != 0)
157                         return r;
158         }
159
160         return 0;
161 }
162
163 int bus_scope_commit_properties(Unit *u) {
164         assert(u);
165
166         unit_realize_cgroup(u);
167         return 0;
168 }