]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
Merge pull request #1843 from teg/ndisc
[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
57183d11
LP
24#ifdef HAVE_SECCOMP
25#include <seccomp.h>
26#endif
27
3ffd4af2 28#include "af-list.h"
b5efdb8a 29#include "alloc-util.h"
718db961 30#include "bus-util.h"
430f0182 31#include "capability-util.h"
3ffd4af2 32#include "dbus-execute.h"
c7040b5d 33#include "env-util.h"
3ffd4af2
LP
34#include "execute.h"
35#include "fd-util.h"
36#include "fileio.h"
37#include "ioprio.h"
38#include "missing.h"
417116f2 39#include "namespace.h"
6bedfcbb 40#include "parse-util.h"
9b15b784 41#include "path-util.h"
7b3e062c 42#include "process-util.h"
78f22b97 43#include "rlimit-util.h"
57183d11
LP
44#ifdef HAVE_SECCOMP
45#include "seccomp-util.h"
46#endif
6bedfcbb 47#include "strv.h"
7ccbd1ae 48#include "syslog-util.h"
6bedfcbb 49#include "utf8.h"
57183d11 50
718db961 51BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_exec_output, exec_output, ExecOutput);
82c121a4 52
718db961 53static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_input, exec_input, ExecInput);
8c7be95e 54
023a4f67
LP
55static BUS_DEFINE_PROPERTY_GET_ENUM(property_get_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode);
56
1b8689f9
LP
57static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_home, protect_home, ProtectHome);
58static BUS_DEFINE_PROPERTY_GET_ENUM(bus_property_get_protect_system, protect_system, ProtectSystem);
417116f2 59
718db961
LP
60static int property_get_environment_files(
61 sd_bus *bus,
62 const char *path,
63 const char *interface,
64 const char *property,
65 sd_bus_message *reply,
ebcf1f97
LP
66 void *userdata,
67 sd_bus_error *error) {
8c7be95e 68
718db961
LP
69 ExecContext *c = userdata;
70 char **j;
71 int r;
8c7be95e 72
718db961
LP
73 assert(bus);
74 assert(reply);
75 assert(c);
76
77 r = sd_bus_message_open_container(reply, 'a', "(sb)");
78 if (r < 0)
79 return r;
8c7be95e 80
718db961
LP
81 STRV_FOREACH(j, c->environment_files) {
82 const char *fn = *j;
8c7be95e 83
718db961
LP
84 r = sd_bus_message_append(reply, "(sb)", fn[0] == '-' ? fn + 1 : fn, fn[0] == '-');
85 if (r < 0)
86 return r;
8c7be95e
LP
87 }
88
718db961
LP
89 return sd_bus_message_close_container(reply);
90}
91
718db961
LP
92static int property_get_oom_score_adjust(
93 sd_bus *bus,
94 const char *path,
95 const char *interface,
96 const char *property,
97 sd_bus_message *reply,
ebcf1f97
LP
98 void *userdata,
99 sd_bus_error *error) {
718db961
LP
100
101
102 ExecContext *c = userdata;
82c121a4
LP
103 int32_t n;
104
718db961
LP
105 assert(bus);
106 assert(reply);
82c121a4
LP
107 assert(c);
108
dd6c17b1
LP
109 if (c->oom_score_adjust_set)
110 n = c->oom_score_adjust;
82c121a4 111 else {
68eda4bd 112 _cleanup_free_ char *t = NULL;
82c121a4
LP
113
114 n = 0;
718db961 115 if (read_one_line_file("/proc/self/oom_score_adj", &t) >= 0)
e4e73a63 116 safe_atoi32(t, &n);
82c121a4
LP
117 }
118
718db961 119 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
120}
121
718db961
LP
122static int property_get_nice(
123 sd_bus *bus,
124 const char *path,
125 const char *interface,
126 const char *property,
127 sd_bus_message *reply,
ebcf1f97
LP
128 void *userdata,
129 sd_bus_error *error) {
718db961
LP
130
131
132 ExecContext *c = userdata;
82c121a4
LP
133 int32_t n;
134
718db961
LP
135 assert(bus);
136 assert(reply);
82c121a4
LP
137 assert(c);
138
139 if (c->nice_set)
140 n = c->nice;
718db961
LP
141 else {
142 errno = 0;
82c121a4 143 n = getpriority(PRIO_PROCESS, 0);
718db961
LP
144 if (errno != 0)
145 n = 0;
146 }
82c121a4 147
718db961 148 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
149}
150
718db961
LP
151static int property_get_ioprio(
152 sd_bus *bus,
153 const char *path,
154 const char *interface,
155 const char *property,
156 sd_bus_message *reply,
ebcf1f97
LP
157 void *userdata,
158 sd_bus_error *error) {
718db961
LP
159
160
161 ExecContext *c = userdata;
82c121a4
LP
162 int32_t n;
163
718db961
LP
164 assert(bus);
165 assert(reply);
82c121a4
LP
166 assert(c);
167
168 if (c->ioprio_set)
169 n = c->ioprio;
718db961 170 else {
82c121a4 171 n = ioprio_get(IOPRIO_WHO_PROCESS, 0);
718db961
LP
172 if (n < 0)
173 n = IOPRIO_PRIO_VALUE(IOPRIO_CLASS_BE, 4);
174 }
82c121a4 175
718db961 176 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
177}
178
718db961
LP
179static int property_get_cpu_sched_policy(
180 sd_bus *bus,
181 const char *path,
182 const char *interface,
183 const char *property,
184 sd_bus_message *reply,
ebcf1f97
LP
185 void *userdata,
186 sd_bus_error *error) {
718db961
LP
187
188 ExecContext *c = userdata;
82c121a4
LP
189 int32_t n;
190
718db961
LP
191 assert(bus);
192 assert(reply);
82c121a4
LP
193 assert(c);
194
195 if (c->cpu_sched_set)
196 n = c->cpu_sched_policy;
718db961 197 else {
82c121a4 198 n = sched_getscheduler(0);
718db961
LP
199 if (n < 0)
200 n = SCHED_OTHER;
201 }
82c121a4 202
718db961 203 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
204}
205
718db961
LP
206static int property_get_cpu_sched_priority(
207 sd_bus *bus,
208 const char *path,
209 const char *interface,
210 const char *property,
211 sd_bus_message *reply,
ebcf1f97
LP
212 void *userdata,
213 sd_bus_error *error) {
718db961
LP
214
215 ExecContext *c = userdata;
82c121a4
LP
216 int32_t n;
217
718db961
LP
218 assert(bus);
219 assert(reply);
82c121a4
LP
220 assert(c);
221
222 if (c->cpu_sched_set)
223 n = c->cpu_sched_priority;
224 else {
b92bea5d 225 struct sched_param p = {};
82c121a4 226
82c121a4
LP
227 if (sched_getparam(0, &p) >= 0)
228 n = p.sched_priority;
e62d8c39
ZJS
229 else
230 n = 0;
82c121a4
LP
231 }
232
718db961 233 return sd_bus_message_append(reply, "i", n);
82c121a4
LP
234}
235
718db961
LP
236static int property_get_cpu_affinity(
237 sd_bus *bus,
238 const char *path,
239 const char *interface,
240 const char *property,
241 sd_bus_message *reply,
ebcf1f97
LP
242 void *userdata,
243 sd_bus_error *error) {
82c121a4 244
718db961 245 ExecContext *c = userdata;
82c121a4 246
718db961
LP
247 assert(bus);
248 assert(reply);
249 assert(c);
82c121a4
LP
250
251 if (c->cpuset)
718db961 252 return sd_bus_message_append_array(reply, 'y', c->cpuset, CPU_ALLOC_SIZE(c->cpuset_ncpus));
82c121a4 253 else
718db961 254 return sd_bus_message_append_array(reply, 'y', NULL, 0);
82c121a4
LP
255}
256
718db961
LP
257static int property_get_timer_slack_nsec(
258 sd_bus *bus,
259 const char *path,
260 const char *interface,
261 const char *property,
262 sd_bus_message *reply,
ebcf1f97
LP
263 void *userdata,
264 sd_bus_error *error) {
718db961
LP
265
266 ExecContext *c = userdata;
82c121a4
LP
267 uint64_t u;
268
718db961
LP
269 assert(bus);
270 assert(reply);
82c121a4
LP
271 assert(c);
272
3a43da28 273 if (c->timer_slack_nsec != NSEC_INFINITY)
03fae018 274 u = (uint64_t) c->timer_slack_nsec;
82c121a4
LP
275 else
276 u = (uint64_t) prctl(PR_GET_TIMERSLACK);
277
718db961 278 return sd_bus_message_append(reply, "t", u);
82c121a4
LP
279}
280
718db961
LP
281static int property_get_capability_bounding_set(
282 sd_bus *bus,
283 const char *path,
284 const char *interface,
285 const char *property,
286 sd_bus_message *reply,
ebcf1f97
LP
287 void *userdata,
288 sd_bus_error *error) {
260abb78 289
718db961
LP
290 ExecContext *c = userdata;
291
292 assert(bus);
293 assert(reply);
260abb78
LP
294 assert(c);
295
7c3d67ef 296 /* We store this negated internally, to match the kernel, but
260abb78 297 * we expose it normalized. */
718db961 298 return sd_bus_message_append(reply, "t", ~c->capability_bounding_set_drop);
260abb78
LP
299}
300
718db961
LP
301static int property_get_capabilities(
302 sd_bus *bus,
303 const char *path,
304 const char *interface,
305 const char *property,
306 sd_bus_message *reply,
ebcf1f97
LP
307 void *userdata,
308 sd_bus_error *error) {
718db961
LP
309
310 ExecContext *c = userdata;
5ce70e5b 311 _cleanup_cap_free_charp_ char *t = NULL;
82c121a4 312 const char *s;
82c121a4 313
718db961
LP
314 assert(bus);
315 assert(reply);
82c121a4
LP
316 assert(c);
317
318 if (c->capabilities)
319 s = t = cap_to_text(c->capabilities, NULL);
320 else
321 s = "";
322
674cdd19 323 if (!s)
82c121a4
LP
324 return -ENOMEM;
325
5ce70e5b 326 return sd_bus_message_append(reply, "s", s);
82c121a4
LP
327}
328
718db961
LP
329static int property_get_syscall_filter(
330 sd_bus *bus,
331 const char *path,
332 const char *interface,
333 const char *property,
334 sd_bus_message *reply,
ebcf1f97
LP
335 void *userdata,
336 sd_bus_error *error) {
82c121a4 337
17df7223
LP
338 ExecContext *c = userdata;
339 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
340 int r;
341
351a19b1 342#ifdef HAVE_SECCOMP
17df7223
LP
343 Iterator i;
344 void *id;
351a19b1 345#endif
17df7223
LP
346
347 assert(bus);
348 assert(reply);
349 assert(c);
350
57183d11
LP
351 r = sd_bus_message_open_container(reply, 'r', "bas");
352 if (r < 0)
353 return r;
354
355 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
356 if (r < 0)
357 return r;
358
351a19b1 359#ifdef HAVE_SECCOMP
17df7223
LP
360 SET_FOREACH(id, c->syscall_filter, i) {
361 char *name;
362
363 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
364 if (!name)
365 continue;
366
6e18964d
ZJS
367 r = strv_consume(&l, name);
368 if (r < 0)
369 return r;
17df7223 370 }
351a19b1 371#endif
17df7223
LP
372
373 strv_sort(l);
374
57183d11
LP
375 r = sd_bus_message_append_strv(reply, l);
376 if (r < 0)
377 return r;
17df7223 378
57183d11
LP
379 return sd_bus_message_close_container(reply);
380}
17df7223 381
57183d11
LP
382static int property_get_syscall_archs(
383 sd_bus *bus,
384 const char *path,
385 const char *interface,
386 const char *property,
387 sd_bus_message *reply,
388 void *userdata,
389 sd_bus_error *error) {
390
391 ExecContext *c = userdata;
392 _cleanup_strv_free_ char **l = NULL;
393 int r;
394
395#ifdef HAVE_SECCOMP
396 Iterator i;
397 void *id;
398#endif
399
400 assert(bus);
401 assert(reply);
402 assert(c);
17df7223 403
57183d11
LP
404#ifdef HAVE_SECCOMP
405 SET_FOREACH(id, c->syscall_archs, i) {
406 const char *name;
407
408 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
409 if (!name)
410 continue;
411
412 r = strv_extend(&l, name);
413 if (r < 0)
414 return -ENOMEM;
17df7223 415 }
57183d11
LP
416#endif
417
418 strv_sort(l);
419
420 r = sd_bus_message_append_strv(reply, l);
421 if (r < 0)
422 return r;
17df7223 423
57183d11 424 return 0;
17df7223
LP
425}
426
427static int property_get_syscall_errno(
428 sd_bus *bus,
429 const char *path,
430 const char *interface,
431 const char *property,
432 sd_bus_message *reply,
433 void *userdata,
434 sd_bus_error *error) {
435
718db961 436 ExecContext *c = userdata;
82c121a4 437
718db961
LP
438 assert(bus);
439 assert(reply);
440 assert(c);
82c121a4 441
17df7223 442 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 443}
82c121a4 444
5f8640fb
LP
445static int property_get_selinux_context(
446 sd_bus *bus,
447 const char *path,
448 const char *interface,
449 const char *property,
450 sd_bus_message *reply,
451 void *userdata,
452 sd_bus_error *error) {
453
454 ExecContext *c = userdata;
455
456 assert(bus);
457 assert(reply);
458 assert(c);
459
460 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
461}
462
eef65bf3
MS
463static int property_get_apparmor_profile(
464 sd_bus *bus,
465 const char *path,
466 const char *interface,
467 const char *property,
468 sd_bus_message *reply,
469 void *userdata,
470 sd_bus_error *error) {
471
472 ExecContext *c = userdata;
473
474 assert(bus);
475 assert(reply);
476 assert(c);
477
478 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
479}
480
2ca620c4
WC
481static int property_get_smack_process_label(
482 sd_bus *bus,
483 const char *path,
484 const char *interface,
485 const char *property,
486 sd_bus_message *reply,
487 void *userdata,
488 sd_bus_error *error) {
489
490 ExecContext *c = userdata;
491
492 assert(bus);
493 assert(reply);
494 assert(c);
495
496 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
497}
498
ac45f971
LP
499static int property_get_personality(
500 sd_bus *bus,
501 const char *path,
502 const char *interface,
503 const char *property,
504 sd_bus_message *reply,
505 void *userdata,
506 sd_bus_error *error) {
507
508 ExecContext *c = userdata;
509
510 assert(bus);
511 assert(reply);
512 assert(c);
513
514 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
515}
516
4298d0b5
LP
517static int property_get_address_families(
518 sd_bus *bus,
519 const char *path,
520 const char *interface,
521 const char *property,
522 sd_bus_message *reply,
523 void *userdata,
524 sd_bus_error *error) {
525
526 ExecContext *c = userdata;
527 _cleanup_strv_free_ char **l = NULL;
528 Iterator i;
529 void *af;
530 int r;
531
532 assert(bus);
533 assert(reply);
534 assert(c);
535
536 r = sd_bus_message_open_container(reply, 'r', "bas");
537 if (r < 0)
538 return r;
539
540 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
541 if (r < 0)
542 return r;
543
544 SET_FOREACH(af, c->address_families, i) {
545 const char *name;
546
547 name = af_to_name(PTR_TO_INT(af));
548 if (!name)
549 continue;
550
551 r = strv_extend(&l, name);
552 if (r < 0)
553 return -ENOMEM;
554 }
555
556 strv_sort(l);
557
558 r = sd_bus_message_append_strv(reply, l);
559 if (r < 0)
560 return r;
561
562 return sd_bus_message_close_container(reply);
563}
564
5f5d8eab
LP
565static int property_get_working_directory(
566 sd_bus *bus,
567 const char *path,
568 const char *interface,
569 const char *property,
570 sd_bus_message *reply,
571 void *userdata,
572 sd_bus_error *error) {
573
574 ExecContext *c = userdata;
575 const char *wd;
576
577 assert(bus);
578 assert(reply);
579 assert(c);
580
581 if (c->working_directory_home)
582 wd = "~";
583 else
584 wd = c->working_directory;
585
586 if (c->working_directory_missing_ok)
587 wd = strjoina("!", wd);
588
589 return sd_bus_message_append(reply, "s", wd);
590}
591
06f2ccf9
EV
592static int property_get_syslog_level(
593 sd_bus *bus,
594 const char *path,
595 const char *interface,
596 const char *property,
597 sd_bus_message *reply,
598 void *userdata,
599 sd_bus_error *error) {
600
601 ExecContext *c = userdata;
602
603 assert(bus);
604 assert(reply);
605 assert(c);
606
607 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
608}
609
610static int property_get_syslog_facility(
611 sd_bus *bus,
612 const char *path,
613 const char *interface,
614 const char *property,
615 sd_bus_message *reply,
616 void *userdata,
617 sd_bus_error *error) {
618
619 ExecContext *c = userdata;
620
621 assert(bus);
622 assert(reply);
623 assert(c);
624
625 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
626}
627
718db961
LP
628const sd_bus_vtable bus_exec_vtable[] = {
629 SD_BUS_VTABLE_START(0),
556089dc
LP
630 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
631 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
632 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3
EV
633 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
634 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
635 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
636 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
637 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
638 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
639 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
640 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
641 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
642 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
643 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
644 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
645 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
646 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
648 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 649 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
650 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
651 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
652 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
653 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
654 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
655 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
656 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
657 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
658 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
659 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
660 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
661 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
662 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
663 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
664 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
665 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
666 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
667 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
668 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
669 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
670 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
671 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
672 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
673 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
674 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
675 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
676 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
677 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
678 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
679 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
680 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
681 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
682 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
683 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 685 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
686 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
687 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
688 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
689 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 690 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 691 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 692 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 693 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
694 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
695 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
696 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 698 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 699 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 700 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e66cf1a3
LP
701 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
703 SD_BUS_VTABLE_END
704};
82c121a4 705
4d4c80d0
LP
706static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
707 int r;
708
709 assert(reply);
710 assert(c);
711
712 if (!c->path)
713 return 0;
714
715 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
716 if (r < 0)
717 return r;
718
719 r = sd_bus_message_append(reply, "s", c->path);
720 if (r < 0)
721 return r;
722
723 r = sd_bus_message_append_strv(reply, c->argv);
724 if (r < 0)
725 return r;
726
727 r = sd_bus_message_append(reply, "bttttuii",
728 c->ignore,
729 c->exec_status.start_timestamp.realtime,
730 c->exec_status.start_timestamp.monotonic,
731 c->exec_status.exit_timestamp.realtime,
732 c->exec_status.exit_timestamp.monotonic,
733 (uint32_t) c->exec_status.pid,
734 (int32_t) c->exec_status.code,
735 (int32_t) c->exec_status.status);
736 if (r < 0)
737 return r;
738
739 return sd_bus_message_close_container(reply);
740}
741
718db961
LP
742int bus_property_get_exec_command(
743 sd_bus *bus,
744 const char *path,
745 const char *interface,
746 const char *property,
747 sd_bus_message *reply,
ebcf1f97
LP
748 void *userdata,
749 sd_bus_error *ret_error) {
fe68089d 750
4d4c80d0 751 ExecCommand *c = (ExecCommand*) userdata;
718db961 752 int r;
fe68089d 753
718db961
LP
754 assert(bus);
755 assert(reply);
fe68089d 756
718db961
LP
757 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
758 if (r < 0)
759 return r;
fe68089d 760
4d4c80d0
LP
761 r = append_exec_command(reply, c);
762 if (r < 0)
763 return r;
fe68089d 764
4d4c80d0
LP
765 return sd_bus_message_close_container(reply);
766}
718db961 767
4d4c80d0
LP
768int bus_property_get_exec_command_list(
769 sd_bus *bus,
770 const char *path,
771 const char *interface,
772 const char *property,
773 sd_bus_message *reply,
774 void *userdata,
775 sd_bus_error *ret_error) {
718db961 776
4d4c80d0
LP
777 ExecCommand *c = *(ExecCommand**) userdata;
778 int r;
718db961 779
4d4c80d0
LP
780 assert(bus);
781 assert(reply);
782
783 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
784 if (r < 0)
785 return r;
718db961 786
4d4c80d0
LP
787 LIST_FOREACH(command, c, c) {
788 r = append_exec_command(reply, c);
718db961
LP
789 if (r < 0)
790 return r;
fe68089d
LP
791 }
792
718db961 793 return sd_bus_message_close_container(reply);
8351ceae 794}
c7040b5d
LP
795
796int bus_exec_context_set_transient_property(
797 Unit *u,
798 ExecContext *c,
799 const char *name,
800 sd_bus_message *message,
801 UnitSetPropertiesMode mode,
802 sd_bus_error *error) {
803
804 int r;
805
806 assert(u);
807 assert(c);
808 assert(name);
809 assert(message);
810
811 if (streq(name, "User")) {
812 const char *uu;
813
814 r = sd_bus_message_read(message, "s", &uu);
815 if (r < 0)
816 return r;
817
818 if (mode != UNIT_CHECK) {
819
820 if (isempty(uu)) {
a1e58e8e 821 c->user = mfree(c->user);
c7040b5d
LP
822 } else {
823 char *t;
824
825 t = strdup(uu);
826 if (!t)
827 return -ENOMEM;
828
829 free(c->user);
830 c->user = t;
831 }
832
833 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
834 }
835
836 return 1;
837
838 } else if (streq(name, "Group")) {
839 const char *gg;
840
841 r = sd_bus_message_read(message, "s", &gg);
842 if (r < 0)
843 return r;
844
845 if (mode != UNIT_CHECK) {
846
847 if (isempty(gg)) {
a1e58e8e 848 c->group = mfree(c->group);
c7040b5d
LP
849 } else {
850 char *t;
851
852 t = strdup(gg);
853 if (!t)
854 return -ENOMEM;
855
856 free(c->group);
857 c->group = t;
858 }
859
860 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
861 }
862
863 return 1;
de53c417
EV
864 } else if (streq(name, "SyslogIdentifier")) {
865 const char *id;
c7040b5d 866
de53c417
EV
867 r = sd_bus_message_read(message, "s", &id);
868 if (r < 0)
869 return r;
870
871 if (mode != UNIT_CHECK) {
872
873 if (isempty(id)) {
874 c->syslog_identifier = mfree(c->syslog_identifier);
875 } else {
876 char *t;
877
878 t = strdup(id);
879 if (!t)
880 return -ENOMEM;
881
882 free(c->syslog_identifier);
883 c->syslog_identifier = t;
884 }
885
886 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
887 }
888
a8a13575
EV
889 return 1;
890 } else if (streq(name, "SyslogLevel")) {
891 int level;
892
893 r = sd_bus_message_read(message, "i", &level);
894 if (r < 0)
895 return r;
896
e0d6e0fa
EV
897 if (!log_level_is_valid(level))
898 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
899
a8a13575
EV
900 if (mode != UNIT_CHECK) {
901 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
902 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level);
903 }
904
460ed929
EV
905 return 1;
906 } else if (streq(name, "SyslogFacility")) {
907 int facility;
908
909 r = sd_bus_message_read(message, "i", &facility);
910 if (r < 0)
911 return r;
912
e0d6e0fa
EV
913 if (!log_facility_unshifted_is_valid(facility))
914 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
915
460ed929
EV
916 if (mode != UNIT_CHECK) {
917 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
918 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility);
919 }
920
de53c417 921 return 1;
c7040b5d
LP
922 } else if (streq(name, "Nice")) {
923 int n;
924
925 r = sd_bus_message_read(message, "i", &n);
926 if (r < 0)
927 return r;
928
929 if (n < PRIO_MIN || n >= PRIO_MAX)
930 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
931
932 if (mode != UNIT_CHECK) {
933 c->nice = n;
934 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
935 }
936
937 return 1;
938
5f5d8eab 939 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
602b8355 940 const char *s;
9b15b784 941
602b8355 942 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
943 if (r < 0)
944 return r;
945
602b8355
NC
946 if (!path_is_absolute(s))
947 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
948
949 if (mode != UNIT_CHECK) {
5f5d8eab
LP
950 if (streq(name, "TTYPath"))
951 r = free_and_strdup(&c->tty_path, s);
952 else {
953 assert(streq(name, "RootDirectory"));
954 r = free_and_strdup(&c->root_directory, s);
602b8355 955 }
5f5d8eab
LP
956 if (r < 0)
957 return r;
9b15b784 958
602b8355 959 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
9b15b784
LP
960 }
961
962 return 1;
963
5f5d8eab
LP
964 } else if (streq(name, "WorkingDirectory")) {
965 const char *s;
966 bool missing_ok;
967
968 r = sd_bus_message_read(message, "s", &s);
969 if (r < 0)
970 return r;
971
972 if (s[0] == '-') {
973 missing_ok = true;
974 s++;
975 } else
976 missing_ok = false;
977
978 if (!streq(s, "~") && !path_is_absolute(s))
979 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
980
981 if (mode != UNIT_CHECK) {
982 if (streq(s, "~")) {
983 c->working_directory = mfree(c->working_directory);
984 c->working_directory_home = true;
985 } else {
986 r = free_and_strdup(&c->working_directory, s);
987 if (r < 0)
988 return r;
989
990 c->working_directory_home = false;
991 }
992
993 c->working_directory_missing_ok = missing_ok;
994 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
995 }
996
997 return 1;
998
9b15b784
LP
999 } else if (streq(name, "StandardInput")) {
1000 const char *s;
1001 ExecInput p;
1002
1003 r = sd_bus_message_read(message, "s", &s);
1004 if (r < 0)
1005 return r;
1006
1007 p = exec_input_from_string(s);
1008 if (p < 0)
1009 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1010
1011 if (mode != UNIT_CHECK) {
1012 c->std_input = p;
1013
1014 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
1015 }
1016
1017 return 1;
1018
1019
1020 } else if (streq(name, "StandardOutput")) {
1021 const char *s;
1022 ExecOutput p;
1023
1024 r = sd_bus_message_read(message, "s", &s);
1025 if (r < 0)
1026 return r;
1027
1028 p = exec_output_from_string(s);
1029 if (p < 0)
1030 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1031
1032 if (mode != UNIT_CHECK) {
1033 c->std_output = p;
1034
1035 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
1036 }
1037
1038 return 1;
1039
1040 } else if (streq(name, "StandardError")) {
1041 const char *s;
1042 ExecOutput p;
1043
1044 r = sd_bus_message_read(message, "s", &s);
1045 if (r < 0)
1046 return r;
1047
1048 p = exec_output_from_string(s);
1049 if (p < 0)
1050 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1051
1052 if (mode != UNIT_CHECK) {
1053 c->std_error = p;
1054
1055 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
1056 }
1057
1058 return 1;
1059
b9c50073
GP
1060 } else if (STR_IN_SET(name,
1061 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1062 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
047d9933 1063 "NoNewPrivileges", "SyslogLevelPrefix")) {
506711fd
LP
1064 int b;
1065
1066 r = sd_bus_message_read(message, "b", &b);
1067 if (r < 0)
1068 return r;
1069
1070 if (mode != UNIT_CHECK) {
b9c50073
GP
1071 if (streq(name, "IgnoreSIGPIPE"))
1072 c->ignore_sigpipe = b;
1073 else if (streq(name, "TTYVHangup"))
1074 c->tty_vhangup = b;
1075 else if (streq(name, "TTYReset"))
1076 c->tty_reset = b;
1077 else if (streq(name, "PrivateTmp"))
1078 c->private_tmp = b;
1079 else if (streq(name, "PrivateDevices"))
1080 c->private_devices = b;
1081 else if (streq(name, "PrivateNetwork"))
1082 c->private_network = b;
1083 else if (streq(name, "NoNewPrivileges"))
1084 c->no_new_privileges = b;
047d9933
EV
1085 else if (streq(name, "SyslogLevelPrefix"))
1086 c->syslog_level_prefix = b;
b9c50073
GP
1087
1088 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
506711fd
LP
1089 }
1090
1091 return 1;
1092
1093 } else if (streq(name, "UtmpIdentifier")) {
1094 const char *id;
1095
1096 r = sd_bus_message_read(message, "s", &id);
1097 if (r < 0)
1098 return r;
1099
1100 if (mode != UNIT_CHECK) {
1101 if (isempty(id))
1102 c->utmp_id = mfree(c->utmp_id);
1103 else if (free_and_strdup(&c->utmp_id, id) < 0)
1104 return -ENOMEM;
1105
1106 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
1107 }
1108
1109 return 1;
1110
1111 } else if (streq(name, "UtmpMode")) {
1112 const char *s;
1113 ExecUtmpMode m;
1114
1115 r = sd_bus_message_read(message, "s", &s);
1116 if (r < 0)
1117 return r;
1118
1119 m = exec_utmp_mode_from_string(s);
1120 if (m < 0)
1121 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1122
1123 if (mode != UNIT_CHECK) {
1124 c->utmp_mode = m;
1125
1126 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1127 }
1128
1129 return 1;
1130
1131 } else if (streq(name, "PAMName")) {
1132 const char *n;
1133
1134 r = sd_bus_message_read(message, "s", &n);
1135 if (r < 0)
1136 return r;
1137
1138 if (mode != UNIT_CHECK) {
1139 if (isempty(n))
1140 c->pam_name = mfree(c->pam_name);
1141 else if (free_and_strdup(&c->pam_name, n) < 0)
1142 return -ENOMEM;
1143
1144 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1145 }
1146
1147 return 1;
1148
c7040b5d
LP
1149 } else if (streq(name, "Environment")) {
1150
1151 _cleanup_strv_free_ char **l = NULL;
1152
1153 r = sd_bus_message_read_strv(message, &l);
1154 if (r < 0)
1155 return r;
1156
1157 if (!strv_env_is_valid(l))
1158 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1159
1160 if (mode != UNIT_CHECK) {
1006a62d 1161 _cleanup_free_ char *joined = NULL;
c7040b5d
LP
1162 char **e;
1163
e9876fc9
EV
1164 if (strv_length(l) == 0) {
1165 c->environment = strv_free(c->environment);
1166 unit_write_drop_in_private_format(u, mode, name, "Environment=\n");
1167 } else {
1168 e = strv_env_merge(2, c->environment, l);
1169 if (!e)
1170 return -ENOMEM;
c7040b5d 1171
e9876fc9
EV
1172 strv_free(c->environment);
1173 c->environment = e;
c7040b5d 1174
e9876fc9
EV
1175 joined = strv_join_quoted(c->environment);
1176 if (!joined)
1177 return -ENOMEM;
1178
1179 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1180 }
c7040b5d
LP
1181 }
1182
d584f638
LP
1183 return 1;
1184
f1db3327
EV
1185 } else if (streq(name, "TimerSlackNSec")) {
1186
1187 nsec_t n;
1188
1189 r = sd_bus_message_read(message, "t", &n);
1190 if (r < 0)
1191 return r;
1192
1193 if (mode != UNIT_CHECK) {
1194 c->timer_slack_nsec = n;
1195 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n);
1196 }
1197
1198 return 1;
1199
6b862936
EV
1200 } else if (streq(name, "OOMScoreAdjust")) {
1201 int oa;
1202
1203 r = sd_bus_message_read(message, "i", &oa);
1204 if (r < 0)
1205 return r;
1206
1207 if (!oom_score_adjust_is_valid(oa))
1208 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1209
1210 if (mode != UNIT_CHECK) {
1211 c->oom_score_adjust = oa;
1212 c->oom_score_adjust_set = true;
1213 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa);
1214 }
1215
1216 return 1;
1217
ceb728cf
NC
1218 } else if (streq(name, "EnvironmentFiles")) {
1219
1220 _cleanup_free_ char *joined = NULL;
1221 _cleanup_fclose_ FILE *f = NULL;
2229f656 1222 _cleanup_free_ char **l = NULL;
ceb728cf 1223 size_t size = 0;
2229f656 1224 char **i;
ceb728cf
NC
1225
1226 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1227 if (r < 0)
1228 return r;
1229
1230 f = open_memstream(&joined, &size);
1231 if (!f)
1232 return -ENOMEM;
1233
2229f656
LP
1234 STRV_FOREACH(i, c->environment_files)
1235 fprintf(f, "EnvironmentFile=%s\n", *i);
ceb728cf
NC
1236
1237 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1238 const char *path;
1239 int b;
1240
ceb728cf
NC
1241 r = sd_bus_message_read(message, "sb", &path, &b);
1242 if (r < 0)
1243 return r;
1244
1245 r = sd_bus_message_exit_container(message);
1246 if (r < 0)
1247 return r;
1248
1249 if (!isempty(path) && !path_is_absolute(path))
1250 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
1251
1252 if (mode != UNIT_CHECK) {
ceb728cf
NC
1253 char *buf = NULL;
1254
1255 buf = strjoin(b ? "-" : "", path, NULL);
2229f656 1256 if (!buf)
ceb728cf
NC
1257 return -ENOMEM;
1258
1259 fprintf(f, "EnvironmentFile=%s\n", buf);
1260
2229f656 1261 r = strv_consume(&l, buf);
ceb728cf
NC
1262 if (r < 0)
1263 return r;
1264 }
1265 }
1266 if (r < 0)
1267 return r;
1268
b0830e21
LP
1269 r = sd_bus_message_exit_container(message);
1270 if (r < 0)
1271 return r;
1272
2229f656
LP
1273 r = fflush_and_check(f);
1274 if (r < 0)
1275 return r;
ceb728cf 1276
2229f656
LP
1277 if (mode != UNIT_CHECK) {
1278 if (strv_isempty(l)) {
1279 c->environment_files = strv_free(c->environment_files);
ceb728cf 1280 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=\n");
2229f656
LP
1281 } else {
1282 r = strv_extend_strv(&c->environment_files, l, true);
1283 if (r < 0)
1284 return r;
1285
ceb728cf 1286 unit_write_drop_in_private(u, mode, name, joined);
2229f656
LP
1287 }
1288 }
ceb728cf 1289
ceb728cf
NC
1290 return 1;
1291
08596068
EV
1292 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1293
1294 _cleanup_strv_free_ char **l = NULL;
1295 char ***dirs;
1296 char **p;
1297
1298 r = sd_bus_message_read_strv(message, &l);
1299 if (r < 0)
1300 return r;
1301
1302 STRV_FOREACH(p, l) {
1303 int offset;
1304 if (!utf8_is_valid(*p))
1305 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1306
1307 offset = **p == '-';
1308 if (!path_is_absolute(*p + offset))
1309 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1310 }
1311
1312 if (mode != UNIT_CHECK) {
1313 _cleanup_free_ char *joined = NULL;
1314
1315 if (streq(name, "ReadWriteDirectories"))
1316 dirs = &c->read_write_dirs;
1317 else if (streq(name, "ReadOnlyDirectories"))
1318 dirs = &c->read_only_dirs;
1319 else if (streq(name, "InaccessibleDirectories"))
1320 dirs = &c->inaccessible_dirs;
1321
1322 if (strv_length(l) == 0) {
1323 *dirs = strv_free(*dirs);
1324 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1325 } else {
1326 r = strv_extend_strv(dirs, l, true);
1327
1328 if (r < 0)
1329 return -ENOMEM;
1330
1331 joined = strv_join_quoted(*dirs);
1332 if (!joined)
1333 return -ENOMEM;
1334
1335 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1336 }
1337
1338 }
1339
1340 return 1;
1341
5664e6cf
EV
1342 } else if (streq(name, "ProtectSystem")) {
1343 const char *s;
1344 ProtectSystem ps;
1345
1346 r = sd_bus_message_read(message, "s", &s);
1347 if (r < 0)
1348 return r;
1349
1350 r = parse_boolean(s);
1351 if (r > 0)
1352 ps = PROTECT_SYSTEM_YES;
1353 else if (r == 0)
1354 ps = PROTECT_SYSTEM_NO;
1355 else {
1356 ps = protect_system_from_string(s);
1357 if (ps < 0)
1358 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
1359 }
1360
1361 if (mode != UNIT_CHECK) {
1362 c->protect_system = ps;
1363 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1364 }
1365
1366 return 1;
1367
eff58074
EV
1368 } else if (streq(name, "ProtectHome")) {
1369 const char *s;
1370 ProtectHome ph;
1371
1372 r = sd_bus_message_read(message, "s", &s);
1373 if (r < 0)
1374 return r;
1375
1376 r = parse_boolean(s);
1377 if (r > 0)
1378 ph = PROTECT_HOME_YES;
1379 else if (r == 0)
1380 ph = PROTECT_HOME_NO;
1381 else {
1382 ph = protect_home_from_string(s);
1383 if (ph < 0)
1384 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
1385 }
1386
1387 if (mode != UNIT_CHECK) {
1388 c->protect_home = ph;
1389 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1390 }
1391
1392 return 1;
1393
fa21b5e3
EV
1394 } else if (streq(name, "RuntimeDirectory")) {
1395 _cleanup_strv_free_ char **l = NULL;
1396 char **p;
1397
1398 r = sd_bus_message_read_strv(message, &l);
1399 if (r < 0)
1400 return r;
1401
1402 STRV_FOREACH(p, l) {
1403 if (!filename_is_valid(*p))
1404 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p);
1405 }
1406
1407 if (mode != UNIT_CHECK) {
1408 _cleanup_free_ char *joined = NULL;
1409
1410 if (strv_isempty(l)) {
1411 c->runtime_directory = strv_free(c->runtime_directory);
1412 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1413 } else {
1414 r = strv_extend_strv(&c->runtime_directory, l, true);
1415
1416 if (r < 0)
1417 return -ENOMEM;
1418
1419 joined = strv_join_quoted(c->runtime_directory);
1420 if (!joined)
1421 return -ENOMEM;
1422
1423 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1424 }
1425 }
1426
1427 return 1;
1428
d584f638
LP
1429 } else if (rlimit_from_string(name) >= 0) {
1430 uint64_t rl;
1431 rlim_t x;
1432
1433 r = sd_bus_message_read(message, "t", &rl);
1434 if (r < 0)
1435 return r;
1436
1437 if (rl == (uint64_t) -1)
1438 x = RLIM_INFINITY;
1439 else {
1440 x = (rlim_t) rl;
1441
1442 if ((uint64_t) x != rl)
1443 return -ERANGE;
1444 }
1445
1446 if (mode != UNIT_CHECK) {
1447 int z;
1448
1449 z = rlimit_from_string(name);
1450
1451 if (!c->rlimit[z]) {
1452 c->rlimit[z] = new(struct rlimit, 1);
1453 if (!c->rlimit[z])
1454 return -ENOMEM;
1455 }
1456
1457 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1458
1459 if (x == RLIM_INFINITY)
1460 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1461 else
1462 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1463 }
1464
c7040b5d
LP
1465 return 1;
1466 }
1467
1468 return 0;
1469}