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