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