Line data Source code
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-execute.h"
27 : #include "dbus-kill.h"
28 : #include "dbus-cgroup.h"
29 : #include "dbus-service.h"
30 : #include "bus-util.h"
31 :
32 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
33 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
34 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
35 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
36 0 : static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action, failure_action, FailureAction);
37 :
38 : const sd_bus_vtable bus_service_vtable[] = {
39 : SD_BUS_VTABLE_START(0),
40 : SD_BUS_PROPERTY("Type", "s", property_get_type, offsetof(Service, type), SD_BUS_VTABLE_PROPERTY_CONST),
41 : SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), SD_BUS_VTABLE_PROPERTY_CONST),
42 : SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), SD_BUS_VTABLE_PROPERTY_CONST),
43 : SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), SD_BUS_VTABLE_PROPERTY_CONST),
44 : SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), SD_BUS_VTABLE_PROPERTY_CONST),
45 : SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST),
46 : SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST),
47 : SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), SD_BUS_VTABLE_PROPERTY_CONST),
48 : BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
49 : SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec, offsetof(Service, start_limit.interval), SD_BUS_VTABLE_PROPERTY_CONST),
50 : SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), SD_BUS_VTABLE_PROPERTY_CONST),
51 : SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
52 : SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
53 : SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action, offsetof(Service, failure_action), SD_BUS_VTABLE_PROPERTY_CONST),
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),
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),
60 : SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
61 : SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", NULL, offsetof(Service, n_fd_store_max), 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 0 : 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 0 : assert(s);
85 0 : assert(name);
86 0 : assert(message);
87 :
88 0 : if (streq(name, "RemainAfterExit")) {
89 : int b;
90 :
91 0 : r = sd_bus_message_read(message, "b", &b);
92 0 : if (r < 0)
93 0 : return r;
94 :
95 0 : if (mode != UNIT_CHECK) {
96 0 : s->remain_after_exit = b;
97 0 : unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
98 : }
99 :
100 0 : return 1;
101 :
102 0 : } else if (streq(name, "Type")) {
103 : const char *t;
104 : ServiceType k;
105 :
106 0 : r = sd_bus_message_read(message, "s", &t);
107 0 : if (r < 0)
108 0 : return r;
109 :
110 0 : k = service_type_from_string(t);
111 0 : if (k < 0)
112 0 : return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
113 :
114 0 : if (mode != UNIT_CHECK) {
115 0 : s->type = k;
116 0 : unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
117 : }
118 :
119 0 : return 1;
120 :
121 0 : } else if (streq(name, "ExecStart")) {
122 0 : unsigned n = 0;
123 :
124 0 : r = sd_bus_message_enter_container(message, 'a', "(sasb)");
125 0 : if (r < 0)
126 0 : return r;
127 :
128 0 : while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
129 0 : _cleanup_strv_free_ char **argv = NULL;
130 : const char *path;
131 : int b;
132 :
133 0 : r = sd_bus_message_read(message, "s", &path);
134 0 : if (r < 0)
135 0 : return r;
136 :
137 0 : if (!path_is_absolute(path))
138 0 : return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
139 :
140 0 : r = sd_bus_message_read_strv(message, &argv);
141 0 : if (r < 0)
142 0 : return r;
143 :
144 0 : r = sd_bus_message_read(message, "b", &b);
145 0 : if (r < 0)
146 0 : return r;
147 :
148 0 : r = sd_bus_message_exit_container(message);
149 0 : if (r < 0)
150 0 : return r;
151 :
152 0 : if (mode != UNIT_CHECK) {
153 : ExecCommand *c;
154 :
155 0 : c = new0(ExecCommand, 1);
156 0 : if (!c)
157 0 : return -ENOMEM;
158 :
159 0 : c->path = strdup(path);
160 0 : if (!c->path) {
161 0 : free(c);
162 0 : return -ENOMEM;
163 : }
164 :
165 0 : c->argv = argv;
166 0 : argv = NULL;
167 :
168 0 : c->ignore = b;
169 :
170 0 : path_kill_slashes(c->path);
171 0 : exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
172 : }
173 :
174 0 : n++;
175 : }
176 :
177 0 : if (r < 0)
178 0 : return r;
179 :
180 0 : r = sd_bus_message_exit_container(message);
181 0 : if (r < 0)
182 0 : return r;
183 :
184 0 : if (mode != UNIT_CHECK) {
185 0 : _cleanup_free_ char *buf = NULL;
186 0 : _cleanup_fclose_ FILE *f = NULL;
187 : ExecCommand *c;
188 0 : size_t size = 0;
189 :
190 0 : if (n == 0)
191 0 : s->exec_command[SERVICE_EXEC_START] = exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
192 :
193 0 : f = open_memstream(&buf, &size);
194 0 : if (!f)
195 0 : return -ENOMEM;
196 :
197 0 : fputs("ExecStart=\n", f);
198 :
199 0 : LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
200 0 : _cleanup_free_ char *a;
201 :
202 0 : a = strv_join_quoted(c->argv);
203 0 : if (!a)
204 0 : return -ENOMEM;
205 :
206 0 : fprintf(f, "ExecStart=%s@%s %s\n",
207 0 : c->ignore ? "-" : "",
208 : c->path,
209 : a);
210 : }
211 :
212 0 : fflush(f);
213 0 : unit_write_drop_in_private(UNIT(s), mode, name, buf);
214 : }
215 :
216 0 : return 1;
217 : }
218 :
219 0 : return 0;
220 : }
221 :
222 0 : int bus_service_set_property(
223 : Unit *u,
224 : const char *name,
225 : sd_bus_message *message,
226 : UnitSetPropertiesMode mode,
227 : sd_bus_error *error) {
228 :
229 0 : Service *s = SERVICE(u);
230 : int r;
231 :
232 0 : assert(s);
233 0 : assert(name);
234 0 : assert(message);
235 :
236 0 : r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
237 0 : if (r != 0)
238 0 : return r;
239 :
240 0 : if (u->transient && u->load_state == UNIT_STUB) {
241 : /* This is a transient unit, let's load a little more */
242 :
243 0 : r = bus_service_set_transient_property(s, name, message, mode, error);
244 0 : if (r != 0)
245 0 : return r;
246 :
247 0 : r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
248 0 : if (r != 0)
249 0 : return r;
250 :
251 0 : r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
252 0 : if (r != 0)
253 0 : return r;
254 : }
255 :
256 0 : return 0;
257 : }
258 :
259 0 : int bus_service_commit_properties(Unit *u) {
260 0 : assert(u);
261 :
262 0 : unit_update_cgroup_members_masks(u);
263 0 : unit_realize_cgroup(u);
264 :
265 0 : return 0;
266 : }
|