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_emergency_action
, emergency_action
, EmergencyAction
);
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 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action
, offsetof(Service
, emergency_action
), SD_BUS_VTABLE_PROPERTY_CONST
),
54 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool
, offsetof(Service
, permissions_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
),
55 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool
, offsetof(Service
, root_directory_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
),
56 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool
, offsetof(Service
, remain_after_exit
), SD_BUS_VTABLE_PROPERTY_CONST
),
57 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool
, offsetof(Service
, guess_main_pid
), SD_BUS_VTABLE_PROPERTY_CONST
),
58 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid
, offsetof(Service
, main_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
59 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid
, offsetof(Service
, control_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
60 SD_BUS_PROPERTY("BusName", "s", NULL
, offsetof(Service
, bus_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
61 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
62 SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store
), 0),
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 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL
, offsetof(Service
, usb_function_descriptors
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
67 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL
, offsetof(Service
, usb_function_strings
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
68 SD_BUS_PROPERTY("UID", "u", NULL
, offsetof(Unit
, ref_uid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
69 SD_BUS_PROPERTY("GID", "u", NULL
, offsetof(Unit
, ref_gid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
70 SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned
, offsetof(Service
, n_restarts
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
72 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service
, main_exec_status
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
73 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service
, exec_command
[SERVICE_EXEC_START_PRE
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
74 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service
, exec_command
[SERVICE_EXEC_START
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
75 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service
, exec_command
[SERVICE_EXEC_START_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
76 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service
, exec_command
[SERVICE_EXEC_RELOAD
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
77 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
78 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
80 /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
81 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
82 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned
, offsetof(Unit
, start_limit
.burst
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
83 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action
, offsetof(Unit
, start_limit_action
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
84 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
88 static int bus_service_set_transient_property(
91 sd_bus_message
*message
,
92 UnitSetPropertiesMode mode
,
93 sd_bus_error
*error
) {
101 if (streq(name
, "RemainAfterExit")) {
104 r
= sd_bus_message_read(message
, "b", &b
);
108 if (mode
!= UNIT_CHECK
) {
109 s
->remain_after_exit
= b
;
110 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "RemainAfterExit=%s", yes_no(b
));
115 } else if (streq(name
, "Type")) {
119 r
= sd_bus_message_read(message
, "s", &t
);
123 k
= service_type_from_string(t
);
125 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service type %s", t
);
127 if (mode
!= UNIT_CHECK
) {
129 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "Type=%s", service_type_to_string(s
->type
));
133 } else if (streq(name
, "RuntimeMaxUSec")) {
136 r
= sd_bus_message_read(message
, "t", &u
);
140 if (mode
!= UNIT_CHECK
) {
141 s
->runtime_max_usec
= u
;
142 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "RuntimeMaxSec=" USEC_FMT
"us", u
);
147 } else if (streq(name
, "Restart")) {
151 r
= sd_bus_message_read(message
, "s", &v
);
156 sr
= SERVICE_RESTART_NO
;
158 sr
= service_restart_from_string(v
);
160 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid restart setting: %s", v
);
163 if (mode
!= UNIT_CHECK
) {
165 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "Restart=%s", service_restart_to_string(sr
));
170 } else if (STR_IN_SET(name
,
171 "StandardInputFileDescriptor",
172 "StandardOutputFileDescriptor",
173 "StandardErrorFileDescriptor")) {
176 r
= sd_bus_message_read(message
, "h", &fd
);
180 if (mode
!= UNIT_CHECK
) {
183 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
187 if (streq(name
, "StandardInputFileDescriptor")) {
188 asynchronous_close(s
->stdin_fd
);
190 } else if (streq(name
, "StandardOutputFileDescriptor")) {
191 asynchronous_close(s
->stdout_fd
);
194 asynchronous_close(s
->stderr_fd
);
198 s
->exec_context
.stdio_as_fds
= true;
203 } else if (streq(name
, "FileDescriptorStoreMax")) {
206 r
= sd_bus_message_read(message
, "u", &u
);
210 if (mode
!= UNIT_CHECK
) {
211 s
->n_fd_store_max
= (unsigned) u
;
212 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "FileDescriptorStoreMax=%" PRIu32
, u
);
217 } else if (streq(name
, "NotifyAccess")) {
221 r
= sd_bus_message_read(message
, "s", &t
);
225 k
= notify_access_from_string(t
);
227 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid notify access setting %s", t
);
229 if (mode
!= UNIT_CHECK
) {
230 s
->notify_access
= k
;
231 unit_write_drop_in_private_format(UNIT(s
), mode
, name
, "NotifyAccess=%s", notify_access_to_string(s
->notify_access
));
236 } else if (streq(name
, "ExecStart")) {
239 r
= sd_bus_message_enter_container(message
, 'a', "(sasb)");
243 while ((r
= sd_bus_message_enter_container(message
, 'r', "sasb")) > 0) {
244 _cleanup_strv_free_
char **argv
= NULL
;
248 r
= sd_bus_message_read(message
, "s", &path
);
252 if (!path_is_absolute(path
))
253 return sd_bus_error_set_errnof(error
, EINVAL
, "Path %s is not absolute.", path
);
255 r
= sd_bus_message_read_strv(message
, &argv
);
259 r
= sd_bus_message_read(message
, "b", &b
);
263 r
= sd_bus_message_exit_container(message
);
267 if (mode
!= UNIT_CHECK
) {
270 c
= new0(ExecCommand
, 1);
274 c
->path
= strdup(path
);
283 c
->flags
= b
? EXEC_COMMAND_IGNORE_FAILURE
: 0;
285 path_kill_slashes(c
->path
);
286 exec_command_append_list(&s
->exec_command
[SERVICE_EXEC_START
], c
);
295 r
= sd_bus_message_exit_container(message
);
299 if (mode
!= UNIT_CHECK
) {
300 _cleanup_free_
char *buf
= NULL
;
301 _cleanup_fclose_
FILE *f
= NULL
;
306 s
->exec_command
[SERVICE_EXEC_START
] = exec_command_free_list(s
->exec_command
[SERVICE_EXEC_START
]);
308 f
= open_memstream(&buf
, &size
);
312 fputs_unlocked("ExecStart=\n", f
);
314 LIST_FOREACH(command
, c
, s
->exec_command
[SERVICE_EXEC_START
]) {
315 _cleanup_free_
char *a
;
317 a
= strv_join_quoted(c
->argv
);
321 fprintf(f
, "ExecStart=%s@%s %s\n",
322 c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
? "-" : "",
327 r
= fflush_and_check(f
);
330 unit_write_drop_in_private(UNIT(s
), mode
, name
, buf
);
339 int bus_service_set_property(
342 sd_bus_message
*message
,
343 UnitSetPropertiesMode mode
,
344 sd_bus_error
*error
) {
346 Service
*s
= SERVICE(u
);
353 r
= bus_cgroup_set_property(u
, &s
->cgroup_context
, name
, message
, mode
, error
);
357 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
358 /* This is a transient unit, let's load a little more */
360 r
= bus_service_set_transient_property(s
, name
, message
, mode
, error
);
364 r
= bus_exec_context_set_transient_property(u
, &s
->exec_context
, name
, message
, mode
, error
);
368 r
= bus_kill_context_set_transient_property(u
, &s
->kill_context
, name
, message
, mode
, error
);
376 int bus_service_commit_properties(Unit
*u
) {
379 unit_update_cgroup_members_masks(u
);
380 unit_realize_cgroup(u
);