summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meson.build6
-rw-r--r--src/config-ini.c147
-rw-r--r--src/config-ini.h22
-rw-r--r--src/config-load.c55
-rw-r--r--src/config-load.h5
-rw-r--r--src/meson.build7
-rw-r--r--src/pnc.c6
-rw-r--r--src/types.h38
8 files changed, 286 insertions, 0 deletions
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 <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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, &section->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, &section->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(&section->fields);
+ list_add_tail(&section->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 <libubox/list.h>
+
+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 <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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, &section->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 <stdbool.h>
+
+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 <libubox/avl.h>
+
+#include <net/if.h>
+#include <stdint.h>
+
+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;