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