]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-service.c
service: add support for reboot argument when triggered by StartLimitAction=
[thirdparty/systemd.git] / src / core / dbus-service.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
LP
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
5430f7f2
LP
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
4139c1b2
LP
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
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
c2756a68
LP
22#include "strv.h"
23#include "path-util.h"
718db961
LP
24#include "unit.h"
25#include "service.h"
4139c1b2
LP
26#include "dbus-unit.h"
27#include "dbus-execute.h"
4819ff03 28#include "dbus-kill.h"
4ad49000 29#include "dbus-cgroup.h"
4ad49000 30#include "dbus-service.h"
718db961
LP
31#include "bus-util.h"
32
33static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type, service_type, ServiceType);
34static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result, service_result, ServiceResult);
35static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart, service_restart, ServiceRestart);
36static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access, notify_access, NotifyAccess);
37static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_start_limit_action, start_limit_action, StartLimitAction);
38
39const sd_bus_vtable bus_service_vtable[] = {
40 SD_BUS_VTABLE_START(0),
556089dc
LP
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),
718db961 49 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service, watchdog_timestamp), 0),
556089dc
LP
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_start_limit_action, offsetof(Service, start_limit_action), SD_BUS_VTABLE_PROPERTY_CONST),
efe6e7d3 53 SD_BUS_PROPERTY("RebootArgument", "s", NULL, offsetof(Service, reboot_arg), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
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),
718db961
LP
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),
556089dc 60 SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
61 SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
62 SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
63 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
556089dc
LP
64 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
65 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
66 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
67 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
68 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
69 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
718db961 70 SD_BUS_VTABLE_END
d200735e
MS
71};
72
9f2e86af 73static int bus_service_set_transient_property(
c2756a68
LP
74 Service *s,
75 const char *name,
718db961 76 sd_bus_message *message,
c2756a68 77 UnitSetPropertiesMode mode,
718db961 78 sd_bus_error *error) {
c2756a68
LP
79
80 int r;
81
c2756a68 82 assert(s);
718db961
LP
83 assert(name);
84 assert(message);
c2756a68 85
6577c7ce 86 if (streq(name, "RemainAfterExit")) {
718db961 87 int b;
6577c7ce 88
718db961
LP
89 r = sd_bus_message_read(message, "b", &b);
90 if (r < 0)
91 return r;
6577c7ce 92
718db961 93 if (mode != UNIT_CHECK) {
6577c7ce
LP
94 s->remain_after_exit = b;
95 unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
96 }
97
98 return 1;
99
c7040b5d
LP
100 } else if (streq(name, "Type")) {
101 const char *t;
102 ServiceType k;
103
104 r = sd_bus_message_read(message, "s", &t);
105 if (r < 0)
106 return r;
107
108 k = service_type_from_string(t);
109 if (k < 0)
110 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid service type %s", t);
111
112 if (mode != UNIT_CHECK) {
113 s->type = k;
114 unit_write_drop_in_private_format(UNIT(s), mode, name, "Type=%s\n", service_type_to_string(s->type));
115 }
116
117 return 1;
118
6577c7ce 119 } else if (streq(name, "ExecStart")) {
c2756a68
LP
120 unsigned n = 0;
121
718db961
LP
122 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
123 if (r < 0)
124 return r;
c2756a68 125
718db961 126 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
c2756a68 127 _cleanup_strv_free_ char **argv = NULL;
c2756a68 128 const char *path;
718db961 129 int b;
c2756a68 130
718db961
LP
131 r = sd_bus_message_read(message, "s", &path);
132 if (r < 0)
133 return r;
c2756a68 134
718db961
LP
135 if (!path_is_absolute(path))
136 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
c2756a68 137
718db961 138 r = sd_bus_message_read_strv(message, &argv);
c2756a68
LP
139 if (r < 0)
140 return r;
141
718db961
LP
142 r = sd_bus_message_read(message, "b", &b);
143 if (r < 0)
144 return r;
c2756a68 145
718db961
LP
146 r = sd_bus_message_exit_container(message);
147 if (r < 0)
148 return r;
c2756a68
LP
149
150 if (mode != UNIT_CHECK) {
151 ExecCommand *c;
152
153 c = new0(ExecCommand, 1);
154 if (!c)
155 return -ENOMEM;
156
157 c->path = strdup(path);
158 if (!c->path) {
159 free(c);
160 return -ENOMEM;
161 }
162
163 c->argv = argv;
164 argv = NULL;
165
718db961 166 c->ignore = b;
c2756a68
LP
167
168 path_kill_slashes(c->path);
169 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
170 }
171
172 n++;
c2756a68 173 }
c7040b5d 174
718db961
LP
175 if (r < 0)
176 return r;
c2756a68 177
6ce270b1
LP
178 r = sd_bus_message_exit_container(message);
179 if (r < 0)
180 return r;
181
c2756a68
LP
182 if (mode != UNIT_CHECK) {
183 _cleanup_free_ char *buf = NULL;
184 _cleanup_fclose_ FILE *f = NULL;
185 ExecCommand *c;
186 size_t size = 0;
187
188 if (n == 0) {
189 exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
190 s->exec_command[SERVICE_EXEC_START] = NULL;
191 }
192
193 f = open_memstream(&buf, &size);
194 if (!f)
195 return -ENOMEM;
196
197 fputs("ExecStart=\n", f);
198
199 LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
a6fde353 200 _cleanup_free_ char *a;
c2756a68 201
a6fde353
ZJS
202 a = strv_join_quoted(c->argv);
203 if (!a)
204 return -ENOMEM;
c2756a68 205
a6fde353
ZJS
206 fprintf(f, "ExecStart=%s@%s %s\n",
207 c->ignore ? "-" : "",
208 c->path,
209 a);
c2756a68
LP
210 }
211
212 fflush(f);
b9ec9359 213 unit_write_drop_in_private(UNIT(s), mode, name, buf);
c2756a68
LP
214 }
215
216 return 1;
217 }
218
219 return 0;
220}
221
74c964d3
LP
222int bus_service_set_property(
223 Unit *u,
224 const char *name,
718db961 225 sd_bus_message *message,
74c964d3 226 UnitSetPropertiesMode mode,
718db961 227 sd_bus_error *error) {
74c964d3
LP
228
229 Service *s = SERVICE(u);
230 int r;
231
718db961 232 assert(s);
74c964d3 233 assert(name);
718db961 234 assert(message);
74c964d3 235
718db961 236 r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
74c964d3
LP
237 if (r != 0)
238 return r;
239
c2756a68
LP
240 if (u->transient && u->load_state == UNIT_STUB) {
241 /* This is a transient unit, let's load a little more */
242
718db961 243 r = bus_service_set_transient_property(s, name, message, mode, error);
c2756a68
LP
244 if (r != 0)
245 return r;
a6c0353b 246
c7040b5d
LP
247 r = bus_exec_context_set_transient_property(u, &s->exec_context, name, message, mode, error);
248 if (r != 0)
249 return r;
250
718db961 251 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
a6c0353b
LP
252 if (r != 0)
253 return r;
c2756a68
LP
254 }
255
74c964d3
LP
256 return 0;
257}
258
259int bus_service_commit_properties(Unit *u) {
260 assert(u);
261
bc432dc7 262 unit_update_cgroup_members_masks(u);
74c964d3 263 unit_realize_cgroup(u);
bc432dc7 264
74c964d3
LP
265 return 0;
266}