chiark / gitweb /
build-sys: prepare release 1
[elogind.git] / src / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2010 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <linux/oom.h>
23 #include <assert.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <fcntl.h>
28 #include <sched.h>
29 #include <sys/prctl.h>
30 #include <sys/mount.h>
31 #include <linux/fs.h>
32
33 #include "unit.h"
34 #include "strv.h"
35 #include "conf-parser.h"
36 #include "load-fragment.h"
37 #include "log.h"
38 #include "ioprio.h"
39 #include "securebits.h"
40 #include "missing.h"
41 #include "unit-name.h"
42
43 #define COMMENTS "#;\n"
44 #define LINE_MAX 4096
45
46 static int config_parse_deps(
47                 const char *filename,
48                 unsigned line,
49                 const char *section,
50                 const char *lvalue,
51                 const char *rvalue,
52                 void *data,
53                 void *userdata) {
54
55         UnitDependency d = PTR_TO_UINT(data);
56         Unit *u = userdata;
57         char *w;
58         size_t l;
59         char *state;
60
61         assert(filename);
62         assert(lvalue);
63         assert(rvalue);
64
65         FOREACH_WORD(w, l, rvalue, state) {
66                 char *t, *k;
67                 int r;
68
69                 if (!(t = strndup(w, l)))
70                         return -ENOMEM;
71
72                 k = unit_name_printf(u, t);
73                 free(t);
74
75                 if (!k)
76                         return -ENOMEM;
77
78                 r = unit_add_dependency_by_name(u, d, k, NULL, true);
79                 free(k);
80
81                 if (r < 0)
82                         return r;
83         }
84
85         return 0;
86 }
87
88 static int config_parse_names(
89                 const char *filename,
90                 unsigned line,
91                 const char *section,
92                 const char *lvalue,
93                 const char *rvalue,
94                 void *data,
95                 void *userdata) {
96
97         Unit *u = userdata;
98         char *w;
99         size_t l;
100         char *state;
101
102         assert(filename);
103         assert(lvalue);
104         assert(rvalue);
105         assert(data);
106
107         FOREACH_WORD(w, l, rvalue, state) {
108                 char *t, *k;
109                 int r;
110
111                 if (!(t = strndup(w, l)))
112                         return -ENOMEM;
113
114                 k = unit_name_printf(u, t);
115                 free(t);
116
117                 if (!k)
118                         return -ENOMEM;
119
120                 r = unit_merge_by_name(u, k);
121                 free(k);
122
123                 if (r < 0)
124                         return r;
125         }
126
127         return 0;
128 }
129
130 static int config_parse_string_printf(
131                 const char *filename,
132                 unsigned line,
133                 const char *section,
134                 const char *lvalue,
135                 const char *rvalue,
136                 void *data,
137                 void *userdata) {
138
139         Unit *u = userdata;
140         char **s = data;
141         char *k;
142
143         assert(filename);
144         assert(lvalue);
145         assert(rvalue);
146         assert(s);
147         assert(u);
148
149         if (!(k = unit_full_printf(u, rvalue)))
150                 return -ENOMEM;
151
152         free(*s);
153         if (*k)
154                 *s = k;
155         else {
156                 free(k);
157                 *s = NULL;
158         }
159
160         return 0;
161 }
162
163 static int config_parse_listen(
164                 const char *filename,
165                 unsigned line,
166                 const char *section,
167                 const char *lvalue,
168                 const char *rvalue,
169                 void *data,
170                 void *userdata) {
171
172         int r;
173         SocketPort *p;
174         Socket *s;
175
176         assert(filename);
177         assert(lvalue);
178         assert(rvalue);
179         assert(data);
180
181         s = (Socket*) data;
182
183         if (!(p = new0(SocketPort, 1)))
184                 return -ENOMEM;
185
186         if (streq(lvalue, "ListenFIFO")) {
187                 p->type = SOCKET_FIFO;
188
189                 if (!(p->path = strdup(rvalue))) {
190                         free(p);
191                         return -ENOMEM;
192                 }
193
194                 path_kill_slashes(p->path);
195         } else {
196                 p->type = SOCKET_SOCKET;
197
198                 if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
199                         log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
200                         free(p);
201                         return r;
202                 }
203
204                 if (streq(lvalue, "ListenStream"))
205                         p->address.type = SOCK_STREAM;
206                 else if (streq(lvalue, "ListenDatagram"))
207                         p->address.type = SOCK_DGRAM;
208                 else {
209                         assert(streq(lvalue, "ListenSequentialPacket"));
210                         p->address.type = SOCK_SEQPACKET;
211                 }
212
213                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
214                         free(p);
215                         return -EPROTONOSUPPORT;
216                 }
217         }
218
219         p->fd = -1;
220         LIST_PREPEND(SocketPort, port, s->ports, p);
221
222         return 0;
223 }
224
225 static int config_parse_socket_bind(
226                 const char *filename,
227                 unsigned line,
228                 const char *section,
229                 const char *lvalue,
230                 const char *rvalue,
231                 void *data,
232                 void *userdata) {
233
234         Socket *s;
235         SocketAddressBindIPv6Only b;
236
237         assert(filename);
238         assert(lvalue);
239         assert(rvalue);
240         assert(data);
241
242         s = (Socket*) data;
243
244         if ((b = socket_address_bind_ipv6_only_from_string(rvalue)) < 0) {
245                 int r;
246
247                 if ((r = parse_boolean(rvalue)) < 0) {
248                         log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
249                         return -EBADMSG;
250                 }
251
252                 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
253         } else
254                 s->bind_ipv6_only = b;
255
256         return 0;
257 }
258
259 static int config_parse_nice(
260                 const char *filename,
261                 unsigned line,
262                 const char *section,
263                 const char *lvalue,
264                 const char *rvalue,
265                 void *data,
266                 void *userdata) {
267
268         ExecContext *c = data;
269         int priority, r;
270
271         assert(filename);
272         assert(lvalue);
273         assert(rvalue);
274         assert(data);
275
276         if ((r = safe_atoi(rvalue, &priority)) < 0) {
277                 log_error("[%s:%u] Failed to parse nice priority: %s", filename, line, rvalue);
278                 return r;
279         }
280
281         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
282                 log_error("[%s:%u] Nice priority out of range: %s", filename, line, rvalue);
283                 return -ERANGE;
284         }
285
286         c->nice = priority;
287         c->nice_set = false;
288
289         return 0;
290 }
291
292 static int config_parse_oom_adjust(
293                 const char *filename,
294                 unsigned line,
295                 const char *section,
296                 const char *lvalue,
297                 const char *rvalue,
298                 void *data,
299                 void *userdata) {
300
301         ExecContext *c = data;
302         int oa, r;
303
304         assert(filename);
305         assert(lvalue);
306         assert(rvalue);
307         assert(data);
308
309         if ((r = safe_atoi(rvalue, &oa)) < 0) {
310                 log_error("[%s:%u] Failed to parse OOM adjust value: %s", filename, line, rvalue);
311                 return r;
312         }
313
314         if (oa < OOM_DISABLE || oa > OOM_ADJUST_MAX) {
315                 log_error("[%s:%u] OOM adjust value out of range: %s", filename, line, rvalue);
316                 return -ERANGE;
317         }
318
319         c->oom_adjust = oa;
320         c->oom_adjust_set = true;
321
322         return 0;
323 }
324
325 static int config_parse_mode(
326                 const char *filename,
327                 unsigned line,
328                 const char *section,
329                 const char *lvalue,
330                 const char *rvalue,
331                 void *data,
332                 void *userdata) {
333
334         mode_t *m = data;
335         long l;
336         char *x = NULL;
337
338         assert(filename);
339         assert(lvalue);
340         assert(rvalue);
341         assert(data);
342
343         errno = 0;
344         l = strtol(rvalue, &x, 8);
345         if (!x || *x || errno) {
346                 log_error("[%s:%u] Failed to parse mode value: %s", filename, line, rvalue);
347                 return errno ? -errno : -EINVAL;
348         }
349
350         if (l < 0000 || l > 07777) {
351                 log_error("[%s:%u] mode value out of range: %s", filename, line, rvalue);
352                 return -ERANGE;
353         }
354
355         *m = (mode_t) l;
356         return 0;
357 }
358
359 static int config_parse_exec(
360                 const char *filename,
361                 unsigned line,
362                 const char *section,
363                 const char *lvalue,
364                 const char *rvalue,
365                 void *data,
366                 void *userdata) {
367
368         ExecCommand **e = data, *nce = NULL;
369         char **n;
370         char *w;
371         unsigned k;
372         size_t l;
373         char *state, *path = NULL;
374         bool honour_argv0, write_to_path;
375
376         assert(filename);
377         assert(lvalue);
378         assert(rvalue);
379         assert(data);
380
381         /* We accept an absolute path as first argument, or
382          * alternatively an absolute prefixed with @ to allow
383          * overriding of argv[0]. */
384
385         honour_argv0 = rvalue[0] == '@';
386
387         if (rvalue[honour_argv0 ? 1 : 0] != '/') {
388                 log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
389                 return -EINVAL;
390         }
391
392         k = 0;
393         FOREACH_WORD_QUOTED(w, l, rvalue, state)
394                 k++;
395
396         if (!(n = new(char*, k + (honour_argv0 ? 0 : 1))))
397                 return -ENOMEM;
398
399         k = 0;
400         write_to_path = honour_argv0;
401         FOREACH_WORD_QUOTED(w, l, rvalue, state) {
402                 if (write_to_path) {
403                         if (!(path = strndup(w+1, l-1)))
404                                 goto fail;
405                         write_to_path = false;
406                 } else {
407                         if (!(n[k++] = strndup(w, l)))
408                                 goto fail;
409                 }
410         }
411
412         n[k] = NULL;
413
414         if (!n[0]) {
415                 log_error("[%s:%u] Invalid command line: %s", filename, line, rvalue);
416                 strv_free(n);
417                 return -EINVAL;
418         }
419
420         if (!path)
421                 if (!(path = strdup(n[0])))
422                         goto fail;
423
424         assert(path_is_absolute(path));
425
426         if (!(nce = new0(ExecCommand, 1)))
427                 goto fail;
428
429         nce->argv = n;
430         nce->path = path;
431
432         path_kill_slashes(nce->path);
433
434         exec_command_append_list(e, nce);
435
436         return 0;
437
438 fail:
439         n[k] = NULL;
440         strv_free(n);
441         free(path);
442         free(nce);
443
444         return -ENOMEM;
445 }
446
447 static int config_parse_usec(
448                 const char *filename,
449                 unsigned line,
450                 const char *section,
451                 const char *lvalue,
452                 const char *rvalue,
453                 void *data,
454                 void *userdata) {
455
456         usec_t *usec = data;
457         int r;
458
459         assert(filename);
460         assert(lvalue);
461         assert(rvalue);
462         assert(data);
463
464         if ((r = parse_usec(rvalue, usec)) < 0) {
465                 log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
466                 return r;
467         }
468
469         return 0;
470 }
471
472 static DEFINE_CONFIG_PARSE_ENUM(config_parse_service_type, service_type, ServiceType, "Failed to parse service type");
473 static DEFINE_CONFIG_PARSE_ENUM(config_parse_service_restart, service_restart, ServiceRestart, "Failed to parse service restart specifier");
474
475 static int config_parse_bindtodevice(
476                 const char *filename,
477                 unsigned line,
478                 const char *section,
479                 const char *lvalue,
480                 const char *rvalue,
481                 void *data,
482                 void *userdata) {
483
484         Socket *s = data;
485         char *n;
486
487         assert(filename);
488         assert(lvalue);
489         assert(rvalue);
490         assert(data);
491
492         if (rvalue[0] && !streq(rvalue, "*")) {
493                 if (!(n = strdup(rvalue)))
494                         return -ENOMEM;
495         } else
496                 n = NULL;
497
498         free(s->bind_to_device);
499         s->bind_to_device = n;
500
501         return 0;
502 }
503
504 static DEFINE_CONFIG_PARSE_ENUM(config_parse_output, exec_output, ExecOutput, "Failed to parse output specifier");
505 static DEFINE_CONFIG_PARSE_ENUM(config_parse_input, exec_input, ExecInput, "Failed to parse input specifier");
506
507 static int config_parse_facility(
508                 const char *filename,
509                 unsigned line,
510                 const char *section,
511                 const char *lvalue,
512                 const char *rvalue,
513                 void *data,
514                 void *userdata) {
515
516
517         int *o = data, x;
518
519         assert(filename);
520         assert(lvalue);
521         assert(rvalue);
522         assert(data);
523
524         if ((x = log_facility_from_string(rvalue)) < 0) {
525                 log_error("[%s:%u] Failed to parse log facility: %s", filename, line, rvalue);
526                 return -EBADMSG;
527         }
528
529         *o = LOG_MAKEPRI(x, LOG_PRI(*o));
530
531         return 0;
532 }
533
534 static int config_parse_level(
535                 const char *filename,
536                 unsigned line,
537                 const char *section,
538                 const char *lvalue,
539                 const char *rvalue,
540                 void *data,
541                 void *userdata) {
542
543
544         int *o = data, x;
545
546         assert(filename);
547         assert(lvalue);
548         assert(rvalue);
549         assert(data);
550
551         if ((x = log_level_from_string(rvalue)) < 0) {
552                 log_error("[%s:%u] Failed to parse log level: %s", filename, line, rvalue);
553                 return -EBADMSG;
554         }
555
556         *o = LOG_MAKEPRI(LOG_FAC(*o), x);
557         return 0;
558 }
559
560 static int config_parse_io_class(
561                 const char *filename,
562                 unsigned line,
563                 const char *section,
564                 const char *lvalue,
565                 const char *rvalue,
566                 void *data,
567                 void *userdata) {
568
569         ExecContext *c = data;
570         int x;
571
572         assert(filename);
573         assert(lvalue);
574         assert(rvalue);
575         assert(data);
576
577         if ((x = ioprio_class_from_string(rvalue)) < 0) {
578                 log_error("[%s:%u] Failed to parse IO scheduling class: %s", filename, line, rvalue);
579                 return -EBADMSG;
580         }
581
582         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
583         c->ioprio_set = true;
584
585         return 0;
586 }
587
588 static int config_parse_io_priority(
589                 const char *filename,
590                 unsigned line,
591                 const char *section,
592                 const char *lvalue,
593                 const char *rvalue,
594                 void *data,
595                 void *userdata) {
596
597         ExecContext *c = data;
598         int i;
599
600         assert(filename);
601         assert(lvalue);
602         assert(rvalue);
603         assert(data);
604
605         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
606                 log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
607                 return -EBADMSG;
608         }
609
610         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
611         c->ioprio_set = true;
612
613         return 0;
614 }
615
616 static int config_parse_cpu_sched_policy(
617                 const char *filename,
618                 unsigned line,
619                 const char *section,
620                 const char *lvalue,
621                 const char *rvalue,
622                 void *data,
623                 void *userdata) {
624
625
626         ExecContext *c = data;
627         int x;
628
629         assert(filename);
630         assert(lvalue);
631         assert(rvalue);
632         assert(data);
633
634         if ((x = sched_policy_from_string(rvalue)) < 0) {
635                 log_error("[%s:%u] Failed to parse CPU scheduling policy: %s", filename, line, rvalue);
636                 return -EBADMSG;
637         }
638
639         c->cpu_sched_policy = x;
640         c->cpu_sched_set = true;
641
642         return 0;
643 }
644
645 static int config_parse_cpu_sched_prio(
646                 const char *filename,
647                 unsigned line,
648                 const char *section,
649                 const char *lvalue,
650                 const char *rvalue,
651                 void *data,
652                 void *userdata) {
653
654         ExecContext *c = data;
655         int i;
656
657         assert(filename);
658         assert(lvalue);
659         assert(rvalue);
660         assert(data);
661
662         /* On Linux RR/FIFO have the same range */
663         if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
664                 log_error("[%s:%u] Failed to parse CPU scheduling priority: %s", filename, line, rvalue);
665                 return -EBADMSG;
666         }
667
668         c->cpu_sched_priority = i;
669         c->cpu_sched_set = true;
670
671         return 0;
672 }
673
674 static int config_parse_cpu_affinity(
675                 const char *filename,
676                 unsigned line,
677                 const char *section,
678                 const char *lvalue,
679                 const char *rvalue,
680                 void *data,
681                 void *userdata) {
682
683         ExecContext *c = data;
684         char *w;
685         size_t l;
686         char *state;
687
688         assert(filename);
689         assert(lvalue);
690         assert(rvalue);
691         assert(data);
692
693         FOREACH_WORD(w, l, rvalue, state) {
694                 char *t;
695                 int r;
696                 unsigned cpu;
697
698                 if (!(t = strndup(w, l)))
699                         return -ENOMEM;
700
701                 r = safe_atou(t, &cpu);
702                 free(t);
703
704                 if (!(c->cpuset))
705                         if (!(c->cpuset = cpu_set_malloc(&c->cpuset_ncpus)))
706                                 return -ENOMEM;
707
708                 if (r < 0 || cpu >= c->cpuset_ncpus) {
709                         log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
710                         return -EBADMSG;
711                 }
712
713                 CPU_SET_S(cpu, CPU_ALLOC_SIZE(c->cpuset_ncpus), c->cpuset);
714         }
715
716         return 0;
717 }
718
719 static int config_parse_capabilities(
720                 const char *filename,
721                 unsigned line,
722                 const char *section,
723                 const char *lvalue,
724                 const char *rvalue,
725                 void *data,
726                 void *userdata) {
727
728         ExecContext *c = data;
729         cap_t cap;
730
731         assert(filename);
732         assert(lvalue);
733         assert(rvalue);
734         assert(data);
735
736         if (!(cap = cap_from_text(rvalue))) {
737                 if (errno == ENOMEM)
738                         return -ENOMEM;
739
740                 log_error("[%s:%u] Failed to parse capabilities: %s", filename, line, rvalue);
741                 return -EBADMSG;
742         }
743
744         if (c->capabilities)
745                 cap_free(c->capabilities);
746         c->capabilities = cap;
747
748         return 0;
749 }
750
751 static int config_parse_secure_bits(
752                 const char *filename,
753                 unsigned line,
754                 const char *section,
755                 const char *lvalue,
756                 const char *rvalue,
757                 void *data,
758                 void *userdata) {
759
760         ExecContext *c = data;
761         char *w;
762         size_t l;
763         char *state;
764
765         assert(filename);
766         assert(lvalue);
767         assert(rvalue);
768         assert(data);
769
770         FOREACH_WORD(w, l, rvalue, state) {
771                 if (first_word(w, "keep-caps"))
772                         c->secure_bits |= SECURE_KEEP_CAPS;
773                 else if (first_word(w, "keep-caps-locked"))
774                         c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
775                 else if (first_word(w, "no-setuid-fixup"))
776                         c->secure_bits |= SECURE_NO_SETUID_FIXUP;
777                 else if (first_word(w, "no-setuid-fixup-locked"))
778                         c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
779                 else if (first_word(w, "noroot"))
780                         c->secure_bits |= SECURE_NOROOT;
781                 else if (first_word(w, "noroot-locked"))
782                         c->secure_bits |= SECURE_NOROOT_LOCKED;
783                 else {
784                         log_error("[%s:%u] Failed to parse secure bits: %s", filename, line, rvalue);
785                         return -EBADMSG;
786                 }
787         }
788
789         return 0;
790 }
791
792 static int config_parse_bounding_set(
793                 const char *filename,
794                 unsigned line,
795                 const char *section,
796                 const char *lvalue,
797                 const char *rvalue,
798                 void *data,
799                 void *userdata) {
800
801         ExecContext *c = data;
802         char *w;
803         size_t l;
804         char *state;
805
806         assert(filename);
807         assert(lvalue);
808         assert(rvalue);
809         assert(data);
810
811         FOREACH_WORD(w, l, rvalue, state) {
812                 char *t;
813                 int r;
814                 cap_value_t cap;
815
816                 if (!(t = strndup(w, l)))
817                         return -ENOMEM;
818
819                 r = cap_from_name(t, &cap);
820                 free(t);
821
822                 if (r < 0) {
823                         log_error("[%s:%u] Failed to parse capability bounding set: %s", filename, line, rvalue);
824                         return -EBADMSG;
825                 }
826
827                 c->capability_bounding_set_drop |= 1 << cap;
828         }
829
830         return 0;
831 }
832
833 static int config_parse_timer_slack_nsec(
834                 const char *filename,
835                 unsigned line,
836                 const char *section,
837                 const char *lvalue,
838                 const char *rvalue,
839                 void *data,
840                 void *userdata) {
841
842         ExecContext *c = data;
843         unsigned long u;
844         int r;
845
846         assert(filename);
847         assert(lvalue);
848         assert(rvalue);
849         assert(data);
850
851         if ((r = safe_atolu(rvalue, &u)) < 0) {
852                 log_error("[%s:%u] Failed to parse time slack value: %s", filename, line, rvalue);
853                 return r;
854         }
855
856         c->timer_slack_nsec = u;
857
858         return 0;
859 }
860
861 static int config_parse_limit(
862                 const char *filename,
863                 unsigned line,
864                 const char *section,
865                 const char *lvalue,
866                 const char *rvalue,
867                 void *data,
868                 void *userdata) {
869
870         struct rlimit **rl = data;
871         unsigned long long u;
872         int r;
873
874         assert(filename);
875         assert(lvalue);
876         assert(rvalue);
877         assert(data);
878
879         if ((r = safe_atollu(rvalue, &u)) < 0) {
880                 log_error("[%s:%u] Failed to parse resource value: %s", filename, line, rvalue);
881                 return r;
882         }
883
884         if (!*rl)
885                 if (!(*rl = new(struct rlimit, 1)))
886                         return -ENOMEM;
887
888         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
889         return 0;
890 }
891
892 static int config_parse_cgroup(
893                 const char *filename,
894                 unsigned line,
895                 const char *section,
896                 const char *lvalue,
897                 const char *rvalue,
898                 void *data,
899                 void *userdata) {
900
901         Unit *u = userdata;
902         char *w;
903         size_t l;
904         char *state;
905
906         FOREACH_WORD(w, l, rvalue, state) {
907                 char *t;
908                 int r;
909
910                 if (!(t = strndup(w, l)))
911                         return -ENOMEM;
912
913                 r = unit_add_cgroup_from_text(u, t);
914                 free(t);
915
916                 if (r < 0)
917                         return r;
918         }
919
920         return 0;
921 }
922
923 static int config_parse_sysv_priority(
924                 const char *filename,
925                 unsigned line,
926                 const char *section,
927                 const char *lvalue,
928                 const char *rvalue,
929                 void *data,
930                 void *userdata) {
931
932         int *priority = data;
933         int r, i;
934
935         assert(filename);
936         assert(lvalue);
937         assert(rvalue);
938         assert(data);
939
940         if ((r = safe_atoi(rvalue, &i)) < 0 || i < 0) {
941                 log_error("[%s:%u] Failed to parse SysV start priority: %s", filename, line, rvalue);
942                 return r;
943         }
944
945         *priority = (int) i;
946         return 0;
947 }
948
949 static DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode");
950
951 static int config_parse_mount_flags(
952                 const char *filename,
953                 unsigned line,
954                 const char *section,
955                 const char *lvalue,
956                 const char *rvalue,
957                 void *data,
958                 void *userdata) {
959
960         ExecContext *c = data;
961         char *w;
962         size_t l;
963         char *state;
964         unsigned long flags = 0;
965
966         assert(filename);
967         assert(lvalue);
968         assert(rvalue);
969         assert(data);
970
971         FOREACH_WORD(w, l, rvalue, state) {
972                 if (strncmp(w, "shared", l) == 0)
973                         flags |= MS_SHARED;
974                 else if (strncmp(w, "slave", l) == 0)
975                         flags |= MS_SLAVE;
976                 else if (strncmp(w, "private", l) == 0)
977                         flags |= MS_PRIVATE;
978                 else {
979                         log_error("[%s:%u] Failed to parse mount flags: %s", filename, line, rvalue);
980                         return -EINVAL;
981                 }
982         }
983
984         c->mount_flags = flags;
985         return 0;
986 }
987
988 static int config_parse_timer(
989                 const char *filename,
990                 unsigned line,
991                 const char *section,
992                 const char *lvalue,
993                 const char *rvalue,
994                 void *data,
995                 void *userdata) {
996
997         Timer *t = data;
998         usec_t u;
999         int r;
1000         TimerValue *v;
1001         TimerBase b;
1002
1003         assert(filename);
1004         assert(lvalue);
1005         assert(rvalue);
1006         assert(data);
1007
1008         if ((b = timer_base_from_string(lvalue)) < 0) {
1009                 log_error("[%s:%u] Failed to parse timer base: %s", filename, line, lvalue);
1010                 return -EINVAL;
1011         }
1012
1013         if ((r = parse_usec(rvalue, &u)) < 0) {
1014                 log_error("[%s:%u] Failed to parse timer value: %s", filename, line, rvalue);
1015                 return r;
1016         }
1017
1018         if (!(v = new0(TimerValue, 1)))
1019                 return -ENOMEM;
1020
1021         v->base = b;
1022         v->value = u;
1023
1024         LIST_PREPEND(TimerValue, value, t->values, v);
1025
1026         return 0;
1027 }
1028
1029 static int config_parse_timer_unit(
1030                 const char *filename,
1031                 unsigned line,
1032                 const char *section,
1033                 const char *lvalue,
1034                 const char *rvalue,
1035                 void *data,
1036                 void *userdata) {
1037
1038         Timer *t = data;
1039         int r;
1040
1041         if (endswith(rvalue, ".timer")) {
1042                 log_error("[%s:%u] Unit cannot be of type timer: %s", filename, line, rvalue);
1043                 return -EINVAL;
1044         }
1045
1046         if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, &t->unit)) < 0) {
1047                 log_error("[%s:%u] Failed to load unit: %s", filename, line, rvalue);
1048                 return r;
1049         }
1050
1051         return 0;
1052 }
1053
1054 static int config_parse_path_spec(
1055                 const char *filename,
1056                 unsigned line,
1057                 const char *section,
1058                 const char *lvalue,
1059                 const char *rvalue,
1060                 void *data,
1061                 void *userdata) {
1062
1063         Path *p = data;
1064         PathSpec *s;
1065         PathType b;
1066
1067         assert(filename);
1068         assert(lvalue);
1069         assert(rvalue);
1070         assert(data);
1071
1072         if ((b = path_type_from_string(lvalue)) < 0) {
1073                 log_error("[%s:%u] Failed to parse path type: %s", filename, line, lvalue);
1074                 return -EINVAL;
1075         }
1076
1077         if (!path_is_absolute(rvalue)) {
1078                 log_error("[%s:%u] Path is not absolute: %s", filename, line, rvalue);
1079                 return -EINVAL;
1080         }
1081
1082         if (!(s = new0(PathSpec, 1)))
1083                 return -ENOMEM;
1084
1085         if (!(s->path = strdup(rvalue))) {
1086                 free(s);
1087                 return -ENOMEM;
1088         }
1089
1090         path_kill_slashes(s->path);
1091
1092         s->type = b;
1093         s->inotify_fd = -1;
1094
1095         LIST_PREPEND(PathSpec, spec, p->specs, s);
1096
1097         return 0;
1098 }
1099
1100 static int config_parse_path_unit(
1101                 const char *filename,
1102                 unsigned line,
1103                 const char *section,
1104                 const char *lvalue,
1105                 const char *rvalue,
1106                 void *data,
1107                 void *userdata) {
1108
1109         Path *t = data;
1110         int r;
1111
1112         if (endswith(rvalue, ".path")) {
1113                 log_error("[%s:%u] Unit cannot be of type path: %s", filename, line, rvalue);
1114                 return -EINVAL;
1115         }
1116
1117         if ((r = manager_load_unit(t->meta.manager, rvalue, NULL, &t->unit)) < 0) {
1118                 log_error("[%s:%u] Failed to load unit: %s", filename, line, rvalue);
1119                 return r;
1120         }
1121
1122         return 0;
1123 }
1124
1125 static int config_parse_env_file(
1126                 const char *filename,
1127                 unsigned line,
1128                 const char *section,
1129                 const char *lvalue,
1130                 const char *rvalue,
1131                 void *data,
1132                 void *userdata) {
1133
1134         FILE *f;
1135         int r;
1136         char ***env = data;
1137
1138         assert(filename);
1139         assert(lvalue);
1140         assert(rvalue);
1141         assert(data);
1142
1143         if (!(f = fopen(rvalue, "re"))) {
1144                 log_error("[%s:%u] Failed to open environment file '%s': %m", filename, line, rvalue);
1145                 return -errno;
1146         }
1147
1148         while (!feof(f)) {
1149                 char l[LINE_MAX], *p;
1150                 char **t;
1151
1152                 if (!fgets(l, sizeof(l), f)) {
1153                         if (feof(f))
1154                                 break;
1155
1156                         r = -errno;
1157                         log_error("[%s:%u] Failed to read environment file '%s': %m", filename, line, rvalue);
1158                         goto finish;
1159                 }
1160
1161                 p = strstrip(l);
1162
1163                 if (!*p)
1164                         continue;
1165
1166                 if (strchr(COMMENTS, *p))
1167                         continue;
1168
1169                 t = strv_env_set(*env, p);
1170                 strv_free(*env);
1171                 *env = t;
1172         }
1173
1174         r = 0;
1175
1176 finish:
1177         if (f)
1178                 fclose(f);
1179
1180         return r;
1181 }
1182
1183 static int config_parse_ip_tos(
1184                 const char *filename,
1185                 unsigned line,
1186                 const char *section,
1187                 const char *lvalue,
1188                 const char *rvalue,
1189                 void *data,
1190                 void *userdata) {
1191
1192         int *ip_tos = data, x;
1193         int r;
1194
1195         assert(filename);
1196         assert(lvalue);
1197         assert(rvalue);
1198         assert(data);
1199
1200         if ((x = ip_tos_from_string(rvalue)) < 0)
1201                 if ((r = safe_atoi(rvalue, &x)) < 0) {
1202                         log_error("[%s:%u] Failed to parse IP TOS value: %s", filename, line, rvalue);
1203                         return r;
1204                 }
1205
1206         *ip_tos = x;
1207         return 0;
1208 }
1209
1210 static DEFINE_CONFIG_PARSE_ENUM(config_parse_notify_access, notify_access, NotifyAccess, "Failed to parse notify access specifier");
1211
1212 #define FOLLOW_MAX 8
1213
1214 static int open_follow(char **filename, FILE **_f, Set *names, char **_final) {
1215         unsigned c = 0;
1216         int fd, r;
1217         FILE *f;
1218         char *id = NULL;
1219
1220         assert(filename);
1221         assert(*filename);
1222         assert(_f);
1223         assert(names);
1224
1225         /* This will update the filename pointer if the loaded file is
1226          * reached by a symlink. The old string will be freed. */
1227
1228         for (;;) {
1229                 char *target, *name;
1230
1231                 if (c++ >= FOLLOW_MAX)
1232                         return -ELOOP;
1233
1234                 path_kill_slashes(*filename);
1235
1236                 /* Add the file name we are currently looking at to
1237                  * the names of this unit */
1238                 name = file_name_from_path(*filename);
1239                 if (!(id = set_get(names, name))) {
1240
1241                         if (!(id = strdup(name)))
1242                                 return -ENOMEM;
1243
1244                         if ((r = set_put(names, id)) < 0) {
1245                                 free(id);
1246                                 return r;
1247                         }
1248                 }
1249
1250                 /* Try to open the file name, but don't if its a symlink */
1251                 if ((fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0)
1252                         break;
1253
1254                 if (errno != ELOOP)
1255                         return -errno;
1256
1257                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
1258                 if ((r = readlink_and_make_absolute(*filename, &target)) < 0)
1259                         return r;
1260
1261                 free(*filename);
1262                 *filename = target;
1263         }
1264
1265         if (!(f = fdopen(fd, "r"))) {
1266                 r = -errno;
1267                 close_nointr_nofail(fd);
1268                 return r;
1269         }
1270
1271         *_f = f;
1272         *_final = id;
1273         return 0;
1274 }
1275
1276 static int merge_by_names(Unit **u, Set *names, const char *id) {
1277         char *k;
1278         int r;
1279
1280         assert(u);
1281         assert(*u);
1282         assert(names);
1283
1284         /* Let's try to add in all symlink names we found */
1285         while ((k = set_steal_first(names))) {
1286
1287                 /* First try to merge in the other name into our
1288                  * unit */
1289                 if ((r = unit_merge_by_name(*u, k)) < 0) {
1290                         Unit *other;
1291
1292                         /* Hmm, we couldn't merge the other unit into
1293                          * ours? Then let's try it the other way
1294                          * round */
1295
1296                         other = manager_get_unit((*u)->meta.manager, k);
1297                         free(k);
1298
1299                         if (other)
1300                                 if ((r = unit_merge(other, *u)) >= 0) {
1301                                         *u = other;
1302                                         return merge_by_names(u, names, NULL);
1303                                 }
1304
1305                         return r;
1306                 }
1307
1308                 if (id == k)
1309                         unit_choose_id(*u, id);
1310
1311                 free(k);
1312         }
1313
1314         return 0;
1315 }
1316
1317 static void dump_items(FILE *f, const ConfigItem *items) {
1318         const ConfigItem *i;
1319         const char *prev_section = NULL;
1320         bool not_first = false;
1321
1322         struct {
1323                 ConfigParserCallback callback;
1324                 const char *rvalue;
1325         } table[] = {
1326                 { config_parse_int,              "INTEGER" },
1327                 { config_parse_unsigned,         "UNSIGNED" },
1328                 { config_parse_size,             "SIZE" },
1329                 { config_parse_bool,             "BOOLEAN" },
1330                 { config_parse_string,           "STRING" },
1331                 { config_parse_path,             "PATH" },
1332                 { config_parse_strv,             "STRING [...]" },
1333                 { config_parse_nice,             "NICE" },
1334                 { config_parse_oom_adjust,       "OOMADJUST" },
1335                 { config_parse_io_class,         "IOCLASS" },
1336                 { config_parse_io_priority,      "IOPRIORITY" },
1337                 { config_parse_cpu_sched_policy, "CPUSCHEDPOLICY" },
1338                 { config_parse_cpu_sched_prio,   "CPUSCHEDPRIO" },
1339                 { config_parse_cpu_affinity,     "CPUAFFINITY" },
1340                 { config_parse_mode,             "MODE" },
1341                 { config_parse_env_file,         "FILE" },
1342                 { config_parse_output,           "OUTPUT" },
1343                 { config_parse_input,            "INPUT" },
1344                 { config_parse_facility,         "FACILITY" },
1345                 { config_parse_level,            "LEVEL" },
1346                 { config_parse_capabilities,     "CAPABILITIES" },
1347                 { config_parse_secure_bits,      "SECUREBITS" },
1348                 { config_parse_bounding_set,     "BOUNDINGSET" },
1349                 { config_parse_timer_slack_nsec, "TIMERSLACK" },
1350                 { config_parse_limit,            "LIMIT" },
1351                 { config_parse_cgroup,           "CGROUP [...]" },
1352                 { config_parse_deps,             "UNIT [...]" },
1353                 { config_parse_names,            "UNIT [...]" },
1354                 { config_parse_exec,             "PATH [ARGUMENT [...]]" },
1355                 { config_parse_service_type,     "SERVICETYPE" },
1356                 { config_parse_service_restart,  "SERVICERESTART" },
1357                 { config_parse_sysv_priority,    "SYSVPRIORITY" },
1358                 { config_parse_kill_mode,        "KILLMODE" },
1359                 { config_parse_listen,           "SOCKET [...]" },
1360                 { config_parse_socket_bind,      "SOCKETBIND" },
1361                 { config_parse_bindtodevice,     "NETWORKINTERFACE" },
1362                 { config_parse_usec,             "SECONDS" },
1363                 { config_parse_path_strv,        "PATH [...]" },
1364                 { config_parse_mount_flags,      "MOUNTFLAG [...]" },
1365                 { config_parse_string_printf,    "STRING" },
1366                 { config_parse_timer,            "TIMER" },
1367                 { config_parse_timer_unit,       "NAME" },
1368                 { config_parse_path_spec,        "PATH" },
1369                 { config_parse_path_unit,        "UNIT" },
1370                 { config_parse_notify_access,    "ACCESS" },
1371                 { config_parse_ip_tos,           "TOS" },
1372         };
1373
1374         assert(f);
1375         assert(items);
1376
1377         for (i = items; i->lvalue; i++) {
1378                 unsigned j;
1379                 const char *rvalue = "OTHER";
1380
1381                 if (!streq_ptr(i->section, prev_section)) {
1382                         if (!not_first)
1383                                 not_first = true;
1384                         else
1385                                 fputc('\n', f);
1386
1387                         fprintf(f, "[%s]\n", i->section);
1388                         prev_section = i->section;
1389                 }
1390
1391                 for (j = 0; j < ELEMENTSOF(table); j++)
1392                         if (i->parse == table[j].callback) {
1393                                 rvalue = table[j].rvalue;
1394                                 break;
1395                         }
1396
1397                 fprintf(f, "%s=%s\n", i->lvalue, rvalue);
1398         }
1399 }
1400
1401 static int load_from_path(Unit *u, const char *path) {
1402
1403         static const char* const section_table[_UNIT_TYPE_MAX] = {
1404                 [UNIT_SERVICE]   = "Service",
1405                 [UNIT_TIMER]     = "Timer",
1406                 [UNIT_SOCKET]    = "Socket",
1407                 [UNIT_TARGET]    = "Target",
1408                 [UNIT_DEVICE]    = "Device",
1409                 [UNIT_MOUNT]     = "Mount",
1410                 [UNIT_AUTOMOUNT] = "Automount",
1411                 [UNIT_SNAPSHOT]  = "Snapshot",
1412                 [UNIT_SWAP]      = "Swap",
1413                 [UNIT_PATH]      = "Path"
1414         };
1415
1416 #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
1417                 { "WorkingDirectory",       config_parse_path,            &(context).working_directory,                    section   }, \
1418                 { "RootDirectory",          config_parse_path,            &(context).root_directory,                       section   }, \
1419                 { "User",                   config_parse_string_printf,   &(context).user,                                 section   }, \
1420                 { "Group",                  config_parse_string_printf,   &(context).group,                                section   }, \
1421                 { "SupplementaryGroups",    config_parse_strv,            &(context).supplementary_groups,                 section   }, \
1422                 { "Nice",                   config_parse_nice,            &(context),                                      section   }, \
1423                 { "OOMAdjust",              config_parse_oom_adjust,      &(context),                                      section   }, \
1424                 { "IOSchedulingClass",      config_parse_io_class,        &(context),                                      section   }, \
1425                 { "IOSchedulingPriority",   config_parse_io_priority,     &(context),                                      section   }, \
1426                 { "CPUSchedulingPolicy",    config_parse_cpu_sched_policy,&(context),                                      section   }, \
1427                 { "CPUSchedulingPriority",  config_parse_cpu_sched_prio,  &(context),                                      section   }, \
1428                 { "CPUSchedulingResetOnFork", config_parse_bool,          &(context).cpu_sched_reset_on_fork,              section   }, \
1429                 { "CPUAffinity",            config_parse_cpu_affinity,    &(context),                                      section   }, \
1430                 { "UMask",                  config_parse_mode,            &(context).umask,                                section   }, \
1431                 { "Environment",            config_parse_strv,            &(context).environment,                          section   }, \
1432                 { "EnvironmentFile",        config_parse_env_file,        &(context).environment,                          section   }, \
1433                 { "StandardInput",          config_parse_input,           &(context).std_input,                            section   }, \
1434                 { "StandardOutput",         config_parse_output,          &(context).std_output,                           section   }, \
1435                 { "StandardError",          config_parse_output,          &(context).std_error,                            section   }, \
1436                 { "TTYPath",                config_parse_path,            &(context).tty_path,                             section   }, \
1437                 { "SyslogIdentifier",       config_parse_string_printf,   &(context).syslog_identifier,                    section   }, \
1438                 { "SyslogFacility",         config_parse_facility,        &(context).syslog_priority,                      section   }, \
1439                 { "SyslogLevel",            config_parse_level,           &(context).syslog_priority,                      section   }, \
1440                 { "SyslogLevelPrefix",      config_parse_bool,            &(context).syslog_level_prefix,                  section   }, \
1441                 { "Capabilities",           config_parse_capabilities,    &(context),                                      section   }, \
1442                 { "SecureBits",             config_parse_secure_bits,     &(context),                                      section   }, \
1443                 { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context),                                      section   }, \
1444                 { "TimerSlackNSec",         config_parse_timer_slack_nsec,&(context),                                      section   }, \
1445                 { "LimitCPU",               config_parse_limit,           &(context).rlimit[RLIMIT_CPU],                   section   }, \
1446                 { "LimitFSIZE",             config_parse_limit,           &(context).rlimit[RLIMIT_FSIZE],                 section   }, \
1447                 { "LimitDATA",              config_parse_limit,           &(context).rlimit[RLIMIT_DATA],                  section   }, \
1448                 { "LimitSTACK",             config_parse_limit,           &(context).rlimit[RLIMIT_STACK],                 section   }, \
1449                 { "LimitCORE",              config_parse_limit,           &(context).rlimit[RLIMIT_CORE],                  section   }, \
1450                 { "LimitRSS",               config_parse_limit,           &(context).rlimit[RLIMIT_RSS],                   section   }, \
1451                 { "LimitNOFILE",            config_parse_limit,           &(context).rlimit[RLIMIT_NOFILE],                section   }, \
1452                 { "LimitAS",                config_parse_limit,           &(context).rlimit[RLIMIT_AS],                    section   }, \
1453                 { "LimitNPROC",             config_parse_limit,           &(context).rlimit[RLIMIT_NPROC],                 section   }, \
1454                 { "LimitMEMLOCK",           config_parse_limit,           &(context).rlimit[RLIMIT_MEMLOCK],               section   }, \
1455                 { "LimitLOCKS",             config_parse_limit,           &(context).rlimit[RLIMIT_LOCKS],                 section   }, \
1456                 { "LimitSIGPENDING",        config_parse_limit,           &(context).rlimit[RLIMIT_SIGPENDING],            section   }, \
1457                 { "LimitMSGQUEUE",          config_parse_limit,           &(context).rlimit[RLIMIT_MSGQUEUE],              section   }, \
1458                 { "LimitNICE",              config_parse_limit,           &(context).rlimit[RLIMIT_NICE],                  section   }, \
1459                 { "LimitRTPRIO",            config_parse_limit,           &(context).rlimit[RLIMIT_RTPRIO],                section   }, \
1460                 { "LimitRTTIME",            config_parse_limit,           &(context).rlimit[RLIMIT_RTTIME],                section   }, \
1461                 { "ControlGroup",           config_parse_cgroup,          u,                                               section   }, \
1462                 { "ReadWriteDirectories",   config_parse_path_strv,       &(context).read_write_dirs,                      section   }, \
1463                 { "ReadOnlyDirectories",    config_parse_path_strv,       &(context).read_only_dirs,                       section   }, \
1464                 { "InaccessibleDirectories",config_parse_path_strv,       &(context).inaccessible_dirs,                    section   }, \
1465                 { "PrivateTmp",             config_parse_bool,            &(context).private_tmp,                          section   }, \
1466                 { "MountFlags",             config_parse_mount_flags,     &(context),                                      section   }, \
1467                 { "TCPWrapName",            config_parse_string_printf,   &(context).tcpwrap_name,                         section   }, \
1468                 { "PAMName",                config_parse_string_printf,   &(context).pam_name,                             section   }
1469
1470         const ConfigItem items[] = {
1471                 { "Names",                  config_parse_names,           u,                                               "Unit"    },
1472                 { "Description",            config_parse_string_printf,   &u->meta.description,                            "Unit"    },
1473                 { "Requires",               config_parse_deps,            UINT_TO_PTR(UNIT_REQUIRES),                      "Unit"    },
1474                 { "RequiresOverridable",    config_parse_deps,            UINT_TO_PTR(UNIT_REQUIRES_OVERRIDABLE),          "Unit"    },
1475                 { "Requisite",              config_parse_deps,            UINT_TO_PTR(UNIT_REQUISITE),                     "Unit"    },
1476                 { "RequisiteOverridable",   config_parse_deps,            UINT_TO_PTR(UNIT_REQUISITE_OVERRIDABLE),         "Unit"    },
1477                 { "Wants",                  config_parse_deps,            UINT_TO_PTR(UNIT_WANTS),                         "Unit"    },
1478                 { "Conflicts",              config_parse_deps,            UINT_TO_PTR(UNIT_CONFLICTS),                     "Unit"    },
1479                 { "Before",                 config_parse_deps,            UINT_TO_PTR(UNIT_BEFORE),                        "Unit"    },
1480                 { "After",                  config_parse_deps,            UINT_TO_PTR(UNIT_AFTER),                         "Unit"    },
1481                 { "RecursiveStop",          config_parse_bool,            &u->meta.recursive_stop,                         "Unit"    },
1482                 { "StopWhenUnneeded",       config_parse_bool,            &u->meta.stop_when_unneeded,                     "Unit"    },
1483                 { "OnlyByDependency",       config_parse_bool,            &u->meta.only_by_dependency,                     "Unit"    },
1484                 { "DefaultDependencies",    config_parse_bool,            &u->meta.default_dependencies,                   "Unit"    },
1485
1486                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },
1487                 { "ExecStartPre",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_PRE,  "Service" },
1488                 { "ExecStart",              config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START,      "Service" },
1489                 { "ExecStartPost",          config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
1490                 { "ExecReload",             config_parse_exec,            u->service.exec_command+SERVICE_EXEC_RELOAD,     "Service" },
1491                 { "ExecStop",               config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP,       "Service" },
1492                 { "ExecStopPost",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP_POST,  "Service" },
1493                 { "RestartSec",             config_parse_usec,            &u->service.restart_usec,                        "Service" },
1494                 { "TimeoutSec",             config_parse_usec,            &u->service.timeout_usec,                        "Service" },
1495                 { "Type",                   config_parse_service_type,    &u->service.type,                                "Service" },
1496                 { "Restart",                config_parse_service_restart, &u->service.restart,                             "Service" },
1497                 { "PermissionsStartOnly",   config_parse_bool,            &u->service.permissions_start_only,              "Service" },
1498                 { "RootDirectoryStartOnly", config_parse_bool,            &u->service.root_directory_start_only,           "Service" },
1499                 { "ValidNoProcess",         config_parse_bool,            &u->service.valid_no_process,                    "Service" },
1500                 { "SysVStartPriority",      config_parse_sysv_priority,   &u->service.sysv_start_priority,                 "Service" },
1501                 { "KillMode",               config_parse_kill_mode,       &u->service.kill_mode,                           "Service" },
1502                 { "NonBlocking",            config_parse_bool,            &u->service.exec_context.non_blocking,           "Service" },
1503                 { "BusName",                config_parse_string_printf,   &u->service.bus_name,                            "Service" },
1504                 { "NotifyAccess",           config_parse_notify_access,   &u->service.notify_access,                       "Service" },
1505                 EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
1506
1507                 { "ListenStream",           config_parse_listen,          &u->socket,                                      "Socket"  },
1508                 { "ListenDatagram",         config_parse_listen,          &u->socket,                                      "Socket"  },
1509                 { "ListenSequentialPacket", config_parse_listen,          &u->socket,                                      "Socket"  },
1510                 { "ListenFIFO",             config_parse_listen,          &u->socket,                                      "Socket"  },
1511                 { "BindIPv6Only",           config_parse_socket_bind,     &u->socket,                                      "Socket"  },
1512                 { "Backlog",                config_parse_unsigned,        &u->socket.backlog,                              "Socket"  },
1513                 { "BindToDevice",           config_parse_bindtodevice,    &u->socket,                                      "Socket"  },
1514                 { "ExecStartPre",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_PRE,    "Socket"  },
1515                 { "ExecStartPost",          config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_POST,   "Socket"  },
1516                 { "ExecStopPre",            config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_PRE,     "Socket"  },
1517                 { "ExecStopPost",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_POST,    "Socket"  },
1518                 { "TimeoutSec",             config_parse_usec,            &u->socket.timeout_usec,                         "Socket"  },
1519                 { "DirectoryMode",          config_parse_mode,            &u->socket.directory_mode,                       "Socket"  },
1520                 { "SocketMode",             config_parse_mode,            &u->socket.socket_mode,                          "Socket"  },
1521                 { "KillMode",               config_parse_kill_mode,       &u->socket.kill_mode,                            "Socket"  },
1522                 { "Accept",                 config_parse_bool,            &u->socket.accept,                               "Socket"  },
1523                 { "MaxConnections",         config_parse_unsigned,        &u->socket.max_connections,                      "Socket"  },
1524                 { "KeepAlive",              config_parse_bool,            &u->socket.keep_alive,                           "Socket"  },
1525                 { "Priority",               config_parse_int,             &u->socket.priority,                             "Socket"  },
1526                 { "ReceiveBuffer",          config_parse_size,            &u->socket.receive_buffer,                       "Socket"  },
1527                 { "SendBuffer",             config_parse_size,            &u->socket.send_buffer,                          "Socket"  },
1528                 { "IPTOS",                  config_parse_ip_tos,          &u->socket.ip_tos,                               "Socket"  },
1529                 { "IPTTL",                  config_parse_int,             &u->socket.ip_ttl,                               "Socket"  },
1530                 { "Mark",                   config_parse_int,             &u->socket.mark,                                 "Socket"  },
1531                 { "PipeSize",               config_parse_size,            &u->socket.pipe_size,                            "Socket"  },
1532                 { "FreeBind",               config_parse_bool,            &u->socket.free_bind,                            "Socket"  },
1533                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
1534
1535                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
1536                 { "Where",                  config_parse_path,            &u->mount.where,                                 "Mount"   },
1537                 { "Options",                config_parse_string,          &u->mount.parameters_fragment.options,           "Mount"   },
1538                 { "Type",                   config_parse_string,          &u->mount.parameters_fragment.fstype,            "Mount"   },
1539                 { "TimeoutSec",             config_parse_usec,            &u->mount.timeout_usec,                          "Mount"   },
1540                 { "KillMode",               config_parse_kill_mode,       &u->mount.kill_mode,                             "Mount"   },
1541                 { "DirectoryMode",          config_parse_mode,            &u->mount.directory_mode,                        "Mount"   },
1542                 EXEC_CONTEXT_CONFIG_ITEMS(u->mount.exec_context, "Mount"),
1543
1544                 { "Where",                  config_parse_path,            &u->automount.where,                             "Automount" },
1545                 { "DirectoryMode",          config_parse_mode,            &u->automount.directory_mode,                    "Automount" },
1546
1547                 { "What",                   config_parse_path,            &u->swap.parameters_fragment.what,               "Swap"    },
1548                 { "Priority",               config_parse_int,             &u->swap.parameters_fragment.priority,           "Swap"    },
1549
1550                 { "OnActiveSec",            config_parse_timer,           &u->timer,                                       "Timer"   },
1551                 { "OnBootSec",              config_parse_timer,           &u->timer,                                       "Timer"   },
1552                 { "OnStartupSec",           config_parse_timer,           &u->timer,                                       "Timer"   },
1553                 { "OnUnitActiveSec",        config_parse_timer,           &u->timer,                                       "Timer"   },
1554                 { "OnUnitInactiveSec",      config_parse_timer,           &u->timer,                                       "Timer"   },
1555                 { "Unit",                   config_parse_timer_unit,      &u->timer,                                       "Timer"   },
1556
1557                 { "PathExists",             config_parse_path_spec,       &u->path,                                        "Path"    },
1558                 { "PathChanged",            config_parse_path_spec,       &u->path,                                        "Path"    },
1559                 { "DirectoryNotEmpty",      config_parse_path_spec,       &u->path,                                        "Path"    },
1560                 { "Unit",                   config_parse_path_unit,       &u->path,                                        "Path"    },
1561
1562                 /* The [Install] section is ignored here. */
1563                 { "Alias",                  NULL,                         NULL,                                            "Install" },
1564                 { "WantedBy",               NULL,                         NULL,                                            "Install" },
1565                 { "Also",                   NULL,                         NULL,                                            "Install" },
1566
1567                 { NULL, NULL, NULL, NULL }
1568         };
1569
1570 #undef EXEC_CONTEXT_CONFIG_ITEMS
1571
1572         const char *sections[4];
1573         int r;
1574         Set *symlink_names;
1575         FILE *f = NULL;
1576         char *filename = NULL, *id = NULL;
1577         Unit *merged;
1578
1579         if (!u) {
1580                 /* Dirty dirty hack. */
1581                 dump_items((FILE*) path, items);
1582                 return 0;
1583         }
1584
1585         assert(u);
1586         assert(path);
1587
1588         sections[0] = "Unit";
1589         sections[1] = section_table[u->meta.type];
1590         sections[2] = "Install";
1591         sections[3] = NULL;
1592
1593         if (!(symlink_names = set_new(string_hash_func, string_compare_func)))
1594                 return -ENOMEM;
1595
1596         if (path_is_absolute(path)) {
1597
1598                 if (!(filename = strdup(path))) {
1599                         r = -ENOMEM;
1600                         goto finish;
1601                 }
1602
1603                 if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1604                         free(filename);
1605                         filename = NULL;
1606
1607                         if (r != -ENOENT)
1608                                 goto finish;
1609                 }
1610
1611         } else  {
1612                 char **p;
1613
1614                 STRV_FOREACH(p, u->meta.manager->lookup_paths.unit_path) {
1615
1616                         /* Instead of opening the path right away, we manually
1617                          * follow all symlinks and add their name to our unit
1618                          * name set while doing so */
1619                         if (!(filename = path_make_absolute(path, *p))) {
1620                                 r = -ENOMEM;
1621                                 goto finish;
1622                         }
1623
1624                         if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1625                                 char *sn;
1626
1627                                 free(filename);
1628                                 filename = NULL;
1629
1630                                 if (r != -ENOENT)
1631                                         goto finish;
1632
1633                                 /* Empty the symlink names for the next run */
1634                                 while ((sn = set_steal_first(symlink_names)))
1635                                         free(sn);
1636
1637                                 continue;
1638                         }
1639
1640                         break;
1641                 }
1642         }
1643
1644         if (!filename) {
1645                 r = 0;
1646                 goto finish;
1647         }
1648
1649         merged = u;
1650         if ((r = merge_by_names(&merged, symlink_names, id)) < 0)
1651                 goto finish;
1652
1653         if (merged != u) {
1654                 u->meta.load_state = UNIT_MERGED;
1655                 r = 0;
1656                 goto finish;
1657         }
1658
1659         /* Now, parse the file contents */
1660         if ((r = config_parse(filename, f, sections, items, false, u)) < 0)
1661                 goto finish;
1662
1663         free(u->meta.fragment_path);
1664         u->meta.fragment_path = filename;
1665         filename = NULL;
1666
1667         u->meta.load_state = UNIT_LOADED;
1668         r = 0;
1669
1670 finish:
1671         set_free_free(symlink_names);
1672         free(filename);
1673
1674         if (f)
1675                 fclose(f);
1676
1677         return r;
1678 }
1679
1680 int unit_load_fragment(Unit *u) {
1681         int r;
1682
1683         assert(u);
1684
1685         if (u->meta.fragment_path) {
1686
1687                 if ((r = load_from_path(u, u->meta.fragment_path)) < 0)
1688                         return r;
1689
1690         } else {
1691                 Iterator i;
1692                 const char *t;
1693
1694                 /* Try to find the unit under its id */
1695                 if ((r = load_from_path(u, u->meta.id)) < 0)
1696                         return r;
1697
1698                 /* Try to find an alias we can load this with */
1699                 if (u->meta.load_state == UNIT_STUB)
1700                         SET_FOREACH(t, u->meta.names, i) {
1701
1702                                 if (t == u->meta.id)
1703                                         continue;
1704
1705                                 if ((r = load_from_path(u, t)) < 0)
1706                                         return r;
1707
1708                                 if (u->meta.load_state != UNIT_STUB)
1709                                         break;
1710                         }
1711
1712                 /* Now, follow the same logic, but look for a template */
1713                 if (u->meta.load_state == UNIT_STUB && u->meta.instance) {
1714                         char *k;
1715
1716                         if (!(k = unit_name_template(u->meta.id)))
1717                                 return -ENOMEM;
1718
1719                         r = load_from_path(u, k);
1720                         free(k);
1721
1722                         if (r < 0)
1723                                 return r;
1724
1725                         if (u->meta.load_state == UNIT_STUB)
1726                                 SET_FOREACH(t, u->meta.names, i) {
1727
1728                                         if (t == u->meta.id)
1729                                                 continue;
1730
1731                                         if (!(k = unit_name_template(t)))
1732                                                 return -ENOMEM;
1733
1734                                         r = load_from_path(u, k);
1735                                         free(k);
1736
1737                                         if (r < 0)
1738                                                 return r;
1739
1740                                         if (u->meta.load_state != UNIT_STUB)
1741                                                 break;
1742                                 }
1743                 }
1744         }
1745
1746         return 0;
1747 }
1748
1749 void unit_dump_config_items(FILE *f) {
1750         /* OK, this wins a prize for extreme ugliness. */
1751
1752         load_from_path(NULL, (const void*) f);
1753 }