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