]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-service.c
bootspec: fix debug message about default entry
[thirdparty/systemd.git] / src / core / dbus-service.c
CommitLineData
53e1b683 1/* SPDX-License-Identifier: LGPL-2.1+ */
4139c1b2
LP
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
5430f7f2
LP
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
4139c1b2
LP
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
5430f7f2 15 Lesser General Public License for more details.
4139c1b2 16
5430f7f2 17 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
19***/
20
b5efdb8a 21#include "alloc-util.h"
a34ceba6 22#include "async.h"
07630cea
LP
23#include "bus-util.h"
24#include "dbus-cgroup.h"
4139c1b2 25#include "dbus-execute.h"
4819ff03 26#include "dbus-kill.h"
3ffd4af2
LP
27#include "dbus-service.h"
28#include "fd-util.h"
0d39fa9c 29#include "fileio.h"
07630cea
LP
30#include "path-util.h"
31#include "service.h"
32#include "string-util.h"
33#include "strv.h"
34#include "unit.h"
718db961
LP
35
36static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
37static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
38static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
39static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
87a47f99 40static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
718db961
LP
41
42const sd_bus_vtable bus_service_vtable[] = {
43 SD_BUS_VTABLE_START(0),
556089dc
LP
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),
36c16a7c 51 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 52 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
718db961 53 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
556089dc
LP
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),
718db961
LP
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),
556089dc 60 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
d8e023aa
LP
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),
718db961 63 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
4774e357 64 SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
718db961 65 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
6b7e5923
PS
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),
00d9ef85
LP
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),
7a0019d3 70 SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
00d9ef85 71
718db961 72 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc
LP
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),
51d73fd9
LP
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),
87a47f99 83 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
53c35a76 84 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
51d73fd9 85 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
718db961 86 SD_BUS_VTABLE_END
d200735e
MS
87};
88
9f2e86af 89static int bus_service_set_transient_property(
c2756a68
LP
90 Service *s,
91 const char *name,
718db961 92 sd_bus_message *message,
2e59b241 93 UnitWriteFlags flags,
718db961 94 sd_bus_error *error) {
c2756a68 95
f6c66be1 96 ServiceExecCommand ci;
c2756a68
LP
97 int r;
98
c2756a68 99 assert(s);
718db961
LP
100 assert(name);
101 assert(message);
c2756a68 102
2e59b241
LP
103 flags |= UNIT_PRIVATE;
104
6577c7ce 105 if (streq(name, "RemainAfterExit")) {
718db961 106 int b;
6577c7ce 107
718db961
LP
108 r = sd_bus_message_read(message, "b", &b);
109 if (r < 0)
110 return r;
6577c7ce 111
2e59b241 112 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
6577c7ce 113 s->remain_after_exit = b;
2e59b241 114 unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
6577c7ce
LP
115 }
116
117 return 1;
118
c7040b5d
LP
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
2e59b241 131 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c7040b5d 132 s->type = k;
2e59b241 133 unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
c7040b5d
LP
134 }
135
36c16a7c
LP
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
2e59b241 144 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
36c16a7c 145 s->runtime_max_usec = u;
2e59b241 146 unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
36c16a7c
LP
147 }
148
c7040b5d
LP
149 return 1;
150
4ea0d7f4
LP
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
2e59b241 167 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
4ea0d7f4 168 s->restart = sr;
2e59b241 169 unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
4ea0d7f4
LP
170 }
171
172 return 1;
173
a34ceba6
LP
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
2e59b241 184 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
a34ceba6
LP
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 }
1e22b5cd
LP
201
202 s->exec_context.stdio_as_fds = true;
a34ceba6
LP
203 }
204
205 return 1;
206
9efb9df9
LP
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
2e59b241 214 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
9efb9df9 215 s->n_fd_store_max = (unsigned) u;
2e59b241 216 unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
9efb9df9
LP
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
2e59b241 233 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
9efb9df9 234 s->notify_access = k;
2e59b241 235 unit_write_settingf(UNIT(s), flags, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
9efb9df9
LP
236 }
237
238 return 1;
239
f6c66be1 240 } else if ((ci = service_exec_command_from_string(name)) >= 0) {
c2756a68
LP
241 unsigned n = 0;
242
718db961
LP
243 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
244 if (r < 0)
245 return r;
c2756a68 246
718db961 247 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
c2756a68 248 _cleanup_strv_free_ char **argv = NULL;
c2756a68 249 const char *path;
718db961 250 int b;
c2756a68 251
718db961
LP
252 r = sd_bus_message_read(message, "s", &path);
253 if (r < 0)
254 return r;
c2756a68 255
718db961 256 if (!path_is_absolute(path))
e74f76ca 257 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
c2756a68 258
718db961 259 r = sd_bus_message_read_strv(message, &argv);
c2756a68
LP
260 if (r < 0)
261 return r;
262
718db961
LP
263 r = sd_bus_message_read(message, "b", &b);
264 if (r < 0)
265 return r;
c2756a68 266
718db961
LP
267 r = sd_bus_message_exit_container(message);
268 if (r < 0)
269 return r;
c2756a68 270
2e59b241 271 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c2756a68
LP
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
3ed0cd26 287 c->flags = b ? EXEC_COMMAND_IGNORE_FAILURE : 0;
c2756a68
LP
288
289 path_kill_slashes(c->path);
f6c66be1 290 exec_command_append_list(&s->exec_command[ci], c);
c2756a68
LP
291 }
292
293 n++;
c2756a68 294 }
c7040b5d 295
718db961
LP
296 if (r < 0)
297 return r;
c2756a68 298
6ce270b1
LP
299 r = sd_bus_message_exit_container(message);
300 if (r < 0)
301 return r;
302
2e59b241 303 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c2756a68
LP
304 _cleanup_free_ char *buf = NULL;
305 _cleanup_fclose_ FILE *f = NULL;
306 ExecCommand *c;
307 size_t size = 0;
308
f1acf85a 309 if (n == 0)
f6c66be1 310 s->exec_command[ci] = exec_command_free_list(s->exec_command[ci]);
c2756a68
LP
311
312 f = open_memstream(&buf, &size);
313 if (!f)
314 return -ENOMEM;
315
4b61c875 316 fputs_unlocked("ExecStart=\n", f);
c2756a68 317
f6c66be1 318 LIST_FOREACH(command, c, s->exec_command[ci]) {
2e59b241
LP
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;
c2756a68 325
2e59b241 326 a = unit_concat_strv(c->argv, UNIT_ESCAPE_C|UNIT_ESCAPE_SPECIFIERS);
a6fde353
ZJS
327 if (!a)
328 return -ENOMEM;
c2756a68 329
f6c66be1
LP
330 fprintf(f, "%s=%s@%s %s\n",
331 name,
3ed0cd26 332 c->flags & EXEC_COMMAND_IGNORE_FAILURE ? "-" : "",
2e59b241 333 p,
a6fde353 334 a);
c2756a68
LP
335 }
336
1f2f874c
NC
337 r = fflush_and_check(f);
338 if (r < 0)
339 return r;
2e59b241
LP
340
341 unit_write_setting(UNIT(s), flags, name, buf);
c2756a68
LP
342 }
343
344 return 1;
345 }
346
347 return 0;
348}
349
74c964d3
LP
350int bus_service_set_property(
351 Unit *u,
352 const char *name,
718db961 353 sd_bus_message *message,
2e59b241 354 UnitWriteFlags flags,
718db961 355 sd_bus_error *error) {
74c964d3
LP
356
357 Service *s = SERVICE(u);
358 int r;
359
718db961 360 assert(s);
74c964d3 361 assert(name);
718db961 362 assert(message);
74c964d3 363
2e59b241 364 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
74c964d3
LP
365 if (r != 0)
366 return r;
367
c2756a68
LP
368 if (u->transient && u->load_state == UNIT_STUB) {
369 /* This is a transient unit, let's load a little more */
370
2e59b241 371 r = bus_service_set_transient_property(s, name, message, flags, error);
c2756a68
LP
372 if (r != 0)
373 return r;
a6c0353b 374
2e59b241 375 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
c7040b5d
LP
376 if (r != 0)
377 return r;
378
2e59b241 379 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
a6c0353b
LP
380 if (r != 0)
381 return r;
c2756a68
LP
382 }
383
74c964d3
LP
384 return 0;
385}
386
387int bus_service_commit_properties(Unit *u) {
388 assert(u);
389
bc432dc7 390 unit_update_cgroup_members_masks(u);
74c964d3 391 unit_realize_cgroup(u);
bc432dc7 392
74c964d3
LP
393 return 0;
394}