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