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