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