chiark / gitweb /
9eb00531c94e27d217c5b594e363151e9733d06f
[elogind.git] / 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
31 #include "unit.h"
32 #include "strv.h"
33 #include "conf-parser.h"
34 #include "load-fragment.h"
35 #include "log.h"
36 #include "ioprio.h"
37 #include "securebits.h"
38 #include "missing.h"
39
40 static int config_parse_deps(
41                 const char *filename,
42                 unsigned line,
43                 const char *section,
44                 const char *lvalue,
45                 const char *rvalue,
46                 void *data,
47                 void *userdata) {
48
49         UnitDependency d = PTR_TO_UINT(data);
50         Unit *u = userdata;
51         char *w;
52         size_t l;
53         char *state;
54
55         assert(filename);
56         assert(lvalue);
57         assert(rvalue);
58
59         if (UNIT_VTABLE(u)->refuse_requires &&
60             (d == UNIT_REQUIRES ||
61              d == UNIT_SOFT_REQUIRES ||
62              d == UNIT_REQUISITE ||
63              d == UNIT_SOFT_REQUISITE)) {
64                     log_error("[%s:%u] Dependency of type %s not acceptable for this unit type.", filename, line, lvalue);
65                     return -EBADMSG;
66             }
67
68         FOREACH_WORD(w, l, rvalue, state) {
69                 char *t;
70                 int r;
71
72                 if (!(t = strndup(w, l)))
73                         return -ENOMEM;
74
75                 r = unit_add_dependency_by_name(u, d, t);
76                 free(t);
77
78                 if (r < 0)
79                         return r;
80         }
81
82         return 0;
83 }
84
85 static int config_parse_names(
86                 const char *filename,
87                 unsigned line,
88                 const char *section,
89                 const char *lvalue,
90                 const char *rvalue,
91                 void *data,
92                 void *userdata) {
93
94         Unit *u = userdata;
95         char *w;
96         size_t l;
97         char *state;
98
99         assert(filename);
100         assert(lvalue);
101         assert(rvalue);
102         assert(data);
103
104         FOREACH_WORD(w, l, rvalue, state) {
105                 char *t;
106                 int r;
107
108                 if (!(t = strndup(w, l)))
109                         return -ENOMEM;
110
111                 r = unit_merge_by_name(u, t);
112                 free(t);
113
114                 if (r < 0)
115                         return r;
116         }
117
118         return 0;
119 }
120
121 static int config_parse_listen(
122                 const char *filename,
123                 unsigned line,
124                 const char *section,
125                 const char *lvalue,
126                 const char *rvalue,
127                 void *data,
128                 void *userdata) {
129
130         int r;
131         SocketPort *p;
132         Socket *s;
133
134         assert(filename);
135         assert(lvalue);
136         assert(rvalue);
137         assert(data);
138
139         s = (Socket*) data;
140
141         if (!(p = new0(SocketPort, 1)))
142                 return -ENOMEM;
143
144         if (streq(lvalue, "ListenFIFO")) {
145                 p->type = SOCKET_FIFO;
146
147                 if (!(p->path = strdup(rvalue))) {
148                         free(p);
149                         return -ENOMEM;
150                 }
151         } else {
152                 p->type = SOCKET_SOCKET;
153
154                 if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
155                         log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
156                         free(p);
157                         return r;
158                 }
159
160                 if (streq(lvalue, "ListenStream"))
161                         p->address.type = SOCK_STREAM;
162                 else if (streq(lvalue, "ListenDatagram"))
163                         p->address.type = SOCK_DGRAM;
164                 else {
165                         assert(streq(lvalue, "ListenSequentialPacket"));
166                         p->address.type = SOCK_SEQPACKET;
167                 }
168
169                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
170                         free(p);
171                         return -EPROTONOSUPPORT;
172                 }
173         }
174
175         p->fd = -1;
176         LIST_PREPEND(SocketPort, port, s->ports, p);
177
178         return 0;
179 }
180
181 static int config_parse_socket_bind(
182                 const char *filename,
183                 unsigned line,
184                 const char *section,
185                 const char *lvalue,
186                 const char *rvalue,
187                 void *data,
188                 void *userdata) {
189
190         int r;
191         Socket *s;
192
193         assert(filename);
194         assert(lvalue);
195         assert(rvalue);
196         assert(data);
197
198         s = (Socket*) data;
199
200         if ((r = parse_boolean(rvalue)) < 0) {
201                 log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
202                 return r;
203         }
204
205         s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
206
207         return 0;
208 }
209
210 static int config_parse_nice(
211                 const char *filename,
212                 unsigned line,
213                 const char *section,
214                 const char *lvalue,
215                 const char *rvalue,
216                 void *data,
217                 void *userdata) {
218
219         ExecContext *c = data;
220         int priority, r;
221
222         assert(filename);
223         assert(lvalue);
224         assert(rvalue);
225         assert(data);
226
227         if ((r = safe_atoi(rvalue, &priority)) < 0) {
228                 log_error("[%s:%u] Failed to parse nice priority: %s", filename, line, rvalue);
229                 return r;
230         }
231
232         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
233                 log_error("[%s:%u] Nice priority out of range: %s", filename, line, rvalue);
234                 return -ERANGE;
235         }
236
237         c->nice = priority;
238         c->nice_set = false;
239
240         return 0;
241 }
242
243 static int config_parse_oom_adjust(
244                 const char *filename,
245                 unsigned line,
246                 const char *section,
247                 const char *lvalue,
248                 const char *rvalue,
249                 void *data,
250                 void *userdata) {
251
252         ExecContext *c = data;
253         int oa, r;
254
255         assert(filename);
256         assert(lvalue);
257         assert(rvalue);
258         assert(data);
259
260         if ((r = safe_atoi(rvalue, &oa)) < 0) {
261                 log_error("[%s:%u] Failed to parse OOM adjust value: %s", filename, line, rvalue);
262                 return r;
263         }
264
265         if (oa < OOM_DISABLE || oa > OOM_ADJUST_MAX) {
266                 log_error("[%s:%u] OOM adjust value out of range: %s", filename, line, rvalue);
267                 return -ERANGE;
268         }
269
270         c->oom_adjust = oa;
271         c->oom_adjust_set = true;
272
273         return 0;
274 }
275
276 static int config_parse_mode(
277                 const char *filename,
278                 unsigned line,
279                 const char *section,
280                 const char *lvalue,
281                 const char *rvalue,
282                 void *data,
283                 void *userdata) {
284
285         mode_t *m = data;
286         long l;
287         char *x = NULL;
288
289         assert(filename);
290         assert(lvalue);
291         assert(rvalue);
292         assert(data);
293
294         errno = 0;
295         l = strtol(rvalue, &x, 8);
296         if (!x || *x || errno) {
297                 log_error("[%s:%u] Failed to parse mode value: %s", filename, line, rvalue);
298                 return errno ? -errno : -EINVAL;
299         }
300
301         if (l < 0000 || l > 07777) {
302                 log_error("[%s:%u] mode value out of range: %s", filename, line, rvalue);
303                 return -ERANGE;
304         }
305
306         *m = (mode_t) l;
307         return 0;
308 }
309
310 static int config_parse_exec(
311                 const char *filename,
312                 unsigned line,
313                 const char *section,
314                 const char *lvalue,
315                 const char *rvalue,
316                 void *data,
317                 void *userdata) {
318
319         ExecCommand **e = data, *nce = NULL;
320         char **n;
321         char *w;
322         unsigned k;
323         size_t l;
324         char *state;
325
326         assert(filename);
327         assert(lvalue);
328         assert(rvalue);
329         assert(data);
330
331         k = 0;
332         FOREACH_WORD_QUOTED(w, l, rvalue, state)
333                 k++;
334
335         if (!(n = new(char*, k+1)))
336                 return -ENOMEM;
337
338         k = 0;
339         FOREACH_WORD_QUOTED(w, l, rvalue, state)
340                 if (!(n[k++] = strndup(w, l)))
341                         goto fail;
342
343         n[k] = NULL;
344
345         if (!n[0] || !path_is_absolute(n[0])) {
346                 log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
347                 strv_free(n);
348                 return -EINVAL;
349         }
350
351         if (!(nce = new0(ExecCommand, 1)))
352                 goto fail;
353
354         nce->argv = n;
355         if (!(nce->path = strdup(n[0])))
356                 goto fail;
357
358         exec_command_append_list(e, nce);
359
360         return 0;
361
362 fail:
363         for (; k > 0; k--)
364                 free(n[k-1]);
365         free(n);
366
367         free(nce);
368
369         return -ENOMEM;
370 }
371
372 static int config_parse_usec(
373                 const char *filename,
374                 unsigned line,
375                 const char *section,
376                 const char *lvalue,
377                 const char *rvalue,
378                 void *data,
379                 void *userdata) {
380
381         usec_t *usec = data;
382         unsigned long long u;
383         int r;
384
385         assert(filename);
386         assert(lvalue);
387         assert(rvalue);
388         assert(data);
389
390         if ((r = safe_atollu(rvalue, &u)) < 0) {
391                 log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
392                 return r;
393         }
394
395         /* We actually assume the user configures seconds. Later on we
396          * might choose to support suffixes for time values, to
397          * configure bigger or smaller units */
398
399         *usec = u * USEC_PER_SEC;
400
401         return 0;
402 }
403
404 static int config_parse_service_type(
405                 const char *filename,
406                 unsigned line,
407                 const char *section,
408                 const char *lvalue,
409                 const char *rvalue,
410                 void *data,
411                 void *userdata) {
412
413         Service *s = data;
414         ServiceType x;
415
416         assert(filename);
417         assert(lvalue);
418         assert(rvalue);
419         assert(data);
420
421         if ((x = service_type_from_string(rvalue)) < 0) {
422                 log_error("[%s:%u] Failed to parse service type: %s", filename, line, rvalue);
423                 return -EBADMSG;
424         }
425
426         s->type = x;
427
428         return 0;
429 }
430
431 static int config_parse_service_restart(
432                 const char *filename,
433                 unsigned line,
434                 const char *section,
435                 const char *lvalue,
436                 const char *rvalue,
437                 void *data,
438                 void *userdata) {
439
440         Service *s = data;
441         ServiceRestart x;
442
443         assert(filename);
444         assert(lvalue);
445         assert(rvalue);
446         assert(data);
447
448         if ((x = service_restart_from_string(rvalue)) < 0) {
449                 log_error("[%s:%u] Failed to parse service restart specifier: %s", filename, line, rvalue);
450                 return -EBADMSG;
451         }
452
453         s->restart = x;
454
455         return 0;
456 }
457
458 static int config_parse_bindtodevice(
459                 const char *filename,
460                 unsigned line,
461                 const char *section,
462                 const char *lvalue,
463                 const char *rvalue,
464                 void *data,
465                 void *userdata) {
466
467         Socket *s = data;
468         char *n;
469
470         assert(filename);
471         assert(lvalue);
472         assert(rvalue);
473         assert(data);
474
475         if (rvalue[0] && !streq(rvalue, "*")) {
476                 if (!(n = strdup(rvalue)))
477                         return -ENOMEM;
478         } else
479                 n = NULL;
480
481         free(s->bind_to_device);
482         s->bind_to_device = n;
483
484         return 0;
485 }
486
487 static int config_parse_output(
488                 const char *filename,
489                 unsigned line,
490                 const char *section,
491                 const char *lvalue,
492                 const char *rvalue,
493                 void *data,
494                 void *userdata) {
495
496         ExecOutput *o = data, x;
497
498         assert(filename);
499         assert(lvalue);
500         assert(rvalue);
501         assert(data);
502
503         if ((x = exec_output_from_string(rvalue)) < 0) {
504                 log_error("[%s:%u] Failed to parse output specifier: %s", filename, line, rvalue);
505                 return -EBADMSG;
506         }
507
508         *o = x;
509
510         return 0;
511 }
512
513 static int config_parse_input(
514                 const char *filename,
515                 unsigned line,
516                 const char *section,
517                 const char *lvalue,
518                 const char *rvalue,
519                 void *data,
520                 void *userdata) {
521
522         ExecInput *i = data, x;
523
524         assert(filename);
525         assert(lvalue);
526         assert(rvalue);
527         assert(data);
528
529         if ((x = exec_input_from_string(rvalue)) < 0) {
530                 log_error("[%s:%u] Failed to parse input specifier: %s", filename, line, rvalue);
531                 return -EBADMSG;
532         }
533
534         *i = x;
535
536         return 0;
537 }
538
539 static int config_parse_facility(
540                 const char *filename,
541                 unsigned line,
542                 const char *section,
543                 const char *lvalue,
544                 const char *rvalue,
545                 void *data,
546                 void *userdata) {
547
548
549         int *o = data, x;
550
551         assert(filename);
552         assert(lvalue);
553         assert(rvalue);
554         assert(data);
555
556         if ((x = log_facility_from_string(rvalue)) < 0)
557
558                 /* Second try, let's see if this is a number. */
559                 if (safe_atoi(rvalue, &x) < 0 || !log_facility_to_string(x)) {
560                         log_error("[%s:%u] Failed to parse log facility: %s", filename, line, rvalue);
561                         return -EBADMSG;
562                 }
563
564         *o = LOG_MAKEPRI(x, LOG_PRI(*o));
565
566         return 0;
567 }
568
569 static int config_parse_level(
570                 const char *filename,
571                 unsigned line,
572                 const char *section,
573                 const char *lvalue,
574                 const char *rvalue,
575                 void *data,
576                 void *userdata) {
577
578
579         int *o = data, x;
580
581         assert(filename);
582         assert(lvalue);
583         assert(rvalue);
584         assert(data);
585
586         if ((x = log_level_from_string(rvalue)) < 0)
587
588                 /* Second try, let's see if this is a number. */
589                 if (safe_atoi(rvalue, &x) < 0 || !log_level_to_string(x)) {
590                         log_error("[%s:%u] Failed to parse log level: %s", filename, line, rvalue);
591                         return -EBADMSG;
592                 }
593
594         *o = LOG_MAKEPRI(LOG_FAC(*o), x);
595         return 0;
596 }
597
598 static int config_parse_io_class(
599                 const char *filename,
600                 unsigned line,
601                 const char *section,
602                 const char *lvalue,
603                 const char *rvalue,
604                 void *data,
605                 void *userdata) {
606
607         ExecContext *c = data;
608         int x;
609
610         assert(filename);
611         assert(lvalue);
612         assert(rvalue);
613         assert(data);
614
615         if ((x = ioprio_class_from_string(rvalue)) < 0)
616
617                 /* Second try, let's see if this is a number. */
618                 if (safe_atoi(rvalue, &x) < 0 || !ioprio_class_to_string(x)) {
619                         log_error("[%s:%u] Failed to parse IO scheduling class: %s", filename, line, rvalue);
620                         return -EBADMSG;
621                 }
622
623         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
624         c->ioprio_set = true;
625
626         return 0;
627 }
628
629 static int config_parse_io_priority(
630                 const char *filename,
631                 unsigned line,
632                 const char *section,
633                 const char *lvalue,
634                 const char *rvalue,
635                 void *data,
636                 void *userdata) {
637
638         ExecContext *c = data;
639         int i;
640
641         assert(filename);
642         assert(lvalue);
643         assert(rvalue);
644         assert(data);
645
646         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
647                 log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
648                 return -EBADMSG;
649         }
650
651         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
652         c->ioprio_set = true;
653
654         return 0;
655 }
656
657 static int config_parse_cpu_sched_policy(
658                 const char *filename,
659                 unsigned line,
660                 const char *section,
661                 const char *lvalue,
662                 const char *rvalue,
663                 void *data,
664                 void *userdata) {
665
666
667         ExecContext *c = data;
668         int x;
669
670         assert(filename);
671         assert(lvalue);
672         assert(rvalue);
673         assert(data);
674
675         if ((x = sched_policy_from_string(rvalue)) < 0)
676
677                 /* Second try, let's see if this is a number. */
678                 if (safe_atoi(rvalue, &x) < 0 || !sched_policy_to_string(x)) {
679                         log_error("[%s:%u] Failed to parse CPU scheduling policy: %s", filename, line, rvalue);
680                         return -EBADMSG;
681                 }
682
683         c->cpu_sched_policy = x;
684         c->cpu_sched_set = true;
685
686         return 0;
687 }
688
689 static int config_parse_cpu_sched_prio(
690                 const char *filename,
691                 unsigned line,
692                 const char *section,
693                 const char *lvalue,
694                 const char *rvalue,
695                 void *data,
696                 void *userdata) {
697
698         ExecContext *c = data;
699         int i;
700
701         assert(filename);
702         assert(lvalue);
703         assert(rvalue);
704         assert(data);
705
706         /* On Linux RR/FIFO have the same range */
707         if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
708                 log_error("[%s:%u] Failed to parse CPU scheduling priority: %s", filename, line, rvalue);
709                 return -EBADMSG;
710         }
711
712         c->cpu_sched_priority = i;
713         c->cpu_sched_set = true;
714
715         return 0;
716 }
717
718 static int config_parse_cpu_affinity(
719                 const char *filename,
720                 unsigned line,
721                 const char *section,
722                 const char *lvalue,
723                 const char *rvalue,
724                 void *data,
725                 void *userdata) {
726
727         ExecContext *c = data;
728         char *w;
729         size_t l;
730         char *state;
731
732         assert(filename);
733         assert(lvalue);
734         assert(rvalue);
735         assert(data);
736
737         FOREACH_WORD(w, l, rvalue, state) {
738                 char *t;
739                 int r;
740                 unsigned cpu;
741
742                 if (!(t = strndup(w, l)))
743                         return -ENOMEM;
744
745                 r = safe_atou(t, &cpu);
746                 free(t);
747
748                 if (r < 0 || cpu >= CPU_SETSIZE) {
749                         log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
750                         return -EBADMSG;
751                 }
752
753                 CPU_SET(cpu, &c->cpu_affinity);
754         }
755
756         c->cpu_affinity_set = true;
757
758         return 0;
759 }
760
761 static int config_parse_capabilities(
762                 const char *filename,
763                 unsigned line,
764                 const char *section,
765                 const char *lvalue,
766                 const char *rvalue,
767                 void *data,
768                 void *userdata) {
769
770         ExecContext *c = data;
771         cap_t cap;
772
773         assert(filename);
774         assert(lvalue);
775         assert(rvalue);
776         assert(data);
777
778         if (!(cap = cap_from_text(rvalue))) {
779                 if (errno == ENOMEM)
780                         return -ENOMEM;
781
782                 log_error("[%s:%u] Failed to parse capabilities: %s", filename, line, rvalue);
783                 return -EBADMSG;
784         }
785
786         if (c->capabilities)
787                 cap_free(c->capabilities);
788         c->capabilities = cap;
789
790         return 0;
791 }
792
793 static int config_parse_secure_bits(
794                 const char *filename,
795                 unsigned line,
796                 const char *section,
797                 const char *lvalue,
798                 const char *rvalue,
799                 void *data,
800                 void *userdata) {
801
802         ExecContext *c = data;
803         char *w;
804         size_t l;
805         char *state;
806
807         assert(filename);
808         assert(lvalue);
809         assert(rvalue);
810         assert(data);
811
812         FOREACH_WORD(w, l, rvalue, state) {
813                 if (first_word(w, "keep-caps"))
814                         c->secure_bits |= SECURE_KEEP_CAPS;
815                 else if (first_word(w, "keep-caps-locked"))
816                         c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
817                 else if (first_word(w, "no-setuid-fixup"))
818                         c->secure_bits |= SECURE_NO_SETUID_FIXUP;
819                 else if (first_word(w, "no-setuid-fixup-locked"))
820                         c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
821                 else if (first_word(w, "noroot"))
822                         c->secure_bits |= SECURE_NOROOT;
823                 else if (first_word(w, "noroot-locked"))
824                         c->secure_bits |= SECURE_NOROOT_LOCKED;
825                 else {
826                         log_error("[%s:%u] Failed to parse secure bits: %s", filename, line, rvalue);
827                         return -EBADMSG;
828                 }
829         }
830
831         return 0;
832 }
833
834 static int config_parse_bounding_set(
835                 const char *filename,
836                 unsigned line,
837                 const char *section,
838                 const char *lvalue,
839                 const char *rvalue,
840                 void *data,
841                 void *userdata) {
842
843         ExecContext *c = data;
844         char *w;
845         size_t l;
846         char *state;
847
848         assert(filename);
849         assert(lvalue);
850         assert(rvalue);
851         assert(data);
852
853         FOREACH_WORD(w, l, rvalue, state) {
854                 char *t;
855                 int r;
856                 cap_value_t cap;
857
858                 if (!(t = strndup(w, l)))
859                         return -ENOMEM;
860
861                 r = cap_from_name(t, &cap);
862                 free(t);
863
864                 if (r < 0) {
865                         log_error("[%s:%u] Failed to parse capability bounding set: %s", filename, line, rvalue);
866                         return -EBADMSG;
867                 }
868
869                 c->capability_bounding_set_drop |= 1 << cap;
870         }
871
872         return 0;
873 }
874
875 static int config_parse_timer_slack_ns(
876                 const char *filename,
877                 unsigned line,
878                 const char *section,
879                 const char *lvalue,
880                 const char *rvalue,
881                 void *data,
882                 void *userdata) {
883
884         ExecContext *c = data;
885         unsigned long u;
886         int r;
887
888         assert(filename);
889         assert(lvalue);
890         assert(rvalue);
891         assert(data);
892
893         if ((r = safe_atolu(rvalue, &u)) < 0) {
894                 log_error("[%s:%u] Failed to parse time slack value: %s", filename, line, rvalue);
895                 return r;
896         }
897
898         c->timer_slack_ns = u;
899
900         return 0;
901 }
902
903 static int config_parse_limit(
904                 const char *filename,
905                 unsigned line,
906                 const char *section,
907                 const char *lvalue,
908                 const char *rvalue,
909                 void *data,
910                 void *userdata) {
911
912         struct rlimit **rl = data;
913         unsigned long long u;
914         int r;
915
916         assert(filename);
917         assert(lvalue);
918         assert(rvalue);
919         assert(data);
920
921         if ((r = safe_atollu(rvalue, &u)) < 0) {
922                 log_error("[%s:%u] Failed to parse resource value: %s", filename, line, rvalue);
923                 return r;
924         }
925
926         if (!*rl)
927                 if (!(*rl = new(struct rlimit, 1)))
928                         return -ENOMEM;
929
930         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
931         return 0;
932 }
933
934 static int config_parse_cgroup(
935                 const char *filename,
936                 unsigned line,
937                 const char *section,
938                 const char *lvalue,
939                 const char *rvalue,
940                 void *data,
941                 void *userdata) {
942
943         Unit *u = userdata;
944         char *w;
945         size_t l;
946         char *state;
947
948         FOREACH_WORD(w, l, rvalue, state) {
949                 char *t;
950                 int r;
951
952                 if (!(t = strndup(w, l)))
953                         return -ENOMEM;
954
955                 r = unit_add_cgroup_from_text(u, t);
956                 free(t);
957
958                 if (r < 0)
959                         return r;
960         }
961
962         return 0;
963 }
964
965 static int config_parse_sysv_priority(
966                 const char *filename,
967                 unsigned line,
968                 const char *section,
969                 const char *lvalue,
970                 const char *rvalue,
971                 void *data,
972                 void *userdata) {
973
974         int *priority = data;
975         int r, i;
976
977         assert(filename);
978         assert(lvalue);
979         assert(rvalue);
980         assert(data);
981
982         if ((r = safe_atoi(rvalue, &i)) < 0 || i < 0) {
983                 log_error("[%s:%u] Failed to parse SysV start priority: %s", filename, line, rvalue);
984                 return r;
985         }
986
987         *priority = (int) i;
988         return 0;
989 }
990
991 static int config_parse_kill_mode(
992                 const char *filename,
993                 unsigned line,
994                 const char *section,
995                 const char *lvalue,
996                 const char *rvalue,
997                 void *data,
998                 void *userdata) {
999
1000         KillMode *m = data, x;
1001
1002         assert(filename);
1003         assert(lvalue);
1004         assert(rvalue);
1005         assert(data);
1006
1007         if ((x = kill_mode_from_string(rvalue)) < 0) {
1008                 log_error("[%s:%u] Failed to parse kill mode specifier: %s", filename, line, rvalue);
1009                 return -EBADMSG;
1010         }
1011
1012         *m = x;
1013
1014         return 0;
1015 }
1016
1017 #define FOLLOW_MAX 8
1018
1019 static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
1020         unsigned c = 0;
1021         int fd, r;
1022         FILE *f;
1023         char *id = NULL;
1024
1025         assert(filename);
1026         assert(*filename);
1027         assert(_f);
1028         assert(names);
1029
1030         /* This will update the filename pointer if the loaded file is
1031          * reached by a symlink. The old string will be freed. */
1032
1033         for (;;) {
1034                 char *target, *k, *name;
1035
1036                 if (c++ >= FOLLOW_MAX)
1037                         return -ELOOP;
1038
1039                 path_kill_slashes(*filename);
1040
1041                 /* Add the file name we are currently looking at to
1042                  * the names of this unit */
1043                 name = file_name_from_path(*filename);
1044                 if (!(id = set_get(names, name))) {
1045
1046                         if (!(id = strdup(name)))
1047                                 return -ENOMEM;
1048
1049                         if ((r = set_put(names, id)) < 0) {
1050                                 free(id);
1051                                 return r;
1052                         }
1053                 }
1054
1055                 /* Try to open the file name, but don't if its a symlink */
1056                 if ((fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0)
1057                         break;
1058
1059                 if (errno != ELOOP)
1060                         return -errno;
1061
1062                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
1063                 if ((r = readlink_malloc(*filename, &target)) < 0)
1064                         return r;
1065
1066                 k = file_in_same_dir(*filename, target);
1067                 free(target);
1068
1069                 if (!k)
1070                         return -ENOMEM;
1071
1072                 free(*filename);
1073                 *filename = k;
1074         }
1075
1076         if (!(f = fdopen(fd, "r"))) {
1077                 r = -errno;
1078                 assert(close_nointr(fd) == 0);
1079                 return r;
1080         }
1081
1082         *_f = f;
1083         *_id = id;
1084         return 0;
1085 }
1086
1087 static int merge_by_names(Unit **u, Set *names, const char *id) {
1088         char *k;
1089         int r;
1090
1091         assert(u);
1092         assert(*u);
1093         assert(names);
1094
1095         /* Let's try to add in all symlink names we found */
1096         while ((k = set_steal_first(names))) {
1097
1098                 /* First try to merge in the other name into our
1099                  * unit */
1100                 if ((r = unit_merge_by_name(*u, k)) < 0) {
1101                         Unit *other;
1102
1103                         /* Hmm, we couldn't merge the other unit into
1104                          * ours? Then let's try it the other way
1105                          * round */
1106
1107                         other = manager_get_unit((*u)->meta.manager, k);
1108                         free(k);
1109
1110                         if (other)
1111                                 if ((r = unit_merge(other, *u)) >= 0) {
1112                                         *u = other;
1113                                         return merge_by_names(u, names, NULL);
1114                                 }
1115
1116                         return r;
1117                 }
1118
1119                 if (id == k)
1120                         unit_choose_id(*u, id);
1121
1122                 free(k);
1123         }
1124
1125         return 0;
1126 }
1127
1128 static void dump_items(FILE *f, const ConfigItem *items) {
1129         const ConfigItem *i;
1130         const char *prev_section = NULL;
1131         bool not_first = false;
1132
1133         struct {
1134                 ConfigParserCallback callback;
1135                 const char *rvalue;
1136         } table[] = {
1137                 { config_parse_int,              "INTEGER" },
1138                 { config_parse_unsigned,         "UNSIGNED" },
1139                 { config_parse_size,             "SIZE" },
1140                 { config_parse_bool,             "BOOLEAN" },
1141                 { config_parse_string,           "STRING" },
1142                 { config_parse_path,             "PATH" },
1143                 { config_parse_strv,             "STRING [...]" },
1144                 { config_parse_nice,             "NICE" },
1145                 { config_parse_oom_adjust,       "OOMADJUST" },
1146                 { config_parse_io_class,         "IOCLASS" },
1147                 { config_parse_io_priority,      "IOPRIORITY" },
1148                 { config_parse_cpu_sched_policy, "CPUSCHEDPOLICY" },
1149                 { config_parse_cpu_sched_prio,   "CPUSCHEDPRIO" },
1150                 { config_parse_cpu_affinity,     "CPUAFFINITY" },
1151                 { config_parse_mode,             "MODE" },
1152                 { config_parse_output,           "OUTPUT" },
1153                 { config_parse_input,            "INPUT" },
1154                 { config_parse_facility,         "FACILITY" },
1155                 { config_parse_level,            "LEVEL" },
1156                 { config_parse_capabilities,     "CAPABILITIES" },
1157                 { config_parse_secure_bits,      "SECUREBITS" },
1158                 { config_parse_bounding_set,     "BOUNDINGSET" },
1159                 { config_parse_timer_slack_ns,   "TIMERSLACK" },
1160                 { config_parse_limit,            "LIMIT" },
1161                 { config_parse_cgroup,           "CGROUP [...]" },
1162                 { config_parse_deps,             "UNIT [...]" },
1163                 { config_parse_names,            "UNIT [...]" },
1164                 { config_parse_exec,             "PATH [ARGUMENT [...]]" },
1165                 { config_parse_service_type,     "SERVICETYPE" },
1166                 { config_parse_service_restart,  "SERVICERESTART" },
1167                 { config_parse_sysv_priority,    "SYSVPRIORITY" },
1168                 { config_parse_kill_mode,        "KILLMODE" },
1169                 { config_parse_listen,           "SOCKET [...]" },
1170                 { config_parse_socket_bind,      "SOCKETBIND" },
1171                 { config_parse_bindtodevice,     "NETWORKINTERFACE" }
1172         };
1173
1174         assert(f);
1175         assert(items);
1176
1177         for (i = items; i->lvalue; i++) {
1178                 unsigned j;
1179                 const char *rvalue = "OTHER";
1180
1181                 if (!streq_ptr(i->section, prev_section)) {
1182                         if (!not_first)
1183                                 not_first = true;
1184                         else
1185                                 fputc('\n', f);
1186
1187                         fprintf(f, "[%s]\n", i->section);
1188                         prev_section = i->section;
1189                 }
1190
1191                 for (j = 0; j < ELEMENTSOF(table); j++)
1192                         if (i->parse == table[j].callback) {
1193                                 rvalue = table[j].rvalue;
1194                                 break;
1195                         }
1196
1197                 fprintf(f, "%s=%s\n", i->lvalue, rvalue);
1198         }
1199 }
1200
1201 static int load_from_path(Unit *u, const char *path) {
1202
1203         static const char* const section_table[_UNIT_TYPE_MAX] = {
1204                 [UNIT_SERVICE]   = "Service",
1205                 [UNIT_TIMER]     = "Timer",
1206                 [UNIT_SOCKET]    = "Socket",
1207                 [UNIT_TARGET]    = "Target",
1208                 [UNIT_DEVICE]    = "Device",
1209                 [UNIT_MOUNT]     = "Mount",
1210                 [UNIT_AUTOMOUNT] = "Automount",
1211                 [UNIT_SNAPSHOT]  = "Snapshot"
1212         };
1213
1214 #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
1215                 { "WorkingDirectory",       config_parse_path,            &(context).working_directory,                    section   }, \
1216                 { "RootDirectory",          config_parse_path,            &(context).root_directory,                       section   }, \
1217                 { "User",                   config_parse_string,          &(context).user,                                 section   }, \
1218                 { "Group",                  config_parse_string,          &(context).group,                                section   }, \
1219                 { "SupplementaryGroups",    config_parse_strv,            &(context).supplementary_groups,                 section   }, \
1220                 { "Nice",                   config_parse_nice,            &(context),                                      section   }, \
1221                 { "OOMAdjust",              config_parse_oom_adjust,      &(context),                                      section   }, \
1222                 { "IOSchedulingClass",      config_parse_io_class,        &(context),                                      section   }, \
1223                 { "IOSchedulingPriority",   config_parse_io_priority,     &(context),                                      section   }, \
1224                 { "CPUSchedulingPolicy",    config_parse_cpu_sched_policy,&(context),                                      section   }, \
1225                 { "CPUSchedulingPriority",  config_parse_cpu_sched_prio,  &(context),                                      section   }, \
1226                 { "CPUSchedulingResetOnFork", config_parse_bool,          &(context).cpu_sched_reset_on_fork,              section   }, \
1227                 { "CPUAffinity",            config_parse_cpu_affinity,    &(context),                                      section   }, \
1228                 { "UMask",                  config_parse_mode,            &(context).umask,                                section   }, \
1229                 { "Environment",            config_parse_strv,            &(context).environment,                          section   }, \
1230                 { "StandardInput",          config_parse_input,           &(context).std_input,                            section   }, \
1231                 { "StandardOutput",         config_parse_output,          &(context).std_output,                           section   }, \
1232                 { "StandardError",          config_parse_output,          &(context).std_output,                           section   }, \
1233                 { "TTYPath",                config_parse_path,            &(context).tty_path,                             section   }, \
1234                 { "SyslogIdentifier",       config_parse_string,          &(context).syslog_identifier,                    section   }, \
1235                 { "SyslogFacility",         config_parse_facility,        &(context).syslog_priority,                      section   }, \
1236                 { "SyslogLevel",            config_parse_level,           &(context).syslog_priority,                      section   }, \
1237                 { "Capabilities",           config_parse_capabilities,    &(context),                                      section   }, \
1238                 { "SecureBits",             config_parse_secure_bits,     &(context),                                      section   }, \
1239                 { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context),                                      section   }, \
1240                 { "TimerSlackNS",           config_parse_timer_slack_ns,  &(context),                                      section   }, \
1241                 { "LimitCPU",               config_parse_limit,           &(context).rlimit[RLIMIT_CPU],                   section   }, \
1242                 { "LimitFSIZE",             config_parse_limit,           &(context).rlimit[RLIMIT_FSIZE],                 section   }, \
1243                 { "LimitDATA",              config_parse_limit,           &(context).rlimit[RLIMIT_DATA],                  section   }, \
1244                 { "LimitSTACK",             config_parse_limit,           &(context).rlimit[RLIMIT_STACK],                 section   }, \
1245                 { "LimitCORE",              config_parse_limit,           &(context).rlimit[RLIMIT_CORE],                  section   }, \
1246                 { "LimitRSS",               config_parse_limit,           &(context).rlimit[RLIMIT_RSS],                   section   }, \
1247                 { "LimitNOFILE",            config_parse_limit,           &(context).rlimit[RLIMIT_NOFILE],                section   }, \
1248                 { "LimitAS",                config_parse_limit,           &(context).rlimit[RLIMIT_AS],                    section   }, \
1249                 { "LimitNPROC",             config_parse_limit,           &(context).rlimit[RLIMIT_NPROC],                 section   }, \
1250                 { "LimitMEMLOCK",           config_parse_limit,           &(context).rlimit[RLIMIT_MEMLOCK],               section   }, \
1251                 { "LimitLOCKS",             config_parse_limit,           &(context).rlimit[RLIMIT_LOCKS],                 section   }, \
1252                 { "LimitSIGPENDING",        config_parse_limit,           &(context).rlimit[RLIMIT_SIGPENDING],            section   }, \
1253                 { "LimitMSGQUEUE",          config_parse_limit,           &(context).rlimit[RLIMIT_MSGQUEUE],              section   }, \
1254                 { "LimitNICE",              config_parse_limit,           &(context).rlimit[RLIMIT_NICE],                  section   }, \
1255                 { "LimitRTPRIO",            config_parse_limit,           &(context).rlimit[RLIMIT_RTPRIO],                section   }, \
1256                 { "LimitRTTIME",            config_parse_limit,           &(context).rlimit[RLIMIT_RTTIME],                section   }, \
1257                 { "ControlGroup",           config_parse_cgroup,          u,                                               section   }
1258
1259         const ConfigItem items[] = {
1260                 { "Names",                  config_parse_names,           u,                                               "Meta"    },
1261                 { "Description",            config_parse_string,          &u->meta.description,                            "Meta"    },
1262                 { "Requires",               config_parse_deps,            UINT_TO_PTR(UNIT_REQUIRES),                      "Meta"    },
1263                 { "SoftRequires",           config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUIRES),                 "Meta"    },
1264                 { "Wants",                  config_parse_deps,            UINT_TO_PTR(UNIT_WANTS),                         "Meta"    },
1265                 { "Requisite",              config_parse_deps,            UINT_TO_PTR(UNIT_REQUISITE),                     "Meta"    },
1266                 { "SoftRequisite",          config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUISITE),                "Meta"    },
1267                 { "Conflicts",              config_parse_deps,            UINT_TO_PTR(UNIT_CONFLICTS),                     "Meta"    },
1268                 { "Before",                 config_parse_deps,            UINT_TO_PTR(UNIT_BEFORE),                        "Meta"    },
1269                 { "After",                  config_parse_deps,            UINT_TO_PTR(UNIT_AFTER),                         "Meta"    },
1270                 { "RecursiveStop",          config_parse_bool,            &u->meta.recursive_stop,                         "Meta"    },
1271                 { "StopWhenUnneeded",       config_parse_bool,            &u->meta.stop_when_unneeded,                     "Meta"    },
1272
1273                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },
1274                 { "ExecStartPre",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_PRE,  "Service" },
1275                 { "ExecStart",              config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START,      "Service" },
1276                 { "ExecStartPost",          config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
1277                 { "ExecReload",             config_parse_exec,            u->service.exec_command+SERVICE_EXEC_RELOAD,     "Service" },
1278                 { "ExecStop",               config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP,       "Service" },
1279                 { "ExecStopPost",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP_POST,  "Service" },
1280                 { "RestartSec",             config_parse_usec,            &u->service.restart_usec,                        "Service" },
1281                 { "TimeoutSec",             config_parse_usec,            &u->service.timeout_usec,                        "Service" },
1282                 { "Type",                   config_parse_service_type,    &u->service,                                     "Service" },
1283                 { "Restart",                config_parse_service_restart, &u->service,                                     "Service" },
1284                 { "PermissionsStartOnly",   config_parse_bool,            &u->service.permissions_start_only,              "Service" },
1285                 { "RootDirectoryStartOnly", config_parse_bool,            &u->service.root_directory_start_only,           "Service" },
1286                 { "ValidNoProcess",         config_parse_bool,            &u->service.valid_no_process,                    "Service" },
1287                 { "SysVStartPriority",      config_parse_sysv_priority,   &u->service.sysv_start_priority,                 "Service" },
1288                 { "KillMode",               config_parse_kill_mode,       &u->service.kill_mode,                           "Service" },
1289                 { "NonBlocking",            config_parse_bool,            &u->service.exec_context.non_blocking,           "Service" },
1290                 EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
1291
1292                 { "ListenStream",           config_parse_listen,          &u->socket,                                      "Socket"  },
1293                 { "ListenDatagram",         config_parse_listen,          &u->socket,                                      "Socket"  },
1294                 { "ListenSequentialPacket", config_parse_listen,          &u->socket,                                      "Socket"  },
1295                 { "ListenFIFO",             config_parse_listen,          &u->socket,                                      "Socket"  },
1296                 { "BindIPv6Only",           config_parse_socket_bind,     &u->socket,                                      "Socket"  },
1297                 { "Backlog",                config_parse_unsigned,        &u->socket.backlog,                              "Socket"  },
1298                 { "BindToDevice",           config_parse_bindtodevice,    &u->socket,                                      "Socket"  },
1299                 { "ExecStartPre",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_PRE,    "Socket"  },
1300                 { "ExecStartPost",          config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_POST,   "Socket"  },
1301                 { "ExecStopPre",            config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_PRE,     "Socket"  },
1302                 { "ExecStopPost",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_POST,    "Socket"  },
1303                 { "TimeoutSec",             config_parse_usec,            &u->socket.timeout_usec,                         "Socket"  },
1304                 { "DirectoryMode",          config_parse_mode,            &u->socket.directory_mode,                       "Socket"  },
1305                 { "SocketMode",             config_parse_mode,            &u->socket.socket_mode,                          "Socket"  },
1306                 { "KillMode",               config_parse_kill_mode,       &u->socket.kill_mode,                            "Socket"  },
1307                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
1308
1309                 { "What",                   config_parse_string,          &u->mount.parameters_fragment.what,              "Mount"   },
1310                 { "Where",                  config_parse_path,            &u->mount.where,                                 "Mount"   },
1311                 { "Options",                config_parse_string,          &u->mount.parameters_fragment.options,           "Mount"   },
1312                 { "Type",                   config_parse_string,          &u->mount.parameters_fragment.fstype,            "Mount"   },
1313                 { "TimeoutSec",             config_parse_usec,            &u->mount.timeout_usec,                          "Mount"   },
1314                 { "KillMode",               config_parse_kill_mode,       &u->mount.kill_mode,                             "Mount"   },
1315                 EXEC_CONTEXT_CONFIG_ITEMS(u->mount.exec_context, "Mount"),
1316
1317                 { NULL, NULL, NULL, NULL }
1318         };
1319
1320 #undef EXEC_CONTEXT_CONFIG_ITEMS
1321
1322         const char *sections[3];
1323         char *k;
1324         int r;
1325         Set *symlink_names;
1326         FILE *f = NULL;
1327         char *filename = NULL, *id = NULL;
1328         Unit *merged;
1329
1330         if (!u) {
1331                 /* Dirty dirty hack. */
1332                 dump_items((FILE*) path, items);
1333                 return 0;
1334         }
1335
1336         assert(u);
1337         assert(path);
1338
1339         sections[0] = "Meta";
1340         sections[1] = section_table[u->meta.type];
1341         sections[2] = NULL;
1342
1343         if (!(symlink_names = set_new(string_hash_func, string_compare_func)))
1344                 return -ENOMEM;
1345
1346         if (path_is_absolute(path)) {
1347
1348                 if (!(filename = strdup(path))) {
1349                         r = -ENOMEM;
1350                         goto finish;
1351                 }
1352
1353                 if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1354                         free(filename);
1355                         filename = NULL;
1356
1357                         if (r != -ENOENT)
1358                                 goto finish;
1359                 }
1360
1361         } else  {
1362                 char **p;
1363
1364                 STRV_FOREACH(p, u->meta.manager->unit_path) {
1365
1366                         /* Instead of opening the path right away, we manually
1367                          * follow all symlinks and add their name to our unit
1368                          * name set while doing so */
1369                         if (!(filename = path_make_absolute(path, *p))) {
1370                                 r = -ENOMEM;
1371                                 goto finish;
1372                         }
1373
1374                         if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1375                                 char *sn;
1376
1377                                 free(filename);
1378                                 filename = NULL;
1379
1380                                 if (r != -ENOENT)
1381                                         goto finish;
1382
1383                                 /* Empty the symlink names for the next run */
1384                                 while ((sn = set_steal_first(symlink_names)))
1385                                         free(sn);
1386
1387                                 continue;
1388                         }
1389
1390                         break;
1391                 }
1392         }
1393
1394         if (!filename) {
1395                 r = 0;
1396                 goto finish;
1397         }
1398
1399         merged = u;
1400         if ((r = merge_by_names(&merged, symlink_names, id)) < 0)
1401                 goto finish;
1402
1403         if (merged != u) {
1404                 u->meta.load_state = UNIT_MERGED;
1405                 r = 0;
1406                 goto finish;
1407         }
1408
1409         /* Now, parse the file contents */
1410         if ((r = config_parse(filename, f, sections, items, u)) < 0)
1411                 goto finish;
1412
1413         free(u->meta.fragment_path);
1414         u->meta.fragment_path = filename;
1415         filename = NULL;
1416
1417         u->meta.load_state = UNIT_LOADED;
1418         r = 0;
1419
1420 finish:
1421         while ((k = set_steal_first(symlink_names)))
1422                 free(k);
1423
1424         set_free(symlink_names);
1425         free(filename);
1426
1427         if (f)
1428                 fclose(f);
1429
1430         return r;
1431 }
1432
1433 int unit_load_fragment(Unit *u) {
1434         int r;
1435
1436         assert(u);
1437
1438         if (u->meta.fragment_path) {
1439
1440                 if ((r = load_from_path(u, u->meta.fragment_path)) < 0)
1441                         return r;
1442
1443         } else {
1444                 Iterator i;
1445                 const char *t;
1446
1447                 /* Try to find the unit under its id */
1448                 if ((t = unit_id(u)))
1449                         if ((r = load_from_path(u, t)) < 0)
1450                                 return r;
1451
1452                 /* Try to find an alias we can load this with */
1453                 if (u->meta.load_state == UNIT_STUB)
1454                         SET_FOREACH(t, u->meta.names, i) {
1455
1456                                 if (unit_id(u) == t)
1457                                         continue;
1458
1459                                 if ((r = load_from_path(u, t)) < 0)
1460                                         return r;
1461
1462                                 if (u->meta.load_state != UNIT_STUB)
1463                                         break;
1464                         }
1465         }
1466
1467         return 0;
1468 }
1469
1470 void unit_dump_config_items(FILE *f) {
1471         /* OK, this wins a prize for extreme ugliness. */
1472
1473         load_from_path(NULL, (const void*) f);
1474 }