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