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