]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
core: rework cgroup mask propagation
[thirdparty/systemd.git] / src / core / dbus-service.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 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 "strv.h"
23 #include "path-util.h"
24 #include "unit.h"
25 #include "service.h"
26 #include "dbus-unit.h"
27 #include "dbus-execute.h"
28 #include "dbus-kill.h"
29 #include "dbus-cgroup.h"
30 #include "dbus-service.h"
31 #include "bus-util.h"
32
33 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction);
38
39 const sd_bus_vtable bus_service_vtable[] = {
40 SD_BUS_VTABLE_START(0),
41 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
42 SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
43 SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
44 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
45 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
46 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
47 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
48 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
49 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
50 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
51 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
52 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
53 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
54 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
55 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
56 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
57 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
58 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
59 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
60 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
61 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
62 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
63 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
64 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
65 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
66 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
67 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
68 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
69 SD_BUS_VTABLE_END
70 };
71
72 static int bus_service_set_transient_property(
73 Service *s,
74 const char *name,
75 sd_bus_message *message,
76 UnitSetPropertiesMode mode,
77 sd_bus_error *error) {
78
79 int r;
80
81 assert(s);
82 assert(name);
83 assert(message);
84
85 if (streq(name, "RemainAfterExit")) {
86 int b;
87
88 r = sd_bus_message_read(message, "b", &b);
89 if (r < 0)
90 return r;
91
92 if (mode != UNIT_CHECK) {
93 s->remain_after_exit = b;
94 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
95 }
96
97 return 1;
98
99 } else if (streq(name, "Type")) {
100 const char *t;
101 ServiceType k;
102
103 r = sd_bus_message_read(message, "s", &t);
104 if (r < 0)
105 return r;
106
107 k = service_type_from_string(t);
108 if (k < 0)
109 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
110
111 if (mode != UNIT_CHECK) {
112 s->type = k;
113 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
114 }
115
116 return 1;
117
118 } else if (streq(name, "ExecStart")) {
119 unsigned n = 0;
120
121 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
122 if (r < 0)
123 return r;
124
125 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
126 _cleanup_strv_free_ char **argv = NULL;
127 const char *path;
128 int b;
129
130 r = sd_bus_message_read(message, "s", &path);
131 if (r < 0)
132 return r;
133
134 if (!path_is_absolute(path))
135 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
136
137 r = sd_bus_message_read_strv(message, &argv);
138 if (r < 0)
139 return r;
140
141 r = sd_bus_message_read(message, "b", &b);
142 if (r < 0)
143 return r;
144
145 r = sd_bus_message_exit_container(message);
146 if (r < 0)
147 return r;
148
149 if (mode != UNIT_CHECK) {
150 ExecCommand *c;
151
152 c = new0(ExecCommand, 1);
153 if (!c)
154 return -ENOMEM;
155
156 c->path = strdup(path);
157 if (!c->path) {
158 free(c);
159 return -ENOMEM;
160 }
161
162 c->argv = argv;
163 argv = NULL;
164
165 c->ignore = b;
166
167 path_kill_slashes(c->path);
168 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
169 }
170
171 n++;
172 }
173
174 if (r < 0)
175 return r;
176
177 r = sd_bus_message_exit_container(message);
178 if (r < 0)
179 return r;
180
181 if (mode != UNIT_CHECK) {
182 _cleanup_free_ char *buf = NULL;
183 _cleanup_fclose_ FILE *f = NULL;
184 ExecCommand *c;
185 size_t size = 0;
186
187 if (n == 0) {
188 exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
189 s->exec_command[SERVICE_EXEC_START] = NULL;
190 }
191
192 f = open_memstream(&buf, &size);
193 if (!f)
194 return -ENOMEM;
195
196 fputs("ExecStart=\n", f);
197
198 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
199 _cleanup_free_ char *a;
200
201 a = strv_join_quoted(c->argv);
202 if (!a)
203 return -ENOMEM;
204
205 fprintf(f, "ExecStart=%s@%s %s\n",
206 c->ignore ? "-" : "",
207 c->path,
208 a);
209 }
210
211 fflush(f);
212 unit_write_drop_in_private(UNIT(s), mode, name, buf);
213 }
214
215 return 1;
216 }
217
218 return 0;
219 }
220
221 int bus_service_set_property(
222 Unit *u,
223 const char *name,
224 sd_bus_message *message,
225 UnitSetPropertiesMode mode,
226 sd_bus_error *error) {
227
228 Service *s = SERVICE(u);
229 int r;
230
231 assert(s);
232 assert(name);
233 assert(message);
234
235 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
236 if (r != 0)
237 return r;
238
239 if (u->transient && u->load_state == UNIT_STUB) {
240 /* This is a transient unit, let's load a little more */
241
242 r = bus_service_set_transient_property(s, name, message, mode, error);
243 if (r != 0)
244 return r;
245
246 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
247 if (r != 0)
248 return r;
249
250 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
251 if (r != 0)
252 return r;
253 }
254
255 return 0;
256 }
257
258 int bus_service_commit_properties(Unit *u) {
259 assert(u);
260
261 unit_update_cgroup_members_masks(u);
262 unit_realize_cgroup(u);
263
264 return 0;
265 }