2 This file is part of systemd.
4 Copyright 2010 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 #include "alloc-util.h"
23 #include "dbus-cgroup.h"
24 #include "dbus-execute.h"
25 #include "dbus-kill.h"
26 #include "dbus-service.h"
29 #include "path-util.h"
31 #include "string-util.h"
35 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, service_type
, ServiceType
);
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result
, service_result
, ServiceResult
);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart
, service_restart
, ServiceRestart
);
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access
, notify_access
, NotifyAccess
);
39 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_failure_action
, failure_action
, FailureAction
);
41 const sd_bus_vtable bus_service_vtable
[] = {
42 SD_BUS_VTABLE_START(0),
43 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Service
, type
), SD_BUS_VTABLE_PROPERTY_CONST
),
44 SD_BUS_PROPERTY("Restart", "s", property_get_restart
, offsetof(Service
, restart
), SD_BUS_VTABLE_PROPERTY_CONST
),
45 SD_BUS_PROPERTY("PIDFile", "s", NULL
, offsetof(Service
, pid_file
), SD_BUS_VTABLE_PROPERTY_CONST
),
46 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access
, offsetof(Service
, notify_access
), SD_BUS_VTABLE_PROPERTY_CONST
),
47 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec
, offsetof(Service
, restart_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
48 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_start_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
49 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_stop_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
50 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec
, offsetof(Service
, runtime_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
51 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec
, offsetof(Service
, watchdog_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
52 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service
, watchdog_timestamp
), 0),
53 /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
54 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
55 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned
, offsetof(Unit
, start_limit
.burst
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
56 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_failure_action
, offsetof(Unit
, start_limit_action
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
57 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
58 SD_BUS_PROPERTY("FailureAction", "s", property_get_failure_action
, offsetof(Service
, failure_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
59 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool
, offsetof(Service
, permissions_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
),
60 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool
, offsetof(Service
, root_directory_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
),
61 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool
, offsetof(Service
, remain_after_exit
), SD_BUS_VTABLE_PROPERTY_CONST
),
62 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool
, offsetof(Service
, guess_main_pid
), SD_BUS_VTABLE_PROPERTY_CONST
),
63 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid
, offsetof(Service
, main_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
64 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid
, offsetof(Service
, control_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
65 SD_BUS_PROPERTY("BusName", "s", NULL
, offsetof(Service
, bus_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
66 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
67 SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store
), 0),
68 SD_BUS_PROPERTY("StatusText", "s", NULL
, offsetof(Service
, status_text
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
69 SD_BUS_PROPERTY("StatusErrno", "i", NULL
, offsetof(Service
, status_errno
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
70 SD_BUS_PROPERTY("Result", "s", property_get_result
, offsetof(Service
, result
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
71 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL
, offsetof(Service
, usb_function_descriptors
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
72 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL
, offsetof(Service
, usb_function_strings
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
73 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service
, main_exec_status
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
74 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service
, exec_command
[SERVICE_EXEC_START_PRE
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
75 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service
, exec_command
[SERVICE_EXEC_START
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
76 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service
, exec_command
[SERVICE_EXEC_START_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
77 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service
, exec_command
[SERVICE_EXEC_RELOAD
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
78 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
79 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
83 static int bus_service_set_transient_property(
86 sd_bus_message
*message
,
87 UnitSetPropertiesMode mode
,
88 sd_bus_error
*error
) {
96 if (streq(name
, "RemainAfterExit")) {
99 r
= sd_bus_message_read(message
, "b", &b
);
103 if (mode
!= UNIT_CHECK
) {
104 s
->remain_after_exit
= b
;
105 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "RemainAfterExit=%s\n", yes_no(b
));
110 } else if (streq(name
, "Type")) {
114 r
= sd_bus_message_read(message
, "s", &t
);
118 k
= service_type_from_string(t
);
120 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service type %s", t
);
122 if (mode
!= UNIT_CHECK
) {
124 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "Type=%s\n", service_type_to_string(s
->type
));
128 } else if (streq(name
, "RuntimeMaxUSec")) {
131 r
= sd_bus_message_read(message
, "t", &u
);
135 if (mode
!= UNIT_CHECK
) {
136 s
->runtime_max_usec
= u
;
137 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "RuntimeMaxSec=" USEC_FMT
"us\n", u
);
142 } else if (STR_IN_SET(name
,
143 "StandardInputFileDescriptor",
144 "StandardOutputFileDescriptor",
145 "StandardErrorFileDescriptor")) {
148 r
= sd_bus_message_read(message
, "h", &fd
);
152 if (mode
!= UNIT_CHECK
) {
155 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
159 if (streq(name
, "StandardInputFileDescriptor")) {
160 asynchronous_close(s
->stdin_fd
);
162 } else if (streq(name
, "StandardOutputFileDescriptor")) {
163 asynchronous_close(s
->stdout_fd
);
166 asynchronous_close(s
->stderr_fd
);
170 s
->exec_context
.stdio_as_fds
= true;
175 } else if (streq(name
, "ExecStart")) {
178 r
= sd_bus_message_enter_container(message
, 'a', "(sasb)");
182 while ((r
= sd_bus_message_enter_container(message
, 'r', "sasb")) > 0) {
183 _cleanup_strv_free_
char **argv
= NULL
;
187 r
= sd_bus_message_read(message
, "s", &path
);
191 if (!path_is_absolute(path
))
192 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
194 r
= sd_bus_message_read_strv(message
, &argv
);
198 r
= sd_bus_message_read(message
, "b", &b
);
202 r
= sd_bus_message_exit_container(message
);
206 if (mode
!= UNIT_CHECK
) {
209 c
= new0(ExecCommand
, 1);
213 c
->path
= strdup(path
);
224 path_kill_slashes(c
->path
);
225 exec_command_append_list(&s
->exec_command
[SERVICE_EXEC_START
], c
);
234 r
= sd_bus_message_exit_container(message
);
238 if (mode
!= UNIT_CHECK
) {
239 _cleanup_free_
char *buf
= NULL
;
240 _cleanup_fclose_
FILE *f
= NULL
;
245 s
->exec_command
[SERVICE_EXEC_START
] = exec_command_free_list(s
->exec_command
[SERVICE_EXEC_START
]);
247 f
= open_memstream(&buf
, &size
);
251 fputs("ExecStart=\n", f
);
253 LIST_FOREACH(command
, c
, s
->exec_command
[SERVICE_EXEC_START
]) {
254 _cleanup_free_
char *a
;
256 a
= strv_join_quoted(c
->argv
);
260 fprintf(f
, "ExecStart=%s@%s %s\n",
261 c
->ignore
? "-" : "",
266 r
= fflush_and_check(f
);
269 unit_write_drop_in_private(UNIT(s
), mode
, name
, buf
);
278 int bus_service_set_property(
281 sd_bus_message
*message
,
282 UnitSetPropertiesMode mode
,
283 sd_bus_error
*error
) {
285 Service
*s
= SERVICE(u
);
292 r
= bus_cgroup_set_property(u
, &s
->cgroup_context
, name
, message
, mode
, error
);
296 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
297 /* This is a transient unit, let's load a little more */
299 r
= bus_service_set_transient_property(s
, name
, message
, mode
, error
);
303 r
= bus_exec_context_set_transient_property(u
, &s
->exec_context
, name
, message
, mode
, error
);
307 r
= bus_kill_context_set_transient_property(u
, &s
->kill_context
, name
, message
, mode
, error
);
315 int bus_service_commit_properties(Unit
*u
) {
318 unit_update_cgroup_members_masks(u
);
319 unit_realize_cgroup(u
);