]> git.ipfire.org Git - thirdparty/systemd.git/blame - conf-parser.c
main: add kernel option to enable confirm_spawn
[thirdparty/systemd.git] / conf-parser.c
CommitLineData
ed5bcfbe
LP
1/*-*- Mode: C; c-basic-offset: 8 -*-*/
2
a7334b09
LP
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
ed5bcfbe
LP
22#include <string.h>
23#include <stdio.h>
24#include <errno.h>
25#include <assert.h>
26#include <stdlib.h>
27
28#include "conf-parser.h"
29#include "util.h"
30#include "macro.h"
57d42a5f 31#include "strv.h"
16354eff 32#include "log.h"
ed5bcfbe 33
ed5bcfbe
LP
34#define COMMENTS "#;\n"
35#define LINE_MAX 4096
36
37/* Run the user supplied parser for an assignment */
38static int next_assignment(
39 const char *filename,
40 unsigned line,
41 const char *section,
42 const ConfigItem *t,
43 const char *lvalue,
44 const char *rvalue,
45 void *userdata) {
46
47 assert(filename);
48 assert(t);
49 assert(lvalue);
50 assert(rvalue);
51
52 for (; t->parse; t++) {
53
54 if (t->lvalue && !streq(lvalue, t->lvalue))
55 continue;
56
57 if (t->section && !section)
58 continue;
59
60 if (t->section && !streq(section, t->section))
61 continue;
62
63 return t->parse(filename, line, section, lvalue, rvalue, t->data, userdata);
64 }
65
f1857be0
LP
66 log_info("[%s:%u] Unknown lvalue '%s' in section '%s'. Ignoring.", filename, line, lvalue, strna(section));
67 return 0;
ed5bcfbe
LP
68}
69
ed5bcfbe 70/* Parse a variable assignment line */
42f4e3c4 71static int parse_line(const char *filename, unsigned line, char **section, const char* const * sections, const ConfigItem *t, char *l, void *userdata) {
b2aa81ef 72 char *e;
ed5bcfbe 73
b2aa81ef 74 l = strstrip(l);
ed5bcfbe 75
b2aa81ef 76 if (!*l)
ed5bcfbe 77 return 0;
1ea86b18 78
b2aa81ef 79 if (strchr(COMMENTS, *l))
1ea86b18 80 return 0;
ed5bcfbe 81
b2aa81ef
LP
82 if (startswith(l, ".include ")) {
83 char *fn;
ed5bcfbe
LP
84 int r;
85
b2aa81ef
LP
86 if (!(fn = file_in_same_dir(filename, strstrip(l+9))))
87 return -ENOMEM;
ed5bcfbe 88
87f0e418 89 r = config_parse(fn, NULL, sections, t, userdata);
b2aa81ef
LP
90 free(fn);
91
ed5bcfbe
LP
92 return r;
93 }
94
b2aa81ef 95 if (*l == '[') {
ed5bcfbe
LP
96 size_t k;
97 char *n;
98
b2aa81ef 99 k = strlen(l);
ed5bcfbe
LP
100 assert(k > 0);
101
b2aa81ef 102 if (l[k-1] != ']') {
16354eff 103 log_error("[%s:%u] Invalid section header.", filename, line);
ed5bcfbe
LP
104 return -EBADMSG;
105 }
106
b2aa81ef 107 if (!(n = strndup(l+1, k-2)))
ed5bcfbe
LP
108 return -ENOMEM;
109
b2aa81ef
LP
110 if (sections && !strv_contains((char**) sections, n)) {
111 free(n);
112 return -EBADMSG;
42f4e3c4
LP
113 }
114
ed5bcfbe
LP
115 free(*section);
116 *section = n;
117
118 return 0;
119 }
120
b2aa81ef 121 if (!(e = strchr(l, '='))) {
16354eff 122 log_error("[%s:%u] Missing '='.", filename, line);
ed5bcfbe
LP
123 return -EBADMSG;
124 }
125
126 *e = 0;
127 e++;
128
b2aa81ef 129 return next_assignment(filename, line, *section, t, strstrip(l), strstrip(e), userdata);
ed5bcfbe
LP
130}
131
132/* Go through the file and parse each line */
87f0e418 133int config_parse(const char *filename, FILE *f, const char* const * sections, const ConfigItem *t, void *userdata) {
ed5bcfbe
LP
134 unsigned line = 0;
135 char *section = NULL;
ed5bcfbe 136 int r;
63ad1ab4 137 bool ours = false;
ed5bcfbe
LP
138
139 assert(filename);
140 assert(t);
141
87f0e418
LP
142 if (!f) {
143 if (!(f = fopen(filename, "re"))) {
144 r = -errno;
145 log_error("Failed to open configuration file '%s': %s", filename, strerror(-r));
146 goto finish;
147 }
63ad1ab4
LP
148
149 ours = true;
ed5bcfbe
LP
150 }
151
152 while (!feof(f)) {
153 char l[LINE_MAX];
154
155 if (!fgets(l, sizeof(l), f)) {
156 if (feof(f))
157 break;
158
159 r = -errno;
16354eff 160 log_error("Failed to read configuration file '%s': %s", filename, strerror(-r));
ed5bcfbe
LP
161 goto finish;
162 }
163
42f4e3c4 164 if ((r = parse_line(filename, ++line, &section, sections, t, l, userdata)) < 0)
ed5bcfbe
LP
165 goto finish;
166 }
167
168 r = 0;
169
170finish:
171 free(section);
172
63ad1ab4 173 if (f && ours)
ed5bcfbe
LP
174 fclose(f);
175
176 return r;
177}
178
179int config_parse_int(
180 const char *filename,
181 unsigned line,
182 const char *section,
183 const char *lvalue,
184 const char *rvalue,
185 void *data,
186 void *userdata) {
187
188 int *i = data;
189 int r;
190
191 assert(filename);
192 assert(lvalue);
193 assert(rvalue);
194 assert(data);
195
196 if ((r = safe_atoi(rvalue, i)) < 0) {
16354eff 197 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
ed5bcfbe
LP
198 return r;
199 }
200
201 return 0;
202}
203
204int config_parse_unsigned(
205 const char *filename,
206 unsigned line,
207 const char *section,
208 const char *lvalue,
209 const char *rvalue,
210 void *data,
211 void *userdata) {
212
213 unsigned *u = data;
214 int r;
215
216 assert(filename);
217 assert(lvalue);
218 assert(rvalue);
219 assert(data);
220
221 if ((r = safe_atou(rvalue, u)) < 0) {
16354eff 222 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
ed5bcfbe
LP
223 return r;
224 }
225
226 return 0;
227}
228
229int config_parse_size(
230 const char *filename,
231 unsigned line,
232 const char *section,
233 const char *lvalue,
234 const char *rvalue,
235 void *data,
236 void *userdata) {
237
238 size_t *sz = data;
239 unsigned u;
240 int r;
241
242 assert(filename);
243 assert(lvalue);
244 assert(rvalue);
245 assert(data);
246
247 if ((r = safe_atou(rvalue, &u)) < 0) {
16354eff 248 log_error("[%s:%u] Failed to parse numeric value: %s", filename, line, rvalue);
ed5bcfbe
LP
249 return r;
250 }
251
252 *sz = (size_t) u;
253 return 0;
254}
255
256int config_parse_bool(
257 const char *filename,
258 unsigned line,
259 const char *section,
260 const char *lvalue,
261 const char *rvalue,
262 void *data,
263 void *userdata) {
264
265 int k;
266 bool *b = data;
267
268 assert(filename);
269 assert(lvalue);
270 assert(rvalue);
271 assert(data);
272
273 if ((k = parse_boolean(rvalue)) < 0) {
16354eff 274 log_error("[%s:%u] Failed to parse boolean value: %s", filename, line, rvalue);
ed5bcfbe
LP
275 return k;
276 }
277
278 *b = !!k;
279 return 0;
280}
281
282int config_parse_string(
283 const char *filename,
284 unsigned line,
285 const char *section,
286 const char *lvalue,
287 const char *rvalue,
288 void *data,
289 void *userdata) {
290
291 char **s = data;
292 char *n;
293
294 assert(filename);
295 assert(lvalue);
296 assert(rvalue);
297 assert(data);
298
299 if (*rvalue) {
300 if (!(n = strdup(rvalue)))
301 return -ENOMEM;
302 } else
303 n = NULL;
304
305 free(*s);
306 *s = n;
307
308 return 0;
309}
57d42a5f 310
034c6ed7
LP
311int config_parse_path(
312 const char *filename,
313 unsigned line,
314 const char *section,
315 const char *lvalue,
316 const char *rvalue,
317 void *data,
318 void *userdata) {
319
320 char **s = data;
321 char *n;
322
323 assert(filename);
324 assert(lvalue);
325 assert(rvalue);
326 assert(data);
327
328 if (*rvalue != '/') {
329 log_error("[%s:%u] Not an absolute path: %s", filename, line, rvalue);
330 return -EINVAL;
331 }
332
333 if (!(n = strdup(rvalue)))
334 return -ENOMEM;
335
336 free(*s);
337 *s = n;
338
339 return 0;
340}
57d42a5f
LP
341
342int config_parse_strv(
343 const char *filename,
344 unsigned line,
345 const char *section,
346 const char *lvalue,
347 const char *rvalue,
348 void *data,
349 void *userdata) {
350
351 char*** sv = data;
352 char **n;
353 char *w;
354 unsigned k;
355 size_t l;
356 char *state;
357
358 assert(filename);
359 assert(lvalue);
360 assert(rvalue);
361 assert(data);
362
363 k = strv_length(*sv);
034c6ed7 364 FOREACH_WORD_QUOTED(w, l, rvalue, state)
57d42a5f
LP
365 k++;
366
367 if (!(n = new(char*, k+1)))
368 return -ENOMEM;
369
3251df7d
LP
370 if (*sv)
371 for (k = 0; (*sv)[k]; k++)
372 n[k] = (*sv)[k];
7418040c
LP
373 else
374 k = 0;
3251df7d 375
034c6ed7 376 FOREACH_WORD_QUOTED(w, l, rvalue, state)
57d42a5f
LP
377 if (!(n[k++] = strndup(w, l)))
378 goto fail;
379
380 n[k] = NULL;
381 free(*sv);
382 *sv = n;
383
384 return 0;
385
386fail:
387 for (; k > 0; k--)
388 free(n[k-1]);
034c6ed7 389 free(n);
57d42a5f
LP
390
391 return -ENOMEM;
392}