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