1 /*#############################################################################
3 # IPFire.org - A linux based firewall #
4 # Copyright (C) 2023 IPFire Network Development Team #
6 # This program is free software: you can redistribute it and/or modify #
7 # it under the terms of the GNU General Public License as published by #
8 # the Free Software Foundation, either version 3 of the License, or #
9 # (at your option) any later version. #
11 # This program is distributed in the hope that it will be useful, #
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14 # GNU General Public License for more details. #
16 # You should have received a copy of the GNU General Public License #
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
19 #############################################################################*/
26 #include <sys/queue.h>
32 struct nw_config_entry
{
33 STAILQ_ENTRY(nw_config_entry
) nodes
;
35 char key
[NETWORK_CONFIG_KEY_MAX_LENGTH
];
36 char value
[NETWORK_CONFIG_KEY_MAX_LENGTH
];
42 // The path to the configuration file
45 STAILQ_HEAD(entries
, nw_config_entry
) entries
;
48 static void nw_config_entry_free(struct nw_config_entry
* entry
) {
52 static struct nw_config_entry
* nw_config_entry_create(
53 struct nw_config
* config
, const char* key
) {
62 // Allocate a new object
63 struct nw_config_entry
* entry
= calloc(1, sizeof(*entry
));
68 r
= nw_string_set(entry
->key
, key
);
72 // Append the new entry
73 STAILQ_INSERT_TAIL(&config
->entries
, entry
, nodes
);
78 nw_config_entry_free(entry
);
82 static void nw_config_free(struct nw_config
* config
) {
84 nw_config_flush(config
);
89 int nw_config_create(struct nw_config
** config
, const char* path
) {
92 struct nw_config
* c
= calloc(1, sizeof(*c
));
96 // Initialize reference counter
100 STAILQ_INIT(&c
->entries
);
104 r
= nw_string_set(c
->path
, path
);
108 // Try to read the configuration from path
109 r
= nw_config_read(c
);
124 struct nw_config
* nw_config_ref(struct nw_config
* config
) {
130 struct nw_config
* nw_config_unref(struct nw_config
* config
) {
131 if (--config
->nrefs
> 0)
134 nw_config_free(config
);
138 const char* nw_config_path(struct nw_config
* config
) {
145 int nw_config_flush(struct nw_config
* config
) {
146 struct nw_config_entry
* entry
= NULL
;
148 while (!STAILQ_EMPTY(&config
->entries
)) {
149 entry
= STAILQ_FIRST(&config
->entries
);
150 STAILQ_REMOVE_HEAD(&config
->entries
, nodes
);
153 nw_config_entry_free(entry
);
159 static int nw_config_readf(struct nw_config
* config
, FILE* f
) {
165 int nw_config_read(struct nw_config
* config
) {
169 // We cannot read if path is not set
170 if (!*config
->path
) {
176 f
= fopen(config
->path
, "r");
178 // Silently ignore if the file does not exist
182 ERROR("Could not read configuration file %s: %m\n", config
->path
);
188 r
= nw_config_readf(config
, f
);
197 static int nw_config_writef(struct nw_config
* config
, FILE* f
) {
198 struct nw_config_entry
* entry
= NULL
;
201 STAILQ_FOREACH(entry
, &config
->entries
, nodes
) {
202 // Skip if value is NULL
207 r
= fprintf(f
, "%s=\"%s\"\n", entry
->key
, entry
->value
);
209 ERROR("Failed to write configuration: %m\n");
217 int nw_config_write(struct nw_config
* config
) {
220 // We cannot write if path is not set
221 if (!*config
->path
) {
226 FILE* f
= fopen(config
->path
, "w");
228 ERROR("Failed to open %s for writing: %m\n", config
->path
);
233 // Write configuration
234 r
= nw_config_writef(config
, f
);
243 static struct nw_config_entry
* nw_config_find(struct nw_config
* config
, const char* key
) {
244 struct nw_config_entry
* entry
= NULL
;
246 STAILQ_FOREACH(entry
, &config
->entries
, nodes
) {
248 if (strcmp(entry
->key
, key
) != 0)
259 int nw_config_del(struct nw_config
* config
, const char* key
) {
260 struct nw_config_entry
* entry
= NULL
;
262 // Find an entry matching the key
263 entry
= nw_config_find(config
, key
);
265 // If there is no entry, there is nothing to do
269 // Otherwise remove the object
270 STAILQ_REMOVE(&config
->entries
, entry
, nw_config_entry
, nodes
);
273 nw_config_entry_free(entry
);
278 const char* nw_config_get(struct nw_config
* config
, const char* key
) {
279 struct nw_config_entry
* entry
= nw_config_find(config
, key
);
281 // Return the value if found and set
282 if (entry
&& *entry
->value
)
285 // Otherwise return NULL
289 int nw_config_set(struct nw_config
* config
, const char* key
, const char* value
) {
290 struct nw_config_entry
* entry
= NULL
;
292 // Delete the entry if val is NULL
294 return nw_config_del(config
, key
);
296 // Find any existing entries
297 entry
= nw_config_find(config
, key
);
299 // Create a new entry if it doesn't exist, yet
301 entry
= nw_config_entry_create(config
, key
);
306 // Store the new value
307 return nw_string_set(entry
->value
, value
);
310 int nw_config_get_int(struct nw_config
* config
, const char* key
, const int __default
) {
311 const char* value
= nw_config_get(config
, key
);
313 // Return zero if not set
317 return strtoul(value
, NULL
, 10);
320 int nw_config_set_int(struct nw_config
* config
, const char* key
, const int value
) {
324 // Format the value as string
325 r
= nw_string_format(__value
, "%d\n", value
);
329 return nw_config_set(config
, key
, __value
);