mirror of
https://github.com/servalproject/serval-dna.git
synced 2025-01-30 08:03:49 +00:00
Improve new config prototype, add LIST to schema
This commit is contained in:
parent
960a6293e1
commit
a3cdf17410
146
config.h
146
config.h
@ -1,3 +1,5 @@
|
|||||||
|
#include <netinet/in.h>
|
||||||
|
|
||||||
typedef unsigned long debugflags_t;
|
typedef unsigned long debugflags_t;
|
||||||
|
|
||||||
struct config_node {
|
struct config_node {
|
||||||
@ -10,54 +12,128 @@ struct config_node {
|
|||||||
struct config_node *nodv[10]; // malloc()
|
struct config_node *nodv[10]; // malloc()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void *emalloc(size_t len);
|
||||||
|
char *strn_emalloc(const char *str, size_t len);
|
||||||
|
char *str_emalloc(const char *str);
|
||||||
|
|
||||||
struct config_node *parse_config(const char *source, const char *buf, size_t len);
|
struct config_node *parse_config(const char *source, const char *buf, size_t len);
|
||||||
int get_child(const struct config_node *parent, const char *key);
|
int get_child(const struct config_node *parent, const char *key);
|
||||||
void unsupported_node(const struct config_node *node);
|
void unsupported_node(const struct config_node *node);
|
||||||
void unsupported_tree(const struct config_node *node);
|
void unsupported_tree(const struct config_node *node);
|
||||||
|
|
||||||
|
// Generate value structs, struct config_SECTION.
|
||||||
|
#define SECTION(__sect) struct config_##__sect {
|
||||||
|
#define ITEM(__name, __type, __default, __parser, __comment) __type __name;
|
||||||
|
#define SUB(__name, __sect) struct config_##__sect __name;
|
||||||
|
#define LIST(__name, __type, __parser, __comment) struct { unsigned listc; struct { const char *label; __type value; } *listv; } __name;
|
||||||
|
#define SECTION_END };
|
||||||
|
#include "config_schema.h"
|
||||||
|
#undef SECTION
|
||||||
|
#undef ITEM
|
||||||
|
#undef SUB
|
||||||
|
#undef LIST
|
||||||
|
#undef SECTION_END
|
||||||
|
|
||||||
|
// Generate parser function prototypes.
|
||||||
|
#define SECTION(__sect) int opt_config_##__sect(struct config_##__sect *s, const struct config_node *node);
|
||||||
|
#define ITEM(__name, __type, __default, __parser, __comment) int __parser(__type *, const struct config_node *);
|
||||||
|
#define SUB(__name, __sect)
|
||||||
|
#define LIST(__name, __type, __parser, __comment) int __parser(__type *, const struct config_node *);
|
||||||
|
#define SECTION_END
|
||||||
|
#include "config_schema.h"
|
||||||
|
#undef SECTION
|
||||||
|
#undef ITEM
|
||||||
|
#undef SUB
|
||||||
|
#undef LIST
|
||||||
|
#undef SECTION_END
|
||||||
|
|
||||||
int opt_boolean(int *booleanp, const struct config_node *node);
|
int opt_boolean(int *booleanp, const struct config_node *node);
|
||||||
int opt_absolute_path(const char **pathp, const struct config_node *node);
|
int opt_absolute_path(const char **pathp, const struct config_node *node);
|
||||||
void opt_debugflags(debugflags_t *flagsp, const struct config_node *node);
|
int opt_debugflags(debugflags_t *flagsp, const struct config_node *node);
|
||||||
|
int opt_rhizome_peer(struct config_rhizomepeer *, const struct config_node *node);
|
||||||
// Generate value structs, struct config_SECTION
|
int opt_host(const char **hostp, const struct config_node *node);
|
||||||
#define CONFIG_SECTION(__sect) struct config_##__sect {
|
int opt_port(unsigned short *portp, const struct config_node *node);
|
||||||
#define CONFIG_ITEM(__name, __type, __default, __parser, __comment) __type __name;
|
|
||||||
#define CONFIG_STRUCT(__name, __sect) struct config_##__sect __name;
|
|
||||||
#define CONFIG_SECTION_END };
|
|
||||||
#include "config_schema.h"
|
|
||||||
#undef CONFIG_SECTION
|
|
||||||
#undef CONFIG_ITEM
|
|
||||||
#undef CONFIG_STRUCT
|
|
||||||
#undef CONFIG_SECTION_END
|
|
||||||
|
|
||||||
// Generate default functions, dfl_config_SECTION()
|
// Generate default functions, dfl_config_SECTION()
|
||||||
#define CONFIG_SECTION(__sect) \
|
#define SECTION(__sect) \
|
||||||
void dfl_config_##__sect(struct config_##__sect *s) {
|
void dfl_config_##__sect(struct config_##__sect *s) {
|
||||||
#define CONFIG_ITEM(__name, __type, __default, __parser, __comment) s->__name = __default;
|
#define ITEM(__name, __type, __default, __parser, __comment) s->__name = __default;
|
||||||
#define CONFIG_STRUCT(__name, __sect) dfl_config_##__sect(&s->__name);
|
#define SUB(__name, __sect) dfl_config_##__sect(&s->__name);
|
||||||
#define CONFIG_SECTION_END }
|
#define LIST(__name, __type, __parser, __comment) s->__name.listc = 0; s->__name.listv = NULL;
|
||||||
|
#define SECTION_END }
|
||||||
#include "config_schema.h"
|
#include "config_schema.h"
|
||||||
#undef CONFIG_SECTION
|
#undef SECTION
|
||||||
#undef CONFIG_ITEM
|
#undef ITEM
|
||||||
#undef CONFIG_STRUCT
|
#undef SUB
|
||||||
#undef CONFIG_SECTION_END
|
#undef LIST
|
||||||
|
#undef SECTION_END
|
||||||
|
|
||||||
// Generate parsing functions, opt_config_SECTION()
|
// Generate parsing functions, opt_config_SECTION()
|
||||||
#define CONFIG_SECTION(__sect) \
|
#define SECTION(__sect) \
|
||||||
void opt_config_##__sect(struct config_##__sect *s, const struct config_node *node) { \
|
int opt_config_##__sect(struct config_##__sect *s, const struct config_node *node) { \
|
||||||
int i; \
|
if (node->text) unsupported_node(node); \
|
||||||
char used[node->nodc]; \
|
int i; \
|
||||||
for (i = 0; i < node->nodc; ++i) used[i] = 0;
|
char used[node->nodc]; \
|
||||||
#define CONFIG_ITEM(__name, __type, __default, __parser, __comment) \
|
for (i = 0; i < node->nodc; ++i) \
|
||||||
if ((i = get_child(node, #__name)) != -1) { used[i] = 1; __parser(&s->__name, node->nodv[i]); }
|
used[i] = 0;
|
||||||
#define CONFIG_STRUCT(__name, __sect) \
|
#define ITEM(__name, __type, __default, __parser, __comment) \
|
||||||
if ((i = get_child(node, #__name)) != -1) { used[i] = 1; opt_config_##__sect(&s->__name, node->nodv[i]); }
|
if ((i = get_child(node, #__name)) != -1) { \
|
||||||
#define CONFIG_SECTION_END \
|
used[i] = 1; \
|
||||||
for (i = 0; i < node->nodc; ++i) { if (!used[i]) unsupported_tree(node->nodv[i]); } \
|
__parser(&s->__name, node->nodv[i]); \
|
||||||
|
}
|
||||||
|
#define SUB(__name, __sect) \
|
||||||
|
if ((i = get_child(node, #__name)) != -1) { \
|
||||||
|
used[i] = 1; \
|
||||||
|
opt_config_##__sect(&s->__name, node->nodv[i]); \
|
||||||
|
}
|
||||||
|
#define LIST(__name, __type, __parser, __comment) \
|
||||||
|
if ((i = get_child(node, #__name)) != -1) { \
|
||||||
|
used[i] = 1; \
|
||||||
|
const struct config_node *child = node->nodv[i]; \
|
||||||
|
if (child->text) \
|
||||||
|
unsupported_node(child); \
|
||||||
|
char *labels[child->nodc]; \
|
||||||
|
__type values[child->nodc]; \
|
||||||
|
int n = 0; \
|
||||||
|
int j; \
|
||||||
|
for (j = 0; j < child->nodc; ++j) { \
|
||||||
|
const struct config_node *elt = child->nodv[j]; \
|
||||||
|
switch (__parser(&values[n], elt)) { \
|
||||||
|
case -1: \
|
||||||
|
return -1; \
|
||||||
|
case 0: \
|
||||||
|
if (!(labels[n++] = str_emalloc(elt->key))) { \
|
||||||
|
while (n) \
|
||||||
|
free(labels[--n]); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
break; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (n) { \
|
||||||
|
if (s->__name.listv = emalloc(n * sizeof(s->__name.listv[0]))) { \
|
||||||
|
for (j = 0; j < n; ++j) { \
|
||||||
|
s->__name.listv[j].label = labels[j]; \
|
||||||
|
s->__name.listv[j].value = values[j]; \
|
||||||
|
} \
|
||||||
|
s->__name.listc = n; \
|
||||||
|
} else { \
|
||||||
|
while (n) \
|
||||||
|
free(labels[--n]); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#define SECTION_END \
|
||||||
|
for (i = 0; i < node->nodc; ++i) \
|
||||||
|
if (!used[i]) \
|
||||||
|
unsupported_tree(node->nodv[i]); \
|
||||||
|
return 0; \
|
||||||
}
|
}
|
||||||
#include "config_schema.h"
|
#include "config_schema.h"
|
||||||
#undef CONFIG_SECTION
|
#undef SECTION
|
||||||
#undef CONFIG_ITEM
|
#undef ITEM
|
||||||
#undef CONFIG_STRUCT
|
#undef SUB
|
||||||
#undef CONFIG_SECTION_END
|
#undef LIST
|
||||||
|
#undef SECTION_END
|
||||||
|
|
||||||
|
@ -1,16 +1,27 @@
|
|||||||
CONFIG_SECTION( log)
|
SECTION(log)
|
||||||
CONFIG_ITEM( file, const char *, NULL, opt_absolute_path, "Absolute path of log file")
|
ITEM( file, const char *, NULL, opt_absolute_path, "Absolute path of log file")
|
||||||
CONFIG_ITEM( show_pid, int, 1, opt_boolean, "If true, all log lines contain PID of logging process")
|
ITEM( show_pid, int, 1, opt_boolean, "If true, all log lines contain PID of logging process")
|
||||||
CONFIG_ITEM( show_time, int, 1, opt_boolean, "If true, all log lines contain time stamp")
|
ITEM( show_time, int, 1, opt_boolean, "If true, all log lines contain time stamp")
|
||||||
CONFIG_SECTION_END
|
SECTION_END
|
||||||
|
|
||||||
CONFIG_SECTION( rhizome)
|
SECTION(rhizomepeer)
|
||||||
CONFIG_ITEM( path, const char *, NULL, opt_absolute_path, "Absolute path of rhizome directory")
|
ITEM( protocol, const char *, NULL, opt_protocol, "Protocol name")
|
||||||
CONFIG_ITEM( enabled, int, 1, opt_boolean, "If true, Rhizome HTTP server is started")
|
ITEM( host, const char *, NULL, opt_host, "Host name or IP address")
|
||||||
CONFIG_SECTION_END
|
ITEM( port, unsigned short, 4110, opt_port, "Port number")
|
||||||
|
SECTION_END
|
||||||
|
|
||||||
CONFIG_SECTION( main)
|
SECTION(rhizomedirect)
|
||||||
CONFIG_STRUCT( log, log)
|
LIST( peer, struct config_rhizomepeer, opt_rhizome_peer, "List of rhizome peers")
|
||||||
CONFIG_ITEM( debug, debugflags_t, 0, opt_debugflags, "Debug flags")
|
SECTION_END
|
||||||
CONFIG_STRUCT( rhizome, rhizome)
|
|
||||||
CONFIG_SECTION_END
|
SECTION(rhizome)
|
||||||
|
ITEM( path, const char *, NULL, opt_absolute_path, "Absolute path of rhizome directory")
|
||||||
|
ITEM( enabled, int, 1, opt_boolean, "If true, Rhizome HTTP server is started")
|
||||||
|
SUB( direct, rhizomedirect)
|
||||||
|
SECTION_END
|
||||||
|
|
||||||
|
SECTION(main)
|
||||||
|
SUB( log, log)
|
||||||
|
ITEM( debug, debugflags_t, 0, opt_debugflags, "Debug flags")
|
||||||
|
SUB( rhizome, rhizome)
|
||||||
|
SECTION_END
|
||||||
|
364
config_test.c
364
config_test.c
@ -4,6 +4,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "str.h"
|
#include "str.h"
|
||||||
#include "strbuf_helpers.h"
|
#include "strbuf_helpers.h"
|
||||||
@ -18,58 +19,115 @@
|
|||||||
struct config_main config;
|
struct config_main config;
|
||||||
struct config_main default_config;
|
struct config_main default_config;
|
||||||
|
|
||||||
const char *find_keyend(const char *const fullkey, const char *const fullkeyend)
|
const char *find_keyend(const char *const key, const char *const fullkeyend)
|
||||||
{
|
{
|
||||||
const char *s;
|
const char *s = key;
|
||||||
for (s = fullkey; s < fullkeyend && (isalnum(*s) || *s == '_'); ++s)
|
if (s < fullkeyend && (isalpha(*s) || *s == '_'))
|
||||||
;
|
++s;
|
||||||
if (s == fullkey || (s < fullkeyend && *s != '.'))
|
while (s < fullkeyend && (isalnum(*s) || *s == '_'))
|
||||||
|
++s;
|
||||||
|
if (s == key || (s < fullkeyend && *s != '.'))
|
||||||
return NULL;
|
return NULL;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *strn_malloc(const char *str, size_t len)
|
void *emalloc(size_t len)
|
||||||
{
|
{
|
||||||
char *new = malloc(len + 1);
|
char *new = malloc(len + 1);
|
||||||
if (!new) {
|
if (!new) {
|
||||||
WHYF_perror("malloc(%lu)", (long)len + 1);
|
WHYF_perror("malloc(%lu)", (long)len);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
strncpy(new, str, len);
|
|
||||||
new[len] = '\0';
|
|
||||||
return new;
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
char *str_malloc(const char *str)
|
char *strn_emalloc(const char *str, size_t len)
|
||||||
{
|
{
|
||||||
return strn_malloc(str, strlen(str));
|
char *new = emalloc(len + 1);
|
||||||
|
if (new) {
|
||||||
|
strncpy(new, str, len);
|
||||||
|
new[len] = '\0';
|
||||||
|
}
|
||||||
|
return new;
|
||||||
}
|
}
|
||||||
|
|
||||||
int make_child(struct config_node **const parentp, const char *const key, size_t keylen)
|
char *str_emalloc(const char *str)
|
||||||
{
|
{
|
||||||
// TODO: search using binary chop and insert in key lexical order.
|
return strn_emalloc(str, strlen(str));
|
||||||
int i;
|
}
|
||||||
|
|
||||||
|
int make_child(struct config_node **const parentp, const char *const fullkey, const char *const key, const char *const keyend)
|
||||||
|
{
|
||||||
|
size_t keylen = keyend - key;
|
||||||
|
//DEBUGF("%s key=%s", __FUNCTION__, alloca_toprint(-1, key, keylen));
|
||||||
|
int i = 0;
|
||||||
struct config_node *child;
|
struct config_node *child;
|
||||||
for (i = 0; i < (*parentp)->nodc; ++i) {
|
if ((*parentp)->nodc) {
|
||||||
child = (*parentp)->nodv[i];
|
// Binary search for matching child.
|
||||||
if (strncmp(child->key, key, keylen) == 0 && child->key[keylen] == '\0')
|
int m = 0;
|
||||||
return i;
|
int n = (*parentp)->nodc - 1;
|
||||||
|
int c;
|
||||||
|
do {
|
||||||
|
i = (m + n) / 2;
|
||||||
|
child = (*parentp)->nodv[i];
|
||||||
|
c = strncmp(key, child->key, keylen);
|
||||||
|
if (c == 0 && child->key[keylen])
|
||||||
|
c = -1;
|
||||||
|
//DEBUGF(" m=%d n=%d i=%d child->key=%s c=%d", m, n, i, alloca_str_toprint(child->key), c);
|
||||||
|
if (c == 0) {
|
||||||
|
//DEBUGF(" found i=%d", i);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
if (c > 0)
|
||||||
|
m = ++i;
|
||||||
|
else
|
||||||
|
n = i - 1;
|
||||||
|
} while (m <= n);
|
||||||
}
|
}
|
||||||
child = (struct config_node *) calloc(1, sizeof *child);
|
// At this point, i is the index where a new child should be inserted.
|
||||||
if (child == NULL) {
|
assert(i >= 0);
|
||||||
WHYF_perror("calloc(1, %u)", sizeof(struct config_node));
|
assert(i <= (*parentp)->nodc);
|
||||||
|
child = emalloc(sizeof *child);
|
||||||
|
if (child == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
memset(child, sizeof *child, 0);
|
||||||
i = (*parentp)->nodc++;
|
++(*parentp)->nodc;
|
||||||
if ((*parentp)->nodc > NELS((*parentp)->nodv))
|
if ((*parentp)->nodc > NELS((*parentp)->nodv))
|
||||||
*parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv)));
|
*parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv)));
|
||||||
|
int j;
|
||||||
|
for (j = (*parentp)->nodc - 1; j > i; --j)
|
||||||
|
(*parentp)->nodv[j] = (*parentp)->nodv[j-1];
|
||||||
(*parentp)->nodv[i] = child;
|
(*parentp)->nodv[i] = child;
|
||||||
|
if (!(child->fullkey = strn_emalloc(fullkey, keyend - fullkey))) {
|
||||||
|
free(child);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
child->key = child->fullkey + (key - fullkey);
|
||||||
|
//DEBUGF(" insert i=%d", i);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void free_config_node(struct config_node *node)
|
||||||
|
{
|
||||||
|
while (node->nodc)
|
||||||
|
free_config_node(node->nodv[--node->nodc]);
|
||||||
|
if (node->fullkey) {
|
||||||
|
free((char *)node->fullkey);
|
||||||
|
node->fullkey = node->key = NULL;
|
||||||
|
}
|
||||||
|
if (node->text) {
|
||||||
|
free((char *)node->text);
|
||||||
|
node->text = NULL;
|
||||||
|
}
|
||||||
|
free(node);
|
||||||
|
}
|
||||||
|
|
||||||
struct config_node *parse_config(const char *source, const char *buf, size_t len)
|
struct config_node *parse_config(const char *source, const char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct config_node *root = calloc(1, sizeof(struct config_node));
|
struct config_node *root = emalloc(sizeof(struct config_node));
|
||||||
|
if (root == NULL)
|
||||||
|
return NULL;
|
||||||
|
memset(root, sizeof *root, 0);
|
||||||
const char *end = buf + len;
|
const char *end = buf + len;
|
||||||
const char *line = buf;
|
const char *line = buf;
|
||||||
const char *nextline;
|
const char *nextline;
|
||||||
@ -93,64 +151,43 @@ struct config_node *parse_config(const char *source, const char *buf, size_t len
|
|||||||
WARNF("%s:%u: malformed configuration line -- ignored", source, lineno);
|
WARNF("%s:%u: malformed configuration line -- ignored", source, lineno);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
struct config_node **parentp = &root;
|
struct config_node **nodep = &root;
|
||||||
const char *fullkey = line;
|
const char *fullkey = line;
|
||||||
const char *fullkeyend = p;
|
const char *fullkeyend = p;
|
||||||
const char *key = fullkey;
|
const char *key = fullkey;
|
||||||
const char *keyend = NULL;
|
const char *keyend = NULL;
|
||||||
int nodi;
|
int nodi = -1;
|
||||||
struct config_node *node = NULL;
|
while (key <= fullkeyend && (keyend = find_keyend(key, fullkeyend)) && (nodi = make_child(nodep, fullkey, key, keyend)) != -1) {
|
||||||
while (key < fullkeyend && (keyend = find_keyend(key, fullkeyend)) && (nodi = make_child(parentp, key, keyend - key)) != -1) {
|
|
||||||
node = (*parentp)->nodv[nodi];
|
|
||||||
if (node->text) {
|
|
||||||
WARNF("%s:%u: duplicate configuration option %s -- ignored (original is at %s:%u)",
|
|
||||||
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey),
|
|
||||||
node->source, node->line_number
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (node->line_number == 0) {
|
|
||||||
node->source = source;
|
|
||||||
node->line_number = lineno;
|
|
||||||
}
|
|
||||||
if (!node->fullkey) {
|
|
||||||
if (!(node->fullkey = strn_malloc(fullkey, keyend - fullkey)))
|
|
||||||
break; // out of memory
|
|
||||||
node->key = node->fullkey + (key - fullkey);
|
|
||||||
}
|
|
||||||
node->text = NULL;
|
|
||||||
key = keyend + 1;
|
key = keyend + 1;
|
||||||
parentp = &(*parentp)->nodv[nodi];
|
nodep = &(*nodep)->nodv[nodi];
|
||||||
}
|
}
|
||||||
if (keyend == NULL) {
|
if (keyend == NULL) {
|
||||||
WARNF("%s:%u: malformed configuration option %s -- ignored",
|
WARNF("%s:%u: malformed configuration option %s -- ignored",
|
||||||
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey)
|
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey)
|
||||||
);
|
);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if (nodi == -1)
|
if (nodi == -1)
|
||||||
break; // out of memory
|
goto error; // out of memory
|
||||||
|
struct config_node *node = *nodep;
|
||||||
|
if (node->text) {
|
||||||
|
WARNF("%s:%u: duplicate configuration option %s -- ignored (original is at %s:%u)",
|
||||||
|
source, lineno, alloca_toprint(-1, fullkey, fullkeyend - fullkey),
|
||||||
|
node->source, node->line_number
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (++p; p < lend && isspace(*p); ++p)
|
for (++p; p < lend && isspace(*p); ++p)
|
||||||
;
|
;
|
||||||
if (!(node->text = strn_malloc(p, lend - p)))
|
if (!(node->text = strn_emalloc(p, lend - p)))
|
||||||
break; // out of memory
|
break; // out of memory
|
||||||
|
node->source = source;
|
||||||
|
node->line_number = lineno;
|
||||||
}
|
}
|
||||||
return root;
|
return root;
|
||||||
}
|
error:
|
||||||
|
free_config_node(root);
|
||||||
void free_config_node(struct config_node *node)
|
return NULL;
|
||||||
{
|
|
||||||
while (node->nodc)
|
|
||||||
free_config_node(node->nodv[--node->nodc]);
|
|
||||||
if (node->fullkey) {
|
|
||||||
free((char *)node->fullkey);
|
|
||||||
node->fullkey = node->key = NULL;
|
|
||||||
}
|
|
||||||
if (node->text) {
|
|
||||||
free((char *)node->text);
|
|
||||||
node->text = NULL;
|
|
||||||
}
|
|
||||||
free(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_config_node(const struct config_node *node, int indent)
|
void dump_config_node(const struct config_node *node, int indent)
|
||||||
@ -180,75 +217,93 @@ int get_child(const struct config_node *parent, const char *key)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalid_text(const struct config_node *node)
|
void invalid_text(const struct config_node *node, const char *reason)
|
||||||
{
|
{
|
||||||
WARNF("%s:%u: invalid configuration option %s=%s -- ignored",
|
WARNF("%s:%u: ignoring configuration option %s with invalid value %s%s%s",
|
||||||
node->source, node->line_number,
|
node->source, node->line_number,
|
||||||
alloca_str_toprint(node->fullkey),
|
alloca_str_toprint(node->fullkey),
|
||||||
alloca_str_toprint(node->text)
|
alloca_str_toprint(node->text),
|
||||||
|
reason && reason[0] ? " -- " : "", reason ? reason : ""
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ignore_node(const struct config_node *node, const char *msg)
|
||||||
|
{
|
||||||
|
WARNF("%s:%u: ignoring configuration option %s%s%s",
|
||||||
|
node->source, node->line_number, alloca_str_toprint(node->fullkey),
|
||||||
|
msg && msg[0] ? " -- " : "", msg ? msg : ""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ignore_tree(const struct config_node *node, const char *msg);
|
||||||
|
|
||||||
|
void ignore_children(const struct config_node *parent, const char *msg)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < parent->nodc; ++i)
|
||||||
|
ignore_tree(parent->nodv[i], msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ignore_tree(const struct config_node *node, const char *msg)
|
||||||
|
{
|
||||||
|
if (node->text)
|
||||||
|
ignore_node(node, msg);
|
||||||
|
ignore_children(node, msg);
|
||||||
|
}
|
||||||
|
|
||||||
void unsupported_node(const struct config_node *node)
|
void unsupported_node(const struct config_node *node)
|
||||||
{
|
{
|
||||||
WARNF("%s:%u: unsupported configuration option %s -- ignored",
|
ignore_node(node, "not supported");
|
||||||
node->source, node->line_number, alloca_str_toprint(node->fullkey)
|
}
|
||||||
);
|
|
||||||
|
void spurious_children(const struct config_node *parent)
|
||||||
|
{
|
||||||
|
ignore_children(parent, "spurious");
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsupported_children(const struct config_node *parent)
|
void unsupported_children(const struct config_node *parent)
|
||||||
{
|
{
|
||||||
int i;
|
ignore_children(parent, "not supported");
|
||||||
for (i = 0; i < parent->nodc; ++i)
|
|
||||||
unsupported_tree(parent->nodv[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void unsupported_tree(const struct config_node *node)
|
void unsupported_tree(const struct config_node *node)
|
||||||
{
|
{
|
||||||
if (node->text)
|
ignore_tree(node, "not supported");
|
||||||
unsupported_node(node);
|
|
||||||
unsupported_children(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
void unused_config_node(const struct config_node *node)
|
|
||||||
{
|
|
||||||
if (node->text)
|
|
||||||
unsupported_node(node);
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < node->nodc; ++i)
|
|
||||||
unused_config_node(node->nodv[i]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int opt_boolean(int *booleanp, const struct config_node *node)
|
int opt_boolean(int *booleanp, const struct config_node *node)
|
||||||
{
|
{
|
||||||
unsupported_children(node);
|
unsupported_children(node);
|
||||||
if (node->text) {
|
if (!node->text)
|
||||||
if (!strcasecmp(node->text, "true") || !strcasecmp(node->text, "yes") || !strcasecmp(node->text, "on") || !strcasecmp(node->text, "1"))
|
return 1;
|
||||||
return (*booleanp = 1);
|
if (!strcasecmp(node->text, "true") || !strcasecmp(node->text, "yes") || !strcasecmp(node->text, "on") || !strcasecmp(node->text, "1")) {
|
||||||
else if (!strcasecmp(node->text, "false") || !strcasecmp(node->text, "no") || !strcasecmp(node->text, "off") || !strcasecmp(node->text, "0"))
|
*booleanp = 1;
|
||||||
return (*booleanp = 0);
|
return 0;
|
||||||
else
|
|
||||||
invalid_text(node);
|
|
||||||
}
|
}
|
||||||
return -1;
|
else if (!strcasecmp(node->text, "false") || !strcasecmp(node->text, "no") || !strcasecmp(node->text, "off") || !strcasecmp(node->text, "0")) {
|
||||||
|
*booleanp = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
invalid_text(node, "expecting true|yes|on|1|false|no|off|0");
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int opt_absolute_path(const char **pathp, const struct config_node *node)
|
int opt_absolute_path(const char **pathp, const struct config_node *node)
|
||||||
{
|
{
|
||||||
DEBUGF("%s", __FUNCTION__);
|
//DEBUGF("%s", __FUNCTION__);
|
||||||
dump_config_node(node, 1);
|
//dump_config_node(node, 1);
|
||||||
unsupported_children(node);
|
unsupported_children(node);
|
||||||
if (node->text) {
|
if (!node->text)
|
||||||
if (node->text[0] != '/')
|
return 1;
|
||||||
invalid_text(node);
|
if (node->text[0] != '/') {
|
||||||
else {
|
invalid_text(node, "must start with '/'");
|
||||||
if (*pathp)
|
return 1;
|
||||||
free((char *) *pathp);
|
|
||||||
if ((*pathp = str_malloc(node->text)))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return -1;
|
if (*pathp)
|
||||||
|
free((char *) *pathp); // TODO: this should be unnecessary
|
||||||
|
if ((*pathp = str_emalloc(node->text)) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
debugflags_t debugFlagMask(const char *flagname)
|
debugflags_t debugFlagMask(const char *flagname)
|
||||||
@ -285,10 +340,10 @@ debugflags_t debugFlagMask(const char *flagname)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void opt_debugflags(debugflags_t *flagsp, const struct config_node *node)
|
int opt_debugflags(debugflags_t *flagsp, const struct config_node *node)
|
||||||
{
|
{
|
||||||
DEBUGF("%s", __FUNCTION__);
|
//DEBUGF("%s", __FUNCTION__);
|
||||||
dump_config_node(node, 1);
|
//dump_config_node(node, 1);
|
||||||
if (node->text)
|
if (node->text)
|
||||||
unsupported_tree(node);
|
unsupported_tree(node);
|
||||||
debugflags_t setmask = 0;
|
debugflags_t setmask = 0;
|
||||||
@ -322,6 +377,90 @@ void opt_debugflags(debugflags_t *flagsp, const struct config_node *node)
|
|||||||
*flagsp = 0;
|
*flagsp = 0;
|
||||||
*flagsp &= ~clearmask;
|
*flagsp &= ~clearmask;
|
||||||
*flagsp |= setmask;
|
*flagsp |= setmask;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt_protocol(const char **protocolp, const struct config_node *node)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt_rhizome_peer(struct config_rhizomepeer *rpeer, const struct config_node *node)
|
||||||
|
{
|
||||||
|
if (!node->text)
|
||||||
|
return opt_config_rhizomepeer(rpeer, node);
|
||||||
|
spurious_children(node);
|
||||||
|
const char *protocol;
|
||||||
|
size_t protolen;
|
||||||
|
const char *auth;
|
||||||
|
if (str_is_uri(node->text)) {
|
||||||
|
const char *hier;
|
||||||
|
if (!( str_uri_scheme(node->text, &protocol, &protolen)
|
||||||
|
&& str_uri_hierarchical(node->text, &hier, NULL)
|
||||||
|
&& str_uri_hierarchical_authority(hier, &auth, NULL))
|
||||||
|
) {
|
||||||
|
invalid_text(node, "malformed URL");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
auth = node->text;
|
||||||
|
protocol = "http";
|
||||||
|
protolen = strlen(protocol);
|
||||||
|
}
|
||||||
|
const char *host;
|
||||||
|
size_t hostlen;
|
||||||
|
unsigned short port = 0;
|
||||||
|
if (!str_uri_authority_hostname(auth, &host, &hostlen))
|
||||||
|
return -1;
|
||||||
|
str_uri_authority_port(auth, &port);
|
||||||
|
if (!(rpeer->protocol = strn_emalloc(protocol, protolen)))
|
||||||
|
return -1;
|
||||||
|
if (!(rpeer->host = str_emalloc(host))) {
|
||||||
|
free((char *) rpeer->protocol);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
rpeer->port = port;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt_host(const char **hostp, const struct config_node *node)
|
||||||
|
{
|
||||||
|
//DEBUGF("%s", __FUNCTION__);
|
||||||
|
//dump_config_node(node, 1);
|
||||||
|
unsupported_children(node);
|
||||||
|
if (!node->text)
|
||||||
|
return 1;
|
||||||
|
if (!node->text[0]) {
|
||||||
|
invalid_text(node, "empty host name");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (*hostp)
|
||||||
|
free((char *) *hostp); // TODO: this should be unnecessary
|
||||||
|
if ((*hostp = str_emalloc(node->text)) == NULL)
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int opt_port(unsigned short *portp, const struct config_node *node)
|
||||||
|
{
|
||||||
|
//DEBUGF("%s", __FUNCTION__);
|
||||||
|
//dump_config_node(node, 1);
|
||||||
|
unsupported_children(node);
|
||||||
|
if (!node->text)
|
||||||
|
return 1;
|
||||||
|
unsigned short port = 0;
|
||||||
|
const char *p;
|
||||||
|
for (p = node->text; isdigit(*p); ++p) {
|
||||||
|
unsigned oport = port;
|
||||||
|
port = port * 10 + *p - '0';
|
||||||
|
if (port / 10 != oport)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*p) {
|
||||||
|
invalid_text(node, "invalid port number");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
*portp = port;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@ -356,6 +495,13 @@ int main(int argc, char **argv)
|
|||||||
DEBUGF("config.log.show_pid = %d", config.log.show_pid);
|
DEBUGF("config.log.show_pid = %d", config.log.show_pid);
|
||||||
DEBUGF("config.log.show_time = %d", config.log.show_time);
|
DEBUGF("config.log.show_time = %d", config.log.show_time);
|
||||||
DEBUGF("config.debug = %llx", (unsigned long long) config.debug);
|
DEBUGF("config.debug = %llx", (unsigned long long) config.debug);
|
||||||
|
int j;
|
||||||
|
for (j = 0; j < config.rhizome.direct.peer.listc; ++j) {
|
||||||
|
DEBUGF("config.rhizome.direct.peer.%s", config.rhizome.direct.peer.listv[j].label);
|
||||||
|
DEBUGF(" .protocol = %s", alloca_str_toprint(config.rhizome.direct.peer.listv[j].value.protocol));
|
||||||
|
DEBUGF(" .host = %s", alloca_str_toprint(config.rhizome.direct.peer.listv[j].value.host));
|
||||||
|
DEBUGF(" .port = %u", config.rhizome.direct.peer.listv[j].value.port);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user