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