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