chiark / gitweb /
specifier: rework specifier calls to return proper error message
[elogind.git] / src / core / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7   Copyright 2012 Holger Hans Peter Freyther
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <linux/oom.h>
24 #include <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(SocketPort, port, s->ports, tail);
304                 LIST_INSERT_AFTER(SocketPort, port, s->ports, tail, p);
305         } else
306                 LIST_PREPEND(SocketPort, 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 int config_parse_fsck_passno(const char *unit,
1037                              const char *filename,
1038                              unsigned line,
1039                              const char *section,
1040                              const char *lvalue,
1041                              int ltype,
1042                              const char *rvalue,
1043                              void *data,
1044                              void *userdata) {
1045
1046         int *passno = data;
1047         int i, r;
1048
1049         assert(filename);
1050         assert(lvalue);
1051         assert(rvalue);
1052         assert(data);
1053
1054         r = safe_atoi(rvalue, &i);
1055         if (r || i < 0) {
1056                 log_syntax(unit, LOG_ERR, filename, line, -r,
1057                            "Failed to parse fsck pass number, ignoring: %s", rvalue);
1058                 return 0;
1059         }
1060
1061         *passno = (int) i;
1062         return 0;
1063 }
1064
1065 DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
1066
1067 int config_parse_kill_signal(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         int *sig = data;
1078         int r;
1079
1080         assert(filename);
1081         assert(lvalue);
1082         assert(rvalue);
1083         assert(sig);
1084
1085         r = signal_from_string_try_harder(rvalue);
1086         if (r <= 0) {
1087                 log_syntax(unit, LOG_ERR, filename, line, -r,
1088                            "Failed to parse kill signal, ignoring: %s", rvalue);
1089                 return 0;
1090         }
1091
1092         *sig = r;
1093         return 0;
1094 }
1095
1096 int config_parse_exec_mount_flags(const char *unit,
1097                                   const char *filename,
1098                                   unsigned line,
1099                                   const char *section,
1100                                   const char *lvalue,
1101                                   int ltype,
1102                                   const char *rvalue,
1103                                   void *data,
1104                                   void *userdata) {
1105
1106         ExecContext *c = data;
1107         char *w;
1108         size_t l;
1109         char *state;
1110         unsigned long flags = 0;
1111
1112         assert(filename);
1113         assert(lvalue);
1114         assert(rvalue);
1115         assert(data);
1116
1117         FOREACH_WORD_SEPARATOR(w, l, rvalue, ", ", state) {
1118                 _cleanup_free_ char *t;
1119
1120                 t = strndup(w, l);
1121                 if (!t)
1122                         return log_oom();
1123
1124                 if (streq(t, "shared"))
1125                         flags |= MS_SHARED;
1126                 else if (streq(t, "slave"))
1127                         flags |= MS_SLAVE;
1128                 else if (streq(w, "private"))
1129                         flags |= MS_PRIVATE;
1130                 else {
1131                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1132                                    "Failed to parse mount flag %s, ignoring: %s",
1133                                    t, rvalue);
1134                         return 0;
1135                 }
1136         }
1137
1138         c->mount_flags = flags;
1139         return 0;
1140 }
1141
1142 int config_parse_timer(const char *unit,
1143                        const char *filename,
1144                        unsigned line,
1145                        const char *section,
1146                        const char *lvalue,
1147                        int ltype,
1148                        const char *rvalue,
1149                        void *data,
1150                        void *userdata) {
1151
1152         Timer *t = data;
1153         usec_t u = 0;
1154         TimerValue *v;
1155         TimerBase b;
1156         CalendarSpec *c = NULL;
1157         clockid_t id;
1158
1159         assert(filename);
1160         assert(lvalue);
1161         assert(rvalue);
1162         assert(data);
1163
1164         if (isempty(rvalue)) {
1165                 /* Empty assignment resets list */
1166                 timer_free_values(t);
1167                 return 0;
1168         }
1169
1170         b = timer_base_from_string(lvalue);
1171         if (b < 0) {
1172                 log_syntax(unit, LOG_ERR, filename, line, -b,
1173                            "Failed to parse timer base, ignoring: %s", lvalue);
1174                 return 0;
1175         }
1176
1177         if (b == TIMER_CALENDAR) {
1178                 if (calendar_spec_from_string(rvalue, &c) < 0) {
1179                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1180                                    "Failed to parse calendar specification, ignoring: %s",
1181                                    rvalue);
1182                         return 0;
1183                 }
1184
1185                 id = CLOCK_REALTIME;
1186         } else {
1187                 if (parse_sec(rvalue, &u) < 0) {
1188                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1189                                    "Failed to parse timer value, ignoring: %s",
1190                                    rvalue);
1191                         return 0;
1192                 }
1193
1194                 id = CLOCK_MONOTONIC;
1195         }
1196
1197         v = new0(TimerValue, 1);
1198         if (!v)
1199                 return log_oom();
1200
1201         v->base = b;
1202         v->clock_id = id;
1203         v->value = u;
1204         v->calendar_spec = c;
1205
1206         LIST_PREPEND(TimerValue, value, t->values, v);
1207
1208         return 0;
1209 }
1210
1211 int config_parse_trigger_unit(
1212                 const char *unit,
1213                 const char *filename,
1214                 unsigned line,
1215                 const char *section,
1216                 const char *lvalue,
1217                 int ltype,
1218                 const char *rvalue,
1219                 void *data,
1220                 void *userdata) {
1221
1222         _cleanup_free_ char *p = NULL;
1223         Unit *u = data;
1224         UnitType type;
1225         int r;
1226
1227         assert(filename);
1228         assert(lvalue);
1229         assert(rvalue);
1230         assert(data);
1231
1232         if (!set_isempty(u->dependencies[UNIT_TRIGGERS])) {
1233                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1234                            "Multiple units to trigger specified, ignoring: %s", rvalue);
1235                 return 0;
1236         }
1237
1238         r = unit_name_printf(u, rvalue, &p);
1239         if (r < 0)
1240                 log_syntax(unit, LOG_ERR, filename, line, -r,
1241                            "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1242
1243         type = unit_name_to_type(p ?: rvalue);
1244         if (type < 0) {
1245                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1246                            "Unit type not valid, ignoring: %s", rvalue);
1247                 return 0;
1248         }
1249
1250         if (type == u->type) {
1251                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1252                            "Trigger cannot be of same type, ignoring: %s", rvalue);
1253                 return 0;
1254         }
1255
1256         r = unit_add_two_dependencies_by_name(u, UNIT_BEFORE, UNIT_TRIGGERS, p ?: rvalue, NULL, true);
1257         if (r < 0) {
1258                 log_syntax(unit, LOG_ERR, filename, line, -r,
1259                            "Failed to add trigger on %s, ignoring: %s", p ?: rvalue, strerror(-r));
1260                 return 0;
1261         }
1262
1263         return 0;
1264 }
1265
1266 int config_parse_path_spec(const char *unit,
1267                            const char *filename,
1268                            unsigned line,
1269                            const char *section,
1270                            const char *lvalue,
1271                            int ltype,
1272                            const char *rvalue,
1273                            void *data,
1274                            void *userdata) {
1275
1276         Path *p = data;
1277         PathSpec *s;
1278         PathType b;
1279         _cleanup_free_ char *k = NULL;
1280         int r;
1281
1282         assert(filename);
1283         assert(lvalue);
1284         assert(rvalue);
1285         assert(data);
1286
1287         if (isempty(rvalue)) {
1288                 /* Empty assignment clears list */
1289                 path_free_specs(p);
1290                 return 0;
1291         }
1292
1293         b = path_type_from_string(lvalue);
1294         if (b < 0) {
1295                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1296                            "Failed to parse path type, ignoring: %s", lvalue);
1297                 return 0;
1298         }
1299
1300         r = unit_full_printf(UNIT(p), rvalue, &k);
1301         if (r < 0) {
1302                 k = strdup(rvalue);
1303                 if (!k)
1304                         return log_oom();
1305                 else
1306                         log_syntax(unit, LOG_ERR, filename, line, -r,
1307                                    "Failed to resolve unit specifiers on %s. Ignoring.",
1308                                    rvalue);
1309         }
1310
1311         if (!path_is_absolute(k)) {
1312                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1313                            "Path is not absolute, ignoring: %s", k);
1314                 return 0;
1315         }
1316
1317         s = new0(PathSpec, 1);
1318         if (!s)
1319                 return log_oom();
1320
1321         s->path = path_kill_slashes(k);
1322         k = NULL;
1323         s->type = b;
1324         s->inotify_fd = -1;
1325
1326         LIST_PREPEND(PathSpec, spec, p->specs, s);
1327
1328         return 0;
1329 }
1330
1331 int config_parse_socket_service(const char *unit,
1332                                 const char *filename,
1333                                 unsigned line,
1334                                 const char *section,
1335                                 const char *lvalue,
1336                                 int ltype,
1337                                 const char *rvalue,
1338                                 void *data,
1339                                 void *userdata) {
1340
1341         Socket *s = data;
1342         int r;
1343         DBusError error;
1344         Unit *x;
1345         _cleanup_free_ char *p = NULL;
1346
1347         assert(filename);
1348         assert(lvalue);
1349         assert(rvalue);
1350         assert(data);
1351
1352         dbus_error_init(&error);
1353
1354         r = unit_name_printf(UNIT(s), rvalue, &p);
1355         if (r < 0)
1356                 log_syntax(unit, LOG_ERR, filename, line, -r,
1357                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1358
1359         if (!endswith(p ?: rvalue, ".service")) {
1360                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1361                            "Unit must be of type service, ignoring: %s", rvalue);
1362                 return 0;
1363         }
1364
1365         r = manager_load_unit(UNIT(s)->manager, p ?: rvalue, NULL, &error, &x);
1366         if (r < 0) {
1367                 log_syntax(unit, LOG_ERR, filename, line, r,
1368                            "Failed to load unit %s, ignoring: %s",
1369                            rvalue, bus_error(&error, r));
1370                 dbus_error_free(&error);
1371                 return 0;
1372         }
1373
1374         unit_ref_set(&s->service, x);
1375
1376         return 0;
1377 }
1378
1379 int config_parse_service_sockets(const char *unit,
1380                                  const char *filename,
1381                                  unsigned line,
1382                                  const char *section,
1383                                  const char *lvalue,
1384                                  int ltype,
1385                                  const char *rvalue,
1386                                  void *data,
1387                                  void *userdata) {
1388
1389         Service *s = data;
1390         int r;
1391         char *state, *w;
1392         size_t l;
1393
1394         assert(filename);
1395         assert(lvalue);
1396         assert(rvalue);
1397         assert(data);
1398
1399         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1400                 _cleanup_free_ char *t = NULL, *k = NULL;
1401
1402                 t = strndup(w, l);
1403                 if (!t)
1404                         return log_oom();
1405
1406                 r = unit_name_printf(UNIT(s), t, &k);
1407                 if (r < 0)
1408                         log_syntax(unit, LOG_ERR, filename, line, -r,
1409                                    "Failed to resolve specifiers, ignoring: %s", strerror(-r));
1410
1411                 if (!endswith(k ?: t, ".socket")) {
1412                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1413                                    "Unit must be of type socket, ignoring: %s", k ?: t);
1414                         continue;
1415                 }
1416
1417                 r = unit_add_two_dependencies_by_name(UNIT(s), UNIT_WANTS, UNIT_AFTER, k ?: t, NULL, true);
1418                 if (r < 0)
1419                         log_syntax(unit, LOG_ERR, filename, line, -r,
1420                                    "Failed to add dependency on %s, ignoring: %s",
1421                                    k ?: t, strerror(-r));
1422
1423                 r = unit_add_dependency_by_name(UNIT(s), UNIT_TRIGGERED_BY, k ?: t, NULL, true);
1424                 if (r < 0)
1425                         return r;
1426         }
1427
1428         return 0;
1429 }
1430
1431 int config_parse_service_timeout(const char *unit,
1432                                  const char *filename,
1433                                  unsigned line,
1434                                  const char *section,
1435                                  const char *lvalue,
1436                                  int ltype,
1437                                  const char *rvalue,
1438                                  void *data,
1439                                  void *userdata) {
1440
1441         Service *s = userdata;
1442         int r;
1443
1444         assert(filename);
1445         assert(lvalue);
1446         assert(rvalue);
1447         assert(s);
1448
1449         r = config_parse_sec(unit, filename, line, section, lvalue, ltype,
1450                              rvalue, data, userdata);
1451         if (r < 0)
1452                 return r;
1453
1454         if (streq(lvalue, "TimeoutSec")) {
1455                 s->start_timeout_defined = true;
1456                 s->timeout_stop_usec = s->timeout_start_usec;
1457         } else if (streq(lvalue, "TimeoutStartSec"))
1458                 s->start_timeout_defined = true;
1459
1460         return 0;
1461 }
1462
1463 int config_parse_unit_env_file(const char *unit,
1464                                const char *filename,
1465                                unsigned line,
1466                                const char *section,
1467                                const char *lvalue,
1468                                int ltype,
1469                                const char *rvalue,
1470                                void *data,
1471                                void *userdata) {
1472
1473         char ***env = data;
1474         Unit *u = userdata;
1475         _cleanup_free_ char *n = NULL;
1476         const char *s;
1477         int r;
1478
1479         assert(filename);
1480         assert(lvalue);
1481         assert(rvalue);
1482         assert(data);
1483
1484         if (isempty(rvalue)) {
1485                 /* Empty assignment frees the list */
1486                 strv_free(*env);
1487                 *env = NULL;
1488                 return 0;
1489         }
1490
1491         r = unit_full_printf(u, rvalue, &n);
1492         if (r < 0)
1493                 log_syntax(unit, LOG_ERR, filename, line, r,
1494                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1495
1496         s = n ?: rvalue;
1497         if (!path_is_absolute(s[0] == '-' ? s + 1 : s)) {
1498                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1499                            "Path '%s' is not absolute, ignoring.", s);
1500                 return 0;
1501         }
1502
1503         r = strv_extend(env, s);
1504         if (r < 0)
1505                 return log_oom();
1506
1507         return 0;
1508 }
1509
1510 int config_parse_environ(const char *unit,
1511                          const char *filename,
1512                          unsigned line,
1513                          const char *section,
1514                          const char *lvalue,
1515                          int ltype,
1516                          const char *rvalue,
1517                          void *data,
1518                          void *userdata) {
1519
1520         Unit *u = userdata;
1521         char*** env = data, *w, *state;
1522         size_t l;
1523         _cleanup_free_ char *k = NULL;
1524         int r;
1525
1526         assert(filename);
1527         assert(lvalue);
1528         assert(rvalue);
1529         assert(data);
1530
1531         if (isempty(rvalue)) {
1532                 /* Empty assignment resets the list */
1533                 strv_free(*env);
1534                 *env = NULL;
1535                 return 0;
1536         }
1537
1538         if (u) {
1539                 r = unit_full_printf(u, rvalue, &k);
1540                 if (r < 0)
1541                         log_syntax(unit, LOG_ERR, filename, line, -r,
1542                                    "Failed to resolve specifiers, ignoring: %s", rvalue);
1543         }
1544
1545         if (!k)
1546                 k = strdup(rvalue);
1547         if (!k)
1548                 return log_oom();
1549
1550         FOREACH_WORD_QUOTED(w, l, k, state) {
1551                 _cleanup_free_ char *n;
1552                 char **x;
1553
1554                 n = cunescape_length(w, l);
1555                 if (!n)
1556                         return log_oom();
1557
1558                 if (!env_assignment_is_valid(n)) {
1559                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1560                                    "Invalid environment assignment, ignoring: %s", rvalue);
1561                         continue;
1562                 }
1563
1564                 x = strv_env_set(*env, n);
1565                 if (!x)
1566                         return log_oom();
1567
1568                 strv_free(*env);
1569                 *env = x;
1570         }
1571
1572         return 0;
1573 }
1574
1575 int config_parse_ip_tos(const char *unit,
1576                         const char *filename,
1577                         unsigned line,
1578                         const char *section,
1579                         const char *lvalue,
1580                         int ltype,
1581                         const char *rvalue,
1582                         void *data,
1583                         void *userdata) {
1584
1585         int *ip_tos = data, x;
1586
1587         assert(filename);
1588         assert(lvalue);
1589         assert(rvalue);
1590         assert(data);
1591
1592         x = ip_tos_from_string(rvalue);
1593         if (x < 0) {
1594                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1595                            "Failed to parse IP TOS value, ignoring: %s", rvalue);
1596                 return 0;
1597         }
1598
1599         *ip_tos = x;
1600         return 0;
1601 }
1602
1603 int config_parse_unit_condition_path(const char *unit,
1604                                      const char *filename,
1605                                      unsigned line,
1606                                      const char *section,
1607                                      const char *lvalue,
1608                                      int ltype,
1609                                      const char *rvalue,
1610                                      void *data,
1611                                      void *userdata) {
1612
1613         ConditionType cond = ltype;
1614         Unit *u = data;
1615         bool trigger, negate;
1616         Condition *c;
1617         _cleanup_free_ char *p = NULL;
1618         int r;
1619
1620         assert(filename);
1621         assert(lvalue);
1622         assert(rvalue);
1623         assert(data);
1624
1625         if (isempty(rvalue)) {
1626                 /* Empty assignment resets the list */
1627                 condition_free_list(u->conditions);
1628                 u->conditions = NULL;
1629                 return 0;
1630         }
1631
1632         trigger = rvalue[0] == '|';
1633         if (trigger)
1634                 rvalue++;
1635
1636         negate = rvalue[0] == '!';
1637         if (negate)
1638                 rvalue++;
1639
1640         r = unit_full_printf(u, rvalue, &p);
1641         if (r < 0)
1642                 log_syntax(unit, LOG_ERR, filename, line, -r,
1643                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1644         if (!p) {
1645                 p = strdup(rvalue);
1646                 if (!p)
1647                         return log_oom();
1648         }
1649
1650         if (!path_is_absolute(p)) {
1651                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1652                            "Path in condition not absolute, ignoring: %s", p);
1653                 return 0;
1654         }
1655
1656         c = condition_new(cond, p, trigger, negate);
1657         if (!c)
1658                 return log_oom();
1659
1660         LIST_PREPEND(Condition, conditions, u->conditions, c);
1661         return 0;
1662 }
1663
1664 int config_parse_unit_condition_string(const char *unit,
1665                                        const char *filename,
1666                                        unsigned line,
1667                                        const char *section,
1668                                        const char *lvalue,
1669                                        int ltype,
1670                                        const char *rvalue,
1671                                        void *data,
1672                                        void *userdata) {
1673
1674         ConditionType cond = ltype;
1675         Unit *u = data;
1676         bool trigger, negate;
1677         Condition *c;
1678         _cleanup_free_ char *s = NULL;
1679         int r;
1680
1681         assert(filename);
1682         assert(lvalue);
1683         assert(rvalue);
1684         assert(data);
1685
1686         if (isempty(rvalue)) {
1687                 /* Empty assignment resets the list */
1688                 condition_free_list(u->conditions);
1689                 u->conditions = NULL;
1690                 return 0;
1691         }
1692
1693         trigger = rvalue[0] == '|';
1694         if (trigger)
1695                 rvalue++;
1696
1697         negate = rvalue[0] == '!';
1698         if (negate)
1699                 rvalue++;
1700
1701         r = unit_full_printf(u, rvalue, &s);
1702         if (r < 0)
1703                 log_syntax(unit, LOG_ERR, filename, line, -r,
1704                            "Failed to resolve specifiers, ignoring: %s", rvalue);
1705         if (!s) {
1706                 s = strdup(rvalue);
1707                 if (!s)
1708                         return log_oom();
1709         }
1710
1711         c = condition_new(cond, s, trigger, negate);
1712         if (!c)
1713                 return log_oom();
1714
1715         LIST_PREPEND(Condition, conditions, u->conditions, c);
1716         return 0;
1717 }
1718
1719 int config_parse_unit_condition_null(const char *unit,
1720                                      const char *filename,
1721                                      unsigned line,
1722                                      const char *section,
1723                                      const char *lvalue,
1724                                      int ltype,
1725                                      const char *rvalue,
1726                                      void *data,
1727                                      void *userdata) {
1728
1729         Unit *u = data;
1730         Condition *c;
1731         bool trigger, negate;
1732         int b;
1733
1734         assert(filename);
1735         assert(lvalue);
1736         assert(rvalue);
1737         assert(data);
1738
1739         if (isempty(rvalue)) {
1740                 /* Empty assignment resets the list */
1741                 condition_free_list(u->conditions);
1742                 u->conditions = NULL;
1743                 return 0;
1744         }
1745
1746         trigger = rvalue[0] == '|';
1747         if (trigger)
1748                 rvalue++;
1749
1750         negate = rvalue[0] == '!';
1751         if (negate)
1752                 rvalue++;
1753
1754         b = parse_boolean(rvalue);
1755         if (b < 0) {
1756                 log_syntax(unit, LOG_ERR, filename, line, -b,
1757                            "Failed to parse boolean value in condition, ignoring: %s",
1758                            rvalue);
1759                 return 0;
1760         }
1761
1762         if (!b)
1763                 negate = !negate;
1764
1765         c = condition_new(CONDITION_NULL, NULL, trigger, negate);
1766         if (!c)
1767                 return log_oom();
1768
1769         LIST_PREPEND(Condition, conditions, u->conditions, c);
1770         return 0;
1771 }
1772
1773 DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1774 DEFINE_CONFIG_PARSE_ENUM(config_parse_start_limit_action, start_limit_action, StartLimitAction, "Failed to parse start limit action specifier");
1775
1776 int config_parse_unit_requires_mounts_for(const char *unit,
1777                                           const char *filename,
1778                                           unsigned line,
1779                                           const char *section,
1780                                           const char *lvalue,
1781                                           int ltype,
1782                                           const char *rvalue,
1783                                           void *data,
1784                                           void *userdata) {
1785
1786         Unit *u = userdata;
1787         int r;
1788         bool empty_before;
1789
1790         assert(filename);
1791         assert(lvalue);
1792         assert(rvalue);
1793         assert(data);
1794
1795         empty_before = !u->requires_mounts_for;
1796
1797         r = config_parse_path_strv(unit, filename, line, section, lvalue, ltype,
1798                                    rvalue, data, userdata);
1799
1800         /* Make it easy to find units with requires_mounts set */
1801         if (empty_before && u->requires_mounts_for)
1802                 LIST_PREPEND(Unit, has_requires_mounts_for, u->manager->has_requires_mounts_for, u);
1803
1804         return r;
1805 }
1806
1807 int config_parse_documentation(const char *unit,
1808                                const char *filename,
1809                                unsigned line,
1810                                const char *section,
1811                                const char *lvalue,
1812                                int ltype,
1813                                const char *rvalue,
1814                                void *data,
1815                                void *userdata) {
1816
1817         Unit *u = userdata;
1818         int r;
1819         char **a, **b;
1820
1821         assert(filename);
1822         assert(lvalue);
1823         assert(rvalue);
1824         assert(u);
1825
1826         if (isempty(rvalue)) {
1827                 /* Empty assignment resets the list */
1828                 strv_free(u->documentation);
1829                 u->documentation = NULL;
1830                 return 0;
1831         }
1832
1833         r = config_parse_unit_strv_printf(unit, filename, line, section, lvalue, ltype,
1834                                           rvalue, data, userdata);
1835         if (r < 0)
1836                 return r;
1837
1838         for (a = b = u->documentation; a && *a; a++) {
1839
1840                 if (is_valid_documentation_url(*a))
1841                         *(b++) = *a;
1842                 else {
1843                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1844                                    "Invalid URL, ignoring: %s", *a);
1845                         free(*a);
1846                 }
1847         }
1848         *b = NULL;
1849
1850         return r;
1851 }
1852
1853 static void syscall_set(uint32_t *p, int nr) {
1854         nr = SYSCALL_TO_INDEX(nr);
1855         p[nr >> 4] |= 1 << (nr & 31);
1856 }
1857
1858 static void syscall_unset(uint32_t *p, int nr) {
1859         nr = SYSCALL_TO_INDEX(nr);
1860         p[nr >> 4] &= ~(1 << (nr & 31));
1861 }
1862
1863 int config_parse_syscall_filter(const char *unit,
1864                                 const char *filename,
1865                                 unsigned line,
1866                                 const char *section,
1867                                 const char *lvalue,
1868                                 int ltype,
1869                                 const char *rvalue,
1870                                 void *data,
1871                                 void *userdata) {
1872
1873         ExecContext *c = data;
1874         Unit *u = userdata;
1875         bool invert = false;
1876         char *w;
1877         size_t l;
1878         char *state;
1879
1880         assert(filename);
1881         assert(lvalue);
1882         assert(rvalue);
1883         assert(u);
1884
1885         if (isempty(rvalue)) {
1886                 /* Empty assignment resets the list */
1887                 free(c->syscall_filter);
1888                 c->syscall_filter = NULL;
1889                 return 0;
1890         }
1891
1892         if (rvalue[0] == '~') {
1893                 invert = true;
1894                 rvalue++;
1895         }
1896
1897         if (!c->syscall_filter) {
1898                 size_t n;
1899
1900                 n = (syscall_max() + 31) >> 4;
1901                 c->syscall_filter = new(uint32_t, n);
1902                 if (!c->syscall_filter)
1903                         return log_oom();
1904
1905                 memset(c->syscall_filter, invert ? 0xFF : 0, n * sizeof(uint32_t));
1906
1907                 /* Add these by default */
1908                 syscall_set(c->syscall_filter, __NR_execve);
1909                 syscall_set(c->syscall_filter, __NR_rt_sigreturn);
1910 #ifdef __NR_sigreturn
1911                 syscall_set(c->syscall_filter, __NR_sigreturn);
1912 #endif
1913                 syscall_set(c->syscall_filter, __NR_exit_group);
1914                 syscall_set(c->syscall_filter, __NR_exit);
1915         }
1916
1917         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
1918                 int id;
1919                 _cleanup_free_ char *t = NULL;
1920
1921                 t = strndup(w, l);
1922                 if (!t)
1923                         return log_oom();
1924
1925                 id = syscall_from_name(t);
1926                 if (id < 0)  {
1927                         log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1928                                    "Failed to parse syscall, ignoring: %s", t);
1929                         continue;
1930                 }
1931
1932                 if (invert)
1933                         syscall_unset(c->syscall_filter, id);
1934                 else
1935                         syscall_set(c->syscall_filter, id);
1936         }
1937
1938         c->no_new_privileges = true;
1939
1940         return 0;
1941 }
1942
1943 int config_parse_unit_slice(
1944                 const char *unit,
1945                 const char *filename,
1946                 unsigned line,
1947                 const char *section,
1948                 const char *lvalue,
1949                 int ltype,
1950                 const char *rvalue,
1951                 void *data,
1952                 void *userdata) {
1953
1954         _cleanup_free_ char *k = NULL;
1955         Unit *u = userdata, *slice;
1956         int r;
1957
1958         assert(filename);
1959         assert(lvalue);
1960         assert(rvalue);
1961         assert(u);
1962
1963         r = unit_name_printf(u, rvalue, &k);
1964         if (r < 0)
1965                 log_syntax(unit, LOG_ERR, filename, line, -r,
1966                            "Failed to resolve unit specifiers on %s. Ignoring.", rvalue);
1967         if (!k) {
1968                 k = strdup(rvalue);
1969                 if (!k)
1970                         return log_oom();
1971         }
1972
1973         r = manager_load_unit(u->manager, k, NULL, NULL, &slice);
1974         if (r < 0) {
1975                 log_syntax(unit, LOG_ERR, filename, line, -r,
1976                            "Failed to load slice unit %s. Ignoring.", k);
1977                 return 0;
1978         }
1979
1980         if (slice->type != UNIT_SLICE) {
1981                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
1982                            "Slice unit %s is not a slice. Ignoring.", k);
1983                 return 0;
1984         }
1985
1986         unit_ref_set(&u->slice, slice);
1987         return 0;
1988 }
1989
1990 DEFINE_CONFIG_PARSE_ENUM(config_parse_device_policy, cgroup_device_policy, CGroupDevicePolicy, "Failed to parse device policy");
1991
1992 int config_parse_cpu_shares(
1993                 const char *unit,
1994                 const char *filename,
1995                 unsigned line,
1996                 const char *section,
1997                 const char *lvalue,
1998                 int ltype,
1999                 const char *rvalue,
2000                 void *data,
2001                 void *userdata) {
2002
2003         CGroupContext *c = data;
2004         unsigned long lu;
2005         int r;
2006
2007         assert(filename);
2008         assert(lvalue);
2009         assert(rvalue);
2010
2011         if (isempty(rvalue)) {
2012                 c->cpu_shares = 1024;
2013                 return 0;
2014         }
2015
2016         r = safe_atolu(rvalue, &lu);
2017         if (r < 0 || lu <= 0) {
2018                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2019                            "CPU shares '%s' invalid. Ignoring.", rvalue);
2020                 return 0;
2021         }
2022
2023         c->cpu_shares = lu;
2024         return 0;
2025 }
2026
2027 int config_parse_memory_limit(
2028                 const char *unit,
2029                 const char *filename,
2030                 unsigned line,
2031                 const char *section,
2032                 const char *lvalue,
2033                 int ltype,
2034                 const char *rvalue,
2035                 void *data,
2036                 void *userdata) {
2037
2038         CGroupContext *c = data;
2039         uint64_t *limit;
2040         off_t bytes;
2041         int r;
2042
2043         limit = streq(lvalue, "MemoryLimit") ? &c->memory_limit : &c->memory_soft_limit;
2044
2045         if (isempty(rvalue)) {
2046                 *limit = (uint64_t) -1;
2047                 return 0;
2048         }
2049
2050         assert_cc(sizeof(uint64_t) == sizeof(off_t));
2051
2052         r = parse_bytes(rvalue, &bytes);
2053         if (r < 0) {
2054                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2055                            "Memory limit '%s' invalid. Ignoring.", rvalue);
2056                 return 0;
2057         }
2058
2059         *limit = (uint64_t) bytes;
2060         return 0;
2061 }
2062
2063 int config_parse_device_allow(
2064                 const char *unit,
2065                 const char *filename,
2066                 unsigned line,
2067                 const char *section,
2068                 const char *lvalue,
2069                 int ltype,
2070                 const char *rvalue,
2071                 void *data,
2072                 void *userdata) {
2073
2074         _cleanup_free_ char *path = NULL;
2075         CGroupContext *c = data;
2076         CGroupDeviceAllow *a;
2077         const char *m;
2078         size_t n;
2079
2080         if (isempty(rvalue)) {
2081                 while (c->device_allow)
2082                         cgroup_context_free_device_allow(c, c->device_allow);
2083
2084                 return 0;
2085         }
2086
2087         n = strcspn(rvalue, WHITESPACE);
2088         path = strndup(rvalue, n);
2089         if (!path)
2090                 return log_oom();
2091
2092         if (!path_startswith(path, "/dev")) {
2093                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2094                            "Invalid device node path '%s'. Ignoring.", path);
2095                 return 0;
2096         }
2097
2098         m = rvalue + n + strspn(rvalue + n, WHITESPACE);
2099         if (isempty(m))
2100                 m = "rwm";
2101
2102         if (!in_charset(m, "rwm")) {
2103                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2104                            "Invalid device rights '%s'. Ignoring.", m);
2105                 return 0;
2106         }
2107
2108         a = new0(CGroupDeviceAllow, 1);
2109         if (!a)
2110                 return log_oom();
2111
2112         a->path = path;
2113         path = NULL;
2114         a->r = !!strchr(m, 'r');
2115         a->w = !!strchr(m, 'w');
2116         a->m = !!strchr(m, 'm');
2117
2118         LIST_PREPEND(CGroupDeviceAllow, device_allow, c->device_allow, a);
2119         return 0;
2120 }
2121
2122 int config_parse_blockio_weight(
2123                 const char *unit,
2124                 const char *filename,
2125                 unsigned line,
2126                 const char *section,
2127                 const char *lvalue,
2128                 int ltype,
2129                 const char *rvalue,
2130                 void *data,
2131                 void *userdata) {
2132
2133         CGroupContext *c = data;
2134         unsigned long lu;
2135         int r;
2136
2137         assert(filename);
2138         assert(lvalue);
2139         assert(rvalue);
2140
2141         if (isempty(rvalue)) {
2142                 c->blockio_weight = 1000;
2143                 return 0;
2144         }
2145
2146         r = safe_atolu(rvalue, &lu);
2147         if (r < 0 || lu < 10 || lu > 1000) {
2148                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2149                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2150                 return 0;
2151         }
2152
2153         c->blockio_weight = lu;
2154
2155         return 0;
2156 }
2157
2158 int config_parse_blockio_device_weight(
2159                 const char *unit,
2160                 const char *filename,
2161                 unsigned line,
2162                 const char *section,
2163                 const char *lvalue,
2164                 int ltype,
2165                 const char *rvalue,
2166                 void *data,
2167                 void *userdata) {
2168
2169         _cleanup_free_ char *path = NULL;
2170         CGroupBlockIODeviceWeight *w;
2171         CGroupContext *c = data;
2172         unsigned long lu;
2173         const char *weight;
2174         size_t n;
2175         int r;
2176
2177         assert(filename);
2178         assert(lvalue);
2179         assert(rvalue);
2180
2181         if (isempty(rvalue)) {
2182                 while (c->blockio_device_weights)
2183                         cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights);
2184
2185                 return 0;
2186         }
2187
2188         n = strcspn(rvalue, WHITESPACE);
2189         weight = rvalue + n;
2190         if (!*weight) {
2191                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2192                            "Expected block device and device weight. Ignoring.");
2193                 return 0;
2194         }
2195
2196         path = strndup(rvalue, n);
2197         if (!path)
2198                 return log_oom();
2199
2200         if (!path_startswith(path, "/dev")) {
2201                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2202                            "Invalid device node path '%s'. Ignoring.", path);
2203                 return 0;
2204         }
2205
2206         weight += strspn(weight, WHITESPACE);
2207         r = safe_atolu(weight, &lu);
2208         if (r < 0 || lu < 10 || lu > 1000) {
2209                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2210                            "Block IO weight '%s' invalid. Ignoring.", rvalue);
2211                 return 0;
2212         }
2213
2214
2215         w = new0(CGroupBlockIODeviceWeight, 1);
2216         if (!w)
2217                 return log_oom();
2218
2219         w->path = path;
2220         path = NULL;
2221
2222         w->weight = lu;
2223
2224         LIST_PREPEND(CGroupBlockIODeviceWeight, device_weights, c->blockio_device_weights, w);
2225         return 0;
2226 }
2227
2228 int config_parse_blockio_bandwidth(
2229                 const char *unit,
2230                 const char *filename,
2231                 unsigned line,
2232                 const char *section,
2233                 const char *lvalue,
2234                 int ltype,
2235                 const char *rvalue,
2236                 void *data,
2237                 void *userdata) {
2238
2239         _cleanup_free_ char *path = NULL;
2240         CGroupBlockIODeviceBandwidth *b;
2241         CGroupContext *c = data;
2242         const char *bandwidth;
2243         off_t bytes;
2244         bool read;
2245         size_t n;
2246         int r;
2247
2248         assert(filename);
2249         assert(lvalue);
2250         assert(rvalue);
2251
2252         read = streq("BlockIOReadBandwidth", lvalue);
2253
2254         if (isempty(rvalue)) {
2255                 CGroupBlockIODeviceBandwidth *next;
2256
2257                 LIST_FOREACH_SAFE (device_bandwidths, b, next, c->blockio_device_bandwidths)
2258                         if (b->read == read)
2259                                 cgroup_context_free_blockio_device_bandwidth(c, b);
2260
2261                 return 0;
2262         }
2263
2264         n = strcspn(rvalue, WHITESPACE);
2265         bandwidth = rvalue + n;
2266         bandwidth += strspn(bandwidth, WHITESPACE);
2267
2268         if (!*bandwidth) {
2269                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2270                            "Expected space separated pair of device node and bandwidth. Ignoring.");
2271                 return 0;
2272         }
2273
2274         path = strndup(rvalue, n);
2275         if (!path)
2276                 return log_oom();
2277
2278         if (!path_startswith(path, "/dev")) {
2279                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2280                            "Invalid device node path '%s'. Ignoring.", path);
2281                 return 0;
2282         }
2283
2284         r = parse_bytes(bandwidth, &bytes);
2285         if (r < 0 || bytes <= 0) {
2286                 log_syntax(unit, LOG_ERR, filename, line, EINVAL,
2287                            "Block IO Bandwidth '%s' invalid. Ignoring.", rvalue);
2288                 return 0;
2289         }
2290
2291         b = new0(CGroupBlockIODeviceBandwidth, 1);
2292         if (!b)
2293                 return log_oom();
2294
2295         b->path = path;
2296         path = NULL;
2297         b->bandwidth = (uint64_t) bytes;
2298         b->read = read;
2299
2300         LIST_PREPEND(CGroupBlockIODeviceBandwidth, device_bandwidths, c->blockio_device_bandwidths, b);
2301
2302         return 0;
2303 }
2304
2305 #define FOLLOW_MAX 8
2306
2307 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
2308         unsigned c = 0;
2309         int fd, r;
2310         FILE *f;
2311         char *id = NULL;
2312
2313         assert(filename);
2314         assert(*filename);
2315         assert(_f);
2316         assert(names);
2317
2318         /* This will update the filename pointer if the loaded file is
2319          * reached by a symlink. The old string will be freed. */
2320
2321         for (;;) {
2322                 char *target, *name;
2323
2324                 if (c++ >= FOLLOW_MAX)
2325                         return -ELOOP;
2326
2327                 path_kill_slashes(*filename);
2328
2329                 /* Add the file name we are currently looking at to
2330                  * the names of this unit, but only if it is a valid
2331                  * unit name. */
2332                 name = path_get_file_name(*filename);
2333
2334                 if (unit_name_is_valid(name, true)) {
2335
2336                         id = set_get(names, name);
2337                         if (!id) {
2338                                 id = strdup(name);
2339                                 if (!id)
2340                                         return -ENOMEM;
2341
2342                                 r = set_consume(names, id);
2343                                 if (r < 0)
2344                                         return r;
2345                         }
2346                 }
2347
2348                 /* Try to open the file name, but don't if its a symlink */
2349                 fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW);
2350                 if (fd >= 0)
2351                         break;
2352
2353                 if (errno != ELOOP)
2354                         return -errno;
2355
2356                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
2357                 r = readlink_and_make_absolute(*filename, &target);
2358                 if (r < 0)
2359                         return r;
2360
2361                 free(*filename);
2362                 *filename = target;
2363         }
2364
2365         f = fdopen(fd, "re");
2366         if (!f) {
2367                 r = -errno;
2368                 close_nointr_nofail(fd);
2369                 return r;
2370         }
2371
2372         *_f = f;
2373         *_final = id;
2374         return 0;
2375 }
2376
2377 static int merge_by_names(Unit **u, Set *names, const char *id) {
2378         char *k;
2379         int r;
2380
2381         assert(u);
2382         assert(*u);
2383         assert(names);
2384
2385         /* Let's try to add in all symlink names we found */
2386         while ((k = set_steal_first(names))) {
2387
2388                 /* First try to merge in the other name into our
2389                  * unit */
2390                 r = unit_merge_by_name(*u, k);
2391                 if (r < 0) {
2392                         Unit *other;
2393
2394                         /* Hmm, we couldn't merge the other unit into
2395                          * ours? Then let's try it the other way
2396                          * round */
2397
2398                         other = manager_get_unit((*u)->manager, k);
2399                         free(k);
2400
2401                         if (other) {
2402                                 r = unit_merge(other, *u);
2403                                 if (r >= 0) {
2404                                         *u = other;
2405                                         return merge_by_names(u, names, NULL);
2406                                 }
2407                         }
2408
2409                         return r;
2410                 }
2411
2412                 if (id == k)
2413                         unit_choose_id(*u, id);
2414
2415                 free(k);
2416         }
2417
2418         return 0;
2419 }
2420
2421 static int load_from_path(Unit *u, const char *path) {
2422         int r;
2423         Set *symlink_names;
2424         FILE *f = NULL;
2425         char *filename = NULL, *id = NULL;
2426         Unit *merged;
2427         struct stat st;
2428
2429         assert(u);
2430         assert(path);
2431
2432         symlink_names = set_new(string_hash_func, string_compare_func);
2433         if (!symlink_names)
2434                 return -ENOMEM;
2435
2436         if (path_is_absolute(path)) {
2437
2438                 filename = strdup(path);
2439                 if (!filename) {
2440                         r = -ENOMEM;
2441                         goto finish;
2442                 }
2443
2444                 r = open_follow(&filename, &f, symlink_names, &id);
2445                 if (r < 0) {
2446                         free(filename);
2447                         filename = NULL;
2448
2449                         if (r != -ENOENT)
2450                                 goto finish;
2451                 }
2452
2453         } else  {
2454                 char **p;
2455
2456                 STRV_FOREACH(p, u->manager->lookup_paths.unit_path) {
2457
2458                         /* Instead of opening the path right away, we manually
2459                          * follow all symlinks and add their name to our unit
2460                          * name set while doing so */
2461                         filename = path_make_absolute(path, *p);
2462                         if (!filename) {
2463                                 r = -ENOMEM;
2464                                 goto finish;
2465                         }
2466
2467                         if (u->manager->unit_path_cache &&
2468                             !set_get(u->manager->unit_path_cache, filename))
2469                                 r = -ENOENT;
2470                         else
2471                                 r = open_follow(&filename, &f, symlink_names, &id);
2472
2473                         if (r < 0) {
2474                                 free(filename);
2475                                 filename = NULL;
2476
2477                                 if (r != -ENOENT)
2478                                         goto finish;
2479
2480                                 /* Empty the symlink names for the next run */
2481                                 set_clear_free(symlink_names);
2482                                 continue;
2483                         }
2484
2485                         break;
2486                 }
2487         }
2488
2489         if (!filename) {
2490                 /* Hmm, no suitable file found? */
2491                 r = 0;
2492                 goto finish;
2493         }
2494
2495         merged = u;
2496         r = merge_by_names(&merged, symlink_names, id);
2497         if (r < 0)
2498                 goto finish;
2499
2500         if (merged != u) {
2501                 u->load_state = UNIT_MERGED;
2502                 r = 0;
2503                 goto finish;
2504         }
2505
2506         if (fstat(fileno(f), &st) < 0) {
2507                 r = -errno;
2508                 goto finish;
2509         }
2510
2511         if (null_or_empty(&st))
2512                 u->load_state = UNIT_MASKED;
2513         else {
2514                 u->load_state = UNIT_LOADED;
2515
2516                 /* Now, parse the file contents */
2517                 r = config_parse(u->id, filename, f, UNIT_VTABLE(u)->sections,
2518                                  config_item_perf_lookup,
2519                                  (void*) load_fragment_gperf_lookup, false, true, u);
2520                 if (r < 0)
2521                         goto finish;
2522         }
2523
2524         free(u->fragment_path);
2525         u->fragment_path = filename;
2526         filename = NULL;
2527
2528         u->fragment_mtime = timespec_load(&st.st_mtim);
2529
2530         if (u->source_path) {
2531                 if (stat(u->source_path, &st) >= 0)
2532                         u->source_mtime = timespec_load(&st.st_mtim);
2533                 else
2534                         u->source_mtime = 0;
2535         }
2536
2537         r = 0;
2538
2539 finish:
2540         set_free_free(symlink_names);
2541         free(filename);
2542
2543         if (f)
2544                 fclose(f);
2545
2546         return r;
2547 }
2548
2549 int unit_load_fragment(Unit *u) {
2550         int r;
2551         Iterator i;
2552         const char *t;
2553
2554         assert(u);
2555         assert(u->load_state == UNIT_STUB);
2556         assert(u->id);
2557
2558         /* First, try to find the unit under its id. We always look
2559          * for unit files in the default directories, to make it easy
2560          * to override things by placing things in /etc/systemd/system */
2561         r = load_from_path(u, u->id);
2562         if (r < 0)
2563                 return r;
2564
2565         /* Try to find an alias we can load this with */
2566         if (u->load_state == UNIT_STUB)
2567                 SET_FOREACH(t, u->names, i) {
2568
2569                         if (t == u->id)
2570                                 continue;
2571
2572                         r = load_from_path(u, t);
2573                         if (r < 0)
2574                                 return r;
2575
2576                         if (u->load_state != UNIT_STUB)
2577                                 break;
2578                 }
2579
2580         /* And now, try looking for it under the suggested (originally linked) path */
2581         if (u->load_state == UNIT_STUB && u->fragment_path) {
2582
2583                 r = load_from_path(u, u->fragment_path);
2584                 if (r < 0)
2585                         return r;
2586
2587                 if (u->load_state == UNIT_STUB) {
2588                         /* Hmm, this didn't work? Then let's get rid
2589                          * of the fragment path stored for us, so that
2590                          * we don't point to an invalid location. */
2591                         free(u->fragment_path);
2592                         u->fragment_path = NULL;
2593                 }
2594         }
2595
2596         /* Look for a template */
2597         if (u->load_state == UNIT_STUB && u->instance) {
2598                 char *k;
2599
2600                 k = unit_name_template(u->id);
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                         SET_FOREACH(t, u->names, i) {
2612
2613                                 if (t == u->id)
2614                                         continue;
2615
2616                                 k = unit_name_template(t);
2617                                 if (!k)
2618                                         return -ENOMEM;
2619
2620                                 r = load_from_path(u, k);
2621                                 free(k);
2622
2623                                 if (r < 0)
2624                                         return r;
2625
2626                                 if (u->load_state != UNIT_STUB)
2627                                         break;
2628                         }
2629         }
2630
2631         return 0;
2632 }
2633
2634 void unit_dump_config_items(FILE *f) {
2635         static const struct {
2636                 const ConfigParserCallback callback;
2637                 const char *rvalue;
2638         } table[] = {
2639                 { config_parse_int,                   "INTEGER" },
2640                 { config_parse_unsigned,              "UNSIGNED" },
2641                 { config_parse_bytes_size,            "SIZE" },
2642                 { config_parse_bool,                  "BOOLEAN" },
2643                 { config_parse_string,                "STRING" },
2644                 { config_parse_path,                  "PATH" },
2645                 { config_parse_unit_path_printf,      "PATH" },
2646                 { config_parse_strv,                  "STRING [...]" },
2647                 { config_parse_exec_nice,             "NICE" },
2648                 { config_parse_exec_oom_score_adjust, "OOMSCOREADJUST" },
2649                 { config_parse_exec_io_class,         "IOCLASS" },
2650                 { config_parse_exec_io_priority,      "IOPRIORITY" },
2651                 { config_parse_exec_cpu_sched_policy, "CPUSCHEDPOLICY" },
2652                 { config_parse_exec_cpu_sched_prio,   "CPUSCHEDPRIO" },
2653                 { config_parse_exec_cpu_affinity,     "CPUAFFINITY" },
2654                 { config_parse_mode,                  "MODE" },
2655                 { config_parse_unit_env_file,         "FILE" },
2656                 { config_parse_output,                "OUTPUT" },
2657                 { config_parse_input,                 "INPUT" },
2658                 { config_parse_facility,              "FACILITY" },
2659                 { config_parse_level,                 "LEVEL" },
2660                 { config_parse_exec_capabilities,     "CAPABILITIES" },
2661                 { config_parse_exec_secure_bits,      "SECUREBITS" },
2662                 { config_parse_bounding_set,          "BOUNDINGSET" },
2663                 { config_parse_limit,                 "LIMIT" },
2664                 { config_parse_unit_deps,             "UNIT [...]" },
2665                 { config_parse_exec,                  "PATH [ARGUMENT [...]]" },
2666                 { config_parse_service_type,          "SERVICETYPE" },
2667                 { config_parse_service_restart,       "SERVICERESTART" },
2668 #ifdef HAVE_SYSV_COMPAT
2669                 { config_parse_sysv_priority,         "SYSVPRIORITY" },
2670 #else
2671                 { config_parse_warn_compat,           "NOTSUPPORTED" },
2672 #endif
2673                 { config_parse_kill_mode,             "KILLMODE" },
2674                 { config_parse_kill_signal,           "SIGNAL" },
2675                 { config_parse_socket_listen,         "SOCKET [...]" },
2676                 { config_parse_socket_bind,           "SOCKETBIND" },
2677                 { config_parse_socket_bindtodevice,   "NETWORKINTERFACE" },
2678                 { config_parse_sec,                   "SECONDS" },
2679                 { config_parse_nsec,                  "NANOSECONDS" },
2680                 { config_parse_path_strv,             "PATH [...]" },
2681                 { config_parse_unit_requires_mounts_for, "PATH [...]" },
2682                 { config_parse_exec_mount_flags,      "MOUNTFLAG [...]" },
2683                 { config_parse_unit_string_printf,    "STRING" },
2684                 { config_parse_trigger_unit,          "UNIT" },
2685                 { config_parse_timer,                 "TIMER" },
2686                 { config_parse_path_spec,             "PATH" },
2687                 { config_parse_notify_access,         "ACCESS" },
2688                 { config_parse_ip_tos,                "TOS" },
2689                 { config_parse_unit_condition_path,   "CONDITION" },
2690                 { config_parse_unit_condition_string, "CONDITION" },
2691                 { config_parse_unit_condition_null,   "CONDITION" },
2692                 { config_parse_unit_slice,            "SLICE" },
2693                 { config_parse_documentation,         "URL" },
2694                 { config_parse_service_timeout,       "SECONDS" },
2695                 { config_parse_start_limit_action,    "ACTION" },
2696                 { config_parse_set_status,            "STATUS" },
2697                 { config_parse_service_sockets,       "SOCKETS" },
2698                 { config_parse_fsck_passno,           "PASSNO" },
2699                 { config_parse_environ,               "ENVIRON" },
2700                 { config_parse_syscall_filter,        "SYSCALL" },
2701                 { config_parse_cpu_shares,            "SHARES" },
2702                 { config_parse_memory_limit,          "LIMIT" },
2703                 { config_parse_device_allow,          "DEVICE" },
2704                 { config_parse_device_policy,         "POLICY" },
2705                 { config_parse_blockio_bandwidth,     "BANDWIDTH" },
2706                 { config_parse_blockio_weight,        "WEIGHT" },
2707                 { config_parse_blockio_device_weight, "DEVICEWEIGHT" },
2708                 { config_parse_long,                  "LONG" },
2709                 { config_parse_socket_service,        "SERVICE" },
2710         };
2711
2712         const char *prev = NULL;
2713         const char *i;
2714
2715         assert(f);
2716
2717         NULSTR_FOREACH(i, load_fragment_gperf_nulstr) {
2718                 const char *rvalue = "OTHER", *lvalue;
2719                 unsigned j;
2720                 size_t prefix_len;
2721                 const char *dot;
2722                 const ConfigPerfItem *p;
2723
2724                 assert_se(p = load_fragment_gperf_lookup(i, strlen(i)));
2725
2726                 dot = strchr(i, '.');
2727                 lvalue = dot ? dot + 1 : i;
2728                 prefix_len = dot-i;
2729
2730                 if (dot)
2731                         if (!prev || !strneq(prev, i, prefix_len+1)) {
2732                                 if (prev)
2733                                         fputc('\n', f);
2734
2735                                 fprintf(f, "[%.*s]\n", (int) prefix_len, i);
2736                         }
2737
2738                 for (j = 0; j < ELEMENTSOF(table); j++)
2739                         if (p->parse == table[j].callback) {
2740                                 rvalue = table[j].rvalue;
2741                                 break;
2742                         }
2743
2744                 fprintf(f, "%s=%s\n", lvalue, rvalue);
2745                 prev = i;
2746         }
2747 }