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