Build system, ini file loading
This commit is contained in:
commit
f4881eb5e2
8 changed files with 286 additions and 0 deletions
6
meson.build
Normal file
6
meson.build
Normal 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
147
src/config-ini.c
Normal 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, §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;
|
||||
}
|
22
src/config-ini.h
Normal file
22
src/config-ini.h
Normal 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
55
src/config-load.c
Normal 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, §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;
|
||||
}
|
5
src/config-load.h
Normal file
5
src/config-load.h
Normal file
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool read_config_file(const char *path);
|
7
src/meson.build
Normal file
7
src/meson.build
Normal 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
6
src/pnc.c
Normal 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
38
src/types.h
Normal 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;
|
Reference in a new issue