chiark / gitweb /
4bb1ef0108d5371f76915e6c0c293befcfc029e9
[elogind.git] / load-fragment.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3 #include <linux/oom.h>
4 #include <assert.h>
5 #include <errno.h>
6 #include <string.h>
7 #include <unistd.h>
8 #include <fcntl.h>
9 #include <sched.h>
10 #include <sys/prctl.h>
11
12 #include "unit.h"
13 #include "strv.h"
14 #include "conf-parser.h"
15 #include "load-fragment.h"
16 #include "log.h"
17 #include "ioprio.h"
18 #include "securebits.h"
19 #include "missing.h"
20
21 static int config_parse_deps(
22                 const char *filename,
23                 unsigned line,
24                 const char *section,
25                 const char *lvalue,
26                 const char *rvalue,
27                 void *data,
28                 void *userdata) {
29
30         UnitDependency d = PTR_TO_UINT(data);
31         Unit *u = userdata;
32         char *w;
33         size_t l;
34         char *state;
35
36         assert(filename);
37         assert(lvalue);
38         assert(rvalue);
39
40         FOREACH_WORD(w, &l, rvalue, state) {
41                 char *t;
42                 int r;
43
44                 if (!(t = strndup(w, l)))
45                         return -ENOMEM;
46
47                 r = unit_add_dependency_by_name(u, d, t);
48                 free(t);
49
50                 if (r < 0)
51                         return r;
52         }
53
54         return 0;
55 }
56
57 static int config_parse_names(
58                 const char *filename,
59                 unsigned line,
60                 const char *section,
61                 const char *lvalue,
62                 const char *rvalue,
63                 void *data,
64                 void *userdata) {
65
66         Unit *u = userdata;
67         char *w;
68         size_t l;
69         char *state;
70
71         assert(filename);
72         assert(lvalue);
73         assert(rvalue);
74         assert(data);
75
76         FOREACH_WORD(w, &l, rvalue, state) {
77                 char *t;
78                 int r;
79                 Unit *other;
80
81                 if (!(t = strndup(w, l)))
82                         return -ENOMEM;
83
84                 other = manager_get_unit(u->meta.manager, t);
85
86                 if (other) {
87
88                         if (other != u) {
89
90                                 if (other->meta.load_state != UNIT_STUB) {
91                                         free(t);
92                                         return -EEXIST;
93                                 }
94
95                                 if ((r = unit_merge(u, other)) < 0) {
96                                         free(t);
97                                         return r;
98                                 }
99                         }
100
101                 } else {
102                         if ((r = unit_add_name(u, t)) < 0) {
103                                 free(t);
104                                 return r;
105                         }
106                 }
107
108                 free(t);
109         }
110
111         return 0;
112 }
113
114 static int config_parse_listen(
115                 const char *filename,
116                 unsigned line,
117                 const char *section,
118                 const char *lvalue,
119                 const char *rvalue,
120                 void *data,
121                 void *userdata) {
122
123         int r;
124         SocketPort *p;
125         Socket *s;
126
127         assert(filename);
128         assert(lvalue);
129         assert(rvalue);
130         assert(data);
131
132         s = (Socket*) data;
133
134         if (!(p = new0(SocketPort, 1)))
135                 return -ENOMEM;
136
137         if (streq(lvalue, "ListenFIFO")) {
138                 p->type = SOCKET_FIFO;
139
140                 if (!(p->path = strdup(rvalue))) {
141                         free(p);
142                         return -ENOMEM;
143                 }
144         } else {
145                 p->type = SOCKET_SOCKET;
146
147                 if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
148                         log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
149                         free(p);
150                         return r;
151                 }
152
153                 if (streq(lvalue, "ListenStream"))
154                         p->address.type = SOCK_STREAM;
155                 else if (streq(lvalue, "ListenDatagram"))
156                         p->address.type = SOCK_DGRAM;
157                 else {
158                         assert(streq(lvalue, "ListenSequentialPacket"));
159                         p->address.type = SOCK_SEQPACKET;
160                 }
161
162                 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
163                         free(p);
164                         return -EPROTONOSUPPORT;
165                 }
166         }
167
168         p->fd = -1;
169         LIST_PREPEND(SocketPort, port, s->ports, p);
170
171         return 0;
172 }
173
174 static int config_parse_socket_bind(
175                 const char *filename,
176                 unsigned line,
177                 const char *section,
178                 const char *lvalue,
179                 const char *rvalue,
180                 void *data,
181                 void *userdata) {
182
183         int r;
184         Socket *s;
185
186         assert(filename);
187         assert(lvalue);
188         assert(rvalue);
189         assert(data);
190
191         s = (Socket*) data;
192
193         if ((r = parse_boolean(rvalue)) < 0) {
194                 log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
195                 return r;
196         }
197
198         s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
199
200         return 0;
201 }
202
203 static int config_parse_nice(
204                 const char *filename,
205                 unsigned line,
206                 const char *section,
207                 const char *lvalue,
208                 const char *rvalue,
209                 void *data,
210                 void *userdata) {
211
212         ExecContext *c = data;
213         int priority, r;
214
215         assert(filename);
216         assert(lvalue);
217         assert(rvalue);
218         assert(data);
219
220         if ((r = safe_atoi(rvalue, &priority)) < 0) {
221                 log_error("[%s:%u] Failed to parse nice priority: %s", filename, line, rvalue);
222                 return r;
223         }
224
225         if (priority < PRIO_MIN || priority >= PRIO_MAX) {
226                 log_error("[%s:%u] Nice priority out of range: %s", filename, line, rvalue);
227                 return -ERANGE;
228         }
229
230         c->nice = priority;
231         c->nice_set = false;
232
233         return 0;
234 }
235
236 static int config_parse_oom_adjust(
237                 const char *filename,
238                 unsigned line,
239                 const char *section,
240                 const char *lvalue,
241                 const char *rvalue,
242                 void *data,
243                 void *userdata) {
244
245         ExecContext *c = data;
246         int oa, r;
247
248         assert(filename);
249         assert(lvalue);
250         assert(rvalue);
251         assert(data);
252
253         if ((r = safe_atoi(rvalue, &oa)) < 0) {
254                 log_error("[%s:%u] Failed to parse OOM adjust value: %s", filename, line, rvalue);
255                 return r;
256         }
257
258         if (oa < OOM_DISABLE || oa > OOM_ADJUST_MAX) {
259                 log_error("[%s:%u] OOM adjust value out of range: %s", filename, line, rvalue);
260                 return -ERANGE;
261         }
262
263         c->oom_adjust = oa;
264         c->oom_adjust_set = true;
265
266         return 0;
267 }
268
269 static int config_parse_umask(
270                 const char *filename,
271                 unsigned line,
272                 const char *section,
273                 const char *lvalue,
274                 const char *rvalue,
275                 void *data,
276                 void *userdata) {
277
278         mode_t *m = data;
279         long l;
280         char *x = NULL;
281
282         assert(filename);
283         assert(lvalue);
284         assert(rvalue);
285         assert(data);
286
287         errno = 0;
288         l = strtol(rvalue, &x, 8);
289         if (!x || *x || errno) {
290                 log_error("[%s:%u] Failed to parse umask value: %s", filename, line, rvalue);
291                 return errno ? -errno : -EINVAL;
292         }
293
294         if (l < 0000 || l > 0777) {
295                 log_error("[%s:%u] umask value out of range: %s", filename, line, rvalue);
296                 return -ERANGE;
297         }
298
299         *m = (mode_t) l;
300         return 0;
301 }
302
303 static int config_parse_exec(
304                 const char *filename,
305                 unsigned line,
306                 const char *section,
307                 const char *lvalue,
308                 const char *rvalue,
309                 void *data,
310                 void *userdata) {
311
312         ExecCommand **e = data, *ee, *nce = NULL;
313         char **n;
314         char *w;
315         unsigned k;
316         size_t l;
317         char *state;
318
319         assert(filename);
320         assert(lvalue);
321         assert(rvalue);
322         assert(data);
323
324         k = 0;
325         FOREACH_WORD_QUOTED(w, l, rvalue, state)
326                 k++;
327
328         if (!(n = new(char*, k+1)))
329                 return -ENOMEM;
330
331         k = 0;
332         FOREACH_WORD_QUOTED(w, l, rvalue, state)
333                 if (!(n[k++] = strndup(w, l)))
334                         goto fail;
335
336         n[k] = NULL;
337
338         if (!n[0] || !path_is_absolute(n[0])) {
339                 log_error("[%s:%u] Invalid executable path in command line: %s", filename, line, rvalue);
340                 strv_free(n);
341                 return -EINVAL;
342         }
343
344         if (!(nce = new0(ExecCommand, 1)))
345                 goto fail;
346
347         nce->argv = n;
348         if (!(nce->path = strdup(n[0])))
349                 goto fail;
350
351         if (*e) {
352                 /* It's kinda important that we keep the order here */
353                 LIST_FIND_TAIL(ExecCommand, command, *e, ee);
354                 LIST_INSERT_AFTER(ExecCommand, command, *e, ee, nce);
355         } else
356                 *e = nce;
357
358         return 0;
359
360 fail:
361         for (; k > 0; k--)
362                 free(n[k-1]);
363         free(n);
364
365         free(nce);
366
367         return -ENOMEM;
368 }
369
370 static int config_parse_usec(
371                 const char *filename,
372                 unsigned line,
373                 const char *section,
374                 const char *lvalue,
375                 const char *rvalue,
376                 void *data,
377                 void *userdata) {
378
379         usec_t *usec = data;
380         unsigned long long u;
381         int r;
382
383         assert(filename);
384         assert(lvalue);
385         assert(rvalue);
386         assert(data);
387
388         if ((r = safe_atollu(rvalue, &u)) < 0) {
389                 log_error("[%s:%u] Failed to parse time value: %s", filename, line, rvalue);
390                 return r;
391         }
392
393         /* We actually assume the user configures seconds. Later on we
394          * might choose to support suffixes for time values, to
395          * configure bigger or smaller units */
396
397         *usec = u * USEC_PER_SEC;
398
399         return 0;
400 }
401
402 static int config_parse_service_type(
403                 const char *filename,
404                 unsigned line,
405                 const char *section,
406                 const char *lvalue,
407                 const char *rvalue,
408                 void *data,
409                 void *userdata) {
410
411         Service *s = data;
412         ServiceType x;
413
414         assert(filename);
415         assert(lvalue);
416         assert(rvalue);
417         assert(data);
418
419         if ((x = service_type_from_string(rvalue)) < 0) {
420                 log_error("[%s:%u] Failed to parse service type: %s", filename, line, rvalue);
421                 return -EBADMSG;
422         }
423
424         s->type = x;
425
426         return 0;
427 }
428
429 static int config_parse_service_restart(
430                 const char *filename,
431                 unsigned line,
432                 const char *section,
433                 const char *lvalue,
434                 const char *rvalue,
435                 void *data,
436                 void *userdata) {
437
438         Service *s = data;
439         ServiceRestart x;
440
441         assert(filename);
442         assert(lvalue);
443         assert(rvalue);
444         assert(data);
445
446         if ((x = service_restart_from_string(rvalue)) < 0) {
447                 log_error("[%s:%u] Failed to parse service restart specifier: %s", filename, line, rvalue);
448                 return -EBADMSG;
449         }
450
451         s->restart = x;
452
453         return 0;
454 }
455
456 int config_parse_bindtodevice(
457                 const char *filename,
458                 unsigned line,
459                 const char *section,
460                 const char *lvalue,
461                 const char *rvalue,
462                 void *data,
463                 void *userdata) {
464
465         Socket *s = data;
466         char *n;
467
468         assert(filename);
469         assert(lvalue);
470         assert(rvalue);
471         assert(data);
472
473         if (rvalue[0] && !streq(rvalue, "*")) {
474                 if (!(n = strdup(rvalue)))
475                         return -ENOMEM;
476         } else
477                 n = NULL;
478
479         free(s->bind_to_device);
480         s->bind_to_device = n;
481
482         return 0;
483 }
484
485 int config_parse_output(
486                 const char *filename,
487                 unsigned line,
488                 const char *section,
489                 const char *lvalue,
490                 const char *rvalue,
491                 void *data,
492                 void *userdata) {
493
494         ExecOutput *o = data, x;
495
496         assert(filename);
497         assert(lvalue);
498         assert(rvalue);
499         assert(data);
500
501         if ((x = exec_output_from_string(rvalue)) < 0) {
502                 log_error("[%s:%u] Failed to parse output specifier: %s", filename, line, rvalue);
503                 return -EBADMSG;
504         }
505
506         *o = x;
507
508         return 0;
509 }
510
511 int config_parse_input(
512                 const char *filename,
513                 unsigned line,
514                 const char *section,
515                 const char *lvalue,
516                 const char *rvalue,
517                 void *data,
518                 void *userdata) {
519
520         ExecInput *i = data, x;
521
522         assert(filename);
523         assert(lvalue);
524         assert(rvalue);
525         assert(data);
526
527         if ((x = exec_input_from_string(rvalue)) < 0) {
528                 log_error("[%s:%u] Failed to parse input specifier: %s", filename, line, rvalue);
529                 return -EBADMSG;
530         }
531
532         *i = x;
533
534         return 0;
535 }
536
537 int config_parse_facility(
538                 const char *filename,
539                 unsigned line,
540                 const char *section,
541                 const char *lvalue,
542                 const char *rvalue,
543                 void *data,
544                 void *userdata) {
545
546
547         int *o = data, x;
548
549         assert(filename);
550         assert(lvalue);
551         assert(rvalue);
552         assert(data);
553
554         if ((x = log_facility_from_string(rvalue)) < 0)
555
556                 /* Second try, let's see if this is a number. */
557                 if (safe_atoi(rvalue, &x) < 0 || !log_facility_to_string(x)) {
558                         log_error("[%s:%u] Failed to parse log facility: %s", filename, line, rvalue);
559                         return -EBADMSG;
560                 }
561
562         *o = LOG_MAKEPRI(x, LOG_PRI(*o));
563
564         return 0;
565 }
566
567 int config_parse_level(
568                 const char *filename,
569                 unsigned line,
570                 const char *section,
571                 const char *lvalue,
572                 const char *rvalue,
573                 void *data,
574                 void *userdata) {
575
576
577         int *o = data, x;
578
579         assert(filename);
580         assert(lvalue);
581         assert(rvalue);
582         assert(data);
583
584         if ((x = log_level_from_string(rvalue)) < 0)
585
586                 /* Second try, let's see if this is a number. */
587                 if (safe_atoi(rvalue, &x) < 0 || !log_level_to_string(x)) {
588                         log_error("[%s:%u] Failed to parse log level: %s", filename, line, rvalue);
589                         return -EBADMSG;
590                 }
591
592         *o = LOG_MAKEPRI(LOG_FAC(*o), x);
593         return 0;
594 }
595
596 int config_parse_io_class(
597                 const char *filename,
598                 unsigned line,
599                 const char *section,
600                 const char *lvalue,
601                 const char *rvalue,
602                 void *data,
603                 void *userdata) {
604
605         ExecContext *c = data;
606         int x;
607
608         assert(filename);
609         assert(lvalue);
610         assert(rvalue);
611         assert(data);
612
613         if ((x = ioprio_class_from_string(rvalue)) < 0)
614
615                 /* Second try, let's see if this is a number. */
616                 if (safe_atoi(rvalue, &x) < 0 || !ioprio_class_to_string(x)) {
617                         log_error("[%s:%u] Failed to parse IO scheduling class: %s", filename, line, rvalue);
618                         return -EBADMSG;
619                 }
620
621         c->ioprio = IOPRIO_PRIO_VALUE(x, IOPRIO_PRIO_DATA(c->ioprio));
622         c->ioprio_set = true;
623
624         return 0;
625 }
626
627 int config_parse_io_priority(
628                 const char *filename,
629                 unsigned line,
630                 const char *section,
631                 const char *lvalue,
632                 const char *rvalue,
633                 void *data,
634                 void *userdata) {
635
636         ExecContext *c = data;
637         int i;
638
639         assert(filename);
640         assert(lvalue);
641         assert(rvalue);
642         assert(data);
643
644         if (safe_atoi(rvalue, &i) < 0 || i < 0 || i >= IOPRIO_BE_NR) {
645                 log_error("[%s:%u] Failed to parse io priority: %s", filename, line, rvalue);
646                 return -EBADMSG;
647         }
648
649         c->ioprio = IOPRIO_PRIO_VALUE(IOPRIO_PRIO_CLASS(c->ioprio), i);
650         c->ioprio_set = true;
651
652         return 0;
653 }
654
655 int config_parse_cpu_sched_policy(
656                 const char *filename,
657                 unsigned line,
658                 const char *section,
659                 const char *lvalue,
660                 const char *rvalue,
661                 void *data,
662                 void *userdata) {
663
664
665         ExecContext *c = data;
666         int x;
667
668         assert(filename);
669         assert(lvalue);
670         assert(rvalue);
671         assert(data);
672
673         if ((x = sched_policy_from_string(rvalue)) < 0)
674
675                 /* Second try, let's see if this is a number. */
676                 if (safe_atoi(rvalue, &x) < 0 || !sched_policy_to_string(x)) {
677                         log_error("[%s:%u] Failed to parse CPU scheduling policy: %s", filename, line, rvalue);
678                         return -EBADMSG;
679                 }
680
681         c->cpu_sched_policy = x;
682         c->cpu_sched_set = true;
683
684         return 0;
685 }
686
687 int config_parse_cpu_sched_prio(
688                 const char *filename,
689                 unsigned line,
690                 const char *section,
691                 const char *lvalue,
692                 const char *rvalue,
693                 void *data,
694                 void *userdata) {
695
696         ExecContext *c = data;
697         int i;
698
699         assert(filename);
700         assert(lvalue);
701         assert(rvalue);
702         assert(data);
703
704         /* On Linux RR/FIFO have the same range */
705         if (safe_atoi(rvalue, &i) < 0 || i < sched_get_priority_min(SCHED_RR) || i > sched_get_priority_max(SCHED_RR)) {
706                 log_error("[%s:%u] Failed to parse CPU scheduling priority: %s", filename, line, rvalue);
707                 return -EBADMSG;
708         }
709
710         c->cpu_sched_priority = i;
711         c->cpu_sched_set = true;
712
713         return 0;
714 }
715
716 int config_parse_cpu_affinity(
717                 const char *filename,
718                 unsigned line,
719                 const char *section,
720                 const char *lvalue,
721                 const char *rvalue,
722                 void *data,
723                 void *userdata) {
724
725         ExecContext *c = data;
726         char *w;
727         size_t l;
728         char *state;
729
730         assert(filename);
731         assert(lvalue);
732         assert(rvalue);
733         assert(data);
734
735         FOREACH_WORD(w, &l, rvalue, state) {
736                 char *t;
737                 int r;
738                 unsigned cpu;
739
740                 if (!(t = strndup(w, l)))
741                         return -ENOMEM;
742
743                 r = safe_atou(t, &cpu);
744                 free(t);
745
746                 if (r < 0 || cpu >= CPU_SETSIZE) {
747                         log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
748                         return -EBADMSG;
749                 }
750
751                 CPU_SET(cpu, &c->cpu_affinity);
752         }
753
754         c->cpu_affinity_set = true;
755
756         return 0;
757 }
758
759 int config_parse_capabilities(
760                 const char *filename,
761                 unsigned line,
762                 const char *section,
763                 const char *lvalue,
764                 const char *rvalue,
765                 void *data,
766                 void *userdata) {
767
768         ExecContext *c = data;
769         cap_t cap;
770
771         assert(filename);
772         assert(lvalue);
773         assert(rvalue);
774         assert(data);
775
776         if (!(cap = cap_from_text(rvalue))) {
777                 if (errno == ENOMEM)
778                         return -ENOMEM;
779
780                 log_error("[%s:%u] Failed to parse capabilities: %s", filename, line, rvalue);
781                 return -EBADMSG;
782         }
783
784         if (c->capabilities)
785                 cap_free(c->capabilities);
786         c->capabilities = cap;
787
788         return 0;
789 }
790
791 int config_parse_secure_bits(
792                 const char *filename,
793                 unsigned line,
794                 const char *section,
795                 const char *lvalue,
796                 const char *rvalue,
797                 void *data,
798                 void *userdata) {
799
800         ExecContext *c = data;
801         char *w;
802         size_t l;
803         char *state;
804
805         assert(filename);
806         assert(lvalue);
807         assert(rvalue);
808         assert(data);
809
810         FOREACH_WORD(w, &l, rvalue, state) {
811                 if (first_word(w, "keep-caps"))
812                         c->secure_bits |= SECURE_KEEP_CAPS;
813                 else if (first_word(w, "keep-caps-locked"))
814                         c->secure_bits |= SECURE_KEEP_CAPS_LOCKED;
815                 else if (first_word(w, "no-setuid-fixup"))
816                         c->secure_bits |= SECURE_NO_SETUID_FIXUP;
817                 else if (first_word(w, "no-setuid-fixup-locked"))
818                         c->secure_bits |= SECURE_NO_SETUID_FIXUP_LOCKED;
819                 else if (first_word(w, "noroot"))
820                         c->secure_bits |= SECURE_NOROOT;
821                 else if (first_word(w, "noroot-locked"))
822                         c->secure_bits |= SECURE_NOROOT_LOCKED;
823                 else {
824                         log_error("[%s:%u] Failed to parse secure bits: %s", filename, line, rvalue);
825                         return -EBADMSG;
826                 }
827         }
828
829         return 0;
830 }
831
832 int config_parse_bounding_set(
833                 const char *filename,
834                 unsigned line,
835                 const char *section,
836                 const char *lvalue,
837                 const char *rvalue,
838                 void *data,
839                 void *userdata) {
840
841         ExecContext *c = data;
842         char *w;
843         size_t l;
844         char *state;
845
846         assert(filename);
847         assert(lvalue);
848         assert(rvalue);
849         assert(data);
850
851         FOREACH_WORD(w, &l, rvalue, state) {
852                 char *t;
853                 int r;
854                 cap_value_t cap;
855
856                 if (!(t = strndup(w, l)))
857                         return -ENOMEM;
858
859                 r = cap_from_name(t, &cap);
860                 free(t);
861
862                 if (r < 0) {
863                         log_error("[%s:%u] Failed to parse capability bounding set: %s", filename, line, rvalue);
864                         return -EBADMSG;
865                 }
866
867                 c->capability_bounding_set_drop |= 1 << cap;
868         }
869
870         return 0;
871 }
872
873 static int config_parse_timer_slack_ns(
874                 const char *filename,
875                 unsigned line,
876                 const char *section,
877                 const char *lvalue,
878                 const char *rvalue,
879                 void *data,
880                 void *userdata) {
881
882         ExecContext *c = data;
883         unsigned long u;
884         int r;
885
886         assert(filename);
887         assert(lvalue);
888         assert(rvalue);
889         assert(data);
890
891         if ((r = safe_atolu(rvalue, &u)) < 0) {
892                 log_error("[%s:%u] Failed to parse time slack value: %s", filename, line, rvalue);
893                 return r;
894         }
895
896         c->timer_slack_ns = u;
897
898         return 0;
899 }
900
901 static int config_parse_limit(
902                 const char *filename,
903                 unsigned line,
904                 const char *section,
905                 const char *lvalue,
906                 const char *rvalue,
907                 void *data,
908                 void *userdata) {
909
910         struct rlimit **rl = data;
911         unsigned long long u;
912         int r;
913
914         assert(filename);
915         assert(lvalue);
916         assert(rvalue);
917         assert(data);
918
919         if ((r = safe_atollu(rvalue, &u)) < 0) {
920                 log_error("[%s:%u] Failed to parse resource value: %s", filename, line, rvalue);
921                 return r;
922         }
923
924         if (!*rl)
925                 if (!(*rl = new(struct rlimit, 1)))
926                         return -ENOMEM;
927
928         (*rl)->rlim_cur = (*rl)->rlim_max = (rlim_t) u;
929         return 0;
930 }
931
932 #define FOLLOW_MAX 8
933
934 static int open_follow(char **filename, FILE **_f, Set *names, char **_id) {
935         unsigned c = 0;
936         int fd, r;
937         FILE *f;
938         char *id = NULL;
939
940         assert(filename);
941         assert(*filename);
942         assert(_f);
943         assert(names);
944
945         /* This will update the filename pointer if the loaded file is
946          * reached by a symlink. The old string will be freed. */
947
948         for (;;) {
949                 char *target, *k, *name;
950
951                 if (c++ >= FOLLOW_MAX)
952                         return -ELOOP;
953
954                 path_kill_slashes(*filename);
955
956                 /* Add the file name we are currently looking at to
957                  * the names of this unit */
958                 name = file_name_from_path(*filename);
959                 if (!(id = set_get(names, name))) {
960
961                         if (!(id = strdup(name)))
962                                 return -ENOMEM;
963
964                         if ((r = set_put(names, id)) < 0) {
965                                 free(id);
966                                 return r;
967                         }
968                 }
969
970                 /* Try to open the file name, but don't if its a symlink */
971                 if ((fd = open(*filename, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW)) >= 0)
972                         break;
973
974                 if (errno != ELOOP)
975                         return -errno;
976
977                 /* Hmm, so this is a symlink. Let's read the name, and follow it manually */
978                 if ((r = readlink_malloc(*filename, &target)) < 0)
979                         return r;
980
981                 k = file_in_same_dir(*filename, target);
982                 free(target);
983
984                 if (!k)
985                         return -ENOMEM;
986
987                 free(*filename);
988                 *filename = k;
989         }
990
991         if (!(f = fdopen(fd, "r"))) {
992                 r = -errno;
993                 assert(close_nointr(fd) == 0);
994                 return r;
995         }
996
997         *_f = f;
998         *_id = id;
999         return 0;
1000 }
1001
1002 static int load_from_path(Unit *u, const char *path) {
1003
1004         static const char* const section_table[_UNIT_TYPE_MAX] = {
1005                 [UNIT_SERVICE]   = "Service",
1006                 [UNIT_TIMER]     = "Timer",
1007                 [UNIT_SOCKET]    = "Socket",
1008                 [UNIT_TARGET]    = "Target",
1009                 [UNIT_DEVICE]    = "Device",
1010                 [UNIT_MOUNT]     = "Mount",
1011                 [UNIT_AUTOMOUNT] = "Automount",
1012                 [UNIT_SNAPSHOT]  = "Snapshot"
1013         };
1014
1015 #define EXEC_CONTEXT_CONFIG_ITEMS(context, section) \
1016                 { "WorkingDirectory",       config_parse_path,            &(context).working_directory,                    section   }, \
1017                 { "RootDirectory",          config_parse_path,            &(context).root_directory,                       section   }, \
1018                 { "User",                   config_parse_string,          &(context).user,                                 section   }, \
1019                 { "Group",                  config_parse_string,          &(context).group,                                section   }, \
1020                 { "SupplementaryGroups",    config_parse_strv,            &(context).supplementary_groups,                 section   }, \
1021                 { "Nice",                   config_parse_nice,            &(context),                                      section   }, \
1022                 { "OOMAdjust",              config_parse_oom_adjust,      &(context),                                      section   }, \
1023                 { "IOSchedulingClass",      config_parse_io_class,        &(context),                                      section   }, \
1024                 { "IOSchedulingPriority",   config_parse_io_priority,     &(context),                                      section   }, \
1025                 { "CPUSchedulingPolicy",    config_parse_cpu_sched_policy,&(context),                                      section   }, \
1026                 { "CPUSchedulingPriority",  config_parse_cpu_sched_prio,  &(context),                                      section   }, \
1027                 { "CPUAffinity",            config_parse_cpu_affinity,    &(context),                                      section   }, \
1028                 { "UMask",                  config_parse_umask,           &(context).umask,                                section   }, \
1029                 { "Environment",            config_parse_strv,            &(context).environment,                          section   }, \
1030                 { "Output",                 config_parse_output,          &(context).output,                               section   }, \
1031                 { "Input",                  config_parse_input,           &(context).input,                                section   }, \
1032                 { "SyslogIdentifier",       config_parse_string,          &(context).syslog_identifier,                    section   }, \
1033                 { "SyslogFacility",         config_parse_facility,        &(context).syslog_priority,                      section   }, \
1034                 { "SyslogLevel",            config_parse_level,           &(context).syslog_priority,                      section   }, \
1035                 { "Capabilities",           config_parse_capabilities,    &(context),                                      section   }, \
1036                 { "SecureBits",             config_parse_secure_bits,     &(context),                                      section   }, \
1037                 { "CapabilityBoundingSetDrop", config_parse_bounding_set, &(context),                                      section   }, \
1038                 { "TimerSlackNS",           config_parse_timer_slack_ns,  &(context),                                      section   }, \
1039                 { "LimitCPU",               config_parse_limit,           &(context).rlimit[RLIMIT_CPU],                   section   }, \
1040                 { "LimitFSIZE",             config_parse_limit,           &(context).rlimit[RLIMIT_FSIZE],                 section   }, \
1041                 { "LimitDATA",              config_parse_limit,           &(context).rlimit[RLIMIT_DATA],                  section   }, \
1042                 { "LimitSTACK",             config_parse_limit,           &(context).rlimit[RLIMIT_STACK],                 section   }, \
1043                 { "LimitCORE",              config_parse_limit,           &(context).rlimit[RLIMIT_CORE],                  section   }, \
1044                 { "LimitRSS",               config_parse_limit,           &(context).rlimit[RLIMIT_RSS],                   section   }, \
1045                 { "LimitNOFILE",            config_parse_limit,           &(context).rlimit[RLIMIT_NOFILE],                section   }, \
1046                 { "LimitAS",                config_parse_limit,           &(context).rlimit[RLIMIT_AS],                    section   }, \
1047                 { "LimitNPROC",             config_parse_limit,           &(context).rlimit[RLIMIT_NPROC],                 section   }, \
1048                 { "LimitMEMLOCK",           config_parse_limit,           &(context).rlimit[RLIMIT_MEMLOCK],               section   }, \
1049                 { "LimitLOCKS",             config_parse_limit,           &(context).rlimit[RLIMIT_LOCKS],                 section   }, \
1050                 { "LimitSIGPENDING",        config_parse_limit,           &(context).rlimit[RLIMIT_SIGPENDING],            section   }, \
1051                 { "LimitMSGQUEUE",          config_parse_limit,           &(context).rlimit[RLIMIT_MSGQUEUE],              section   }, \
1052                 { "LimitNICE",              config_parse_limit,           &(context).rlimit[RLIMIT_NICE],                  section   }, \
1053                 { "LimitRTPRIO",            config_parse_limit,           &(context).rlimit[RLIMIT_RTPRIO],                section   }, \
1054                 { "LimitRTTIME",            config_parse_limit,           &(context).rlimit[RLIMIT_RTTIME],                section   }
1055
1056         const ConfigItem items[] = {
1057                 { "Names",                  config_parse_names,           u,                                               "Meta"    },
1058                 { "Description",            config_parse_string,          &u->meta.description,                            "Meta"    },
1059                 { "Requires",               config_parse_deps,            UINT_TO_PTR(UNIT_REQUIRES),                      "Meta"    },
1060                 { "SoftRequires",           config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUIRES),                 "Meta"    },
1061                 { "Wants",                  config_parse_deps,            UINT_TO_PTR(UNIT_WANTS),                         "Meta"    },
1062                 { "Requisite",              config_parse_deps,            UINT_TO_PTR(UNIT_REQUISITE),                     "Meta"    },
1063                 { "SoftRequisite",          config_parse_deps,            UINT_TO_PTR(UNIT_SOFT_REQUISITE),                "Meta"    },
1064                 { "Conflicts",              config_parse_deps,            UINT_TO_PTR(UNIT_CONFLICTS),                     "Meta"    },
1065                 { "Before",                 config_parse_deps,            UINT_TO_PTR(UNIT_BEFORE),                        "Meta"    },
1066                 { "After",                  config_parse_deps,            UINT_TO_PTR(UNIT_AFTER),                         "Meta"    },
1067                 { "RecursiveStop",          config_parse_bool,            &u->meta.recursive_stop,                         "Meta"    },
1068                 { "StopWhenUnneeded",       config_parse_bool,            &u->meta.stop_when_unneeded,                     "Meta"    },
1069
1070                 { "PIDFile",                config_parse_path,            &u->service.pid_file,                            "Service" },
1071                 { "ExecStartPre",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_PRE,  "Service" },
1072                 { "ExecStart",              config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START,      "Service" },
1073                 { "ExecStartPost",          config_parse_exec,            u->service.exec_command+SERVICE_EXEC_START_POST, "Service" },
1074                 { "ExecReload",             config_parse_exec,            u->service.exec_command+SERVICE_EXEC_RELOAD,     "Service" },
1075                 { "ExecStop",               config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP,       "Service" },
1076                 { "ExecStopPost",           config_parse_exec,            u->service.exec_command+SERVICE_EXEC_STOP_POST,  "Service" },
1077                 { "RestartSec",             config_parse_usec,            &u->service.restart_usec,                        "Service" },
1078                 { "TimeoutSec",             config_parse_usec,            &u->service.timeout_usec,                        "Service" },
1079                 { "Type",                   config_parse_service_type,    &u->service,                                     "Service" },
1080                 { "Restart",                config_parse_service_restart, &u->service,                                     "Service" },
1081                 EXEC_CONTEXT_CONFIG_ITEMS(u->service.exec_context, "Service"),
1082
1083                 { "ListenStream",           config_parse_listen,          &u->socket,                                      "Socket"  },
1084                 { "ListenDatagram",         config_parse_listen,          &u->socket,                                      "Socket"  },
1085                 { "ListenSequentialPacket", config_parse_listen,          &u->socket,                                      "Socket"  },
1086                 { "ListenFIFO",             config_parse_listen,          &u->socket,                                      "Socket"  },
1087                 { "BindIPv6Only",           config_parse_socket_bind,     &u->socket,                                      "Socket"  },
1088                 { "Backlog",                config_parse_unsigned,        &u->socket.backlog,                              "Socket"  },
1089                 { "BindToDevice",           config_parse_bindtodevice,    &u->socket,                                      "Socket"  },
1090                 { "ExecStartPre",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_PRE,    "Socket"  },
1091                 { "ExecStartPost",          config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_START_POST,   "Socket"  },
1092                 { "ExecStopPre",            config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_PRE,     "Socket"  },
1093                 { "ExecStopPost",           config_parse_exec,            u->socket.exec_command+SOCKET_EXEC_STOP_POST,    "Socket"  },
1094                 EXEC_CONTEXT_CONFIG_ITEMS(u->socket.exec_context, "Socket"),
1095
1096                 EXEC_CONTEXT_CONFIG_ITEMS(u->automount.exec_context, "Automount"),
1097
1098                 { NULL, NULL, NULL, NULL }
1099         };
1100
1101 #undef EXEC_CONTEXT_CONFIG_ITEMS
1102
1103         const char *sections[3];
1104         char *k;
1105         int r;
1106         Set *symlink_names;
1107         FILE *f;
1108         char *filename, *id;
1109
1110         sections[0] = "Meta";
1111         sections[1] = section_table[u->meta.type];
1112         sections[2] = NULL;
1113
1114         if (!(symlink_names = set_new(string_hash_func, string_compare_func)))
1115                 return -ENOMEM;
1116
1117         /* Instead of opening the path right away, we manually
1118          * follow all symlinks and add their name to our unit
1119          * name set while doing so */
1120         if (!(filename = path_make_absolute(path, unit_path()))) {
1121                 r = -ENOMEM;
1122                 goto finish;
1123         }
1124
1125         if ((r = open_follow(&filename, &f, symlink_names, &id)) < 0) {
1126                 if (r == -ENOENT)
1127                         r = 0; /* returning 0 means: no suitable config file found */
1128
1129                 goto finish;
1130         }
1131
1132         /* Now, parse the file contents */
1133         r = config_parse(filename, f, sections, items, u);
1134         if (r < 0)
1135                 goto finish;
1136
1137         /* Let's try to add in all symlink names we found */
1138         while ((k = set_steal_first(symlink_names))) {
1139                 if ((r = unit_add_name(u, k)) < 0)
1140                         goto finish;
1141
1142
1143                 if (id == k)
1144                         unit_choose_id(u, id);
1145                 free(k);
1146         }
1147
1148
1149         free(u->meta.load_path);
1150         u->meta.load_path = filename;
1151         filename = NULL;
1152
1153         r = 1; /* returning 1 means: suitable config file found and loaded */
1154
1155 finish:
1156         while ((k = set_steal_first(symlink_names)))
1157                 free(k);
1158         set_free(symlink_names);
1159         free(filename);
1160
1161         return r;
1162 }
1163
1164 int unit_load_fragment(Unit *u) {
1165         int r = 0;
1166         ExecContext *c;
1167
1168         assert(u);
1169         assert(u->meta.load_state == UNIT_STUB);
1170
1171         if (u->meta.load_path)
1172                 r = load_from_path(u, u->meta.load_path);
1173         else {
1174                 Iterator i;
1175                 char *t;
1176
1177                 /* Try to find a name we can load this with */
1178                 SET_FOREACH(t, u->meta.names, i)
1179                         if ((r = load_from_path(u, t)) != 0)
1180                                 return r;
1181         }
1182
1183         if (u->meta.type == UNIT_SOCKET)
1184                 c = &u->socket.exec_context;
1185         else if (u->meta.type == UNIT_SERVICE)
1186                 c = &u->service.exec_context;
1187         else
1188                 c = NULL;
1189
1190         if (r >= 0 && c &&
1191             (c->output == EXEC_OUTPUT_KERNEL || c->output == EXEC_OUTPUT_SYSLOG)) {
1192                 int k;
1193
1194                 /* If syslog or kernel logging is requested, make sure
1195                  * our own logging daemon is run first. */
1196
1197                 if ((k = unit_add_dependency_by_name(u, UNIT_AFTER, SPECIAL_LOGGER_SOCKET)) < 0)
1198                         return k;
1199
1200                 if ((k = unit_add_dependency_by_name(u, UNIT_REQUIRES, SPECIAL_LOGGER_SOCKET)) < 0)
1201                         return k;
1202         }
1203
1204         return r;
1205 }