From f4881eb5e2892e75723b8cd26749b735741b52c4 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 29 Dec 2018 13:30:53 +0100 Subject: Build system, ini file loading --- meson.build | 6 +++ src/config-ini.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/config-ini.h | 22 ++++++++ src/config-load.c | 55 ++++++++++++++++++++ src/config-load.h | 5 ++ src/meson.build | 7 +++ src/pnc.c | 6 +++ src/types.h | 38 ++++++++++++++ 8 files changed, 286 insertions(+) create mode 100644 meson.build create mode 100644 src/config-ini.c create mode 100644 src/config-ini.h create mode 100644 src/config-load.c create mode 100644 src/config-load.h create mode 100644 src/meson.build create mode 100644 src/pnc.c create mode 100644 src/types.h diff --git a/meson.build b/meson.build new file mode 100644 index 0000000..aaa8cf6 --- /dev/null +++ b/meson.build @@ -0,0 +1,6 @@ +project('pnc', 'c') + +cc = meson.get_compiler('c') +ubox_dep = cc.find_library('ubox') + +subdir('src') diff --git a/src/config-ini.c b/src/config-ini.c new file mode 100644 index 0000000..7cfa1ff --- /dev/null +++ b/src/config-ini.c @@ -0,0 +1,147 @@ +#include "config-ini.h" +#include "types.h" + +#include +#include +#include +#include +#include + +static void free_field(ini_field_t *field) { + free(field->key); + free(field->value); + free(field); +} + +static void free_section(ini_section_t *section) { + ini_field_t *field, *tmp; + + list_for_each_entry_safe(field, tmp, §ion->fields, node) + free_field(field); + + free(section->name); + free(section); +} + +void free_ini_file(ini_file_t *file) { + ini_section_t *section, *tmp; + + list_for_each_entry_safe(section, tmp, &file->sections, node) + free_section(section); + + free(file); +} + +static bool add_field(ini_section_t *section, const char *key, const char *value) { + ini_field_t *field = calloc(1, sizeof(*field)); + if (!field) + return false; + + field->key = strdup(key); + field->value = strdup(value); + + if (!field->key || !field->value) { + free_field(field); + return false; + } + + list_add_tail(&field->node, §ion->fields); + + return true; +} + +static ini_section_t * add_section(ini_file_t *file, const char *name) { + ini_section_t *section = calloc(1, sizeof(*section)); + if (!section) + return NULL; + + section->name = strdup(name); + if (!section->name) { + free(section); + return false; + } + + INIT_LIST_HEAD(§ion->fields); + list_add_tail(§ion->node, &file->sections); + + return section; +} + +ini_file_t * read_ini_file(const char *filename) { + FILE *f = fopen(filename, "r"); + if (!f) + return NULL; + + ini_file_t *file = calloc(1, sizeof(*file)); + if (!file) + goto error; + + INIT_LIST_HEAD(&file->sections); + + ini_section_t *section = NULL; + int err = 0; + + char *line = NULL; + size_t n = 0; + + while (getline(&line, &n, f) >= 0) { + char *input = line; + + while (isspace(input[0])) + input++; + + if (input[0] == '#' || input[0] == '\0') + continue; + + size_t len = strlen(input); + + while (isspace(input[len-1])) + len--; + + if (input[0] == '[') { + if (input[len-1] != ']') { + err = EINVAL; + goto error; + } + + input[len-1] = '\0'; + + section = add_section(file, input+1); + if (!section) + goto error; + } else { + if (!section) { + err = EINVAL; + goto error; + } + + input[len] = '\0'; + + char *delim = strchr(input, '='); + if (!delim) { + err = EINVAL; + goto error; + } + + *delim = '\0'; + + if (!add_field(section, input, delim+1)) + goto error; + } + } + + if (ferror(f)) + err = EIO; + +error: + free(line); + fclose(f); + + if (err) { + free_ini_file(file); + errno = err; + return NULL; + } + + return file; +} diff --git a/src/config-ini.h b/src/config-ini.h new file mode 100644 index 0000000..802195d --- /dev/null +++ b/src/config-ini.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +typedef struct { + struct list_head node; + char *key; + char *value; +} ini_field_t; + +typedef struct { + struct list_head node; + struct list_head fields; + char *name; +} ini_section_t; + +typedef struct { + struct list_head sections; +} ini_file_t; + +ini_file_t * read_ini_file(const char *filename); +void free_ini_file(ini_file_t *file); diff --git a/src/config-load.c b/src/config-load.c new file mode 100644 index 0000000..9335813 --- /dev/null +++ b/src/config-load.c @@ -0,0 +1,55 @@ +#include "config-load.h" +#include "config-ini.h" +#include "types.h" + +#include +#include +#include +#include + +static const char * simple_basename(const char *path) { + const char *slash = strrchr(path, '/'); + return slash ? (slash+1) : path; +} + +static const char * extname(const char *filename) { + const char *dot = strrchr(filename, '.'); + return dot ? (dot+1) : NULL; +} + +static interface_config_t * read_interface_config(const char *path) { + ini_file_t *file = read_ini_file(path); + ini_section_t *section; + ini_field_t *field; + + list_for_each_entry(section, &file->sections, node) { + printf("%s\n", section->name); + + list_for_each_entry(field, §ion->fields, node) + printf("%s.%s=%s\n", section->name, field->key, field->value); + } + + free_ini_file(file); + + return NULL; +} + +bool read_config_file(const char *path) { + const char *filename = simple_basename(path); + const char *ext = extname(filename); + if (!ext) { + errno = EINVAL; + return false; + } + + char *name = strndup(filename, (ext - filename) - 1); + + if (strcmp(ext, "interface") == 0) { + interface_config_t *iface = read_interface_config(path); + free(iface); + } + + free(name); + + return true; +} diff --git a/src/config-load.h b/src/config-load.h new file mode 100644 index 0000000..0c278ee --- /dev/null +++ b/src/config-load.h @@ -0,0 +1,5 @@ +#pragma once + +#include + +bool read_config_file(const char *path); diff --git a/src/meson.build b/src/meson.build new file mode 100644 index 0000000..c24ca21 --- /dev/null +++ b/src/meson.build @@ -0,0 +1,7 @@ +src = [ + 'pnc.c', + 'config-ini.c', + 'config-load.c', +] + +executable('pnc', sources: src, dependencies: [ubox_dep]) diff --git a/src/pnc.c b/src/pnc.c new file mode 100644 index 0000000..651d140 --- /dev/null +++ b/src/pnc.c @@ -0,0 +1,6 @@ +#include "config-load.h" + +int main(int argc, char *argv[]) { + read_config_file(argv[1]); + return 0; +} diff --git a/src/types.h b/src/types.h new file mode 100644 index 0000000..cabaac6 --- /dev/null +++ b/src/types.h @@ -0,0 +1,38 @@ +#pragma once + +#include + +#include +#include + +typedef struct { + uint8_t addr[6]; +} macaddr_t; + +#define NODE_NAME(c) (*(char **)&(c)->node.key) + +typedef struct { + struct avl_tree subtypes; + struct avl_tree interfaces; +} config_t; + +typedef struct { + struct avl_node node; +} subconfig_type_t; + +typedef struct { + struct avl_node node; + struct avl_tree subconfigs; + + macaddr_t macaddr; + uint16_t mtu; +} interface_config_t; + +typedef struct { + struct avl_node node; + const char *type; +} interface_subconfig_t; + + +typedef struct { +} interface_generator_t; -- cgit v1.2.3