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_oom_score_adjust(
89 const char *interface
,
91 sd_bus_message
*reply
,
93 sd_bus_error
*error
) {
96 ExecContext
*c
= userdata
;
103 if (c
->oom_score_adjust_set
)
104 n
= c
->oom_score_adjust
;
106 _cleanup_free_
char *t
= NULL
;
109 if (read_one_line_file("/proc/self/oom_score_adj", &t
) >= 0)
113 return sd_bus_message_append(reply
, "i", n
);
116 static int property_get_nice(
119 const char *interface
,
120 const char *property
,
121 sd_bus_message
*reply
,
123 sd_bus_error
*error
) {
126 ExecContext
*c
= userdata
;
137 n
= getpriority(PRIO_PROCESS
, 0);
142 return sd_bus_message_append(reply
, "i", n
);
145 static int property_get_ioprio(
148 const char *interface
,
149 const char *property
,
150 sd_bus_message
*reply
,
152 sd_bus_error
*error
) {
155 ExecContext
*c
= userdata
;
165 n
= ioprio_get(IOPRIO_WHO_PROCESS
, 0);
167 n
= IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE
, 4);
170 return sd_bus_message_append(reply
, "i", n
);
173 static int property_get_cpu_sched_policy(
176 const char *interface
,
177 const char *property
,
178 sd_bus_message
*reply
,
180 sd_bus_error
*error
) {
182 ExecContext
*c
= userdata
;
189 if (c
->cpu_sched_set
)
190 n
= c
->cpu_sched_policy
;
192 n
= sched_getscheduler(0);
197 return sd_bus_message_append(reply
, "i", n
);
200 static int property_get_cpu_sched_priority(
203 const char *interface
,
204 const char *property
,
205 sd_bus_message
*reply
,
207 sd_bus_error
*error
) {
209 ExecContext
*c
= userdata
;
216 if (c
->cpu_sched_set
)
217 n
= c
->cpu_sched_priority
;
219 struct sched_param p
= {};
221 if (sched_getparam(0, &p
) >= 0)
222 n
= p
.sched_priority
;
227 return sd_bus_message_append(reply
, "i", n
);
230 static int property_get_cpu_affinity(
233 const char *interface
,
234 const char *property
,
235 sd_bus_message
*reply
,
237 sd_bus_error
*error
) {
239 ExecContext
*c
= userdata
;
246 return sd_bus_message_append_array(reply
, 'y', c
->cpuset
, CPU_ALLOC_SIZE(c
->cpuset_ncpus
));
248 return sd_bus_message_append_array(reply
, 'y', NULL
, 0);
251 static int property_get_timer_slack_nsec(
254 const char *interface
,
255 const char *property
,
256 sd_bus_message
*reply
,
258 sd_bus_error
*error
) {
260 ExecContext
*c
= userdata
;
267 if (c
->timer_slack_nsec
!= NSEC_INFINITY
)
268 u
= (uint64_t) c
->timer_slack_nsec
;
270 u
= (uint64_t) prctl(PR_GET_TIMERSLACK
);
272 return sd_bus_message_append(reply
, "t", u
);
275 static int property_get_capability_bounding_set(
278 const char *interface
,
279 const char *property
,
280 sd_bus_message
*reply
,
282 sd_bus_error
*error
) {
284 ExecContext
*c
= userdata
;
290 /* We store this negated internally, to match the kernel, but
291 * we expose it normalized. */
292 return sd_bus_message_append(reply
, "t", ~c
->capability_bounding_set_drop
);
295 static int property_get_capabilities(
298 const char *interface
,
299 const char *property
,
300 sd_bus_message
*reply
,
302 sd_bus_error
*error
) {
304 ExecContext
*c
= userdata
;
305 _cleanup_cap_free_charp_
char *t
= NULL
;
313 s
= t
= cap_to_text(c
->capabilities
, NULL
);
320 return sd_bus_message_append(reply
, "s", s
);
323 static int property_get_syscall_filter(
326 const char *interface
,
327 const char *property
,
328 sd_bus_message
*reply
,
330 sd_bus_error
*error
) {
332 ExecContext
*c
= userdata
;
333 _cleanup_strv_free_
char **l
= NULL
;
345 r
= sd_bus_message_open_container(reply
, 'r', "bas");
349 r
= sd_bus_message_append(reply
, "b", c
->syscall_whitelist
);
354 SET_FOREACH(id
, c
->syscall_filter
, i
) {
357 name
= seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE
, PTR_TO_INT(id
) - 1);
361 r
= strv_consume(&l
, name
);
369 r
= sd_bus_message_append_strv(reply
, l
);
373 return sd_bus_message_close_container(reply
);
376 static int property_get_syscall_archs(
379 const char *interface
,
380 const char *property
,
381 sd_bus_message
*reply
,
383 sd_bus_error
*error
) {
385 ExecContext
*c
= userdata
;
386 _cleanup_strv_free_
char **l
= NULL
;
399 SET_FOREACH(id
, c
->syscall_archs
, i
) {
402 name
= seccomp_arch_to_string(PTR_TO_UINT32(id
) - 1);
406 r
= strv_extend(&l
, name
);
414 r
= sd_bus_message_append_strv(reply
, l
);
421 static int property_get_syscall_errno(
424 const char *interface
,
425 const char *property
,
426 sd_bus_message
*reply
,
428 sd_bus_error
*error
) {
430 ExecContext
*c
= userdata
;
436 return sd_bus_message_append(reply
, "i", (int32_t) c
->syscall_errno
);
439 static int property_get_selinux_context(
442 const char *interface
,
443 const char *property
,
444 sd_bus_message
*reply
,
446 sd_bus_error
*error
) {
448 ExecContext
*c
= userdata
;
454 return sd_bus_message_append(reply
, "(bs)", c
->selinux_context_ignore
, c
->selinux_context
);
457 static int property_get_apparmor_profile(
460 const char *interface
,
461 const char *property
,
462 sd_bus_message
*reply
,
464 sd_bus_error
*error
) {
466 ExecContext
*c
= userdata
;
472 return sd_bus_message_append(reply
, "(bs)", c
->apparmor_profile_ignore
, c
->apparmor_profile
);
475 static int property_get_smack_process_label(
478 const char *interface
,
479 const char *property
,
480 sd_bus_message
*reply
,
482 sd_bus_error
*error
) {
484 ExecContext
*c
= userdata
;
490 return sd_bus_message_append(reply
, "(bs)", c
->smack_process_label_ignore
, c
->smack_process_label
);
493 static int property_get_personality(
496 const char *interface
,
497 const char *property
,
498 sd_bus_message
*reply
,
500 sd_bus_error
*error
) {
502 ExecContext
*c
= userdata
;
508 return sd_bus_message_append(reply
, "s", personality_to_string(c
->personality
));
511 static int property_get_address_families(
514 const char *interface
,
515 const char *property
,
516 sd_bus_message
*reply
,
518 sd_bus_error
*error
) {
520 ExecContext
*c
= userdata
;
521 _cleanup_strv_free_
char **l
= NULL
;
530 r
= sd_bus_message_open_container(reply
, 'r', "bas");
534 r
= sd_bus_message_append(reply
, "b", c
->address_families_whitelist
);
538 SET_FOREACH(af
, c
->address_families
, i
) {
541 name
= af_to_name(PTR_TO_INT(af
));
545 r
= strv_extend(&l
, name
);
552 r
= sd_bus_message_append_strv(reply
, l
);
556 return sd_bus_message_close_container(reply
);
559 static int property_get_working_directory(
562 const char *interface
,
563 const char *property
,
564 sd_bus_message
*reply
,
566 sd_bus_error
*error
) {
568 ExecContext
*c
= userdata
;
575 if (c
->working_directory_home
)
578 wd
= c
->working_directory
;
580 if (c
->working_directory_missing_ok
)
581 wd
= strjoina("!", wd
);
583 return sd_bus_message_append(reply
, "s", wd
);
586 static int property_get_syslog_level(
589 const char *interface
,
590 const char *property
,
591 sd_bus_message
*reply
,
593 sd_bus_error
*error
) {
595 ExecContext
*c
= userdata
;
601 return sd_bus_message_append(reply
, "i", LOG_PRI(c
->syslog_priority
));
604 static int property_get_syslog_facility(
607 const char *interface
,
608 const char *property
,
609 sd_bus_message
*reply
,
611 sd_bus_error
*error
) {
613 ExecContext
*c
= userdata
;
619 return sd_bus_message_append(reply
, "i", LOG_FAC(c
->syslog_priority
));
622 const sd_bus_vtable bus_exec_vtable
[] = {
623 SD_BUS_VTABLE_START(0),
624 SD_BUS_PROPERTY("Environment", "as", NULL
, offsetof(ExecContext
, environment
), SD_BUS_VTABLE_PROPERTY_CONST
),
625 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
626 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode
, offsetof(ExecContext
, umask
), SD_BUS_VTABLE_PROPERTY_CONST
),
627 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CPU
]), SD_BUS_VTABLE_PROPERTY_CONST
),
628 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_FSIZE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
629 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_DATA
]), SD_BUS_VTABLE_PROPERTY_CONST
),
630 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_STACK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
631 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_CORE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
632 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RSS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
633 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NOFILE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
634 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_AS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
635 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NPROC
]), SD_BUS_VTABLE_PROPERTY_CONST
),
636 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MEMLOCK
]), SD_BUS_VTABLE_PROPERTY_CONST
),
637 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_LOCKS
]), SD_BUS_VTABLE_PROPERTY_CONST
),
638 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_SIGPENDING
]), SD_BUS_VTABLE_PROPERTY_CONST
),
639 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_MSGQUEUE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
640 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_NICE
]), SD_BUS_VTABLE_PROPERTY_CONST
),
641 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTPRIO
]), SD_BUS_VTABLE_PROPERTY_CONST
),
642 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit
, offsetof(ExecContext
, rlimit
[RLIMIT_RTTIME
]), SD_BUS_VTABLE_PROPERTY_CONST
),
643 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
644 SD_BUS_PROPERTY("RootDirectory", "s", NULL
, offsetof(ExecContext
, root_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
645 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
646 SD_BUS_PROPERTY("Nice", "i", property_get_nice
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
647 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
648 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
649 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
650 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
651 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
652 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool
, offsetof(ExecContext
, cpu_sched_reset_on_fork
), SD_BUS_VTABLE_PROPERTY_CONST
),
653 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool
, offsetof(ExecContext
, non_blocking
), SD_BUS_VTABLE_PROPERTY_CONST
),
654 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input
, offsetof(ExecContext
, std_input
), SD_BUS_VTABLE_PROPERTY_CONST
),
655 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_output
), SD_BUS_VTABLE_PROPERTY_CONST
),
656 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output
, offsetof(ExecContext
, std_error
), SD_BUS_VTABLE_PROPERTY_CONST
),
657 SD_BUS_PROPERTY("TTYPath", "s", NULL
, offsetof(ExecContext
, tty_path
), SD_BUS_VTABLE_PROPERTY_CONST
),
658 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_reset
), SD_BUS_VTABLE_PROPERTY_CONST
),
659 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vhangup
), SD_BUS_VTABLE_PROPERTY_CONST
),
660 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool
, offsetof(ExecContext
, tty_vt_disallocate
), SD_BUS_VTABLE_PROPERTY_CONST
),
661 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int
, offsetof(ExecContext
, syslog_priority
), SD_BUS_VTABLE_PROPERTY_CONST
),
662 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL
, offsetof(ExecContext
, syslog_identifier
), SD_BUS_VTABLE_PROPERTY_CONST
),
663 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool
, offsetof(ExecContext
, syslog_level_prefix
), SD_BUS_VTABLE_PROPERTY_CONST
),
664 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
665 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
666 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
667 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int
, offsetof(ExecContext
, secure_bits
), SD_BUS_VTABLE_PROPERTY_CONST
),
668 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
669 SD_BUS_PROPERTY("User", "s", NULL
, offsetof(ExecContext
, user
), SD_BUS_VTABLE_PROPERTY_CONST
),
670 SD_BUS_PROPERTY("Group", "s", NULL
, offsetof(ExecContext
, group
), SD_BUS_VTABLE_PROPERTY_CONST
),
671 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL
, offsetof(ExecContext
, supplementary_groups
), SD_BUS_VTABLE_PROPERTY_CONST
),
672 SD_BUS_PROPERTY("PAMName", "s", NULL
, offsetof(ExecContext
, pam_name
), SD_BUS_VTABLE_PROPERTY_CONST
),
673 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL
, offsetof(ExecContext
, read_write_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
674 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL
, offsetof(ExecContext
, read_only_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
675 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL
, offsetof(ExecContext
, inaccessible_dirs
), SD_BUS_VTABLE_PROPERTY_CONST
),
676 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong
, offsetof(ExecContext
, mount_flags
), SD_BUS_VTABLE_PROPERTY_CONST
),
677 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool
, offsetof(ExecContext
, private_tmp
), SD_BUS_VTABLE_PROPERTY_CONST
),
678 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool
, offsetof(ExecContext
, private_network
), SD_BUS_VTABLE_PROPERTY_CONST
),
679 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool
, offsetof(ExecContext
, private_devices
), SD_BUS_VTABLE_PROPERTY_CONST
),
680 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home
, offsetof(ExecContext
, protect_home
), SD_BUS_VTABLE_PROPERTY_CONST
),
681 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system
, offsetof(ExecContext
, protect_system
), SD_BUS_VTABLE_PROPERTY_CONST
),
682 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool
, offsetof(ExecContext
, same_pgrp
), SD_BUS_VTABLE_PROPERTY_CONST
),
683 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL
, offsetof(ExecContext
, utmp_id
), SD_BUS_VTABLE_PROPERTY_CONST
),
684 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode
, offsetof(ExecContext
, utmp_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
685 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
686 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
687 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
688 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool
, offsetof(ExecContext
, ignore_sigpipe
), SD_BUS_VTABLE_PROPERTY_CONST
),
689 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool
, offsetof(ExecContext
, no_new_privileges
), SD_BUS_VTABLE_PROPERTY_CONST
),
690 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
691 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
692 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
693 SD_BUS_PROPERTY("Personality", "s", property_get_personality
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
694 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families
, 0, SD_BUS_VTABLE_PROPERTY_CONST
),
695 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode
, offsetof(ExecContext
, runtime_directory_mode
), SD_BUS_VTABLE_PROPERTY_CONST
),
696 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL
, offsetof(ExecContext
, runtime_directory
), SD_BUS_VTABLE_PROPERTY_CONST
),
700 static int append_exec_command(sd_bus_message
*reply
, ExecCommand
*c
) {
709 r
= sd_bus_message_open_container(reply
, 'r', "sasbttttuii");
713 r
= sd_bus_message_append(reply
, "s", c
->path
);
717 r
= sd_bus_message_append_strv(reply
, c
->argv
);
721 r
= sd_bus_message_append(reply
, "bttttuii",
723 c
->exec_status
.start_timestamp
.realtime
,
724 c
->exec_status
.start_timestamp
.monotonic
,
725 c
->exec_status
.exit_timestamp
.realtime
,
726 c
->exec_status
.exit_timestamp
.monotonic
,
727 (uint32_t) c
->exec_status
.pid
,
728 (int32_t) c
->exec_status
.code
,
729 (int32_t) c
->exec_status
.status
);
733 return sd_bus_message_close_container(reply
);
736 int bus_property_get_exec_command(
739 const char *interface
,
740 const char *property
,
741 sd_bus_message
*reply
,
743 sd_bus_error
*ret_error
) {
745 ExecCommand
*c
= (ExecCommand
*) userdata
;
751 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
755 r
= append_exec_command(reply
, c
);
759 return sd_bus_message_close_container(reply
);
762 int bus_property_get_exec_command_list(
765 const char *interface
,
766 const char *property
,
767 sd_bus_message
*reply
,
769 sd_bus_error
*ret_error
) {
771 ExecCommand
*c
= *(ExecCommand
**) userdata
;
777 r
= sd_bus_message_open_container(reply
, 'a', "(sasbttttuii)");
781 LIST_FOREACH(command
, c
, c
) {
782 r
= append_exec_command(reply
, c
);
787 return sd_bus_message_close_container(reply
);
790 int bus_exec_context_set_transient_property(
794 sd_bus_message
*message
,
795 UnitSetPropertiesMode mode
,
796 sd_bus_error
*error
) {
805 if (streq(name
, "User")) {
808 r
= sd_bus_message_read(message
, "s", &uu
);
812 if (mode
!= UNIT_CHECK
) {
815 c
->user
= mfree(c
->user
);
827 unit_write_drop_in_private_format(u
, mode
, name
, "User=%s\n", uu
);
832 } else if (streq(name
, "Group")) {
835 r
= sd_bus_message_read(message
, "s", &gg
);
839 if (mode
!= UNIT_CHECK
) {
842 c
->group
= mfree(c
->group
);
854 unit_write_drop_in_private_format(u
, mode
, name
, "Group=%s\n", gg
);
858 } else if (streq(name
, "SyslogIdentifier")) {
861 r
= sd_bus_message_read(message
, "s", &id
);
865 if (mode
!= UNIT_CHECK
) {
868 c
->syslog_identifier
= mfree(c
->syslog_identifier
);
876 free(c
->syslog_identifier
);
877 c
->syslog_identifier
= t
;
880 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogIdentifier=%s\n", id
);
884 } else if (streq(name
, "SyslogLevel")) {
887 r
= sd_bus_message_read(message
, "i", &level
);
891 if (!log_level_is_valid(level
))
892 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log level value out of range");
894 if (mode
!= UNIT_CHECK
) {
895 c
->syslog_priority
= (c
->syslog_priority
& LOG_FACMASK
) | level
;
896 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogLevel=%i\n", level
);
900 } else if (streq(name
, "SyslogFacility")) {
903 r
= sd_bus_message_read(message
, "i", &facility
);
907 if (!log_facility_unshifted_is_valid(facility
))
908 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Log facility value out of range");
910 if (mode
!= UNIT_CHECK
) {
911 c
->syslog_priority
= (facility
<< 3) | LOG_PRI(c
->syslog_priority
);
912 unit_write_drop_in_private_format(u
, mode
, name
, "SyslogFacility=%i\n", facility
);
916 } else if (streq(name
, "Nice")) {
919 r
= sd_bus_message_read(message
, "i", &n
);
923 if (n
< PRIO_MIN
|| n
>= PRIO_MAX
)
924 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Nice value out of range");
926 if (mode
!= UNIT_CHECK
) {
928 unit_write_drop_in_private_format(u
, mode
, name
, "Nice=%i\n", n
);
933 } else if (STR_IN_SET(name
, "TTYPath", "RootDirectory")) {
936 r
= sd_bus_message_read(message
, "s", &s
);
940 if (!path_is_absolute(s
))
941 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "%s takes an absolute path", name
);
943 if (mode
!= UNIT_CHECK
) {
944 if (streq(name
, "TTYPath"))
945 r
= free_and_strdup(&c
->tty_path
, s
);
947 assert(streq(name
, "RootDirectory"));
948 r
= free_and_strdup(&c
->root_directory
, s
);
953 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, s
);
958 } else if (streq(name
, "WorkingDirectory")) {
962 r
= sd_bus_message_read(message
, "s", &s
);
972 if (!streq(s
, "~") && !path_is_absolute(s
))
973 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "WorkingDirectory= expects an absolute path or '~'");
975 if (mode
!= UNIT_CHECK
) {
977 c
->working_directory
= mfree(c
->working_directory
);
978 c
->working_directory_home
= true;
980 r
= free_and_strdup(&c
->working_directory
, s
);
984 c
->working_directory_home
= false;
987 c
->working_directory_missing_ok
= missing_ok
;
988 unit_write_drop_in_private_format(u
, mode
, name
, "WorkingDirectory=%s%s", missing_ok
? "-" : "", s
);
993 } else if (streq(name
, "StandardInput")) {
997 r
= sd_bus_message_read(message
, "s", &s
);
1001 p
= exec_input_from_string(s
);
1003 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard input name");
1005 if (mode
!= UNIT_CHECK
) {
1008 unit_write_drop_in_private_format(u
, mode
, name
, "StandardInput=%s\n", exec_input_to_string(p
));
1014 } else if (streq(name
, "StandardOutput")) {
1018 r
= sd_bus_message_read(message
, "s", &s
);
1022 p
= exec_output_from_string(s
);
1024 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard output name");
1026 if (mode
!= UNIT_CHECK
) {
1029 unit_write_drop_in_private_format(u
, mode
, name
, "StandardOutput=%s\n", exec_output_to_string(p
));
1034 } else if (streq(name
, "StandardError")) {
1038 r
= sd_bus_message_read(message
, "s", &s
);
1042 p
= exec_output_from_string(s
);
1044 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid standard error name");
1046 if (mode
!= UNIT_CHECK
) {
1049 unit_write_drop_in_private_format(u
, mode
, name
, "StandardError=%s\n", exec_output_to_string(p
));
1054 } else if (STR_IN_SET(name
,
1055 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1056 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
1057 "NoNewPrivileges", "SyslogLevelPrefix")) {
1060 r
= sd_bus_message_read(message
, "b", &b
);
1064 if (mode
!= UNIT_CHECK
) {
1065 if (streq(name
, "IgnoreSIGPIPE"))
1066 c
->ignore_sigpipe
= b
;
1067 else if (streq(name
, "TTYVHangup"))
1069 else if (streq(name
, "TTYReset"))
1071 else if (streq(name
, "PrivateTmp"))
1073 else if (streq(name
, "PrivateDevices"))
1074 c
->private_devices
= b
;
1075 else if (streq(name
, "PrivateNetwork"))
1076 c
->private_network
= b
;
1077 else if (streq(name
, "NoNewPrivileges"))
1078 c
->no_new_privileges
= b
;
1079 else if (streq(name
, "SyslogLevelPrefix"))
1080 c
->syslog_level_prefix
= b
;
1082 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%s\n", name
, yes_no(b
));
1087 } else if (streq(name
, "UtmpIdentifier")) {
1090 r
= sd_bus_message_read(message
, "s", &id
);
1094 if (mode
!= UNIT_CHECK
) {
1096 c
->utmp_id
= mfree(c
->utmp_id
);
1097 else if (free_and_strdup(&c
->utmp_id
, id
) < 0)
1100 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpIdentifier=%s\n", strempty(id
));
1105 } else if (streq(name
, "UtmpMode")) {
1109 r
= sd_bus_message_read(message
, "s", &s
);
1113 m
= exec_utmp_mode_from_string(s
);
1115 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid utmp mode");
1117 if (mode
!= UNIT_CHECK
) {
1120 unit_write_drop_in_private_format(u
, mode
, name
, "UtmpMode=%s\n", exec_utmp_mode_to_string(m
));
1125 } else if (streq(name
, "PAMName")) {
1128 r
= sd_bus_message_read(message
, "s", &n
);
1132 if (mode
!= UNIT_CHECK
) {
1134 c
->pam_name
= mfree(c
->pam_name
);
1135 else if (free_and_strdup(&c
->pam_name
, n
) < 0)
1138 unit_write_drop_in_private_format(u
, mode
, name
, "PAMName=%s\n", strempty(n
));
1143 } else if (streq(name
, "Environment")) {
1145 _cleanup_strv_free_
char **l
= NULL
;
1147 r
= sd_bus_message_read_strv(message
, &l
);
1151 if (!strv_env_is_valid(l
))
1152 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "Invalid environment block.");
1154 if (mode
!= UNIT_CHECK
) {
1155 _cleanup_free_
char *joined
= NULL
;
1158 e
= strv_env_merge(2, c
->environment
, l
);
1162 strv_free(c
->environment
);
1165 joined
= strv_join_quoted(c
->environment
);
1169 unit_write_drop_in_private_format(u
, mode
, name
, "Environment=%s\n", joined
);
1174 } else if (streq(name
, "TimerSlackNSec")) {
1178 r
= sd_bus_message_read(message
, "t", &n
);
1182 if (mode
!= UNIT_CHECK
) {
1183 c
->timer_slack_nsec
= n
;
1184 unit_write_drop_in_private_format(u
, mode
, name
, "TimerSlackNSec=" NSEC_FMT
"\n", n
);
1189 } else if (streq(name
, "OOMScoreAdjust")) {
1192 r
= sd_bus_message_read(message
, "i", &oa
);
1196 if (!oom_score_adjust_is_valid(oa
))
1197 return sd_bus_error_setf(error
, SD_BUS_ERROR_INVALID_ARGS
, "OOM score adjust value out of range");
1199 if (mode
!= UNIT_CHECK
) {
1200 c
->oom_score_adjust
= oa
;
1201 c
->oom_score_adjust_set
= true;
1202 unit_write_drop_in_private_format(u
, mode
, name
, "OOMScoreAdjust=%i\n", oa
);
1207 } else if (rlimit_from_string(name
) >= 0) {
1211 r
= sd_bus_message_read(message
, "t", &rl
);
1215 if (rl
== (uint64_t) -1)
1220 if ((uint64_t) x
!= rl
)
1224 if (mode
!= UNIT_CHECK
) {
1227 z
= rlimit_from_string(name
);
1229 if (!c
->rlimit
[z
]) {
1230 c
->rlimit
[z
] = new(struct rlimit
, 1);
1235 c
->rlimit
[z
]->rlim_cur
= c
->rlimit
[z
]->rlim_max
= x
;
1237 if (x
== RLIM_INFINITY
)
1238 unit_write_drop_in_private_format(u
, mode
, name
, "%s=infinity\n", name
);
1240 unit_write_drop_in_private_format(u
, mode
, name
, "%s=%" PRIu64
"\n", name
, rl
);