1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 #include "alloc-util.h"
7 #include "bus-internal.h"
9 #include "dbus-cgroup.h"
10 #include "dbus-execute.h"
11 #include "dbus-kill.h"
12 #include "dbus-manager.h"
13 #include "dbus-service.h"
14 #include "dbus-util.h"
15 #include "exit-status.h"
18 #include "parse-util.h"
19 #include "path-util.h"
21 #include "signal-util.h"
22 #include "string-util.h"
26 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_type
, service_type
, ServiceType
);
27 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_result
, service_result
, ServiceResult
);
28 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_restart
, service_restart
, ServiceRestart
);
29 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_notify_access
, notify_access
, NotifyAccess
);
30 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_emergency_action
, emergency_action
, EmergencyAction
);
32 static int property_get_timeout_abort_usec(
35 const char *interface
,
37 sd_bus_message
*reply
,
39 sd_bus_error
*error
) {
41 Service
*s
= userdata
;
48 t
= service_timeout_abort_usec(s
);
50 return sd_bus_message_append(reply
, "t", t
);
53 static int property_get_exit_status_set(
56 const char *interface
,
58 sd_bus_message
*reply
,
60 sd_bus_error
*error
) {
62 ExitStatusSet
*status_set
= userdata
;
71 r
= sd_bus_message_open_container(reply
, 'r', "aiai");
75 r
= sd_bus_message_open_container(reply
, 'a', "i");
79 SET_FOREACH(id
, status_set
->status
, i
) {
80 int32_t val
= PTR_TO_INT(id
);
82 if (val
< 0 || val
> 255)
85 r
= sd_bus_message_append_basic(reply
, 'i', &val
);
90 r
= sd_bus_message_close_container(reply
);
94 r
= sd_bus_message_open_container(reply
, 'a', "i");
98 SET_FOREACH(id
, status_set
->signal
, i
) {
99 int32_t val
= PTR_TO_INT(id
);
102 str
= signal_to_string((int) val
);
106 r
= sd_bus_message_append_basic(reply
, 'i', &val
);
111 r
= sd_bus_message_close_container(reply
);
115 return sd_bus_message_close_container(reply
);
118 const sd_bus_vtable bus_service_vtable
[] = {
119 SD_BUS_VTABLE_START(0),
120 SD_BUS_PROPERTY("Type", "s", property_get_type
, offsetof(Service
, type
), SD_BUS_VTABLE_PROPERTY_CONST
),
121 SD_BUS_PROPERTY("Restart", "s", property_get_restart
, offsetof(Service
, restart
), SD_BUS_VTABLE_PROPERTY_CONST
),
122 SD_BUS_PROPERTY("PIDFile", "s", NULL
, offsetof(Service
, pid_file
), SD_BUS_VTABLE_PROPERTY_CONST
),
123 SD_BUS_PROPERTY("NotifyAccess", "s", property_get_notify_access
, offsetof(Service
, notify_access
), SD_BUS_VTABLE_PROPERTY_CONST
),
124 SD_BUS_PROPERTY("RestartUSec", "t", bus_property_get_usec
, offsetof(Service
, restart_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
125 SD_BUS_PROPERTY("TimeoutStartUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_start_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
126 SD_BUS_PROPERTY("TimeoutStopUSec", "t", bus_property_get_usec
, offsetof(Service
, timeout_stop_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
127 SD_BUS_PROPERTY("TimeoutAbortUSec", "t", property_get_timeout_abort_usec
, 0, 0),
128 SD_BUS_PROPERTY("RuntimeMaxUSec", "t", bus_property_get_usec
, offsetof(Service
, runtime_max_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
129 SD_BUS_PROPERTY("WatchdogUSec", "t", bus_property_get_usec
, offsetof(Service
, watchdog_usec
), SD_BUS_VTABLE_PROPERTY_CONST
),
130 BUS_PROPERTY_DUAL_TIMESTAMP("WatchdogTimestamp", offsetof(Service
, watchdog_timestamp
), 0),
131 SD_BUS_PROPERTY("PermissionsStartOnly", "b", bus_property_get_bool
, offsetof(Service
, permissions_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
), /* 😷 deprecated */
132 SD_BUS_PROPERTY("RootDirectoryStartOnly", "b", bus_property_get_bool
, offsetof(Service
, root_directory_start_only
), SD_BUS_VTABLE_PROPERTY_CONST
),
133 SD_BUS_PROPERTY("RemainAfterExit", "b", bus_property_get_bool
, offsetof(Service
, remain_after_exit
), SD_BUS_VTABLE_PROPERTY_CONST
),
134 SD_BUS_PROPERTY("GuessMainPID", "b", bus_property_get_bool
, offsetof(Service
, guess_main_pid
), SD_BUS_VTABLE_PROPERTY_CONST
),
135 SD_BUS_PROPERTY("RestartPreventExitStatus", "(aiai)", property_get_exit_status_set
, offsetof(Service
, restart_prevent_status
), SD_BUS_VTABLE_PROPERTY_CONST
),
136 SD_BUS_PROPERTY("RestartForceExitStatus", "(aiai)", property_get_exit_status_set
, offsetof(Service
, restart_force_status
), SD_BUS_VTABLE_PROPERTY_CONST
),
137 SD_BUS_PROPERTY("SuccessExitStatus", "(aiai)", property_get_exit_status_set
, offsetof(Service
, success_status
), SD_BUS_VTABLE_PROPERTY_CONST
),
138 SD_BUS_PROPERTY("MainPID", "u", bus_property_get_pid
, offsetof(Service
, main_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
139 SD_BUS_PROPERTY("ControlPID", "u", bus_property_get_pid
, offsetof(Service
, control_pid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
140 SD_BUS_PROPERTY("BusName", "s", NULL
, offsetof(Service
, bus_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
141 SD_BUS_PROPERTY("FileDescriptorStoreMax", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store_max
), SD_BUS_VTABLE_PROPERTY_CONST
),
142 SD_BUS_PROPERTY("NFileDescriptorStore", "u", bus_property_get_unsigned
, offsetof(Service
, n_fd_store
), 0),
143 SD_BUS_PROPERTY("StatusText", "s", NULL
, offsetof(Service
, status_text
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
144 SD_BUS_PROPERTY("StatusErrno", "i", bus_property_get_int
, offsetof(Service
, status_errno
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
145 SD_BUS_PROPERTY("Result", "s", property_get_result
, offsetof(Service
, result
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
146 SD_BUS_PROPERTY("ReloadResult", "s", property_get_result
, offsetof(Service
, reload_result
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
147 SD_BUS_PROPERTY("USBFunctionDescriptors", "s", NULL
, offsetof(Service
, usb_function_descriptors
), SD_BUS_VTABLE_PROPERTY_CONST
),
148 SD_BUS_PROPERTY("USBFunctionStrings", "s", NULL
, offsetof(Service
, usb_function_strings
), SD_BUS_VTABLE_PROPERTY_CONST
),
149 SD_BUS_PROPERTY("UID", "u", bus_property_get_uid
, offsetof(Unit
, ref_uid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
150 SD_BUS_PROPERTY("GID", "u", bus_property_get_gid
, offsetof(Unit
, ref_gid
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
151 SD_BUS_PROPERTY("NRestarts", "u", bus_property_get_unsigned
, offsetof(Service
, n_restarts
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
152 SD_BUS_PROPERTY("OOMPolicy", "s", bus_property_get_oom_policy
, offsetof(Service
, oom_policy
), SD_BUS_VTABLE_PROPERTY_CONST
),
154 BUS_EXEC_STATUS_VTABLE("ExecMain", offsetof(Service
, main_exec_status
), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE
),
155 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPre", offsetof(Service
, exec_command
[SERVICE_EXEC_START_PRE
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
156 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStart", offsetof(Service
, exec_command
[SERVICE_EXEC_START
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
157 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStartPost", offsetof(Service
, exec_command
[SERVICE_EXEC_START_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
158 BUS_EXEC_COMMAND_LIST_VTABLE("ExecReload", offsetof(Service
, exec_command
[SERVICE_EXEC_RELOAD
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
159 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStop", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
160 BUS_EXEC_COMMAND_LIST_VTABLE("ExecStopPost", offsetof(Service
, exec_command
[SERVICE_EXEC_STOP_POST
]), SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION
),
162 /* The following four are obsolete, and thus marked hidden here. They moved into the Unit interface */
163 SD_BUS_PROPERTY("StartLimitInterval", "t", bus_property_get_usec
, offsetof(Unit
, start_limit
.interval
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
164 SD_BUS_PROPERTY("StartLimitBurst", "u", bus_property_get_unsigned
, offsetof(Unit
, start_limit
.burst
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
165 SD_BUS_PROPERTY("StartLimitAction", "s", property_get_emergency_action
, offsetof(Unit
, start_limit_action
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
166 SD_BUS_PROPERTY("FailureAction", "s", property_get_emergency_action
, offsetof(Unit
, failure_action
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
167 SD_BUS_PROPERTY("RebootArgument", "s", NULL
, offsetof(Unit
, reboot_arg
), SD_BUS_VTABLE_PROPERTY_CONST
|SD_BUS_VTABLE_HIDDEN
),
171 static int bus_set_transient_exit_status(
174 ExitStatusSet
*status_set
,
175 sd_bus_message
*message
,
176 UnitWriteFlags flags
,
177 sd_bus_error
*error
) {
179 const int32_t *status
, *signal
;
180 size_t sz_status
, sz_signal
, i
;
183 r
= sd_bus_message_enter_container(message
, 'r', "aiai");
187 r
= sd_bus_message_read_array(message
, 'i', (const void **) &status
, &sz_status
);
191 r
= sd_bus_message_read_array(message
, 'i', (const void **) &signal
, &sz_signal
);
195 r
= sd_bus_message_exit_container(message
);
199 sz_status
/= sizeof(int32_t);
200 sz_signal
/= sizeof(int32_t);
202 if (sz_status
== 0 && sz_signal
== 0 && !UNIT_WRITE_FLAGS_NOOP(flags
)) {
203 exit_status_set_free(status_set
);
204 unit_write_settingf(u
, flags
, name
, "%s=", name
);
208 for (i
= 0; i
< sz_status
; i
++) {
209 if (status
[i
] < 0 || status
[i
] > 255)
210 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid status code in %s: %"PRIi32
, name
, status
[i
]);
212 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
213 r
= set_ensure_allocated(&status_set
->status
, NULL
);
217 r
= set_put(status_set
->status
, INT_TO_PTR((int) status
[i
]));
221 unit_write_settingf(u
, flags
, name
, "%s=%"PRIi32
, name
, status
[i
]);
225 for (i
= 0; i
< sz_signal
; i
++) {
228 str
= signal_to_string((int) signal
[i
]);
230 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid signal in %s: %"PRIi32
, name
, signal
[i
]);
232 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
233 r
= set_ensure_allocated(&status_set
->signal
, NULL
);
237 r
= set_put(status_set
->signal
, INT_TO_PTR((int) signal
[i
]));
241 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, str
);
248 static int bus_set_transient_std_fd(
253 sd_bus_message
*message
,
254 UnitWriteFlags flags
,
255 sd_bus_error
*error
) {
262 r
= sd_bus_message_read(message
, "h", &fd
);
266 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
269 copy
= fcntl(fd
, F_DUPFD_CLOEXEC
, 3);
273 asynchronous_close(*p
);
280 static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access
, NotifyAccess
, notify_access_from_string
);
281 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type
, ServiceType
, service_type_from_string
);
282 static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart
, ServiceRestart
, service_restart_from_string
);
283 static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy
, OOMPolicy
, oom_policy_from_string
);
284 static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name
, service_name_is_valid
);
286 static int bus_service_set_transient_property(
289 sd_bus_message
*message
,
290 UnitWriteFlags flags
,
291 sd_bus_error
*error
) {
294 ServiceExecCommand ci
;
301 flags
|= UNIT_PRIVATE
;
303 if (streq(name
, "PermissionsStartOnly"))
304 return bus_set_transient_bool(u
, name
, &s
->permissions_start_only
, message
, flags
, error
);
306 if (streq(name
, "RootDirectoryStartOnly"))
307 return bus_set_transient_bool(u
, name
, &s
->root_directory_start_only
, message
, flags
, error
);
309 if (streq(name
, "RemainAfterExit"))
310 return bus_set_transient_bool(u
, name
, &s
->remain_after_exit
, message
, flags
, error
);
312 if (streq(name
, "GuessMainPID"))
313 return bus_set_transient_bool(u
, name
, &s
->guess_main_pid
, message
, flags
, error
);
315 if (streq(name
, "Type"))
316 return bus_set_transient_service_type(u
, name
, &s
->type
, message
, flags
, error
);
318 if (streq(name
, "OOMPolicy"))
319 return bus_set_transient_oom_policy(u
, name
, &s
->oom_policy
, message
, flags
, error
);
321 if (streq(name
, "RestartUSec"))
322 return bus_set_transient_usec(u
, name
, &s
->restart_usec
, message
, flags
, error
);
324 if (streq(name
, "TimeoutStartUSec")) {
325 r
= bus_set_transient_usec(u
, name
, &s
->timeout_start_usec
, message
, flags
, error
);
326 if (r
>= 0 && !UNIT_WRITE_FLAGS_NOOP(flags
))
327 s
->start_timeout_defined
= true;
332 if (streq(name
, "TimeoutStopUSec"))
333 return bus_set_transient_usec(u
, name
, &s
->timeout_stop_usec
, message
, flags
, error
);
335 if (streq(name
, "RuntimeMaxUSec"))
336 return bus_set_transient_usec(u
, name
, &s
->runtime_max_usec
, message
, flags
, error
);
338 if (streq(name
, "WatchdogUSec"))
339 return bus_set_transient_usec(u
, name
, &s
->watchdog_usec
, message
, flags
, error
);
341 if (streq(name
, "FileDescriptorStoreMax"))
342 return bus_set_transient_unsigned(u
, name
, &s
->n_fd_store_max
, message
, flags
, error
);
344 if (streq(name
, "NotifyAccess"))
345 return bus_set_transient_notify_access(u
, name
, &s
->notify_access
, message
, flags
, error
);
347 if (streq(name
, "PIDFile")) {
348 _cleanup_free_
char *n
= NULL
;
351 r
= sd_bus_message_read(message
, "s", &v
);
356 n
= path_make_absolute(v
, u
->manager
->prefix
[EXEC_DIRECTORY_RUNTIME
]);
360 path_simplify(n
, true);
362 if (!path_is_normalized(n
))
363 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "PIDFile= path '%s' is not valid", n
);
365 e
= path_startswith(n
, "/var/run/");
369 z
= strjoin("/run/", e
);
373 if (!UNIT_WRITE_FLAGS_NOOP(flags
))
374 log_unit_notice(u
, "Transient unit's PIDFile= property references path below legacy directory /var/run, updating %s → %s; please update client accordingly.", n
, z
);
376 free_and_replace(n
, z
);
380 if (!UNIT_WRITE_FLAGS_NOOP(flags
)) {
381 free_and_replace(s
->pid_file
, n
);
382 unit_write_settingf(u
, flags
, name
, "%s=%s", name
, strempty(s
->pid_file
));
388 if (streq(name
, "USBFunctionDescriptors"))
389 return bus_set_transient_path(u
, name
, &s
->usb_function_descriptors
, message
, flags
, error
);
391 if (streq(name
, "USBFunctionStrings"))
392 return bus_set_transient_path(u
, name
, &s
->usb_function_strings
, message
, flags
, error
);
394 if (streq(name
, "BusName"))
395 return bus_set_transient_bus_name(u
, name
, &s
->bus_name
, message
, flags
, error
);
397 if (streq(name
, "Restart"))
398 return bus_set_transient_service_restart(u
, name
, &s
->restart
, message
, flags
, error
);
400 if (streq(name
, "RestartPreventExitStatus"))
401 return bus_set_transient_exit_status(u
, name
, &s
->restart_prevent_status
, message
, flags
, error
);
403 if (streq(name
, "RestartForceExitStatus"))
404 return bus_set_transient_exit_status(u
, name
, &s
->restart_force_status
, message
, flags
, error
);
406 if (streq(name
, "SuccessExitStatus"))
407 return bus_set_transient_exit_status(u
, name
, &s
->success_status
, message
, flags
, error
);
409 ci
= service_exec_command_from_string(name
);
411 return bus_set_transient_exec_command(u
, name
, &s
->exec_command
[ci
], message
, flags
, error
);
413 if (streq(name
, "StandardInputFileDescriptor"))
414 return bus_set_transient_std_fd(u
, name
, &s
->stdin_fd
, &s
->exec_context
.stdio_as_fds
, message
, flags
, error
);
416 if (streq(name
, "StandardOutputFileDescriptor"))
417 return bus_set_transient_std_fd(u
, name
, &s
->stdout_fd
, &s
->exec_context
.stdio_as_fds
, message
, flags
, error
);
419 if (streq(name
, "StandardErrorFileDescriptor"))
420 return bus_set_transient_std_fd(u
, name
, &s
->stderr_fd
, &s
->exec_context
.stdio_as_fds
, message
, flags
, error
);
425 int bus_service_set_property(
428 sd_bus_message
*message
,
429 UnitWriteFlags flags
,
430 sd_bus_error
*error
) {
432 Service
*s
= SERVICE(u
);
439 r
= bus_cgroup_set_property(u
, &s
->cgroup_context
, name
, message
, flags
, error
);
443 if (u
->transient
&& u
->load_state
== UNIT_STUB
) {
444 /* This is a transient unit, let's load a little more */
446 r
= bus_service_set_transient_property(s
, name
, message
, flags
, error
);
450 r
= bus_exec_context_set_transient_property(u
, &s
->exec_context
, name
, message
, flags
, error
);
454 r
= bus_kill_context_set_transient_property(u
, &s
->kill_context
, name
, message
, flags
, error
);
462 int bus_service_commit_properties(Unit
*u
) {
465 unit_invalidate_cgroup_members_masks(u
);
466 unit_realize_cgroup(u
);