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