chiark / gitweb /
fa4e931b23c30897e172320f3d77f60a147d4180
[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, "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
1135                         return 0;
1136                 }
1137         }
1138
1139         c->mount_flags = flags;
1140         return 0;
1141 }
1142
1143 int config_parse_exec_selinux_context(
1144                 const char *unit,
1145                 const char *filename,
1146                 unsigned line,
1147                 const char *section,
1148                 unsigned section_line,
1149                 const char *lvalue,
1150                 int ltype,
1151                 const char *rvalue,
1152                 void *data,
1153                 void *userdata) {
1154
1155         ExecContext *c = data;
1156         Unit *u = userdata;
1157         bool ignore;
1158         char *k;
1159         int r;
1160
1161         assert(filename);
1162         assert(lvalue);
1163         assert(rvalue);
1164         assert(data);
1165
1166         if (isempty(rvalue)) {
1167                 free(c->selinux_context);
1168                 c->selinux_context = NULL;
1169                 c->selinux_context_ignore = false;
1170                 return 0;
1171         }
1172
1173         if (rvalue[0] == '-') {
1174                 ignore = true;
1175                 rvalue++;
1176         } else
1177                 ignore = false;
1178
1179         r = unit_name_printf(u, rvalue, &k);
1180         if (r < 0) {
1181                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1182                 return 0;
1183         }
1184
1185         free(c->selinux_context);
1186         c->selinux_context = k;
1187         c->selinux_context_ignore = ignore;
1188
1189         return 0;
1190 }
1191
1192 int config_parse_exec_apparmor_profile(
1193                 const char *unit,
1194                 const char *filename,
1195                 unsigned line,
1196                 const char *section,
1197                 unsigned section_line,
1198                 const char *lvalue,
1199                 int ltype,
1200                 const char *rvalue,
1201                 void *data,
1202                 void *userdata) {
1203
1204         ExecContext *c = data;
1205         Unit *u = userdata;
1206         bool ignore;
1207         char *k;
1208         int r;
1209
1210         assert(filename);
1211         assert(lvalue);
1212         assert(rvalue);
1213         assert(data);
1214
1215         if (isempty(rvalue)) {
1216                 free(c->apparmor_profile);
1217                 c->apparmor_profile = NULL;
1218                 c->apparmor_profile_ignore = false;
1219                 return 0;
1220         }
1221
1222         if (rvalue[0] == '-') {
1223                 ignore = true;
1224                 rvalue++;
1225         } else
1226                 ignore = false;
1227
1228         r = unit_name_printf(u, rvalue, &k);
1229         if (r < 0) {
1230                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1231                 return 0;
1232         }
1233
1234         free(c->apparmor_profile);
1235         c->apparmor_profile = k;
1236         c->apparmor_profile_ignore = ignore;
1237
1238         return 0;
1239 }
1240
1241 int config_parse_timer(const char *unit,
1242                        const char *filename,
1243                        unsigned line,
1244                        const char *section,
1245                        unsigned section_line,
1246                        const char *lvalue,
1247                        int ltype,
1248                        const char *rvalue,
1249                        void *data,
1250                        void *userdata) {
1251
1252         Timer *t = data;
1253         usec_t u = 0;
1254         TimerValue *v;
1255         TimerBase b;
1256         CalendarSpec *c = NULL;
1257         clockid_t id;
1258
1259         assert(filename);
1260         assert(lvalue);
1261         assert(rvalue);
1262         assert(data);
1263
1264         if (isempty(rvalue)) {
1265                 /* Empty assignment resets list */
1266                 timer_free_values(t);
1267                 return 0;
1268         }
1269
1270         b = timer_base_from_string(lvalue);
1271         if (b < 0) {
1272                 log_syntax(unit, LOG_ERR, filename, line, -b,
1273                            "Failed to parse timer base, ignoring: %s", lvalue);
1274                 return 0;
1275         }
1276
1277         if (b == TIMER_CALENDAR) {
1278                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1279                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1280                                    "Failed to parse calendar specification, ignoring: %s",
1281                                    rvalue);
1282                         return 0;
1283                 }
1284
1285                 id = CLOCK_REALTIME;
1286         } else {
1287                 if (parse_sec(rvalue, &u) < 0) {
1288                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1289                                    "Failed to parse timer value, ignoring: %s",
1290                                    rvalue);
1291                         return 0;
1292                 }
1293
1294                 id = CLOCK_MONOTONIC;
1295         }
1296
1297         v = new0(TimerValue, 1);
1298         if (!v)
1299                 return log_oom();
1300
1301         v->base = b;
1302         v->clock_id = id;
1303         v->value = u;
1304         v->calendar_spec = c;
1305
1306         LIST_PREPEND(value, t->values, v);
1307
1308         return 0;
1309 }
1310
1311 int config_parse_trigger_unit(
1312                 const char *unit,
1313                 const char *filename,
1314                 unsigned line,
1315                 const char *section,
1316                 unsigned section_line,
1317                 const char *lvalue,
1318                 int ltype,
1319                 const char *rvalue,
1320                 void *data,
1321                 void *userdata) {
1322
1323         _cleanup_free_ char *p = NULL;
1324         Unit *u = data;
1325         UnitType type;
1326         int r;
1327
1328         assert(filename);
1329         assert(lvalue);
1330         assert(rvalue);
1331         assert(data);
1332
1333         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1334                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1335                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1336                 return 0;
1337         }
1338
1339         r = unit_name_printf(u, rvalue, &p);
1340         if (r < 0)
1341                 log_syntax(unit, LOG_ERR, filename, line, -r,
1342                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1343
1344         type = unit_name_to_type(p ?: rvalue);
1345         if (type < 0) {
1346                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1347                            "Unit type not valid, ignoring: %s", rvalue);
1348                 return 0;
1349         }
1350
1351         if (type == u->type) {
1352                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1353                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1354                 return 0;
1355         }
1356
1357         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1358         if (r < 0) {
1359                 log_syntax(unit, LOG_ERR, filename, line, -r,
1360                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1361                 return 0;
1362         }
1363
1364         return 0;
1365 }
1366
1367 int config_parse_path_spec(const char *unit,
1368                            const char *filename,
1369                            unsigned line,
1370                            const char *section,
1371                            unsigned section_line,
1372                            const char *lvalue,
1373                            int ltype,
1374                            const char *rvalue,
1375                            void *data,
1376                            void *userdata) {
1377
1378         Path *p = data;
1379         PathSpec *s;
1380         PathType b;
1381         _cleanup_free_ char *k = NULL;
1382         int r;
1383
1384         assert(filename);
1385         assert(lvalue);
1386         assert(rvalue);
1387         assert(data);
1388
1389         if (isempty(rvalue)) {
1390                 /* Empty assignment clears list */
1391                 path_free_specs(p);
1392                 return 0;
1393         }
1394
1395         b = path_type_from_string(lvalue);
1396         if (b < 0) {
1397                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1398                            "Failed to parse path type, ignoring: %s", lvalue);
1399                 return 0;
1400         }
1401
1402         r = unit_full_printf(UNIT(p), rvalue, &k);
1403         if (r < 0) {
1404                 k = strdup(rvalue);
1405                 if (!k)
1406                         return log_oom();
1407                 else
1408                         log_syntax(unit, LOG_ERR, filename, line, -r,
1409                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1410                                    rvalue);
1411         }
1412
1413         if (!path_is_absolute(k)) {
1414                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1415                            "Path is not absolute, ignoring: %s", k);
1416                 return 0;
1417         }
1418
1419         s = new0(PathSpec, 1);
1420         if (!s)
1421                 return log_oom();
1422
1423         s->unit = UNIT(p);
1424         s->path = path_kill_slashes(k);
1425         k = NULL;
1426         s->type = b;
1427         s->inotify_fd = -1;
1428
1429         LIST_PREPEND(spec, p->specs, s);
1430
1431         return 0;
1432 }
1433
1434 int config_parse_socket_service(const char *unit,
1435                                 const char *filename,
1436                                 unsigned line,
1437                                 const char *section,
1438                                 unsigned section_line,
1439                                 const char *lvalue,
1440                                 int ltype,
1441                                 const char *rvalue,
1442                                 void *data,
1443                                 void *userdata) {
1444
1445         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1446         Socket *s = data;
1447         int r;
1448         Unit *x;
1449         _cleanup_free_ char *p = NULL;
1450
1451         assert(filename);
1452         assert(lvalue);
1453         assert(rvalue);
1454         assert(data);
1455
1456         r = unit_name_printf(UNIT(s), rvalue, &p);
1457         if (r < 0) {
1458                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1459                 return 0;
1460         }
1461
1462         if (!endswith(p, ".service")) {
1463                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1464                 return 0;
1465         }
1466
1467         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1468         if (r < 0) {
1469                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1470                 return 0;
1471         }
1472
1473         unit_ref_set(&s->service, x);
1474
1475         return 0;
1476 }
1477
1478 int config_parse_service_sockets(const char *unit,
1479                                  const char *filename,
1480                                  unsigned line,
1481                                  const char *section,
1482                                  unsigned section_line,
1483                                  const char *lvalue,
1484                                  int ltype,
1485                                  const char *rvalue,
1486                                  void *data,
1487                                  void *userdata) {
1488
1489         Service *s = data;
1490         int r;
1491         char *state, *w;
1492         size_t l;
1493
1494         assert(filename);
1495         assert(lvalue);
1496         assert(rvalue);
1497         assert(data);
1498
1499         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1500                 _cleanup_free_ char *t = NULL, *k = NULL;
1501
1502                 t = strndup(w, l);
1503                 if (!t)
1504                         return log_oom();
1505
1506                 r = unit_name_printf(UNIT(s), t, &k);
1507                 if (r < 0)
1508                         log_syntax(unit, LOG_ERR, filename, line, -r,
1509                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1510
1511                 if (!endswith(k ?: t, ".socket")) {
1512                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1513                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1514                         continue;
1515                 }
1516
1517                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1518                 if (r < 0)
1519                         log_syntax(unit, LOG_ERR, filename, line, -r,
1520                                    "Failed to add dependency on %s, ignoring: %s",
1521                                    k ?: t, strerror(-r));
1522
1523                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1524                 if (r < 0)
1525                         return r;
1526         }
1527
1528         return 0;
1529 }
1530
1531 int config_parse_service_timeout(const char *unit,
1532                                  const char *filename,
1533                                  unsigned line,
1534                                  const char *section,
1535                                  unsigned section_line,
1536                                  const char *lvalue,
1537                                  int ltype,
1538                                  const char *rvalue,
1539                                  void *data,
1540                                  void *userdata) {
1541
1542         Service *s = userdata;
1543         int r;
1544
1545         assert(filename);
1546         assert(lvalue);
1547         assert(rvalue);
1548         assert(s);
1549
1550         r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1551                              rvalue, data, userdata);
1552         if (r < 0)
1553                 return r;
1554
1555         if (streq(lvalue, "TimeoutSec")) {
1556                 s->start_timeout_defined = true;
1557                 s->timeout_stop_usec = s->timeout_start_usec;
1558         } else if (streq(lvalue, "TimeoutStartSec"))
1559                 s->start_timeout_defined = true;
1560
1561         return 0;
1562 }
1563
1564 int config_parse_busname_service(
1565                 const char *unit,
1566                 const char *filename,
1567                 unsigned line,
1568                 const char *section,
1569                 unsigned section_line,
1570                 const char *lvalue,
1571                 int ltype,
1572                 const char *rvalue,
1573                 void *data,
1574                 void *userdata) {
1575
1576         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1577         BusName *n = data;
1578         int r;
1579         Unit *x;
1580         _cleanup_free_ char *p = NULL;
1581
1582         assert(filename);
1583         assert(lvalue);
1584         assert(rvalue);
1585         assert(data);
1586
1587         r = unit_name_printf(UNIT(n), rvalue, &p);
1588         if (r < 0) {
1589                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1590                 return 0;
1591         }
1592
1593         if (!endswith(p, ".service")) {
1594                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1595                 return 0;
1596         }
1597
1598         r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1599         if (r < 0) {
1600                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1601                 return 0;
1602         }
1603
1604         unit_ref_set(&n->service, x);
1605
1606         return 0;
1607 }
1608
1609 int config_parse_bus_policy(
1610                 const char *unit,
1611                 const char *filename,
1612                 unsigned line,
1613                 const char *section,
1614                 unsigned section_line,
1615                 const char *lvalue,
1616                 int ltype,
1617                 const char *rvalue,
1618                 void *data,
1619                 void *userdata) {
1620
1621         _cleanup_free_ BusNamePolicy *p = NULL;
1622         _cleanup_free_ char *id_str = NULL;
1623         BusName *busname = data;
1624         char *access_str;
1625         int r;
1626
1627         assert(filename);
1628         assert(lvalue);
1629         assert(rvalue);
1630         assert(data);
1631
1632         p = new0(BusNamePolicy, 1);
1633         if (!p)
1634                 return log_oom();
1635
1636         if (streq(lvalue, "AllowUser"))
1637                 p->type = BUSNAME_POLICY_TYPE_USER;
1638         else if (streq(lvalue, "AllowGroup"))
1639                 p->type = BUSNAME_POLICY_TYPE_GROUP;
1640         else if (streq(lvalue, "AllowWorld"))
1641                 p->type = BUSNAME_POLICY_TYPE_WORLD;
1642         else
1643                 assert_not_reached("Unknown lvalue");
1644
1645         id_str = strdup(rvalue);
1646         if (!id_str)
1647                 return log_oom();
1648
1649         if (p->type != BUSNAME_POLICY_TYPE_WORLD) {
1650                 access_str = strchr(id_str, ' ');
1651                 if (!access_str) {
1652                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy value '%s'", rvalue);
1653                         return 0;
1654                 }
1655
1656                 *access_str = '\0';
1657                 access_str++;
1658
1659                 if (p->type == BUSNAME_POLICY_TYPE_USER) {
1660                         const char *user = id_str;
1661
1662                         r = get_user_creds(&user, &p->uid, NULL, NULL, NULL);
1663                         if (r < 0) {
1664                                 log_syntax(unit, LOG_ERR, filename, line, r, "Unable to parse uid from '%s'", id_str);
1665                                 return 0;
1666                         }
1667                 } else {
1668                         const char *group = id_str;
1669
1670                         r = get_group_creds(&group, &p->gid);
1671                         if (r < 0) {
1672                                 log_syntax(unit, LOG_ERR, filename, line, -errno, "Unable to parse gid from '%s'", id_str);
1673                                 return 0;
1674                         }
1675                 }
1676         } else {
1677                 access_str = id_str;
1678         }
1679
1680         p->access = busname_policy_access_from_string(access_str);
1681         if (p->access < 0) {
1682                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid busname policy access type '%s'", access_str);
1683                 return 0;
1684         }
1685
1686         LIST_PREPEND(policy, busname->policy, p);
1687         p = NULL;
1688
1689         return 0;
1690 }
1691
1692 int config_parse_unit_env_file(const char *unit,
1693                                const char *filename,
1694                                unsigned line,
1695                                const char *section,
1696                                unsigned section_line,
1697                                const char *lvalue,
1698                                int ltype,
1699                                const char *rvalue,
1700                                void *data,
1701                                void *userdata) {
1702
1703         char ***env = data;
1704         Unit *u = userdata;
1705         _cleanup_free_ char *n = NULL;
1706         const char *s;
1707         int r;
1708
1709         assert(filename);
1710         assert(lvalue);
1711         assert(rvalue);
1712         assert(data);
1713
1714         if (isempty(rvalue)) {
1715                 /* Empty assignment frees the list */
1716                 strv_free(*env);
1717                 *env = NULL;
1718                 return 0;
1719         }
1720
1721         r = unit_full_printf(u, rvalue, &n);
1722         if (r < 0)
1723                 log_syntax(unit, LOG_ERR, filename, line, r,
1724                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1725
1726         s = n ?: rvalue;
1727         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1728                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1729                            "Path '%s' is not absolute, ignoring.", s);
1730                 return 0;
1731         }
1732
1733         r = strv_extend(env, s);
1734         if (r < 0)
1735                 return log_oom();
1736
1737         return 0;
1738 }
1739
1740 int config_parse_environ(const char *unit,
1741                          const char *filename,
1742                          unsigned line,
1743                          const char *section,
1744                          unsigned section_line,
1745                          const char *lvalue,
1746                          int ltype,
1747                          const char *rvalue,
1748                          void *data,
1749                          void *userdata) {
1750
1751         Unit *u = userdata;
1752         char*** env = data, *w, *state;
1753         size_t l;
1754         _cleanup_free_ char *k = NULL;
1755         int r;
1756
1757         assert(filename);
1758         assert(lvalue);
1759         assert(rvalue);
1760         assert(data);
1761
1762         if (isempty(rvalue)) {
1763                 /* Empty assignment resets the list */
1764                 strv_free(*env);
1765                 *env = NULL;
1766                 return 0;
1767         }
1768
1769         if (u) {
1770                 r = unit_full_printf(u, rvalue, &k);
1771                 if (r < 0)
1772                         log_syntax(unit, LOG_ERR, filename, line, -r,
1773                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1774         }
1775
1776         if (!k)
1777                 k = strdup(rvalue);
1778         if (!k)
1779                 return log_oom();
1780
1781         FOREACH_WORD_QUOTED(w, l, k, state) {
1782                 _cleanup_free_ char *n;
1783                 char **x;
1784
1785                 n = cunescape_length(w, l);
1786                 if (!n)
1787                         return log_oom();
1788
1789                 if (!env_assignment_is_valid(n)) {
1790                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1791                                    "Invalid environment assignment, ignoring: %s", rvalue);
1792                         continue;
1793                 }
1794
1795                 x = strv_env_set(*env, n);
1796                 if (!x)
1797                         return log_oom();
1798
1799                 strv_free(*env);
1800                 *env = x;
1801         }
1802
1803         return 0;
1804 }
1805
1806 int config_parse_ip_tos(const char *unit,
1807                         const char *filename,
1808                         unsigned line,
1809                         const char *section,
1810                         unsigned section_line,
1811                         const char *lvalue,
1812                         int ltype,
1813                         const char *rvalue,
1814                         void *data,
1815                         void *userdata) {
1816
1817         int *ip_tos = data, x;
1818
1819         assert(filename);
1820         assert(lvalue);
1821         assert(rvalue);
1822         assert(data);
1823
1824         x = ip_tos_from_string(rvalue);
1825         if (x < 0) {
1826                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1827                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1828                 return 0;
1829         }
1830
1831         *ip_tos = x;
1832         return 0;
1833 }
1834
1835 int config_parse_unit_condition_path(const char *unit,
1836                                      const char *filename,
1837                                      unsigned line,
1838                                      const char *section,
1839                                      unsigned section_line,
1840                                      const char *lvalue,
1841                                      int ltype,
1842                                      const char *rvalue,
1843                                      void *data,
1844                                      void *userdata) {
1845
1846         ConditionType cond = ltype;
1847         Unit *u = data;
1848         bool trigger, negate;
1849         Condition *c;
1850         _cleanup_free_ char *p = NULL;
1851         int r;
1852
1853         assert(filename);
1854         assert(lvalue);
1855         assert(rvalue);
1856         assert(data);
1857
1858         if (isempty(rvalue)) {
1859                 /* Empty assignment resets the list */
1860                 condition_free_list(u->conditions);
1861                 u->conditions = NULL;
1862                 return 0;
1863         }
1864
1865         trigger = rvalue[0] == '|';
1866         if (trigger)
1867                 rvalue++;
1868
1869         negate = rvalue[0] == '!';
1870         if (negate)
1871                 rvalue++;
1872
1873         r = unit_full_printf(u, rvalue, &p);
1874         if (r < 0)
1875                 log_syntax(unit, LOG_ERR, filename, line, -r,
1876                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1877         if (!p) {
1878                 p = strdup(rvalue);
1879                 if (!p)
1880                         return log_oom();
1881         }
1882
1883         if (!path_is_absolute(p)) {
1884                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1885                            "Path in condition not absolute, ignoring: %s", p);
1886                 return 0;
1887         }
1888
1889         c = condition_new(cond, p, trigger, negate);
1890         if (!c)
1891                 return log_oom();
1892
1893         LIST_PREPEND(conditions, u->conditions, c);
1894         return 0;
1895 }
1896
1897 int config_parse_unit_condition_string(const char *unit,
1898                                        const char *filename,
1899                                        unsigned line,
1900                                        const char *section,
1901                                        unsigned section_line,
1902                                        const char *lvalue,
1903                                        int ltype,
1904                                        const char *rvalue,
1905                                        void *data,
1906                                        void *userdata) {
1907
1908         ConditionType cond = ltype;
1909         Unit *u = data;
1910         bool trigger, negate;
1911         Condition *c;
1912         _cleanup_free_ char *s = NULL;
1913         int r;
1914
1915         assert(filename);
1916         assert(lvalue);
1917         assert(rvalue);
1918         assert(data);
1919
1920         if (isempty(rvalue)) {
1921                 /* Empty assignment resets the list */
1922                 condition_free_list(u->conditions);
1923                 u->conditions = NULL;
1924                 return 0;
1925         }
1926
1927         trigger = rvalue[0] == '|';
1928         if (trigger)
1929                 rvalue++;
1930
1931         negate = rvalue[0] == '!';
1932         if (negate)
1933                 rvalue++;
1934
1935         r = unit_full_printf(u, rvalue, &s);
1936         if (r < 0)
1937                 log_syntax(unit, LOG_ERR, filename, line, -r,
1938                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1939         if (!s) {
1940                 s = strdup(rvalue);
1941                 if (!s)
1942                         return log_oom();
1943         }
1944
1945         c = condition_new(cond, s, trigger, negate);
1946         if (!c)
1947                 return log_oom();
1948
1949         LIST_PREPEND(conditions, u->conditions, c);
1950         return 0;
1951 }
1952
1953 int config_parse_unit_condition_null(const char *unit,
1954                                      const char *filename,
1955                                      unsigned line,
1956                                      const char *section,
1957                                      unsigned section_line,
1958                                      const char *lvalue,
1959                                      int ltype,
1960                                      const char *rvalue,
1961                                      void *data,
1962                                      void *userdata) {
1963
1964         Unit *u = data;
1965         Condition *c;
1966         bool trigger, negate;
1967         int b;
1968
1969         assert(filename);
1970         assert(lvalue);
1971         assert(rvalue);
1972         assert(data);
1973
1974         if (isempty(rvalue)) {
1975                 /* Empty assignment resets the list */
1976                 condition_free_list(u->conditions);
1977                 u->conditions = NULL;
1978                 return 0;
1979         }
1980
1981         trigger = rvalue[0] == '|';
1982         if (trigger)
1983                 rvalue++;
1984
1985         negate = rvalue[0] == '!';
1986         if (negate)
1987                 rvalue++;
1988
1989         b = parse_boolean(rvalue);
1990         if (b < 0) {
1991                 log_syntax(unit, LOG_ERR, filename, line, -b,
1992                            "Failed to parse boolean value in condition, ignoring: %s",
1993                            rvalue);
1994                 return 0;
1995         }
1996
1997         if (!b)
1998                 negate = !negate;
1999
2000         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
2001         if (!c)
2002                 return log_oom();
2003
2004         LIST_PREPEND(conditions, u->conditions, c);
2005         return 0;
2006 }
2007
2008 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
2009 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
2010
2011 int config_parse_unit_requires_mounts_for(
2012                 const char *unit,
2013                 const char *filename,
2014                 unsigned line,
2015                 const char *section,
2016                 unsigned section_line,
2017                 const char *lvalue,
2018                 int ltype,
2019                 const char *rvalue,
2020                 void *data,
2021                 void *userdata) {
2022
2023         Unit *u = userdata;
2024         char *state;
2025         size_t l;
2026         char *w;
2027
2028         assert(filename);
2029         assert(lvalue);
2030         assert(rvalue);
2031         assert(data);
2032
2033         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2034                 int r;
2035                 _cleanup_free_ char *n;
2036
2037                 n = strndup(w, l);
2038                 if (!n)
2039                         return log_oom();
2040
2041                 if (!utf8_is_valid(n)) {
2042                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2043                         continue;
2044                 }
2045
2046                 r = unit_require_mounts_for(u, n);
2047                 if (r < 0) {
2048                         log_syntax(unit, LOG_ERR, filename, line, r,
2049                                    "Failed to add required mount for, ignoring: %s", rvalue);
2050                         continue;
2051                 }
2052         }
2053
2054         return 0;
2055 }
2056
2057 int config_parse_documentation(const char *unit,
2058                                const char *filename,
2059                                unsigned line,
2060                                const char *section,
2061                                unsigned section_line,
2062                                const char *lvalue,
2063                                int ltype,
2064                                const char *rvalue,
2065                                void *data,
2066                                void *userdata) {
2067
2068         Unit *u = userdata;
2069         int r;
2070         char **a, **b;
2071
2072         assert(filename);
2073         assert(lvalue);
2074         assert(rvalue);
2075         assert(u);
2076
2077         if (isempty(rvalue)) {
2078                 /* Empty assignment resets the list */
2079                 strv_free(u->documentation);
2080                 u->documentation = NULL;
2081                 return 0;
2082         }
2083
2084         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
2085                                           rvalue, data, userdata);
2086         if (r < 0)
2087                 return r;
2088
2089         for (a = b = u->documentation; a && *a; a++) {
2090
2091                 if (is_valid_documentation_url(*a))
2092                         *(b++) = *a;
2093                 else {
2094                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2095                                    "Invalid URL, ignoring: %s", *a);
2096                         free(*a);
2097                 }
2098         }
2099         if (b)
2100                 *b = NULL;
2101
2102         return r;
2103 }
2104
2105 #ifdef HAVE_SECCOMP
2106 int config_parse_syscall_filter(
2107                 const char *unit,
2108                 const char *filename,
2109                 unsigned line,
2110                 const char *section,
2111                 unsigned section_line,
2112                 const char *lvalue,
2113                 int ltype,
2114                 const char *rvalue,
2115                 void *data,
2116                 void *userdata) {
2117
2118         static const char default_syscalls[] =
2119                 "execve\0"
2120                 "exit\0"
2121                 "exit_group\0"
2122                 "rt_sigreturn\0"
2123                 "sigreturn\0";
2124
2125         ExecContext *c = data;
2126         Unit *u = userdata;
2127         bool invert = false;
2128         char *w, *state;
2129         size_t l;
2130         int r;
2131
2132         assert(filename);
2133         assert(lvalue);
2134         assert(rvalue);
2135         assert(u);
2136
2137         if (isempty(rvalue)) {
2138                 /* Empty assignment resets the list */
2139                 set_free(c->syscall_filter);
2140                 c->syscall_filter = NULL;
2141                 c->syscall_whitelist = false;
2142                 return 0;
2143         }
2144
2145         if (rvalue[0] == '~') {
2146                 invert = true;
2147                 rvalue++;
2148         }
2149
2150         if (!c->syscall_filter) {
2151                 c->syscall_filter = set_new(trivial_hash_func, trivial_compare_func);
2152                 if (!c->syscall_filter)
2153                         return log_oom();
2154
2155                 if (invert)
2156                         /* Allow everything but the ones listed */
2157                         c->syscall_whitelist = false;
2158                 else {
2159                         const char *i;
2160
2161                         /* Allow nothing but the ones listed */
2162                         c->syscall_whitelist = true;
2163
2164                         /* Accept default syscalls if we are on a whitelist */
2165                         NULSTR_FOREACH(i, default_syscalls)  {
2166                                 int id;
2167
2168                                 id = seccomp_syscall_resolve_name(i);
2169                                 if (id < 0)
2170                                         continue;
2171
2172                                 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2173                                 if (r == -EEXIST)
2174                                         continue;
2175                                 if (r < 0)
2176                                         return log_oom();
2177                         }
2178                 }
2179         }
2180
2181         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2182                 _cleanup_free_ char *t = NULL;
2183                 int id;
2184
2185                 t = strndup(w, l);
2186                 if (!t)
2187                         return log_oom();
2188
2189                 id = seccomp_syscall_resolve_name(t);
2190                 if (id < 0)  {
2191                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call, ignoring: %s", t);
2192                         continue;
2193                 }
2194
2195                 /* If we previously wanted to forbid a syscall and now
2196                  * we want to allow it, then remove it from the list
2197                  */
2198                 if (!invert == c->syscall_whitelist)  {
2199                         r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2200                         if (r == -EEXIST)
2201                                 continue;
2202                         if (r < 0)
2203                                 return log_oom();
2204                 } else
2205                         set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2206         }
2207
2208         /* Turn on NNP, but only if it wasn't configured explicitly
2209          * before, and only if we are in user mode. */
2210         if (!c->no_new_privileges_set && u->manager->running_as == SYSTEMD_USER)
2211                 c->no_new_privileges = true;
2212
2213         return 0;
2214 }
2215
2216 int config_parse_syscall_archs(
2217                 const char *unit,
2218                 const char *filename,
2219                 unsigned line,
2220                 const char *section,
2221                 unsigned section_line,
2222                 const char *lvalue,
2223                 int ltype,
2224                 const char *rvalue,
2225                 void *data,
2226                 void *userdata) {
2227
2228         Set **archs = data;
2229         char *w, *state;
2230         size_t l;
2231         int r;
2232
2233         if (isempty(rvalue)) {
2234                 set_free(*archs);
2235                 *archs = NULL;
2236                 return 0;
2237         }
2238
2239         r = set_ensure_allocated(archs, trivial_hash_func, trivial_compare_func);
2240         if (r < 0)
2241                 return log_oom();
2242
2243         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2244                 _cleanup_free_ char *t = NULL;
2245                 uint32_t a;
2246
2247                 t = strndup(w, l);
2248                 if (!t)
2249                         return log_oom();
2250
2251                 r = seccomp_arch_from_string(t, &a);
2252                 if (r < 0) {
2253                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse system call architecture, ignoring: %s", t);
2254                         continue;
2255                 }
2256
2257                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2258                 if (r == -EEXIST)
2259                         continue;
2260                 if (r < 0)
2261                         return log_oom();
2262         }
2263
2264         return 0;
2265 }
2266
2267 int config_parse_syscall_errno(
2268                 const char *unit,
2269                 const char *filename,
2270                 unsigned line,
2271                 const char *section,
2272                 unsigned section_line,
2273                 const char *lvalue,
2274                 int ltype,
2275                 const char *rvalue,
2276                 void *data,
2277                 void *userdata) {
2278
2279         ExecContext *c = data;
2280         int e;
2281
2282         assert(filename);
2283         assert(lvalue);
2284         assert(rvalue);
2285
2286         if (isempty(rvalue)) {
2287                 /* Empty assignment resets to KILL */
2288                 c->syscall_errno = 0;
2289                 return 0;
2290         }
2291
2292         e = errno_from_name(rvalue);
2293         if (e < 0) {
2294                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse error number, ignoring: %s", rvalue);
2295                 return 0;
2296         }
2297
2298         c->syscall_errno = e;
2299         return 0;
2300 }
2301
2302 int config_parse_address_families(
2303                 const char *unit,
2304                 const char *filename,
2305                 unsigned line,
2306                 const char *section,
2307                 unsigned section_line,
2308                 const char *lvalue,
2309                 int ltype,
2310                 const char *rvalue,
2311                 void *data,
2312                 void *userdata) {
2313
2314         ExecContext *c = data;
2315         Unit *u = userdata;
2316         bool invert = false;
2317         char *w, *state;
2318         size_t l;
2319         int r;
2320
2321         assert(filename);
2322         assert(lvalue);
2323         assert(rvalue);
2324         assert(u);
2325
2326         if (isempty(rvalue)) {
2327                 /* Empty assignment resets the list */
2328                 set_free(c->address_families);
2329                 c->address_families = NULL;
2330                 c->address_families_whitelist = false;
2331                 return 0;
2332         }
2333
2334         if (rvalue[0] == '~') {
2335                 invert = true;
2336                 rvalue++;
2337         }
2338
2339         if (!c->address_families) {
2340                 c->address_families = set_new(trivial_hash_func, trivial_compare_func);
2341                 if (!c->address_families)
2342                         return log_oom();
2343
2344                 c->address_families_whitelist = !invert;
2345         }
2346
2347         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2348                 _cleanup_free_ char *t = NULL;
2349                 int af;
2350
2351                 t = strndup(w, l);
2352                 if (!t)
2353                         return log_oom();
2354
2355                 af = af_from_name(t);
2356                 if (af <= 0)  {
2357                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse address family, ignoring: %s", t);
2358                         continue;
2359                 }
2360
2361                 /* If we previously wanted to forbid an address family and now
2362                  * we want to allow it, then remove it from the list
2363                  */
2364                 if (!invert == c->address_families_whitelist)  {
2365                         r = set_put(c->address_families, INT_TO_PTR(af));
2366                         if (r == -EEXIST)
2367                                 continue;
2368                         if (r < 0)
2369                                 return log_oom();
2370                 } else
2371                         set_remove(c->address_families, INT_TO_PTR(af));
2372         }
2373
2374         return 0;
2375 }
2376 #endif
2377
2378 int config_parse_unit_slice(
2379                 const char *unit,
2380                 const char *filename,
2381                 unsigned line,
2382                 const char *section,
2383                 unsigned section_line,
2384                 const char *lvalue,
2385                 int ltype,
2386                 const char *rvalue,
2387                 void *data,
2388                 void *userdata) {
2389
2390         _cleanup_free_ char *k = NULL;
2391         Unit *u = userdata, *slice;
2392         int r;
2393
2394         assert(filename);
2395         assert(lvalue);
2396         assert(rvalue);
2397         assert(u);
2398
2399         r = unit_name_printf(u, rvalue, &k);
2400         if (r < 0)
2401                 log_syntax(unit, LOG_ERR, filename, line, -r,
2402                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2403         if (!k) {
2404                 k = strdup(rvalue);
2405                 if (!k)
2406                         return log_oom();
2407         }
2408
2409         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2410         if (r < 0) {
2411                 log_syntax(unit, LOG_ERR, filename, line, -r,
2412                            "Failed to load slice unit %s. Ignoring.", k);
2413                 return 0;
2414         }
2415
2416         if (slice->type != UNIT_SLICE) {
2417                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2418                            "Slice unit %s is not a slice. Ignoring.", k);
2419                 return 0;
2420         }
2421
2422         unit_ref_set(&u->slice, slice);
2423         return 0;
2424 }
2425
2426 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2427
2428 int config_parse_cpu_shares(
2429                 const char *unit,
2430                 const char *filename,
2431                 unsigned line,
2432                 const char *section,
2433                 unsigned section_line,
2434                 const char *lvalue,
2435                 int ltype,
2436                 const char *rvalue,
2437                 void *data,
2438                 void *userdata) {
2439
2440         CGroupContext *c = data;
2441         unsigned long lu;
2442         int r;
2443
2444         assert(filename);
2445         assert(lvalue);
2446         assert(rvalue);
2447
2448         if (isempty(rvalue)) {
2449                 c->cpu_shares = 1024;
2450                 return 0;
2451         }
2452
2453         r = safe_atolu(rvalue, &lu);
2454         if (r < 0 || lu <= 0) {
2455                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2456                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2457                 return 0;
2458         }
2459
2460         c->cpu_shares = lu;
2461         return 0;
2462 }
2463
2464 int config_parse_memory_limit(
2465                 const char *unit,
2466                 const char *filename,
2467                 unsigned line,
2468                 const char *section,
2469                 unsigned section_line,
2470                 const char *lvalue,
2471                 int ltype,
2472                 const char *rvalue,
2473                 void *data,
2474                 void *userdata) {
2475
2476         CGroupContext *c = data;
2477         off_t bytes;
2478         int r;
2479
2480         if (isempty(rvalue)) {
2481                 c->memory_limit = (uint64_t) -1;
2482                 return 0;
2483         }
2484
2485         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2486
2487         r = parse_size(rvalue, 1024, &bytes);
2488         if (r < 0) {
2489                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Memory limit '%s' invalid. Ignoring.", rvalue);
2490                 return 0;
2491         }
2492
2493         c->memory_limit = (uint64_t) bytes;
2494         return 0;
2495 }
2496
2497 int config_parse_device_allow(
2498                 const char *unit,
2499                 const char *filename,
2500                 unsigned line,
2501                 const char *section,
2502                 unsigned section_line,
2503                 const char *lvalue,
2504                 int ltype,
2505                 const char *rvalue,
2506                 void *data,
2507                 void *userdata) {
2508
2509         _cleanup_free_ char *path = NULL;
2510         CGroupContext *c = data;
2511         CGroupDeviceAllow *a;
2512         const char *m;
2513         size_t n;
2514
2515         if (isempty(rvalue)) {
2516                 while (c->device_allow)
2517                         cgroup_context_free_device_allow(c, c->device_allow);
2518
2519                 return 0;
2520         }
2521
2522         n = strcspn(rvalue, WHITESPACE);
2523         path = strndup(rvalue, n);
2524         if (!path)
2525                 return log_oom();
2526
2527         if (!startswith(path, "/dev/") &&
2528             !startswith(path, "block-") &&
2529             !startswith(path, "char-")) {
2530                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device node path '%s'. Ignoring.", path);
2531                 return 0;
2532         }
2533
2534         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2535         if (isempty(m))
2536                 m = "rwm";
2537
2538         if (!in_charset(m, "rwm")) {
2539                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Invalid device rights '%s'. Ignoring.", m);
2540                 return 0;
2541         }
2542
2543         a = new0(CGroupDeviceAllow, 1);
2544         if (!a)
2545                 return log_oom();
2546
2547         a->path = path;
2548         path = NULL;
2549         a->r = !!strchr(m, 'r');
2550         a->w = !!strchr(m, 'w');
2551         a->m = !!strchr(m, 'm');
2552
2553         LIST_PREPEND(device_allow, c->device_allow, a);
2554         return 0;
2555 }
2556
2557 int config_parse_blockio_weight(
2558                 const char *unit,
2559                 const char *filename,
2560                 unsigned line,
2561                 const char *section,
2562                 unsigned section_line,
2563                 const char *lvalue,
2564                 int ltype,
2565                 const char *rvalue,
2566                 void *data,
2567                 void *userdata) {
2568
2569         CGroupContext *c = data;
2570         unsigned long lu;
2571         int r;
2572
2573         assert(filename);
2574         assert(lvalue);
2575         assert(rvalue);
2576
2577         if (isempty(rvalue)) {
2578                 c->blockio_weight = 1000;
2579                 return 0;
2580         }
2581
2582         r = safe_atolu(rvalue, &lu);
2583         if (r < 0 || lu < 10 || lu > 1000) {
2584                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2585                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2586                 return 0;
2587         }
2588
2589         c->blockio_weight = lu;
2590
2591         return 0;
2592 }
2593
2594 int config_parse_blockio_device_weight(
2595                 const char *unit,
2596                 const char *filename,
2597                 unsigned line,
2598                 const char *section,
2599                 unsigned section_line,
2600                 const char *lvalue,
2601                 int ltype,
2602                 const char *rvalue,
2603                 void *data,
2604                 void *userdata) {
2605
2606         _cleanup_free_ char *path = NULL;
2607         CGroupBlockIODeviceWeight *w;
2608         CGroupContext *c = data;
2609         unsigned long lu;
2610         const char *weight;
2611         size_t n;
2612         int r;
2613
2614         assert(filename);
2615         assert(lvalue);
2616         assert(rvalue);
2617
2618         if (isempty(rvalue)) {
2619                 while (c->blockio_device_weights)
2620                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2621
2622                 return 0;
2623         }
2624
2625         n = strcspn(rvalue, WHITESPACE);
2626         weight = rvalue + n;
2627         if (!*weight) {
2628                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2629                            "Expected block device and device weight. Ignoring.");
2630                 return 0;
2631         }
2632
2633         path = strndup(rvalue, n);
2634         if (!path)
2635                 return log_oom();
2636
2637         if (!path_startswith(path, "/dev")) {
2638                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2639                            "Invalid device node path '%s'. Ignoring.", path);
2640                 return 0;
2641         }
2642
2643         weight += strspn(weight, WHITESPACE);
2644         r = safe_atolu(weight, &lu);
2645         if (r < 0 || lu < 10 || lu > 1000) {
2646                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2647                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2648                 return 0;
2649         }
2650
2651
2652         w = new0(CGroupBlockIODeviceWeight, 1);
2653         if (!w)
2654                 return log_oom();
2655
2656         w->path = path;
2657         path = NULL;
2658
2659         w->weight = lu;
2660
2661         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2662         return 0;
2663 }
2664
2665 int config_parse_blockio_bandwidth(
2666                 const char *unit,
2667                 const char *filename,
2668                 unsigned line,
2669                 const char *section,
2670                 unsigned section_line,
2671                 const char *lvalue,
2672                 int ltype,
2673                 const char *rvalue,
2674                 void *data,
2675                 void *userdata) {
2676
2677         _cleanup_free_ char *path = NULL;
2678         CGroupBlockIODeviceBandwidth *b;
2679         CGroupContext *c = data;
2680         const char *bandwidth;
2681         off_t bytes;
2682         bool read;
2683         size_t n;
2684         int r;
2685
2686         assert(filename);
2687         assert(lvalue);
2688         assert(rvalue);
2689
2690         read = streq("BlockIOReadBandwidth", lvalue);
2691
2692         if (isempty(rvalue)) {
2693                 CGroupBlockIODeviceBandwidth *next;
2694
2695                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2696                         if (b->read == read)
2697                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2698
2699                 return 0;
2700         }
2701
2702         n = strcspn(rvalue, WHITESPACE);
2703         bandwidth = rvalue + n;
2704         bandwidth += strspn(bandwidth, WHITESPACE);
2705
2706         if (!*bandwidth) {
2707                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2708                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2709                 return 0;
2710         }
2711
2712         path = strndup(rvalue, n);
2713         if (!path)
2714                 return log_oom();
2715
2716         if (!path_startswith(path, "/dev")) {
2717                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2718                            "Invalid device node path '%s'. Ignoring.", path);
2719                 return 0;
2720         }
2721
2722         r = parse_size(bandwidth, 1000, &bytes);
2723         if (r < 0 || bytes <= 0) {
2724                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2725                 return 0;
2726         }
2727
2728         b = new0(CGroupBlockIODeviceBandwidth, 1);
2729         if (!b)
2730                 return log_oom();
2731
2732         b->path = path;
2733         path = NULL;
2734         b->bandwidth = (uint64_t) bytes;
2735         b->read = read;
2736
2737         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
2738
2739         return 0;
2740 }
2741
2742 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
2743
2744 int config_parse_job_mode_isolate(
2745                 const char *unit,
2746                 const char *filename,
2747                 unsigned line,
2748                 const char *section,
2749                 unsigned section_line,
2750                 const char *lvalue,
2751                 int ltype,
2752                 const char *rvalue,
2753                 void *data,
2754                 void *userdata) {
2755
2756         JobMode *m = data;
2757         int r;
2758
2759         assert(filename);
2760         assert(lvalue);
2761         assert(rvalue);
2762
2763         r = parse_boolean(rvalue);
2764         if (r < 0) {
2765                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Failed to parse boolean, ignoring: %s", rvalue);
2766                 return 0;
2767         }
2768
2769         *m = r ? JOB_ISOLATE : JOB_REPLACE;
2770         return 0;
2771 }
2772
2773 int config_parse_personality(
2774                 const char *unit,
2775                 const char *filename,
2776                 unsigned line,
2777                 const char *section,
2778                 unsigned section_line,
2779                 const char *lvalue,
2780                 int ltype,
2781                 const char *rvalue,
2782                 void *data,
2783                 void *userdata) {
2784
2785         unsigned long *personality = data, p;
2786
2787         assert(filename);
2788         assert(lvalue);
2789         assert(rvalue);
2790         assert(personality);
2791
2792         p = personality_from_string(rvalue);
2793         if (p == 0xffffffffUL) {
2794                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2795                            "Failed to parse personality, ignoring: %s", rvalue);
2796                 return 0;
2797         }
2798
2799         *personality = p;
2800         return 0;
2801 }
2802
2803 int config_parse_runtime_directory(
2804                 const char *unit,
2805                 const char *filename,
2806                 unsigned line,
2807                 const char *section,
2808                 unsigned section_line,
2809                 const char *lvalue,
2810                 int ltype,
2811                 const char *rvalue,
2812                 void *data,
2813                 void *userdata) {
2814
2815         char***rt = data, *w, *state;
2816         size_t l;
2817         int r;
2818
2819         assert(filename);
2820         assert(lvalue);
2821         assert(rvalue);
2822         assert(data);
2823
2824         if (isempty(rvalue)) {
2825                 /* Empty assignment resets the list */
2826                 strv_free(*rt);
2827                 *rt = NULL;
2828                 return 0;
2829         }
2830
2831         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2832                 _cleanup_free_ char *n;
2833
2834                 n = strndup(w, l);
2835                 if (!n)
2836                         return log_oom();
2837
2838                 if (!filename_is_safe(n)) {
2839                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Runtime directory is not valid, ignoring assignment: %s", rvalue);
2840                         continue;
2841                 }
2842
2843                 r = strv_push(rt, n);
2844                 if (r < 0)
2845                         return log_oom();
2846
2847                 n = NULL;
2848         }
2849
2850         return 0;
2851 }
2852
2853 int config_parse_set_status(
2854                 const char *unit,
2855                 const char *filename,
2856                 unsigned line,
2857                 const char *section,
2858                 unsigned section_line,
2859                 const char *lvalue,
2860                 int ltype,
2861                 const char *rvalue,
2862                 void *data,
2863                 void *userdata) {
2864
2865         char *w;
2866         size_t l;
2867         char *state;
2868         int r;
2869         ExitStatusSet *status_set = data;
2870
2871         assert(filename);
2872         assert(lvalue);
2873         assert(rvalue);
2874         assert(data);
2875
2876         if (isempty(rvalue)) {
2877                 /* Empty assignment resets the list */
2878
2879                 set_free(status_set->signal);
2880                 set_free(status_set->code);
2881
2882                 status_set->signal = status_set->code = NULL;
2883                 return 0;
2884         }
2885
2886         FOREACH_WORD(w, l, rvalue, state) {
2887                 _cleanup_free_ char *temp;
2888                 int val;
2889
2890                 temp = strndup(w, l);
2891                 if (!temp)
2892                         return log_oom();
2893
2894                 r = safe_atoi(temp, &val);
2895                 if (r < 0) {
2896                         val = signal_from_string_try_harder(temp);
2897
2898                         if (val > 0) {
2899                                 r = set_ensure_allocated(&status_set->signal, trivial_hash_func, trivial_compare_func);
2900                                 if (r < 0)
2901                                         return log_oom();
2902
2903                                 r = set_put(status_set->signal, INT_TO_PTR(val));
2904                                 if (r < 0) {
2905                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2906                                         return r;
2907                                 }
2908                         } else {
2909                                 log_syntax(unit, LOG_ERR, filename, line, -val, "Failed to parse value, ignoring: %s", w);
2910                                 return 0;
2911                         }
2912                 } else {
2913                         if (val < 0 || val > 255)
2914                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE, "Value %d is outside range 0-255, ignoring", val);
2915                         else {
2916                                 r = set_ensure_allocated(&status_set->code, trivial_hash_func, trivial_compare_func);
2917                                 if (r < 0)
2918                                         return log_oom();
2919
2920                                 r = set_put(status_set->code, INT_TO_PTR(val));
2921                                 if (r < 0) {
2922                                         log_syntax(unit, LOG_ERR, filename, line, -r, "Unable to store: %s", w);
2923                                         return r;
2924                                 }
2925                         }
2926                 }
2927         }
2928
2929         return 0;
2930 }
2931
2932 int config_parse_namespace_path_strv(
2933                 const char *unit,
2934                 const char *filename,
2935                 unsigned line,
2936                 const char *section,
2937                 unsigned section_line,
2938                 const char *lvalue,
2939                 int ltype,
2940                 const char *rvalue,
2941                 void *data,
2942                 void *userdata) {
2943
2944         char*** sv = data, *w, *state;
2945         size_t l;
2946         int r;
2947
2948         assert(filename);
2949         assert(lvalue);
2950         assert(rvalue);
2951         assert(data);
2952
2953         if (isempty(rvalue)) {
2954                 /* Empty assignment resets the list */
2955                 strv_free(*sv);
2956                 *sv = NULL;
2957                 return 0;
2958         }
2959
2960         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
2961                 _cleanup_free_ char *n;
2962                 int offset;
2963
2964                 n = strndup(w, l);
2965                 if (!n)
2966                         return log_oom();
2967
2968                 if (!utf8_is_valid(n)) {
2969                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2970                         continue;
2971                 }
2972
2973                 offset = n[0] == '-';
2974                 if (!path_is_absolute(n + offset)) {
2975                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Not an absolute path, ignoring: %s", rvalue);
2976                         continue;
2977                 }
2978
2979                 path_kill_slashes(n);
2980
2981                 r = strv_push(sv, n);
2982                 if (r < 0)
2983                         return log_oom();
2984
2985                 n = NULL;
2986         }
2987
2988         return 0;
2989 }
2990
2991 int config_parse_no_new_priviliges(
2992                 const char* unit,
2993                 const char *filename,
2994                 unsigned line,
2995                 const char *section,
2996                 unsigned section_line,
2997                 const char *lvalue,
2998                 int ltype,
2999                 const char *rvalue,
3000                 void *data,
3001                 void *userdata) {
3002
3003         ExecContext *c = data;
3004         int k;
3005
3006         assert(filename);
3007         assert(lvalue);
3008         assert(rvalue);
3009         assert(data);
3010
3011         k = parse_boolean(rvalue);
3012         if (k < 0) {
3013                 log_syntax(unit, LOG_ERR, filename, line, -k, "Failed to parse boolean value, ignoring: %s", rvalue);
3014                 return 0;
3015         }
3016
3017         c->no_new_privileges = !!k;
3018         c->no_new_privileges_set = true;
3019
3020         return 0;
3021 }
3022
3023 #define FOLLOW_MAX 8
3024
3025 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
3026         unsigned c = 0;
3027         int fd, r;
3028         FILE *f;
3029         char *id = NULL;
3030
3031         assert(filename);
3032         assert(*filename);
3033         assert(_f);
3034         assert(names);
3035
3036         /* This will update the filename pointer if the loaded file is
3037          * reached by a symlink. The old string will be freed. */
3038
3039         for (;;) {
3040                 char *target, *name;
3041
3042                 if (c++ >= FOLLOW_MAX)
3043                         return -ELOOP;
3044
3045                 path_kill_slashes(*filename);
3046
3047                 /* Add the file name we are currently looking at to
3048                  * the names of this unit, but only if it is a valid
3049                  * unit name. */
3050                 name = basename(*filename);
3051
3052                 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
3053
3054                         id = set_get(names, name);
3055                         if (!id) {
3056                                 id = strdup(name);
3057                                 if (!id)
3058                                         return -ENOMEM;
3059
3060                                 r = set_consume(names, id);
3061                                 if (r < 0)
3062                                         return r;
3063                         }
3064                 }
3065
3066                 /* Try to open the file name, but don't if its a symlink */
3067                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
3068                 if (fd >= 0)
3069                         break;
3070
3071                 if (errno != ELOOP)
3072                         return -errno;
3073
3074                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
3075                 r = readlink_and_make_absolute(*filename, &target);
3076                 if (r < 0)
3077                         return r;
3078
3079                 free(*filename);
3080                 *filename = target;
3081         }
3082
3083         f = fdopen(fd, "re");
3084         if (!f) {
3085                 r = -errno;
3086                 safe_close(fd);
3087                 return r;
3088         }
3089
3090         *_f = f;
3091         *_final = id;
3092         return 0;
3093 }
3094
3095 static int merge_by_names(Unit **u, Set *names, const char *id) {
3096         char *k;
3097         int r;
3098
3099         assert(u);
3100         assert(*u);
3101         assert(names);
3102
3103         /* Let's try to add in all symlink names we found */
3104         while ((k = set_steal_first(names))) {
3105
3106                 /* First try to merge in the other name into our
3107                  * unit */
3108                 r = unit_merge_by_name(*u, k);
3109                 if (r < 0) {
3110                         Unit *other;
3111
3112                         /* Hmm, we couldn't merge the other unit into
3113                          * ours? Then let's try it the other way
3114                          * round */
3115
3116                         other = manager_get_unit((*u)->manager, k);
3117                         free(k);
3118
3119                         if (other) {
3120                                 r = unit_merge(other, *u);
3121                                 if (r >= 0) {
3122                                         *u = other;
3123                                         return merge_by_names(u, names, NULL);
3124                                 }
3125                         }
3126
3127                         return r;
3128                 }
3129
3130                 if (id == k)
3131                         unit_choose_id(*u, id);
3132
3133                 free(k);
3134         }
3135
3136         return 0;
3137 }
3138
3139 static int load_from_path(Unit *u, const char *path) {
3140         int r;
3141         _cleanup_set_free_free_ Set *symlink_names = NULL;
3142         _cleanup_fclose_ FILE *f = NULL;
3143         _cleanup_free_ char *filename = NULL;
3144         char *id = NULL;
3145         Unit *merged;
3146         struct stat st;
3147
3148         assert(u);
3149         assert(path);
3150
3151         symlink_names = set_new(string_hash_func, string_compare_func);
3152         if (!symlink_names)
3153                 return -ENOMEM;
3154
3155         if (path_is_absolute(path)) {
3156
3157                 filename = strdup(path);
3158                 if (!filename)
3159                         return -ENOMEM;
3160
3161                 r = open_follow(&filename, &f, symlink_names, &id);
3162                 if (r < 0) {
3163                         free(filename);
3164                         filename = NULL;
3165
3166                         if (r != -ENOENT)
3167                                 return r;
3168                 }
3169
3170         } else  {
3171                 char **p;
3172
3173                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
3174
3175                         /* Instead of opening the path right away, we manually
3176                          * follow all symlinks and add their name to our unit
3177                          * name set while doing so */
3178                         filename = path_make_absolute(path, *p);
3179                         if (!filename)
3180                                 return -ENOMEM;
3181
3182                         if (u->manager->unit_path_cache &&
3183                             !set_get(u->manager->unit_path_cache, filename))
3184                                 r = -ENOENT;
3185                         else
3186                                 r = open_follow(&filename, &f, symlink_names, &id);
3187
3188                         if (r < 0) {
3189                                 free(filename);
3190                                 filename = NULL;
3191
3192                                 if (r != -ENOENT)
3193                                         return r;
3194
3195                                 /* Empty the symlink names for the next run */
3196                                 set_clear_free(symlink_names);
3197                                 continue;
3198                         }
3199
3200                         break;
3201                 }
3202         }
3203
3204         if (!filename)
3205                 /* Hmm, no suitable file found? */
3206                 return 0;
3207
3208         merged = u;
3209         r = merge_by_names(&merged, symlink_names, id);
3210         if (r < 0)
3211                 return r;
3212
3213         if (merged != u) {
3214                 u->load_state = UNIT_MERGED;
3215                 return 0;
3216         }
3217
3218         if (fstat(fileno(f), &st) < 0)
3219                 return -errno;
3220
3221         if (null_or_empty(&st))
3222                 u->load_state = UNIT_MASKED;
3223         else {
3224                 u->load_state = UNIT_LOADED;
3225
3226                 /* Now, parse the file contents */
3227                 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
3228                                  config_item_perf_lookup,
3229                                  (void*) load_fragment_gperf_lookup, false, true, u);
3230                 if (r < 0)
3231                         return r;
3232         }
3233
3234         free(u->fragment_path);
3235         u->fragment_path = filename;
3236         filename = NULL;
3237
3238         u->fragment_mtime = timespec_load(&st.st_mtim);
3239
3240         if (u->source_path) {
3241                 if (stat(u->source_path, &st) >= 0)
3242                         u->source_mtime = timespec_load(&st.st_mtim);
3243                 else
3244                         u->source_mtime = 0;
3245         }
3246
3247         return 0;
3248 }
3249
3250 int unit_load_fragment(Unit *u) {
3251         int r;
3252         Iterator i;
3253         const char *t;
3254
3255         assert(u);
3256         assert(u->load_state == UNIT_STUB);
3257         assert(u->id);
3258
3259         /* First, try to find the unit under its id. We always look
3260          * for unit files in the default directories, to make it easy
3261          * to override things by placing things in /etc/systemd/system */
3262         r = load_from_path(u, u->id);
3263         if (r < 0)
3264                 return r;
3265
3266         /* Try to find an alias we can load this with */
3267         if (u->load_state == UNIT_STUB)
3268                 SET_FOREACH(t, u->names, i) {
3269
3270                         if (t == u->id)
3271                                 continue;
3272
3273                         r = load_from_path(u, t);
3274                         if (r < 0)
3275                                 return r;
3276
3277                         if (u->load_state != UNIT_STUB)
3278                                 break;
3279                 }
3280
3281         /* And now, try looking for it under the suggested (originally linked) path */
3282         if (u->load_state == UNIT_STUB && u->fragment_path) {
3283
3284                 r = load_from_path(u, u->fragment_path);
3285                 if (r < 0)
3286                         return r;
3287
3288                 if (u->load_state == UNIT_STUB) {
3289                         /* Hmm, this didn't work? Then let's get rid
3290                          * of the fragment path stored for us, so that
3291                          * we don't point to an invalid location. */
3292                         free(u->fragment_path);
3293                         u->fragment_path = NULL;
3294                 }
3295         }
3296
3297         /* Look for a template */
3298         if (u->load_state == UNIT_STUB && u->instance) {
3299                 _cleanup_free_ char *k;
3300
3301                 k = unit_name_template(u->id);
3302                 if (!k)
3303                         return -ENOMEM;
3304
3305                 r = load_from_path(u, k);
3306                 if (r < 0)
3307                         return r;
3308
3309                 if (u->load_state == UNIT_STUB)
3310                         SET_FOREACH(t, u->names, i) {
3311                                 _cleanup_free_ char *z = NULL;
3312
3313                                 if (t == u->id)
3314                                         continue;
3315
3316                                 z = unit_name_template(t);
3317                                 if (!z)
3318                                         return -ENOMEM;
3319
3320                                 r = load_from_path(u, z);
3321                                 if (r < 0)
3322                                         return r;
3323
3324                                 if (u->load_state != UNIT_STUB)
3325                                         break;
3326                         }
3327         }
3328
3329         return 0;
3330 }
3331
3332 void unit_dump_config_items(FILE *f) {
3333         static const struct {
3334                 const ConfigParserCallback callback;
3335                 const char *rvalue;
3336         } table[] = {
3337 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_LIBWRAP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
3338                 { config_parse_warn_compat,           "NOTSUPPORTED" },
3339 #endif
3340                 { config_parse_int,                   "INTEGER" },
3341                 { config_parse_unsigned,              "UNSIGNED" },
3342                 { config_parse_iec_size,              "SIZE" },
3343                 { config_parse_iec_off,               "SIZE" },
3344                 { config_parse_si_size,               "SIZE" },
3345                 { config_parse_bool,                  "BOOLEAN" },
3346                 { config_parse_string,                "STRING" },
3347                 { config_parse_path,                  "PATH" },
3348                 { config_parse_unit_path_printf,      "PATH" },
3349                 { config_parse_strv,                  "STRING [...]" },
3350                 { config_parse_exec_nice,             "NICE" },
3351                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
3352                 { config_parse_exec_io_class,         "IOCLASS" },
3353                 { config_parse_exec_io_priority,      "IOPRIORITY" },
3354                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
3355                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
3356                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
3357                 { config_parse_mode,                  "MODE" },
3358                 { config_parse_unit_env_file,         "FILE" },
3359                 { config_parse_output,                "OUTPUT" },
3360                 { config_parse_input,                 "INPUT" },
3361                 { config_parse_log_facility,          "FACILITY" },
3362                 { config_parse_log_level,             "LEVEL" },
3363                 { config_parse_exec_capabilities,     "CAPABILITIES" },
3364                 { config_parse_exec_secure_bits,      "SECUREBITS" },
3365                 { config_parse_bounding_set,          "BOUNDINGSET" },
3366                 { config_parse_limit,                 "LIMIT" },
3367                 { config_parse_unit_deps,             "UNIT [...]" },
3368                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
3369                 { config_parse_service_type,          "SERVICETYPE" },
3370                 { config_parse_service_restart,       "SERVICERESTART" },
3371 #ifdef HAVE_SYSV_COMPAT
3372                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
3373 #endif
3374                 { config_parse_kill_mode,             "KILLMODE" },
3375                 { config_parse_kill_signal,           "SIGNAL" },
3376                 { config_parse_socket_listen,         "SOCKET [...]" },
3377                 { config_parse_socket_bind,           "SOCKETBIND" },
3378                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
3379                 { config_parse_sec,                   "SECONDS" },
3380                 { config_parse_nsec,                  "NANOSECONDS" },
3381                 { config_parse_namespace_path_strv,   "PATH [...]" },
3382                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
3383                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
3384                 { config_parse_unit_string_printf,    "STRING" },
3385                 { config_parse_trigger_unit,          "UNIT" },
3386                 { config_parse_timer,                 "TIMER" },
3387                 { config_parse_path_spec,             "PATH" },
3388                 { config_parse_notify_access,         "ACCESS" },
3389                 { config_parse_ip_tos,                "TOS" },
3390                 { config_parse_unit_condition_path,   "CONDITION" },
3391                 { config_parse_unit_condition_string, "CONDITION" },
3392                 { config_parse_unit_condition_null,   "CONDITION" },
3393                 { config_parse_unit_slice,            "SLICE" },
3394                 { config_parse_documentation,         "URL" },
3395                 { config_parse_service_timeout,       "SECONDS" },
3396                 { config_parse_start_limit_action,    "ACTION" },
3397                 { config_parse_set_status,            "STATUS" },
3398                 { config_parse_service_sockets,       "SOCKETS" },
3399                 { config_parse_environ,               "ENVIRON" },
3400 #ifdef HAVE_SECCOMP
3401                 { config_parse_syscall_filter,        "SYSCALLS" },
3402                 { config_parse_syscall_archs,         "ARCHS" },
3403                 { config_parse_syscall_errno,         "ERRNO" },
3404                 { config_parse_address_families,      "FAMILIES" },
3405 #endif
3406                 { config_parse_cpu_shares,            "SHARES" },
3407                 { config_parse_memory_limit,          "LIMIT" },
3408                 { config_parse_device_allow,          "DEVICE" },
3409                 { config_parse_device_policy,         "POLICY" },
3410                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
3411                 { config_parse_blockio_weight,        "WEIGHT" },
3412                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
3413                 { config_parse_long,                  "LONG" },
3414                 { config_parse_socket_service,        "SERVICE" },
3415 #ifdef HAVE_SELINUX
3416                 { config_parse_exec_selinux_context,  "LABEL" },
3417 #endif
3418                 { config_parse_job_mode,              "MODE" },
3419                 { config_parse_job_mode_isolate,      "BOOLEAN" },
3420                 { config_parse_personality,           "PERSONALITY" },
3421         };
3422
3423         const char *prev = NULL;
3424         const char *i;
3425
3426         assert(f);
3427
3428         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
3429                 const char *rvalue = "OTHER", *lvalue;
3430                 unsigned j;
3431                 size_t prefix_len;
3432                 const char *dot;
3433                 const ConfigPerfItem *p;
3434
3435                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
3436
3437                 dot = strchr(i, '.');
3438                 lvalue = dot ? dot + 1 : i;
3439                 prefix_len = dot-i;
3440
3441                 if (dot)
3442                         if (!prev || !strneq(prev, i, prefix_len+1)) {
3443                                 if (prev)
3444                                         fputc('\n', f);
3445
3446                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
3447                         }
3448
3449                 for (j = 0; j < ELEMENTSOF(table); j++)
3450                         if (p->parse == table[j].callback) {
3451                                 rvalue = table[j].rvalue;
3452                                 break;
3453                         }
3454
3455                 fprintf(f, "%s=%s\n", lvalue, rvalue);
3456                 prev = i;
3457         }
3458 }