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
= 1U << 0,
24 CONFIG_PARSE_ALLOW_INCLUDE
= 1U << 1,
25 CONFIG_PARSE_WARN
= 1U << 2,
26 CONFIG_PARSE_REFUSE_BOM
= 1U << 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 int config_parse_many(
110 const char *conf_file
, /* possibly NULL */
111 const char* const* conf_file_dirs
,
112 const char *dropin_dirname
,
113 const char *sections
, /* nulstr */
114 ConfigItemLookup lookup
,
116 ConfigParseFlags flags
,
119 CONFIG_PARSER_PROTOTYPE(config_parse_int
);
120 CONFIG_PARSER_PROTOTYPE(config_parse_unsigned
);
121 CONFIG_PARSER_PROTOTYPE(config_parse_long
);
122 CONFIG_PARSER_PROTOTYPE(config_parse_uint8
);
123 CONFIG_PARSER_PROTOTYPE(config_parse_uint16
);
124 CONFIG_PARSER_PROTOTYPE(config_parse_uint32
);
125 CONFIG_PARSER_PROTOTYPE(config_parse_uint64
);
126 CONFIG_PARSER_PROTOTYPE(config_parse_double
);
127 CONFIG_PARSER_PROTOTYPE(config_parse_iec_size
);
128 CONFIG_PARSER_PROTOTYPE(config_parse_si_size
);
129 CONFIG_PARSER_PROTOTYPE(config_parse_iec_uint64
);
130 CONFIG_PARSER_PROTOTYPE(config_parse_bool
);
131 CONFIG_PARSER_PROTOTYPE(config_parse_tristate
);
132 CONFIG_PARSER_PROTOTYPE(config_parse_string
);
133 CONFIG_PARSER_PROTOTYPE(config_parse_path
);
134 CONFIG_PARSER_PROTOTYPE(config_parse_strv
);
135 CONFIG_PARSER_PROTOTYPE(config_parse_sec
);
136 CONFIG_PARSER_PROTOTYPE(config_parse_nsec
);
137 CONFIG_PARSER_PROTOTYPE(config_parse_mode
);
138 CONFIG_PARSER_PROTOTYPE(config_parse_warn_compat
);
139 CONFIG_PARSER_PROTOTYPE(config_parse_log_facility
);
140 CONFIG_PARSER_PROTOTYPE(config_parse_log_level
);
141 CONFIG_PARSER_PROTOTYPE(config_parse_signal
);
142 CONFIG_PARSER_PROTOTYPE(config_parse_personality
);
143 CONFIG_PARSER_PROTOTYPE(config_parse_ifname
);
144 CONFIG_PARSER_PROTOTYPE(config_parse_ip_port
);
145 CONFIG_PARSER_PROTOTYPE(config_parse_join_controllers
);
146 CONFIG_PARSER_PROTOTYPE(config_parse_mtu
);
147 CONFIG_PARSER_PROTOTYPE(config_parse_rlimit
);
149 typedef enum Disabled
{
150 DISABLED_CONFIGURATION
,
152 DISABLED_EXPERIMENTAL
,
155 #define DEFINE_CONFIG_PARSE_ENUM(function,name,type,msg) \
156 CONFIG_PARSER_PROTOTYPE(function) { \
164 if ((x = name##_from_string(rvalue)) < 0) { \
165 log_syntax(unit, LOG_ERR, filename, line, -x, \
166 msg ", ignoring: %s", rvalue); \
174 #define DEFINE_CONFIG_PARSE_ENUMV(function,name,type,invalid,msg) \
175 CONFIG_PARSER_PROTOTYPE(function) { \
176 type **enums = data, x, *ys; \
177 _cleanup_free_ type *xs = NULL; \
178 const char *word, *state; \
186 xs = new0(type, 1); \
192 FOREACH_WORD(word, l, rvalue, state) { \
193 _cleanup_free_ char *en = NULL; \
196 en = strndup(word, l); \
200 if ((x = name##_from_string(en)) < 0) { \
201 log_syntax(unit, LOG_ERR, filename, line, \
202 -x, msg ", ignoring: %s", en); \
206 for (ys = xs; x != invalid && *ys != invalid; ys++) { \
208 log_syntax(unit, LOG_ERR, filename, \
210 "Duplicate entry, ignoring: %s", \
220 new_xs = realloc(xs, (++i + 1) * sizeof(type)); \
226 *(xs + i) = invalid; \