chiark / gitweb /
service: add the ability for units to join other unit's PrivateNetwork= and PrivateTm...
[elogind.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_start_limit_action, start_limit_action, StartLimitAction);
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), 0),
42         SD_BUS_PROPERTY("Restart", "s", property_get_restart, offsetof(Service, restart), 0),
43         SD_BUS_PROPERTY("PIDFile", "s", NULL, offsetof(Service, pid_file), 0),
44         SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access, offsetof(Service, notify_access), 0),
45         SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec, offsetof(Service, restart_usec), 0),
46         SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec, offsetof(Service, timeout_start_usec), 0),
47         SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec, offsetof(Service, timeout_stop_usec), 0),
48         SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec, offsetof(Service, watchdog_usec), 0),
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), 0),
51         SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned, offsetof(Service, start_limit.burst), 0),
52         SD_BUS_PROPERTY("StartLimitAction", "s", property_get_start_limit_action, offsetof(Service, start_limit_action), 0),
53         SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool, offsetof(Service, permissions_start_only), 0),
54         SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool, offsetof(Service, root_directory_start_only), 0),
55         SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool, offsetof(Service, remain_after_exit), 0),
56         SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool, offsetof(Service, guess_main_pid), 0),
57         SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid, offsetof(Service, main_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
58         SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid, offsetof(Service, control_pid), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
59         SD_BUS_PROPERTY("BusName", "s", NULL, offsetof(Service, bus_name), 0),
60         SD_BUS_PROPERTY("StatusText", "s", NULL, offsetof(Service, status_text), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
61         SD_BUS_PROPERTY("Result", "s", property_get_result, offsetof(Service, result), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
62         BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service, main_exec_status), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
63         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0),
64         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0),
65         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0),
66         BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0),
67         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0),
68         BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service, exec_command[SERVICE_EXEC_STOP_POST]), 0),
69         SD_BUS_VTABLE_END
70 };
71
72 const char* const bus_service_changing_properties[] = {
73         "ExecMainStartTimestamp",
74         "ExecMainStartTimestampMonotonic",
75         "ExecMainExitTimestamp",
76         "ExecMainExitTimestampMonotonic",
77         "ExecMainPID",
78         "ExecMainCode",
79         "ExecMainStatus",
80         "MainPID",
81         "ControlPID",
82         "StatusText",
83         "Result",
84         NULL
85 };
86
87 static int bus_service_set_transient_property(
88                 Service *s,
89                 const char *name,
90                 sd_bus_message *message,
91                 UnitSetPropertiesMode mode,
92                 sd_bus_error *error) {
93
94         int r;
95
96         assert(s);
97         assert(name);
98         assert(message);
99
100         if (streq(name, "RemainAfterExit")) {
101                 int b;
102
103                 r = sd_bus_message_read(message, "b", &b);
104                 if (r < 0)
105                         return r;
106
107                 if (mode != UNIT_CHECK) {
108                         s->remain_after_exit = b;
109                         unit_write_drop_in_private_format(UNIT(s), mode, name, "RemainAfterExit=%s\n", yes_no(b));
110                 }
111
112                 return 1;
113
114         } else if (streq(name, "ExecStart")) {
115                 unsigned n = 0;
116
117                 r = sd_bus_message_enter_container(message, 'a', "(sasb)");
118                 if (r < 0)
119                         return r;
120
121                 while ((r = sd_bus_message_enter_container(message, 'r', "sasb")) > 0) {
122                         _cleanup_strv_free_ char **argv = NULL;
123                         const char *path;
124                         int b;
125
126                         r = sd_bus_message_read(message, "s", &path);
127                         if (r < 0)
128                                 return r;
129
130                         if (!path_is_absolute(path))
131                                 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
132
133                         r = sd_bus_message_read_strv(message, &argv);
134                         if (r < 0)
135                                 return r;
136
137                         r = sd_bus_message_read(message, "b", &b);
138                         if (r < 0)
139                                 return r;
140
141                         r = sd_bus_message_exit_container(message);
142                         if (r < 0)
143                                 return r;
144
145                         if (mode != UNIT_CHECK) {
146                                 ExecCommand *c;
147
148                                 c = new0(ExecCommand, 1);
149                                 if (!c)
150                                         return -ENOMEM;
151
152                                 c->path = strdup(path);
153                                 if (!c->path) {
154                                         free(c);
155                                         return -ENOMEM;
156                                 }
157
158                                 c->argv = argv;
159                                 argv = NULL;
160
161                                 c->ignore = b;
162
163                                 path_kill_slashes(c->path);
164                                 exec_command_append_list(&s->exec_command[SERVICE_EXEC_START], c);
165                         }
166
167                         n++;
168                 }
169                 if (r < 0)
170                         return r;
171
172                 r = sd_bus_message_exit_container(message);
173                 if (r < 0)
174                         return r;
175
176                 if (mode != UNIT_CHECK) {
177                         _cleanup_free_ char *buf = NULL;
178                         _cleanup_fclose_ FILE *f = NULL;
179                         ExecCommand *c;
180                         size_t size = 0;
181
182                         if (n == 0) {
183                                 exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
184                                 s->exec_command[SERVICE_EXEC_START] = NULL;
185                         }
186
187                         f = open_memstream(&buf, &size);
188                         if (!f)
189                                 return -ENOMEM;
190
191                         fputs("ExecStart=\n", f);
192
193                         LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
194                                 _cleanup_free_ char *a;
195
196                                 a = strv_join_quoted(c->argv);
197                                 if (!a)
198                                         return -ENOMEM;
199
200                                 fprintf(f, "ExecStart=%s@%s %s\n",
201                                         c->ignore ? "-" : "",
202                                         c->path,
203                                         a);
204                         }
205
206                         fflush(f);
207                         unit_write_drop_in_private(UNIT(s), mode, name, buf);
208                 }
209
210                 return 1;
211         }
212
213         return 0;
214 }
215
216 int bus_service_set_property(
217                 Unit *u,
218                 const char *name,
219                 sd_bus_message *message,
220                 UnitSetPropertiesMode mode,
221                 sd_bus_error *error) {
222
223         Service *s = SERVICE(u);
224         int r;
225
226         assert(s);
227         assert(name);
228         assert(message);
229
230         r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
231         if (r != 0)
232                 return r;
233
234         if (u->transient && u->load_state == UNIT_STUB) {
235                 /* This is a transient unit, let's load a little more */
236
237                 r = bus_service_set_transient_property(s, name, message, mode, error);
238                 if (r != 0)
239                         return r;
240
241                 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
242                 if (r != 0)
243                         return r;
244         }
245
246         return 0;
247 }
248
249 int bus_service_commit_properties(Unit *u) {
250         assert(u);
251
252         unit_realize_cgroup(u);
253         return 0;
254 }