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