]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
Merge pull request #7705 from keszybz/redo-linking
[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 <stdio_ext.h>
22
23 #include "alloc-util.h"
24 #include "async.h"
25 #include "bus-util.h"
26 #include "dbus-cgroup.h"
27 #include "dbus-execute.h"
28 #include "dbus-kill.h"
29 #include "dbus-service.h"
30 #include "fd-util.h"
31 #include "fileio.h"
32 #include "path-util.h"
33 #include "service.h"
34 #include "string-util.h"
35 #include "strv.h"
36 #include "unit.h"
37
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
39 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
40 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
41 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
42 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action, emergency_action, EmergencyAction);
43
44 const sd_bus_vtable bus_service_vtable[] = {
45 SD_BUS_VTABLE_START(0),
46 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
47 SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
48 SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
49 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
50 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
51 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
52 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
53 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec, offsetof(Service, runtime_max_usec), SD_BUS_VTABLE_PROPERTY_CONST),
54 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
55 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
56 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
57 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
58 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
59 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
60 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
61 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
62 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
63 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
64 SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned, offsetof(Service, n_fd_store), 0),
65 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
67 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
68 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
69 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
70 SD_BUS_PROPERTY("UID", "u", NULL, offsetof(Unit, ref_uid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
71 SD_BUS_PROPERTY("GID", "u", NULL, offsetof(Unit, ref_gid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
72 SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned, offsetof(Service, n_restarts), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
73
74 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
75 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
76 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
77 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
78 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
79 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
80 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
81
82 /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
83 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Unit, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
84 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Unit, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
85 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action, offsetof(Unit, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
86 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action, offsetof(Unit, failure_action), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
87 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Unit, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST|SD_BUS_VTABLE_HIDDEN),
88 SD_BUS_VTABLE_END
89 };
90
91 static int bus_service_set_transient_property(
92 Service *s,
93 const char *name,
94 sd_bus_message *message,
95 UnitWriteFlags flags,
96 sd_bus_error *error) {
97
98 ServiceExecCommand ci;
99 int r;
100
101 assert(s);
102 assert(name);
103 assert(message);
104
105 flags |= UNIT_PRIVATE;
106
107 if (streq(name, "RemainAfterExit")) {
108 int b;
109
110 r = sd_bus_message_read(message, "b", &b);
111 if (r < 0)
112 return r;
113
114 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
115 s->remain_after_exit = b;
116 unit_write_settingf(UNIT(s), flags, name, "RemainAfterExit=%s", yes_no(b));
117 }
118
119 return 1;
120
121 } else if (streq(name, "Type")) {
122 const char *t;
123 ServiceType k;
124
125 r = sd_bus_message_read(message, "s", &t);
126 if (r < 0)
127 return r;
128
129 k = service_type_from_string(t);
130 if (k < 0)
131 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
132
133 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
134 s->type = k;
135 unit_write_settingf(UNIT(s), flags, name, "Type=%s", service_type_to_string(s->type));
136 }
137
138 return 1;
139 } else if (streq(name, "RuntimeMaxUSec")) {
140 usec_t u;
141
142 r = sd_bus_message_read(message, "t", &u);
143 if (r < 0)
144 return r;
145
146 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
147 s->runtime_max_usec = u;
148 unit_write_settingf(UNIT(s), flags, name, "RuntimeMaxSec=" USEC_FMT "us", u);
149 }
150
151 return 1;
152
153 } else if (streq(name, "Restart")) {
154 ServiceRestart sr;
155 const char *v;
156
157 r = sd_bus_message_read(message, "s", &v);
158 if (r < 0)
159 return r;
160
161 if (isempty(v))
162 sr = SERVICE_RESTART_NO;
163 else {
164 sr = service_restart_from_string(v);
165 if (sr < 0)
166 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid restart setting: %s", v);
167 }
168
169 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
170 s->restart = sr;
171 unit_write_settingf(UNIT(s), flags, name, "Restart=%s", service_restart_to_string(sr));
172 }
173
174 return 1;
175
176 } else if (STR_IN_SET(name,
177 "StandardInputFileDescriptor",
178 "StandardOutputFileDescriptor",
179 "StandardErrorFileDescriptor")) {
180 int fd;
181
182 r = sd_bus_message_read(message, "h", &fd);
183 if (r < 0)
184 return r;
185
186 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
187 int copy;
188
189 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
190 if (copy < 0)
191 return -errno;
192
193 if (streq(name, "StandardInputFileDescriptor")) {
194 asynchronous_close(s->stdin_fd);
195 s->stdin_fd = copy;
196 } else if (streq(name, "StandardOutputFileDescriptor")) {
197 asynchronous_close(s->stdout_fd);
198 s->stdout_fd = copy;
199 } else {
200 asynchronous_close(s->stderr_fd);
201 s->stderr_fd = copy;
202 }
203
204 s->exec_context.stdio_as_fds = true;
205 }
206
207 return 1;
208
209 } else if (streq(name, "FileDescriptorStoreMax")) {
210 uint32_t u;
211
212 r = sd_bus_message_read(message, "u", &u);
213 if (r < 0)
214 return r;
215
216 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
217 s->n_fd_store_max = (unsigned) u;
218 unit_write_settingf(UNIT(s), flags, name, "FileDescriptorStoreMax=%" PRIu32, u);
219 }
220
221 return 1;
222
223 } else if (streq(name, "NotifyAccess")) {
224 const char *t;
225 NotifyAccess k;
226
227 r = sd_bus_message_read(message, "s", &t);
228 if (r < 0)
229 return r;
230
231 k = notify_access_from_string(t);
232 if (k < 0)
233 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid notify access setting %s", t);
234
235 if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
236 s->notify_access = k;
237 unit_write_settingf(UNIT(s), flags, name, "NotifyAccess=%s", notify_access_to_string(s->notify_access));
238 }
239
240 return 1;
241
242 } else if ((ci = service_exec_command_from_string(name)) >= 0)
243 return bus_exec_command_set_transient_property(UNIT(s), name, &s->exec_command[ci], message, flags, error);
244
245 return 0;
246 }
247
248 int bus_service_set_property(
249 Unit *u,
250 const char *name,
251 sd_bus_message *message,
252 UnitWriteFlags flags,
253 sd_bus_error *error) {
254
255 Service *s = SERVICE(u);
256 int r;
257
258 assert(s);
259 assert(name);
260 assert(message);
261
262 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, flags, error);
263 if (r != 0)
264 return r;
265
266 if (u->transient && u->load_state == UNIT_STUB) {
267 /* This is a transient unit, let's load a little more */
268
269 r = bus_service_set_transient_property(s, name, message, flags, error);
270 if (r != 0)
271 return r;
272
273 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, flags, error);
274 if (r != 0)
275 return r;
276
277 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error);
278 if (r != 0)
279 return r;
280 }
281
282 return 0;
283 }
284
285 int bus_service_commit_properties(Unit *u) {
286 assert(u);
287
288 unit_update_cgroup_members_masks(u);
289 unit_realize_cgroup(u);
290
291 return 0;
292 }