]> git.ipfire.org Git - thirdparty/systemd.git/blame - load-fragment.c
add simple event loop
[thirdparty/systemd.git] / load-fragment.c
CommitLineData
3efd4195
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
3#include <assert.h>
4#include <errno.h>
5#include <string.h>
6
7#include "name.h"
8#include "strv.h"
9#include "conf-parser.h"
10#include "load-fragment.h"
16354eff 11#include "log.h"
3efd4195 12
42f4e3c4 13static int config_parse_deps(
3efd4195
LP
14 const char *filename,
15 unsigned line,
16 const char *section,
17 const char *lvalue,
18 const char *rvalue,
19 void *data,
20 void *userdata) {
21
22 Set **set = data;
23 Name *name = userdata;
24 char *w;
25 size_t l;
26 char *state;
27
28 assert(filename);
29 assert(lvalue);
30 assert(rvalue);
31 assert(data);
32
33 FOREACH_WORD(w, &l, rvalue, state) {
34 char *t;
35 int r;
36 Name *other;
37
38 if (!(t = strndup(w, l)))
39 return -ENOMEM;
40
41 r = manager_load_name(name->meta.manager, t, &other);
42 free(t);
43
44 if (r < 0)
45 return r;
46
47 if (!*set)
48 if (!(*set = set_new(trivial_hash_func, trivial_compare_func)))
49 return -ENOMEM;
50
51 if ((r = set_put(*set, other)) < 0)
52 return r;
53 }
54
55 return 0;
56}
57
42f4e3c4 58static int config_parse_names(
87d1515d
LP
59 const char *filename,
60 unsigned line,
61 const char *section,
62 const char *lvalue,
63 const char *rvalue,
64 void *data,
65 void *userdata) {
66
67 Set **set = data;
68 Name *name = userdata;
69 char *w;
70 size_t l;
71 char *state;
72
73 assert(filename);
74 assert(lvalue);
75 assert(rvalue);
76 assert(data);
77
78 FOREACH_WORD(w, &l, rvalue, state) {
79 char *t;
80 int r;
81 Name *other;
82
83 if (!(t = strndup(w, l)))
84 return -ENOMEM;
85
86 other = manager_get_name(name->meta.manager, t);
87
88 if (other) {
89
90 if (other != name) {
91
5cb5a6ff 92 if (other->meta.load_state != NAME_STUB) {
87d1515d
LP
93 free(t);
94 return -EEXIST;
95 }
96
7fad411c 97 if ((r = name_merge(name, other)) < 0) {
87d1515d
LP
98 free(t);
99 return r;
100 }
101 }
102
103 } else {
104
105 if (!*set)
106 if (!(*set = set_new(trivial_hash_func, trivial_compare_func))) {
107 free(t);
108 return -ENOMEM;
109 }
110
111 if ((r = set_put(*set, t)) < 0) {
112 free(t);
113 return r;
114 }
11dd41ce
LP
115
116 t = NULL;
87d1515d
LP
117 }
118
119 free(t);
120 }
121
122 return 0;
123}
124
42f4e3c4
LP
125static int config_parse_listen(
126 const char *filename,
127 unsigned line,
128 const char *section,
129 const char *lvalue,
130 const char *rvalue,
131 void *data,
132 void *userdata) {
133
16354eff 134 int r;
542563ba
LP
135 SocketPort *p;
136 Socket *s;
16354eff 137
42f4e3c4
LP
138 assert(filename);
139 assert(lvalue);
140 assert(rvalue);
141 assert(data);
142
542563ba
LP
143 s = (Socket*) data;
144
145 if (!(p = new0(SocketPort, 1)))
146 return -ENOMEM;
147
148 if (streq(lvalue, "ListenFIFO")) {
149 p->type = SOCKET_FIFO;
150
151 if (!(p->path = strdup(rvalue))) {
152 free(p);
153 return -ENOMEM;
154 }
155 } else {
156 p->type = SOCKET_SOCKET;
157
158 if ((r = socket_address_parse(&p->address, rvalue)) < 0) {
159 log_error("[%s:%u] Failed to parse address value: %s", filename, line, rvalue);
160 free(p);
161 return r;
162 }
163
164 if (streq(lvalue, "ListenStream"))
165 p->address.type = SOCK_STREAM;
166 else if (streq(lvalue, "ListenDatagram"))
167 p->address.type = SOCK_DGRAM;
168 else {
169 assert(streq(lvalue, "ListenSequentialPacket"));
170 p->address.type = SOCK_SEQPACKET;
171 }
172
173 if (socket_address_family(&p->address) != AF_LOCAL && p->address.type == SOCK_SEQPACKET) {
174 free(p);
175 return -EPROTONOSUPPORT;
176 }
16354eff
LP
177 }
178
542563ba
LP
179 p->fd = -1;
180 LIST_PREPEND(SocketPort, s->ports, p);
181
16354eff 182 return 0;
42f4e3c4
LP
183}
184
542563ba 185static int config_parse_bind(
42f4e3c4
LP
186 const char *filename,
187 unsigned line,
188 const char *section,
189 const char *lvalue,
190 const char *rvalue,
191 void *data,
192 void *userdata) {
193
542563ba
LP
194 int r;
195 Socket *s;
42f4e3c4
LP
196
197 assert(filename);
198 assert(lvalue);
199 assert(rvalue);
200 assert(data);
201
542563ba
LP
202 s = (Socket*) data;
203
204 if ((r = parse_boolean(rvalue)) < 0) {
205 log_error("[%s:%u] Failed to parse bind IPv6 only value: %s", filename, line, rvalue);
206 return r;
16354eff 207 }
42f4e3c4 208
542563ba
LP
209 s->bind_ipv6_only = r ? SOCKET_ADDRESS_IPV6_ONLY : SOCKET_ADDRESS_BOTH;
210
42f4e3c4
LP
211 return 0;
212}
213
3efd4195
LP
214int name_load_fragment(Name *n) {
215
5cb5a6ff 216 static const char* const section_table[_NAME_TYPE_MAX] = {
42f4e3c4
LP
217 [NAME_SERVICE] = "Service",
218 [NAME_TIMER] = "Timer",
219 [NAME_SOCKET] = "Socket",
220 [NAME_MILESTONE] = "Milestone",
221 [NAME_DEVICE] = "Device",
222 [NAME_MOUNT] = "Mount",
223 [NAME_AUTOMOUNT] = "Automount",
224 [NAME_SNAPSHOT] = "Snapshot"
225 };
226
3efd4195 227 const ConfigItem items[] = {
542563ba
LP
228 { "Names", config_parse_names, &n->meta.names, "Meta" },
229 { "Description", config_parse_string, &n->meta.description, "Meta" },
230 { "Requires", config_parse_deps, n->meta.dependencies+NAME_REQUIRES, "Meta" },
231 { "SoftRequires", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUIRES, "Meta" },
232 { "Wants", config_parse_deps, n->meta.dependencies+NAME_WANTS, "Meta" },
233 { "Requisite", config_parse_deps, n->meta.dependencies+NAME_REQUISITE, "Meta" },
234 { "SoftRequisite", config_parse_deps, n->meta.dependencies+NAME_SOFT_REQUISITE, "Meta" },
235 { "Conflicts", config_parse_deps, n->meta.dependencies+NAME_CONFLICTS, "Meta" },
236 { "Before", config_parse_deps, n->meta.dependencies+NAME_BEFORE, "Meta" },
237 { "After", config_parse_deps, n->meta.dependencies+NAME_AFTER, "Meta" },
238 { "ListenStream", config_parse_listen, &n->socket, "Socket" },
239 { "ListenDatagram", config_parse_listen, &n->socket, "Socket" },
240 { "ListenSequentialPacket", config_parse_listen, &n->socket, "Socket" },
241 { "ListenFIFO", config_parse_listen, &n->socket, "Socket" },
242 { "BindIPv6Only", config_parse_bind, &n->socket, "Socket" },
243 { "Backlog", config_parse_unsigned, &n->socket.backlog, "Socket" },
3efd4195
LP
244 { NULL, NULL, NULL, NULL }
245 };
246
42f4e3c4
LP
247 const
248
87d1515d 249 char *t;
3efd4195 250 int r;
87d1515d 251 void *state;
42f4e3c4 252 const char *sections[3];
3efd4195
LP
253
254 assert(n);
5cb5a6ff 255 assert(n->meta.load_state == NAME_STUB);
3efd4195 256
42f4e3c4
LP
257 sections[0] = "Meta";
258 sections[1] = section_table[n->meta.type];
259 sections[2] = NULL;
260
87d1515d 261 SET_FOREACH(t, n->meta.names, state)
42f4e3c4 262 if ((r = config_parse(t, sections, items, n)) < 0)
3efd4195
LP
263 goto fail;
264
87d1515d 265 r = 0;
3efd4195
LP
266
267fail:
87d1515d 268 return r;
3efd4195 269}