1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 #include <sys/prctl.h>
34 #include "capability.h"
37 #include "namespace.h"
38 #include "path-util.h"
39 #include "dbus-execute.h"
42 #include "seccomp-util.h"
45 BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output
, exec_output
, ExecOutput
);
47 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input
, exec_input
, ExecInput
);
49 static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode
, exec_utmp_mode
, ExecUtmpMode
);
51 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home
, protect_home
, ProtectHome
);
52 static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system
, protect_system
, ProtectSystem
);
54 static int property_get_environment_files(
57 const char *interface
,
59 sd_bus_message
*reply
,
61 sd_bus_error
*error
) {
63 ExecContext
*c
= userdata
;
71 r
= sd_bus_message_open_container(reply
, 'a', "(sb)");
75 STRV_FOREACH(j
, c
->environment_files
) {
78 r
= sd_bus_message_append(reply
, "(sb)", fn
[0] == '-' ? fn
+ 1 : fn
, fn
[0] == '-');
83 return sd_bus_message_close_container(reply
);
86 static int property_get_rlimit(
89 const char *interface
,
91 sd_bus_message
*reply
,
93 sd_bus_error
*error
) {
103 rl
= *(struct rlimit
**) userdata
;
107 struct rlimit buf
= {};
110 z
= rlimit_from_string(property
);
117 /* rlim_t might have different sizes, let's map
118 * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
120 u
= x
== RLIM_INFINITY
? (uint64_t) -1 : (uint64_t) x
;
122 return sd_bus_message_append(reply
, "t", u
);
125 static int property_get_oom_score_adjust(
128 const char *interface
,
129 const char *property
,
130 sd_bus_message
*reply
,
132 sd_bus_error
*error
) {
135 ExecContext
*c
= userdata
;
142 if (c
->oom_score_adjust_set
)
143 n
= c
->oom_score_adjust
;
145 _cleanup_free_
char *t
= NULL
;
148 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
152 return sd_bus_message_append(reply
, "i", n
);
155 static int property_get_nice(
158 const char *interface
,
159 const char *property
,
160 sd_bus_message
*reply
,
162 sd_bus_error
*error
) {
165 ExecContext
*c
= userdata
;
176 n
= getpriority(PRIO_PROCESS
, 0);
181 return sd_bus_message_append(reply
, "i", n
);
184 static int property_get_ioprio(
187 const char *interface
,
188 const char *property
,
189 sd_bus_message
*reply
,
191 sd_bus_error
*error
) {
194 ExecContext
*c
= userdata
;
204 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
206 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
209 return sd_bus_message_append(reply
, "i", n
);
212 static int property_get_cpu_sched_policy(
215 const char *interface
,
216 const char *property
,
217 sd_bus_message
*reply
,
219 sd_bus_error
*error
) {
221 ExecContext
*c
= userdata
;
228 if (c
->cpu_sched_set
)
229 n
= c
->cpu_sched_policy
;
231 n
= sched_getscheduler(0);
236 return sd_bus_message_append(reply
, "i", n
);
239 static int property_get_cpu_sched_priority(
242 const char *interface
,
243 const char *property
,
244 sd_bus_message
*reply
,
246 sd_bus_error
*error
) {
248 ExecContext
*c
= userdata
;
255 if (c
->cpu_sched_set
)
256 n
= c
->cpu_sched_priority
;
258 struct sched_param p
= {};
260 if (sched_getparam(0, &p
) >= 0)
261 n
= p
.sched_priority
;
266 return sd_bus_message_append(reply
, "i", n
);
269 static int property_get_cpu_affinity(
272 const char *interface
,
273 const char *property
,
274 sd_bus_message
*reply
,
276 sd_bus_error
*error
) {
278 ExecContext
*c
= userdata
;
285 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
287 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
290 static int property_get_timer_slack_nsec(
293 const char *interface
,
294 const char *property
,
295 sd_bus_message
*reply
,
297 sd_bus_error
*error
) {
299 ExecContext
*c
= userdata
;
306 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
307 u
= (uint64_t) c
->timer_slack_nsec
;
309 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
311 return sd_bus_message_append(reply
, "t", u
);
314 static int property_get_capability_bounding_set(
317 const char *interface
,
318 const char *property
,
319 sd_bus_message
*reply
,
321 sd_bus_error
*error
) {
323 ExecContext
*c
= userdata
;
329 /* We store this negated internally, to match the kernel, but
330 * we expose it normalized. */
331 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
334 static int property_get_capabilities(
337 const char *interface
,
338 const char *property
,
339 sd_bus_message
*reply
,
341 sd_bus_error
*error
) {
343 ExecContext
*c
= userdata
;
344 _cleanup_cap_free_charp_
char *t
= NULL
;
352 s
= t
= cap_to_text(c
->capabilities
, NULL
);
359 return sd_bus_message_append(reply
, "s", s
);
362 static int property_get_syscall_filter(
365 const char *interface
,
366 const char *property
,
367 sd_bus_message
*reply
,
369 sd_bus_error
*error
) {
371 ExecContext
*c
= userdata
;
372 _cleanup_strv_free_
char **l
= NULL
;
384 r
= sd_bus_message_open_container(reply
, 'r', "bas");
388 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
393 SET_FOREACH(id
, c
->syscall_filter
, i
) {
396 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
400 r
= strv_consume(&l
, name
);
408 r
= sd_bus_message_append_strv(reply
, l
);
412 return sd_bus_message_close_container(reply
);
415 static int property_get_syscall_archs(
418 const char *interface
,
419 const char *property
,
420 sd_bus_message
*reply
,
422 sd_bus_error
*error
) {
424 ExecContext
*c
= userdata
;
425 _cleanup_strv_free_
char **l
= NULL
;
438 SET_FOREACH(id
, c
->syscall_archs
, i
) {
441 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
445 r
= strv_extend(&l
, name
);
453 r
= sd_bus_message_append_strv(reply
, l
);
460 static int property_get_syscall_errno(
463 const char *interface
,
464 const char *property
,
465 sd_bus_message
*reply
,
467 sd_bus_error
*error
) {
469 ExecContext
*c
= userdata
;
475 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
478 static int property_get_selinux_context(
481 const char *interface
,
482 const char *property
,
483 sd_bus_message
*reply
,
485 sd_bus_error
*error
) {
487 ExecContext
*c
= userdata
;
493 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
496 static int property_get_apparmor_profile(
499 const char *interface
,
500 const char *property
,
501 sd_bus_message
*reply
,
503 sd_bus_error
*error
) {
505 ExecContext
*c
= userdata
;
511 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
514 static int property_get_smack_process_label(
517 const char *interface
,
518 const char *property
,
519 sd_bus_message
*reply
,
521 sd_bus_error
*error
) {
523 ExecContext
*c
= userdata
;
529 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
532 static int property_get_personality(
535 const char *interface
,
536 const char *property
,
537 sd_bus_message
*reply
,
539 sd_bus_error
*error
) {
541 ExecContext
*c
= userdata
;
547 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
550 static int property_get_address_families(
553 const char *interface
,
554 const char *property
,
555 sd_bus_message
*reply
,
557 sd_bus_error
*error
) {
559 ExecContext
*c
= userdata
;
560 _cleanup_strv_free_
char **l
= NULL
;
569 r
= sd_bus_message_open_container(reply
, 'r', "bas");
573 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
577 SET_FOREACH(af
, c
->address_families
, i
) {
580 name
= af_to_name(PTR_TO_INT(af
));
584 r
= strv_extend(&l
, name
);
591 r
= sd_bus_message_append_strv(reply
, l
);
595 return sd_bus_message_close_container(reply
);
598 static int property_get_working_directory(
601 const char *interface
,
602 const char *property
,
603 sd_bus_message
*reply
,
605 sd_bus_error
*error
) {
607 ExecContext
*c
= userdata
;
614 if (c
->working_directory_home
)
617 wd
= c
->working_directory
;
619 if (c
->working_directory_missing_ok
)
620 wd
= strjoina("!", wd
);
622 return sd_bus_message_append(reply
, "s", wd
);
625 const sd_bus_vtable bus_exec_vtable
[] = {
626 SD_BUS_VTABLE_START(0),
627 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
628 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
629 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
630 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
697 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
701 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
710 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
714 r
= sd_bus_message_append(reply
, "s", c
->path
);
718 r
= sd_bus_message_append_strv(reply
, c
->argv
);
722 r
= sd_bus_message_append(reply
, "bttttuii",
724 c
->exec_status
.start_timestamp
.realtime
,
725 c
->exec_status
.start_timestamp
.monotonic
,
726 c
->exec_status
.exit_timestamp
.realtime
,
727 c
->exec_status
.exit_timestamp
.monotonic
,
728 (uint32_t) c
->exec_status
.pid
,
729 (int32_t) c
->exec_status
.code
,
730 (int32_t) c
->exec_status
.status
);
734 return sd_bus_message_close_container(reply
);
737 int bus_property_get_exec_command(
740 const char *interface
,
741 const char *property
,
742 sd_bus_message
*reply
,
744 sd_bus_error
*ret_error
) {
746 ExecCommand
*c
= (ExecCommand
*) userdata
;
752 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
756 r
= append_exec_command(reply
, c
);
760 return sd_bus_message_close_container(reply
);
763 int bus_property_get_exec_command_list(
766 const char *interface
,
767 const char *property
,
768 sd_bus_message
*reply
,
770 sd_bus_error
*ret_error
) {
772 ExecCommand
*c
= *(ExecCommand
**) userdata
;
778 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
782 LIST_FOREACH(command
, c
, c
) {
783 r
= append_exec_command(reply
, c
);
788 return sd_bus_message_close_container(reply
);
791 int bus_exec_context_set_transient_property(
795 sd_bus_message
*message
,
796 UnitSetPropertiesMode mode
,
797 sd_bus_error
*error
) {
806 if (streq(name
, "User")) {
809 r
= sd_bus_message_read(message
, "s", &uu
);
813 if (mode
!= UNIT_CHECK
) {
816 c
->user
= mfree(c
->user
);
828 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
833 } else if (streq(name
, "Group")) {
836 r
= sd_bus_message_read(message
, "s", &gg
);
840 if (mode
!= UNIT_CHECK
) {
843 c
->group
= mfree(c
->group
);
855 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
860 } else if (streq(name
, "Nice")) {
863 r
= sd_bus_message_read(message
, "i", &n
);
867 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
868 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
870 if (mode
!= UNIT_CHECK
) {
872 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
877 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
880 r
= sd_bus_message_read(message
, "s", &s
);
884 if (!path_is_absolute(s
))
885 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
887 if (mode
!= UNIT_CHECK
) {
888 if (streq(name
, "TTYPath"))
889 r
= free_and_strdup(&c
->tty_path
, s
);
891 assert(streq(name
, "RootDirectory"));
892 r
= free_and_strdup(&c
->root_directory
, s
);
897 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
902 } else if (streq(name
, "WorkingDirectory")) {
906 r
= sd_bus_message_read(message
, "s", &s
);
916 if (!streq(s
, "~") && !path_is_absolute(s
))
917 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
919 if (mode
!= UNIT_CHECK
) {
921 c
->working_directory
= mfree(c
->working_directory
);
922 c
->working_directory_home
= true;
924 r
= free_and_strdup(&c
->working_directory
, s
);
928 c
->working_directory_home
= false;
931 c
->working_directory_missing_ok
= missing_ok
;
932 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
937 } else if (streq(name
, "StandardInput")) {
941 r
= sd_bus_message_read(message
, "s", &s
);
945 p
= exec_input_from_string(s
);
947 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
949 if (mode
!= UNIT_CHECK
) {
952 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
958 } else if (streq(name
, "StandardOutput")) {
962 r
= sd_bus_message_read(message
, "s", &s
);
966 p
= exec_output_from_string(s
);
968 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
970 if (mode
!= UNIT_CHECK
) {
973 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
978 } else if (streq(name
, "StandardError")) {
982 r
= sd_bus_message_read(message
, "s", &s
);
986 p
= exec_output_from_string(s
);
988 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
990 if (mode
!= UNIT_CHECK
) {
993 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
998 } else if (STR_IN_SET(name
,
999 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1000 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1001 "NoNewPrivileges")) {
1004 r
= sd_bus_message_read(message
, "b", &b
);
1008 if (mode
!= UNIT_CHECK
) {
1009 if (streq(name
, "IgnoreSIGPIPE"))
1010 c
->ignore_sigpipe
= b
;
1011 else if (streq(name
, "TTYVHangup"))
1013 else if (streq(name
, "TTYReset"))
1015 else if (streq(name
, "PrivateTmp"))
1017 else if (streq(name
, "PrivateDevices"))
1018 c
->private_devices
= b
;
1019 else if (streq(name
, "PrivateNetwork"))
1020 c
->private_network
= b
;
1021 else if (streq(name
, "NoNewPrivileges"))
1022 c
->no_new_privileges
= b
;
1024 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1029 } else if (streq(name
, "UtmpIdentifier")) {
1032 r
= sd_bus_message_read(message
, "s", &id
);
1036 if (mode
!= UNIT_CHECK
) {
1038 c
->utmp_id
= mfree(c
->utmp_id
);
1039 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1042 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1047 } else if (streq(name
, "UtmpMode")) {
1051 r
= sd_bus_message_read(message
, "s", &s
);
1055 m
= exec_utmp_mode_from_string(s
);
1057 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1059 if (mode
!= UNIT_CHECK
) {
1062 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1067 } else if (streq(name
, "PAMName")) {
1070 r
= sd_bus_message_read(message
, "s", &n
);
1074 if (mode
!= UNIT_CHECK
) {
1076 c
->pam_name
= mfree(c
->pam_name
);
1077 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1080 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1085 } else if (streq(name
, "Environment")) {
1087 _cleanup_strv_free_
char **l
= NULL
;
1089 r
= sd_bus_message_read_strv(message
, &l
);
1093 if (!strv_env_is_valid(l
))
1094 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1096 if (mode
!= UNIT_CHECK
) {
1097 _cleanup_free_
char *joined
= NULL
;
1100 e
= strv_env_merge(2, c
->environment
, l
);
1104 strv_free(c
->environment
);
1107 joined
= strv_join_quoted(c
->environment
);
1111 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1116 } else if (rlimit_from_string(name
) >= 0) {
1120 r
= sd_bus_message_read(message
, "t", &rl
);
1124 if (rl
== (uint64_t) -1)
1129 if ((uint64_t) x
!= rl
)
1133 if (mode
!= UNIT_CHECK
) {
1136 z
= rlimit_from_string(name
);
1138 if (!c
->rlimit
[z
]) {
1139 c
->rlimit
[z
] = new(struct rlimit
, 1);
1144 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1146 if (x
== RLIM_INFINITY
)
1147 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1149 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);