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