]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/dbus-execute.c
tree-wide: check if errno is greater then zero
[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
a103496c 296 return sd_bus_message_append(reply, "t", c->capability_bounding_set);
260abb78
LP
297}
298
755d4b67
IP
299static int property_get_ambient_capabilities(
300 sd_bus *bus,
301 const char *path,
302 const char *interface,
303 const char *property,
304 sd_bus_message *reply,
305 void *userdata,
306 sd_bus_error *error) {
307
308 ExecContext *c = userdata;
309
310 assert(bus);
311 assert(reply);
312 assert(c);
313
314 return sd_bus_message_append(reply, "t", c->capability_ambient_set);
315}
316
718db961
LP
317static int property_get_capabilities(
318 sd_bus *bus,
319 const char *path,
320 const char *interface,
321 const char *property,
322 sd_bus_message *reply,
ebcf1f97
LP
323 void *userdata,
324 sd_bus_error *error) {
718db961
LP
325
326 ExecContext *c = userdata;
5ce70e5b 327 _cleanup_cap_free_charp_ char *t = NULL;
82c121a4 328 const char *s;
82c121a4 329
718db961
LP
330 assert(bus);
331 assert(reply);
82c121a4
LP
332 assert(c);
333
334 if (c->capabilities)
335 s = t = cap_to_text(c->capabilities, NULL);
336 else
337 s = "";
338
674cdd19 339 if (!s)
82c121a4
LP
340 return -ENOMEM;
341
5ce70e5b 342 return sd_bus_message_append(reply, "s", s);
82c121a4
LP
343}
344
718db961
LP
345static int property_get_syscall_filter(
346 sd_bus *bus,
347 const char *path,
348 const char *interface,
349 const char *property,
350 sd_bus_message *reply,
ebcf1f97
LP
351 void *userdata,
352 sd_bus_error *error) {
82c121a4 353
17df7223
LP
354 ExecContext *c = userdata;
355 _cleanup_strv_free_ char **l = NULL;
57183d11
LP
356 int r;
357
351a19b1 358#ifdef HAVE_SECCOMP
17df7223
LP
359 Iterator i;
360 void *id;
351a19b1 361#endif
17df7223
LP
362
363 assert(bus);
364 assert(reply);
365 assert(c);
366
57183d11
LP
367 r = sd_bus_message_open_container(reply, 'r', "bas");
368 if (r < 0)
369 return r;
370
371 r = sd_bus_message_append(reply, "b", c->syscall_whitelist);
372 if (r < 0)
373 return r;
374
351a19b1 375#ifdef HAVE_SECCOMP
17df7223
LP
376 SET_FOREACH(id, c->syscall_filter, i) {
377 char *name;
378
379 name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, PTR_TO_INT(id) - 1);
380 if (!name)
381 continue;
382
6e18964d
ZJS
383 r = strv_consume(&l, name);
384 if (r < 0)
385 return r;
17df7223 386 }
351a19b1 387#endif
17df7223
LP
388
389 strv_sort(l);
390
57183d11
LP
391 r = sd_bus_message_append_strv(reply, l);
392 if (r < 0)
393 return r;
17df7223 394
57183d11
LP
395 return sd_bus_message_close_container(reply);
396}
17df7223 397
57183d11
LP
398static int property_get_syscall_archs(
399 sd_bus *bus,
400 const char *path,
401 const char *interface,
402 const char *property,
403 sd_bus_message *reply,
404 void *userdata,
405 sd_bus_error *error) {
406
407 ExecContext *c = userdata;
408 _cleanup_strv_free_ char **l = NULL;
409 int r;
410
411#ifdef HAVE_SECCOMP
412 Iterator i;
413 void *id;
414#endif
415
416 assert(bus);
417 assert(reply);
418 assert(c);
17df7223 419
57183d11
LP
420#ifdef HAVE_SECCOMP
421 SET_FOREACH(id, c->syscall_archs, i) {
422 const char *name;
423
424 name = seccomp_arch_to_string(PTR_TO_UINT32(id) - 1);
425 if (!name)
426 continue;
427
428 r = strv_extend(&l, name);
429 if (r < 0)
430 return -ENOMEM;
17df7223 431 }
57183d11
LP
432#endif
433
434 strv_sort(l);
435
436 r = sd_bus_message_append_strv(reply, l);
437 if (r < 0)
438 return r;
17df7223 439
57183d11 440 return 0;
17df7223
LP
441}
442
443static int property_get_syscall_errno(
444 sd_bus *bus,
445 const char *path,
446 const char *interface,
447 const char *property,
448 sd_bus_message *reply,
449 void *userdata,
450 sd_bus_error *error) {
451
718db961 452 ExecContext *c = userdata;
82c121a4 453
718db961
LP
454 assert(bus);
455 assert(reply);
456 assert(c);
82c121a4 457
17df7223 458 return sd_bus_message_append(reply, "i", (int32_t) c->syscall_errno);
718db961 459}
82c121a4 460
5f8640fb
LP
461static int property_get_selinux_context(
462 sd_bus *bus,
463 const char *path,
464 const char *interface,
465 const char *property,
466 sd_bus_message *reply,
467 void *userdata,
468 sd_bus_error *error) {
469
470 ExecContext *c = userdata;
471
472 assert(bus);
473 assert(reply);
474 assert(c);
475
476 return sd_bus_message_append(reply, "(bs)", c->selinux_context_ignore, c->selinux_context);
477}
478
eef65bf3
MS
479static int property_get_apparmor_profile(
480 sd_bus *bus,
481 const char *path,
482 const char *interface,
483 const char *property,
484 sd_bus_message *reply,
485 void *userdata,
486 sd_bus_error *error) {
487
488 ExecContext *c = userdata;
489
490 assert(bus);
491 assert(reply);
492 assert(c);
493
494 return sd_bus_message_append(reply, "(bs)", c->apparmor_profile_ignore, c->apparmor_profile);
495}
496
2ca620c4
WC
497static int property_get_smack_process_label(
498 sd_bus *bus,
499 const char *path,
500 const char *interface,
501 const char *property,
502 sd_bus_message *reply,
503 void *userdata,
504 sd_bus_error *error) {
505
506 ExecContext *c = userdata;
507
508 assert(bus);
509 assert(reply);
510 assert(c);
511
512 return sd_bus_message_append(reply, "(bs)", c->smack_process_label_ignore, c->smack_process_label);
513}
514
ac45f971
LP
515static int property_get_personality(
516 sd_bus *bus,
517 const char *path,
518 const char *interface,
519 const char *property,
520 sd_bus_message *reply,
521 void *userdata,
522 sd_bus_error *error) {
523
524 ExecContext *c = userdata;
525
526 assert(bus);
527 assert(reply);
528 assert(c);
529
530 return sd_bus_message_append(reply, "s", personality_to_string(c->personality));
531}
532
4298d0b5
LP
533static int property_get_address_families(
534 sd_bus *bus,
535 const char *path,
536 const char *interface,
537 const char *property,
538 sd_bus_message *reply,
539 void *userdata,
540 sd_bus_error *error) {
541
542 ExecContext *c = userdata;
543 _cleanup_strv_free_ char **l = NULL;
544 Iterator i;
545 void *af;
546 int r;
547
548 assert(bus);
549 assert(reply);
550 assert(c);
551
552 r = sd_bus_message_open_container(reply, 'r', "bas");
553 if (r < 0)
554 return r;
555
556 r = sd_bus_message_append(reply, "b", c->address_families_whitelist);
557 if (r < 0)
558 return r;
559
560 SET_FOREACH(af, c->address_families, i) {
561 const char *name;
562
563 name = af_to_name(PTR_TO_INT(af));
564 if (!name)
565 continue;
566
567 r = strv_extend(&l, name);
568 if (r < 0)
569 return -ENOMEM;
570 }
571
572 strv_sort(l);
573
574 r = sd_bus_message_append_strv(reply, l);
575 if (r < 0)
576 return r;
577
578 return sd_bus_message_close_container(reply);
579}
580
5f5d8eab
LP
581static int property_get_working_directory(
582 sd_bus *bus,
583 const char *path,
584 const char *interface,
585 const char *property,
586 sd_bus_message *reply,
587 void *userdata,
588 sd_bus_error *error) {
589
590 ExecContext *c = userdata;
591 const char *wd;
592
593 assert(bus);
594 assert(reply);
595 assert(c);
596
597 if (c->working_directory_home)
598 wd = "~";
599 else
600 wd = c->working_directory;
601
602 if (c->working_directory_missing_ok)
603 wd = strjoina("!", wd);
604
605 return sd_bus_message_append(reply, "s", wd);
606}
607
06f2ccf9
EV
608static int property_get_syslog_level(
609 sd_bus *bus,
610 const char *path,
611 const char *interface,
612 const char *property,
613 sd_bus_message *reply,
614 void *userdata,
615 sd_bus_error *error) {
616
617 ExecContext *c = userdata;
618
619 assert(bus);
620 assert(reply);
621 assert(c);
622
623 return sd_bus_message_append(reply, "i", LOG_PRI(c->syslog_priority));
624}
625
626static int property_get_syslog_facility(
627 sd_bus *bus,
628 const char *path,
629 const char *interface,
630 const char *property,
631 sd_bus_message *reply,
632 void *userdata,
633 sd_bus_error *error) {
634
635 ExecContext *c = userdata;
636
637 assert(bus);
638 assert(reply);
639 assert(c);
640
641 return sd_bus_message_append(reply, "i", LOG_FAC(c->syslog_priority));
642}
643
718db961
LP
644const sd_bus_vtable bus_exec_vtable[] = {
645 SD_BUS_VTABLE_START(0),
556089dc
LP
646 SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
647 SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
b4c14404 648 SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc 649 SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 650 SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 651 SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 652 SD_BUS_PROPERTY("LimitFSIZE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 653 SD_BUS_PROPERTY("LimitFSIZESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_FSIZE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 654 SD_BUS_PROPERTY("LimitDATA", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 655 SD_BUS_PROPERTY("LimitDATASoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_DATA]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 656 SD_BUS_PROPERTY("LimitSTACK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 657 SD_BUS_PROPERTY("LimitSTACKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_STACK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 658 SD_BUS_PROPERTY("LimitCORE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 659 SD_BUS_PROPERTY("LimitCORESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CORE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 660 SD_BUS_PROPERTY("LimitRSS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 661 SD_BUS_PROPERTY("LimitRSSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RSS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 662 SD_BUS_PROPERTY("LimitNOFILE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 663 SD_BUS_PROPERTY("LimitNOFILESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NOFILE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 664 SD_BUS_PROPERTY("LimitAS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 665 SD_BUS_PROPERTY("LimitASSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_AS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 666 SD_BUS_PROPERTY("LimitNPROC", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 667 SD_BUS_PROPERTY("LimitNPROCSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NPROC]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 668 SD_BUS_PROPERTY("LimitMEMLOCK", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 669 SD_BUS_PROPERTY("LimitMEMLOCKSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MEMLOCK]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 670 SD_BUS_PROPERTY("LimitLOCKS", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 671 SD_BUS_PROPERTY("LimitLOCKSSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_LOCKS]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 672 SD_BUS_PROPERTY("LimitSIGPENDING", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 673 SD_BUS_PROPERTY("LimitSIGPENDINGSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_SIGPENDING]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 674 SD_BUS_PROPERTY("LimitMSGQUEUE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 675 SD_BUS_PROPERTY("LimitMSGQUEUESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_MSGQUEUE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 676 SD_BUS_PROPERTY("LimitNICE", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 677 SD_BUS_PROPERTY("LimitNICESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_NICE]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 678 SD_BUS_PROPERTY("LimitRTPRIO", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 679 SD_BUS_PROPERTY("LimitRTPRIOSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTPRIO]), SD_BUS_VTABLE_PROPERTY_CONST),
c9d031c3 680 SD_BUS_PROPERTY("LimitRTTIME", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
147f6858 681 SD_BUS_PROPERTY("LimitRTTIMESoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_RTTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
5f5d8eab 682 SD_BUS_PROPERTY("WorkingDirectory", "s", property_get_working_directory, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
683 SD_BUS_PROPERTY("RootDirectory", "s", NULL, offsetof(ExecContext, root_directory), SD_BUS_VTABLE_PROPERTY_CONST),
684 SD_BUS_PROPERTY("OOMScoreAdjust", "i", property_get_oom_score_adjust, 0, SD_BUS_VTABLE_PROPERTY_CONST),
685 SD_BUS_PROPERTY("Nice", "i", property_get_nice, 0, SD_BUS_VTABLE_PROPERTY_CONST),
686 SD_BUS_PROPERTY("IOScheduling", "i", property_get_ioprio, 0, SD_BUS_VTABLE_PROPERTY_CONST),
687 SD_BUS_PROPERTY("CPUSchedulingPolicy", "i", property_get_cpu_sched_policy, 0, SD_BUS_VTABLE_PROPERTY_CONST),
688 SD_BUS_PROPERTY("CPUSchedulingPriority", "i", property_get_cpu_sched_priority, 0, SD_BUS_VTABLE_PROPERTY_CONST),
689 SD_BUS_PROPERTY("CPUAffinity", "ay", property_get_cpu_affinity, 0, SD_BUS_VTABLE_PROPERTY_CONST),
690 SD_BUS_PROPERTY("TimerSlackNSec", "t", property_get_timer_slack_nsec, 0, SD_BUS_VTABLE_PROPERTY_CONST),
691 SD_BUS_PROPERTY("CPUSchedulingResetOnFork", "b", bus_property_get_bool, offsetof(ExecContext, cpu_sched_reset_on_fork), SD_BUS_VTABLE_PROPERTY_CONST),
692 SD_BUS_PROPERTY("NonBlocking", "b", bus_property_get_bool, offsetof(ExecContext, non_blocking), SD_BUS_VTABLE_PROPERTY_CONST),
693 SD_BUS_PROPERTY("StandardInput", "s", property_get_exec_input, offsetof(ExecContext, std_input), SD_BUS_VTABLE_PROPERTY_CONST),
694 SD_BUS_PROPERTY("StandardOutput", "s", bus_property_get_exec_output, offsetof(ExecContext, std_output), SD_BUS_VTABLE_PROPERTY_CONST),
695 SD_BUS_PROPERTY("StandardError", "s", bus_property_get_exec_output, offsetof(ExecContext, std_error), SD_BUS_VTABLE_PROPERTY_CONST),
696 SD_BUS_PROPERTY("TTYPath", "s", NULL, offsetof(ExecContext, tty_path), SD_BUS_VTABLE_PROPERTY_CONST),
697 SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST),
698 SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST),
699 SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST),
700 SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST),
701 SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST),
702 SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST),
06f2ccf9
EV
703 SD_BUS_PROPERTY("SyslogLevel", "i", property_get_syslog_level, 0, SD_BUS_VTABLE_PROPERTY_CONST),
704 SD_BUS_PROPERTY("SyslogFacility", "i", property_get_syslog_facility, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
705 SD_BUS_PROPERTY("Capabilities", "s", property_get_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
706 SD_BUS_PROPERTY("SecureBits", "i", bus_property_get_int, offsetof(ExecContext, secure_bits), SD_BUS_VTABLE_PROPERTY_CONST),
707 SD_BUS_PROPERTY("CapabilityBoundingSet", "t", property_get_capability_bounding_set, 0, SD_BUS_VTABLE_PROPERTY_CONST),
755d4b67 708 SD_BUS_PROPERTY("AmbientCapabilities", "t", property_get_ambient_capabilities, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
709 SD_BUS_PROPERTY("User", "s", NULL, offsetof(ExecContext, user), SD_BUS_VTABLE_PROPERTY_CONST),
710 SD_BUS_PROPERTY("Group", "s", NULL, offsetof(ExecContext, group), SD_BUS_VTABLE_PROPERTY_CONST),
711 SD_BUS_PROPERTY("SupplementaryGroups", "as", NULL, offsetof(ExecContext, supplementary_groups), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
712 SD_BUS_PROPERTY("PAMName", "s", NULL, offsetof(ExecContext, pam_name), SD_BUS_VTABLE_PROPERTY_CONST),
713 SD_BUS_PROPERTY("ReadWriteDirectories", "as", NULL, offsetof(ExecContext, read_write_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
714 SD_BUS_PROPERTY("ReadOnlyDirectories", "as", NULL, offsetof(ExecContext, read_only_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
715 SD_BUS_PROPERTY("InaccessibleDirectories", "as", NULL, offsetof(ExecContext, inaccessible_dirs), SD_BUS_VTABLE_PROPERTY_CONST),
716 SD_BUS_PROPERTY("MountFlags", "t", bus_property_get_ulong, offsetof(ExecContext, mount_flags), SD_BUS_VTABLE_PROPERTY_CONST),
717 SD_BUS_PROPERTY("PrivateTmp", "b", bus_property_get_bool, offsetof(ExecContext, private_tmp), SD_BUS_VTABLE_PROPERTY_CONST),
718 SD_BUS_PROPERTY("PrivateNetwork", "b", bus_property_get_bool, offsetof(ExecContext, private_network), SD_BUS_VTABLE_PROPERTY_CONST),
7f112f50 719 SD_BUS_PROPERTY("PrivateDevices", "b", bus_property_get_bool, offsetof(ExecContext, private_devices), SD_BUS_VTABLE_PROPERTY_CONST),
1b8689f9
LP
720 SD_BUS_PROPERTY("ProtectHome", "s", bus_property_get_protect_home, offsetof(ExecContext, protect_home), SD_BUS_VTABLE_PROPERTY_CONST),
721 SD_BUS_PROPERTY("ProtectSystem", "s", bus_property_get_protect_system, offsetof(ExecContext, protect_system), SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
722 SD_BUS_PROPERTY("SameProcessGroup", "b", bus_property_get_bool, offsetof(ExecContext, same_pgrp), SD_BUS_VTABLE_PROPERTY_CONST),
723 SD_BUS_PROPERTY("UtmpIdentifier", "s", NULL, offsetof(ExecContext, utmp_id), SD_BUS_VTABLE_PROPERTY_CONST),
023a4f67 724 SD_BUS_PROPERTY("UtmpMode", "s", property_get_exec_utmp_mode, offsetof(ExecContext, utmp_mode), SD_BUS_VTABLE_PROPERTY_CONST),
5f8640fb 725 SD_BUS_PROPERTY("SELinuxContext", "(bs)", property_get_selinux_context, 0, SD_BUS_VTABLE_PROPERTY_CONST),
eef65bf3 726 SD_BUS_PROPERTY("AppArmorProfile", "(bs)", property_get_apparmor_profile, 0, SD_BUS_VTABLE_PROPERTY_CONST),
2ca620c4 727 SD_BUS_PROPERTY("SmackProcessLabel", "(bs)", property_get_smack_process_label, 0, SD_BUS_VTABLE_PROPERTY_CONST),
556089dc
LP
728 SD_BUS_PROPERTY("IgnoreSIGPIPE", "b", bus_property_get_bool, offsetof(ExecContext, ignore_sigpipe), SD_BUS_VTABLE_PROPERTY_CONST),
729 SD_BUS_PROPERTY("NoNewPrivileges", "b", bus_property_get_bool, offsetof(ExecContext, no_new_privileges), SD_BUS_VTABLE_PROPERTY_CONST),
57183d11
LP
730 SD_BUS_PROPERTY("SystemCallFilter", "(bas)", property_get_syscall_filter, 0, SD_BUS_VTABLE_PROPERTY_CONST),
731 SD_BUS_PROPERTY("SystemCallArchitectures", "as", property_get_syscall_archs, 0, SD_BUS_VTABLE_PROPERTY_CONST),
17df7223 732 SD_BUS_PROPERTY("SystemCallErrorNumber", "i", property_get_syscall_errno, 0, SD_BUS_VTABLE_PROPERTY_CONST),
ac45f971 733 SD_BUS_PROPERTY("Personality", "s", property_get_personality, 0, SD_BUS_VTABLE_PROPERTY_CONST),
4298d0b5 734 SD_BUS_PROPERTY("RestrictAddressFamilies", "(bas)", property_get_address_families, 0, SD_BUS_VTABLE_PROPERTY_CONST),
e66cf1a3
LP
735 SD_BUS_PROPERTY("RuntimeDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, runtime_directory_mode), SD_BUS_VTABLE_PROPERTY_CONST),
736 SD_BUS_PROPERTY("RuntimeDirectory", "as", NULL, offsetof(ExecContext, runtime_directory), SD_BUS_VTABLE_PROPERTY_CONST),
718db961
LP
737 SD_BUS_VTABLE_END
738};
82c121a4 739
4d4c80d0
LP
740static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
741 int r;
742
743 assert(reply);
744 assert(c);
745
746 if (!c->path)
747 return 0;
748
749 r = sd_bus_message_open_container(reply, 'r', "sasbttttuii");
750 if (r < 0)
751 return r;
752
753 r = sd_bus_message_append(reply, "s", c->path);
754 if (r < 0)
755 return r;
756
757 r = sd_bus_message_append_strv(reply, c->argv);
758 if (r < 0)
759 return r;
760
761 r = sd_bus_message_append(reply, "bttttuii",
762 c->ignore,
763 c->exec_status.start_timestamp.realtime,
764 c->exec_status.start_timestamp.monotonic,
765 c->exec_status.exit_timestamp.realtime,
766 c->exec_status.exit_timestamp.monotonic,
767 (uint32_t) c->exec_status.pid,
768 (int32_t) c->exec_status.code,
769 (int32_t) c->exec_status.status);
770 if (r < 0)
771 return r;
772
773 return sd_bus_message_close_container(reply);
774}
775
718db961
LP
776int bus_property_get_exec_command(
777 sd_bus *bus,
778 const char *path,
779 const char *interface,
780 const char *property,
781 sd_bus_message *reply,
ebcf1f97
LP
782 void *userdata,
783 sd_bus_error *ret_error) {
fe68089d 784
4d4c80d0 785 ExecCommand *c = (ExecCommand*) userdata;
718db961 786 int r;
fe68089d 787
718db961
LP
788 assert(bus);
789 assert(reply);
fe68089d 790
718db961
LP
791 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
792 if (r < 0)
793 return r;
fe68089d 794
4d4c80d0
LP
795 r = append_exec_command(reply, c);
796 if (r < 0)
797 return r;
fe68089d 798
4d4c80d0
LP
799 return sd_bus_message_close_container(reply);
800}
718db961 801
4d4c80d0
LP
802int bus_property_get_exec_command_list(
803 sd_bus *bus,
804 const char *path,
805 const char *interface,
806 const char *property,
807 sd_bus_message *reply,
808 void *userdata,
809 sd_bus_error *ret_error) {
718db961 810
4d4c80d0
LP
811 ExecCommand *c = *(ExecCommand**) userdata;
812 int r;
718db961 813
4d4c80d0
LP
814 assert(bus);
815 assert(reply);
816
817 r = sd_bus_message_open_container(reply, 'a', "(sasbttttuii)");
818 if (r < 0)
819 return r;
718db961 820
4d4c80d0
LP
821 LIST_FOREACH(command, c, c) {
822 r = append_exec_command(reply, c);
718db961
LP
823 if (r < 0)
824 return r;
fe68089d
LP
825 }
826
718db961 827 return sd_bus_message_close_container(reply);
8351ceae 828}
c7040b5d
LP
829
830int bus_exec_context_set_transient_property(
831 Unit *u,
832 ExecContext *c,
833 const char *name,
834 sd_bus_message *message,
835 UnitSetPropertiesMode mode,
836 sd_bus_error *error) {
837
838 int r;
839
840 assert(u);
841 assert(c);
842 assert(name);
843 assert(message);
844
845 if (streq(name, "User")) {
846 const char *uu;
847
848 r = sd_bus_message_read(message, "s", &uu);
849 if (r < 0)
850 return r;
851
852 if (mode != UNIT_CHECK) {
853
854 if (isempty(uu)) {
a1e58e8e 855 c->user = mfree(c->user);
c7040b5d
LP
856 } else {
857 char *t;
858
859 t = strdup(uu);
860 if (!t)
861 return -ENOMEM;
862
863 free(c->user);
864 c->user = t;
865 }
866
867 unit_write_drop_in_private_format(u, mode, name, "User=%s\n", uu);
868 }
869
870 return 1;
871
872 } else if (streq(name, "Group")) {
873 const char *gg;
874
875 r = sd_bus_message_read(message, "s", &gg);
876 if (r < 0)
877 return r;
878
879 if (mode != UNIT_CHECK) {
880
881 if (isempty(gg)) {
a1e58e8e 882 c->group = mfree(c->group);
c7040b5d
LP
883 } else {
884 char *t;
885
886 t = strdup(gg);
887 if (!t)
888 return -ENOMEM;
889
890 free(c->group);
891 c->group = t;
892 }
893
894 unit_write_drop_in_private_format(u, mode, name, "Group=%s\n", gg);
895 }
896
897 return 1;
de53c417
EV
898 } else if (streq(name, "SyslogIdentifier")) {
899 const char *id;
c7040b5d 900
de53c417
EV
901 r = sd_bus_message_read(message, "s", &id);
902 if (r < 0)
903 return r;
904
905 if (mode != UNIT_CHECK) {
906
907 if (isempty(id)) {
908 c->syslog_identifier = mfree(c->syslog_identifier);
909 } else {
910 char *t;
911
912 t = strdup(id);
913 if (!t)
914 return -ENOMEM;
915
916 free(c->syslog_identifier);
917 c->syslog_identifier = t;
918 }
919
920 unit_write_drop_in_private_format(u, mode, name, "SyslogIdentifier=%s\n", id);
921 }
922
a8a13575
EV
923 return 1;
924 } else if (streq(name, "SyslogLevel")) {
925 int level;
926
927 r = sd_bus_message_read(message, "i", &level);
928 if (r < 0)
929 return r;
930
e0d6e0fa
EV
931 if (!log_level_is_valid(level))
932 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log level value out of range");
933
a8a13575
EV
934 if (mode != UNIT_CHECK) {
935 c->syslog_priority = (c->syslog_priority & LOG_FACMASK) | level;
936 unit_write_drop_in_private_format(u, mode, name, "SyslogLevel=%i\n", level);
937 }
938
460ed929
EV
939 return 1;
940 } else if (streq(name, "SyslogFacility")) {
941 int facility;
942
943 r = sd_bus_message_read(message, "i", &facility);
944 if (r < 0)
945 return r;
946
e0d6e0fa
EV
947 if (!log_facility_unshifted_is_valid(facility))
948 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Log facility value out of range");
949
460ed929
EV
950 if (mode != UNIT_CHECK) {
951 c->syslog_priority = (facility << 3) | LOG_PRI(c->syslog_priority);
952 unit_write_drop_in_private_format(u, mode, name, "SyslogFacility=%i\n", facility);
953 }
954
de53c417 955 return 1;
c7040b5d
LP
956 } else if (streq(name, "Nice")) {
957 int n;
958
959 r = sd_bus_message_read(message, "i", &n);
960 if (r < 0)
961 return r;
962
963 if (n < PRIO_MIN || n >= PRIO_MAX)
964 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Nice value out of range");
965
966 if (mode != UNIT_CHECK) {
967 c->nice = n;
968 unit_write_drop_in_private_format(u, mode, name, "Nice=%i\n", n);
969 }
970
971 return 1;
972
5f5d8eab 973 } else if (STR_IN_SET(name, "TTYPath", "RootDirectory")) {
602b8355 974 const char *s;
9b15b784 975
602b8355 976 r = sd_bus_message_read(message, "s", &s);
9b15b784
LP
977 if (r < 0)
978 return r;
979
602b8355
NC
980 if (!path_is_absolute(s))
981 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "%s takes an absolute path", name);
9b15b784
LP
982
983 if (mode != UNIT_CHECK) {
5f5d8eab
LP
984 if (streq(name, "TTYPath"))
985 r = free_and_strdup(&c->tty_path, s);
986 else {
987 assert(streq(name, "RootDirectory"));
988 r = free_and_strdup(&c->root_directory, s);
602b8355 989 }
5f5d8eab
LP
990 if (r < 0)
991 return r;
9b15b784 992
602b8355 993 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
9b15b784
LP
994 }
995
996 return 1;
997
5f5d8eab
LP
998 } else if (streq(name, "WorkingDirectory")) {
999 const char *s;
1000 bool missing_ok;
1001
1002 r = sd_bus_message_read(message, "s", &s);
1003 if (r < 0)
1004 return r;
1005
1006 if (s[0] == '-') {
1007 missing_ok = true;
1008 s++;
1009 } else
1010 missing_ok = false;
1011
1012 if (!streq(s, "~") && !path_is_absolute(s))
1013 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "WorkingDirectory= expects an absolute path or '~'");
1014
1015 if (mode != UNIT_CHECK) {
1016 if (streq(s, "~")) {
1017 c->working_directory = mfree(c->working_directory);
1018 c->working_directory_home = true;
1019 } else {
1020 r = free_and_strdup(&c->working_directory, s);
1021 if (r < 0)
1022 return r;
1023
1024 c->working_directory_home = false;
1025 }
1026
1027 c->working_directory_missing_ok = missing_ok;
1028 unit_write_drop_in_private_format(u, mode, name, "WorkingDirectory=%s%s", missing_ok ? "-" : "", s);
1029 }
1030
1031 return 1;
1032
9b15b784
LP
1033 } else if (streq(name, "StandardInput")) {
1034 const char *s;
1035 ExecInput p;
1036
1037 r = sd_bus_message_read(message, "s", &s);
1038 if (r < 0)
1039 return r;
1040
1041 p = exec_input_from_string(s);
1042 if (p < 0)
1043 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard input name");
1044
1045 if (mode != UNIT_CHECK) {
1046 c->std_input = p;
1047
1048 unit_write_drop_in_private_format(u, mode, name, "StandardInput=%s\n", exec_input_to_string(p));
1049 }
1050
1051 return 1;
1052
1053
1054 } else if (streq(name, "StandardOutput")) {
1055 const char *s;
1056 ExecOutput p;
1057
1058 r = sd_bus_message_read(message, "s", &s);
1059 if (r < 0)
1060 return r;
1061
1062 p = exec_output_from_string(s);
1063 if (p < 0)
1064 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard output name");
1065
1066 if (mode != UNIT_CHECK) {
1067 c->std_output = p;
1068
1069 unit_write_drop_in_private_format(u, mode, name, "StandardOutput=%s\n", exec_output_to_string(p));
1070 }
1071
1072 return 1;
1073
1074 } else if (streq(name, "StandardError")) {
1075 const char *s;
1076 ExecOutput p;
1077
1078 r = sd_bus_message_read(message, "s", &s);
1079 if (r < 0)
1080 return r;
1081
1082 p = exec_output_from_string(s);
1083 if (p < 0)
1084 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid standard error name");
1085
1086 if (mode != UNIT_CHECK) {
1087 c->std_error = p;
1088
1089 unit_write_drop_in_private_format(u, mode, name, "StandardError=%s\n", exec_output_to_string(p));
1090 }
1091
1092 return 1;
1093
b9c50073
GP
1094 } else if (STR_IN_SET(name,
1095 "IgnoreSIGPIPE", "TTYVHangup", "TTYReset",
1096 "PrivateTmp", "PrivateDevices", "PrivateNetwork",
047d9933 1097 "NoNewPrivileges", "SyslogLevelPrefix")) {
506711fd
LP
1098 int b;
1099
1100 r = sd_bus_message_read(message, "b", &b);
1101 if (r < 0)
1102 return r;
1103
1104 if (mode != UNIT_CHECK) {
b9c50073
GP
1105 if (streq(name, "IgnoreSIGPIPE"))
1106 c->ignore_sigpipe = b;
1107 else if (streq(name, "TTYVHangup"))
1108 c->tty_vhangup = b;
1109 else if (streq(name, "TTYReset"))
1110 c->tty_reset = b;
1111 else if (streq(name, "PrivateTmp"))
1112 c->private_tmp = b;
1113 else if (streq(name, "PrivateDevices"))
1114 c->private_devices = b;
1115 else if (streq(name, "PrivateNetwork"))
1116 c->private_network = b;
1117 else if (streq(name, "NoNewPrivileges"))
1118 c->no_new_privileges = b;
047d9933
EV
1119 else if (streq(name, "SyslogLevelPrefix"))
1120 c->syslog_level_prefix = b;
b9c50073
GP
1121
1122 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, yes_no(b));
506711fd
LP
1123 }
1124
1125 return 1;
1126
1127 } else if (streq(name, "UtmpIdentifier")) {
1128 const char *id;
1129
1130 r = sd_bus_message_read(message, "s", &id);
1131 if (r < 0)
1132 return r;
1133
1134 if (mode != UNIT_CHECK) {
1135 if (isempty(id))
1136 c->utmp_id = mfree(c->utmp_id);
1137 else if (free_and_strdup(&c->utmp_id, id) < 0)
1138 return -ENOMEM;
1139
1140 unit_write_drop_in_private_format(u, mode, name, "UtmpIdentifier=%s\n", strempty(id));
1141 }
1142
1143 return 1;
1144
1145 } else if (streq(name, "UtmpMode")) {
1146 const char *s;
1147 ExecUtmpMode m;
1148
1149 r = sd_bus_message_read(message, "s", &s);
1150 if (r < 0)
1151 return r;
1152
1153 m = exec_utmp_mode_from_string(s);
1154 if (m < 0)
1155 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid utmp mode");
1156
1157 if (mode != UNIT_CHECK) {
1158 c->utmp_mode = m;
1159
1160 unit_write_drop_in_private_format(u, mode, name, "UtmpMode=%s\n", exec_utmp_mode_to_string(m));
1161 }
1162
1163 return 1;
1164
1165 } else if (streq(name, "PAMName")) {
1166 const char *n;
1167
1168 r = sd_bus_message_read(message, "s", &n);
1169 if (r < 0)
1170 return r;
1171
1172 if (mode != UNIT_CHECK) {
1173 if (isempty(n))
1174 c->pam_name = mfree(c->pam_name);
1175 else if (free_and_strdup(&c->pam_name, n) < 0)
1176 return -ENOMEM;
1177
1178 unit_write_drop_in_private_format(u, mode, name, "PAMName=%s\n", strempty(n));
1179 }
1180
1181 return 1;
1182
c7040b5d
LP
1183 } else if (streq(name, "Environment")) {
1184
1185 _cleanup_strv_free_ char **l = NULL;
1186
1187 r = sd_bus_message_read_strv(message, &l);
1188 if (r < 0)
1189 return r;
1190
1191 if (!strv_env_is_valid(l))
1192 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
1193
1194 if (mode != UNIT_CHECK) {
1006a62d 1195 _cleanup_free_ char *joined = NULL;
c7040b5d
LP
1196 char **e;
1197
e9876fc9
EV
1198 if (strv_length(l) == 0) {
1199 c->environment = strv_free(c->environment);
1200 unit_write_drop_in_private_format(u, mode, name, "Environment=\n");
1201 } else {
1202 e = strv_env_merge(2, c->environment, l);
1203 if (!e)
1204 return -ENOMEM;
c7040b5d 1205
e9876fc9
EV
1206 strv_free(c->environment);
1207 c->environment = e;
c7040b5d 1208
e9876fc9
EV
1209 joined = strv_join_quoted(c->environment);
1210 if (!joined)
1211 return -ENOMEM;
1212
1213 unit_write_drop_in_private_format(u, mode, name, "Environment=%s\n", joined);
1214 }
c7040b5d
LP
1215 }
1216
d584f638
LP
1217 return 1;
1218
f1db3327
EV
1219 } else if (streq(name, "TimerSlackNSec")) {
1220
1221 nsec_t n;
1222
1223 r = sd_bus_message_read(message, "t", &n);
1224 if (r < 0)
1225 return r;
1226
1227 if (mode != UNIT_CHECK) {
1228 c->timer_slack_nsec = n;
1229 unit_write_drop_in_private_format(u, mode, name, "TimerSlackNSec=" NSEC_FMT "\n", n);
1230 }
1231
1232 return 1;
1233
6b862936
EV
1234 } else if (streq(name, "OOMScoreAdjust")) {
1235 int oa;
1236
1237 r = sd_bus_message_read(message, "i", &oa);
1238 if (r < 0)
1239 return r;
1240
1241 if (!oom_score_adjust_is_valid(oa))
1242 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "OOM score adjust value out of range");
1243
1244 if (mode != UNIT_CHECK) {
1245 c->oom_score_adjust = oa;
1246 c->oom_score_adjust_set = true;
1247 unit_write_drop_in_private_format(u, mode, name, "OOMScoreAdjust=%i\n", oa);
1248 }
1249
1250 return 1;
1251
ceb728cf
NC
1252 } else if (streq(name, "EnvironmentFiles")) {
1253
1254 _cleanup_free_ char *joined = NULL;
1255 _cleanup_fclose_ FILE *f = NULL;
2229f656 1256 _cleanup_free_ char **l = NULL;
ceb728cf 1257 size_t size = 0;
2229f656 1258 char **i;
ceb728cf
NC
1259
1260 r = sd_bus_message_enter_container(message, 'a', "(sb)");
1261 if (r < 0)
1262 return r;
1263
1264 f = open_memstream(&joined, &size);
1265 if (!f)
1266 return -ENOMEM;
1267
2229f656
LP
1268 STRV_FOREACH(i, c->environment_files)
1269 fprintf(f, "EnvironmentFile=%s\n", *i);
ceb728cf
NC
1270
1271 while ((r = sd_bus_message_enter_container(message, 'r', "sb")) > 0) {
1272 const char *path;
1273 int b;
1274
ceb728cf
NC
1275 r = sd_bus_message_read(message, "sb", &path, &b);
1276 if (r < 0)
1277 return r;
1278
1279 r = sd_bus_message_exit_container(message);
1280 if (r < 0)
1281 return r;
1282
1283 if (!isempty(path) && !path_is_absolute(path))
1284 return sd_bus_error_set_errnof(error, EINVAL, "Path %s is not absolute.", path);
1285
1286 if (mode != UNIT_CHECK) {
ceb728cf
NC
1287 char *buf = NULL;
1288
1289 buf = strjoin(b ? "-" : "", path, NULL);
2229f656 1290 if (!buf)
ceb728cf
NC
1291 return -ENOMEM;
1292
1293 fprintf(f, "EnvironmentFile=%s\n", buf);
1294
2229f656 1295 r = strv_consume(&l, buf);
ceb728cf
NC
1296 if (r < 0)
1297 return r;
1298 }
1299 }
1300 if (r < 0)
1301 return r;
1302
b0830e21
LP
1303 r = sd_bus_message_exit_container(message);
1304 if (r < 0)
1305 return r;
1306
2229f656
LP
1307 r = fflush_and_check(f);
1308 if (r < 0)
1309 return r;
ceb728cf 1310
2229f656
LP
1311 if (mode != UNIT_CHECK) {
1312 if (strv_isempty(l)) {
1313 c->environment_files = strv_free(c->environment_files);
ceb728cf 1314 unit_write_drop_in_private(u, mode, name, "EnvironmentFile=\n");
2229f656
LP
1315 } else {
1316 r = strv_extend_strv(&c->environment_files, l, true);
1317 if (r < 0)
1318 return r;
1319
ceb728cf 1320 unit_write_drop_in_private(u, mode, name, joined);
2229f656
LP
1321 }
1322 }
ceb728cf 1323
ceb728cf
NC
1324 return 1;
1325
b4c14404
FB
1326 } else if (streq(name, "PassEnvironment")) {
1327
1328 _cleanup_strv_free_ char **l = NULL;
1329
1330 r = sd_bus_message_read_strv(message, &l);
1331 if (r < 0)
1332 return r;
1333
1334 if (!strv_env_name_is_valid(l))
1335 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
1336
1337 if (mode != UNIT_CHECK) {
1338 if (strv_isempty(l)) {
1339 c->pass_environment = strv_free(c->pass_environment);
1340 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=\n");
1341 } else {
1342 _cleanup_free_ char *joined = NULL;
1343
1344 r = strv_extend_strv(&c->pass_environment, l, true);
1345 if (r < 0)
1346 return r;
1347
1348 joined = strv_join_quoted(c->pass_environment);
1349 if (!joined)
1350 return -ENOMEM;
1351
1352 unit_write_drop_in_private_format(u, mode, name, "PassEnvironment=%s\n", joined);
1353 }
1354 }
1355
1356 return 1;
1357
08596068
EV
1358 } else if (STR_IN_SET(name, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
1359
1360 _cleanup_strv_free_ char **l = NULL;
1361 char ***dirs;
1362 char **p;
1363
1364 r = sd_bus_message_read_strv(message, &l);
1365 if (r < 0)
1366 return r;
1367
1368 STRV_FOREACH(p, l) {
1369 int offset;
1370 if (!utf8_is_valid(*p))
1371 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1372
1373 offset = **p == '-';
1374 if (!path_is_absolute(*p + offset))
1375 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid %s", name);
1376 }
1377
1378 if (mode != UNIT_CHECK) {
1379 _cleanup_free_ char *joined = NULL;
1380
1381 if (streq(name, "ReadWriteDirectories"))
1382 dirs = &c->read_write_dirs;
1383 else if (streq(name, "ReadOnlyDirectories"))
1384 dirs = &c->read_only_dirs;
1385 else if (streq(name, "InaccessibleDirectories"))
1386 dirs = &c->inaccessible_dirs;
1387
1388 if (strv_length(l) == 0) {
1389 *dirs = strv_free(*dirs);
1390 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1391 } else {
1392 r = strv_extend_strv(dirs, l, true);
1393
1394 if (r < 0)
1395 return -ENOMEM;
1396
1397 joined = strv_join_quoted(*dirs);
1398 if (!joined)
1399 return -ENOMEM;
1400
1401 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1402 }
1403
1404 }
1405
1406 return 1;
1407
5664e6cf
EV
1408 } else if (streq(name, "ProtectSystem")) {
1409 const char *s;
1410 ProtectSystem ps;
1411
1412 r = sd_bus_message_read(message, "s", &s);
1413 if (r < 0)
1414 return r;
1415
1416 r = parse_boolean(s);
1417 if (r > 0)
1418 ps = PROTECT_SYSTEM_YES;
1419 else if (r == 0)
1420 ps = PROTECT_SYSTEM_NO;
1421 else {
1422 ps = protect_system_from_string(s);
1423 if (ps < 0)
1424 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect system value");
1425 }
1426
1427 if (mode != UNIT_CHECK) {
1428 c->protect_system = ps;
1429 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1430 }
1431
1432 return 1;
1433
eff58074
EV
1434 } else if (streq(name, "ProtectHome")) {
1435 const char *s;
1436 ProtectHome ph;
1437
1438 r = sd_bus_message_read(message, "s", &s);
1439 if (r < 0)
1440 return r;
1441
1442 r = parse_boolean(s);
1443 if (r > 0)
1444 ph = PROTECT_HOME_YES;
1445 else if (r == 0)
1446 ph = PROTECT_HOME_NO;
1447 else {
1448 ph = protect_home_from_string(s);
1449 if (ph < 0)
1450 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Failed to parse protect home value");
1451 }
1452
1453 if (mode != UNIT_CHECK) {
1454 c->protect_home = ph;
1455 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, s);
1456 }
1457
1458 return 1;
1459
fa21b5e3
EV
1460 } else if (streq(name, "RuntimeDirectory")) {
1461 _cleanup_strv_free_ char **l = NULL;
1462 char **p;
1463
1464 r = sd_bus_message_read_strv(message, &l);
1465 if (r < 0)
1466 return r;
1467
1468 STRV_FOREACH(p, l) {
1469 if (!filename_is_valid(*p))
1470 return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Runtime directory is not valid %s", *p);
1471 }
1472
1473 if (mode != UNIT_CHECK) {
1474 _cleanup_free_ char *joined = NULL;
1475
1476 if (strv_isempty(l)) {
1477 c->runtime_directory = strv_free(c->runtime_directory);
1478 unit_write_drop_in_private_format(u, mode, name, "%s=\n", name);
1479 } else {
1480 r = strv_extend_strv(&c->runtime_directory, l, true);
1481
1482 if (r < 0)
1483 return -ENOMEM;
1484
1485 joined = strv_join_quoted(c->runtime_directory);
1486 if (!joined)
1487 return -ENOMEM;
1488
1489 unit_write_drop_in_private_format(u, mode, name, "%s=%s\n", name, joined);
1490 }
1491 }
1492
1493 return 1;
1494
d584f638
LP
1495 } else if (rlimit_from_string(name) >= 0) {
1496 uint64_t rl;
1497 rlim_t x;
1498
1499 r = sd_bus_message_read(message, "t", &rl);
1500 if (r < 0)
1501 return r;
1502
1503 if (rl == (uint64_t) -1)
1504 x = RLIM_INFINITY;
1505 else {
1506 x = (rlim_t) rl;
1507
1508 if ((uint64_t) x != rl)
1509 return -ERANGE;
1510 }
1511
1512 if (mode != UNIT_CHECK) {
1513 int z;
1514
1515 z = rlimit_from_string(name);
1516
1517 if (!c->rlimit[z]) {
1518 c->rlimit[z] = new(struct rlimit, 1);
1519 if (!c->rlimit[z])
1520 return -ENOMEM;
1521 }
1522
1523 c->rlimit[z]->rlim_cur = c->rlimit[z]->rlim_max = x;
1524
1525 if (x == RLIM_INFINITY)
1526 unit_write_drop_in_private_format(u, mode, name, "%s=infinity\n", name);
1527 else
1528 unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64 "\n", name, rl);
1529 }
1530
c7040b5d
LP
1531 return 1;
1532 }
1533
1534 return 0;
1535}