]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
util-lib: split our string related calls from util.[ch] into its own file string...
[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 "bus-util.h"
24 #include "dbus-cgroup.h"
25 #include "dbus-execute.h"
26 #include "dbus-kill.h"
27 #include "path-util.h"
28 #include "service.h"
29 #include "string-util.h"
30 #include "strv.h"
31 #include "unit.h"
32 #include "dbus-service.h"
33
34 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction);
39
40 const sd_bus_vtable bus_service_vtable[] = {
41 SD_BUS_VTABLE_START(0),
42 SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
43 SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
44 SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
45 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
46 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
47 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
48 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
49 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
50 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
51 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
52 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
53 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
54 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
55 SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
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", NULL, offsetof(Service, n_fd_store_max), SD_BUS_VTABLE_PROPERTY_CONST),
64 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
65 SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
67 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL, offsetof(Service, usb_function_descriptors), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
68 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL, offsetof(Service, usb_function_strings), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
69 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
70 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
71 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
72 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
73 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
74 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
75 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
76 SD_BUS_VTABLE_END
77 };
78
79 static int bus_service_set_transient_property(
80 Service *s,
81 const char *name,
82 sd_bus_message *message,
83 UnitSetPropertiesMode mode,
84 sd_bus_error *error) {
85
86 int r;
87
88 assert(s);
89 assert(name);
90 assert(message);
91
92 if (streq(name, "RemainAfterExit")) {
93 int b;
94
95 r = sd_bus_message_read(message, "b", &b);
96 if (r < 0)
97 return r;
98
99 if (mode != UNIT_CHECK) {
100 s->remain_after_exit = b;
101 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
102 }
103
104 return 1;
105
106 } else if (streq(name, "Type")) {
107 const char *t;
108 ServiceType k;
109
110 r = sd_bus_message_read(message, "s", &t);
111 if (r < 0)
112 return r;
113
114 k = service_type_from_string(t);
115 if (k < 0)
116 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
117
118 if (mode != UNIT_CHECK) {
119 s->type = k;
120 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
121 }
122
123 return 1;
124
125 } else if (STR_IN_SET(name,
126 "StandardInputFileDescriptor",
127 "StandardOutputFileDescriptor",
128 "StandardErrorFileDescriptor")) {
129 int fd;
130
131 r = sd_bus_message_read(message, "h", &fd);
132 if (r < 0)
133 return r;
134
135 if (mode != UNIT_CHECK) {
136 int copy;
137
138 copy = fcntl(fd, F_DUPFD_CLOEXEC, 3);
139 if (copy < 0)
140 return -errno;
141
142 if (streq(name, "StandardInputFileDescriptor")) {
143 asynchronous_close(s->stdin_fd);
144 s->stdin_fd = copy;
145 } else if (streq(name, "StandardOutputFileDescriptor")) {
146 asynchronous_close(s->stdout_fd);
147 s->stdout_fd = copy;
148 } else {
149 asynchronous_close(s->stderr_fd);
150 s->stderr_fd = copy;
151 }
152 }
153
154 return 1;
155
156 } else if (streq(name, "ExecStart")) {
157 unsigned n = 0;
158
159 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
160 if (r < 0)
161 return r;
162
163 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
164 _cleanup_strv_free_ char **argv = NULL;
165 const char *path;
166 int b;
167
168 r = sd_bus_message_read(message, "s", &path);
169 if (r < 0)
170 return r;
171
172 if (!path_is_absolute(path))
173 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
174
175 r = sd_bus_message_read_strv(message, &argv);
176 if (r < 0)
177 return r;
178
179 r = sd_bus_message_read(message, "b", &b);
180 if (r < 0)
181 return r;
182
183 r = sd_bus_message_exit_container(message);
184 if (r < 0)
185 return r;
186
187 if (mode != UNIT_CHECK) {
188 ExecCommand *c;
189
190 c = new0(ExecCommand, 1);
191 if (!c)
192 return -ENOMEM;
193
194 c->path = strdup(path);
195 if (!c->path) {
196 free(c);
197 return -ENOMEM;
198 }
199
200 c->argv = argv;
201 argv = NULL;
202
203 c->ignore = b;
204
205 path_kill_slashes(c->path);
206 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
207 }
208
209 n++;
210 }
211
212 if (r < 0)
213 return r;
214
215 r = sd_bus_message_exit_container(message);
216 if (r < 0)
217 return r;
218
219 if (mode != UNIT_CHECK) {
220 _cleanup_free_ char *buf = NULL;
221 _cleanup_fclose_ FILE *f = NULL;
222 ExecCommand *c;
223 size_t size = 0;
224
225 if (n == 0)
226 s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
227
228 f = open_memstream(&buf, &size);
229 if (!f)
230 return -ENOMEM;
231
232 fputs("ExecStart=\n", f);
233
234 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
235 _cleanup_free_ char *a;
236
237 a = strv_join_quoted(c->argv);
238 if (!a)
239 return -ENOMEM;
240
241 fprintf(f, "ExecStart=%s@%s %s\n",
242 c->ignore ? "-" : "",
243 c->path,
244 a);
245 }
246
247 r = fflush_and_check(f);
248 if (r < 0)
249 return r;
250 unit_write_drop_in_private(UNIT(s), mode, name, buf);
251 }
252
253 return 1;
254 }
255
256 return 0;
257 }
258
259 int bus_service_set_property(
260 Unit *u,
261 const char *name,
262 sd_bus_message *message,
263 UnitSetPropertiesMode mode,
264 sd_bus_error *error) {
265
266 Service *s = SERVICE(u);
267 int r;
268
269 assert(s);
270 assert(name);
271 assert(message);
272
273 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
274 if (r != 0)
275 return r;
276
277 if (u->transient && u->load_state == UNIT_STUB) {
278 /* This is a transient unit, let's load a little more */
279
280 r = bus_service_set_transient_property(s, name, message, mode, error);
281 if (r != 0)
282 return r;
283
284 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
285 if (r != 0)
286 return r;
287
288 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
289 if (r != 0)
290 return r;
291 }
292
293 return 0;
294 }
295
296 int bus_service_commit_properties(Unit *u) {
297 assert(u);
298
299 unit_update_cgroup_members_masks(u);
300 unit_realize_cgroup(u);
301
302 return 0;
303 }