1 /* SPDX-License-Identifier: LGPL-2.1+ */
5 This file is part of systemd.
7 Copyright 2010 Lennart Poettering
16 #include "alloc-util.h"
20 /* An abstract parser for simple, line based, shallow configuration files consisting of variable assignments only. */
22 typedef enum ConfigParseFlags {
23 CONFIG_PARSE_RELAXED = 1 << 0,
24 CONFIG_PARSE_ALLOW_INCLUDE = 1 << 1,
25 CONFIG_PARSE_WARN = 1 << 2,
26 CONFIG_PARSE_REFUSE_BOM = 1 << 3,
29 /* Argument list for parsers of specific configuration settings. */
30 #define CONFIG_PARSER_ARGUMENTS \
32 const char *filename, \
34 const char *section, \
35 unsigned section_line, \
42 /* Prototype for a parser for a specific configuration setting */
43 typedef int (*ConfigParserCallback)(CONFIG_PARSER_ARGUMENTS);
45 /* A macro declaring the a function prototype, following the typedef above, simply because it's so cumbersomely long
46 * otherwise. (And current emacs gets irritatingly slow when editing files that contain lots of very long function
47 * prototypes on the same screen…) */
48 #define CONFIG_PARSER_PROTOTYPE(name) int name(CONFIG_PARSER_ARGUMENTS)
50 /* Wraps information for parsing a specific configuration variable, to
51 * be stored in a simple array */
52 typedef struct ConfigTableItem {
53 const char *section; /* Section */
54 const char *lvalue; /* Name of the variable */
55 ConfigParserCallback parse; /* Function that is called to parse the variable's value */
56 int ltype; /* Distinguish different variables passed to the same callback */
57 void *data; /* Where to store the variable's data */
60 /* Wraps information for parsing a specific configuration variable, to
61 * be stored in a gperf perfect hashtable */
62 typedef struct ConfigPerfItem {
63 const char *section_and_lvalue; /* Section + "." + name of the variable */
64 ConfigParserCallback parse; /* Function that is called to parse the variable's value */
65 int ltype; /* Distinguish different variables passed to the same callback */
66 size_t offset; /* Offset where to store data, from the beginning of userdata */
69 /* Prototype for a low-level gperf lookup function */
70 typedef const ConfigPerfItem* (*ConfigPerfItemLookup)(const char *section_and_lvalue, unsigned length);
72 /* Prototype for a generic high-level lookup function */
73 typedef int (*ConfigItemLookup)(
77 ConfigParserCallback *func,
82 /* Linear table search implementation of ConfigItemLookup, based on
83 * ConfigTableItem arrays */
84 int config_item_table_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
86 /* gperf implementation of ConfigItemLookup, based on gperf
87 * ConfigPerfItem tables */
88 int config_item_perf_lookup(const void *table, const char *section, const char *lvalue, ConfigParserCallback *func, int *ltype, void **data, void *userdata);
94 const char *sections, /* nulstr */
95 ConfigItemLookup lookup,
97 ConfigParseFlags flags,
100 int config_parse_many_nulstr(
101 const char *conf_file, /* possibly NULL */
102 const char *conf_file_dirs, /* nulstr */
103 const char *sections, /* nulstr */
104 ConfigItemLookup lookup,
106 ConfigParseFlags flags,
109 #if 0 /// UNNEEDED by elogind
110 int config_parse_many(
111 const char *conf_file, /* possibly NULL */
112 const char* const* conf_file_dirs,
113 const char *dropin_dirname,
114 const char *sections, /* nulstr */
115 ConfigItemLookup lookup,
117 ConfigParseFlags flags,
121 #if 0 /// UNNEEDED by elogind
123 #if 0 /// UNNEEDED by elogind
125 #if 0 /// UNNEEDED by elogind
127 #if 0 /// UNNEEDED by elogind
129 #if 0 /// UNNEEDED by elogind
131 #if 0 /// UNNEEDED by elogind
133 #if 0 /// UNNEEDED by elogind
135 CONFIG_PARSER_PROTOTYPE(config_parse_int);
136 CONFIG_PARSER_PROTOTYPE(config_parse_unsigned);
137 CONFIG_PARSER_PROTOTYPE(config_parse_long);
138 CONFIG_PARSER_PROTOTYPE(config_parse_uint8);
139 CONFIG_PARSER_PROTOTYPE(config_parse_uint16);
140 CONFIG_PARSER_PROTOTYPE(config_parse_uint32);
141 CONFIG_PARSER_PROTOTYPE(config_parse_uint64);
142 CONFIG_PARSER_PROTOTYPE(config_parse_double);
143 CONFIG_PARSER_PROTOTYPE(config_parse_iec_size);
144 CONFIG_PARSER_PROTOTYPE(config_parse_si_size);
145 CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64);
146 CONFIG_PARSER_PROTOTYPE(config_parse_bool);
147 CONFIG_PARSER_PROTOTYPE(config_parse_tristate);
148 CONFIG_PARSER_PROTOTYPE(config_parse_string);
149 CONFIG_PARSER_PROTOTYPE(config_parse_path);
150 CONFIG_PARSER_PROTOTYPE(config_parse_strv);
151 CONFIG_PARSER_PROTOTYPE(config_parse_sec);
152 CONFIG_PARSER_PROTOTYPE(config_parse_nsec);
153 CONFIG_PARSER_PROTOTYPE(config_parse_mode);
154 CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat);
155 CONFIG_PARSER_PROTOTYPE(config_parse_log_facility);
156 CONFIG_PARSER_PROTOTYPE(config_parse_log_level);
157 CONFIG_PARSER_PROTOTYPE(config_parse_signal);
158 CONFIG_PARSER_PROTOTYPE(config_parse_personality);
159 CONFIG_PARSER_PROTOTYPE(config_parse_permille);
160 CONFIG_PARSER_PROTOTYPE(config_parse_ifname);
161 CONFIG_PARSER_PROTOTYPE(config_parse_ip_port);
162 CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers);
163 CONFIG_PARSER_PROTOTYPE(config_parse_mtu);
164 CONFIG_PARSER_PROTOTYPE(config_parse_rlimit);
166 typedef enum Disabled {
167 DISABLED_CONFIGURATION,
169 DISABLED_EXPERIMENTAL,
172 #define DEFINE_CONFIG_PARSE(function, parser, msg) \
173 CONFIG_PARSER_PROTOTYPE(function) { \
181 r = parser(rvalue); \
183 log_syntax(unit, LOG_ERR, filename, line, r, \
184 msg ", ignoring: %s", rvalue); \
192 #define DEFINE_CONFIG_PARSE_PTR(function, parser, type, msg) \
193 CONFIG_PARSER_PROTOTYPE(function) { \
202 r = parser(rvalue, i); \
204 log_syntax(unit, LOG_ERR, filename, line, r, \
205 msg ", ignoring: %s", rvalue); \
210 #define DEFINE_CONFIG_PARSE_ENUM(function, name, type, msg) \
211 CONFIG_PARSER_PROTOTYPE(function) { \
219 x = name##_from_string(rvalue); \
221 log_syntax(unit, LOG_ERR, filename, line, 0, \
222 msg ", ignoring: %s", rvalue); \
230 #define DEFINE_CONFIG_PARSE_ENUM_WITH_DEFAULT(function, name, type, default_value, msg) \
231 CONFIG_PARSER_PROTOTYPE(function) { \
239 if (isempty(rvalue)) { \
240 *i = default_value; \
244 x = name##_from_string(rvalue); \
246 log_syntax(unit, LOG_ERR, filename, line, 0, \
247 msg ", ignoring: %s", rvalue); \
255 #define DEFINE_CONFIG_PARSE_ENUMV(function, name, type, invalid, msg) \
256 CONFIG_PARSER_PROTOTYPE(function) { \
257 type **enums = data, x, *ys; \
258 _cleanup_free_ type *xs = NULL; \
259 const char *word, *state; \
267 xs = new0(type, 1); \
273 FOREACH_WORD(word, l, rvalue, state) { \
274 _cleanup_free_ char *en = NULL; \
277 en = strndup(word, l); \
281 if ((x = name##_from_string(en)) < 0) { \
282 log_syntax(unit, LOG_ERR, filename, line, 0, \
283 msg ", ignoring: %s", en); \
287 for (ys = xs; x != invalid && *ys != invalid; ys++) { \
289 log_syntax(unit, LOG_NOTICE, filename, \
291 "Duplicate entry, ignoring: %s", \
301 new_xs = realloc(xs, (++i + 1) * sizeof(type)); \
307 *(xs + i) = invalid; \
310 free_and_replace(*enums, xs); \