]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
Merge pull request #1527 from keszybz/lz4
[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 "async.h"
23 #include "strv.h"
24 #include "path-util.h"
25 #include "unit.h"
26 #include "service.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_failure_action, failure_action, FailureAction);
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_failure_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
53 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
54 SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
55 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
56 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), SD_BUS_VTABLE_PROPERTY_CONST),
57 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), SD_BUS_VTABLE_PROPERTY_CONST),
58 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), SD_BUS_VTABLE_PROPERTY_CONST),
59 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
60 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
61 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
62 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", NULL, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
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 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
69 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
70 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
71 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
72 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
73 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
74 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
75 SD_BUS_VTABLE_END
76 };
77
78 static int bus_service_set_transient_property(
79 Service *s,
80 const char *name,
81 sd_bus_message *message,
82 UnitSetPropertiesMode mode,
83 sd_bus_error *error) {
84
85 int r;
86
87 assert(s);
88 assert(name);
89 assert(message);
90
91 if (streq(name, "RemainAfterExit")) {
92 int b;
93
94 r = sd_bus_message_read(message, "b", &b);
95 if (r < 0)
96 return r;
97
98 if (mode != UNIT_CHECK) {
99 s->remain_after_exit = b;
100 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
101 }
102
103 return 1;
104
105 } else if (streq(name, "Type")) {
106 const char *t;
107 ServiceType k;
108
109 r = sd_bus_message_read(message, "s", &t);
110 if (r < 0)
111 return r;
112
113 k = service_type_from_string(t);
114 if (k < 0)
115 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
116
117 if (mode != UNIT_CHECK) {
118 s->type = k;
119 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
120 }
121
122 return 1;
123
124 } else if (STR_IN_SET(name,
125 "StandardInputFileDescriptor",
126 "StandardOutputFileDescriptor",
127 "StandardErrorFileDescriptor")) {
128 int fd;
129
130 r = sd_bus_message_read(message, "h", &fd);
131 if (r < 0)
132 return r;
133
134 if (mode != UNIT_CHECK) {
135 int copy;
136
137 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
138 if (copy < 0)
139 return -errno;
140
141 if (streq(name, "StandardInputFileDescriptor")) {
142 asynchronous_close(s->stdin_fd);
143 s->stdin_fd = copy;
144 } else if (streq(name, "StandardOutputFileDescriptor")) {
145 asynchronous_close(s->stdout_fd);
146 s->stdout_fd = copy;
147 } else {
148 asynchronous_close(s->stderr_fd);
149 s->stderr_fd = copy;
150 }
151 }
152
153 return 1;
154
155 } else if (streq(name, "ExecStart")) {
156 unsigned n = 0;
157
158 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
159 if (r < 0)
160 return r;
161
162 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
163 _cleanup_strv_free_ char **argv = NULL;
164 const char *path;
165 int b;
166
167 r = sd_bus_message_read(message, "s", &path);
168 if (r < 0)
169 return r;
170
171 if (!path_is_absolute(path))
172 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
173
174 r = sd_bus_message_read_strv(message, &argv);
175 if (r < 0)
176 return r;
177
178 r = sd_bus_message_read(message, "b", &b);
179 if (r < 0)
180 return r;
181
182 r = sd_bus_message_exit_container(message);
183 if (r < 0)
184 return r;
185
186 if (mode != UNIT_CHECK) {
187 ExecCommand *c;
188
189 c = new0(ExecCommand, 1);
190 if (!c)
191 return -ENOMEM;
192
193 c->path = strdup(path);
194 if (!c->path) {
195 free(c);
196 return -ENOMEM;
197 }
198
199 c->argv = argv;
200 argv = NULL;
201
202 c->ignore = b;
203
204 path_kill_slashes(c->path);
205 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
206 }
207
208 n++;
209 }
210
211 if (r < 0)
212 return r;
213
214 r = sd_bus_message_exit_container(message);
215 if (r < 0)
216 return r;
217
218 if (mode != UNIT_CHECK) {
219 _cleanup_free_ char *buf = NULL;
220 _cleanup_fclose_ FILE *f = NULL;
221 ExecCommand *c;
222 size_t size = 0;
223
224 if (n == 0)
225 s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
226
227 f = open_memstream(&buf, &size);
228 if (!f)
229 return -ENOMEM;
230
231 fputs("ExecStart=\n", f);
232
233 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
234 _cleanup_free_ char *a;
235
236 a = strv_join_quoted(c->argv);
237 if (!a)
238 return -ENOMEM;
239
240 fprintf(f, "ExecStart=%s@%s %s\n",
241 c->ignore ? "-" : "",
242 c->path,
243 a);
244 }
245
246 fflush(f);
247 unit_write_drop_in_private(UNIT(s), mode, name, buf);
248 }
249
250 return 1;
251 }
252
253 return 0;
254 }
255
256 int bus_service_set_property(
257 Unit *u,
258 const char *name,
259 sd_bus_message *message,
260 UnitSetPropertiesMode mode,
261 sd_bus_error *error) {
262
263 Service *s = SERVICE(u);
264 int r;
265
266 assert(s);
267 assert(name);
268 assert(message);
269
270 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
271 if (r != 0)
272 return r;
273
274 if (u->transient && u->load_state == UNIT_STUB) {
275 /* This is a transient unit, let's load a little more */
276
277 r = bus_service_set_transient_property(s, name, message, mode, error);
278 if (r != 0)
279 return r;
280
281 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
282 if (r != 0)
283 return r;
284
285 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
286 if (r != 0)
287 return r;
288 }
289
290 return 0;
291 }
292
293 int bus_service_commit_properties(Unit *u) {
294 assert(u);
295
296 unit_update_cgroup_members_masks(u);
297 unit_realize_cgroup(u);
298
299 return 0;
300 }