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/>.
23 #include <dbus/dbus.h>
24 #include <sys/prctl.h>
26 #include "dbus-execute.h"
30 #include "dbus-common.h"
32 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_kill_mode, kill_mode, KillMode);
34 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_input, exec_input, ExecInput);
35 DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_execute_append_output, exec_output, ExecOutput);
37 int bus_execute_append_env_files(DBusMessageIter *i, const char *property, void *data) {
38 char **env_files = data, **j;
39 DBusMessageIter sub, sub2;
44 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sb)", &sub))
47 STRV_FOREACH(j, env_files) {
48 dbus_bool_t b = false;
56 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
57 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &fn) ||
58 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
59 !dbus_message_iter_close_container(&sub, &sub2))
63 if (!dbus_message_iter_close_container(i, &sub))
69 int bus_execute_append_oom_score_adjust(DBusMessageIter *i, const char *property, void *data) {
70 ExecContext *c = data;
77 if (c->oom_score_adjust_set)
78 n = c->oom_score_adjust;
83 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0) {
86 } else if (read_one_line_file("/proc/self/oom_adj", &t) >= 0) {
90 if (n == OOM_ADJUST_MAX)
91 n = OOM_SCORE_ADJ_MAX;
93 n = (n * OOM_SCORE_ADJ_MAX) / -OOM_DISABLE;
97 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
103 int bus_execute_append_nice(DBusMessageIter *i, const char *property, void *data) {
104 ExecContext *c = data;
114 n = getpriority(PRIO_PROCESS, 0);
116 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
122 int bus_execute_append_ioprio(DBusMessageIter *i, const char *property, void *data) {
123 ExecContext *c = data;
133 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
135 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
141 int bus_execute_append_cpu_sched_policy(DBusMessageIter *i, const char *property, void *data) {
142 ExecContext *c = data;
149 if (c->cpu_sched_set)
150 n = c->cpu_sched_policy;
152 n = sched_getscheduler(0);
154 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
160 int bus_execute_append_cpu_sched_priority(DBusMessageIter *i, const char *property, void *data) {
161 ExecContext *c = data;
168 if (c->cpu_sched_set)
169 n = c->cpu_sched_priority;
171 struct sched_param p;
175 if (sched_getparam(0, &p) >= 0)
176 n = p.sched_priority;
179 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_INT32, &n))
185 int bus_execute_append_affinity(DBusMessageIter *i, const char *property, void *data) {
186 ExecContext *c = data;
194 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "y", &sub))
198 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
200 b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &c->cpuset, 0);
205 if (!dbus_message_iter_close_container(i, &sub))
211 int bus_execute_append_timer_slack_nsec(DBusMessageIter *i, const char *property, void *data) {
212 ExecContext *c = data;
219 if (c->timer_slack_nsec_set)
220 u = (uint64_t) c->timer_slack_nsec;
222 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
224 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
230 int bus_execute_append_capability_bs(DBusMessageIter *i, const char *property, void *data) {
231 ExecContext *c = data;
232 uint64_t normal, inverted;
238 /* We store this negated internally, to match the kernel, but
239 * we expose it normalized. */
241 normal = *(uint64_t*) data;
244 return bus_property_append_uint64(i, property, &inverted);
247 int bus_execute_append_capabilities(DBusMessageIter *i, const char *property, void *data) {
248 ExecContext *c = data;
258 s = t = cap_to_text(c->capabilities, NULL);
265 b = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &s);
276 int bus_execute_append_rlimits(DBusMessageIter *i, const char *property, void *data) {
277 ExecContext *c = data;
285 assert_se((r = rlimit_from_string(property)) >= 0);
288 u = (uint64_t) c->rlimit[r]->rlim_max;
295 u = (uint64_t) rl.rlim_max;
298 if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
304 int bus_execute_append_command(DBusMessageIter *i, const char *property, void *data) {
305 ExecCommand *c = data;
306 DBusMessageIter sub, sub2, sub3;
311 if (!dbus_message_iter_open_container(i, DBUS_TYPE_ARRAY, "(sasbttttuii)", &sub))
314 LIST_FOREACH(command, c, c) {
317 int32_t code, status;
323 if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2) ||
324 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &c->path) ||
325 !dbus_message_iter_open_container(&sub2, DBUS_TYPE_ARRAY, "s", &sub3))
328 STRV_FOREACH(l, c->argv)
329 if (!dbus_message_iter_append_basic(&sub3, DBUS_TYPE_STRING, l))
332 pid = (uint32_t) c->exec_status.pid;
333 code = (int32_t) c->exec_status.code;
334 status = (int32_t) c->exec_status.status;
338 if (!dbus_message_iter_close_container(&sub2, &sub3) ||
339 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_BOOLEAN, &b) ||
340 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.realtime) ||
341 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.start_timestamp.monotonic) ||
342 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.realtime) ||
343 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT64, &c->exec_status.exit_timestamp.monotonic) ||
344 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid) ||
345 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &code) ||
346 !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_INT32, &status))
349 if (!dbus_message_iter_close_container(&sub, &sub2))
353 if (!dbus_message_iter_close_container(i, &sub))
359 const BusProperty bus_exec_context_properties[] = {
360 { "Environment", bus_property_append_strv, "as", offsetof(ExecContext, environment), true },
361 { "EnvironmentFiles", bus_execute_append_env_files, "a(sb)", offsetof(ExecContext, environment_files), true },
362 { "UMask", bus_property_append_mode, "u", offsetof(ExecContext, umask) },
363 { "LimitCPU", bus_execute_append_rlimits, "t", 0 },
364 { "LimitFSIZE", bus_execute_append_rlimits, "t", 0 },
365 { "LimitDATA", bus_execute_append_rlimits, "t", 0 },
366 { "LimitSTACK", bus_execute_append_rlimits, "t", 0 },
367 { "LimitCORE", bus_execute_append_rlimits, "t", 0 },
368 { "LimitRSS", bus_execute_append_rlimits, "t", 0 },
369 { "LimitNOFILE", bus_execute_append_rlimits, "t", 0 },
370 { "LimitAS", bus_execute_append_rlimits, "t", 0 },
371 { "LimitNPROC", bus_execute_append_rlimits, "t", 0 },
372 { "LimitMEMLOCK", bus_execute_append_rlimits, "t", 0 },
373 { "LimitLOCKS", bus_execute_append_rlimits, "t", 0 },
374 { "LimitSIGPENDING", bus_execute_append_rlimits, "t", 0 },
375 { "LimitMSGQUEUE", bus_execute_append_rlimits, "t", 0 },
376 { "LimitNICE", bus_execute_append_rlimits, "t", 0 },
377 { "LimitRTPRIO", bus_execute_append_rlimits, "t", 0 },
378 { "LimitRTTIME", bus_execute_append_rlimits, "t", 0 },
379 { "WorkingDirectory", bus_property_append_string, "s", offsetof(ExecContext, working_directory), true },
380 { "RootDirectory", bus_property_append_string, "s", offsetof(ExecContext, root_directory), true },
381 { "OOMScoreAdjust", bus_execute_append_oom_score_adjust, "i", 0 },
382 { "Nice", bus_execute_append_nice, "i", 0 },
383 { "IOScheduling", bus_execute_append_ioprio, "i", 0 },
384 { "CPUSchedulingPolicy", bus_execute_append_cpu_sched_policy, "i", 0 },
385 { "CPUSchedulingPriority", bus_execute_append_cpu_sched_priority, "i", 0 },
386 { "CPUAffinity", bus_execute_append_affinity, "ay", 0 },
387 { "TimerSlackNSec", bus_execute_append_timer_slack_nsec, "t", 0 },
388 { "CPUSchedulingResetOnFork", bus_property_append_bool, "b", offsetof(ExecContext, cpu_sched_reset_on_fork) },
389 { "NonBlocking", bus_property_append_bool, "b", offsetof(ExecContext, non_blocking) },
390 { "StandardInput", bus_execute_append_input, "s", offsetof(ExecContext, std_input) },
391 { "StandardOutput", bus_execute_append_output, "s", offsetof(ExecContext, std_output) },
392 { "StandardError", bus_execute_append_output, "s", offsetof(ExecContext, std_error) },
393 { "TTYPath", bus_property_append_string, "s", offsetof(ExecContext, tty_path), true },
394 { "TTYReset", bus_property_append_bool, "b", offsetof(ExecContext, tty_reset) },
395 { "TTYVHangup", bus_property_append_bool, "b", offsetof(ExecContext, tty_vhangup) },
396 { "TTYVTDisallocate", bus_property_append_bool, "b", offsetof(ExecContext, tty_vt_disallocate) },
397 { "SyslogPriority", bus_property_append_int, "i", offsetof(ExecContext, syslog_priority) },
398 { "SyslogIdentifier", bus_property_append_string, "s", offsetof(ExecContext, syslog_identifier), true },
399 { "SyslogLevelPrefix", bus_property_append_bool, "b", offsetof(ExecContext, syslog_level_prefix) },
400 { "Capabilities", bus_execute_append_capabilities, "s", 0 },
401 { "SecureBits", bus_property_append_int, "i", offsetof(ExecContext, secure_bits) },
402 { "CapabilityBoundingSet", bus_execute_append_capability_bs, "t", offsetof(ExecContext, capability_bounding_set_drop) },
403 { "User", bus_property_append_string, "s", offsetof(ExecContext, user), true },
404 { "Group", bus_property_append_string, "s", offsetof(ExecContext, group), true },
405 { "SupplementaryGroups", bus_property_append_strv, "as", offsetof(ExecContext, supplementary_groups), true },
406 { "TCPWrapName", bus_property_append_string, "s", offsetof(ExecContext, tcpwrap_name), true },
407 { "PAMName", bus_property_append_string, "s", offsetof(ExecContext, pam_name), true },
408 { "ReadWriteDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_write_dirs), true },
409 { "ReadOnlyDirectories", bus_property_append_strv, "as", offsetof(ExecContext, read_only_dirs), true },
410 { "InaccessibleDirectories", bus_property_append_strv, "as", offsetof(ExecContext, inaccessible_dirs), true },
411 { "MountFlags", bus_property_append_ul, "t", offsetof(ExecContext, mount_flags) },
412 { "PrivateTmp", bus_property_append_bool, "b", offsetof(ExecContext, private_tmp) },
413 { "PrivateNetwork", bus_property_append_bool, "b", offsetof(ExecContext, private_network) },
414 { "SameProcessGroup", bus_property_append_bool, "b", offsetof(ExecContext, same_pgrp) },
415 { "KillMode", bus_execute_append_kill_mode, "s", offsetof(ExecContext, kill_mode) },
416 { "KillSignal", bus_property_append_int, "i", offsetof(ExecContext, kill_signal) },
417 { "UtmpIdentifier", bus_property_append_string, "s", offsetof(ExecContext, utmp_id), true },
418 { "ControlGroupModify", bus_property_append_bool, "b", offsetof(ExecContext, control_group_modify) },
419 { "ControlGroupPersistent", bus_property_append_tristate_false, "b", offsetof(ExecContext, control_group_persistent) },
420 { "IgnoreSIGPIPE", bus_property_append_bool, "b", offsetof(ExecContext, ignore_sigpipe ) },