]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
syscallfilter: port to libseccomp
[thirdparty/systemd.git] / src / core / dbus-execute.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4139c1b2
LP
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
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
4139c1b2
LP
11 (at your option) any later version.
12
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
5430f7f2 16 Lesser General Public License for more details.
4139c1b2 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
4139c1b2
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
82c121a4 22#include <sys/prctl.h>
4139c1b2 23
718db961 24#include "bus-util.h"
82c121a4
LP
25#include "missing.h"
26#include "ioprio.h"
fe68089d 27#include "strv.h"
a5c32cff 28#include "fileio.h"
718db961
LP
29#include "execute.h"
30#include "dbus-execute.h"
5ce70e5b 31#include "capability.h"
c7040b5d 32#include "env-util.h"
4139c1b2 33
718db961 34BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 35
718db961 36static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 37
718db961
LP
38static int property_get_environment_files(
39 sd_bus *bus,
40 const char *path,
41 const char *interface,
42 const char *property,
43 sd_bus_message *reply,
ebcf1f97
LP
44 void *userdata,
45 sd_bus_error *error) {
8c7be95e 46
718db961
LP
47 ExecContext *c = userdata;
48 char **j;
49 int r;
8c7be95e 50
718db961
LP
51 assert(bus);
52 assert(reply);
53 assert(c);
54
55 r = sd_bus_message_open_container(reply, 'a', "(sb)");
56 if (r < 0)
57 return r;
8c7be95e 58
718db961
LP
59 STRV_FOREACH(j, c->environment_files) {
60 const char *fn = *j;
8c7be95e 61
718db961
LP
62 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
63 if (r < 0)
64 return r;
8c7be95e
LP
65 }
66
718db961
LP
67 return sd_bus_message_close_container(reply);
68}
69
70static int property_get_rlimit(
71 sd_bus *bus,
72 const char *path,
73 const char *interface,
74 const char *property,
75 sd_bus_message *reply,
ebcf1f97
LP
76 void *userdata,
77 sd_bus_error *error) {
718db961
LP
78
79 struct rlimit *rl;
80 uint64_t u;
81
82 assert(bus);
83 assert(reply);
84 assert(userdata);
8c7be95e 85
718db961
LP
86 rl = *(struct rlimit**) userdata;
87 if (rl)
88 u = (uint64_t) rl->rlim_max;
89 else {
90 struct rlimit buf = {};
91 int z;
92
93 z = rlimit_from_string(property);
94 assert(z >= 0);
95
96 getrlimit(z, &buf);
97
98 u = (uint64_t) buf.rlim_max;
99 }
100
101 return sd_bus_message_append(reply, "t", u);
8c7be95e
LP
102}
103
718db961
LP
104static int property_get_oom_score_adjust(
105 sd_bus *bus,
106 const char *path,
107 const char *interface,
108 const char *property,
109 sd_bus_message *reply,
ebcf1f97
LP
110 void *userdata,
111 sd_bus_error *error) {
718db961
LP
112
113
114 ExecContext *c = userdata;
82c121a4
LP
115 int32_t n;
116
718db961
LP
117 assert(bus);
118 assert(reply);
82c121a4
LP
119 assert(c);
120
dd6c17b1
LP
121 if (c->oom_score_adjust_set)
122 n = c->oom_score_adjust;
82c121a4 123 else {
68eda4bd 124 _cleanup_free_ char *t = NULL;
82c121a4
LP
125
126 n = 0;
718db961 127 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
82c121a4 128 safe_atoi(t, &n);
82c121a4
LP
129 }
130
718db961 131 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
132}
133
718db961
LP
134static int property_get_nice(
135 sd_bus *bus,
136 const char *path,
137 const char *interface,
138 const char *property,
139 sd_bus_message *reply,
ebcf1f97
LP
140 void *userdata,
141 sd_bus_error *error) {
718db961
LP
142
143
144 ExecContext *c = userdata;
82c121a4
LP
145 int32_t n;
146
718db961
LP
147 assert(bus);
148 assert(reply);
82c121a4
LP
149 assert(c);
150
151 if (c->nice_set)
152 n = c->nice;
718db961
LP
153 else {
154 errno = 0;
82c121a4 155 n = getpriority(PRIO_PROCESS, 0);
718db961
LP
156 if (errno != 0)
157 n = 0;
158 }
82c121a4 159
718db961 160 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
161}
162
718db961
LP
163static int property_get_ioprio(
164 sd_bus *bus,
165 const char *path,
166 const char *interface,
167 const char *property,
168 sd_bus_message *reply,
ebcf1f97
LP
169 void *userdata,
170 sd_bus_error *error) {
718db961
LP
171
172
173 ExecContext *c = userdata;
82c121a4
LP
174 int32_t n;
175
718db961
LP
176 assert(bus);
177 assert(reply);
82c121a4
LP
178 assert(c);
179
180 if (c->ioprio_set)
181 n = c->ioprio;
718db961 182 else {
82c121a4 183 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
718db961
LP
184 if (n < 0)
185 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
186 }
82c121a4 187
718db961 188 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
189}
190
718db961
LP
191static int property_get_cpu_sched_policy(
192 sd_bus *bus,
193 const char *path,
194 const char *interface,
195 const char *property,
196 sd_bus_message *reply,
ebcf1f97
LP
197 void *userdata,
198 sd_bus_error *error) {
718db961
LP
199
200 ExecContext *c = userdata;
82c121a4
LP
201 int32_t n;
202
718db961
LP
203 assert(bus);
204 assert(reply);
82c121a4
LP
205 assert(c);
206
207 if (c->cpu_sched_set)
208 n = c->cpu_sched_policy;
718db961 209 else {
82c121a4 210 n = sched_getscheduler(0);
718db961
LP
211 if (n < 0)
212 n = SCHED_OTHER;
213 }
82c121a4 214
718db961 215 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
216}
217
718db961
LP
218static int property_get_cpu_sched_priority(
219 sd_bus *bus,
220 const char *path,
221 const char *interface,
222 const char *property,
223 sd_bus_message *reply,
ebcf1f97
LP
224 void *userdata,
225 sd_bus_error *error) {
718db961
LP
226
227 ExecContext *c = userdata;
82c121a4
LP
228 int32_t n;
229
718db961
LP
230 assert(bus);
231 assert(reply);
82c121a4
LP
232 assert(c);
233
234 if (c->cpu_sched_set)
235 n = c->cpu_sched_priority;
236 else {
b92bea5d 237 struct sched_param p = {};
82c121a4 238
82c121a4
LP
239 if (sched_getparam(0, &p) >= 0)
240 n = p.sched_priority;
e62d8c39
ZJS
241 else
242 n = 0;
82c121a4
LP
243 }
244
718db961 245 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
246}
247
718db961
LP
248static int property_get_cpu_affinity(
249 sd_bus *bus,
250 const char *path,
251 const char *interface,
252 const char *property,
253 sd_bus_message *reply,
ebcf1f97
LP
254 void *userdata,
255 sd_bus_error *error) {
82c121a4 256
718db961 257 ExecContext *c = userdata;
82c121a4 258
718db961
LP
259 assert(bus);
260 assert(reply);
261 assert(c);
82c121a4
LP
262
263 if (c->cpuset)
718db961 264 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 265 else
718db961 266 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
267}
268
718db961
LP
269static int property_get_timer_slack_nsec(
270 sd_bus *bus,
271 const char *path,
272 const char *interface,
273 const char *property,
274 sd_bus_message *reply,
ebcf1f97
LP
275 void *userdata,
276 sd_bus_error *error) {
718db961
LP
277
278 ExecContext *c = userdata;
82c121a4
LP
279 uint64_t u;
280
718db961
LP
281 assert(bus);
282 assert(reply);
82c121a4
LP
283 assert(c);
284
d88a251b 285 if (c->timer_slack_nsec != (nsec_t) -1)
03fae018 286 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
287 else
288 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
289
718db961 290 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
291}
292
718db961
LP
293static int property_get_capability_bounding_set(
294 sd_bus *bus,
295 const char *path,
296 const char *interface,
297 const char *property,
298 sd_bus_message *reply,
ebcf1f97
LP
299 void *userdata,
300 sd_bus_error *error) {
260abb78 301
718db961
LP
302 ExecContext *c = userdata;
303
304 assert(bus);
305 assert(reply);
260abb78
LP
306 assert(c);
307
7c3d67ef 308 /* We store this negated internally, to match the kernel, but
260abb78 309 * we expose it normalized. */
718db961 310 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
260abb78
LP
311}
312
718db961
LP
313static int property_get_capabilities(
314 sd_bus *bus,
315 const char *path,
316 const char *interface,
317 const char *property,
318 sd_bus_message *reply,
ebcf1f97
LP
319 void *userdata,
320 sd_bus_error *error) {
718db961
LP
321
322 ExecContext *c = userdata;
5ce70e5b 323 _cleanup_cap_free_charp_ char *t = NULL;
82c121a4 324 const char *s;
82c121a4 325
718db961
LP
326 assert(bus);
327 assert(reply);
82c121a4
LP
328 assert(c);
329
330 if (c->capabilities)
331 s = t = cap_to_text(c->capabilities, NULL);
332 else
333 s = "";
334
674cdd19 335 if (!s)
82c121a4
LP
336 return -ENOMEM;
337
5ce70e5b 338 return sd_bus_message_append(reply, "s", s);
82c121a4
LP
339}
340
718db961
LP
341static int property_get_syscall_filter(
342 sd_bus *bus,
343 const char *path,
344 const char *interface,
345 const char *property,
346 sd_bus_message *reply,
ebcf1f97
LP
347 void *userdata,
348 sd_bus_error *error) {
82c121a4 349
718db961 350 ExecContext *c = userdata;
82c121a4 351
718db961
LP
352 assert(bus);
353 assert(reply);
354 assert(c);
82c121a4 355
c0467cf3 356 return sd_bus_message_append(reply, "s", c->syscall_filter_string);
718db961 357}
82c121a4 358
718db961
LP
359const sd_bus_vtable bus_exec_vtable[] = {
360 SD_BUS_VTABLE_START(0),
556089dc
LP
361 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
362 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
363 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
364 SD_BUS_PROPERTY("LimitCPU", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
365 SD_BUS_PROPERTY("LimitFSIZE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
366 SD_BUS_PROPERTY("LimitDATA", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
367 SD_BUS_PROPERTY("LimitSTACK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
368 SD_BUS_PROPERTY("LimitCORE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
369 SD_BUS_PROPERTY("LimitRSS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
370 SD_BUS_PROPERTY("LimitNOFILE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
371 SD_BUS_PROPERTY("LimitAS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
372 SD_BUS_PROPERTY("LimitNPROC", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
373 SD_BUS_PROPERTY("LimitMEMLOCK", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
374 SD_BUS_PROPERTY("LimitLOCKS", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
375 SD_BUS_PROPERTY("LimitSIGPENDING", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
376 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
377 SD_BUS_PROPERTY("LimitNICE", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
378 SD_BUS_PROPERTY("LimitRTPRIO", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
379 SD_BUS_PROPERTY("LimitRTTIME", "t", property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
380 SD_BUS_PROPERTY("WorkingDirectory", "s", NULL, offsetof(ExecContext, working_directory), SD_BUS_VTABLE_PROPERTY_CONST),
381 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
382 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
383 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
384 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
385 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
386 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
387 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
388 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
389 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
390 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
391 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
392 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
393 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
394 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
395 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
396 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
397 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
398 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
399 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
400 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
401 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
402 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
403 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
404 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
405 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
406 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
407 SD_BUS_PROPERTY("TCPWrapName", "s", NULL, offsetof(ExecContext, tcpwrap_name), SD_BUS_VTABLE_PROPERTY_CONST),
408 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
409 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
410 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
411 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
412 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
413 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
414 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 415 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
416 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
417 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
7b52a628 418 SD_BUS_PROPERTY("SELinuxContext", "s", NULL, offsetof(ExecContext, selinux_context), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
419 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
420 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
c0467cf3 421 SD_BUS_PROPERTY("SystemCallFilter", "s", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
422 SD_BUS_VTABLE_END
423};
82c121a4 424
4d4c80d0
LP
425static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
426 int r;
427
428 assert(reply);
429 assert(c);
430
431 if (!c->path)
432 return 0;
433
434 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
435 if (r < 0)
436 return r;
437
438 r = sd_bus_message_append(reply, "s", c->path);
439 if (r < 0)
440 return r;
441
442 r = sd_bus_message_append_strv(reply, c->argv);
443 if (r < 0)
444 return r;
445
446 r = sd_bus_message_append(reply, "bttttuii",
447 c->ignore,
448 c->exec_status.start_timestamp.realtime,
449 c->exec_status.start_timestamp.monotonic,
450 c->exec_status.exit_timestamp.realtime,
451 c->exec_status.exit_timestamp.monotonic,
452 (uint32_t) c->exec_status.pid,
453 (int32_t) c->exec_status.code,
454 (int32_t) c->exec_status.status);
455 if (r < 0)
456 return r;
457
458 return sd_bus_message_close_container(reply);
459}
460
718db961
LP
461int bus_property_get_exec_command(
462 sd_bus *bus,
463 const char *path,
464 const char *interface,
465 const char *property,
466 sd_bus_message *reply,
ebcf1f97
LP
467 void *userdata,
468 sd_bus_error *ret_error) {
fe68089d 469
4d4c80d0 470 ExecCommand *c = (ExecCommand*) userdata;
718db961 471 int r;
fe68089d 472
718db961
LP
473 assert(bus);
474 assert(reply);
fe68089d 475
718db961
LP
476 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
477 if (r < 0)
478 return r;
fe68089d 479
4d4c80d0
LP
480 r = append_exec_command(reply, c);
481 if (r < 0)
482 return r;
fe68089d 483
4d4c80d0
LP
484 return sd_bus_message_close_container(reply);
485}
718db961 486
4d4c80d0
LP
487int bus_property_get_exec_command_list(
488 sd_bus *bus,
489 const char *path,
490 const char *interface,
491 const char *property,
492 sd_bus_message *reply,
493 void *userdata,
494 sd_bus_error *ret_error) {
718db961 495
4d4c80d0
LP
496 ExecCommand *c = *(ExecCommand**) userdata;
497 int r;
718db961 498
4d4c80d0
LP
499 assert(bus);
500 assert(reply);
501
502 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
503 if (r < 0)
504 return r;
718db961 505
4d4c80d0
LP
506 LIST_FOREACH(command, c, c) {
507 r = append_exec_command(reply, c);
718db961
LP
508 if (r < 0)
509 return r;
fe68089d
LP
510 }
511
718db961 512 return sd_bus_message_close_container(reply);
8351ceae 513}
c7040b5d
LP
514
515int bus_exec_context_set_transient_property(
516 Unit *u,
517 ExecContext *c,
518 const char *name,
519 sd_bus_message *message,
520 UnitSetPropertiesMode mode,
521 sd_bus_error *error) {
522
523 int r;
524
525 assert(u);
526 assert(c);
527 assert(name);
528 assert(message);
529
530 if (streq(name, "User")) {
531 const char *uu;
532
533 r = sd_bus_message_read(message, "s", &uu);
534 if (r < 0)
535 return r;
536
537 if (mode != UNIT_CHECK) {
538
539 if (isempty(uu)) {
540 free(c->user);
541 c->user = NULL;
542 } else {
543 char *t;
544
545 t = strdup(uu);
546 if (!t)
547 return -ENOMEM;
548
549 free(c->user);
550 c->user = t;
551 }
552
553 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
554 }
555
556 return 1;
557
558 } else if (streq(name, "Group")) {
559 const char *gg;
560
561 r = sd_bus_message_read(message, "s", &gg);
562 if (r < 0)
563 return r;
564
565 if (mode != UNIT_CHECK) {
566
567 if (isempty(gg)) {
568 free(c->group);
569 c->group = NULL;
570 } else {
571 char *t;
572
573 t = strdup(gg);
574 if (!t)
575 return -ENOMEM;
576
577 free(c->group);
578 c->group = t;
579 }
580
581 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
582 }
583
584 return 1;
585
586 } else if (streq(name, "Nice")) {
587 int n;
588
589 r = sd_bus_message_read(message, "i", &n);
590 if (r < 0)
591 return r;
592
593 if (n < PRIO_MIN || n >= PRIO_MAX)
594 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
595
596 if (mode != UNIT_CHECK) {
597 c->nice = n;
598 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
599 }
600
601 return 1;
602
603 } else if (streq(name, "Environment")) {
604
605 _cleanup_strv_free_ char **l = NULL;
606
607 r = sd_bus_message_read_strv(message, &l);
608 if (r < 0)
609 return r;
610
611 if (!strv_env_is_valid(l))
612 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
613
614 if (mode != UNIT_CHECK) {
1006a62d 615 _cleanup_free_ char *joined = NULL;
c7040b5d
LP
616 char **e;
617
618 e = strv_env_merge(2, c->environment, l);
619 if (!e)
620 return -ENOMEM;
621
622 strv_free(c->environment);
623 c->environment = e;
624
625 joined = strv_join(c->environment, " ");
626 if (!joined)
627 return -ENOMEM;
628
629 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
630 }
631
632 return 1;
633 }
634
635 return 0;
636}