]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
05bdc0a74855b43d44721f739ab915b62591fb90
[thirdparty/systemd.git] / src / core / dbus-service.c
1 /***
2 This file is part of systemd.
3
4 Copyright 2010 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 ***/
19
20 #include "alloc-util.h"
21 #include "async.h"
22 #include "bus-util.h"
23 #include "dbus-cgroup.h"
24 #include "dbus-execute.h"
25 #include "dbus-kill.h"
26 #include "dbus-service.h"
27 #include "fd-util.h"
28 #include "fileio.h"
29 #include "path-util.h"
30 #include "service.h"
31 #include "string-util.h"
32 #include "strv.h"
33 #include "unit.h"
34
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
39 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
40
41 const sd_bus_vtable bus_service_vtable[] = {
42 SD_BUS_VTABLE_START(0),
43 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
44 SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
45 SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
46 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
47 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
48 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
49 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
50 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
51 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
52 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
53 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Service, emergency_action), SD_BUS_VTABLE_PROPERTY_CONST),
54 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
55 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
56 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
57 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
58 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
59 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
60 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
61 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
62 SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
63 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
64 SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
65 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
67 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
68 SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
69 SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
70 SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
71
72 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
73 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
74 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
75 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
76 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
77 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
78 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
79
80 /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
81 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
82 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
83 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
84 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
85 SD_BUS_VTABLE_END
86 };
87
88 static int bus_service_set_transient_property(
89 Service *s,
90 const char *name,
91 sd_bus_message *message,
92 UnitSetPropertiesMode mode,
93 sd_bus_error *error) {
94
95 int r;
96
97 assert(s);
98 assert(name);
99 assert(message);
100
101 if (streq(name, "RemainAfterExit")) {
102 int b;
103
104 r = sd_bus_message_read(message, "b", &b);
105 if (r < 0)
106 return r;
107
108 if (mode != UNIT_CHECK) {
109 s->remain_after_exit = b;
110 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s", yes_no(b));
111 }
112
113 return 1;
114
115 } else if (streq(name, "Type")) {
116 const char *t;
117 ServiceType k;
118
119 r = sd_bus_message_read(message, "s", &t);
120 if (r < 0)
121 return r;
122
123 k = service_type_from_string(t);
124 if (k < 0)
125 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
126
127 if (mode != UNIT_CHECK) {
128 s->type = k;
129 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s", service_type_to_string(s->type));
130 }
131
132 return 1;
133 } else if (streq(name, "RuntimeMaxUSec")) {
134 usec_t u;
135
136 r = sd_bus_message_read(message, "t", &u);
137 if (r < 0)
138 return r;
139
140 if (mode != UNIT_CHECK) {
141 s->runtime_max_usec = u;
142 unit_write_drop_in_private_format(UNIT(s), mode, name, "RuntimeMaxSec=" USEC_FMT "us", u);
143 }
144
145 return 1;
146
147 } else if (streq(name, "Restart")) {
148 ServiceRestart sr;
149 const char *v;
150
151 r = sd_bus_message_read(message, "s", &v);
152 if (r < 0)
153 return r;
154
155 if (isempty(v))
156 sr = SERVICE_RESTART_NO;
157 else {
158 sr = service_restart_from_string(v);
159 if (sr < 0)
160 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
161 }
162
163 if (mode != UNIT_CHECK) {
164 s->restart = sr;
165 unit_write_drop_in_private_format(UNIT(s), mode, name, "Restart=%s", service_restart_to_string(sr));
166 }
167
168 return 1;
169
170 } else if (STR_IN_SET(name,
171 "StandardInputFileDescriptor",
172 "StandardOutputFileDescriptor",
173 "StandardErrorFileDescriptor")) {
174 int fd;
175
176 r = sd_bus_message_read(message, "h", &fd);
177 if (r < 0)
178 return r;
179
180 if (mode != UNIT_CHECK) {
181 int copy;
182
183 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
184 if (copy < 0)
185 return -errno;
186
187 if (streq(name, "StandardInputFileDescriptor")) {
188 asynchronous_close(s->stdin_fd);
189 s->stdin_fd = copy;
190 } else if (streq(name, "StandardOutputFileDescriptor")) {
191 asynchronous_close(s->stdout_fd);
192 s->stdout_fd = copy;
193 } else {
194 asynchronous_close(s->stderr_fd);
195 s->stderr_fd = copy;
196 }
197
198 s->exec_context.stdio_as_fds = true;
199 }
200
201 return 1;
202
203 } else if (streq(name, "FileDescriptorStoreMax")) {
204 uint32_t u;
205
206 r = sd_bus_message_read(message, "u", &u);
207 if (r < 0)
208 return r;
209
210 if (mode != UNIT_CHECK) {
211 s->n_fd_store_max = (unsigned) u;
212 unit_write_drop_in_private_format(UNIT(s), mode, name, "FileDescriptorStoreMax=%" PRIu32, u);
213 }
214
215 return 1;
216
217 } else if (streq(name, "NotifyAccess")) {
218 const char *t;
219 NotifyAccess k;
220
221 r = sd_bus_message_read(message, "s", &t);
222 if (r < 0)
223 return r;
224
225 k = notify_access_from_string(t);
226 if (k < 0)
227 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
228
229 if (mode != UNIT_CHECK) {
230 s->notify_access = k;
231 unit_write_drop_in_private_format(UNIT(s), mode, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
232 }
233
234 return 1;
235
236 } else if (streq(name, "ExecStart")) {
237 unsigned n = 0;
238
239 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
240 if (r < 0)
241 return r;
242
243 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
244 _cleanup_strv_free_ char **argv = NULL;
245 const char *path;
246 int b;
247
248 r = sd_bus_message_read(message, "s", &path);
249 if (r < 0)
250 return r;
251
252 if (!path_is_absolute(path))
253 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
254
255 r = sd_bus_message_read_strv(message, &argv);
256 if (r < 0)
257 return r;
258
259 r = sd_bus_message_read(message, "b", &b);
260 if (r < 0)
261 return r;
262
263 r = sd_bus_message_exit_container(message);
264 if (r < 0)
265 return r;
266
267 if (mode != UNIT_CHECK) {
268 ExecCommand *c;
269
270 c = new0(ExecCommand, 1);
271 if (!c)
272 return -ENOMEM;
273
274 c->path = strdup(path);
275 if (!c->path) {
276 free(c);
277 return -ENOMEM;
278 }
279
280 c->argv = argv;
281 argv = NULL;
282
283 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
284
285 path_kill_slashes(c->path);
286 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
287 }
288
289 n++;
290 }
291
292 if (r < 0)
293 return r;
294
295 r = sd_bus_message_exit_container(message);
296 if (r < 0)
297 return r;
298
299 if (mode != UNIT_CHECK) {
300 _cleanup_free_ char *buf = NULL;
301 _cleanup_fclose_ FILE *f = NULL;
302 ExecCommand *c;
303 size_t size = 0;
304
305 if (n == 0)
306 s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
307
308 f = open_memstream(&buf, &size);
309 if (!f)
310 return -ENOMEM;
311
312 fputs_unlocked("ExecStart=\n", f);
313
314 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
315 _cleanup_free_ char *a;
316
317 a = strv_join_quoted(c->argv);
318 if (!a)
319 return -ENOMEM;
320
321 fprintf(f, "ExecStart=%s@%s %s\n",
322 c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
323 c->path,
324 a);
325 }
326
327 r = fflush_and_check(f);
328 if (r < 0)
329 return r;
330 unit_write_drop_in_private(UNIT(s), mode, name, buf);
331 }
332
333 return 1;
334 }
335
336 return 0;
337 }
338
339 int bus_service_set_property(
340 Unit *u,
341 const char *name,
342 sd_bus_message *message,
343 UnitSetPropertiesMode mode,
344 sd_bus_error *error) {
345
346 Service *s = SERVICE(u);
347 int r;
348
349 assert(s);
350 assert(name);
351 assert(message);
352
353 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
354 if (r != 0)
355 return r;
356
357 if (u->transient && u->load_state == UNIT_STUB) {
358 /* This is a transient unit, let's load a little more */
359
360 r = bus_service_set_transient_property(s, name, message, mode, error);
361 if (r != 0)
362 return r;
363
364 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
365 if (r != 0)
366 return r;
367
368 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
369 if (r != 0)
370 return r;
371 }
372
373 return 0;
374 }
375
376 int bus_service_commit_properties(Unit *u) {
377 assert(u);
378
379 unit_update_cgroup_members_masks(u);
380 unit_realize_cgroup(u);
381
382 return 0;
383 }