1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include "alloc-util.h"
24 #include "dbus-cgroup.h"
25 #include "dbus-execute.h"
26 #include "dbus-kill.h"
27 #include "dbus-service.h"
30 #include "path-util.h"
32 #include "string-util.h"
36 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, service_type
, ServiceType
);
37 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result
, service_result
, ServiceResult
);
38 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart
, service_restart
, ServiceRestart
);
39 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access
, notify_access
, NotifyAccess
);
40 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action
, emergency_action
, EmergencyAction
);
42 const sd_bus_vtable bus_service_vtable
[] = {
43 SD_BUS_VTABLE_START(0),
44 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Service
, type
), SD_BUS_VTABLE_PROPERTY_CONST
),
45 SD_BUS_PROPERTY("Restart", "s", property_get_restart
, offsetof(Service
, restart
), SD_BUS_VTABLE_PROPERTY_CONST
),
46 SD_BUS_PROPERTY("PIDFile", "s", NULL
, offsetof(Service
, pid_file
), SD_BUS_VTABLE_PROPERTY_CONST
),
47 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access
, offsetof(Service
, notify_access
), SD_BUS_VTABLE_PROPERTY_CONST
),
48 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec
, offsetof(Service
, restart_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
49 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_start_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
50 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_stop_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
51 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec
, offsetof(Service
, runtime_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
52 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec
, offsetof(Service
, watchdog_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
53 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service
, watchdog_timestamp
), 0),
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("FailureAction", "s", property_get_emergency_action
, offsetof(Unit
, failure_action
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
85 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
89 static int bus_service_set_transient_property(
92 sd_bus_message
*message
,
94 sd_bus_error
*error
) {
96 ServiceExecCommand ci
;
103 flags
|= UNIT_PRIVATE
;
105 if (streq(name
, "RemainAfterExit")) {
108 r
= sd_bus_message_read(message
, "b", &b
);
112 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
113 s
->remain_after_exit
= b
;
114 unit_write_settingf(UNIT(s
), flags
, name
, "RemainAfterExit=%s", yes_no(b
));
119 } else if (streq(name
, "Type")) {
123 r
= sd_bus_message_read(message
, "s", &t
);
127 k
= service_type_from_string(t
);
129 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid service type %s", t
);
131 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
133 unit_write_settingf(UNIT(s
), flags
, name
, "Type=%s", service_type_to_string(s
->type
));
137 } else if (streq(name
, "RuntimeMaxUSec")) {
140 r
= sd_bus_message_read(message
, "t", &u
);
144 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
145 s
->runtime_max_usec
= u
;
146 unit_write_settingf(UNIT(s
), flags
, name
, "RuntimeMaxSec=" USEC_FMT
"us", u
);
151 } else if (streq(name
, "Restart")) {
155 r
= sd_bus_message_read(message
, "s", &v
);
160 sr
= SERVICE_RESTART_NO
;
162 sr
= service_restart_from_string(v
);
164 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid restart setting: %s", v
);
167 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
169 unit_write_settingf(UNIT(s
), flags
, name
, "Restart=%s", service_restart_to_string(sr
));
174 } else if (STR_IN_SET(name
,
175 "StandardInputFileDescriptor",
176 "StandardOutputFileDescriptor",
177 "StandardErrorFileDescriptor")) {
180 r
= sd_bus_message_read(message
, "h", &fd
);
184 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
187 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
191 if (streq(name
, "StandardInputFileDescriptor")) {
192 asynchronous_close(s
->stdin_fd
);
194 } else if (streq(name
, "StandardOutputFileDescriptor")) {
195 asynchronous_close(s
->stdout_fd
);
198 asynchronous_close(s
->stderr_fd
);
202 s
->exec_context
.stdio_as_fds
= true;
207 } else if (streq(name
, "FileDescriptorStoreMax")) {
210 r
= sd_bus_message_read(message
, "u", &u
);
214 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
215 s
->n_fd_store_max
= (unsigned) u
;
216 unit_write_settingf(UNIT(s
), flags
, name
, "FileDescriptorStoreMax=%" PRIu32
, u
);
221 } else if (streq(name
, "NotifyAccess")) {
225 r
= sd_bus_message_read(message
, "s", &t
);
229 k
= notify_access_from_string(t
);
231 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid notify access setting %s", t
);
233 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
234 s
->notify_access
= k
;
235 unit_write_settingf(UNIT(s
), flags
, name
, "NotifyAccess=%s", notify_access_to_string(s
->notify_access
));
240 } else if ((ci
= service_exec_command_from_string(name
)) >= 0) {
243 r
= sd_bus_message_enter_container(message
, 'a', "(sasb)");
247 while ((r
= sd_bus_message_enter_container(message
, 'r', "sasb")) > 0) {
248 _cleanup_strv_free_
char **argv
= NULL
;
252 r
= sd_bus_message_read(message
, "s", &path
);
256 if (!path_is_absolute(path
))
257 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Path %s is not absolute.", path
);
259 r
= sd_bus_message_read_strv(message
, &argv
);
263 r
= sd_bus_message_read(message
, "b", &b
);
267 r
= sd_bus_message_exit_container(message
);
271 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
274 c
= new0(ExecCommand
, 1);
278 c
->path
= strdup(path
);
287 c
->flags
= b
? EXEC_COMMAND_IGNORE_FAILURE
: 0;
289 path_kill_slashes(c
->path
);
290 exec_command_append_list(&s
->exec_command
[ci
], c
);
299 r
= sd_bus_message_exit_container(message
);
303 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
304 _cleanup_free_
char *buf
= NULL
;
305 _cleanup_fclose_
FILE *f
= NULL
;
310 s
->exec_command
[ci
] = exec_command_free_list(s
->exec_command
[ci
]);
312 f
= open_memstream(&buf
, &size
);
316 fputs_unlocked("ExecStart=\n", f
);
318 LIST_FOREACH(command
, c
, s
->exec_command
[ci
]) {
319 _cleanup_free_
char *a
= NULL
, *t
= NULL
;
322 p
= unit_escape_setting(c
->path
, UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
, &t
);
326 a
= unit_concat_strv(c
->argv
, UNIT_ESCAPE_C
|UNIT_ESCAPE_SPECIFIERS
);
330 fprintf(f
, "%s=%s@%s %s\n",
332 c
->flags
& EXEC_COMMAND_IGNORE_FAILURE
? "-" : "",
337 r
= fflush_and_check(f
);
341 unit_write_setting(UNIT(s
), flags
, name
, buf
);
350 int bus_service_set_property(
353 sd_bus_message
*message
,
354 UnitWriteFlags flags
,
355 sd_bus_error
*error
) {
357 Service
*s
= SERVICE(u
);
364 r
= bus_cgroup_set_property(u
, &s
->cgroup_context
, name
, message
, flags
, error
);
368 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
369 /* This is a transient unit, let's load a little more */
371 r
= bus_service_set_transient_property(s
, name
, message
, flags
, error
);
375 r
= bus_exec_context_set_transient_property(u
, &s
->exec_context
, name
, message
, flags
, error
);
379 r
= bus_kill_context_set_transient_property(u
, &s
->kill_context
, name
, message
, flags
, error
);
387 int bus_service_commit_properties(Unit
*u
) {
390 unit_update_cgroup_members_masks(u
);
391 unit_realize_cgroup(u
);