chiark / gitweb /
core: convert PID 1 to libsystemd-bus
[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_VTABLE("ExecStartPre", offsetof(Service, exec_command[SERVICE_EXEC_START_PRE]), 0),
64         BUS_EXEC_COMMAND_VTABLE("ExecStart", offsetof(Service, exec_command[SERVICE_EXEC_START]), 0),
65         BUS_EXEC_COMMAND_VTABLE("ExecStartPost", offsetof(Service, exec_command[SERVICE_EXEC_START_POST]), 0),
66         BUS_EXEC_COMMAND_VTABLE("ExecReload", offsetof(Service, exec_command[SERVICE_EXEC_RELOAD]), 0),
67         BUS_EXEC_COMMAND_VTABLE("ExecStop", offsetof(Service, exec_command[SERVICE_EXEC_STOP]), 0),
68         BUS_EXEC_COMMAND_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                 if (mode != UNIT_CHECK) {
173                         _cleanup_free_ char *buf = NULL;
174                         _cleanup_fclose_ FILE *f = NULL;
175                         ExecCommand *c;
176                         size_t size = 0;
177
178                         if (n == 0) {
179                                 exec_command_free_list(s->exec_command[SERVICE_EXEC_START]);
180                                 s->exec_command[SERVICE_EXEC_START] = NULL;
181                         }
182
183                         f = open_memstream(&buf, &size);
184                         if (!f)
185                                 return -ENOMEM;
186
187                         fputs("ExecStart=\n", f);
188
189                         LIST_FOREACH(command, c, s->exec_command[SERVICE_EXEC_START]) {
190                                 _cleanup_free_ char *a;
191
192                                 a = strv_join_quoted(c->argv);
193                                 if (!a)
194                                         return -ENOMEM;
195
196                                 fprintf(f, "ExecStart=%s@%s %s\n",
197                                         c->ignore ? "-" : "",
198                                         c->path,
199                                         a);
200                         }
201
202                         fflush(f);
203                         unit_write_drop_in_private(UNIT(s), mode, name, buf);
204                 }
205
206                 return 1;
207         }
208
209         return 0;
210 }
211
212 int bus_service_set_property(
213                 Unit *u,
214                 const char *name,
215                 sd_bus_message *message,
216                 UnitSetPropertiesMode mode,
217                 sd_bus_error *error) {
218
219         Service *s = SERVICE(u);
220         int r;
221
222         assert(s);
223         assert(name);
224         assert(message);
225
226         r = bus_cgroup_set_property(u, &s->cgroup_context, name, message, mode, error);
227         if (r != 0)
228                 return r;
229
230         if (u->transient && u->load_state == UNIT_STUB) {
231                 /* This is a transient unit, let's load a little more */
232
233                 r = bus_service_set_transient_property(s, name, message, mode, error);
234                 if (r != 0)
235                         return r;
236
237                 r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, mode, error);
238                 if (r != 0)
239                         return r;
240         }
241
242         return 0;
243 }
244
245 int bus_service_commit_properties(Unit *u) {
246         assert(u);
247
248         unit_realize_cgroup(u);
249         return 0;
250 }