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