]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/dbus-service.c
Set $NOTIFY_SOCKET for control procs if NotifyAccess=all
[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 "strv.h"
23 #include "path-util.h"
24 #include "unit.h"
25 #include "service.h"
26 #include "dbus-unit.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("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
63 SD_BUS_PROPERTY("StatusErrno", "i", NULL, offsetof(Service, status_errno), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
64 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
65 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
66 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
67 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
68 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
69 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
70 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
71 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
72 SD_BUS_VTABLE_END
73 };
74
75 static int bus_service_set_transient_property(
76 Service *s,
77 const char *name,
78 sd_bus_message *message,
79 UnitSetPropertiesMode mode,
80 sd_bus_error *error) {
81
82 int r;
83
84 assert(s);
85 assert(name);
86 assert(message);
87
88 if (streq(name, "RemainAfterExit")) {
89 int b;
90
91 r = sd_bus_message_read(message, "b", &b);
92 if (r < 0)
93 return r;
94
95 if (mode != UNIT_CHECK) {
96 s->remain_after_exit = b;
97 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
98 }
99
100 return 1;
101
102 } else if (streq(name, "Type")) {
103 const char *t;
104 ServiceType k;
105
106 r = sd_bus_message_read(message, "s", &t);
107 if (r < 0)
108 return r;
109
110 k = service_type_from_string(t);
111 if (k < 0)
112 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
113
114 if (mode != UNIT_CHECK) {
115 s->type = k;
116 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
117 }
118
119 return 1;
120
121 } else if (streq(name, "ExecStart")) {
122 unsigned n = 0;
123
124 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
125 if (r < 0)
126 return r;
127
128 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
129 _cleanup_strv_free_ char **argv = NULL;
130 const char *path;
131 int b;
132
133 r = sd_bus_message_read(message, "s", &path);
134 if (r < 0)
135 return r;
136
137 if (!path_is_absolute(path))
138 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
139
140 r = sd_bus_message_read_strv(message, &argv);
141 if (r < 0)
142 return r;
143
144 r = sd_bus_message_read(message, "b", &b);
145 if (r < 0)
146 return r;
147
148 r = sd_bus_message_exit_container(message);
149 if (r < 0)
150 return r;
151
152 if (mode != UNIT_CHECK) {
153 ExecCommand *c;
154
155 c = new0(ExecCommand, 1);
156 if (!c)
157 return -ENOMEM;
158
159 c->path = strdup(path);
160 if (!c->path) {
161 free(c);
162 return -ENOMEM;
163 }
164
165 c->argv = argv;
166 argv = NULL;
167
168 c->ignore = b;
169
170 path_kill_slashes(c->path);
171 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
172 }
173
174 n++;
175 }
176
177 if (r < 0)
178 return r;
179
180 r = sd_bus_message_exit_container(message);
181 if (r < 0)
182 return r;
183
184 if (mode != UNIT_CHECK) {
185 _cleanup_free_ char *buf = NULL;
186 _cleanup_fclose_ FILE *f = NULL;
187 ExecCommand *c;
188 size_t size = 0;
189
190 if (n == 0) {
191 exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
192 s->exec_command[SERVICE_EXEC_START] = NULL;
193 }
194
195 f = open_memstream(&buf, &size);
196 if (!f)
197 return -ENOMEM;
198
199 fputs("ExecStart=\n", f);
200
201 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
202 _cleanup_free_ char *a;
203
204 a = strv_join_quoted(c->argv);
205 if (!a)
206 return -ENOMEM;
207
208 fprintf(f, "ExecStart=%s@%s %s\n",
209 c->ignore ? "-" : "",
210 c->path,
211 a);
212 }
213
214 fflush(f);
215 unit_write_drop_in_private(UNIT(s), mode, name, buf);
216 }
217
218 return 1;
219 }
220
221 return 0;
222 }
223
224 int bus_service_set_property(
225 Unit *u,
226 const char *name,
227 sd_bus_message *message,
228 UnitSetPropertiesMode mode,
229 sd_bus_error *error) {
230
231 Service *s = SERVICE(u);
232 int r;
233
234 assert(s);
235 assert(name);
236 assert(message);
237
238 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
239 if (r != 0)
240 return r;
241
242 if (u->transient && u->load_state == UNIT_STUB) {
243 /* This is a transient unit, let's load a little more */
244
245 r = bus_service_set_transient_property(s, name, message, mode, error);
246 if (r != 0)
247 return r;
248
249 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
250 if (r != 0)
251 return r;
252
253 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
254 if (r != 0)
255 return r;
256 }
257
258 return 0;
259 }
260
261 int bus_service_commit_properties(Unit *u) {
262 assert(u);
263
264 unit_update_cgroup_members_masks(u);
265 unit_realize_cgroup(u);
266
267 return 0;
268 }