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