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