Build system, ini file loading

This commit is contained in:
Matthias Schiffer 2018-12-29 13:30:53 +01:00
commit f4881eb5e2
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
8 changed files with 286 additions and 0 deletions

6
meson.build Normal file
View file

@ -0,0 +1,6 @@
project('pnc', 'c')
cc = meson.get_compiler('c')
ubox_dep = cc.find_library('ubox')
subdir('src')

147
src/config-ini.c Normal file
View file

@ -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;
}

22
src/config-ini.h Normal file
View file

@ -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);

55
src/config-load.c Normal file
View file

@ -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;
}

5
src/config-load.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <stdbool.h>
bool read_config_file(const char *path);

7
src/meson.build Normal file
View file

@ -0,0 +1,7 @@
src = [
'pnc.c',
'config-ini.c',
'config-load.c',
]
executable('pnc', sources: src, dependencies: [ubox_dep])

6
src/pnc.c Normal file
View file

@ -0,0 +1,6 @@
#include "config-load.h"
int main(int argc, char *argv[]) {
read_config_file(argv[1]);
return 0;
}

38
src/types.h Normal file
View file

@ -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;