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