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