chiark / gitweb /
util: make http url validity checks more generic, and move them to util.c
[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                 /* If seperate_argv0, we'll move first element to path variable */
593                 n = new(char*, MAX(k + !separate_argv0, 1u));
594                 if (!n)
595                         return log_oom();
596
597                 k = 0;
598                 FOREACH_WORD_QUOTED(word, l, rvalue, state) {
599                         char *c;
600                         unsigned skip;
601
602                         if (separate_argv0 ? path == NULL : k == 0) {
603                                 /* first word, very special */
604                                 skip = separate_argv0 + ignore;
605
606                                 /* skip special chars in the beginning */
607                                 assert(skip < l);
608
609                         } else if (strneq(word, ";", MAX(l, 1U)))
610                                 /* new commandline */
611                                 break;
612
613                         else
614                                 skip = strneq(word, "\\;", MAX(l, 1U));
615
616                         c = cunescape_length(word + skip, l - skip);
617                         if (!c) {
618                                 r = log_oom();
619                                 goto fail;
620                         }
621
622                         if (!utf8_is_valid(c)) {
623                                 log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
624                                 r = 0;
625                                 goto fail;
626                         }
627
628                         /* where to stuff this? */
629                         if (separate_argv0 && path == NULL)
630                                 path = c;
631                         else
632                                 n[k++] = c;
633                 }
634
635                 n[k] = NULL;
636
637                 log_debug("path: %s", path ?: n[0]);
638
639                 if (!n[0])
640                         reason = "Empty executable name or zeroeth argument";
641                 else if (!string_is_safe(path ?: n[0]))
642                         reason = "Executable path contains special characters";
643                 else if (!path_is_absolute(path ?: n[0]))
644                         reason = "Executable path is not absolute";
645                 else if (endswith(path ?: n[0], "/"))
646                         reason = "Executable path specifies a directory";
647                 else
648                         goto ok;
649
650                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
651                            "%s, ignoring: %s", reason, rvalue);
652                 r = 0;
653                 goto fail;
654
655 ok:
656                 if (!path) {
657                         path = strdup(n[0]);
658                         if (!path) {
659                                 r = log_oom();
660                                 goto fail;
661                         }
662                 }
663
664                 nce = new0(ExecCommand, 1);
665                 if (!nce) {
666                         r = log_oom();
667                         goto fail;
668                 }
669
670                 nce->argv = n;
671                 nce->path = path;
672                 nce->ignore = ignore;
673
674                 path_kill_slashes(nce->path);
675
676                 exec_command_append_list(e, nce);
677
678                 rvalue = state;
679         }
680
681         return 0;
682
683 fail:
684         n[k] = NULL;
685         strv_free(n);
686         free(path);
687         free(nce);
688
689         return r;
690 }
691
692 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
693 DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
694
695 int config_parse_socket_bindtodevice(const char* unit,
696                                      const char *filename,
697                                      unsigned line,
698                                      const char *section,
699                                      unsigned section_line,
700                                      const char *lvalue,
701                                      int ltype,
702                                      const char *rvalue,
703                                      void *data,
704                                      void *userdata) {
705
706         Socket *s = data;
707         char *n;
708
709         assert(filename);
710         assert(lvalue);
711         assert(rvalue);
712         assert(data);
713
714         if (rvalue[0] && !streq(rvalue, "*")) {
715                 n = strdup(rvalue);
716                 if (!n)
717                         return log_oom();
718         } else
719                 n = NULL;
720
721         free(s->bind_to_device);
722         s->bind_to_device = n;
723
724         return 0;
725 }
726
727 DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
728 DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
729
730 int config_parse_exec_io_class(const char *unit,
731                                const char *filename,
732                                unsigned line,
733                                const char *section,
734                                unsigned section_line,
735                                const char *lvalue,
736                                int ltype,
737                                const char *rvalue,
738                                void *data,
739                                void *userdata) {
740
741         ExecContext *c = data;
742         int x;
743
744         assert(filename);
745         assert(lvalue);
746         assert(rvalue);
747         assert(data);
748
749         x = ioprio_class_from_string(rvalue);
750         if (x < 0) {
751                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
752                            "Failed to parse IO scheduling class, ignoring: %s", rvalue);
753                 return 0;
754         }
755
756         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
757         c->ioprio_set = true;
758
759         return 0;
760 }
761
762 int config_parse_exec_io_priority(const char *unit,
763                                   const char *filename,
764                                   unsigned line,
765                                   const char *section,
766                                   unsigned section_line,
767                                   const char *lvalue,
768                                   int ltype,
769                                   const char *rvalue,
770                                   void *data,
771                                   void *userdata) {
772
773         ExecContext *c = data;
774         int i, r;
775
776         assert(filename);
777         assert(lvalue);
778         assert(rvalue);
779         assert(data);
780
781         r = safe_atoi(rvalue, &i);
782         if (r < 0 || i < 0 || i >= IOPRIO_BE_NR) {
783                 log_syntax(unit, LOG_ERR, filename, line, -r,
784                            "Failed to parse IO priority, ignoring: %s", rvalue);
785                 return 0;
786         }
787
788         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
789         c->ioprio_set = true;
790
791         return 0;
792 }
793
794 int config_parse_exec_cpu_sched_policy(const char *unit,
795                                        const char *filename,
796                                        unsigned line,
797                                        const char *section,
798                                        unsigned section_line,
799                                        const char *lvalue,
800                                        int ltype,
801                                        const char *rvalue,
802                                        void *data,
803                                        void *userdata) {
804
805
806         ExecContext *c = data;
807         int x;
808
809         assert(filename);
810         assert(lvalue);
811         assert(rvalue);
812         assert(data);
813
814         x = sched_policy_from_string(rvalue);
815         if (x < 0) {
816                 log_syntax(unit, LOG_ERR, filename, line, -x,
817                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
818                 return 0;
819         }
820
821         c->cpu_sched_policy = x;
822         /* Moving to or from real-time policy? We need to adjust the priority */
823         c->cpu_sched_priority = CLAMP(c->cpu_sched_priority, sched_get_priority_min(x), sched_get_priority_max(x));
824         c->cpu_sched_set = true;
825
826         return 0;
827 }
828
829 int config_parse_exec_cpu_sched_prio(const char *unit,
830                                      const char *filename,
831                                      unsigned line,
832                                      const char *section,
833                                      unsigned section_line,
834                                      const char *lvalue,
835                                      int ltype,
836                                      const char *rvalue,
837                                      void *data,
838                                      void *userdata) {
839
840         ExecContext *c = data;
841         int i, min, max, r;
842
843         assert(filename);
844         assert(lvalue);
845         assert(rvalue);
846         assert(data);
847
848         r = safe_atoi(rvalue, &i);
849         if (r < 0) {
850                 log_syntax(unit, LOG_ERR, filename, line, -r,
851                            "Failed to parse CPU scheduling policy, ignoring: %s", rvalue);
852                 return 0;
853         }
854
855         /* On Linux RR/FIFO range from 1 to 99 and OTHER/BATCH may only be 0 */
856         min = sched_get_priority_min(c->cpu_sched_policy);
857         max = sched_get_priority_max(c->cpu_sched_policy);
858
859         if (i < min || i > max) {
860                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
861                            "CPU scheduling priority is out of range, ignoring: %s", rvalue);
862                 return 0;
863         }
864
865         c->cpu_sched_priority = i;
866         c->cpu_sched_set = true;
867
868         return 0;
869 }
870
871 int config_parse_exec_cpu_affinity(const char *unit,
872                                    const char *filename,
873                                    unsigned line,
874                                    const char *section,
875                                    unsigned section_line,
876                                    const char *lvalue,
877                                    int ltype,
878                                    const char *rvalue,
879                                    void *data,
880                                    void *userdata) {
881
882         ExecContext *c = data;
883         const char *word, *state;
884         size_t l;
885
886         assert(filename);
887         assert(lvalue);
888         assert(rvalue);
889         assert(data);
890
891         if (isempty(rvalue)) {
892                 /* An empty assignment resets the CPU list */
893                 if (c->cpuset)
894                         CPU_FREE(c->cpuset);
895                 c->cpuset = NULL;
896                 return 0;
897         }
898
899         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
900                 _cleanup_free_ char *t = NULL;
901                 int r;
902                 unsigned cpu;
903
904                 t = strndup(word, l);
905                 if (!t)
906                         return log_oom();
907
908                 r = safe_atou(t, &cpu);
909
910                 if (!c->cpuset) {
911                         c->cpuset = cpu_set_malloc(&c->cpuset_ncpus);
912                         if (!c->cpuset)
913                                 return log_oom();
914                 }
915
916                 if (r < 0 || cpu >= c->cpuset_ncpus) {
917                         log_syntax(unit, LOG_ERR, filename, line, ERANGE,
918                                    "Failed to parse CPU affinity '%s', ignoring: %s", t, rvalue);
919                         return 0;
920                 }
921
922                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
923         }
924         if (!isempty(state))
925                 log_syntax(unit, LOG_WARNING, filename, line, EINVAL,
926                            "Trailing garbage, ignoring.");
927
928         return 0;
929 }
930
931 int config_parse_exec_capabilities(const char *unit,
932                                    const char *filename,
933                                    unsigned line,
934                                    const char *section,
935                                    unsigned section_line,
936                                    const char *lvalue,
937                                    int ltype,
938                                    const char *rvalue,
939                                    void *data,
940                                    void *userdata) {
941
942         ExecContext *c = data;
943         cap_t cap;
944
945         assert(filename);
946         assert(lvalue);
947         assert(rvalue);
948         assert(data);
949
950         cap = cap_from_text(rvalue);
951         if (!cap) {
952                 log_syntax(unit, LOG_ERR, filename, line, errno,
953                            "Failed to parse capabilities, ignoring: %s", rvalue);
954                 return 0;
955         }
956
957         if (c->capabilities)
958                 cap_free(c->capabilities);
959         c->capabilities = cap;
960
961         return 0;
962 }
963
964 int config_parse_exec_secure_bits(const char *unit,
965                                   const char *filename,
966                                   unsigned line,
967                                   const char *section,
968                                   unsigned section_line,
969                                   const char *lvalue,
970                                   int ltype,
971                                   const char *rvalue,
972                                   void *data,
973                                   void *userdata) {
974
975         ExecContext *c = data;
976         size_t l;
977         const char *word, *state;
978
979         assert(filename);
980         assert(lvalue);
981         assert(rvalue);
982         assert(data);
983
984         if (isempty(rvalue)) {
985                 /* An empty assignment resets the field */
986                 c->secure_bits = 0;
987                 return 0;
988         }
989
990         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
991                 if (first_word(word, "keep-caps"))
992                         c->secure_bits |= 1<<SECURE_KEEP_CAPS;
993                 else if (first_word(word, "keep-caps-locked"))
994                         c->secure_bits |= 1<<SECURE_KEEP_CAPS_LOCKED;
995                 else if (first_word(word, "no-setuid-fixup"))
996                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP;
997                 else if (first_word(word, "no-setuid-fixup-locked"))
998                         c->secure_bits |= 1<<SECURE_NO_SETUID_FIXUP_LOCKED;
999                 else if (first_word(word, "noroot"))
1000                         c->secure_bits |= 1<<SECURE_NOROOT;
1001                 else if (first_word(word, "noroot-locked"))
1002                         c->secure_bits |= 1<<SECURE_NOROOT_LOCKED;
1003                 else {
1004                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1005                                    "Failed to parse secure bits, ignoring: %s", rvalue);
1006                         return 0;
1007                 }
1008         }
1009         if (!isempty(state))
1010                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1011                            "Invalid syntax, garbage at the end, ignoring.");
1012
1013         return 0;
1014 }
1015
1016 int config_parse_bounding_set(const char *unit,
1017                               const char *filename,
1018                               unsigned line,
1019                               const char *section,
1020                               unsigned section_line,
1021                               const char *lvalue,
1022                               int ltype,
1023                               const char *rvalue,
1024                               void *data,
1025                               void *userdata) {
1026
1027         uint64_t *capability_bounding_set_drop = data;
1028         const char *word, *state;
1029         size_t l;
1030         bool invert = false;
1031         uint64_t sum = 0;
1032
1033         assert(filename);
1034         assert(lvalue);
1035         assert(rvalue);
1036         assert(data);
1037
1038         if (rvalue[0] == '~') {
1039                 invert = true;
1040                 rvalue++;
1041         }
1042
1043         /* Note that we store this inverted internally, since the
1044          * kernel wants it like this. But we actually expose it
1045          * non-inverted everywhere to have a fully normalized
1046          * interface. */
1047
1048         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
1049                 _cleanup_free_ char *t = NULL;
1050                 int cap;
1051
1052                 t = strndup(word, l);
1053                 if (!t)
1054                         return log_oom();
1055
1056                 cap = capability_from_name(t);
1057                 if (cap < 0) {
1058                         log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse capability in bounding set, ignoring: %s", t);
1059                         continue;
1060                 }
1061
1062                 sum |= ((uint64_t) 1ULL) << (uint64_t) cap;
1063         }
1064         if (!isempty(state))
1065                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1066                            "Trailing garbage, ignoring.");
1067
1068         if (invert)
1069                 *capability_bounding_set_drop |= sum;
1070         else
1071                 *capability_bounding_set_drop |= ~sum;
1072
1073         return 0;
1074 }
1075
1076 int config_parse_limit(const char *unit,
1077                        const char *filename,
1078                        unsigned line,
1079                        const char *section,
1080                        unsigned section_line,
1081                        const char *lvalue,
1082                        int ltype,
1083                        const char *rvalue,
1084                        void *data,
1085                        void *userdata) {
1086
1087         struct rlimit **rl = data;
1088         unsigned long long u;
1089
1090         assert(filename);
1091         assert(lvalue);
1092         assert(rvalue);
1093         assert(data);
1094
1095         rl += ltype;
1096
1097         if (streq(rvalue, "infinity"))
1098                 u = (unsigned long long) RLIM_INFINITY;
1099         else {
1100                 int r;
1101
1102                 r = safe_atollu(rvalue, &u);
1103                 if (r < 0) {
1104                         log_syntax(unit, LOG_ERR, filename, line, -r,
1105                                    "Failed to parse resource value, ignoring: %s", rvalue);
1106                         return 0;
1107                 }
1108         }
1109
1110         if (!*rl) {
1111                 *rl = new(struct rlimit, 1);
1112                 if (!*rl)
1113                         return log_oom();
1114         }
1115
1116         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
1117         return 0;
1118 }
1119
1120 #ifdef HAVE_SYSV_COMPAT
1121 int config_parse_sysv_priority(const char *unit,
1122                                const char *filename,
1123                                unsigned line,
1124                                const char *section,
1125                                unsigned section_line,
1126                                const char *lvalue,
1127                                int ltype,
1128                                const char *rvalue,
1129                                void *data,
1130                                void *userdata) {
1131
1132         int *priority = data;
1133         int i, r;
1134
1135         assert(filename);
1136         assert(lvalue);
1137         assert(rvalue);
1138         assert(data);
1139
1140         r = safe_atoi(rvalue, &i);
1141         if (r < 0 || i < 0) {
1142                 log_syntax(unit, LOG_ERR, filename, line, -r,
1143                            "Failed to parse SysV start priority, ignoring: %s", rvalue);
1144                 return 0;
1145         }
1146
1147         *priority = (int) i;
1148         return 0;
1149 }
1150 #endif
1151
1152 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1153
1154 int config_parse_kill_signal(const char *unit,
1155                              const char *filename,
1156                              unsigned line,
1157                              const char *section,
1158                              unsigned section_line,
1159                              const char *lvalue,
1160                              int ltype,
1161                              const char *rvalue,
1162                              void *data,
1163                              void *userdata) {
1164
1165         int *sig = data;
1166         int r;
1167
1168         assert(filename);
1169         assert(lvalue);
1170         assert(rvalue);
1171         assert(sig);
1172
1173         r = signal_from_string_try_harder(rvalue);
1174         if (r <= 0) {
1175                 log_syntax(unit, LOG_ERR, filename, line, -r,
1176                            "Failed to parse kill signal, ignoring: %s", rvalue);
1177                 return 0;
1178         }
1179
1180         *sig = r;
1181         return 0;
1182 }
1183
1184 int config_parse_exec_mount_flags(const char *unit,
1185                                   const char *filename,
1186                                   unsigned line,
1187                                   const char *section,
1188                                   unsigned section_line,
1189                                   const char *lvalue,
1190                                   int ltype,
1191                                   const char *rvalue,
1192                                   void *data,
1193                                   void *userdata) {
1194
1195         ExecContext *c = data;
1196         const char *word, *state;
1197         size_t l;
1198         unsigned long flags = 0;
1199
1200         assert(filename);
1201         assert(lvalue);
1202         assert(rvalue);
1203         assert(data);
1204
1205         FOREACH_WORD_SEPARATOR(word, l, rvalue, ", ", state) {
1206                 _cleanup_free_ char *t;
1207
1208                 t = strndup(word, l);
1209                 if (!t)
1210                         return log_oom();
1211
1212                 if (streq(t, "shared"))
1213                         flags = MS_SHARED;
1214                 else if (streq(t, "slave"))
1215                         flags = MS_SLAVE;
1216                 else if (streq(word, "private"))
1217                         flags = MS_PRIVATE;
1218                 else {
1219                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1220                                    "Failed to parse mount flag %s, ignoring: %s", t, rvalue);
1221                         return 0;
1222                 }
1223         }
1224         if (!isempty(state))
1225                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1226                            "Trailing garbage, ignoring.");
1227
1228         c->mount_flags = flags;
1229         return 0;
1230 }
1231
1232 int config_parse_exec_selinux_context(
1233                 const char *unit,
1234                 const char *filename,
1235                 unsigned line,
1236                 const char *section,
1237                 unsigned section_line,
1238                 const char *lvalue,
1239                 int ltype,
1240                 const char *rvalue,
1241                 void *data,
1242                 void *userdata) {
1243
1244         ExecContext *c = data;
1245         Unit *u = userdata;
1246         bool ignore;
1247         char *k;
1248         int r;
1249
1250         assert(filename);
1251         assert(lvalue);
1252         assert(rvalue);
1253         assert(data);
1254
1255         if (isempty(rvalue)) {
1256                 free(c->selinux_context);
1257                 c->selinux_context = NULL;
1258                 c->selinux_context_ignore = false;
1259                 return 0;
1260         }
1261
1262         if (rvalue[0] == '-') {
1263                 ignore = true;
1264                 rvalue++;
1265         } else
1266                 ignore = false;
1267
1268         r = unit_name_printf(u, rvalue, &k);
1269         if (r < 0) {
1270                 log_syntax(unit, LOG_ERR, filename, line, -r,
1271                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1272                 return 0;
1273         }
1274
1275         free(c->selinux_context);
1276         c->selinux_context = k;
1277         c->selinux_context_ignore = ignore;
1278
1279         return 0;
1280 }
1281
1282 int config_parse_exec_apparmor_profile(
1283                 const char *unit,
1284                 const char *filename,
1285                 unsigned line,
1286                 const char *section,
1287                 unsigned section_line,
1288                 const char *lvalue,
1289                 int ltype,
1290                 const char *rvalue,
1291                 void *data,
1292                 void *userdata) {
1293
1294         ExecContext *c = data;
1295         Unit *u = userdata;
1296         bool ignore;
1297         char *k;
1298         int r;
1299
1300         assert(filename);
1301         assert(lvalue);
1302         assert(rvalue);
1303         assert(data);
1304
1305         if (isempty(rvalue)) {
1306                 free(c->apparmor_profile);
1307                 c->apparmor_profile = NULL;
1308                 c->apparmor_profile_ignore = false;
1309                 return 0;
1310         }
1311
1312         if (rvalue[0] == '-') {
1313                 ignore = true;
1314                 rvalue++;
1315         } else
1316                 ignore = false;
1317
1318         r = unit_name_printf(u, rvalue, &k);
1319         if (r < 0) {
1320                 log_syntax(unit, LOG_ERR, filename, line, -r,
1321                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1322                 return 0;
1323         }
1324
1325         free(c->apparmor_profile);
1326         c->apparmor_profile = k;
1327         c->apparmor_profile_ignore = ignore;
1328
1329         return 0;
1330 }
1331
1332 int config_parse_exec_smack_process_label(
1333                 const char *unit,
1334                 const char *filename,
1335                 unsigned line,
1336                 const char *section,
1337                 unsigned section_line,
1338                 const char *lvalue,
1339                 int ltype,
1340                 const char *rvalue,
1341                 void *data,
1342                 void *userdata) {
1343
1344         ExecContext *c = data;
1345         Unit *u = userdata;
1346         bool ignore;
1347         char *k;
1348         int r;
1349
1350         assert(filename);
1351         assert(lvalue);
1352         assert(rvalue);
1353         assert(data);
1354
1355         if (isempty(rvalue)) {
1356                 free(c->smack_process_label);
1357                 c->smack_process_label = NULL;
1358                 c->smack_process_label_ignore = false;
1359                 return 0;
1360         }
1361
1362         if (rvalue[0] == '-') {
1363                 ignore = true;
1364                 rvalue++;
1365         } else
1366                 ignore = false;
1367
1368         r = unit_name_printf(u, rvalue, &k);
1369         if (r < 0) {
1370                 log_syntax(unit, LOG_ERR, filename, line, -r,
1371                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1372                 return 0;
1373         }
1374
1375         free(c->smack_process_label);
1376         c->smack_process_label = k;
1377         c->smack_process_label_ignore = ignore;
1378
1379         return 0;
1380 }
1381
1382 int config_parse_timer(const char *unit,
1383                        const char *filename,
1384                        unsigned line,
1385                        const char *section,
1386                        unsigned section_line,
1387                        const char *lvalue,
1388                        int ltype,
1389                        const char *rvalue,
1390                        void *data,
1391                        void *userdata) {
1392
1393         Timer *t = data;
1394         usec_t u = 0;
1395         TimerValue *v;
1396         TimerBase b;
1397         CalendarSpec *c = NULL;
1398
1399         assert(filename);
1400         assert(lvalue);
1401         assert(rvalue);
1402         assert(data);
1403
1404         if (isempty(rvalue)) {
1405                 /* Empty assignment resets list */
1406                 timer_free_values(t);
1407                 return 0;
1408         }
1409
1410         b = timer_base_from_string(lvalue);
1411         if (b < 0) {
1412                 log_syntax(unit, LOG_ERR, filename, line, -b,
1413                            "Failed to parse timer base, ignoring: %s", lvalue);
1414                 return 0;
1415         }
1416
1417         if (b == TIMER_CALENDAR) {
1418                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1419                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1420                                    "Failed to parse calendar specification, ignoring: %s",
1421                                    rvalue);
1422                         return 0;
1423                 }
1424         } else {
1425                 if (parse_sec(rvalue, &u) < 0) {
1426                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1427                                    "Failed to parse timer value, ignoring: %s",
1428                                    rvalue);
1429                         return 0;
1430                 }
1431         }
1432
1433         v = new0(TimerValue, 1);
1434         if (!v) {
1435                 calendar_spec_free(c);
1436                 return log_oom();
1437         }
1438
1439         v->base = b;
1440         v->value = u;
1441         v->calendar_spec = c;
1442
1443         LIST_PREPEND(value, t->values, v);
1444
1445         return 0;
1446 }
1447
1448 int config_parse_trigger_unit(
1449                 const char *unit,
1450                 const char *filename,
1451                 unsigned line,
1452                 const char *section,
1453                 unsigned section_line,
1454                 const char *lvalue,
1455                 int ltype,
1456                 const char *rvalue,
1457                 void *data,
1458                 void *userdata) {
1459
1460         _cleanup_free_ char *p = NULL;
1461         Unit *u = data;
1462         UnitType type;
1463         int r;
1464
1465         assert(filename);
1466         assert(lvalue);
1467         assert(rvalue);
1468         assert(data);
1469
1470         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1471                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1472                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1473                 return 0;
1474         }
1475
1476         r = unit_name_printf(u, rvalue, &p);
1477         if (r < 0)
1478                 log_syntax(unit, LOG_ERR, filename, line, -r,
1479                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1480
1481         type = unit_name_to_type(p ?: rvalue);
1482         if (type < 0) {
1483                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1484                            "Unit type not valid, ignoring: %s", rvalue);
1485                 return 0;
1486         }
1487
1488         if (type == u->type) {
1489                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1490                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1491                 return 0;
1492         }
1493
1494         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1495         if (r < 0) {
1496                 log_syntax(unit, LOG_ERR, filename, line, -r,
1497                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1498                 return 0;
1499         }
1500
1501         return 0;
1502 }
1503
1504 int config_parse_path_spec(const char *unit,
1505                            const char *filename,
1506                            unsigned line,
1507                            const char *section,
1508                            unsigned section_line,
1509                            const char *lvalue,
1510                            int ltype,
1511                            const char *rvalue,
1512                            void *data,
1513                            void *userdata) {
1514
1515         Path *p = data;
1516         PathSpec *s;
1517         PathType b;
1518         _cleanup_free_ char *k = NULL;
1519         int r;
1520
1521         assert(filename);
1522         assert(lvalue);
1523         assert(rvalue);
1524         assert(data);
1525
1526         if (isempty(rvalue)) {
1527                 /* Empty assignment clears list */
1528                 path_free_specs(p);
1529                 return 0;
1530         }
1531
1532         b = path_type_from_string(lvalue);
1533         if (b < 0) {
1534                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1535                            "Failed to parse path type, ignoring: %s", lvalue);
1536                 return 0;
1537         }
1538
1539         r = unit_full_printf(UNIT(p), rvalue, &k);
1540         if (r < 0) {
1541                 k = strdup(rvalue);
1542                 if (!k)
1543                         return log_oom();
1544                 else
1545                         log_syntax(unit, LOG_ERR, filename, line, -r,
1546                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1547                                    rvalue);
1548         }
1549
1550         if (!path_is_absolute(k)) {
1551                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1552                            "Path is not absolute, ignoring: %s", k);
1553                 return 0;
1554         }
1555
1556         s = new0(PathSpec, 1);
1557         if (!s)
1558                 return log_oom();
1559
1560         s->unit = UNIT(p);
1561         s->path = path_kill_slashes(k);
1562         k = NULL;
1563         s->type = b;
1564         s->inotify_fd = -1;
1565
1566         LIST_PREPEND(spec, p->specs, s);
1567
1568         return 0;
1569 }
1570
1571 int config_parse_socket_service(
1572                 const char *unit,
1573                 const char *filename,
1574                 unsigned line,
1575                 const char *section,
1576                 unsigned section_line,
1577                 const char *lvalue,
1578                 int ltype,
1579                 const char *rvalue,
1580                 void *data,
1581                 void *userdata) {
1582
1583         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1584         Socket *s = data;
1585         int r;
1586         Unit *x;
1587         _cleanup_free_ char *p = NULL;
1588
1589         assert(filename);
1590         assert(lvalue);
1591         assert(rvalue);
1592         assert(data);
1593
1594         r = unit_name_printf(UNIT(s), rvalue, &p);
1595         if (r < 0) {
1596                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %s", rvalue);
1597                 return 0;
1598         }
1599
1600         if (!endswith(p, ".service")) {
1601                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type service, ignoring: %s", rvalue);
1602                 return 0;
1603         }
1604
1605         r = manager_load_unit(UNIT(s)->manager, p, NULL, &error, &x);
1606         if (r < 0) {
1607                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1608                 return 0;
1609         }
1610
1611         unit_ref_set(&s->service, x);
1612
1613         return 0;
1614 }
1615
1616 int config_parse_service_sockets(
1617                 const char *unit,
1618                 const char *filename,
1619                 unsigned line,
1620                 const char *section,
1621                 unsigned section_line,
1622                 const char *lvalue,
1623                 int ltype,
1624                 const char *rvalue,
1625                 void *data,
1626                 void *userdata) {
1627
1628         Service *s = data;
1629         const char *word, *state;
1630         size_t l;
1631         int r;
1632
1633         assert(filename);
1634         assert(lvalue);
1635         assert(rvalue);
1636         assert(data);
1637
1638         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
1639                 _cleanup_free_ char *t = NULL, *k = NULL;
1640
1641                 t = strndup(word, l);
1642                 if (!t)
1643                         return log_oom();
1644
1645                 r = unit_name_printf(UNIT(s), t, &k);
1646                 if (r < 0) {
1647                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve specifiers, ignoring: %m");
1648                         continue;
1649                 }
1650
1651                 if (!endswith(k, ".socket")) {
1652                         log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Unit must be of type socket, ignoring: %s", k);
1653                         continue;
1654                 }
1655
1656                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k, NULL, true);
1657                 if (r < 0)
1658                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
1659
1660                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k, NULL, true);
1661                 if (r < 0)
1662                         log_syntax(unit, LOG_ERR, filename, line, r, "Failed to add dependency on %s, ignoring: %m", k);
1663         }
1664         if (!isempty(state))
1665                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Trailing garbage, ignoring.");
1666
1667         return 0;
1668 }
1669
1670 int config_parse_bus_name(
1671                 const char *unit,
1672                 const char *filename,
1673                 unsigned line,
1674                 const char *section,
1675                 unsigned section_line,
1676                 const char *lvalue,
1677                 int ltype,
1678                 const char *rvalue,
1679                 void *data,
1680                 void *userdata) {
1681
1682         _cleanup_free_ char *k = NULL;
1683         Unit *u = userdata;
1684         int r;
1685
1686         assert(filename);
1687         assert(lvalue);
1688         assert(rvalue);
1689         assert(u);
1690
1691         r = unit_full_printf(u, rvalue, &k);
1692         if (r < 0) {
1693                 log_syntax(unit, LOG_ERR, filename, line, r, "Failed to resolve unit specifiers on %s, ignoring: %m", rvalue);
1694                 return 0;
1695         }
1696
1697         if (!service_name_is_valid(k)) {
1698                 log_syntax(unit, LOG_ERR, filename, line, r, "Invalid bus name %s, ignoring.", k);
1699                 return 0;
1700         }
1701
1702         return config_parse_string(unit, filename, line, section, section_line, lvalue, ltype, k, data, userdata);
1703 }
1704
1705 int config_parse_service_timeout(const char *unit,
1706                                  const char *filename,
1707                                  unsigned line,
1708                                  const char *section,
1709                                  unsigned section_line,
1710                                  const char *lvalue,
1711                                  int ltype,
1712                                  const char *rvalue,
1713                                  void *data,
1714                                  void *userdata) {
1715
1716         Service *s = userdata;
1717         int r;
1718
1719         assert(filename);
1720         assert(lvalue);
1721         assert(rvalue);
1722         assert(s);
1723
1724         r = config_parse_sec(unit, filename, line, section, section_line, lvalue, ltype,
1725                              rvalue, data, userdata);
1726         if (r < 0)
1727                 return r;
1728
1729         if (streq(lvalue, "TimeoutSec")) {
1730                 s->start_timeout_defined = true;
1731                 s->timeout_stop_usec = s->timeout_start_usec;
1732         } else if (streq(lvalue, "TimeoutStartSec"))
1733                 s->start_timeout_defined = true;
1734
1735         return 0;
1736 }
1737
1738 int config_parse_busname_service(
1739                 const char *unit,
1740                 const char *filename,
1741                 unsigned line,
1742                 const char *section,
1743                 unsigned section_line,
1744                 const char *lvalue,
1745                 int ltype,
1746                 const char *rvalue,
1747                 void *data,
1748                 void *userdata) {
1749
1750         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1751         BusName *n = data;
1752         int r;
1753         Unit *x;
1754         _cleanup_free_ char *p = NULL;
1755
1756         assert(filename);
1757         assert(lvalue);
1758         assert(rvalue);
1759         assert(data);
1760
1761         r = unit_name_printf(UNIT(n), rvalue, &p);
1762         if (r < 0) {
1763                 log_syntax(unit, LOG_ERR, filename, line, -r,
1764                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1765                 return 0;
1766         }
1767
1768         if (!endswith(p, ".service")) {
1769                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1770                            "Unit must be of type service, ignoring: %s", rvalue);
1771                 return 0;
1772         }
1773
1774         r = manager_load_unit(UNIT(n)->manager, p, NULL, &error, &x);
1775         if (r < 0) {
1776                 log_syntax(unit, LOG_ERR, filename, line, -r,
1777                            "Failed to load unit %s, ignoring: %s", rvalue, bus_error_message(&error, r));
1778                 return 0;
1779         }
1780
1781         unit_ref_set(&n->service, x);
1782
1783         return 0;
1784 }
1785
1786 DEFINE_CONFIG_PARSE_ENUM(config_parse_bus_policy_world, bus_policy_access, BusPolicyAccess, "Failed to parse bus name policy access");
1787
1788 int config_parse_bus_policy(
1789                 const char *unit,
1790                 const char *filename,
1791                 unsigned line,
1792                 const char *section,
1793                 unsigned section_line,
1794                 const char *lvalue,
1795                 int ltype,
1796                 const char *rvalue,
1797                 void *data,
1798                 void *userdata) {
1799
1800         _cleanup_free_ BusNamePolicy *p = NULL;
1801         _cleanup_free_ char *id_str = NULL;
1802         BusName *busname = data;
1803         char *access_str;
1804
1805         assert(filename);
1806         assert(lvalue);
1807         assert(rvalue);
1808         assert(data);
1809
1810         p = new0(BusNamePolicy, 1);
1811         if (!p)
1812                 return log_oom();
1813
1814         if (streq(lvalue, "AllowUser"))
1815                 p->type = BUSNAME_POLICY_TYPE_USER;
1816         else if (streq(lvalue, "AllowGroup"))
1817                 p->type = BUSNAME_POLICY_TYPE_GROUP;
1818         else
1819                 assert_not_reached("Unknown lvalue");
1820
1821         id_str = strdup(rvalue);
1822         if (!id_str)
1823                 return log_oom();
1824
1825         access_str = strpbrk(id_str, WHITESPACE);
1826         if (!access_str) {
1827                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1828                            "Invalid busname policy value '%s'", rvalue);
1829                 return 0;
1830         }
1831
1832         *access_str = '\0';
1833         access_str++;
1834         access_str += strspn(access_str, WHITESPACE);
1835
1836         p->access = bus_policy_access_from_string(access_str);
1837         if (p->access < 0) {
1838                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1839                            "Invalid busname policy access type '%s'", access_str);
1840                 return 0;
1841         }
1842
1843         p->name = id_str;
1844         id_str = NULL;
1845
1846         LIST_PREPEND(policy, busname->policy, p);
1847         p = NULL;
1848
1849         return 0;
1850 }
1851
1852 int config_parse_bus_endpoint_policy(
1853                 const char *unit,
1854                 const char *filename,
1855                 unsigned line,
1856                 const char *section,
1857                 unsigned section_line,
1858                 const char *lvalue,
1859                 int ltype,
1860                 const char *rvalue,
1861                 void *data,
1862                 void *userdata) {
1863
1864         _cleanup_free_ char *name = NULL;
1865         BusPolicyAccess access;
1866         ExecContext *c = data;
1867         char *access_str;
1868         int r;
1869
1870         assert(filename);
1871         assert(lvalue);
1872         assert(rvalue);
1873         assert(data);
1874
1875         name = strdup(rvalue);
1876         if (!name)
1877                 return log_oom();
1878
1879         access_str = strpbrk(name, WHITESPACE);
1880         if (!access_str) {
1881                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1882                            "Invalid endpoint policy value '%s'", rvalue);
1883                 return 0;
1884         }
1885
1886         *access_str = '\0';
1887         access_str++;
1888         access_str += strspn(access_str, WHITESPACE);
1889
1890         access = bus_policy_access_from_string(access_str);
1891         if (access <= _BUS_POLICY_ACCESS_INVALID ||
1892             access >= _BUS_POLICY_ACCESS_MAX) {
1893                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1894                            "Invalid endpoint policy access type '%s'", access_str);
1895                 return 0;
1896         }
1897
1898         if (!c->bus_endpoint) {
1899                 r = bus_endpoint_new(&c->bus_endpoint);
1900
1901                 if (r < 0)
1902                         return r;
1903         }
1904
1905         return bus_endpoint_add_policy(c->bus_endpoint, name, access);
1906 }
1907
1908 int config_parse_unit_env_file(const char *unit,
1909                                const char *filename,
1910                                unsigned line,
1911                                const char *section,
1912                                unsigned section_line,
1913                                const char *lvalue,
1914                                int ltype,
1915                                const char *rvalue,
1916                                void *data,
1917                                void *userdata) {
1918
1919         char ***env = data;
1920         Unit *u = userdata;
1921         _cleanup_free_ char *n = NULL;
1922         const char *s;
1923         int r;
1924
1925         assert(filename);
1926         assert(lvalue);
1927         assert(rvalue);
1928         assert(data);
1929
1930         if (isempty(rvalue)) {
1931                 /* Empty assignment frees the list */
1932                 strv_free(*env);
1933                 *env = NULL;
1934                 return 0;
1935         }
1936
1937         r = unit_full_printf(u, rvalue, &n);
1938         if (r < 0)
1939                 log_syntax(unit, LOG_ERR, filename, line, -r,
1940                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1941
1942         s = n ?: rvalue;
1943         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1944                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1945                            "Path '%s' is not absolute, ignoring.", s);
1946                 return 0;
1947         }
1948
1949         r = strv_extend(env, s);
1950         if (r < 0)
1951                 return log_oom();
1952
1953         return 0;
1954 }
1955
1956 int config_parse_environ(const char *unit,
1957                          const char *filename,
1958                          unsigned line,
1959                          const char *section,
1960                          unsigned section_line,
1961                          const char *lvalue,
1962                          int ltype,
1963                          const char *rvalue,
1964                          void *data,
1965                          void *userdata) {
1966
1967         Unit *u = userdata;
1968         char*** env = data;
1969         const char *word, *state;
1970         size_t l;
1971         _cleanup_free_ char *k = NULL;
1972         int r;
1973
1974         assert(filename);
1975         assert(lvalue);
1976         assert(rvalue);
1977         assert(data);
1978
1979         if (isempty(rvalue)) {
1980                 /* Empty assignment resets the list */
1981                 strv_free(*env);
1982                 *env = NULL;
1983                 return 0;
1984         }
1985
1986         if (u) {
1987                 r = unit_full_printf(u, rvalue, &k);
1988                 if (r < 0)
1989                         log_syntax(unit, LOG_ERR, filename, line, -r,
1990                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1991         }
1992
1993         if (!k)
1994                 k = strdup(rvalue);
1995         if (!k)
1996                 return log_oom();
1997
1998         FOREACH_WORD_QUOTED(word, l, k, state) {
1999                 _cleanup_free_ char *n;
2000                 char **x;
2001
2002                 n = cunescape_length(word, l);
2003                 if (!n)
2004                         return log_oom();
2005
2006                 if (!env_assignment_is_valid(n)) {
2007                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2008                                    "Invalid environment assignment, ignoring: %s", rvalue);
2009                         continue;
2010                 }
2011
2012                 x = strv_env_set(*env, n);
2013                 if (!x)
2014                         return log_oom();
2015
2016                 strv_free(*env);
2017                 *env = x;
2018         }
2019         if (!isempty(state))
2020                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2021                            "Trailing garbage, ignoring.");
2022
2023         return 0;
2024 }
2025
2026 int config_parse_ip_tos(const char *unit,
2027                         const char *filename,
2028                         unsigned line,
2029                         const char *section,
2030                         unsigned section_line,
2031                         const char *lvalue,
2032                         int ltype,
2033                         const char *rvalue,
2034                         void *data,
2035                         void *userdata) {
2036
2037         int *ip_tos = data, x;
2038
2039         assert(filename);
2040         assert(lvalue);
2041         assert(rvalue);
2042         assert(data);
2043
2044         x = ip_tos_from_string(rvalue);
2045         if (x < 0) {
2046                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2047                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
2048                 return 0;
2049         }
2050
2051         *ip_tos = x;
2052         return 0;
2053 }
2054
2055 int config_parse_unit_condition_path(
2056                 const char *unit,
2057                 const char *filename,
2058                 unsigned line,
2059                 const char *section,
2060                 unsigned section_line,
2061                 const char *lvalue,
2062                 int ltype,
2063                 const char *rvalue,
2064                 void *data,
2065                 void *userdata) {
2066
2067         _cleanup_free_ char *p = NULL;
2068         Condition **list = data, *c;
2069         ConditionType t = ltype;
2070         bool trigger, negate;
2071         Unit *u = userdata;
2072         int r;
2073
2074         assert(filename);
2075         assert(lvalue);
2076         assert(rvalue);
2077         assert(data);
2078
2079         if (isempty(rvalue)) {
2080                 /* Empty assignment resets the list */
2081                 *list = condition_free_list(*list);
2082                 return 0;
2083         }
2084
2085         trigger = rvalue[0] == '|';
2086         if (trigger)
2087                 rvalue++;
2088
2089         negate = rvalue[0] == '!';
2090         if (negate)
2091                 rvalue++;
2092
2093         r = unit_full_printf(u, rvalue, &p);
2094         if (r < 0) {
2095                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
2096                 return 0;
2097         }
2098
2099         if (!path_is_absolute(p)) {
2100                 log_syntax(unit, LOG_ERR, filename, line, EINVAL, "Path in condition not absolute, ignoring: %s", p);
2101                 return 0;
2102         }
2103
2104         c = condition_new(t, p, trigger, negate);
2105         if (!c)
2106                 return log_oom();
2107
2108         LIST_PREPEND(conditions, *list, c);
2109         return 0;
2110 }
2111
2112 int config_parse_unit_condition_string(
2113                 const char *unit,
2114                 const char *filename,
2115                 unsigned line,
2116                 const char *section,
2117                 unsigned section_line,
2118                 const char *lvalue,
2119                 int ltype,
2120                 const char *rvalue,
2121                 void *data,
2122                 void *userdata) {
2123
2124         _cleanup_free_ char *s = NULL;
2125         Condition **list = data, *c;
2126         ConditionType t = ltype;
2127         bool trigger, negate;
2128         Unit *u = userdata;
2129         int r;
2130
2131         assert(filename);
2132         assert(lvalue);
2133         assert(rvalue);
2134         assert(data);
2135
2136         if (isempty(rvalue)) {
2137                 /* Empty assignment resets the list */
2138                 *list = condition_free_list(*list);
2139                 return 0;
2140         }
2141
2142         trigger = rvalue[0] == '|';
2143         if (trigger)
2144                 rvalue++;
2145
2146         negate = rvalue[0] == '!';
2147         if (negate)
2148                 rvalue++;
2149
2150         r = unit_full_printf(u, rvalue, &s);
2151         if (r < 0) {
2152                 log_syntax(unit, LOG_ERR, filename, line, -r, "Failed to resolve specifiers, ignoring: %s", rvalue);
2153                 return 0;
2154         }
2155
2156         c = condition_new(t, s, trigger, negate);
2157         if (!c)
2158                 return log_oom();
2159
2160         LIST_PREPEND(conditions, *list, c);
2161         return 0;
2162 }
2163
2164 int config_parse_unit_condition_null(
2165                 const char *unit,
2166                 const char *filename,
2167                 unsigned line,
2168                 const char *section,
2169                 unsigned section_line,
2170                 const char *lvalue,
2171                 int ltype,
2172                 const char *rvalue,
2173                 void *data,
2174                 void *userdata) {
2175
2176         Condition **list = data, *c;
2177         bool trigger, negate;
2178         int b;
2179
2180         assert(filename);
2181         assert(lvalue);
2182         assert(rvalue);
2183         assert(data);
2184
2185         if (isempty(rvalue)) {
2186                 /* Empty assignment resets the list */
2187                 *list = condition_free_list(*list);
2188                 return 0;
2189         }
2190
2191         trigger = rvalue[0] == '|';
2192         if (trigger)
2193                 rvalue++;
2194
2195         negate = rvalue[0] == '!';
2196         if (negate)
2197                 rvalue++;
2198
2199         b = parse_boolean(rvalue);
2200         if (b < 0) {
2201                 log_syntax(unit, LOG_ERR, filename, line, -b, "Failed to parse boolean value in condition, ignoring: %s", rvalue);
2202                 return 0;
2203         }
2204
2205         if (!b)
2206                 negate = !negate;
2207
2208         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
2209         if (!c)
2210                 return log_oom();
2211
2212         LIST_PREPEND(conditions, *list, c);
2213         return 0;
2214 }
2215
2216 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
2217 DEFINE_CONFIG_PARSE_ENUM(config_parse_failure_action, failure_action, FailureAction, "Failed to parse failure action specifier");
2218
2219 int config_parse_unit_requires_mounts_for(
2220                 const char *unit,
2221                 const char *filename,
2222                 unsigned line,
2223                 const char *section,
2224                 unsigned section_line,
2225                 const char *lvalue,
2226                 int ltype,
2227                 const char *rvalue,
2228                 void *data,
2229                 void *userdata) {
2230
2231         Unit *u = userdata;
2232         const char *word, *state;
2233         size_t l;
2234
2235         assert(filename);
2236         assert(lvalue);
2237         assert(rvalue);
2238         assert(data);
2239
2240         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2241                 int r;
2242                 _cleanup_free_ char *n;
2243
2244                 n = strndup(word, l);
2245                 if (!n)
2246                         return log_oom();
2247
2248                 if (!utf8_is_valid(n)) {
2249                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
2250                         continue;
2251                 }
2252
2253                 r = unit_require_mounts_for(u, n);
2254                 if (r < 0) {
2255                         log_syntax(unit, LOG_ERR, filename, line, -r,
2256                                    "Failed to add required mount for, ignoring: %s", rvalue);
2257                         continue;
2258                 }
2259         }
2260         if (!isempty(state))
2261                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2262                            "Trailing garbage, ignoring.");
2263
2264         return 0;
2265 }
2266
2267 int config_parse_documentation(const char *unit,
2268                                const char *filename,
2269                                unsigned line,
2270                                const char *section,
2271                                unsigned section_line,
2272                                const char *lvalue,
2273                                int ltype,
2274                                const char *rvalue,
2275                                void *data,
2276                                void *userdata) {
2277
2278         Unit *u = userdata;
2279         int r;
2280         char **a, **b;
2281
2282         assert(filename);
2283         assert(lvalue);
2284         assert(rvalue);
2285         assert(u);
2286
2287         if (isempty(rvalue)) {
2288                 /* Empty assignment resets the list */
2289                 strv_free(u->documentation);
2290                 u->documentation = NULL;
2291                 return 0;
2292         }
2293
2294         r = config_parse_unit_strv_printf(unit, filename, line, section, section_line, lvalue, ltype,
2295                                           rvalue, data, userdata);
2296         if (r < 0)
2297                 return r;
2298
2299         for (a = b = u->documentation; a && *a; a++) {
2300
2301                 if (documentation_url_is_valid(*a))
2302                         *(b++) = *a;
2303                 else {
2304                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2305                                    "Invalid URL, ignoring: %s", *a);
2306                         free(*a);
2307                 }
2308         }
2309         if (b)
2310                 *b = NULL;
2311
2312         return r;
2313 }
2314
2315 #ifdef HAVE_SECCOMP
2316 int config_parse_syscall_filter(
2317                 const char *unit,
2318                 const char *filename,
2319                 unsigned line,
2320                 const char *section,
2321                 unsigned section_line,
2322                 const char *lvalue,
2323                 int ltype,
2324                 const char *rvalue,
2325                 void *data,
2326                 void *userdata) {
2327
2328         static const char default_syscalls[] =
2329                 "execve\0"
2330                 "exit\0"
2331                 "exit_group\0"
2332                 "rt_sigreturn\0"
2333                 "sigreturn\0";
2334
2335         ExecContext *c = data;
2336         Unit *u = userdata;
2337         bool invert = false;
2338         const char *word, *state;
2339         size_t l;
2340         int r;
2341
2342         assert(filename);
2343         assert(lvalue);
2344         assert(rvalue);
2345         assert(u);
2346
2347         if (isempty(rvalue)) {
2348                 /* Empty assignment resets the list */
2349                 set_free(c->syscall_filter);
2350                 c->syscall_filter = NULL;
2351                 c->syscall_whitelist = false;
2352                 return 0;
2353         }
2354
2355         if (rvalue[0] == '~') {
2356                 invert = true;
2357                 rvalue++;
2358         }
2359
2360         if (!c->syscall_filter) {
2361                 c->syscall_filter = set_new(NULL);
2362                 if (!c->syscall_filter)
2363                         return log_oom();
2364
2365                 if (invert)
2366                         /* Allow everything but the ones listed */
2367                         c->syscall_whitelist = false;
2368                 else {
2369                         const char *i;
2370
2371                         /* Allow nothing but the ones listed */
2372                         c->syscall_whitelist = true;
2373
2374                         /* Accept default syscalls if we are on a whitelist */
2375                         NULSTR_FOREACH(i, default_syscalls)  {
2376                                 int id;
2377
2378                                 id = seccomp_syscall_resolve_name(i);
2379                                 if (id < 0)
2380                                         continue;
2381
2382                                 r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2383                                 if (r == -EEXIST)
2384                                         continue;
2385                                 if (r < 0)
2386                                         return log_oom();
2387                         }
2388                 }
2389         }
2390
2391         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2392                 _cleanup_free_ char *t = NULL;
2393                 int id;
2394
2395                 t = strndup(word, l);
2396                 if (!t)
2397                         return log_oom();
2398
2399                 id = seccomp_syscall_resolve_name(t);
2400                 if (id < 0)  {
2401                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2402                                    "Failed to parse system call, ignoring: %s", t);
2403                         continue;
2404                 }
2405
2406                 /* If we previously wanted to forbid a syscall and now
2407                  * we want to allow it, then remove it from the list
2408                  */
2409                 if (!invert == c->syscall_whitelist)  {
2410                         r = set_put(c->syscall_filter, INT_TO_PTR(id + 1));
2411                         if (r == -EEXIST)
2412                                 continue;
2413                         if (r < 0)
2414                                 return log_oom();
2415                 } else
2416                         set_remove(c->syscall_filter, INT_TO_PTR(id + 1));
2417         }
2418         if (!isempty(state))
2419                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2420                            "Trailing garbage, ignoring.");
2421
2422         /* Turn on NNP, but only if it wasn't configured explicitly
2423          * before, and only if we are in user mode. */
2424         if (!c->no_new_privileges_set && u->manager->running_as == SYSTEMD_USER)
2425                 c->no_new_privileges = true;
2426
2427         return 0;
2428 }
2429
2430 int config_parse_syscall_archs(
2431                 const char *unit,
2432                 const char *filename,
2433                 unsigned line,
2434                 const char *section,
2435                 unsigned section_line,
2436                 const char *lvalue,
2437                 int ltype,
2438                 const char *rvalue,
2439                 void *data,
2440                 void *userdata) {
2441
2442         Set **archs = data;
2443         const char *word, *state;
2444         size_t l;
2445         int r;
2446
2447         if (isempty(rvalue)) {
2448                 set_free(*archs);
2449                 *archs = NULL;
2450                 return 0;
2451         }
2452
2453         r = set_ensure_allocated(archs, NULL);
2454         if (r < 0)
2455                 return log_oom();
2456
2457         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2458                 _cleanup_free_ char *t = NULL;
2459                 uint32_t a;
2460
2461                 t = strndup(word, l);
2462                 if (!t)
2463                         return log_oom();
2464
2465                 r = seccomp_arch_from_string(t, &a);
2466                 if (r < 0) {
2467                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2468                                    "Failed to parse system call architecture, ignoring: %s", t);
2469                         continue;
2470                 }
2471
2472                 r = set_put(*archs, UINT32_TO_PTR(a + 1));
2473                 if (r == -EEXIST)
2474                         continue;
2475                 if (r < 0)
2476                         return log_oom();
2477         }
2478         if (!isempty(state))
2479                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2480                            "Trailing garbage, ignoring.");
2481
2482         return 0;
2483 }
2484
2485 int config_parse_syscall_errno(
2486                 const char *unit,
2487                 const char *filename,
2488                 unsigned line,
2489                 const char *section,
2490                 unsigned section_line,
2491                 const char *lvalue,
2492                 int ltype,
2493                 const char *rvalue,
2494                 void *data,
2495                 void *userdata) {
2496
2497         ExecContext *c = data;
2498         int e;
2499
2500         assert(filename);
2501         assert(lvalue);
2502         assert(rvalue);
2503
2504         if (isempty(rvalue)) {
2505                 /* Empty assignment resets to KILL */
2506                 c->syscall_errno = 0;
2507                 return 0;
2508         }
2509
2510         e = errno_from_name(rvalue);
2511         if (e < 0) {
2512                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2513                            "Failed to parse error number, ignoring: %s", rvalue);
2514                 return 0;
2515         }
2516
2517         c->syscall_errno = e;
2518         return 0;
2519 }
2520
2521 int config_parse_address_families(
2522                 const char *unit,
2523                 const char *filename,
2524                 unsigned line,
2525                 const char *section,
2526                 unsigned section_line,
2527                 const char *lvalue,
2528                 int ltype,
2529                 const char *rvalue,
2530                 void *data,
2531                 void *userdata) {
2532
2533         ExecContext *c = data;
2534         bool invert = false;
2535         const char *word, *state;
2536         size_t l;
2537         int r;
2538
2539         assert(filename);
2540         assert(lvalue);
2541         assert(rvalue);
2542
2543         if (isempty(rvalue)) {
2544                 /* Empty assignment resets the list */
2545                 set_free(c->address_families);
2546                 c->address_families = NULL;
2547                 c->address_families_whitelist = false;
2548                 return 0;
2549         }
2550
2551         if (rvalue[0] == '~') {
2552                 invert = true;
2553                 rvalue++;
2554         }
2555
2556         if (!c->address_families) {
2557                 c->address_families = set_new(NULL);
2558                 if (!c->address_families)
2559                         return log_oom();
2560
2561                 c->address_families_whitelist = !invert;
2562         }
2563
2564         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
2565                 _cleanup_free_ char *t = NULL;
2566                 int af;
2567
2568                 t = strndup(word, l);
2569                 if (!t)
2570                         return log_oom();
2571
2572                 af = af_from_name(t);
2573                 if (af <= 0)  {
2574                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2575                                    "Failed to parse address family, ignoring: %s", t);
2576                         continue;
2577                 }
2578
2579                 /* If we previously wanted to forbid an address family and now
2580                  * we want to allow it, then remove it from the list
2581                  */
2582                 if (!invert == c->address_families_whitelist)  {
2583                         r = set_put(c->address_families, INT_TO_PTR(af));
2584                         if (r == -EEXIST)
2585                                 continue;
2586                         if (r < 0)
2587                                 return log_oom();
2588                 } else
2589                         set_remove(c->address_families, INT_TO_PTR(af));
2590         }
2591         if (!isempty(state))
2592                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2593                            "Trailing garbage, ignoring.");
2594
2595         return 0;
2596 }
2597 #endif
2598
2599 int config_parse_unit_slice(
2600                 const char *unit,
2601                 const char *filename,
2602                 unsigned line,
2603                 const char *section,
2604                 unsigned section_line,
2605                 const char *lvalue,
2606                 int ltype,
2607                 const char *rvalue,
2608                 void *data,
2609                 void *userdata) {
2610
2611         _cleanup_free_ char *k = NULL;
2612         Unit *u = userdata, *slice;
2613         int r;
2614
2615         assert(filename);
2616         assert(lvalue);
2617         assert(rvalue);
2618         assert(u);
2619
2620         r = unit_name_printf(u, rvalue, &k);
2621         if (r < 0)
2622                 log_syntax(unit, LOG_ERR, filename, line, -r,
2623                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
2624         if (!k) {
2625                 k = strdup(rvalue);
2626                 if (!k)
2627                         return log_oom();
2628         }
2629
2630         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
2631         if (r < 0) {
2632                 log_syntax(unit, LOG_ERR, filename, line, -r,
2633                            "Failed to load slice unit %s. Ignoring.", k);
2634                 return 0;
2635         }
2636
2637         if (slice->type != UNIT_SLICE) {
2638                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2639                            "Slice unit %s is not a slice. Ignoring.", k);
2640                 return 0;
2641         }
2642
2643         unit_ref_set(&u->slice, slice);
2644         return 0;
2645 }
2646
2647 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
2648
2649 int config_parse_cpu_shares(
2650                 const char *unit,
2651                 const char *filename,
2652                 unsigned line,
2653                 const char *section,
2654                 unsigned section_line,
2655                 const char *lvalue,
2656                 int ltype,
2657                 const char *rvalue,
2658                 void *data,
2659                 void *userdata) {
2660
2661         unsigned long *shares = data, lu;
2662         int r;
2663
2664         assert(filename);
2665         assert(lvalue);
2666         assert(rvalue);
2667
2668         if (isempty(rvalue)) {
2669                 *shares = (unsigned long) -1;
2670                 return 0;
2671         }
2672
2673         r = safe_atolu(rvalue, &lu);
2674         if (r < 0 || lu <= 0) {
2675                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2676                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2677                 return 0;
2678         }
2679
2680         *shares = lu;
2681         return 0;
2682 }
2683
2684 int config_parse_cpu_quota(
2685                 const char *unit,
2686                 const char *filename,
2687                 unsigned line,
2688                 const char *section,
2689                 unsigned section_line,
2690                 const char *lvalue,
2691                 int ltype,
2692                 const char *rvalue,
2693                 void *data,
2694                 void *userdata) {
2695
2696         CGroupContext *c = data;
2697         double percent;
2698
2699         assert(filename);
2700         assert(lvalue);
2701         assert(rvalue);
2702
2703         if (isempty(rvalue)) {
2704                 c->cpu_quota_per_sec_usec = USEC_INFINITY;
2705                 return 0;
2706         }
2707
2708         if (!endswith(rvalue, "%")) {
2709
2710                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2711                            "CPU quota '%s' not ending in '%%'. Ignoring.", rvalue);
2712                 return 0;
2713         }
2714
2715         if (sscanf(rvalue, "%lf%%", &percent) != 1 || percent <= 0) {
2716                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2717                            "CPU quota '%s' invalid. Ignoring.", rvalue);
2718                 return 0;
2719         }
2720
2721         c->cpu_quota_per_sec_usec = (usec_t) (percent * USEC_PER_SEC / 100);
2722
2723         return 0;
2724 }
2725
2726 int config_parse_memory_limit(
2727                 const char *unit,
2728                 const char *filename,
2729                 unsigned line,
2730                 const char *section,
2731                 unsigned section_line,
2732                 const char *lvalue,
2733                 int ltype,
2734                 const char *rvalue,
2735                 void *data,
2736                 void *userdata) {
2737
2738         CGroupContext *c = data;
2739         off_t bytes;
2740         int r;
2741
2742         if (isempty(rvalue)) {
2743                 c->memory_limit = (uint64_t) -1;
2744                 return 0;
2745         }
2746
2747         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2748
2749         r = parse_size(rvalue, 1024, &bytes);
2750         if (r < 0) {
2751                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2752                            "Memory limit '%s' invalid. Ignoring.", rvalue);
2753                 return 0;
2754         }
2755
2756         c->memory_limit = (uint64_t) bytes;
2757         return 0;
2758 }
2759
2760 int config_parse_device_allow(
2761                 const char *unit,
2762                 const char *filename,
2763                 unsigned line,
2764                 const char *section,
2765                 unsigned section_line,
2766                 const char *lvalue,
2767                 int ltype,
2768                 const char *rvalue,
2769                 void *data,
2770                 void *userdata) {
2771
2772         _cleanup_free_ char *path = NULL;
2773         CGroupContext *c = data;
2774         CGroupDeviceAllow *a;
2775         const char *m;
2776         size_t n;
2777
2778         if (isempty(rvalue)) {
2779                 while (c->device_allow)
2780                         cgroup_context_free_device_allow(c, c->device_allow);
2781
2782                 return 0;
2783         }
2784
2785         n = strcspn(rvalue, WHITESPACE);
2786         path = strndup(rvalue, n);
2787         if (!path)
2788                 return log_oom();
2789
2790         if (!startswith(path, "/dev/") &&
2791             !startswith(path, "block-") &&
2792             !startswith(path, "char-")) {
2793                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2794                            "Invalid device node path '%s'. Ignoring.", path);
2795                 return 0;
2796         }
2797
2798         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2799         if (isempty(m))
2800                 m = "rwm";
2801
2802         if (!in_charset(m, "rwm")) {
2803                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2804                            "Invalid device rights '%s'. Ignoring.", m);
2805                 return 0;
2806         }
2807
2808         a = new0(CGroupDeviceAllow, 1);
2809         if (!a)
2810                 return log_oom();
2811
2812         a->path = path;
2813         path = NULL;
2814         a->r = !!strchr(m, 'r');
2815         a->w = !!strchr(m, 'w');
2816         a->m = !!strchr(m, 'm');
2817
2818         LIST_PREPEND(device_allow, c->device_allow, a);
2819         return 0;
2820 }
2821
2822 int config_parse_blockio_weight(
2823                 const char *unit,
2824                 const char *filename,
2825                 unsigned line,
2826                 const char *section,
2827                 unsigned section_line,
2828                 const char *lvalue,
2829                 int ltype,
2830                 const char *rvalue,
2831                 void *data,
2832                 void *userdata) {
2833
2834         unsigned long *weight = data, lu;
2835         int r;
2836
2837         assert(filename);
2838         assert(lvalue);
2839         assert(rvalue);
2840
2841         if (isempty(rvalue)) {
2842                 *weight = (unsigned long) -1;
2843                 return 0;
2844         }
2845
2846         r = safe_atolu(rvalue, &lu);
2847         if (r < 0 || lu < 10 || lu > 1000) {
2848                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2849                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2850                 return 0;
2851         }
2852
2853         *weight = lu;
2854         return 0;
2855 }
2856
2857 int config_parse_blockio_device_weight(
2858                 const char *unit,
2859                 const char *filename,
2860                 unsigned line,
2861                 const char *section,
2862                 unsigned section_line,
2863                 const char *lvalue,
2864                 int ltype,
2865                 const char *rvalue,
2866                 void *data,
2867                 void *userdata) {
2868
2869         _cleanup_free_ char *path = NULL;
2870         CGroupBlockIODeviceWeight *w;
2871         CGroupContext *c = data;
2872         unsigned long lu;
2873         const char *weight;
2874         size_t n;
2875         int r;
2876
2877         assert(filename);
2878         assert(lvalue);
2879         assert(rvalue);
2880
2881         if (isempty(rvalue)) {
2882                 while (c->blockio_device_weights)
2883                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2884
2885                 return 0;
2886         }
2887
2888         n = strcspn(rvalue, WHITESPACE);
2889         weight = rvalue + n;
2890         if (!*weight) {
2891                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2892                            "Expected block device and device weight. Ignoring.");
2893                 return 0;
2894         }
2895
2896         path = strndup(rvalue, n);
2897         if (!path)
2898                 return log_oom();
2899
2900         if (!path_startswith(path, "/dev")) {
2901                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2902                            "Invalid device node path '%s'. Ignoring.", path);
2903                 return 0;
2904         }
2905
2906         weight += strspn(weight, WHITESPACE);
2907         r = safe_atolu(weight, &lu);
2908         if (r < 0 || lu < 10 || lu > 1000) {
2909                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2910                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2911                 return 0;
2912         }
2913
2914         w = new0(CGroupBlockIODeviceWeight, 1);
2915         if (!w)
2916                 return log_oom();
2917
2918         w->path = path;
2919         path = NULL;
2920
2921         w->weight = lu;
2922
2923         LIST_PREPEND(device_weights, c->blockio_device_weights, w);
2924         return 0;
2925 }
2926
2927 int config_parse_blockio_bandwidth(
2928                 const char *unit,
2929                 const char *filename,
2930                 unsigned line,
2931                 const char *section,
2932                 unsigned section_line,
2933                 const char *lvalue,
2934                 int ltype,
2935                 const char *rvalue,
2936                 void *data,
2937                 void *userdata) {
2938
2939         _cleanup_free_ char *path = NULL;
2940         CGroupBlockIODeviceBandwidth *b;
2941         CGroupContext *c = data;
2942         const char *bandwidth;
2943         off_t bytes;
2944         bool read;
2945         size_t n;
2946         int r;
2947
2948         assert(filename);
2949         assert(lvalue);
2950         assert(rvalue);
2951
2952         read = streq("BlockIOReadBandwidth", lvalue);
2953
2954         if (isempty(rvalue)) {
2955                 CGroupBlockIODeviceBandwidth *next;
2956
2957                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2958                         if (b->read == read)
2959                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2960
2961                 return 0;
2962         }
2963
2964         n = strcspn(rvalue, WHITESPACE);
2965         bandwidth = rvalue + n;
2966         bandwidth += strspn(bandwidth, WHITESPACE);
2967
2968         if (!*bandwidth) {
2969                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2970                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2971                 return 0;
2972         }
2973
2974         path = strndup(rvalue, n);
2975         if (!path)
2976                 return log_oom();
2977
2978         if (!path_startswith(path, "/dev")) {
2979                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2980                            "Invalid device node path '%s'. Ignoring.", path);
2981                 return 0;
2982         }
2983
2984         r = parse_size(bandwidth, 1000, &bytes);
2985         if (r < 0 || bytes <= 0) {
2986                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2987                            "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2988                 return 0;
2989         }
2990
2991         b = new0(CGroupBlockIODeviceBandwidth, 1);
2992         if (!b)
2993                 return log_oom();
2994
2995         b->path = path;
2996         path = NULL;
2997         b->bandwidth = (uint64_t) bytes;
2998         b->read = read;
2999
3000         LIST_PREPEND(device_bandwidths, c->blockio_device_bandwidths, b);
3001
3002         return 0;
3003 }
3004
3005 DEFINE_CONFIG_PARSE_ENUM(config_parse_job_mode, job_mode, JobMode, "Failed to parse job mode");
3006
3007 int config_parse_job_mode_isolate(
3008                 const char *unit,
3009                 const char *filename,
3010                 unsigned line,
3011                 const char *section,
3012                 unsigned section_line,
3013                 const char *lvalue,
3014                 int ltype,
3015                 const char *rvalue,
3016                 void *data,
3017                 void *userdata) {
3018
3019         JobMode *m = data;
3020         int r;
3021
3022         assert(filename);
3023         assert(lvalue);
3024         assert(rvalue);
3025
3026         r = parse_boolean(rvalue);
3027         if (r < 0) {
3028                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3029                            "Failed to parse boolean, ignoring: %s", rvalue);
3030                 return 0;
3031         }
3032
3033         *m = r ? JOB_ISOLATE : JOB_REPLACE;
3034         return 0;
3035 }
3036
3037 int config_parse_personality(
3038                 const char *unit,
3039                 const char *filename,
3040                 unsigned line,
3041                 const char *section,
3042                 unsigned section_line,
3043                 const char *lvalue,
3044                 int ltype,
3045                 const char *rvalue,
3046                 void *data,
3047                 void *userdata) {
3048
3049         unsigned long *personality = data, p;
3050
3051         assert(filename);
3052         assert(lvalue);
3053         assert(rvalue);
3054         assert(personality);
3055
3056         p = personality_from_string(rvalue);
3057         if (p == 0xffffffffUL) {
3058                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3059                            "Failed to parse personality, ignoring: %s", rvalue);
3060                 return 0;
3061         }
3062
3063         *personality = p;
3064         return 0;
3065 }
3066
3067 int config_parse_runtime_directory(
3068                 const char *unit,
3069                 const char *filename,
3070                 unsigned line,
3071                 const char *section,
3072                 unsigned section_line,
3073                 const char *lvalue,
3074                 int ltype,
3075                 const char *rvalue,
3076                 void *data,
3077                 void *userdata) {
3078
3079         char***rt = data;
3080         const char *word, *state;
3081         size_t l;
3082         int r;
3083
3084         assert(filename);
3085         assert(lvalue);
3086         assert(rvalue);
3087         assert(data);
3088
3089         if (isempty(rvalue)) {
3090                 /* Empty assignment resets the list */
3091                 strv_free(*rt);
3092                 *rt = NULL;
3093                 return 0;
3094         }
3095
3096         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
3097                 _cleanup_free_ char *n;
3098
3099                 n = strndup(word, l);
3100                 if (!n)
3101                         return log_oom();
3102
3103                 if (!filename_is_valid(n)) {
3104                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3105                                    "Runtime directory is not valid, ignoring assignment: %s", rvalue);
3106                         continue;
3107                 }
3108
3109                 r = strv_push(rt, n);
3110                 if (r < 0)
3111                         return log_oom();
3112
3113                 n = NULL;
3114         }
3115         if (!isempty(state))
3116                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3117                            "Trailing garbage, ignoring.");
3118
3119         return 0;
3120 }
3121
3122 int config_parse_set_status(
3123                 const char *unit,
3124                 const char *filename,
3125                 unsigned line,
3126                 const char *section,
3127                 unsigned section_line,
3128                 const char *lvalue,
3129                 int ltype,
3130                 const char *rvalue,
3131                 void *data,
3132                 void *userdata) {
3133
3134         size_t l;
3135         const char *word, *state;
3136         int r;
3137         ExitStatusSet *status_set = data;
3138
3139         assert(filename);
3140         assert(lvalue);
3141         assert(rvalue);
3142         assert(data);
3143
3144         /* Empty assignment resets the list */
3145         if (isempty(rvalue)) {
3146                 exit_status_set_free(status_set);
3147                 return 0;
3148         }
3149
3150         FOREACH_WORD(word, l, rvalue, state) {
3151                 _cleanup_free_ char *temp;
3152                 int val;
3153
3154                 temp = strndup(word, l);
3155                 if (!temp)
3156                         return log_oom();
3157
3158                 r = safe_atoi(temp, &val);
3159                 if (r < 0) {
3160                         val = signal_from_string_try_harder(temp);
3161
3162                         if (val <= 0) {
3163                                 log_syntax(unit, LOG_ERR, filename, line, -val,
3164                                            "Failed to parse value, ignoring: %s", word);
3165                                 return 0;
3166                         }
3167                 } else {
3168                         if (val < 0 || val > 255) {
3169                                 log_syntax(unit, LOG_ERR, filename, line, ERANGE,
3170                                            "Value %d is outside range 0-255, ignoring", val);
3171                                 continue;
3172                         }
3173                 }
3174
3175                 r = set_ensure_allocated(&status_set->status, NULL);
3176                 if (r < 0)
3177                         return log_oom();
3178
3179                 r = set_put(status_set->status, INT_TO_PTR(val));
3180                 if (r < 0) {
3181                         log_syntax(unit, LOG_ERR, filename, line, -r,
3182                                    "Unable to store: %s", word);
3183                         return r;
3184                 }
3185         }
3186         if (!isempty(state))
3187                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3188                            "Trailing garbage, ignoring.");
3189
3190         return 0;
3191 }
3192
3193 int config_parse_namespace_path_strv(
3194                 const char *unit,
3195                 const char *filename,
3196                 unsigned line,
3197                 const char *section,
3198                 unsigned section_line,
3199                 const char *lvalue,
3200                 int ltype,
3201                 const char *rvalue,
3202                 void *data,
3203                 void *userdata) {
3204
3205         char*** sv = data;
3206         const char *word, *state;
3207         size_t l;
3208         int r;
3209
3210         assert(filename);
3211         assert(lvalue);
3212         assert(rvalue);
3213         assert(data);
3214
3215         if (isempty(rvalue)) {
3216                 /* Empty assignment resets the list */
3217                 strv_free(*sv);
3218                 *sv = NULL;
3219                 return 0;
3220         }
3221
3222         FOREACH_WORD_QUOTED(word, l, rvalue, state) {
3223                 _cleanup_free_ char *n;
3224                 int offset;
3225
3226                 n = strndup(word, l);
3227                 if (!n)
3228                         return log_oom();
3229
3230                 if (!utf8_is_valid(n)) {
3231                         log_invalid_utf8(unit, LOG_ERR, filename, line, EINVAL, rvalue);
3232                         continue;
3233                 }
3234
3235                 offset = n[0] == '-';
3236                 if (!path_is_absolute(n + offset)) {
3237                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3238                                    "Not an absolute path, ignoring: %s", rvalue);
3239                         continue;
3240                 }
3241
3242                 path_kill_slashes(n);
3243
3244                 r = strv_push(sv, n);
3245                 if (r < 0)
3246                         return log_oom();
3247
3248                 n = NULL;
3249         }
3250         if (!isempty(state))
3251                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
3252                            "Trailing garbage, ignoring.");
3253
3254         return 0;
3255 }
3256
3257 int config_parse_no_new_privileges(
3258                 const char* unit,
3259                 const char *filename,
3260                 unsigned line,
3261                 const char *section,
3262                 unsigned section_line,
3263                 const char *lvalue,
3264                 int ltype,
3265                 const char *rvalue,
3266                 void *data,
3267                 void *userdata) {
3268
3269         ExecContext *c = data;
3270         int k;
3271
3272         assert(filename);
3273         assert(lvalue);
3274         assert(rvalue);
3275         assert(data);
3276
3277         k = parse_boolean(rvalue);
3278         if (k < 0) {
3279                 log_syntax(unit, LOG_ERR, filename, line, -k,
3280                            "Failed to parse boolean value, ignoring: %s", rvalue);
3281                 return 0;
3282         }
3283
3284         c->no_new_privileges = !!k;
3285         c->no_new_privileges_set = true;
3286
3287         return 0;
3288 }
3289
3290 int config_parse_protect_home(
3291                 const char* unit,
3292                 const char *filename,
3293                 unsigned line,
3294                 const char *section,
3295                 unsigned section_line,
3296                 const char *lvalue,
3297                 int ltype,
3298                 const char *rvalue,
3299                 void *data,
3300                 void *userdata) {
3301
3302         ExecContext *c = data;
3303         int k;
3304
3305         assert(filename);
3306         assert(lvalue);
3307         assert(rvalue);
3308         assert(data);
3309
3310         /* Our enum shall be a superset of booleans, hence first try
3311          * to parse as as boolean, and then as enum */
3312
3313         k = parse_boolean(rvalue);
3314         if (k > 0)
3315                 c->protect_home = PROTECT_HOME_YES;
3316         else if (k == 0)
3317                 c->protect_home = PROTECT_HOME_NO;
3318         else {
3319                 ProtectHome h;
3320
3321                 h = protect_home_from_string(rvalue);
3322                 if (h < 0){
3323                         log_syntax(unit, LOG_ERR, filename, line, -h,
3324                                    "Failed to parse protect home value, ignoring: %s", rvalue);
3325                         return 0;
3326                 }
3327
3328                 c->protect_home = h;
3329         }
3330
3331         return 0;
3332 }
3333
3334 int config_parse_protect_system(
3335                 const char* unit,
3336                 const char *filename,
3337                 unsigned line,
3338                 const char *section,
3339                 unsigned section_line,
3340                 const char *lvalue,
3341                 int ltype,
3342                 const char *rvalue,
3343                 void *data,
3344                 void *userdata) {
3345
3346         ExecContext *c = data;
3347         int k;
3348
3349         assert(filename);
3350         assert(lvalue);
3351         assert(rvalue);
3352         assert(data);
3353
3354         /* Our enum shall be a superset of booleans, hence first try
3355          * to parse as as boolean, and then as enum */
3356
3357         k = parse_boolean(rvalue);
3358         if (k > 0)
3359                 c->protect_system = PROTECT_SYSTEM_YES;
3360         else if (k == 0)
3361                 c->protect_system = PROTECT_SYSTEM_NO;
3362         else {
3363                 ProtectSystem s;
3364
3365                 s = protect_system_from_string(rvalue);
3366                 if (s < 0){
3367                         log_syntax(unit, LOG_ERR, filename, line, -s,
3368                                    "Failed to parse protect system value, ignoring: %s", rvalue);
3369                         return 0;
3370                 }
3371
3372                 c->protect_system = s;
3373         }
3374
3375         return 0;
3376 }
3377
3378 #define FOLLOW_MAX 8
3379
3380 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
3381         unsigned c = 0;
3382         int fd, r;
3383         FILE *f;
3384         char *id = NULL;
3385
3386         assert(filename);
3387         assert(*filename);
3388         assert(_f);
3389         assert(names);
3390
3391         /* This will update the filename pointer if the loaded file is
3392          * reached by a symlink. The old string will be freed. */
3393
3394         for (;;) {
3395                 char *target, *name;
3396
3397                 if (c++ >= FOLLOW_MAX)
3398                         return -ELOOP;
3399
3400                 path_kill_slashes(*filename);
3401
3402                 /* Add the file name we are currently looking at to
3403                  * the names of this unit, but only if it is a valid
3404                  * unit name. */
3405                 name = basename(*filename);
3406
3407                 if (unit_name_is_valid(name, TEMPLATE_VALID)) {
3408
3409                         id = set_get(names, name);
3410                         if (!id) {
3411                                 id = strdup(name);
3412                                 if (!id)
3413                                         return -ENOMEM;
3414
3415                                 r = set_consume(names, id);
3416                                 if (r < 0)
3417                                         return r;
3418                         }
3419                 }
3420
3421                 /* Try to open the file name, but don't if its a symlink */
3422                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
3423                 if (fd >= 0)
3424                         break;
3425
3426                 if (errno != ELOOP)
3427                         return -errno;
3428
3429                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
3430                 r = readlink_and_make_absolute(*filename, &target);
3431                 if (r < 0)
3432                         return r;
3433
3434                 free(*filename);
3435                 *filename = target;
3436         }
3437
3438         f = fdopen(fd, "re");
3439         if (!f) {
3440                 r = -errno;
3441                 safe_close(fd);
3442                 return r;
3443         }
3444
3445         *_f = f;
3446         *_final = id;
3447         return 0;
3448 }
3449
3450 static int merge_by_names(Unit **u, Set *names, const char *id) {
3451         char *k;
3452         int r;
3453
3454         assert(u);
3455         assert(*u);
3456         assert(names);
3457
3458         /* Let's try to add in all symlink names we found */
3459         while ((k = set_steal_first(names))) {
3460
3461                 /* First try to merge in the other name into our
3462                  * unit */
3463                 r = unit_merge_by_name(*u, k);
3464                 if (r < 0) {
3465                         Unit *other;
3466
3467                         /* Hmm, we couldn't merge the other unit into
3468                          * ours? Then let's try it the other way
3469                          * round */
3470
3471                         other = manager_get_unit((*u)->manager, k);
3472                         free(k);
3473
3474                         if (other) {
3475                                 r = unit_merge(other, *u);
3476                                 if (r >= 0) {
3477                                         *u = other;
3478                                         return merge_by_names(u, names, NULL);
3479                                 }
3480                         }
3481
3482                         return r;
3483                 }
3484
3485                 if (id == k)
3486                         unit_choose_id(*u, id);
3487
3488                 free(k);
3489         }
3490
3491         return 0;
3492 }
3493
3494 static int load_from_path(Unit *u, const char *path) {
3495         int r;
3496         _cleanup_set_free_free_ Set *symlink_names = NULL;
3497         _cleanup_fclose_ FILE *f = NULL;
3498         _cleanup_free_ char *filename = NULL;
3499         char *id = NULL;
3500         Unit *merged;
3501         struct stat st;
3502
3503         assert(u);
3504         assert(path);
3505
3506         symlink_names = set_new(&string_hash_ops);
3507         if (!symlink_names)
3508                 return -ENOMEM;
3509
3510         if (path_is_absolute(path)) {
3511
3512                 filename = strdup(path);
3513                 if (!filename)
3514                         return -ENOMEM;
3515
3516                 r = open_follow(&filename, &f, symlink_names, &id);
3517                 if (r < 0) {
3518                         free(filename);
3519                         filename = NULL;
3520
3521                         if (r != -ENOENT)
3522                                 return r;
3523                 }
3524
3525         } else  {
3526                 char **p;
3527
3528                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
3529
3530                         /* Instead of opening the path right away, we manually
3531                          * follow all symlinks and add their name to our unit
3532                          * name set while doing so */
3533                         filename = path_make_absolute(path, *p);
3534                         if (!filename)
3535                                 return -ENOMEM;
3536
3537                         if (u->manager->unit_path_cache &&
3538                             !set_get(u->manager->unit_path_cache, filename))
3539                                 r = -ENOENT;
3540                         else
3541                                 r = open_follow(&filename, &f, symlink_names, &id);
3542
3543                         if (r < 0) {
3544                                 free(filename);
3545                                 filename = NULL;
3546
3547                                 if (r != -ENOENT)
3548                                         return r;
3549
3550                                 /* Empty the symlink names for the next run */
3551                                 set_clear_free(symlink_names);
3552                                 continue;
3553                         }
3554
3555                         break;
3556                 }
3557         }
3558
3559         if (!filename)
3560                 /* Hmm, no suitable file found? */
3561                 return 0;
3562
3563         merged = u;
3564         r = merge_by_names(&merged, symlink_names, id);
3565         if (r < 0)
3566                 return r;
3567
3568         if (merged != u) {
3569                 u->load_state = UNIT_MERGED;
3570                 return 0;
3571         }
3572
3573         if (fstat(fileno(f), &st) < 0)
3574                 return -errno;
3575
3576         if (null_or_empty(&st))
3577                 u->load_state = UNIT_MASKED;
3578         else {
3579                 u->load_state = UNIT_LOADED;
3580
3581                 /* Now, parse the file contents */
3582                 r = config_parse(u->id, filename, f,
3583                                  UNIT_VTABLE(u)->sections,
3584                                  config_item_perf_lookup, load_fragment_gperf_lookup,
3585                                  false, true, false, u);
3586                 if (r < 0)
3587                         return r;
3588         }
3589
3590         free(u->fragment_path);
3591         u->fragment_path = filename;
3592         filename = NULL;
3593
3594         u->fragment_mtime = timespec_load(&st.st_mtim);
3595
3596         if (u->source_path) {
3597                 if (stat(u->source_path, &st) >= 0)
3598                         u->source_mtime = timespec_load(&st.st_mtim);
3599                 else
3600                         u->source_mtime = 0;
3601         }
3602
3603         return 0;
3604 }
3605
3606 int unit_load_fragment(Unit *u) {
3607         int r;
3608         Iterator i;
3609         const char *t;
3610
3611         assert(u);
3612         assert(u->load_state == UNIT_STUB);
3613         assert(u->id);
3614
3615         /* First, try to find the unit under its id. We always look
3616          * for unit files in the default directories, to make it easy
3617          * to override things by placing things in /etc/systemd/system */
3618         r = load_from_path(u, u->id);
3619         if (r < 0)
3620                 return r;
3621
3622         /* Try to find an alias we can load this with */
3623         if (u->load_state == UNIT_STUB) {
3624                 SET_FOREACH(t, u->names, i) {
3625
3626                         if (t == u->id)
3627                                 continue;
3628
3629                         r = load_from_path(u, t);
3630                         if (r < 0)
3631                                 return r;
3632
3633                         if (u->load_state != UNIT_STUB)
3634                                 break;
3635                 }
3636         }
3637
3638         /* And now, try looking for it under the suggested (originally linked) path */
3639         if (u->load_state == UNIT_STUB && u->fragment_path) {
3640
3641                 r = load_from_path(u, u->fragment_path);
3642                 if (r < 0)
3643                         return r;
3644
3645                 if (u->load_state == UNIT_STUB) {
3646                         /* Hmm, this didn't work? Then let's get rid
3647                          * of the fragment path stored for us, so that
3648                          * we don't point to an invalid location. */
3649                         free(u->fragment_path);
3650                         u->fragment_path = NULL;
3651                 }
3652         }
3653
3654         /* Look for a template */
3655         if (u->load_state == UNIT_STUB && u->instance) {
3656                 _cleanup_free_ char *k;
3657
3658                 k = unit_name_template(u->id);
3659                 if (!k)
3660                         return -ENOMEM;
3661
3662                 r = load_from_path(u, k);
3663                 if (r < 0)
3664                         return r;
3665
3666                 if (u->load_state == UNIT_STUB) {
3667                         SET_FOREACH(t, u->names, i) {
3668                                 _cleanup_free_ char *z = NULL;
3669
3670                                 if (t == u->id)
3671                                         continue;
3672
3673                                 z = unit_name_template(t);
3674                                 if (!z)
3675                                         return -ENOMEM;
3676
3677                                 r = load_from_path(u, z);
3678                                 if (r < 0)
3679                                         return r;
3680
3681                                 if (u->load_state != UNIT_STUB)
3682                                         break;
3683                         }
3684                 }
3685         }
3686
3687         return 0;
3688 }
3689
3690 void unit_dump_config_items(FILE *f) {
3691         static const struct {
3692                 const ConfigParserCallback callback;
3693                 const char *rvalue;
3694         } table[] = {
3695 #if !defined(HAVE_SYSV_COMPAT) || !defined(HAVE_SECCOMP) || !defined(HAVE_PAM) || !defined(HAVE_SELINUX) || !defined(HAVE_SMACK) || !defined(HAVE_APPARMOR)
3696                 { config_parse_warn_compat,           "NOTSUPPORTED" },
3697 #endif
3698                 { config_parse_int,                   "INTEGER" },
3699                 { config_parse_unsigned,              "UNSIGNED" },
3700                 { config_parse_iec_size,              "SIZE" },
3701                 { config_parse_iec_off,               "SIZE" },
3702                 { config_parse_si_size,               "SIZE" },
3703                 { config_parse_bool,                  "BOOLEAN" },
3704                 { config_parse_string,                "STRING" },
3705                 { config_parse_path,                  "PATH" },
3706                 { config_parse_unit_path_printf,      "PATH" },
3707                 { config_parse_strv,                  "STRING [...]" },
3708                 { config_parse_exec_nice,             "NICE" },
3709                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
3710                 { config_parse_exec_io_class,         "IOCLASS" },
3711                 { config_parse_exec_io_priority,      "IOPRIORITY" },
3712                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
3713                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
3714                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
3715                 { config_parse_mode,                  "MODE" },
3716                 { config_parse_unit_env_file,         "FILE" },
3717                 { config_parse_output,                "OUTPUT" },
3718                 { config_parse_input,                 "INPUT" },
3719                 { config_parse_log_facility,          "FACILITY" },
3720                 { config_parse_log_level,             "LEVEL" },
3721                 { config_parse_exec_capabilities,     "CAPABILITIES" },
3722                 { config_parse_exec_secure_bits,      "SECUREBITS" },
3723                 { config_parse_bounding_set,          "BOUNDINGSET" },
3724                 { config_parse_limit,                 "LIMIT" },
3725                 { config_parse_unit_deps,             "UNIT [...]" },
3726                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
3727                 { config_parse_service_type,          "SERVICETYPE" },
3728                 { config_parse_service_restart,       "SERVICERESTART" },
3729 #ifdef HAVE_SYSV_COMPAT
3730                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
3731 #endif
3732                 { config_parse_kill_mode,             "KILLMODE" },
3733                 { config_parse_kill_signal,           "SIGNAL" },
3734                 { config_parse_socket_listen,         "SOCKET [...]" },
3735                 { config_parse_socket_bind,           "SOCKETBIND" },
3736                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
3737                 { config_parse_sec,                   "SECONDS" },
3738                 { config_parse_nsec,                  "NANOSECONDS" },
3739                 { config_parse_namespace_path_strv,   "PATH [...]" },
3740                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
3741                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
3742                 { config_parse_unit_string_printf,    "STRING" },
3743                 { config_parse_trigger_unit,          "UNIT" },
3744                 { config_parse_timer,                 "TIMER" },
3745                 { config_parse_path_spec,             "PATH" },
3746                 { config_parse_notify_access,         "ACCESS" },
3747                 { config_parse_ip_tos,                "TOS" },
3748                 { config_parse_unit_condition_path,   "CONDITION" },
3749                 { config_parse_unit_condition_string, "CONDITION" },
3750                 { config_parse_unit_condition_null,   "CONDITION" },
3751                 { config_parse_unit_slice,            "SLICE" },
3752                 { config_parse_documentation,         "URL" },
3753                 { config_parse_service_timeout,       "SECONDS" },
3754                 { config_parse_failure_action,        "ACTION" },
3755                 { config_parse_set_status,            "STATUS" },
3756                 { config_parse_service_sockets,       "SOCKETS" },
3757                 { config_parse_environ,               "ENVIRON" },
3758 #ifdef HAVE_SECCOMP
3759                 { config_parse_syscall_filter,        "SYSCALLS" },
3760                 { config_parse_syscall_archs,         "ARCHS" },
3761                 { config_parse_syscall_errno,         "ERRNO" },
3762                 { config_parse_address_families,      "FAMILIES" },
3763 #endif
3764                 { config_parse_cpu_shares,            "SHARES" },
3765                 { config_parse_memory_limit,          "LIMIT" },
3766                 { config_parse_device_allow,          "DEVICE" },
3767                 { config_parse_device_policy,         "POLICY" },
3768                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
3769                 { config_parse_blockio_weight,        "WEIGHT" },
3770                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
3771                 { config_parse_long,                  "LONG" },
3772                 { config_parse_socket_service,        "SERVICE" },
3773 #ifdef HAVE_SELINUX
3774                 { config_parse_exec_selinux_context,  "LABEL" },
3775 #endif
3776                 { config_parse_job_mode,              "MODE" },
3777                 { config_parse_job_mode_isolate,      "BOOLEAN" },
3778                 { config_parse_personality,           "PERSONALITY" },
3779         };
3780
3781         const char *prev = NULL;
3782         const char *i;
3783
3784         assert(f);
3785
3786         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
3787                 const char *rvalue = "OTHER", *lvalue;
3788                 unsigned j;
3789                 size_t prefix_len;
3790                 const char *dot;
3791                 const ConfigPerfItem *p;
3792
3793                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
3794
3795                 dot = strchr(i, '.');
3796                 lvalue = dot ? dot + 1 : i;
3797                 prefix_len = dot-i;
3798
3799                 if (dot)
3800                         if (!prev || !strneq(prev, i, prefix_len+1)) {
3801                                 if (prev)
3802                                         fputc('\n', f);
3803
3804                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
3805                         }
3806
3807                 for (j = 0; j < ELEMENTSOF(table); j++)
3808                         if (p->parse == table[j].callback) {
3809                                 rvalue = table[j].rvalue;
3810                                 break;
3811                         }
3812
3813                 fprintf(f, "%s=%s\n", lvalue, rvalue);
3814                 prev = i;
3815         }
3816 }