chiark / gitweb /
b0448e2c4b3277c035721aa3840ff6aec307aa3d
[elogind.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2012 Holger Hans Peter Freyther
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <assert.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <sched.h>
30 #include <sys/prctl.h>
31 #include <sys/mount.h>
32 #include <linux/fs.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <sys/resource.h>
36 #include <sys/types.h>
37 #include <grp.h>
38
39 #ifdef HAVE_SECCOMP
40 #include <seccomp.h>
41 #endif
42
43 #include "sd-messages.h"
44 #include "unit.h"
45 #include "strv.h"
46 #include "conf-parser.h"
47 #include "load-fragment.h"
48 #include "log.h"
49 #include "ioprio.h"
50 #include "securebits.h"
51 #include "missing.h"
52 #include "unit-name.h"
53 #include "unit-printf.h"
54 #include "utf8.h"
55 #include "path-util.h"
56 #include "env-util.h"
57 #include "cgroup.h"
58 #include "bus-util.h"
59 #include "bus-error.h"
60 #include "errno-list.h"
61 #include "af-list.h"
62
63 #ifdef HAVE_SECCOMP
64 #include "seccomp-util.h"
65 #endif
66
67 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
68 int config_parse_warn_compat(
69                 const char *unit,
70                 const char *filename,
71                 unsigned line,
72                 const char *section,
73                 unsigned section_line,
74                 const char *lvalue,
75                 int ltype,
76                 const char *rvalue,
77                 void *data,
78                 void *userdata) {
79
80         log_syntax(unit, LOG_DEBUG, filename, line, EINVAL,
81                    "Support for option %s= has been disabled at compile time and is ignored",
82                    lvalue);
83         return 0;
84 }
85 #endif
86
87 int config_parse_unit_deps(const char* unit,
88                            const char *filename,
89                            unsigned line,
90                            const char *section,
91                            unsigned section_line,
92                            const char *lvalue,
93                            int ltype,
94                            const char *rvalue,
95                            void *data,
96                            void *userdata) {
97
98         UnitDependency d = ltype;
99         Unit *u = userdata;
100         const char *word, *state;
101         size_t l;
102
103         assert(filename);
104         assert(lvalue);
105         assert(rvalue);
106
107         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
108                 _cleanup_free_ char *t = NULL, *k = NULL;
109                 int r;
110
111                 t = strndup(word, l);
112                 if (!t)
113                         return log_oom();
114
115                 r = unit_name_printf(u, t, &k);
116                 if (r < 0) {
117                         log_syntax(unit, LOG_ERR, filename, line, -r,
118                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
119                         continue;
120                 }
121
122                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
123                 if (r < 0)
124                         log_syntax(unit, LOG_ERR, filename, line, -r,
125                                    "Failed to add dependency on %s, ignoring: %s", k, strerror(-r));
126         }
127
128         return 0;
129 }
130
131 int config_parse_unit_string_printf(const char *unit,
132                                     const char *filename,
133                                     unsigned line,
134                                     const char *section,
135                                     unsigned section_line,
136                                     const char *lvalue,
137                                     int ltype,
138                                     const char *rvalue,
139                                     void *data,
140                                     void *userdata) {
141
142         Unit *u = userdata;
143         _cleanup_free_ char *k = NULL;
144         int r;
145
146         assert(filename);
147         assert(lvalue);
148         assert(rvalue);
149         assert(u);
150
151         r = unit_full_printf(u, rvalue, &k);
152         if (r < 0)
153                 log_syntax(unit, LOG_ERR, filename, line, -r,
154                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
155
156         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype,
157                                    k ? k : rvalue, data, userdata);
158 }
159
160 int config_parse_unit_strv_printf(const char *unit,
161                                   const char *filename,
162                                   unsigned line,
163                                   const char *section,
164                                   unsigned section_line,
165                                   const char *lvalue,
166                                   int ltype,
167                                   const char *rvalue,
168                                   void *data,
169                                   void *userdata) {
170
171         Unit *u = userdata;
172         _cleanup_free_ char *k = NULL;
173         int r;
174
175         assert(filename);
176         assert(lvalue);
177         assert(rvalue);
178         assert(u);
179
180         r = unit_full_printf(u, rvalue, &k);
181         if (r < 0)
182                 log_syntax(unit, LOG_ERR, filename, line, -r,
183                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
184
185         return config_parse_strv(unit, filename, line, section, section_line, lvalue, ltype,
186                                  k ? k : rvalue, data, userdata);
187 }
188
189 int config_parse_unit_path_printf(const char *unit,
190                                   const char *filename,
191                                   unsigned line,
192                                   const char *section,
193                                   unsigned section_line,
194                                   const char *lvalue,
195                                   int ltype,
196                                   const char *rvalue,
197                                   void *data,
198                                   void *userdata) {
199
200         _cleanup_free_ char *k = NULL;
201         Unit *u = userdata;
202         int r;
203
204         assert(filename);
205         assert(lvalue);
206         assert(rvalue);
207         assert(u);
208
209         r = unit_full_printf(u, rvalue, &k);
210         if (r < 0) {
211                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
212                 return 0;
213         }
214
215         return config_parse_path(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
216 }
217
218 int config_parse_unit_path_strv_printf(
219                 const char *unit,
220                 const char *filename,
221                 unsigned line,
222                 const char *section,
223                 unsigned section_line,
224                 const char *lvalue,
225                 int ltype,
226                 const char *rvalue,
227                 void *data,
228                 void *userdata) {
229
230         char ***x = data;
231         const char *word, *state;
232         Unit *u = userdata;
233         size_t l;
234         int r;
235
236         assert(filename);
237         assert(lvalue);
238         assert(rvalue);
239         assert(u);
240
241         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
242                 _cleanup_free_ char *k = NULL;
243                 char t[l+1];
244
245                 memcpy(t, word, l);
246                 t[l] = 0;
247
248                 r = unit_full_printf(u, t, &k);
249                 if (r < 0) {
250                         log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve unit specifiers on %s, ignoring: %s", t, strerror(-r));
251                         return 0;
252                 }
253
254                 if (!utf8_is_valid(k)) {
255                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
256                         return 0;
257                 }
258
259                 if (!path_is_absolute(k)) {
260                         log_syntax(unit, LOG_ERR, filename, line, -r, "Symlink path %s is not absolute, ignoring: %s", k, strerror(-r));
261                         return 0;
262                 }
263
264                 path_kill_slashes(k);
265
266                 r = strv_push(x, k);
267                 if (r < 0)
268                         return log_oom();
269
270                 k = NULL;
271         }
272
273         return 0;
274 }
275
276 int config_parse_socket_listen(const char *unit,
277                                const char *filename,
278                                unsigned line,
279                                const char *section,
280                                unsigned section_line,
281                                const char *lvalue,
282                                int ltype,
283                                const char *rvalue,
284                                void *data,
285                                void *userdata) {
286
287         SocketPort *p, *tail;
288         Socket *s;
289         int r;
290
291         assert(filename);
292         assert(lvalue);
293         assert(rvalue);
294         assert(data);
295
296         s = SOCKET(data);
297
298         if (isempty(rvalue)) {
299                 /* An empty assignment removes all ports */
300                 socket_free_ports(s);
301                 return 0;
302         }
303
304         p = new0(SocketPort, 1);
305         if (!p)
306                 return log_oom();
307
308         if (ltype != SOCKET_SOCKET) {
309
310                 p->type = ltype;
311                 r = unit_full_printf(UNIT(s), rvalue, &p->path);
312                 if (r < 0) {
313                         p->path = strdup(rvalue);
314                         if (!p->path) {
315                                 free(p);
316                                 return log_oom();
317                         } else
318                                 log_syntax(unit, LOG_ERR, filename, line, -r,
319                                            "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
320                 }
321
322                 path_kill_slashes(p->path);
323
324         } else if (streq(lvalue, "ListenNetlink")) {
325                 _cleanup_free_ char  *k = NULL;
326
327                 p->type = SOCKET_SOCKET;
328                 r = unit_full_printf(UNIT(s), rvalue, &k);
329                 if (r < 0)
330                         log_syntax(unit, LOG_ERR, filename, line, -r,
331                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
332
333                 r = socket_address_parse_netlink(&p->address, k ? k : rvalue);
334                 if (r < 0) {
335                         log_syntax(unit, LOG_ERR, filename, line, -r,
336                                    "Failed to parse address value, ignoring: %s", rvalue);
337                         free(p);
338                         return 0;
339                 }
340
341         } else {
342                 _cleanup_free_ char *k = NULL;
343
344                 p->type = SOCKET_SOCKET;
345                 r = unit_full_printf(UNIT(s), rvalue, &k);
346                 if (r < 0)
347                         log_syntax(unit, LOG_ERR, filename, line, -r,
348                                    "Failed to resolve unit specifiers on %s, ignoring: %s", rvalue, strerror(-r));
349
350                 r = socket_address_parse(&p->address, k ? k : rvalue);
351                 if (r < 0) {
352                         log_syntax(unit, LOG_ERR, filename, line, -r,
353                                    "Failed to parse address value, ignoring: %s", rvalue);
354                         free(p);
355                         return 0;
356                 }
357
358                 if (streq(lvalue, "ListenStream"))
359                         p->address.type = SOCK_STREAM;
360                 else if (streq(lvalue, "ListenDatagram"))
361                         p->address.type = SOCK_DGRAM;
362                 else {
363                         assert(streq(lvalue, "ListenSequentialPacket"));
364                         p->address.type = SOCK_SEQPACKET;
365                 }
366
367                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
368                         log_syntax(unit, LOG_ERR, filename, line, ENOTSUP,
369                                    "Address family not supported, ignoring: %s", rvalue);
370                         free(p);
371                         return 0;
372                 }
373         }
374
375         p->fd = -1;
376         p->socket = s;
377
378         if (s->ports) {
379                 LIST_FIND_TAIL(port, s->ports, tail);
380                 LIST_INSERT_AFTER(port, s->ports, tail, p);
381         } else
382                 LIST_PREPEND(port, s->ports, p);
383
384         return 0;
385 }
386
387 int config_parse_socket_bind(const char *unit,
388                              const char *filename,
389                              unsigned line,
390                              const char *section,
391                              unsigned section_line,
392                              const char *lvalue,
393                              int ltype,
394                              const char *rvalue,
395                              void *data,
396                              void *userdata) {
397
398         Socket *s;
399         SocketAddressBindIPv6Only b;
400
401         assert(filename);
402         assert(lvalue);
403         assert(rvalue);
404         assert(data);
405
406         s = SOCKET(data);
407
408         b = socket_address_bind_ipv6_only_from_string(rvalue);
409         if (b < 0) {
410                 int r;
411
412                 r = parse_boolean(rvalue);
413                 if (r < 0) {
414                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
415                                    "Failed to parse bind IPv6 only value, ignoring: %s", rvalue);
416                         return 0;
417                 }
418
419                 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
420         } else
421                 s->bind_ipv6_only = b;
422
423         return 0;
424 }
425
426 int config_parse_exec_nice(const char *unit,
427                            const char *filename,
428                            unsigned line,
429                            const char *section,
430                            unsigned section_line,
431                            const char *lvalue,
432                            int ltype,
433                            const char *rvalue,
434                            void *data,
435                            void *userdata) {
436
437         ExecContext *c = data;
438         int priority, r;
439
440         assert(filename);
441         assert(lvalue);
442         assert(rvalue);
443         assert(data);
444
445         r = safe_atoi(rvalue, &priority);
446         if (r < 0) {
447                 log_syntax(unit, LOG_ERR, filename, line, -r,
448                            "Failed to parse nice priority, ignoring: %s. ", rvalue);
449                 return 0;
450         }
451
452         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
453                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
454                            "Nice priority out of range, ignoring: %s", rvalue);
455                 return 0;
456         }
457
458         c->nice = priority;
459         c->nice_set = true;
460
461         return 0;
462 }
463
464 int config_parse_exec_oom_score_adjust(const char* unit,
465                                        const char *filename,
466                                        unsigned line,
467                                        const char *section,
468                                        unsigned section_line,
469                                        const char *lvalue,
470                                        int ltype,
471                                        const char *rvalue,
472                                        void *data,
473                                        void *userdata) {
474
475         ExecContext *c = data;
476         int oa, r;
477
478         assert(filename);
479         assert(lvalue);
480         assert(rvalue);
481         assert(data);
482
483         r = safe_atoi(rvalue, &oa);
484         if (r < 0) {
485                 log_syntax(unit, LOG_ERR, filename, line, -r,
486                            "Failed to parse the OOM score adjust value, ignoring: %s", rvalue);
487                 return 0;
488         }
489
490         if (oa < OOM_SCORE_ADJ_MIN || oa > OOM_SCORE_ADJ_MAX) {
491                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
492                            "OOM score adjust value out of range, ignoring: %s", rvalue);
493                 return 0;
494         }
495
496         c->oom_score_adjust = oa;
497         c->oom_score_adjust_set = true;
498
499         return 0;
500 }
501
502 int config_parse_exec(const char *unit,
503                       const char *filename,
504                       unsigned line,
505                       const char *section,
506                       unsigned section_line,
507                       const char *lvalue,
508                       int ltype,
509                       const char *rvalue,
510                       void *data,
511                       void *userdata) {
512
513         ExecCommand **e = data, *nce;
514         char *path, **n;
515         unsigned k;
516         int r;
517
518         assert(filename);
519         assert(lvalue);
520         assert(rvalue);
521         assert(e);
522
523         e += ltype;
524
525         if (isempty(rvalue)) {
526                 /* An empty assignment resets the list */
527                 exec_command_free_list(*e);
528                 *e = NULL;
529                 return 0;
530         }
531
532         /* We accept an absolute path as first argument, or
533          * alternatively an absolute prefixed with @ to allow
534          * overriding of argv[0]. */
535         for (;;) {
536                 int i;
537                 const char *word, *state;
538                 size_t l;
539                 bool honour_argv0 = false, ignore = false;
540
541                 path = NULL;
542                 nce = NULL;
543                 n = NULL;
544
545                 rvalue += strspn(rvalue, WHITESPACE);
546
547                 if (rvalue[0] == 0)
548                         break;
549
550                 for (i = 0; i < 2; i++) {
551                         if (rvalue[0] == '-' && !ignore) {
552                                 ignore = true;
553                                 rvalue ++;
554                         }
555
556                         if (rvalue[0] == '@' && !honour_argv0) {
557                                 honour_argv0 = true;
558                                 rvalue ++;
559                         }
560                 }
561
562                 if (*rvalue != '/') {
563                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
564                                    "Executable path is not absolute, ignoring: %s", rvalue);
565                         return 0;
566                 }
567
568                 k = 0;
569                 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
570                         if (strneq(word, ";", MAX(l, 1U)))
571                                 break;
572
573                         k++;
574                 }
575
576                 n = new(char*, k + !honour_argv0);
577                 if (!n)
578                         return log_oom();
579
580                 k = 0;
581                 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
582                         if (strneq(word, ";", MAX(l, 1U)))
583                                 break;
584                         else if (strneq(word, "\\;", MAX(l, 1U)))
585                                 word ++;
586
587                         if (honour_argv0 && word == rvalue) {
588                                 assert(!path);
589
590                                 path = strndup(word, l);
591                                 if (!path) {
592                                         r = log_oom();
593                                         goto fail;
594                                 }
595
596                                 if (!utf8_is_valid(path)) {
597                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
598                                         r = 0;
599                                         goto fail;
600                                 }
601
602                         } else {
603                                 char *c;
604
605                                 c = n[k++] = cunescape_length(word, l);
606                                 if (!c) {
607                                         r = log_oom();
608                                         goto fail;
609                                 }
610
611                                 if (!utf8_is_valid(c)) {
612                                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
613                                         r = 0;
614                                         goto fail;
615                                 }
616                         }
617                 }
618
619                 n[k] = NULL;
620
621                 if (!n[0]) {
622                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
623                                    "Invalid command line, ignoring: %s", rvalue);
624                         r = 0;
625                         goto fail;
626                 }
627
628                 if (!path) {
629                         path = strdup(n[0]);
630                         if (!path) {
631                                 r = log_oom();
632                                 goto fail;
633                         }
634                 }
635
636                 assert(path_is_absolute(path));
637
638                 nce = new0(ExecCommand, 1);
639                 if (!nce) {
640                         r = log_oom();
641                         goto fail;
642                 }
643
644                 nce->argv = n;
645                 nce->path = path;
646                 nce->ignore = ignore;
647
648                 path_kill_slashes(nce->path);
649
650                 exec_command_append_list(e, nce);
651
652                 rvalue = state;
653         }
654
655         return 0;
656
657 fail:
658         n[k] = NULL;
659         strv_free(n);
660         free(path);
661         free(nce);
662
663         return r;
664 }
665
666 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
667 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
668
669 int config_parse_socket_bindtodevice(const char* unit,
670                                      const char *filename,
671                                      unsigned line,
672                                      const char *section,
673                                      unsigned section_line,
674                                      const char *lvalue,
675                                      int ltype,
676                                      const char *rvalue,
677                                      void *data,
678                                      void *userdata) {
679
680         Socket *s = data;
681         char *n;
682
683         assert(filename);
684         assert(lvalue);
685         assert(rvalue);
686         assert(data);
687
688         if (rvalue[0] && !streq(rvalue, "*")) {
689                 n = strdup(rvalue);
690                 if (!n)
691                         return log_oom();
692         } else
693                 n = NULL;
694
695         free(s->bind_to_device);
696         s->bind_to_device = n;
697
698         return 0;
699 }
700
701 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
702 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
703
704 int config_parse_exec_io_class(const char *unit,
705                                const char *filename,
706                                unsigned line,
707                                const char *section,
708                                unsigned section_line,
709                                const char *lvalue,
710                                int ltype,
711                                const char *rvalue,
712                                void *data,
713                                void *userdata) {
714
715         ExecContext *c = data;
716         int x;
717
718         assert(filename);
719         assert(lvalue);
720         assert(rvalue);
721         assert(data);
722
723         x = ioprio_class_from_string(rvalue);
724         if (x < 0) {
725                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
726                            "Failed to parse IO scheduling class, ignoring: %s", rvalue);
727                 return 0;
728         }
729
730         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
731         c->ioprio_set = true;
732
733         return 0;
734 }
735
736 int config_parse_exec_io_priority(const char *unit,
737                                   const char *filename,
738                                   unsigned line,
739                                   const char *section,
740                                   unsigned section_line,
741                                   const char *lvalue,
742                                   int ltype,
743                                   const char *rvalue,
744                                   void *data,
745                                   void *userdata) {
746
747         ExecContext *c = data;
748         int i, r;
749
750         assert(filename);
751         assert(lvalue);
752         assert(rvalue);
753         assert(data);
754
755         r = safe_atoi(rvalue, &i);
756         if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
757                 log_syntax(unit, LOG_ERR, filename, line, -r,
758                            "Failed to parse IO priority, ignoring: %s", rvalue);
759                 return 0;
760         }
761
762         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
763         c->ioprio_set = true;
764
765         return 0;
766 }
767
768 int config_parse_exec_cpu_sched_policy(const char *unit,
769                                        const char *filename,
770                                        unsigned line,
771                                        const char *section,
772                                        unsigned section_line,
773                                        const char *lvalue,
774                                        int ltype,
775                                        const char *rvalue,
776                                        void *data,
777                                        void *userdata) {
778
779
780         ExecContext *c = data;
781         int x;
782
783         assert(filename);
784         assert(lvalue);
785         assert(rvalue);
786         assert(data);
787
788         x = sched_policy_from_string(rvalue);
789         if (x < 0) {
790                 log_syntax(unit, LOG_ERR, filename, line, -x,
791                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
792                 return 0;
793         }
794
795         c->cpu_sched_policy = x;
796         /* Moving to or from real-time policy? We need to adjust the priority */
797         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
798         c->cpu_sched_set = true;
799
800         return 0;
801 }
802
803 int config_parse_exec_cpu_sched_prio(const char *unit,
804                                      const char *filename,
805                                      unsigned line,
806                                      const char *section,
807                                      unsigned section_line,
808                                      const char *lvalue,
809                                      int ltype,
810                                      const char *rvalue,
811                                      void *data,
812                                      void *userdata) {
813
814         ExecContext *c = data;
815         int i, min, max, r;
816
817         assert(filename);
818         assert(lvalue);
819         assert(rvalue);
820         assert(data);
821
822         r = safe_atoi(rvalue, &i);
823         if (r < 0) {
824                 log_syntax(unit, LOG_ERR, filename, line, -r,
825                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
826                 return 0;
827         }
828
829         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
830         min = sched_get_priority_min(c->cpu_sched_policy);
831         max = sched_get_priority_max(c->cpu_sched_policy);
832
833         if (i < min || i > max) {
834                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
835                            "CPU scheduling priority is out of range, ignoring: %s", rvalue);
836                 return 0;
837         }
838
839         c->cpu_sched_priority = i;
840         c->cpu_sched_set = true;
841
842         return 0;
843 }
844
845 int config_parse_exec_cpu_affinity(const char *unit,
846                                    const char *filename,
847                                    unsigned line,
848                                    const char *section,
849                                    unsigned section_line,
850                                    const char *lvalue,
851                                    int ltype,
852                                    const char *rvalue,
853                                    void *data,
854                                    void *userdata) {
855
856         ExecContext *c = data;
857         const char *word, *state;
858         size_t l;
859
860         assert(filename);
861         assert(lvalue);
862         assert(rvalue);
863         assert(data);
864
865         if (isempty(rvalue)) {
866                 /* An empty assignment resets the CPU list */
867                 if (c->cpuset)
868                         CPU_FREE(c->cpuset);
869                 c->cpuset = NULL;
870                 return 0;
871         }
872
873         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
874                 _cleanup_free_ char *t = NULL;
875                 int r;
876                 unsigned cpu;
877
878                 t = strndup(word, l);
879                 if (!t)
880                         return log_oom();
881
882                 r = safe_atou(t, &cpu);
883
884                 if (!c->cpuset) {
885                         c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
886                         if (!c->cpuset)
887                                 return log_oom();
888                 }
889
890                 if (r < 0 || cpu >= c->cpuset_ncpus) {
891                         log_syntax(unit, LOG_ERR, filename, line, ERANGE,
892                                    "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
893                         return 0;
894                 }
895
896                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
897         }
898
899         return 0;
900 }
901
902 int config_parse_exec_capabilities(const char *unit,
903                                    const char *filename,
904                                    unsigned line,
905                                    const char *section,
906                                    unsigned section_line,
907                                    const char *lvalue,
908                                    int ltype,
909                                    const char *rvalue,
910                                    void *data,
911                                    void *userdata) {
912
913         ExecContext *c = data;
914         cap_t cap;
915
916         assert(filename);
917         assert(lvalue);
918         assert(rvalue);
919         assert(data);
920
921         cap = cap_from_text(rvalue);
922         if (!cap) {
923                 log_syntax(unit, LOG_ERR, filename, line, errno,
924                            "Failed to parse capabilities, ignoring: %s", rvalue);
925                 return 0;
926         }
927
928         if (c->capabilities)
929                 cap_free(c->capabilities);
930         c->capabilities = cap;
931
932         return 0;
933 }
934
935 int config_parse_exec_secure_bits(const char *unit,
936                                   const char *filename,
937                                   unsigned line,
938                                   const char *section,
939                                   unsigned section_line,
940                                   const char *lvalue,
941                                   int ltype,
942                                   const char *rvalue,
943                                   void *data,
944                                   void *userdata) {
945
946         ExecContext *c = data;
947         size_t l;
948         const char *word, *state;
949
950         assert(filename);
951         assert(lvalue);
952         assert(rvalue);
953         assert(data);
954
955         if (isempty(rvalue)) {
956                 /* An empty assignment resets the field */
957                 c->secure_bits = 0;
958                 return 0;
959         }
960
961         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
962                 if (first_word(word, "keep-caps"))
963                         c->secure_bits |= 1<<SECURE_KEEP_CAPS;
964                 else if (first_word(word, "keep-caps-locked"))
965                         c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
966                 else if (first_word(word, "no-setuid-fixup"))
967                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
968                 else if (first_word(word, "no-setuid-fixup-locked"))
969                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
970                 else if (first_word(word, "noroot"))
971                         c->secure_bits |= 1<<SECURE_NOROOT;
972                 else if (first_word(word, "noroot-locked"))
973                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
974                 else {
975                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
976                                    "Failed to parse secure bits, ignoring: %s", rvalue);
977                         return 0;
978                 }
979         }
980
981         return 0;
982 }
983
984 int config_parse_bounding_set(const char *unit,
985                               const char *filename,
986                               unsigned line,
987                               const char *section,
988                               unsigned section_line,
989                               const char *lvalue,
990                               int ltype,
991                               const char *rvalue,
992                               void *data,
993                               void *userdata) {
994
995         uint64_t *capability_bounding_set_drop = data;
996         const char *word, *state;
997         size_t l;
998         bool invert = false;
999         uint64_t sum = 0;
1000
1001         assert(filename);
1002         assert(lvalue);
1003         assert(rvalue);
1004         assert(data);
1005
1006         if (rvalue[0] == '~') {
1007                 invert = true;
1008                 rvalue++;
1009         }
1010
1011         /* Note that we store this inverted internally, since the
1012          * kernel wants it like this. But we actually expose it
1013          * non-inverted everywhere to have a fully normalized
1014          * interface. */
1015
1016         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
1017                 _cleanup_free_ char *t = NULL;
1018                 int r;
1019                 cap_value_t cap;
1020
1021                 t = strndup(word, l);
1022                 if (!t)
1023                         return log_oom();
1024
1025                 r = cap_from_name(t, &cap);
1026                 if (r < 0) {
1027                         log_syntax(unit, LOG_ERR, filename, line, errno,
1028                                    "Failed to parse capability in bounding set, ignoring: %s", t);
1029                         continue;
1030                 }
1031
1032                 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
1033         }
1034
1035         if (invert)
1036                 *capability_bounding_set_drop |= sum;
1037         else
1038                 *capability_bounding_set_drop |= ~sum;
1039
1040         return 0;
1041 }
1042
1043 int config_parse_limit(const char *unit,
1044                        const char *filename,
1045                        unsigned line,
1046                        const char *section,
1047                        unsigned section_line,
1048                        const char *lvalue,
1049                        int ltype,
1050                        const char *rvalue,
1051                        void *data,
1052                        void *userdata) {
1053
1054         struct rlimit **rl = data;
1055         unsigned long long u;
1056
1057         assert(filename);
1058         assert(lvalue);
1059         assert(rvalue);
1060         assert(data);
1061
1062         rl += ltype;
1063
1064         if (streq(rvalue, "infinity"))
1065                 u = (unsigned long long) RLIM_INFINITY;
1066         else {
1067                 int r;
1068
1069                 r = safe_atollu(rvalue, &u);
1070                 if (r < 0) {
1071                         log_syntax(unit, LOG_ERR, filename, line, -r,
1072                                    "Failed to parse resource value, ignoring: %s", rvalue);
1073                         return 0;
1074                 }
1075         }
1076
1077         if (!*rl) {
1078                 *rl = new(struct rlimit, 1);
1079                 if (!*rl)
1080                         return log_oom();
1081         }
1082
1083         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1084         return 0;
1085 }
1086
1087 #ifdef HAVE_SYSV_COMPAT
1088 int config_parse_sysv_priority(const char *unit,
1089                                const char *filename,
1090                                unsigned line,
1091                                const char *section,
1092                                unsigned section_line,
1093                                const char *lvalue,
1094                                int ltype,
1095                                const char *rvalue,
1096                                void *data,
1097                                void *userdata) {
1098
1099         int *priority = data;
1100         int i, r;
1101
1102         assert(filename);
1103         assert(lvalue);
1104         assert(rvalue);
1105         assert(data);
1106
1107         r = safe_atoi(rvalue, &i);
1108         if (r < 0 || i < 0) {
1109                 log_syntax(unit, LOG_ERR, filename, line, -r,
1110                            "Failed to parse SysV start priority, ignoring: %s", rvalue);
1111                 return 0;
1112         }
1113
1114         *priority = (int) i;
1115         return 0;
1116 }
1117 #endif
1118
1119 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1120
1121 int config_parse_kill_signal(const char *unit,
1122                              const char *filename,
1123                              unsigned line,
1124                              const char *section,
1125                              unsigned section_line,
1126                              const char *lvalue,
1127                              int ltype,
1128                              const char *rvalue,
1129                              void *data,
1130                              void *userdata) {
1131
1132         int *sig = data;
1133         int r;
1134
1135         assert(filename);
1136         assert(lvalue);
1137         assert(rvalue);
1138         assert(sig);
1139
1140         r = signal_from_string_try_harder(rvalue);
1141         if (r <= 0) {
1142                 log_syntax(unit, LOG_ERR, filename, line, -r,
1143                            "Failed to parse kill signal, ignoring: %s", rvalue);
1144                 return 0;
1145         }
1146
1147         *sig = r;
1148         return 0;
1149 }
1150
1151 int config_parse_exec_mount_flags(const char *unit,
1152                                   const char *filename,
1153                                   unsigned line,
1154                                   const char *section,
1155                                   unsigned section_line,
1156                                   const char *lvalue,
1157                                   int ltype,
1158                                   const char *rvalue,
1159                                   void *data,
1160                                   void *userdata) {
1161
1162         ExecContext *c = data;
1163         const char *word, *state;
1164         size_t l;
1165         unsigned long flags = 0;
1166
1167         assert(filename);
1168         assert(lvalue);
1169         assert(rvalue);
1170         assert(data);
1171
1172         FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
1173                 _cleanup_free_ char *t;
1174
1175                 t = strndup(word, l);
1176                 if (!t)
1177                         return log_oom();
1178
1179                 if (streq(t, "shared"))
1180                         flags = MS_SHARED;
1181                 else if (streq(t, "slave"))
1182                         flags = MS_SLAVE;
1183                 else if (streq(word, "private"))
1184                         flags = MS_PRIVATE;
1185                 else {
1186                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
1187                         return 0;
1188                 }
1189         }
1190
1191         c->mount_flags = flags;
1192         return 0;
1193 }
1194
1195 int config_parse_exec_selinux_context(
1196                 const char *unit,
1197                 const char *filename,
1198                 unsigned line,
1199                 const char *section,
1200                 unsigned section_line,
1201                 const char *lvalue,
1202                 int ltype,
1203                 const char *rvalue,
1204                 void *data,
1205                 void *userdata) {
1206
1207         ExecContext *c = data;
1208         Unit *u = userdata;
1209         bool ignore;
1210         char *k;
1211         int r;
1212
1213         assert(filename);
1214         assert(lvalue);
1215         assert(rvalue);
1216         assert(data);
1217
1218         if (isempty(rvalue)) {
1219                 free(c->selinux_context);
1220                 c->selinux_context = NULL;
1221                 c->selinux_context_ignore = false;
1222                 return 0;
1223         }
1224
1225         if (rvalue[0] == '-') {
1226                 ignore = true;
1227                 rvalue++;
1228         } else
1229                 ignore = false;
1230
1231         r = unit_name_printf(u, rvalue, &k);
1232         if (r < 0) {
1233                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1234                 return 0;
1235         }
1236
1237         free(c->selinux_context);
1238         c->selinux_context = k;
1239         c->selinux_context_ignore = ignore;
1240
1241         return 0;
1242 }
1243
1244 int config_parse_exec_apparmor_profile(
1245                 const char *unit,
1246                 const char *filename,
1247                 unsigned line,
1248                 const char *section,
1249                 unsigned section_line,
1250                 const char *lvalue,
1251                 int ltype,
1252                 const char *rvalue,
1253                 void *data,
1254                 void *userdata) {
1255
1256         ExecContext *c = data;
1257         Unit *u = userdata;
1258         bool ignore;
1259         char *k;
1260         int r;
1261
1262         assert(filename);
1263         assert(lvalue);
1264         assert(rvalue);
1265         assert(data);
1266
1267         if (isempty(rvalue)) {
1268                 free(c->apparmor_profile);
1269                 c->apparmor_profile = NULL;
1270                 c->apparmor_profile_ignore = false;
1271                 return 0;
1272         }
1273
1274         if (rvalue[0] == '-') {
1275                 ignore = true;
1276                 rvalue++;
1277         } else
1278                 ignore = false;
1279
1280         r = unit_name_printf(u, rvalue, &k);
1281         if (r < 0) {
1282                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1283                 return 0;
1284         }
1285
1286         free(c->apparmor_profile);
1287         c->apparmor_profile = k;
1288         c->apparmor_profile_ignore = ignore;
1289
1290         return 0;
1291 }
1292
1293 int config_parse_timer(const char *unit,
1294                        const char *filename,
1295                        unsigned line,
1296                        const char *section,
1297                        unsigned section_line,
1298                        const char *lvalue,
1299                        int ltype,
1300                        const char *rvalue,
1301                        void *data,
1302                        void *userdata) {
1303
1304         Timer *t = data;
1305         usec_t u = 0;
1306         TimerValue *v;
1307         TimerBase b;
1308         CalendarSpec *c = NULL;
1309
1310         assert(filename);
1311         assert(lvalue);
1312         assert(rvalue);
1313         assert(data);
1314
1315         if (isempty(rvalue)) {
1316                 /* Empty assignment resets list */
1317                 timer_free_values(t);
1318                 return 0;
1319         }
1320
1321         b = timer_base_from_string(lvalue);
1322         if (b < 0) {
1323                 log_syntax(unit, LOG_ERR, filename, line, -b,
1324                            "Failed to parse timer base, ignoring: %s", lvalue);
1325                 return 0;
1326         }
1327
1328         if (b == TIMER_CALENDAR) {
1329                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1330                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1331                                    "Failed to parse calendar specification, ignoring: %s",
1332                                    rvalue);
1333                         return 0;
1334                 }
1335         } else {
1336                 if (parse_sec(rvalue, &u) < 0) {
1337                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1338                                    "Failed to parse timer value, ignoring: %s",
1339                                    rvalue);
1340                         return 0;
1341                 }
1342         }
1343
1344         v = new0(TimerValue, 1);
1345         if (!v)
1346                 return log_oom();
1347
1348         v->base = b;
1349         v->value = u;
1350         v->calendar_spec = c;
1351
1352         LIST_PREPEND(value, t->values, v);
1353
1354         return 0;
1355 }
1356
1357 int config_parse_trigger_unit(
1358                 const char *unit,
1359                 const char *filename,
1360                 unsigned line,
1361                 const char *section,
1362                 unsigned section_line,
1363                 const char *lvalue,
1364                 int ltype,
1365                 const char *rvalue,
1366                 void *data,
1367                 void *userdata) {
1368
1369         _cleanup_free_ char *p = NULL;
1370         Unit *u = data;
1371         UnitType type;
1372         int r;
1373
1374         assert(filename);
1375         assert(lvalue);
1376         assert(rvalue);
1377         assert(data);
1378
1379         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1380                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1381                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1382                 return 0;
1383         }
1384
1385         r = unit_name_printf(u, rvalue, &p);
1386         if (r < 0)
1387                 log_syntax(unit, LOG_ERR, filename, line, -r,
1388                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1389
1390         type = unit_name_to_type(p ?: rvalue);
1391         if (type < 0) {
1392                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1393                            "Unit type not valid, ignoring: %s", rvalue);
1394                 return 0;
1395         }
1396
1397         if (type == u->type) {
1398                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1399                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1400                 return 0;
1401         }
1402
1403         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1404         if (r < 0) {
1405                 log_syntax(unit, LOG_ERR, filename, line, -r,
1406                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1407                 return 0;
1408         }
1409
1410         return 0;
1411 }
1412
1413 int config_parse_path_spec(const char *unit,
1414                            const char *filename,
1415                            unsigned line,
1416                            const char *section,
1417                            unsigned section_line,
1418                            const char *lvalue,
1419                            int ltype,
1420                            const char *rvalue,
1421                            void *data,
1422                            void *userdata) {
1423
1424         Path *p = data;
1425         PathSpec *s;
1426         PathType b;
1427         _cleanup_free_ char *k = NULL;
1428         int r;
1429
1430         assert(filename);
1431         assert(lvalue);
1432         assert(rvalue);
1433         assert(data);
1434
1435         if (isempty(rvalue)) {
1436                 /* Empty assignment clears list */
1437                 path_free_specs(p);
1438                 return 0;
1439         }
1440
1441         b = path_type_from_string(lvalue);
1442         if (b < 0) {
1443                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1444                            "Failed to parse path type, ignoring: %s", lvalue);
1445                 return 0;
1446         }
1447
1448         r = unit_full_printf(UNIT(p), rvalue, &k);
1449         if (r < 0) {
1450                 k = strdup(rvalue);
1451                 if (!k)
1452                         return log_oom();
1453                 else
1454                         log_syntax(unit, LOG_ERR, filename, line, -r,
1455                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1456                                    rvalue);
1457         }
1458
1459         if (!path_is_absolute(k)) {
1460                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1461                            "Path is not absolute, ignoring: %s", k);
1462                 return 0;
1463         }
1464
1465         s = new0(PathSpec, 1);
1466         if (!s)
1467                 return log_oom();
1468
1469         s->unit = UNIT(p);
1470         s->path = path_kill_slashes(k);
1471         k = NULL;
1472         s->type = b;
1473         s->inotify_fd = -1;
1474
1475         LIST_PREPEND(spec, p->specs, s);
1476
1477         return 0;
1478 }
1479
1480 int config_parse_socket_service(const char *unit,
1481                                 const char *filename,
1482                                 unsigned line,
1483                                 const char *section,
1484                                 unsigned section_line,
1485                                 const char *lvalue,
1486                                 int ltype,
1487                                 const char *rvalue,
1488                                 void *data,
1489                                 void *userdata) {
1490
1491         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1492         Socket *s = data;
1493         int r;
1494         Unit *x;
1495         _cleanup_free_ char *p = NULL;
1496
1497         assert(filename);
1498         assert(lvalue);
1499         assert(rvalue);
1500         assert(data);
1501
1502         r = unit_name_printf(UNIT(s), rvalue, &p);
1503         if (r < 0) {
1504                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1505                 return 0;
1506         }
1507
1508         if (!endswith(p, ".service")) {
1509                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1510                 return 0;
1511         }
1512
1513         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1514         if (r < 0) {
1515                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1516                 return 0;
1517         }
1518
1519         unit_ref_set(&s->service, x);
1520
1521         return 0;
1522 }
1523
1524 int config_parse_service_sockets(const char *unit,
1525                                  const char *filename,
1526                                  unsigned line,
1527                                  const char *section,
1528                                  unsigned section_line,
1529                                  const char *lvalue,
1530                                  int ltype,
1531                                  const char *rvalue,
1532                                  void *data,
1533                                  void *userdata) {
1534
1535         Service *s = data;
1536         int r;
1537         const char *word, *state;
1538         size_t l;
1539
1540         assert(filename);
1541         assert(lvalue);
1542         assert(rvalue);
1543         assert(data);
1544
1545         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
1546                 _cleanup_free_ char *t = NULL, *k = NULL;
1547
1548                 t = strndup(word, l);
1549                 if (!t)
1550                         return log_oom();
1551
1552                 r = unit_name_printf(UNIT(s), t, &k);
1553                 if (r < 0)
1554                         log_syntax(unit, LOG_ERR, filename, line, -r,
1555                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1556
1557                 if (!endswith(k ?: t, ".socket")) {
1558                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1559                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1560                         continue;
1561                 }
1562
1563                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1564                 if (r < 0)
1565                         log_syntax(unit, LOG_ERR, filename, line, -r,
1566                                    "Failed to add dependency on %s, ignoring: %s",
1567                                    k ?: t, strerror(-r));
1568
1569                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1570                 if (r < 0)
1571                         return r;
1572         }
1573
1574         return 0;
1575 }
1576
1577 int config_parse_service_timeout(const char *unit,
1578                                  const char *filename,
1579                                  unsigned line,
1580                                  const char *section,
1581                                  unsigned section_line,
1582                                  const char *lvalue,
1583                                  int ltype,
1584                                  const char *rvalue,
1585                                  void *data,
1586                                  void *userdata) {
1587
1588         Service *s = userdata;
1589         int r;
1590
1591         assert(filename);
1592         assert(lvalue);
1593         assert(rvalue);
1594         assert(s);
1595
1596         r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1597                              rvalue, data, userdata);
1598         if (r < 0)
1599                 return r;
1600
1601         if (streq(lvalue, "TimeoutSec")) {
1602                 s->start_timeout_defined = true;
1603                 s->timeout_stop_usec = s->timeout_start_usec;
1604         } else if (streq(lvalue, "TimeoutStartSec"))
1605                 s->start_timeout_defined = true;
1606
1607         return 0;
1608 }
1609
1610 int config_parse_busname_service(
1611                 const char *unit,
1612                 const char *filename,
1613                 unsigned line,
1614                 const char *section,
1615                 unsigned section_line,
1616                 const char *lvalue,
1617                 int ltype,
1618                 const char *rvalue,
1619                 void *data,
1620                 void *userdata) {
1621
1622         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1623         BusName *n = data;
1624         int r;
1625         Unit *x;
1626         _cleanup_free_ char *p = NULL;
1627
1628         assert(filename);
1629         assert(lvalue);
1630         assert(rvalue);
1631         assert(data);
1632
1633         r = unit_name_printf(UNIT(n), rvalue, &p);
1634         if (r < 0) {
1635                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1636                 return 0;
1637         }
1638
1639         if (!endswith(p, ".service")) {
1640                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1641                 return 0;
1642         }
1643
1644         r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1645         if (r < 0) {
1646                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1647                 return 0;
1648         }
1649
1650         unit_ref_set(&n->service, x);
1651
1652         return 0;
1653 }
1654
1655 DEFINE_CONFIG_PARSE_ENUM(config_parse_bus_policy_world, busname_policy_access, BusNamePolicyAccess, "Failed to parse bus name policy access");
1656
1657 int config_parse_bus_policy(
1658                 const char *unit,
1659                 const char *filename,
1660                 unsigned line,
1661                 const char *section,
1662                 unsigned section_line,
1663                 const char *lvalue,
1664                 int ltype,
1665                 const char *rvalue,
1666                 void *data,
1667                 void *userdata) {
1668
1669         _cleanup_free_ BusNamePolicy *p = NULL;
1670         _cleanup_free_ char *id_str = NULL;
1671         BusName *busname = data;
1672         char *access_str;
1673
1674         assert(filename);
1675         assert(lvalue);
1676         assert(rvalue);
1677         assert(data);
1678
1679         p = new0(BusNamePolicy, 1);
1680         if (!p)
1681                 return log_oom();
1682
1683         if (streq(lvalue, "AllowUser"))
1684                 p->type = BUSNAME_POLICY_TYPE_USER;
1685         else if (streq(lvalue, "AllowGroup"))
1686                 p->type = BUSNAME_POLICY_TYPE_GROUP;
1687         else
1688                 assert_not_reached("Unknown lvalue");
1689
1690         id_str = strdup(rvalue);
1691         if (!id_str)
1692                 return log_oom();
1693
1694         access_str = strpbrk(id_str, WHITESPACE);
1695         if (!access_str) {
1696                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy value '%s'", rvalue);
1697                 return 0;
1698         }
1699
1700         *access_str = '\0';
1701         access_str++;
1702         access_str += strspn(access_str, WHITESPACE);
1703
1704         p->access = busname_policy_access_from_string(access_str);
1705         if (p->access < 0) {
1706                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy access type '%s'", access_str);
1707                 return 0;
1708         }
1709
1710         p->name = id_str;
1711         id_str = NULL;
1712
1713         LIST_PREPEND(policy, busname->policy, p);
1714         p = NULL;
1715
1716         return 0;
1717 }
1718
1719 int config_parse_unit_env_file(const char *unit,
1720                                const char *filename,
1721                                unsigned line,
1722                                const char *section,
1723                                unsigned section_line,
1724                                const char *lvalue,
1725                                int ltype,
1726                                const char *rvalue,
1727                                void *data,
1728                                void *userdata) {
1729
1730         char ***env = data;
1731         Unit *u = userdata;
1732         _cleanup_free_ char *n = NULL;
1733         const char *s;
1734         int r;
1735
1736         assert(filename);
1737         assert(lvalue);
1738         assert(rvalue);
1739         assert(data);
1740
1741         if (isempty(rvalue)) {
1742                 /* Empty assignment frees the list */
1743                 strv_free(*env);
1744                 *env = NULL;
1745                 return 0;
1746         }
1747
1748         r = unit_full_printf(u, rvalue, &n);
1749         if (r < 0)
1750                 log_syntax(unit, LOG_ERR, filename, line, r,
1751                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1752
1753         s = n ?: rvalue;
1754         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1755                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1756                            "Path '%s' is not absolute, ignoring.", s);
1757                 return 0;
1758         }
1759
1760         r = strv_extend(env, s);
1761         if (r < 0)
1762                 return log_oom();
1763
1764         return 0;
1765 }
1766
1767 int config_parse_environ(const char *unit,
1768                          const char *filename,
1769                          unsigned line,
1770                          const char *section,
1771                          unsigned section_line,
1772                          const char *lvalue,
1773                          int ltype,
1774                          const char *rvalue,
1775                          void *data,
1776                          void *userdata) {
1777
1778         Unit *u = userdata;
1779         char*** env = data;
1780         const char *word, *state;
1781         size_t l;
1782         _cleanup_free_ char *k = NULL;
1783         int r;
1784
1785         assert(filename);
1786         assert(lvalue);
1787         assert(rvalue);
1788         assert(data);
1789
1790         if (isempty(rvalue)) {
1791                 /* Empty assignment resets the list */
1792                 strv_free(*env);
1793                 *env = NULL;
1794                 return 0;
1795         }
1796
1797         if (u) {
1798                 r = unit_full_printf(u, rvalue, &k);
1799                 if (r < 0)
1800                         log_syntax(unit, LOG_ERR, filename, line, -r,
1801                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1802         }
1803
1804         if (!k)
1805                 k = strdup(rvalue);
1806         if (!k)
1807                 return log_oom();
1808
1809         FOREACH_WORD_QUOTED(word, l, k, state) {
1810                 _cleanup_free_ char *n;
1811                 char **x;
1812
1813                 n = cunescape_length(word, l);
1814                 if (!n)
1815                         return log_oom();
1816
1817                 if (!env_assignment_is_valid(n)) {
1818                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1819                                    "Invalid environment assignment, ignoring: %s", rvalue);
1820                         continue;
1821                 }
1822
1823                 x = strv_env_set(*env, n);
1824                 if (!x)
1825                         return log_oom();
1826
1827                 strv_free(*env);
1828                 *env = x;
1829         }
1830
1831         return 0;
1832 }
1833
1834 int config_parse_ip_tos(const char *unit,
1835                         const char *filename,
1836                         unsigned line,
1837                         const char *section,
1838                         unsigned section_line,
1839                         const char *lvalue,
1840                         int ltype,
1841                         const char *rvalue,
1842                         void *data,
1843                         void *userdata) {
1844
1845         int *ip_tos = data, x;
1846
1847         assert(filename);
1848         assert(lvalue);
1849         assert(rvalue);
1850         assert(data);
1851
1852         x = ip_tos_from_string(rvalue);
1853         if (x < 0) {
1854                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1855                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1856                 return 0;
1857         }
1858
1859         *ip_tos = x;
1860         return 0;
1861 }
1862
1863 int config_parse_unit_condition_path(const char *unit,
1864                                      const char *filename,
1865                                      unsigned line,
1866                                      const char *section,
1867                                      unsigned section_line,
1868                                      const char *lvalue,
1869                                      int ltype,
1870                                      const char *rvalue,
1871                                      void *data,
1872                                      void *userdata) {
1873
1874         ConditionType cond = ltype;
1875         Unit *u = data;
1876         bool trigger, negate;
1877         Condition *c;
1878         _cleanup_free_ char *p = NULL;
1879         int r;
1880
1881         assert(filename);
1882         assert(lvalue);
1883         assert(rvalue);
1884         assert(data);
1885
1886         if (isempty(rvalue)) {
1887                 /* Empty assignment resets the list */
1888                 condition_free_list(u->conditions);
1889                 u->conditions = NULL;
1890                 return 0;
1891         }
1892
1893         trigger = rvalue[0] == '|';
1894         if (trigger)
1895                 rvalue++;
1896
1897         negate = rvalue[0] == '!';
1898         if (negate)
1899                 rvalue++;
1900
1901         r = unit_full_printf(u, rvalue, &p);
1902         if (r < 0)
1903                 log_syntax(unit, LOG_ERR, filename, line, -r,
1904                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1905         if (!p) {
1906                 p = strdup(rvalue);
1907                 if (!p)
1908                         return log_oom();
1909         }
1910
1911         if (!path_is_absolute(p)) {
1912                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1913                            "Path in condition not absolute, ignoring: %s", p);
1914                 return 0;
1915         }
1916
1917         c = condition_new(cond, p, trigger, negate);
1918         if (!c)
1919                 return log_oom();
1920
1921         LIST_PREPEND(conditions, u->conditions, c);
1922         return 0;
1923 }
1924
1925 int config_parse_unit_condition_string(const char *unit,
1926                                        const char *filename,
1927                                        unsigned line,
1928                                        const char *section,
1929                                        unsigned section_line,
1930                                        const char *lvalue,
1931                                        int ltype,
1932                                        const char *rvalue,
1933                                        void *data,
1934                                        void *userdata) {
1935
1936         ConditionType cond = ltype;
1937         Unit *u = data;
1938         bool trigger, negate;
1939         Condition *c;
1940         _cleanup_free_ char *s = NULL;
1941         int r;
1942
1943         assert(filename);
1944         assert(lvalue);
1945         assert(rvalue);
1946         assert(data);
1947
1948         if (isempty(rvalue)) {
1949                 /* Empty assignment resets the list */
1950                 condition_free_list(u->conditions);
1951                 u->conditions = NULL;
1952                 return 0;
1953         }
1954
1955         trigger = rvalue[0] == '|';
1956         if (trigger)
1957                 rvalue++;
1958
1959         negate = rvalue[0] == '!';
1960         if (negate)
1961                 rvalue++;
1962
1963         r = unit_full_printf(u, rvalue, &s);
1964         if (r < 0)
1965                 log_syntax(unit, LOG_ERR, filename, line, -r,
1966                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1967         if (!s) {
1968                 s = strdup(rvalue);
1969                 if (!s)
1970                         return log_oom();
1971         }
1972
1973         c = condition_new(cond, s, trigger, negate);
1974         if (!c)
1975                 return log_oom();
1976
1977         LIST_PREPEND(conditions, u->conditions, c);
1978         return 0;
1979 }
1980
1981 int config_parse_unit_condition_null(const char *unit,
1982                                      const char *filename,
1983                                      unsigned line,
1984                                      const char *section,
1985                                      unsigned section_line,
1986                                      const char *lvalue,
1987                                      int ltype,
1988                                      const char *rvalue,
1989                                      void *data,
1990                                      void *userdata) {
1991
1992         Unit *u = data;
1993         Condition *c;
1994         bool trigger, negate;
1995         int b;
1996
1997         assert(filename);
1998         assert(lvalue);
1999         assert(rvalue);
2000         assert(data);
2001
2002         if (isempty(rvalue)) {
2003                 /* Empty assignment resets the list */
2004                 condition_free_list(u->conditions);
2005                 u->conditions = NULL;
2006                 return 0;
2007         }
2008
2009         trigger = rvalue[0] == '|';
2010         if (trigger)
2011                 rvalue++;
2012
2013         negate = rvalue[0] == '!';
2014         if (negate)
2015                 rvalue++;
2016
2017         b = parse_boolean(rvalue);
2018         if (b < 0) {
2019                 log_syntax(unit, LOG_ERR, filename, line, -b,
2020                            "Failed to parse boolean value in condition, ignoring: %s",
2021                            rvalue);
2022                 return 0;
2023         }
2024
2025         if (!b)
2026                 negate = !negate;
2027
2028         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
2029         if (!c)
2030                 return log_oom();
2031
2032         LIST_PREPEND(conditions, u->conditions, c);
2033         return 0;
2034 }
2035
2036 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
2037 DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier");
2038
2039 int config_parse_unit_requires_mounts_for(
2040                 const char *unit,
2041                 const char *filename,
2042                 unsigned line,
2043                 const char *section,
2044                 unsigned section_line,
2045                 const char *lvalue,
2046                 int ltype,
2047                 const char *rvalue,
2048                 void *data,
2049                 void *userdata) {
2050
2051         Unit *u = userdata;
2052         const char *word, *state;
2053         size_t l;
2054
2055         assert(filename);
2056         assert(lvalue);
2057         assert(rvalue);
2058         assert(data);
2059
2060         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2061                 int r;
2062                 _cleanup_free_ char *n;
2063
2064                 n = strndup(word, l);
2065                 if (!n)
2066                         return log_oom();
2067
2068                 if (!utf8_is_valid(n)) {
2069                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2070                         continue;
2071                 }
2072
2073                 r = unit_require_mounts_for(u, n);
2074                 if (r < 0) {
2075                         log_syntax(unit, LOG_ERR, filename, line, r,
2076                                    "Failed to add required mount for, ignoring: %s", rvalue);
2077                         continue;
2078                 }
2079         }
2080
2081         return 0;
2082 }
2083
2084 int config_parse_documentation(const char *unit,
2085                                const char *filename,
2086                                unsigned line,
2087                                const char *section,
2088                                unsigned section_line,
2089                                const char *lvalue,
2090                                int ltype,
2091                                const char *rvalue,
2092                                void *data,
2093                                void *userdata) {
2094
2095         Unit *u = userdata;
2096         int r;
2097         char **a, **b;
2098
2099         assert(filename);
2100         assert(lvalue);
2101         assert(rvalue);
2102         assert(u);
2103
2104         if (isempty(rvalue)) {
2105                 /* Empty assignment resets the list */
2106                 strv_free(u->documentation);
2107                 u->documentation = NULL;
2108                 return 0;
2109         }
2110
2111         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
2112                                           rvalue, data, userdata);
2113         if (r < 0)
2114                 return r;
2115
2116         for (a = b = u->documentation; a && *a; a++) {
2117
2118                 if (is_valid_documentation_url(*a))
2119                         *(b++) = *a;
2120                 else {
2121                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2122                                    "Invalid URL, ignoring: %s", *a);
2123                         free(*a);
2124                 }
2125         }
2126         if (b)
2127                 *b = NULL;
2128
2129         return r;
2130 }
2131
2132 #ifdef HAVE_SECCOMP
2133 int config_parse_syscall_filter(
2134                 const char *unit,
2135                 const char *filename,
2136                 unsigned line,
2137                 const char *section,
2138                 unsigned section_line,
2139                 const char *lvalue,
2140                 int ltype,
2141                 const char *rvalue,
2142                 void *data,
2143                 void *userdata) {
2144
2145         static const char default_syscalls[] =
2146                 "execve\0"
2147                 "exit\0"
2148                 "exit_group\0"
2149                 "rt_sigreturn\0"
2150                 "sigreturn\0";
2151
2152         ExecContext *c = data;
2153         Unit *u = userdata;
2154         bool invert = false;
2155         const char *word, *state;
2156         size_t l;
2157         int r;
2158
2159         assert(filename);
2160         assert(lvalue);
2161         assert(rvalue);
2162         assert(u);
2163
2164         if (isempty(rvalue)) {
2165                 /* Empty assignment resets the list */
2166                 set_free(c->syscall_filter);
2167                 c->syscall_filter = NULL;
2168                 c->syscall_whitelist = false;
2169                 return 0;
2170         }
2171
2172         if (rvalue[0] == '~') {
2173                 invert = true;
2174                 rvalue++;
2175         }
2176
2177         if (!c->syscall_filter) {
2178                 c->syscall_filter = set_new(trivial_hash_func, trivial_compare_func);
2179                 if (!c->syscall_filter)
2180                         return log_oom();
2181
2182                 if (invert)
2183                         /* Allow everything but the ones listed */
2184                         c->syscall_whitelist = false;
2185                 else {
2186                         const char *i;
2187
2188                         /* Allow nothing but the ones listed */
2189                         c->syscall_whitelist = true;
2190
2191                         /* Accept default syscalls if we are on a whitelist */
2192                         NULSTR_FOREACH(i, default_syscalls)  {
2193                                 int id;
2194
2195                                 id = seccomp_syscall_resolve_name(i);
2196                                 if (id < 0)
2197                                         continue;
2198
2199                                 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2200                                 if (r == -EEXIST)
2201                                         continue;
2202                                 if (r < 0)
2203                                         return log_oom();
2204                         }
2205                 }
2206         }
2207
2208         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2209                 _cleanup_free_ char *t = NULL;
2210                 int id;
2211
2212                 t = strndup(word, l);
2213                 if (!t)
2214                         return log_oom();
2215
2216                 id = seccomp_syscall_resolve_name(t);
2217                 if (id < 0)  {
2218                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call, ignoring: %s", t);
2219                         continue;
2220                 }
2221
2222                 /* If we previously wanted to forbid a syscall and now
2223                  * we want to allow it, then remove it from the list
2224                  */
2225                 if (!invert == c->syscall_whitelist)  {
2226                         r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2227                         if (r == -EEXIST)
2228                                 continue;
2229                         if (r < 0)
2230                                 return log_oom();
2231                 } else
2232                         set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2233         }
2234
2235         /* Turn on NNP, but only if it wasn't configured explicitly
2236          * before, and only if we are in user mode. */
2237         if (!c->no_new_privileges_set && u->manager->running_as == SYSTEMD_USER)
2238                 c->no_new_privileges = true;
2239
2240         return 0;
2241 }
2242
2243 int config_parse_syscall_archs(
2244                 const char *unit,
2245                 const char *filename,
2246                 unsigned line,
2247                 const char *section,
2248                 unsigned section_line,
2249                 const char *lvalue,
2250                 int ltype,
2251                 const char *rvalue,
2252                 void *data,
2253                 void *userdata) {
2254
2255         Set **archs = data;
2256         const char *word, *state;
2257         size_t l;
2258         int r;
2259
2260         if (isempty(rvalue)) {
2261                 set_free(*archs);
2262                 *archs = NULL;
2263                 return 0;
2264         }
2265
2266         r = set_ensure_allocated(archs, trivial_hash_func, trivial_compare_func);
2267         if (r < 0)
2268                 return log_oom();
2269
2270         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2271                 _cleanup_free_ char *t = NULL;
2272                 uint32_t a;
2273
2274                 t = strndup(word, l);
2275                 if (!t)
2276                         return log_oom();
2277
2278                 r = seccomp_arch_from_string(t, &a);
2279                 if (r < 0) {
2280                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
2281                         continue;
2282                 }
2283
2284                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2285                 if (r == -EEXIST)
2286                         continue;
2287                 if (r < 0)
2288                         return log_oom();
2289         }
2290
2291         return 0;
2292 }
2293
2294 int config_parse_syscall_errno(
2295                 const char *unit,
2296                 const char *filename,
2297                 unsigned line,
2298                 const char *section,
2299                 unsigned section_line,
2300                 const char *lvalue,
2301                 int ltype,
2302                 const char *rvalue,
2303                 void *data,
2304                 void *userdata) {
2305
2306         ExecContext *c = data;
2307         int e;
2308
2309         assert(filename);
2310         assert(lvalue);
2311         assert(rvalue);
2312
2313         if (isempty(rvalue)) {
2314                 /* Empty assignment resets to KILL */
2315                 c->syscall_errno = 0;
2316                 return 0;
2317         }
2318
2319         e = errno_from_name(rvalue);
2320         if (e < 0) {
2321                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse error number, ignoring: %s", rvalue);
2322                 return 0;
2323         }
2324
2325         c->syscall_errno = e;
2326         return 0;
2327 }
2328
2329 int config_parse_address_families(
2330                 const char *unit,
2331                 const char *filename,
2332                 unsigned line,
2333                 const char *section,
2334                 unsigned section_line,
2335                 const char *lvalue,
2336                 int ltype,
2337                 const char *rvalue,
2338                 void *data,
2339                 void *userdata) {
2340
2341         ExecContext *c = data;
2342         Unit *u = userdata;
2343         bool invert = false;
2344         const char *word, *state;
2345         size_t l;
2346         int r;
2347
2348         assert(filename);
2349         assert(lvalue);
2350         assert(rvalue);
2351         assert(u);
2352
2353         if (isempty(rvalue)) {
2354                 /* Empty assignment resets the list */
2355                 set_free(c->address_families);
2356                 c->address_families = NULL;
2357                 c->address_families_whitelist = false;
2358                 return 0;
2359         }
2360
2361         if (rvalue[0] == '~') {
2362                 invert = true;
2363                 rvalue++;
2364         }
2365
2366         if (!c->address_families) {
2367                 c->address_families = set_new(trivial_hash_func, trivial_compare_func);
2368                 if (!c->address_families)
2369                         return log_oom();
2370
2371                 c->address_families_whitelist = !invert;
2372         }
2373
2374         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2375                 _cleanup_free_ char *t = NULL;
2376                 int af;
2377
2378                 t = strndup(word, l);
2379                 if (!t)
2380                         return log_oom();
2381
2382                 af = af_from_name(t);
2383                 if (af <= 0)  {
2384                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse address family, ignoring: %s", t);
2385                         continue;
2386                 }
2387
2388                 /* If we previously wanted to forbid an address family and now
2389                  * we want to allow it, then remove it from the list
2390                  */
2391                 if (!invert == c->address_families_whitelist)  {
2392                         r = set_put(c->address_families, INT_TO_PTR(af));
2393                         if (r == -EEXIST)
2394                                 continue;
2395                         if (r < 0)
2396                                 return log_oom();
2397                 } else
2398                         set_remove(c->address_families, INT_TO_PTR(af));
2399         }
2400
2401         return 0;
2402 }
2403 #endif
2404
2405 int config_parse_unit_slice(
2406                 const char *unit,
2407                 const char *filename,
2408                 unsigned line,
2409                 const char *section,
2410                 unsigned section_line,
2411                 const char *lvalue,
2412                 int ltype,
2413                 const char *rvalue,
2414                 void *data,
2415                 void *userdata) {
2416
2417         _cleanup_free_ char *k = NULL;
2418         Unit *u = userdata, *slice;
2419         int r;
2420
2421         assert(filename);
2422         assert(lvalue);
2423         assert(rvalue);
2424         assert(u);
2425
2426         r = unit_name_printf(u, rvalue, &k);
2427         if (r < 0)
2428                 log_syntax(unit, LOG_ERR, filename, line, -r,
2429                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2430         if (!k) {
2431                 k = strdup(rvalue);
2432                 if (!k)
2433                         return log_oom();
2434         }
2435
2436         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2437         if (r < 0) {
2438                 log_syntax(unit, LOG_ERR, filename, line, -r,
2439                            "Failed to load slice unit %s. Ignoring.", k);
2440                 return 0;
2441         }
2442
2443         if (slice->type != UNIT_SLICE) {
2444                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2445                            "Slice unit %s is not a slice. Ignoring.", k);
2446                 return 0;
2447         }
2448
2449         unit_ref_set(&u->slice, slice);
2450         return 0;
2451 }
2452
2453 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2454
2455 int config_parse_cpu_shares(
2456                 const char *unit,
2457                 const char *filename,
2458                 unsigned line,
2459                 const char *section,
2460                 unsigned section_line,
2461                 const char *lvalue,
2462                 int ltype,
2463                 const char *rvalue,
2464                 void *data,
2465                 void *userdata) {
2466
2467         unsigned long *shares = data, lu;
2468         int r;
2469
2470         assert(filename);
2471         assert(lvalue);
2472         assert(rvalue);
2473
2474         if (isempty(rvalue)) {
2475                 *shares = (unsigned long) -1;
2476                 return 0;
2477         }
2478
2479         r = safe_atolu(rvalue, &lu);
2480         if (r < 0 || lu <= 0) {
2481                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU shares '%s' invalid. Ignoring.", rvalue);
2482                 return 0;
2483         }
2484
2485         *shares = lu;
2486         return 0;
2487 }
2488
2489 int config_parse_cpu_quota(
2490                 const char *unit,
2491                 const char *filename,
2492                 unsigned line,
2493                 const char *section,
2494                 unsigned section_line,
2495                 const char *lvalue,
2496                 int ltype,
2497                 const char *rvalue,
2498                 void *data,
2499                 void *userdata) {
2500
2501         CGroupContext *c = data;
2502         double percent;
2503
2504         assert(filename);
2505         assert(lvalue);
2506         assert(rvalue);
2507
2508         if (isempty(rvalue)) {
2509                 c->cpu_quota_per_sec_usec = USEC_INFINITY;
2510                 return 0;
2511         }
2512
2513         if (!endswith(rvalue, "%")) {
2514
2515                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
2516                 return 0;
2517         }
2518
2519         if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
2520                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "CPU quota '%s' invalid. Ignoring.", rvalue);
2521                 return 0;
2522         }
2523
2524         c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100);
2525
2526         return 0;
2527 }
2528
2529 int config_parse_memory_limit(
2530                 const char *unit,
2531                 const char *filename,
2532                 unsigned line,
2533                 const char *section,
2534                 unsigned section_line,
2535                 const char *lvalue,
2536                 int ltype,
2537                 const char *rvalue,
2538                 void *data,
2539                 void *userdata) {
2540
2541         CGroupContext *c = data;
2542         off_t bytes;
2543         int r;
2544
2545         if (isempty(rvalue)) {
2546                 c->memory_limit = (uint64_t) -1;
2547                 return 0;
2548         }
2549
2550         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2551
2552         r = parse_size(rvalue, 1024, &bytes);
2553         if (r < 0) {
2554                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
2555                 return 0;
2556         }
2557
2558         c->memory_limit = (uint64_t) bytes;
2559         return 0;
2560 }
2561
2562 int config_parse_device_allow(
2563                 const char *unit,
2564                 const char *filename,
2565                 unsigned line,
2566                 const char *section,
2567                 unsigned section_line,
2568                 const char *lvalue,
2569                 int ltype,
2570                 const char *rvalue,
2571                 void *data,
2572                 void *userdata) {
2573
2574         _cleanup_free_ char *path = NULL;
2575         CGroupContext *c = data;
2576         CGroupDeviceAllow *a;
2577         const char *m;
2578         size_t n;
2579
2580         if (isempty(rvalue)) {
2581                 while (c->device_allow)
2582                         cgroup_context_free_device_allow(c, c->device_allow);
2583
2584                 return 0;
2585         }
2586
2587         n = strcspn(rvalue, WHITESPACE);
2588         path = strndup(rvalue, n);
2589         if (!path)
2590                 return log_oom();
2591
2592         if (!startswith(path, "/dev/") &&
2593             !startswith(path, "block-") &&
2594             !startswith(path, "char-")) {
2595                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2596                 return 0;
2597         }
2598
2599         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2600         if (isempty(m))
2601                 m = "rwm";
2602
2603         if (!in_charset(m, "rwm")) {
2604                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device rights '%s'. Ignoring.", m);
2605                 return 0;
2606         }
2607
2608         a = new0(CGroupDeviceAllow, 1);
2609         if (!a)
2610                 return log_oom();
2611
2612         a->path = path;
2613         path = NULL;
2614         a->r = !!strchr(m, 'r');
2615         a->w = !!strchr(m, 'w');
2616         a->m = !!strchr(m, 'm');
2617
2618         LIST_PREPEND(device_allow, c->device_allow, a);
2619         return 0;
2620 }
2621
2622 int config_parse_blockio_weight(
2623                 const char *unit,
2624                 const char *filename,
2625                 unsigned line,
2626                 const char *section,
2627                 unsigned section_line,
2628                 const char *lvalue,
2629                 int ltype,
2630                 const char *rvalue,
2631                 void *data,
2632                 void *userdata) {
2633
2634         unsigned long *weight = data, lu;
2635         int r;
2636
2637         assert(filename);
2638         assert(lvalue);
2639         assert(rvalue);
2640
2641         if (isempty(rvalue)) {
2642                 *weight = (unsigned long) -1;
2643                 return 0;
2644         }
2645
2646         r = safe_atolu(rvalue, &lu);
2647         if (r < 0 || lu < 10 || lu > 1000) {
2648                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO weight '%s' invalid. Ignoring.", rvalue);
2649                 return 0;
2650         }
2651
2652         *weight = lu;
2653         return 0;
2654 }
2655
2656 int config_parse_blockio_device_weight(
2657                 const char *unit,
2658                 const char *filename,
2659                 unsigned line,
2660                 const char *section,
2661                 unsigned section_line,
2662                 const char *lvalue,
2663                 int ltype,
2664                 const char *rvalue,
2665                 void *data,
2666                 void *userdata) {
2667
2668         _cleanup_free_ char *path = NULL;
2669         CGroupBlockIODeviceWeight *w;
2670         CGroupContext *c = data;
2671         unsigned long lu;
2672         const char *weight;
2673         size_t n;
2674         int r;
2675
2676         assert(filename);
2677         assert(lvalue);
2678         assert(rvalue);
2679
2680         if (isempty(rvalue)) {
2681                 while (c->blockio_device_weights)
2682                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2683
2684                 return 0;
2685         }
2686
2687         n = strcspn(rvalue, WHITESPACE);
2688         weight = rvalue + n;
2689         if (!*weight) {
2690                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Expected block device and device weight. Ignoring.");
2691                 return 0;
2692         }
2693
2694         path = strndup(rvalue, n);
2695         if (!path)
2696                 return log_oom();
2697
2698         if (!path_startswith(path, "/dev")) {
2699                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2700                 return 0;
2701         }
2702
2703         weight += strspn(weight, WHITESPACE);
2704         r = safe_atolu(weight, &lu);
2705         if (r < 0 || lu < 10 || lu > 1000) {
2706                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO weight '%s' invalid. Ignoring.", rvalue);
2707                 return 0;
2708         }
2709
2710         w = new0(CGroupBlockIODeviceWeight, 1);
2711         if (!w)
2712                 return log_oom();
2713
2714         w->path = path;
2715         path = NULL;
2716
2717         w->weight = lu;
2718
2719         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2720         return 0;
2721 }
2722
2723 int config_parse_blockio_bandwidth(
2724                 const char *unit,
2725                 const char *filename,
2726                 unsigned line,
2727                 const char *section,
2728                 unsigned section_line,
2729                 const char *lvalue,
2730                 int ltype,
2731                 const char *rvalue,
2732                 void *data,
2733                 void *userdata) {
2734
2735         _cleanup_free_ char *path = NULL;
2736         CGroupBlockIODeviceBandwidth *b;
2737         CGroupContext *c = data;
2738         const char *bandwidth;
2739         off_t bytes;
2740         bool read;
2741         size_t n;
2742         int r;
2743
2744         assert(filename);
2745         assert(lvalue);
2746         assert(rvalue);
2747
2748         read = streq("BlockIOReadBandwidth", lvalue);
2749
2750         if (isempty(rvalue)) {
2751                 CGroupBlockIODeviceBandwidth *next;
2752
2753                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2754                         if (b->read == read)
2755                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2756
2757                 return 0;
2758         }
2759
2760         n = strcspn(rvalue, WHITESPACE);
2761         bandwidth = rvalue + n;
2762         bandwidth += strspn(bandwidth, WHITESPACE);
2763
2764         if (!*bandwidth) {
2765                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2766                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2767                 return 0;
2768         }
2769
2770         path = strndup(rvalue, n);
2771         if (!path)
2772                 return log_oom();
2773
2774         if (!path_startswith(path, "/dev")) {
2775                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2776                            "Invalid device node path '%s'. Ignoring.", path);
2777                 return 0;
2778         }
2779
2780         r = parse_size(bandwidth, 1000, &bytes);
2781         if (r < 0 || bytes <= 0) {
2782                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2783                 return 0;
2784         }
2785
2786         b = new0(CGroupBlockIODeviceBandwidth, 1);
2787         if (!b)
2788                 return log_oom();
2789
2790         b->path = path;
2791         path = NULL;
2792         b->bandwidth = (uint64_t) bytes;
2793         b->read = read;
2794
2795         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2796
2797         return 0;
2798 }
2799
2800 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2801
2802 int config_parse_job_mode_isolate(
2803                 const char *unit,
2804                 const char *filename,
2805                 unsigned line,
2806                 const char *section,
2807                 unsigned section_line,
2808                 const char *lvalue,
2809                 int ltype,
2810                 const char *rvalue,
2811                 void *data,
2812                 void *userdata) {
2813
2814         JobMode *m = data;
2815         int r;
2816
2817         assert(filename);
2818         assert(lvalue);
2819         assert(rvalue);
2820
2821         r = parse_boolean(rvalue);
2822         if (r < 0) {
2823                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2824                 return 0;
2825         }
2826
2827         *m = r ? JOB_ISOLATE : JOB_REPLACE;
2828         return 0;
2829 }
2830
2831 int config_parse_personality(
2832                 const char *unit,
2833                 const char *filename,
2834                 unsigned line,
2835                 const char *section,
2836                 unsigned section_line,
2837                 const char *lvalue,
2838                 int ltype,
2839                 const char *rvalue,
2840                 void *data,
2841                 void *userdata) {
2842
2843         unsigned long *personality = data, p;
2844
2845         assert(filename);
2846         assert(lvalue);
2847         assert(rvalue);
2848         assert(personality);
2849
2850         p = personality_from_string(rvalue);
2851         if (p == 0xffffffffUL) {
2852                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2853                            "Failed to parse personality, ignoring: %s", rvalue);
2854                 return 0;
2855         }
2856
2857         *personality = p;
2858         return 0;
2859 }
2860
2861 int config_parse_runtime_directory(
2862                 const char *unit,
2863                 const char *filename,
2864                 unsigned line,
2865                 const char *section,
2866                 unsigned section_line,
2867                 const char *lvalue,
2868                 int ltype,
2869                 const char *rvalue,
2870                 void *data,
2871                 void *userdata) {
2872
2873         char***rt = data;
2874         const char *word, *state;
2875         size_t l;
2876         int r;
2877
2878         assert(filename);
2879         assert(lvalue);
2880         assert(rvalue);
2881         assert(data);
2882
2883         if (isempty(rvalue)) {
2884                 /* Empty assignment resets the list */
2885                 strv_free(*rt);
2886                 *rt = NULL;
2887                 return 0;
2888         }
2889
2890         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2891                 _cleanup_free_ char *n;
2892
2893                 n = strndup(word, l);
2894                 if (!n)
2895                         return log_oom();
2896
2897                 if (!filename_is_safe(n)) {
2898                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Runtime directory is not valid, ignoring assignment: %s", rvalue);
2899                         continue;
2900                 }
2901
2902                 r = strv_push(rt, n);
2903                 if (r < 0)
2904                         return log_oom();
2905
2906                 n = NULL;
2907         }
2908
2909         return 0;
2910 }
2911
2912 int config_parse_set_status(
2913                 const char *unit,
2914                 const char *filename,
2915                 unsigned line,
2916                 const char *section,
2917                 unsigned section_line,
2918                 const char *lvalue,
2919                 int ltype,
2920                 const char *rvalue,
2921                 void *data,
2922                 void *userdata) {
2923
2924         size_t l;
2925         const char *word, *state;
2926         int r;
2927         ExitStatusSet *status_set = data;
2928
2929         assert(filename);
2930         assert(lvalue);
2931         assert(rvalue);
2932         assert(data);
2933
2934         /* Empty assignment resets the list */
2935         if (isempty(rvalue)) {
2936                 exit_status_set_free(status_set);
2937                 return 0;
2938         }
2939
2940         FOREACH_WORD(word, l, rvalue, state) {
2941                 _cleanup_free_ char *temp;
2942                 int val;
2943
2944                 temp = strndup(word, l);
2945                 if (!temp)
2946                         return log_oom();
2947
2948                 r = safe_atoi(temp, &val);
2949                 if (r < 0) {
2950                         val = signal_from_string_try_harder(temp);
2951
2952                         if (val > 0) {
2953                                 r = set_ensure_allocated(&status_set->signal, NULL, NULL);
2954                                 if (r < 0)
2955                                         return log_oom();
2956
2957                                 r = set_put(status_set->signal, INT_TO_PTR(val));
2958                                 if (r < 0) {
2959                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", word);
2960                                         return r;
2961                                 }
2962                         } else {
2963                                 log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", word);
2964                                 return 0;
2965                         }
2966                 } else {
2967                         if (val < 0 || val > 255)
2968                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE, "Value %d is outside range 0-255, ignoring", val);
2969                         else {
2970                                 r = set_ensure_allocated(&status_set->status, NULL, NULL);
2971                                 if (r < 0)
2972                                         return log_oom();
2973
2974                                 r = set_put(status_set->status, INT_TO_PTR(val));
2975                                 if (r < 0) {
2976                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", word);
2977                                         return r;
2978                                 }
2979                         }
2980                 }
2981         }
2982
2983         return 0;
2984 }
2985
2986 int config_parse_namespace_path_strv(
2987                 const char *unit,
2988                 const char *filename,
2989                 unsigned line,
2990                 const char *section,
2991                 unsigned section_line,
2992                 const char *lvalue,
2993                 int ltype,
2994                 const char *rvalue,
2995                 void *data,
2996                 void *userdata) {
2997
2998         char*** sv = data;
2999         const char *word, *state;
3000         size_t l;
3001         int r;
3002
3003         assert(filename);
3004         assert(lvalue);
3005         assert(rvalue);
3006         assert(data);
3007
3008         if (isempty(rvalue)) {
3009                 /* Empty assignment resets the list */
3010                 strv_free(*sv);
3011                 *sv = NULL;
3012                 return 0;
3013         }
3014
3015         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
3016                 _cleanup_free_ char *n;
3017                 int offset;
3018
3019                 n = strndup(word, l);
3020                 if (!n)
3021                         return log_oom();
3022
3023                 if (!utf8_is_valid(n)) {
3024                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
3025                         continue;
3026                 }
3027
3028                 offset = n[0] == '-';
3029                 if (!path_is_absolute(n + offset)) {
3030                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
3031                         continue;
3032                 }
3033
3034                 path_kill_slashes(n);
3035
3036                 r = strv_push(sv, n);
3037                 if (r < 0)
3038                         return log_oom();
3039
3040                 n = NULL;
3041         }
3042
3043         return 0;
3044 }
3045
3046 int config_parse_no_new_privileges(
3047                 const char* unit,
3048                 const char *filename,
3049                 unsigned line,
3050                 const char *section,
3051                 unsigned section_line,
3052                 const char *lvalue,
3053                 int ltype,
3054                 const char *rvalue,
3055                 void *data,
3056                 void *userdata) {
3057
3058         ExecContext *c = data;
3059         int k;
3060
3061         assert(filename);
3062         assert(lvalue);
3063         assert(rvalue);
3064         assert(data);
3065
3066         k = parse_boolean(rvalue);
3067         if (k < 0) {
3068                 log_syntax(unit, LOG_ERR, filename, line, -k, "Failed to parse boolean value, ignoring: %s", rvalue);
3069                 return 0;
3070         }
3071
3072         c->no_new_privileges = !!k;
3073         c->no_new_privileges_set = true;
3074
3075         return 0;
3076 }
3077
3078 int config_parse_protect_home(
3079                 const char* unit,
3080                 const char *filename,
3081                 unsigned line,
3082                 const char *section,
3083                 unsigned section_line,
3084                 const char *lvalue,
3085                 int ltype,
3086                 const char *rvalue,
3087                 void *data,
3088                 void *userdata) {
3089
3090         ExecContext *c = data;
3091         int k;
3092
3093         assert(filename);
3094         assert(lvalue);
3095         assert(rvalue);
3096         assert(data);
3097
3098         /* Our enum shall be a superset of booleans, hence first try
3099          * to parse as as boolean, and then as enum */
3100
3101         k = parse_boolean(rvalue);
3102         if (k > 0)
3103                 c->protect_home = PROTECT_HOME_YES;
3104         else if (k == 0)
3105                 c->protect_home = PROTECT_HOME_NO;
3106         else {
3107                 ProtectHome h;
3108
3109                 h = protect_home_from_string(rvalue);
3110                 if (h < 0){
3111                         log_syntax(unit, LOG_ERR, filename, line, -h, "Failed to parse protect home value, ignoring: %s", rvalue);
3112                         return 0;
3113                 }
3114
3115                 c->protect_home = h;
3116         }
3117
3118         return 0;
3119 }
3120
3121 int config_parse_protect_system(
3122                 const char* unit,
3123                 const char *filename,
3124                 unsigned line,
3125                 const char *section,
3126                 unsigned section_line,
3127                 const char *lvalue,
3128                 int ltype,
3129                 const char *rvalue,
3130                 void *data,
3131                 void *userdata) {
3132
3133         ExecContext *c = data;
3134         int k;
3135
3136         assert(filename);
3137         assert(lvalue);
3138         assert(rvalue);
3139         assert(data);
3140
3141         /* Our enum shall be a superset of booleans, hence first try
3142          * to parse as as boolean, and then as enum */
3143
3144         k = parse_boolean(rvalue);
3145         if (k > 0)
3146                 c->protect_system = PROTECT_SYSTEM_YES;
3147         else if (k == 0)
3148                 c->protect_system = PROTECT_SYSTEM_NO;
3149         else {
3150                 ProtectSystem s;
3151
3152                 s = protect_system_from_string(rvalue);
3153                 if (s < 0){
3154                         log_syntax(unit, LOG_ERR, filename, line, -s, "Failed to parse protect system value, ignoring: %s", rvalue);
3155                         return 0;
3156                 }
3157
3158                 c->protect_system = s;
3159         }
3160
3161         return 0;
3162 }
3163
3164 #define FOLLOW_MAX 8
3165
3166 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
3167         unsigned c = 0;
3168         int fd, r;
3169         FILE *f;
3170         char *id = NULL;
3171
3172         assert(filename);
3173         assert(*filename);
3174         assert(_f);
3175         assert(names);
3176
3177         /* This will update the filename pointer if the loaded file is
3178          * reached by a symlink. The old string will be freed. */
3179
3180         for (;;) {
3181                 char *target, *name;
3182
3183                 if (c++ >= FOLLOW_MAX)
3184                         return -ELOOP;
3185
3186                 path_kill_slashes(*filename);
3187
3188                 /* Add the file name we are currently looking at to
3189                  * the names of this unit, but only if it is a valid
3190                  * unit name. */
3191                 name = basename(*filename);
3192
3193                 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
3194
3195                         id = set_get(names, name);
3196                         if (!id) {
3197                                 id = strdup(name);
3198                                 if (!id)
3199                                         return -ENOMEM;
3200
3201                                 r = set_consume(names, id);
3202                                 if (r < 0)
3203                                         return r;
3204                         }
3205                 }
3206
3207                 /* Try to open the file name, but don't if its a symlink */
3208                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
3209                 if (fd >= 0)
3210                         break;
3211
3212                 if (errno != ELOOP)
3213                         return -errno;
3214
3215                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
3216                 r = readlink_and_make_absolute(*filename, &target);
3217                 if (r < 0)
3218                         return r;
3219
3220                 free(*filename);
3221                 *filename = target;
3222         }
3223
3224         f = fdopen(fd, "re");
3225         if (!f) {
3226                 r = -errno;
3227                 safe_close(fd);
3228                 return r;
3229         }
3230
3231         *_f = f;
3232         *_final = id;
3233         return 0;
3234 }
3235
3236 static int merge_by_names(Unit **u, Set *names, const char *id) {
3237         char *k;
3238         int r;
3239
3240         assert(u);
3241         assert(*u);
3242         assert(names);
3243
3244         /* Let's try to add in all symlink names we found */
3245         while ((k = set_steal_first(names))) {
3246
3247                 /* First try to merge in the other name into our
3248                  * unit */
3249                 r = unit_merge_by_name(*u, k);
3250                 if (r < 0) {
3251                         Unit *other;
3252
3253                         /* Hmm, we couldn't merge the other unit into
3254                          * ours? Then let's try it the other way
3255                          * round */
3256
3257                         other = manager_get_unit((*u)->manager, k);
3258                         free(k);
3259
3260                         if (other) {
3261                                 r = unit_merge(other, *u);
3262                                 if (r >= 0) {
3263                                         *u = other;
3264                                         return merge_by_names(u, names, NULL);
3265                                 }
3266                         }
3267
3268                         return r;
3269                 }
3270
3271                 if (id == k)
3272                         unit_choose_id(*u, id);
3273
3274                 free(k);
3275         }
3276
3277         return 0;
3278 }
3279
3280 static int load_from_path(Unit *u, const char *path) {
3281         int r;
3282         _cleanup_set_free_free_ Set *symlink_names = NULL;
3283         _cleanup_fclose_ FILE *f = NULL;
3284         _cleanup_free_ char *filename = NULL;
3285         char *id = NULL;
3286         Unit *merged;
3287         struct stat st;
3288
3289         assert(u);
3290         assert(path);
3291
3292         symlink_names = set_new(string_hash_func, string_compare_func);
3293         if (!symlink_names)
3294                 return -ENOMEM;
3295
3296         if (path_is_absolute(path)) {
3297
3298                 filename = strdup(path);
3299                 if (!filename)
3300                         return -ENOMEM;
3301
3302                 r = open_follow(&filename, &f, symlink_names, &id);
3303                 if (r < 0) {
3304                         free(filename);
3305                         filename = NULL;
3306
3307                         if (r != -ENOENT)
3308                                 return r;
3309                 }
3310
3311         } else  {
3312                 char **p;
3313
3314                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
3315
3316                         /* Instead of opening the path right away, we manually
3317                          * follow all symlinks and add their name to our unit
3318                          * name set while doing so */
3319                         filename = path_make_absolute(path, *p);
3320                         if (!filename)
3321                                 return -ENOMEM;
3322
3323                         if (u->manager->unit_path_cache &&
3324                             !set_get(u->manager->unit_path_cache, filename))
3325                                 r = -ENOENT;
3326                         else
3327                                 r = open_follow(&filename, &f, symlink_names, &id);
3328
3329                         if (r < 0) {
3330                                 free(filename);
3331                                 filename = NULL;
3332
3333                                 if (r != -ENOENT)
3334                                         return r;
3335
3336                                 /* Empty the symlink names for the next run */
3337                                 set_clear_free(symlink_names);
3338                                 continue;
3339                         }
3340
3341                         break;
3342                 }
3343         }
3344
3345         if (!filename)
3346                 /* Hmm, no suitable file found? */
3347                 return 0;
3348
3349         merged = u;
3350         r = merge_by_names(&merged, symlink_names, id);
3351         if (r < 0)
3352                 return r;
3353
3354         if (merged != u) {
3355                 u->load_state = UNIT_MERGED;
3356                 return 0;
3357         }
3358
3359         if (fstat(fileno(f), &st) < 0)
3360                 return -errno;
3361
3362         if (null_or_empty(&st))
3363                 u->load_state = UNIT_MASKED;
3364         else {
3365                 u->load_state = UNIT_LOADED;
3366
3367                 /* Now, parse the file contents */
3368                 r = config_parse(u->id, filename, f,
3369                                  UNIT_VTABLE(u)->sections,
3370                                  config_item_perf_lookup, load_fragment_gperf_lookup,
3371                                  false, true, false, u);
3372                 if (r < 0)
3373                         return r;
3374         }
3375
3376         free(u->fragment_path);
3377         u->fragment_path = filename;
3378         filename = NULL;
3379
3380         u->fragment_mtime = timespec_load(&st.st_mtim);
3381
3382         if (u->source_path) {
3383                 if (stat(u->source_path, &st) >= 0)
3384                         u->source_mtime = timespec_load(&st.st_mtim);
3385                 else
3386                         u->source_mtime = 0;
3387         }
3388
3389         return 0;
3390 }
3391
3392 int unit_load_fragment(Unit *u) {
3393         int r;
3394         Iterator i;
3395         const char *t;
3396
3397         assert(u);
3398         assert(u->load_state == UNIT_STUB);
3399         assert(u->id);
3400
3401         /* First, try to find the unit under its id. We always look
3402          * for unit files in the default directories, to make it easy
3403          * to override things by placing things in /etc/systemd/system */
3404         r = load_from_path(u, u->id);
3405         if (r < 0)
3406                 return r;
3407
3408         /* Try to find an alias we can load this with */
3409         if (u->load_state == UNIT_STUB)
3410                 SET_FOREACH(t, u->names, i) {
3411
3412                         if (t == u->id)
3413                                 continue;
3414
3415                         r = load_from_path(u, t);
3416                         if (r < 0)
3417                                 return r;
3418
3419                         if (u->load_state != UNIT_STUB)
3420                                 break;
3421                 }
3422
3423         /* And now, try looking for it under the suggested (originally linked) path */
3424         if (u->load_state == UNIT_STUB && u->fragment_path) {
3425
3426                 r = load_from_path(u, u->fragment_path);
3427                 if (r < 0)
3428                         return r;
3429
3430                 if (u->load_state == UNIT_STUB) {
3431                         /* Hmm, this didn't work? Then let's get rid
3432                          * of the fragment path stored for us, so that
3433                          * we don't point to an invalid location. */
3434                         free(u->fragment_path);
3435                         u->fragment_path = NULL;
3436                 }
3437         }
3438
3439         /* Look for a template */
3440         if (u->load_state == UNIT_STUB && u->instance) {
3441                 _cleanup_free_ char *k;
3442
3443                 k = unit_name_template(u->id);
3444                 if (!k)
3445                         return -ENOMEM;
3446
3447                 r = load_from_path(u, k);
3448                 if (r < 0)
3449                         return r;
3450
3451                 if (u->load_state == UNIT_STUB)
3452                         SET_FOREACH(t, u->names, i) {
3453                                 _cleanup_free_ char *z = NULL;
3454
3455                                 if (t == u->id)
3456                                         continue;
3457
3458                                 z = unit_name_template(t);
3459                                 if (!z)
3460                                         return -ENOMEM;
3461
3462                                 r = load_from_path(u, z);
3463                                 if (r < 0)
3464                                         return r;
3465
3466                                 if (u->load_state != UNIT_STUB)
3467                                         break;
3468                         }
3469         }
3470
3471         return 0;
3472 }
3473
3474 void unit_dump_config_items(FILE *f) {
3475         static const struct {
3476                 const ConfigParserCallback callback;
3477                 const char *rvalue;
3478         } table[] = {
3479 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
3480                 { config_parse_warn_compat,           "NOTSUPPORTED" },
3481 #endif
3482                 { config_parse_int,                   "INTEGER" },
3483                 { config_parse_unsigned,              "UNSIGNED" },
3484                 { config_parse_iec_size,              "SIZE" },
3485                 { config_parse_iec_off,               "SIZE" },
3486                 { config_parse_si_size,               "SIZE" },
3487                 { config_parse_bool,                  "BOOLEAN" },
3488                 { config_parse_string,                "STRING" },
3489                 { config_parse_path,                  "PATH" },
3490                 { config_parse_unit_path_printf,      "PATH" },
3491                 { config_parse_strv,                  "STRING [...]" },
3492                 { config_parse_exec_nice,             "NICE" },
3493                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
3494                 { config_parse_exec_io_class,         "IOCLASS" },
3495                 { config_parse_exec_io_priority,      "IOPRIORITY" },
3496                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
3497                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
3498                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
3499                 { config_parse_mode,                  "MODE" },
3500                 { config_parse_unit_env_file,         "FILE" },
3501                 { config_parse_output,                "OUTPUT" },
3502                 { config_parse_input,                 "INPUT" },
3503                 { config_parse_log_facility,          "FACILITY" },
3504                 { config_parse_log_level,             "LEVEL" },
3505                 { config_parse_exec_capabilities,     "CAPABILITIES" },
3506                 { config_parse_exec_secure_bits,      "SECUREBITS" },
3507                 { config_parse_bounding_set,          "BOUNDINGSET" },
3508                 { config_parse_limit,                 "LIMIT" },
3509                 { config_parse_unit_deps,             "UNIT [...]" },
3510                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
3511                 { config_parse_service_type,          "SERVICETYPE" },
3512                 { config_parse_service_restart,       "SERVICERESTART" },
3513 #ifdef HAVE_SYSV_COMPAT
3514                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
3515 #endif
3516                 { config_parse_kill_mode,             "KILLMODE" },
3517                 { config_parse_kill_signal,           "SIGNAL" },
3518                 { config_parse_socket_listen,         "SOCKET [...]" },
3519                 { config_parse_socket_bind,           "SOCKETBIND" },
3520                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
3521                 { config_parse_sec,                   "SECONDS" },
3522                 { config_parse_nsec,                  "NANOSECONDS" },
3523                 { config_parse_namespace_path_strv,   "PATH [...]" },
3524                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
3525                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
3526                 { config_parse_unit_string_printf,    "STRING" },
3527                 { config_parse_trigger_unit,          "UNIT" },
3528                 { config_parse_timer,                 "TIMER" },
3529                 { config_parse_path_spec,             "PATH" },
3530                 { config_parse_notify_access,         "ACCESS" },
3531                 { config_parse_ip_tos,                "TOS" },
3532                 { config_parse_unit_condition_path,   "CONDITION" },
3533                 { config_parse_unit_condition_string, "CONDITION" },
3534                 { config_parse_unit_condition_null,   "CONDITION" },
3535                 { config_parse_unit_slice,            "SLICE" },
3536                 { config_parse_documentation,         "URL" },
3537                 { config_parse_service_timeout,       "SECONDS" },
3538                 { config_parse_failure_action,        "ACTION" },
3539                 { config_parse_set_status,            "STATUS" },
3540                 { config_parse_service_sockets,       "SOCKETS" },
3541                 { config_parse_environ,               "ENVIRON" },
3542 #ifdef HAVE_SECCOMP
3543                 { config_parse_syscall_filter,        "SYSCALLS" },
3544                 { config_parse_syscall_archs,         "ARCHS" },
3545                 { config_parse_syscall_errno,         "ERRNO" },
3546                 { config_parse_address_families,      "FAMILIES" },
3547 #endif
3548                 { config_parse_cpu_shares,            "SHARES" },
3549                 { config_parse_memory_limit,          "LIMIT" },
3550                 { config_parse_device_allow,          "DEVICE" },
3551                 { config_parse_device_policy,         "POLICY" },
3552                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
3553                 { config_parse_blockio_weight,        "WEIGHT" },
3554                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
3555                 { config_parse_long,                  "LONG" },
3556                 { config_parse_socket_service,        "SERVICE" },
3557 #ifdef HAVE_SELINUX
3558                 { config_parse_exec_selinux_context,  "LABEL" },
3559 #endif
3560                 { config_parse_job_mode,              "MODE" },
3561                 { config_parse_job_mode_isolate,      "BOOLEAN" },
3562                 { config_parse_personality,           "PERSONALITY" },
3563         };
3564
3565         const char *prev = NULL;
3566         const char *i;
3567
3568         assert(f);
3569
3570         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
3571                 const char *rvalue = "OTHER", *lvalue;
3572                 unsigned j;
3573                 size_t prefix_len;
3574                 const char *dot;
3575                 const ConfigPerfItem *p;
3576
3577                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
3578
3579                 dot = strchr(i, '.');
3580                 lvalue = dot ? dot + 1 : i;
3581                 prefix_len = dot-i;
3582
3583                 if (dot)
3584                         if (!prev || !strneq(prev, i, prefix_len+1)) {
3585                                 if (prev)
3586                                         fputc('\n', f);
3587
3588                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
3589                         }
3590
3591                 for (j = 0; j < ELEMENTSOF(table); j++)
3592                         if (p->parse == table[j].callback) {
3593                                 rvalue = table[j].rvalue;
3594                                 break;
3595                         }
3596
3597                 fprintf(f, "%s=%s\n", lvalue, rvalue);
3598                 prev = i;
3599         }
3600 }