mirror of
https://github.com/servalproject/serval-dna.git
synced 2024-12-21 14:07:53 +00:00
Merge branch 'naf2-logging' into 'development'
This commit is contained in:
commit
8771d6181b
@ -1140,8 +1140,10 @@ int app_config_schema(const struct cli_parsed *parsed, void *context)
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
struct cf_om_node *root = NULL;
|
||||
if (cf_sch_config_main(&root) == -1)
|
||||
if (cf_sch_config_main(&root) == -1) {
|
||||
cf_om_free_node(&root);
|
||||
return -1;
|
||||
}
|
||||
struct cf_om_iterator it;
|
||||
for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it))
|
||||
if (it.node->text || it.node->nodc == 0) {
|
||||
@ -1151,9 +1153,36 @@ int app_config_schema(const struct cli_parsed *parsed, void *context)
|
||||
cli_puts(it.node->text);
|
||||
cli_delim("\n");
|
||||
}
|
||||
cf_om_free_node(&root);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int app_config_dump(const struct cli_parsed *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
DEBUG_cli_parsed(parsed);
|
||||
int full = 0 == cli_arg(parsed, "--full", NULL, NULL, NULL);
|
||||
if (create_serval_instance_dir() == -1)
|
||||
return -1;
|
||||
struct cf_om_node *root = NULL;
|
||||
int ret = cf_fmt_config_main(&root, &config);
|
||||
if (ret == CFERROR) {
|
||||
cf_om_free_node(&root);
|
||||
return -1;
|
||||
}
|
||||
struct cf_om_iterator it;
|
||||
for (cf_om_iter_start(&it, root); it.node; cf_om_iter_next(&it)) {
|
||||
if (it.node->text && (full || it.node->line_number)) {
|
||||
cli_puts(it.node->fullkey);
|
||||
cli_delim("=");
|
||||
cli_puts(it.node->text);
|
||||
cli_delim("\n");
|
||||
}
|
||||
}
|
||||
cf_om_free_node(&root);
|
||||
return ret == CFOK ? 0 : 1;
|
||||
}
|
||||
|
||||
int app_config_set(const struct cli_parsed *parsed, void *context)
|
||||
{
|
||||
if (config.debug.verbose)
|
||||
@ -2349,7 +2378,9 @@ struct cli_schema command_line_options[]={
|
||||
{app_trace,{"mdp","trace","<SID>",NULL},0,
|
||||
"Trace through the network to the specified node via MDP."},
|
||||
{app_config_schema,{"config","schema",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Dump configuration schema."},
|
||||
"Display configuration schema."},
|
||||
{app_config_dump,{"config","dump","[--full]",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Dump configuration settings."},
|
||||
{app_config_set,{"config","set","<variable>","<value>","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
|
||||
"Set and del specified configuration variables."},
|
||||
{app_config_set,{"config","del","<variable>","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG,
|
||||
|
180
conf.h
180
conf.h
@ -238,6 +238,9 @@ int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char
|
||||
const char *cf_om_get(const struct cf_om_node *root, const char *fullkey);
|
||||
int cf_om_set(struct cf_om_node **nodep, const char *fullkey, const char *text);
|
||||
int cf_om_add_child(struct cf_om_node **const parentp, const char *const key);
|
||||
int cf_om_remove_null_child(struct cf_om_node **parentp, unsigned n);
|
||||
int cf_om_remove_empty_child(struct cf_om_node **parentp, unsigned n);
|
||||
void cf_om_remove_child(struct cf_om_node **parent, unsigned n);
|
||||
void cf_om_free_node(struct cf_om_node **nodep);
|
||||
void cf_om_dump_node(const struct cf_om_node *node, int indent);
|
||||
int cf_om_match(const char *pattern, const struct cf_om_node *node);
|
||||
@ -319,10 +322,10 @@ struct pattern_list {
|
||||
struct config_##__name { \
|
||||
unsigned ac; \
|
||||
struct config_##__name##__element {
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
__type key;
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
char key[(__strsize) + 1];
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
__type key; // key must be first element in struct
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
char key[(__strsize) + 1]; // key must be first element in struct
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
__type value;
|
||||
#define VALUE_STRING(__strsize, __eltrepr) \
|
||||
@ -367,8 +370,8 @@ struct pattern_list {
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_dfl_config_##__name(struct config_##__name *a); \
|
||||
int cf_sch_config_##__name(struct cf_om_node **parentp);
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...)
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...)
|
||||
#define KEY_ATOM(__type, __keyrepr)
|
||||
#define KEY_STRING(__strsize, __keyrepr)
|
||||
#define VALUE_ATOM(__type, __eltrepr)
|
||||
#define VALUE_STRING(__strsize, __eltrepr)
|
||||
#define VALUE_NODE(__type, __eltrepr)
|
||||
@ -393,46 +396,71 @@ struct pattern_list {
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate config parser function prototypes.
|
||||
// Generate config parser function prototypes: cf_opt_REPR(), cf_fmt_REPR(), cf_cmp_REPR()
|
||||
#define __VALIDATOR(__name, __validator...) \
|
||||
typedef int __validator_func__config_##__name##__t(const struct cf_om_node *, struct config_##__name *, int); \
|
||||
__validator_func__config_##__name##__t __dummy__validator_func__config_##__name, ##__validator;
|
||||
#define STRUCT(__name, __validator...) \
|
||||
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||
int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \
|
||||
int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \
|
||||
__VALIDATOR(__name, ##__validator)
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
||||
int cf_opt_##__repr(__type *, const struct cf_om_node *); \
|
||||
char * cf_fmt_##__repr(const __type *);
|
||||
int cf_fmt_##__repr(struct cf_om_node **, const __type *); \
|
||||
int cf_cmp_##__repr(const __type *, const __type *);
|
||||
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
||||
int cf_opt_##__repr(__type *, const char *); \
|
||||
char * cf_fmt_##__repr(const __type *);
|
||||
int cf_fmt_##__repr(const char **, const __type *); \
|
||||
int cf_cmp_##__repr(const __type *, const __type *);
|
||||
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
||||
int cf_opt_##__repr(char *, size_t, const char *); \
|
||||
char * cf_fmt_##__repr(const char *);
|
||||
#define SUB_STRUCT(__name, __element, __flags) \
|
||||
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||
struct cf_om_node * cf_fmt_config_##__name(struct config_##__name *);
|
||||
#define NODE_STRUCT(__name, __element, __repr, __flags) \
|
||||
int cf_opt_##__repr(struct config_##__name *, const struct cf_om_node *); \
|
||||
struct cf_om_node * cf_fmt_##__repr(struct config_##__name *);
|
||||
int cf_fmt_##__repr(const char **, const char *); \
|
||||
int cf_cmp_##__repr(const char *, const char *);
|
||||
#define SUB_STRUCT(__structname, __element, __flags) \
|
||||
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \
|
||||
int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \
|
||||
int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *);
|
||||
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
|
||||
SUB_STRUCT(__structname, __element, __flags) \
|
||||
int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \
|
||||
int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \
|
||||
int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *);
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_opt_config_##__name(struct config_##__name *, const struct cf_om_node *); \
|
||||
int cf_fmt_config_##__name(struct cf_om_node **, const struct config_##__name *); \
|
||||
int cf_cmp_config_##__name(const struct config_##__name *, const struct config_##__name *); \
|
||||
__VALIDATOR(__name, ##__validator)
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
int cf_opt_##__keyrepr(__type *, const char *);
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
int cf_opt_##__keyrepr(char *, size_t, const char *);
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
int cf_opt_##__keyrepr(__type *, const char *); \
|
||||
int cf_fmt_##__keyrepr(const char **, const __type *); \
|
||||
int cf_cmp_##__keyrepr(const __type *, const __type *);
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
int cf_opt_##__keyrepr(char *, size_t, const char *); \
|
||||
int cf_fmt_##__keyrepr(const char **, const char *); \
|
||||
int cf_cmp_##__keyrepr(const char *, const char *);
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
int cf_opt_##__eltrepr(__type *, const char *);
|
||||
int cf_opt_##__eltrepr(__type *, const char *); \
|
||||
int cf_fmt_##__eltrepr(const char **, const __type *); \
|
||||
int cf_cmp_##__eltrepr(const __type *, const __type *);
|
||||
#define VALUE_STRING(__strsize, __eltrepr) \
|
||||
int cf_opt_##__eltrepr(char *, size_t, const char *);
|
||||
int cf_opt_##__eltrepr(char *, size_t, const char *); \
|
||||
int cf_fmt_##__eltrepr(const char **, const char *); \
|
||||
int cf_cmp_##__eltrepr(const char *, const char *);
|
||||
#define VALUE_NODE(__type, __eltrepr) \
|
||||
int cf_opt_##__eltrepr(__type *, const struct cf_om_node *);
|
||||
int cf_opt_##__eltrepr(__type *, const struct cf_om_node *); \
|
||||
int cf_fmt_##__eltrepr(struct cf_om_node **, const __type *); \
|
||||
int cf_cmp_##__eltrepr(const __type *, const __type *);
|
||||
#define VALUE_SUB_STRUCT(__structname) \
|
||||
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *);
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
||||
int cf_opt_##__eltrepr(struct config_##__structname *, const struct cf_om_node *);
|
||||
int cf_opt_config_##__structname(struct config_##__structname *, const struct cf_om_node *); \
|
||||
int cf_fmt_config_##__structname(struct cf_om_node **, const struct config_##__structname *); \
|
||||
int cf_cmp_config_##__structname(const struct config_##__structname *, const struct config_##__structname *);
|
||||
#define VALUE_NODE_STRUCT(__structname, __repr) \
|
||||
VALUE_SUB_STRUCT(__structname) \
|
||||
int cf_opt_##__repr(struct config_##__structname *, const struct cf_om_node *); \
|
||||
int cf_fmt_##__repr(struct cf_om_node **, const struct config_##__structname *); \
|
||||
int cf_cmp_##__repr(const struct config_##__structname *, const struct config_##__structname *);
|
||||
#define END_ARRAY(__size)
|
||||
#include "conf_schema.h"
|
||||
#undef __VALIDATOR
|
||||
@ -453,54 +481,6 @@ struct pattern_list {
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate config array key comparison function prototypes.
|
||||
#define STRUCT(__name, __validator...)
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment)
|
||||
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
|
||||
#define STRING(__size, __element, __default, __repr, __flags, __comment)
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __repr, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
typedef int __compare_func__config_##__name##__t
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
(const __type *, const __type *);
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
(const char *, const char *);
|
||||
#define VALUE_ATOM(__type, __eltrepr)
|
||||
#define VALUE_STRING(__strsize, __eltrepr)
|
||||
#define VALUE_NODE(__type, __eltrepr)
|
||||
#define VALUE_SUB_STRUCT(__structname)
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
|
||||
#define END_ARRAY(__size)
|
||||
#include "conf_schema.h"
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
__compare_func__config_##__name##__t __dummy__compare_func__config_##__name
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
,##__cmpfunc;
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
,##__cmpfunc;
|
||||
#include "conf_schema.h"
|
||||
#undef STRUCT
|
||||
#undef NODE
|
||||
#undef ATOM
|
||||
#undef STRING
|
||||
#undef SUB_STRUCT
|
||||
#undef NODE_STRUCT
|
||||
#undef END_STRUCT
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#undef VALUE_ATOM
|
||||
#undef VALUE_STRING
|
||||
#undef VALUE_NODE
|
||||
#undef VALUE_SUB_STRUCT
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate config array search-by-key function prototypes.
|
||||
#define STRUCT(__name, __validator...)
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment)
|
||||
@ -511,9 +491,9 @@ struct pattern_list {
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int config_##__name##__get(const struct config_##__name *,
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
const __type *);
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
const char *);
|
||||
#define VALUE_ATOM(__type, __eltrepr)
|
||||
#define VALUE_STRING(__strsize, __eltrepr)
|
||||
@ -540,28 +520,72 @@ struct pattern_list {
|
||||
#undef END_ARRAY
|
||||
|
||||
int cf_opt_char_boolean(char *booleanp, const char *text);
|
||||
int cf_fmt_char_boolean(const char **, const char *booleanp);
|
||||
|
||||
int cf_opt_int_boolean(int *booleanp, const char *text);
|
||||
int cf_fmt_int_boolean(const char **, const int *booleanp);
|
||||
|
||||
int cf_opt_absolute_path(char *str, size_t len, const char *text);
|
||||
int cf_fmt_absolute_path(const char **, const char *path);
|
||||
|
||||
int cf_opt_rhizome_peer(struct config_rhizome_peer *, const struct cf_om_node *node);
|
||||
int cf_fmt_rhizome_peer(struct cf_om_node **, const struct config_rhizome_peer *);
|
||||
|
||||
int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *, const char *uri);
|
||||
|
||||
int cf_opt_str(char *str, size_t len, const char *text);
|
||||
int cf_fmt_str(const char **, const char *str);
|
||||
|
||||
int cf_opt_str_nonempty(char *str, size_t len, const char *text);
|
||||
int cf_fmt_str_nonempty(const char **, const char *str);
|
||||
|
||||
int cf_opt_int(int *intp, const char *text);
|
||||
int cf_fmt_int(const char **, const int *intp);
|
||||
|
||||
int cf_opt_uint16(uint16_t *intp, const char *text);
|
||||
int cf_fmt_int16(const char **, const int16_t *intp);
|
||||
|
||||
int cf_opt_uint16_nonzero(uint16_t *intp, const char *text);
|
||||
int cf_fmt_int16_nonzero(const char **, const uint16_t *intp);
|
||||
|
||||
int cf_opt_int32_nonneg(int32_t *intp, const char *text);
|
||||
int cf_fmt_int32_nonneg(const char **, const int32_t *intp);
|
||||
|
||||
int cf_opt_uint32_nonzero(uint32_t *intp, const char *text);
|
||||
int cf_fmt_uint32_nonzero(const char **, const uint32_t *intp);
|
||||
|
||||
int cf_opt_uint64_scaled(uint64_t *intp, const char *text);
|
||||
int cf_fmt_uint64_scaled(const char **, const uint64_t *intp);
|
||||
|
||||
int cf_opt_protocol(char *str, size_t len, const char *text);
|
||||
int cf_fmt_protocol(const char **, const char *str);
|
||||
|
||||
int cf_opt_in_addr(struct in_addr *addrp, const char *text);
|
||||
int cf_fmt_in_addr(const char **, const struct in_addr *addrp);
|
||||
|
||||
int cf_opt_sid(sid_t *sidp, const char *text);
|
||||
int cf_fmt_sid(const char **, const sid_t *sidp);
|
||||
|
||||
int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text);
|
||||
int cf_fmt_rhizome_bk(const char **, const rhizome_bk_t *bkp);
|
||||
|
||||
int cf_opt_interface_type(short *typep, const char *text);
|
||||
int cf_fmt_interface_type(const char **, const short *typep);
|
||||
|
||||
int cf_opt_pattern_list(struct pattern_list *listp, const char *text);
|
||||
int cf_fmt_pattern_list(const char **, const struct pattern_list *listp);
|
||||
|
||||
int cf_opt_network_interface(struct config_network_interface *nifp, const struct cf_om_node *node);
|
||||
int cf_fmt_network_interface(struct cf_om_node **, const struct config_network_interface *nifp);
|
||||
|
||||
int cf_opt_interface_list(struct config_interface_list *listp, const struct cf_om_node *node);
|
||||
int cf_opt_socket_type(int *typep, const char *text);
|
||||
int cf_opt_encapsulation(int *typep, const char *text);
|
||||
int cf_fmt_interface_list(struct cf_om_node **, const struct config_interface_list *listp);
|
||||
|
||||
int cf_opt_socket_type(short *typep, const char *text);
|
||||
int cf_fmt_socket_type(const char **, const short *typep);
|
||||
|
||||
int cf_opt_encapsulation(short *encapp, const char *text);
|
||||
int cf_fmt_encapsulation(const char **, const short *encapp);
|
||||
|
||||
extern int cf_limbo;
|
||||
extern struct config_main config;
|
||||
|
44
conf_om.c
44
conf_om.c
@ -148,6 +148,11 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const
|
||||
assert(i <= (*parentp)->nodc);
|
||||
if ((child = emalloc_zero(sizeof *child)) == NULL)
|
||||
return -1;
|
||||
if (!(child->fullkey = strn_edup(fullkey, keyend - fullkey))) {
|
||||
free(child);
|
||||
return -1;
|
||||
}
|
||||
child->key = child->fullkey + (key - fullkey);
|
||||
++(*parentp)->nodc;
|
||||
if ((*parentp)->nodc > NELS((*parentp)->nodv))
|
||||
*parentp = realloc(*parentp, sizeof(**parentp) + sizeof((*parentp)->nodv[0]) * ((*parentp)->nodc - NELS((*parentp)->nodv)));
|
||||
@ -155,11 +160,6 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const
|
||||
for (j = (*parentp)->nodc - 1; j > i; --j)
|
||||
(*parentp)->nodv[j] = (*parentp)->nodv[j-1];
|
||||
(*parentp)->nodv[i] = child;
|
||||
if (!(child->fullkey = strn_edup(fullkey, keyend - fullkey))) {
|
||||
free(child);
|
||||
return -1;
|
||||
}
|
||||
child->key = child->fullkey + (key - fullkey);
|
||||
//DEBUGF(" insert i=%d", i);
|
||||
return i;
|
||||
}
|
||||
@ -191,6 +191,35 @@ int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char
|
||||
return -1;
|
||||
}
|
||||
|
||||
int cf_om_remove_null_child(struct cf_om_node **parentp, unsigned n)
|
||||
{
|
||||
assert(n < (*parentp)->nodc);
|
||||
if ((*parentp)->nodv[n] == NULL) {
|
||||
cf_om_remove_child(parentp, n);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cf_om_remove_empty_child(struct cf_om_node **parentp, unsigned n)
|
||||
{
|
||||
assert(n < (*parentp)->nodc);
|
||||
if ((*parentp)->nodv[n] && (*parentp)->nodv[n]->text == NULL && (*parentp)->nodv[n]->nodc == 0) {
|
||||
cf_om_remove_child(parentp, n);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void cf_om_remove_child(struct cf_om_node **parentp, unsigned n)
|
||||
{
|
||||
assert(n < (*parentp)->nodc);
|
||||
cf_om_free_node(&(*parentp)->nodv[n]);
|
||||
--(*parentp)->nodc;
|
||||
for (; n < (*parentp)->nodc; ++n)
|
||||
(*parentp)->nodv[n] = (*parentp)->nodv[n+1];
|
||||
}
|
||||
|
||||
int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_node **rootp)
|
||||
{
|
||||
const char *end = buf + len;
|
||||
@ -261,6 +290,7 @@ int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_no
|
||||
void cf_om_free_node(struct cf_om_node **nodep)
|
||||
{
|
||||
if (*nodep) {
|
||||
//DEBUGF("%s text=%s nodc=%d", (*nodep)->fullkey, alloca_str_toprint((*nodep)->text), (*nodep)->nodc);
|
||||
while ((*nodep)->nodc)
|
||||
cf_om_free_node(&(*nodep)->nodv[--(*nodep)->nodc]);
|
||||
if ((*nodep)->fullkey) {
|
||||
@ -418,8 +448,10 @@ int cf_om_iter_next(struct cf_om_iterator *it)
|
||||
int i = it->stack[it->sp].index++;
|
||||
if (i < parent->nodc) {
|
||||
it->node = parent->nodv[i];
|
||||
if (it->node == NULL)
|
||||
return WHY("null node");
|
||||
if (it->sp >= NELS(it->stack))
|
||||
return -1;
|
||||
return WHY("stack overflow");
|
||||
++it->sp;
|
||||
it->stack[it->sp].node = it->node;
|
||||
it->stack[it->sp].index = 0;
|
||||
|
314
conf_parse.c
314
conf_parse.c
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Serval DNA configuration
|
||||
Copyright (C) 2012 Serval Project Inc.
|
||||
|
||||
@ -42,8 +42,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
a->ac = 0; \
|
||||
return CFOK; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...)
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...)
|
||||
#define KEY_ATOM(__type, __keyrepr)
|
||||
#define KEY_STRING(__strsize, __keyrepr)
|
||||
#define VALUE_ATOM(__type, __eltrepr)
|
||||
#define VALUE_STRING(__strsize, __eltrepr)
|
||||
#define VALUE_NODE(__type, __eltrepr)
|
||||
@ -68,60 +68,16 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate array element comparison functions.
|
||||
#define STRUCT(__name, __validator...)
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment)
|
||||
#define ATOM(__type, __element, __default, __repr, __flags, __comment)
|
||||
#define STRING(__size, __element, __default, __repr, __flags, __comment)
|
||||
#define SUB_STRUCT(__name, __element, __flags)
|
||||
#define NODE_STRUCT(__name, __element, __repr, __flags)
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
static int __cmp_config_##__name(const struct config_##__name##__element *a, const struct config_##__name##__element *b) { \
|
||||
__compare_func__config_##__name##__t *cmp = (NULL
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(&a->key, &b->key) : memcmp(&a->key, &b->key, sizeof a->key);
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
,##__cmpfunc); \
|
||||
return cmp ? (*cmp)(a->key, b->key) : strcmp(a->key, b->key);
|
||||
#define VALUE_ATOM(__type, __eltrepr)
|
||||
#define VALUE_STRING(__strsize, __eltrepr)
|
||||
#define VALUE_NODE(__type, __eltrepr)
|
||||
#define VALUE_SUB_STRUCT(__structname)
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltrepr)
|
||||
#define END_ARRAY(__size) \
|
||||
}
|
||||
#include "conf_schema.h"
|
||||
#undef STRUCT
|
||||
#undef NODE
|
||||
#undef ATOM
|
||||
#undef STRING
|
||||
#undef SUB_STRUCT
|
||||
#undef NODE_STRUCT
|
||||
#undef END_STRUCT
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#undef VALUE_ATOM
|
||||
#undef VALUE_STRING
|
||||
#undef VALUE_NODE
|
||||
#undef VALUE_SUB_STRUCT
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Schema item flags.
|
||||
#define __MANDATORY (1<<0)
|
||||
#define __TEXT (1<<1)
|
||||
#define __CHILDREN (1<<2)
|
||||
#define __SORTED (1<<3)
|
||||
#define __NO_DUPLICATES (1<<4)
|
||||
#define __NO_DUPLICATES (1<<3)
|
||||
|
||||
// Schema flag symbols, to be used in the '__flags' macro arguments.
|
||||
#define MANDATORY |__MANDATORY
|
||||
#define USES_TEXT |__TEXT
|
||||
#define USES_CHILDREN |__CHILDREN
|
||||
#define SORTED |__SORTED
|
||||
#define NO_DUPLICATES |__NO_DUPLICATES
|
||||
|
||||
// Generate parsing functions, cf_opt_config_SECTION()
|
||||
@ -188,14 +144,15 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_opt_config_##__name(struct config_##__name *array, const struct cf_om_node *node) { \
|
||||
int flags = (0 __flags); \
|
||||
int (*eltcmp)(const struct config_##__name##__element *, const struct config_##__name##__element *) = __cmp_config_##__name; \
|
||||
int (*keycmp)(const void *, const void *) = NULL; \
|
||||
int (*validator)(const struct cf_om_node *, struct config_##__name *, int) = (NULL, ##__validator); \
|
||||
int result = CFOK; \
|
||||
int i, n; \
|
||||
for (n = 0, i = 0; i < node->nodc && n < NELS(array->av); ++i) { \
|
||||
const struct cf_om_node *child = node->nodv[i]; \
|
||||
int ret = CFEMPTY;
|
||||
#define __ARRAY_KEY(__parseexpr, __cmpfunc...) \
|
||||
#define __ARRAY_KEY(__parseexpr, __cmpfunc, __cmpfuncargs) \
|
||||
keycmp = (int (*)(const void *, const void *)) __cmpfunc; \
|
||||
ret = (__parseexpr); \
|
||||
if (ret == CFERROR) \
|
||||
return CFERROR; \
|
||||
@ -205,7 +162,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
if (ret == CFOK && (flags & __NO_DUPLICATES)) { \
|
||||
int j; \
|
||||
for (j = 0; j < n; ++j) { \
|
||||
if ((*eltcmp)(&array->av[j], &array->av[n]) == 0) { \
|
||||
if (__cmpfunc __cmpfuncargs == 0) { \
|
||||
cf_warn_duplicate_node(child, NULL); \
|
||||
ret |= CFDUPLICATE; \
|
||||
} \
|
||||
@ -237,8 +194,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
cf_warn_list_overflow(node->nodv[i]); \
|
||||
} \
|
||||
array->ac = n; \
|
||||
if (flags & __SORTED) \
|
||||
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) eltcmp); \
|
||||
qsort(array->av, array->ac, sizeof array->av[0], (int (*)(const void *, const void *)) keycmp); \
|
||||
if (validator) \
|
||||
result = (*validator)(node, array, result); \
|
||||
if (result & ~CFEMPTY) { \
|
||||
@ -249,10 +205,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
result |= CFEMPTY; \
|
||||
return result; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
__ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), ##__cmpfunc)
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
__ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), ##__cmpfunc)
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
__ARRAY_KEY(cf_opt_##__keyrepr(&array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key, &array->av[n].key))
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
__ARRAY_KEY(cf_opt_##__keyrepr(array->av[n].key, sizeof array->av[n].key, child->key), cf_cmp_##__keyrepr, (&array->av[j].key[0], &array->av[n].key[0]))
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
__ARRAY_VALUE(CFOK, child->text ? cf_opt_##__eltrepr(&array->av[n].value, child->text) : CFEMPTY)
|
||||
#define VALUE_STRING(__strsize, __eltrepr) \
|
||||
@ -279,6 +235,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#undef VALUE_NODE
|
||||
#undef VALUE_SUB_STRUCT
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef __ARRAY_KEY
|
||||
#undef __ARRAY_VALUE
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate config array search-by-key functions.
|
||||
@ -291,21 +249,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#define END_STRUCT
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int config_##__name##__get(const struct config_##__name *array,
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
const __type *key) { \
|
||||
int (*cmp)(const __type *, const __type *) = (NULL, ##__cmpfunc); \
|
||||
int i; \
|
||||
for (i = 0; i < array->ac; ++i) \
|
||||
if ((cmp ? (*cmp)(key, &array->av[i].key) : memcmp(key, &array->av[i].key, sizeof *key)) == 0) \
|
||||
if ((cf_cmp_##__keyrepr(key, &array->av[i].key)) == 0) \
|
||||
return i; \
|
||||
return -1; \
|
||||
}
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
const char *key) { \
|
||||
int (*cmp)(const char *, const char *) = (NULL, ##__cmpfunc); \
|
||||
int i; \
|
||||
for (i = 0; i < array->ac; ++i) \
|
||||
if ((cmp ? (*cmp)(key, array->av[i].key) : strcmp(key, array->av[i].key)) == 0) \
|
||||
if ((cf_cmp_##__keyrepr(&key[0], &array->av[i].key[0])) == 0) \
|
||||
return i; \
|
||||
return -1; \
|
||||
}
|
||||
@ -373,9 +329,9 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
int cf_sch_config_##__name(struct cf_om_node **rootp) { \
|
||||
int i; \
|
||||
struct cf_om_node **childp;
|
||||
#define KEY_ATOM(__type, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
__ADD_CHILD(rootp, "[" #__keyrepr "]")
|
||||
#define KEY_STRING(__strsize, __keyrepr, __cmpfunc...) \
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
__ADD_CHILD(rootp, "[" #__keyrepr "]")
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
__ATOM(childp, "(" #__eltrepr ")")
|
||||
@ -415,3 +371,231 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate formatting functions, cf_fmt_config_SECTION()
|
||||
#define STRUCT(__name, __validator...) \
|
||||
int cf_fmt_config_##__name(struct cf_om_node **parentp, const struct config_##__name *strct) { \
|
||||
int result = CFOK; \
|
||||
int ret;
|
||||
#define __FMT_TEXT(__repr, __eltname, __eltexpr, __defaultvar) \
|
||||
const char *text = NULL; \
|
||||
ret = cf_fmt_##__repr(&text, __eltexpr); \
|
||||
if (ret == CFOK) { \
|
||||
int n; \
|
||||
if (text == NULL) { \
|
||||
WHY("cf_fmt_" #__repr "() returned CFOK but text=NULL"); \
|
||||
ret = CFERROR; \
|
||||
} else if ((n = cf_om_add_child(parentp, __eltname)) == -1) { \
|
||||
ret = CFERROR; \
|
||||
} else { \
|
||||
(*parentp)->nodv[n]->text = text; \
|
||||
(*parentp)->nodv[n]->line_number = is_default ? 0 : 1; \
|
||||
text = NULL; \
|
||||
} \
|
||||
} else if (ret == CFERROR || !is_default) \
|
||||
WARNF("cf_fmt_" #__repr "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
|
||||
if (text) { \
|
||||
free((char *)text); \
|
||||
text = NULL; \
|
||||
} \
|
||||
if (ret == CFERROR) \
|
||||
return CFERROR; \
|
||||
else if (ret != CFOK && !is_default) \
|
||||
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS);
|
||||
#define __FMT_NODE(__fmtfunc, __element) \
|
||||
{ \
|
||||
int n = cf_om_add_child(parentp, #__element); \
|
||||
if (n == -1) \
|
||||
ret = CFERROR; \
|
||||
else { \
|
||||
ret = __fmtfunc(&(*parentp)->nodv[n], &strct->__element); \
|
||||
cf_om_remove_null_child(parentp, n); \
|
||||
if (ret != CFOK) \
|
||||
WARNF(#__fmtfunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
|
||||
if (n < (*parentp)->nodc && cf_om_remove_empty_child(parentp, n)) { \
|
||||
WHYF(#__fmtfunc "() returned empty node at n=%d", n); \
|
||||
ret = CFERROR; \
|
||||
} \
|
||||
} \
|
||||
if (ret == CFERROR) \
|
||||
return CFERROR; \
|
||||
else if (ret != CFOK) \
|
||||
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS); \
|
||||
}
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
||||
__FMT_NODE(cf_fmt_##__repr, __element)
|
||||
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
||||
{ \
|
||||
__type dfl = __default; \
|
||||
int is_default = cf_cmp_##__repr(&strct->__element, &dfl) == 0; \
|
||||
__FMT_TEXT(__repr, #__element, &strct->__element, __default) \
|
||||
}
|
||||
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
||||
{ \
|
||||
int is_default = cf_cmp_##__repr(&strct->__element[0], __default) == 0; \
|
||||
__FMT_TEXT(__repr, #__element, &strct->__element[0], __default) \
|
||||
}
|
||||
#define SUB_STRUCT(__structname, __element, __flags) \
|
||||
__FMT_NODE(cf_fmt_config_##__structname, __element)
|
||||
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
|
||||
__FMT_NODE(cf_fmt_##__repr, __element)
|
||||
#define END_STRUCT \
|
||||
if ((*parentp)->nodc == 0) \
|
||||
cf_om_free_node(parentp); \
|
||||
return result; \
|
||||
}
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_fmt_config_##__name(struct cf_om_node **parentp, const struct config_##__name *array) { \
|
||||
int result = CFOK; \
|
||||
int i; \
|
||||
for (i = 0; i < array->ac; ++i) {
|
||||
#define __ARRAY_KEY(__keyfunc, __keyexpr) \
|
||||
const char *key = NULL; \
|
||||
int ret = __keyfunc(&key, __keyexpr); \
|
||||
int n = -1; \
|
||||
if (ret != CFOK) { \
|
||||
WARNF(#__keyfunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
|
||||
} else if (key == NULL) { \
|
||||
WHY(#__keyfunc "() returned CFOK but key=NULL"); \
|
||||
ret = CFERROR; \
|
||||
} else { \
|
||||
n = cf_om_add_child(parentp, key); \
|
||||
if (n == -1) \
|
||||
ret = CFERROR; \
|
||||
} \
|
||||
if (key) { \
|
||||
free((char *)key); \
|
||||
key = NULL; \
|
||||
} \
|
||||
if (ret == CFOK) {
|
||||
#define __ARRAY_VALUE(__valuefunc) \
|
||||
cf_om_remove_null_child(parentp, n); \
|
||||
if (ret != CFOK) \
|
||||
WARNF(#__valuefunc "() returned %s", strbuf_str(strbuf_cf_flags(strbuf_alloca(300), ret))); \
|
||||
if (n < (*parentp)->nodc && cf_om_remove_empty_child(parentp, n)) { \
|
||||
WHYF(#__valuefunc "() returned empty node at n=%d", n); \
|
||||
ret = CFERROR; \
|
||||
}
|
||||
#define __ARRAY_TEXT(__valuefunc, __eltexpr) \
|
||||
ret = __valuefunc(&(*parentp)->nodv[n]->text, __eltexpr); \
|
||||
__ARRAY_VALUE(__valuefunc)
|
||||
#define __ARRAY_NODE(__valuefunc, __eltexpr) \
|
||||
ret = __valuefunc(&(*parentp)->nodv[n], __eltexpr); \
|
||||
__ARRAY_VALUE(__valuefunc)
|
||||
#define END_ARRAY(__size) \
|
||||
} \
|
||||
if (ret == CFERROR) \
|
||||
return CFERROR; \
|
||||
else if (ret != CFOK) \
|
||||
result |= (ret & CF__SUBFLAGS) | CFSUB(ret & CF__FLAGS); \
|
||||
} \
|
||||
if ((*parentp)->nodc == 0) \
|
||||
cf_om_free_node(parentp); \
|
||||
return result; \
|
||||
}
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key);
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
__ARRAY_KEY(cf_fmt_##__keyrepr, &array->av[i].key[0]);
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
__ARRAY_TEXT(cf_fmt_##__eltrepr, &array->av[i].value)
|
||||
#define VALUE_STRING(__strsize, __eltrepr) \
|
||||
__ARRAY_TEXT(cf_fmt_##__eltrepr, &array->av[i].value[0])
|
||||
#define VALUE_NODE(__type, __eltrepr) \
|
||||
__ARRAY_NODE(cf_fmt_##__eltrepr, &array->av[i].value)
|
||||
#define VALUE_SUB_STRUCT(__structname) \
|
||||
__ARRAY_NODE(cf_fmt_config_##__structname, &array->av[i].value)
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
||||
__ARRAY_NODE(cf_fmt_##__eltrepr, &array->av[i].value)
|
||||
#include "conf_schema.h"
|
||||
#undef STRUCT
|
||||
#undef NODE
|
||||
#undef ATOM
|
||||
#undef STRING
|
||||
#undef SUB_STRUCT
|
||||
#undef NODE_STRUCT
|
||||
#undef END_STRUCT
|
||||
#undef __FMT_TEXT
|
||||
#undef __FMT_NODE
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#undef VALUE_ATOM
|
||||
#undef VALUE_STRING
|
||||
#undef VALUE_NODE
|
||||
#undef VALUE_SUB_STRUCT
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef __ARRAY_KEY
|
||||
#undef __ARRAY_TEXT
|
||||
#undef __ARRAY_NODE
|
||||
#undef __ARRAY_VALUE
|
||||
#undef END_ARRAY
|
||||
|
||||
// Generate comparison functions, cf_cmp_config_SECTION()
|
||||
#define STRUCT(__name, __validator...) \
|
||||
int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \
|
||||
int c;
|
||||
#define NODE(__type, __element, __default, __repr, __flags, __comment) \
|
||||
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
|
||||
return c;
|
||||
#define ATOM(__type, __element, __default, __repr, __flags, __comment) \
|
||||
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
|
||||
return c;
|
||||
#define STRING(__size, __element, __default, __repr, __flags, __comment) \
|
||||
if ((c = cf_cmp_##__repr(&a->__element[0], &b->__element[0]))) \
|
||||
return c;
|
||||
#define SUB_STRUCT(__structname, __element, __flags) \
|
||||
if ((c = cf_cmp_config_##__structname(&a->__element, &b->__element))) \
|
||||
return c;
|
||||
#define NODE_STRUCT(__structname, __element, __repr, __flags) \
|
||||
if ((c = cf_cmp_##__repr(&a->__element, &b->__element))) \
|
||||
return c;
|
||||
#define END_STRUCT \
|
||||
return 0; \
|
||||
}
|
||||
#define ARRAY(__name, __flags, __validator...) \
|
||||
int cf_cmp_config_##__name(const struct config_##__name *a, const struct config_##__name *b) { \
|
||||
int c; \
|
||||
int i; \
|
||||
for (i = 0; i < a->ac && i < b->ac; ++i) {
|
||||
#define KEY_ATOM(__type, __keyrepr) \
|
||||
if ((c = cf_cmp_##__keyrepr(&a->av[i].key, &b->av[i].key))) \
|
||||
return c;
|
||||
#define KEY_STRING(__strsize, __keyrepr) \
|
||||
if ((c = cf_cmp_##__keyrepr(&a->av[i].key[0], &b->av[i].key[0]))) \
|
||||
return c;
|
||||
#define VALUE_ATOM(__type, __eltrepr) \
|
||||
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
|
||||
return c;
|
||||
#define VALUE_STRING(__strsize, __eltrepr) \
|
||||
if ((c = cf_cmp_##__eltrepr(&a->av[i].value[0], &b->av[i].value[0]))) \
|
||||
return c;
|
||||
#define VALUE_NODE(__type, __eltrepr) \
|
||||
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
|
||||
return c;
|
||||
#define VALUE_SUB_STRUCT(__structname) \
|
||||
if ((c = cf_cmp_config_##__structname(&a->av[i].value, &b->av[i].value))) \
|
||||
return c;
|
||||
#define VALUE_NODE_STRUCT(__structname, __eltrepr) \
|
||||
if ((c = cf_cmp_##__eltrepr(&a->av[i].value, &b->av[i].value))) \
|
||||
return c;
|
||||
#define END_ARRAY(__size) \
|
||||
} \
|
||||
return (a->ac < b->ac) ? -1 : (a->ac > b->ac) ? 1 : 0; \
|
||||
}
|
||||
#include "conf_schema.h"
|
||||
#undef STRUCT
|
||||
#undef NODE
|
||||
#undef ATOM
|
||||
#undef STRING
|
||||
#undef SUB_STRUCT
|
||||
#undef NODE_STRUCT
|
||||
#undef END_STRUCT
|
||||
#undef ARRAY
|
||||
#undef KEY_ATOM
|
||||
#undef KEY_STRING
|
||||
#undef VALUE_ATOM
|
||||
#undef VALUE_STRING
|
||||
#undef VALUE_NODE
|
||||
#undef VALUE_SUB_STRUCT
|
||||
#undef VALUE_NODE_STRUCT
|
||||
#undef END_ARRAY
|
||||
|
422
conf_schema.c
422
conf_schema.c
@ -45,6 +45,24 @@ int cf_opt_char_boolean(char *booleanp, const char *text)
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_fmt_char_boolean(const char **textp, const char *booleanp)
|
||||
{
|
||||
if (*booleanp == 1) {
|
||||
*textp = str_edup("true");
|
||||
return CFOK;
|
||||
}
|
||||
else if (*booleanp == 0) {
|
||||
*textp = str_edup("false");
|
||||
return CFOK;
|
||||
}
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_cmp_char_boolean(const char *a, const char *b)
|
||||
{
|
||||
return !*a && *b ? -1 : *a && !*b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_int_boolean(int *booleanp, const char *text)
|
||||
{
|
||||
char b;
|
||||
@ -54,6 +72,24 @@ int cf_opt_int_boolean(int *booleanp, const char *text)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cf_fmt_int_boolean(const char **textp, const int *booleanp)
|
||||
{
|
||||
if (*booleanp == 1) {
|
||||
*textp = str_edup("true");
|
||||
return CFOK;
|
||||
}
|
||||
else if (*booleanp == 0) {
|
||||
*textp = str_edup("false");
|
||||
return CFOK;
|
||||
}
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_cmp_int_boolean(const int *a, const int *b)
|
||||
{
|
||||
return !*a && *b ? -1 : *a && !*b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_absolute_path(char *str, size_t len, const char *text)
|
||||
{
|
||||
if (text[0] != '/')
|
||||
@ -65,6 +101,19 @@ int cf_opt_absolute_path(char *str, size_t len, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_absolute_path(const char **textp, const char *str)
|
||||
{
|
||||
if (str[0] != '/')
|
||||
return CFINVALID;
|
||||
*textp = str_edup(str);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_absolute_path(const char *a, const char *b)
|
||||
{
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_protocol(char *str, size_t len, const char *text)
|
||||
{
|
||||
if (!str_is_uri_scheme(text))
|
||||
@ -76,6 +125,19 @@ int cf_opt_protocol(char *str, size_t len, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_protocol(const char **textp, const char *str)
|
||||
{
|
||||
if (!str_is_uri_scheme(str))
|
||||
return CFINVALID;
|
||||
*textp = str_edup(str);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_protocol(const char *a, const char *b)
|
||||
{
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_rhizome_peer(struct config_rhizome_peer *rpeer, const struct cf_om_node *node)
|
||||
{
|
||||
if (!node->text)
|
||||
@ -87,6 +149,16 @@ int cf_opt_rhizome_peer(struct config_rhizome_peer *rpeer, const struct cf_om_no
|
||||
return cf_opt_rhizome_peer_from_uri(rpeer, node->text);
|
||||
}
|
||||
|
||||
int cf_fmt_rhizome_peer(struct cf_om_node **parentp, const struct config_rhizome_peer *rpeer)
|
||||
{
|
||||
return cf_fmt_config_rhizome_peer(parentp, rpeer);
|
||||
}
|
||||
|
||||
int cf_cmp_rhizome_peer(const struct config_rhizome_peer *a, const struct config_rhizome_peer *b)
|
||||
{
|
||||
return cf_cmp_config_rhizome_peer(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_rhizome_peer_from_uri(struct config_rhizome_peer *rpeer, const char *text)
|
||||
{
|
||||
const char *protocol;
|
||||
@ -129,6 +201,17 @@ int cf_opt_str(char *str, size_t len, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_str(const char **textp, const char *str)
|
||||
{
|
||||
*textp = str_edup(str);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_str(const char *a, const char *b)
|
||||
{
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_str_nonempty(char *str, size_t len, const char *text)
|
||||
{
|
||||
if (!text[0])
|
||||
@ -136,6 +219,19 @@ int cf_opt_str_nonempty(char *str, size_t len, const char *text)
|
||||
return cf_opt_str(str, len, text);
|
||||
}
|
||||
|
||||
int cf_fmt_str_nonempty(const char **textp, const char *str)
|
||||
{
|
||||
if (!str[0])
|
||||
return CFINVALID;
|
||||
*textp = str_edup(str);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_str_nonempty(const char *a, const char *b)
|
||||
{
|
||||
return strcmp(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_int(int *intp, const char *text)
|
||||
{
|
||||
const char *end = text;
|
||||
@ -146,6 +242,19 @@ int cf_opt_int(int *intp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_int(const char **textp, const int *intp)
|
||||
{
|
||||
char buf[22];
|
||||
sprintf(buf, "%d", *intp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_int(const int *a, const int *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_uint(unsigned int *uintp, const char *text)
|
||||
{
|
||||
const char *end = text;
|
||||
@ -156,6 +265,19 @@ int cf_opt_uint(unsigned int *uintp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_uint(const char **textp, const unsigned int *uintp)
|
||||
{
|
||||
char buf[22];
|
||||
sprintf(buf, "%u", *uintp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_uint(const unsigned int *a, const unsigned int *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_int32_nonneg(int32_t *intp, const char *text)
|
||||
{
|
||||
const char *end = text;
|
||||
@ -166,6 +288,44 @@ int cf_opt_int32_nonneg(int32_t *intp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
static int cf_fmt_int32(const char **textp, const int32_t *intp)
|
||||
{
|
||||
char buf[12];
|
||||
sprintf(buf, "%d", *intp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_int32(const int32_t *a, const int32_t *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
static int cf_fmt_uint32(const char **textp, const uint32_t *uintp)
|
||||
{
|
||||
char buf[12];
|
||||
sprintf(buf, "%u", *uintp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_uint32(const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_fmt_int32_nonneg(const char **textp, const int32_t *intp)
|
||||
{
|
||||
if (*intp < 0)
|
||||
return CFINVALID;
|
||||
return cf_fmt_int32(textp, intp);
|
||||
}
|
||||
|
||||
int cf_cmp_int32_nonneg(const int32_t *a, const int32_t *b)
|
||||
{
|
||||
return cf_cmp_int32(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_uint32_nonzero(uint32_t *intp, const char *text)
|
||||
{
|
||||
const char *end = text;
|
||||
@ -176,6 +336,18 @@ int cf_opt_uint32_nonzero(uint32_t *intp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_uint32_nonzero(const char **textp, const uint32_t *uintp)
|
||||
{
|
||||
if (*uintp == 0)
|
||||
return CFINVALID;
|
||||
return cf_fmt_uint32(textp, uintp);
|
||||
}
|
||||
|
||||
int cf_cmp_uint32_nonzero(const uint32_t *a, const uint32_t *b)
|
||||
{
|
||||
return cf_cmp_uint32(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_uint64_scaled(uint64_t *intp, const char *text)
|
||||
{
|
||||
uint64_t result;
|
||||
@ -186,6 +358,20 @@ int cf_opt_uint64_scaled(uint64_t *intp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_uint64_scaled(const char **textp, const uint64_t *uintp)
|
||||
{
|
||||
char buf[25];
|
||||
int n = uint64_scaled_to_str(buf, sizeof buf, *uintp);
|
||||
assert(n != 0);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_uint64_scaled(const uint64_t *a, const uint64_t *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_ushort_nonzero(unsigned short *ushortp, const char *text)
|
||||
{
|
||||
uint32_t ui;
|
||||
@ -195,19 +381,34 @@ int cf_opt_ushort_nonzero(unsigned short *ushortp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cmp_short(const short *a, const short *b)
|
||||
int cf_fmt_ushort(const char **textp, const unsigned short *ushortp)
|
||||
{
|
||||
char buf[12];
|
||||
sprintf(buf, "%u", (unsigned int) *ushortp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_ushort(const unsigned short *a, const unsigned short *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cmp_ushort(const unsigned short *a, const unsigned short *b)
|
||||
int cf_fmt_ushort_nonzero(const char **textp, const unsigned short *ushortp)
|
||||
{
|
||||
if (*ushortp == 0)
|
||||
return CFINVALID;
|
||||
return cf_fmt_ushort(textp, ushortp);
|
||||
}
|
||||
|
||||
int cf_cmp_short(const short *a, const short *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cmp_sid(const sid_t *a, const sid_t *b)
|
||||
int cf_cmp_ushort_nonzero(const unsigned short *a, const unsigned short *b)
|
||||
{
|
||||
return memcmp(a->binary, b->binary, sizeof a->binary);
|
||||
return cf_cmp_ushort(a, b);
|
||||
}
|
||||
|
||||
int vld_argv(const struct cf_om_node *parent, struct config_argv *array, int result)
|
||||
@ -255,7 +456,18 @@ int cf_opt_in_addr(struct in_addr *addrp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_opt_uint16(uint16_t *intp, const char *text)
|
||||
int cf_fmt_in_addr(const char **textp, const struct in_addr *addrp)
|
||||
{
|
||||
*textp = str_edup(inet_ntoa(*addrp));
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_in_addr(const struct in_addr *a, const struct in_addr *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(struct in_addr));
|
||||
}
|
||||
|
||||
int cf_opt_uint16(uint16_t *uintp, const char *text)
|
||||
{
|
||||
uint16_t ui = 0;
|
||||
const char *p;
|
||||
@ -267,19 +479,44 @@ int cf_opt_uint16(uint16_t *intp, const char *text)
|
||||
}
|
||||
if (*p)
|
||||
return CFINVALID;
|
||||
*intp = ui;
|
||||
*uintp = ui;
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_opt_uint16_nonzero(uint16_t *intp, const char *text)
|
||||
int cf_fmt_uint16(const char **textp, const uint16_t *uintp)
|
||||
{
|
||||
char buf[12];
|
||||
sprintf(buf, "%u", (unsigned int) *uintp);
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_uint16(const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_uint16_nonzero(uint16_t *uintp, const char *text)
|
||||
{
|
||||
uint16_t ui;
|
||||
if (cf_opt_uint16(&ui, text) != CFOK || ui == 0)
|
||||
return CFINVALID;
|
||||
*intp = ui;
|
||||
*uintp = ui;
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_uint16_nonzero(const char **textp, const uint16_t *uintp)
|
||||
{
|
||||
if (*uintp == 0)
|
||||
return CFINVALID;
|
||||
return cf_fmt_uint16(textp, uintp);
|
||||
}
|
||||
|
||||
int cf_cmp_uint16_nonzero(const uint16_t *a, const uint16_t *b)
|
||||
{
|
||||
return cf_cmp_uint16(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_sid(sid_t *sidp, const char *text)
|
||||
{
|
||||
if (!str_is_subscriber_id(text))
|
||||
@ -289,6 +526,17 @@ int cf_opt_sid(sid_t *sidp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_sid(const char **textp, const sid_t *sidp)
|
||||
{
|
||||
*textp = str_edup(alloca_tohex_sid_t(*sidp));
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_sid(const sid_t *a, const sid_t *b)
|
||||
{
|
||||
return memcmp(a->binary, b->binary, sizeof a->binary);
|
||||
}
|
||||
|
||||
int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text)
|
||||
{
|
||||
if (!rhizome_str_is_bundle_key(text))
|
||||
@ -298,6 +546,17 @@ int cf_opt_rhizome_bk(rhizome_bk_t *bkp, const char *text)
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_rhizome_bk(const char **textp, const rhizome_bk_t *bkp)
|
||||
{
|
||||
*textp = str_edup(alloca_tohex_rhizome_bk_t(*bkp));
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_rhizome_bk(const rhizome_bk_t *a, const rhizome_bk_t *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof a->binary);
|
||||
}
|
||||
|
||||
int cf_opt_interface_type(short *typep, const char *text)
|
||||
{
|
||||
if (strcasecmp(text, "ethernet") == 0) {
|
||||
@ -319,7 +578,27 @@ int cf_opt_interface_type(short *typep, const char *text)
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_opt_socket_type(int *typep, const char *text)
|
||||
int cf_fmt_interface_type(const char **textp, const short *typep)
|
||||
{
|
||||
const char *t = NULL;
|
||||
switch (*typep) {
|
||||
case OVERLAY_INTERFACE_ETHERNET: t = "ethernet"; break;
|
||||
case OVERLAY_INTERFACE_WIFI: t = "wifi"; break;
|
||||
case OVERLAY_INTERFACE_PACKETRADIO: t = "catear"; break;
|
||||
case OVERLAY_INTERFACE_UNKNOWN: t = "other"; break;
|
||||
}
|
||||
if (!t)
|
||||
return CFINVALID;
|
||||
*textp = str_edup(t);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_interface_type(const short *a, const short *b)
|
||||
{
|
||||
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
||||
}
|
||||
|
||||
int cf_opt_socket_type(short *typep, const char *text)
|
||||
{
|
||||
if (strcasecmp(text, "dgram") == 0) {
|
||||
*typep = SOCK_DGRAM;
|
||||
@ -336,19 +615,56 @@ int cf_opt_socket_type(int *typep, const char *text)
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_opt_encapsulation(int *typep, const char *text)
|
||||
int cf_fmt_socket_type(const char **textp, const short *typep)
|
||||
{
|
||||
const char *t = NULL;
|
||||
switch (*typep) {
|
||||
case SOCK_DGRAM: t = "dgram"; break;
|
||||
case SOCK_STREAM: t = "stream"; break;
|
||||
case SOCK_FILE: t = "file"; break;
|
||||
}
|
||||
if (!t)
|
||||
return CFINVALID;
|
||||
*textp = str_edup(t);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_socket_type(const short *a, const short *b)
|
||||
{
|
||||
return cf_cmp_short(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_encapsulation(short *encapp, const char *text)
|
||||
{
|
||||
if (strcasecmp(text, "overlay") == 0) {
|
||||
*typep = ENCAP_OVERLAY;
|
||||
*encapp = ENCAP_OVERLAY;
|
||||
return CFOK;
|
||||
}
|
||||
if (strcasecmp(text, "single") == 0) {
|
||||
*typep = ENCAP_SINGLE;
|
||||
*encapp = ENCAP_SINGLE;
|
||||
return CFOK;
|
||||
}
|
||||
return CFINVALID;
|
||||
}
|
||||
|
||||
int cf_fmt_encapsulation(const char **textp, const short *encapp)
|
||||
{
|
||||
const char *t = NULL;
|
||||
switch (*encapp) {
|
||||
case ENCAP_OVERLAY: t = "overlay"; break;
|
||||
case ENCAP_SINGLE: t = "single"; break;
|
||||
}
|
||||
if (!t)
|
||||
return CFINVALID;
|
||||
*textp = str_edup(t);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_encapsulation(const short *a, const short *b)
|
||||
{
|
||||
return cf_cmp_short(a, b);
|
||||
}
|
||||
|
||||
int cf_opt_pattern_list(struct pattern_list *listp, const char *text)
|
||||
{
|
||||
struct pattern_list list;
|
||||
@ -370,10 +686,46 @@ int cf_opt_pattern_list(struct pattern_list *listp, const char *text)
|
||||
word = p;
|
||||
}
|
||||
assert(word == NULL);
|
||||
if (list.patc == 0)
|
||||
return CFEMPTY;
|
||||
*listp = list;
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_fmt_pattern_list(const char **textp, const struct pattern_list *listp)
|
||||
{
|
||||
if (listp->patc == 0)
|
||||
return CFEMPTY;
|
||||
char buf[sizeof listp->patv];
|
||||
char *bufp = buf;
|
||||
unsigned i;
|
||||
for (i = 0; i < listp->patc; ++i) {
|
||||
if (bufp != buf)
|
||||
*bufp++ = ',';
|
||||
const char *patvp = listp->patv[i];
|
||||
const char *npatvp = listp->patv[i + 1];
|
||||
while (bufp < &buf[sizeof buf - 1] && patvp < npatvp && (*bufp = *patvp))
|
||||
++bufp, ++patvp;
|
||||
if (patvp >= npatvp)
|
||||
return CFINVALID;
|
||||
assert(bufp < &buf[sizeof buf - 1]);
|
||||
}
|
||||
*bufp = '\0';
|
||||
DEBUGF("buf=%s", alloca_toprint(-1, buf, sizeof buf));
|
||||
*textp = str_edup(buf);
|
||||
return CFOK;
|
||||
}
|
||||
|
||||
int cf_cmp_pattern_list(const struct pattern_list *a, const struct pattern_list *b)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < a->patc && i < b->patc; ++i) {
|
||||
int c = strcmp(a->patv[i], b->patv[i]);
|
||||
if (c)
|
||||
return c;
|
||||
}
|
||||
return (a->patc < b->patc) ? -1 : (a->patc > b->patc) ? 1 : 0;
|
||||
}
|
||||
|
||||
/* Config parse function. Implements the original form of the 'interfaces' config option. Parses a
|
||||
* single text string of the form:
|
||||
@ -427,11 +779,11 @@ static int cf_opt_network_interface_legacy(struct config_network_interface *nifp
|
||||
nif.match.patc = 0;
|
||||
nif.socket_type = SOCK_FILE;
|
||||
} else {
|
||||
int star = (strchr(name, '*') != NULL) ? 1 : 0;
|
||||
if (len + star >= sizeof(nif.match.patv[0]))
|
||||
int addstar = strnchr(name, len, '*') == NULL ? 1 : 0;
|
||||
if (len + addstar >= sizeof(nif.match.patv[0]))
|
||||
return CFSTRINGOVERFLOW;
|
||||
strncpy(nif.match.patv[0], name, len)[len + star] = '\0';
|
||||
if (star)
|
||||
strncpy(nif.match.patv[0], name, len)[len + addstar] = '\0';
|
||||
if (addstar)
|
||||
nif.match.patv[0][len] = '*';
|
||||
nif.match.patc = 1;
|
||||
nif.socket_type = SOCK_DGRAM;
|
||||
@ -490,6 +842,16 @@ int cf_opt_network_interface(struct config_network_interface *nifp, const struct
|
||||
return cf_opt_network_interface_legacy(nifp, node->text);
|
||||
}
|
||||
|
||||
int cf_fmt_network_interface(struct cf_om_node **parentp, const struct config_network_interface *nifp)
|
||||
{
|
||||
return cf_fmt_config_network_interface(parentp, nifp);
|
||||
}
|
||||
|
||||
int cf_cmp_network_interface(const struct config_network_interface *a, const struct config_network_interface *b)
|
||||
{
|
||||
return cf_cmp_config_network_interface(a, b);
|
||||
}
|
||||
|
||||
int vld_network_interface(const struct cf_om_node *parent, struct config_network_interface *nifp, int result)
|
||||
{
|
||||
if (nifp->match.patc != 0 && nifp->file[0]) {
|
||||
@ -500,19 +862,17 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
|
||||
cf_warn_incompatible(parent->nodv[nodei_match], parent->nodv[nodei_file]);
|
||||
return result | CFSUB(CFINCOMPATIBLE);
|
||||
}
|
||||
|
||||
if (nifp->socket_type == SOCK_UNSPECIFIED){
|
||||
if (nifp->socket_type == SOCK_UNSPECIFIED) {
|
||||
if (nifp->match.patc != 0)
|
||||
nifp->socket_type=SOCK_DGRAM;
|
||||
nifp->socket_type = SOCK_DGRAM;
|
||||
else if (nifp->file[0])
|
||||
nifp->socket_type=SOCK_FILE;
|
||||
else{
|
||||
nifp->socket_type = SOCK_FILE;
|
||||
else {
|
||||
cf_warn_missing_node(parent, "match");
|
||||
return result | CFINCOMPLETE;
|
||||
}
|
||||
}else{
|
||||
|
||||
if (nifp->socket_type==SOCK_DGRAM && nifp->file[0]){
|
||||
} else {
|
||||
if (nifp->socket_type == SOCK_DGRAM && nifp->file[0]){
|
||||
int nodei_socket_type = cf_om_get_child(parent, "socket_type", NULL);
|
||||
int nodei_file = cf_om_get_child(parent, "file", NULL);
|
||||
assert(nodei_socket_type != -1);
|
||||
@ -520,13 +880,11 @@ int vld_network_interface(const struct cf_om_node *parent, struct config_network
|
||||
cf_warn_incompatible(parent->nodv[nodei_socket_type], parent->nodv[nodei_file]);
|
||||
return result | CFSUB(CFINCOMPATIBLE);
|
||||
}
|
||||
|
||||
if (nifp->socket_type!=SOCK_DGRAM && !nifp->file[0]){
|
||||
if (nifp->socket_type != SOCK_DGRAM && !nifp->file[0]){
|
||||
cf_warn_missing_node(parent, "file");
|
||||
return result | CFSUB(CFINCOMPATIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -592,3 +950,13 @@ bye:
|
||||
result |= CFEMPTY;
|
||||
return result;
|
||||
}
|
||||
|
||||
int cf_fmt_interface_list(struct cf_om_node **parentp, const struct config_interface_list *listp)
|
||||
{
|
||||
return cf_fmt_config_interface_list(parentp, listp);
|
||||
}
|
||||
|
||||
int cf_cmp_interface_list(const struct config_interface_list *a, const struct config_interface_list *b)
|
||||
{
|
||||
return cf_cmp_config_interface_list(a, b);
|
||||
}
|
||||
|
@ -46,7 +46,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* the following schema would do:
|
||||
*
|
||||
* STRUCT(happy)
|
||||
* ATOM(int32_t, element1, 0, int32_nonnegative,, "An integer >= 0")
|
||||
* ATOM(int32_t, element1, 0, int32_nonneg,, "An integer >= 0")
|
||||
* STRING(80, element2, "boo!", str_nonempty, MANDATORY, "A non-empty string")
|
||||
* END_STRUCT
|
||||
*
|
||||
@ -111,8 +111,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* where key-declaration is one of:
|
||||
*
|
||||
* KEY_ATOM(type, repr[, comparefunc])
|
||||
* KEY_STRING(strlen, repr[, comparefunc])
|
||||
* KEY_ATOM(type, repr)
|
||||
* KEY_STRING(strlen, repr)
|
||||
*
|
||||
* and value-declaration is one of:
|
||||
*
|
||||
@ -149,24 +149,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
* Only used for ATOM and NODE struct elements. Gives the default value for the element if
|
||||
* absent from the config file.
|
||||
* 'repr'
|
||||
* The string representation. This name specifies a pair of functions, <repr> and
|
||||
* cf_fmt_<repr> that convert the given 'type' from and to a string respectively:
|
||||
* - The <repr> functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
|
||||
* The string representation. This name specifies a trio of functions, cf_opt_<repr>(),
|
||||
* cf_fmt_<repr>() and cf_cmp_<repr>():
|
||||
* - The cf_opt_<repr>() functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and
|
||||
* VALUE_STRING take a (const char *) argument pointing to nul-terminated text. The
|
||||
* <repr> functions for NODE and VALUE_NODE take a pointer to a COM node (const
|
||||
* struct cf_om_node *), and are responsible for parsing the node's text and all of its
|
||||
* descendents (children).
|
||||
* - Each cf_fmt_<repr> function is the inverse of <repr>. The cf_fmt_<repr>
|
||||
* functions for ATOM, STRING, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a
|
||||
* pointer to a const 'type', and return a malloc()ed nul-terminated string which, if passed
|
||||
* to <repr>(), would produce the same original value. If the value is invalid
|
||||
* (outside the legal range) or malloc() fails, then cf_fmt_<repr> returns NULL. The
|
||||
* cf_fmt_<repr> functions for NODE and VALUE_NODE take a pointer to a const 'type' and
|
||||
* return a pointer to a malloc()ed COM node (struct cf_om_node *) which, if passed to
|
||||
* <repr> would produce the same original value.
|
||||
* 'comparefunc'
|
||||
* A function used to sort an array after all elements have been parsed, and before being
|
||||
* validated (see below).
|
||||
* - Each cf_fmt_<repr>() function is the inverse of cf_opt_<repr>. The cf_fmt_<repr>
|
||||
* functions for ATOM, KEY_ATOM, KEY_STRING, VALUE_ATOM and VALUE_STRING all take a pointer
|
||||
* to a const 'type', and produce a malloc()ed nul-terminated string which, if passed to
|
||||
* cf_opt_<repr>(), would produce the same original value. If the value is invalid (outside
|
||||
* the legal range) then cf_fmt_<repr> returns CFINVALID or CFEMPTY. The cf_fmt_<repr>
|
||||
* functions for NODE and VALUE_NODE take a pointer to a const 'type' and produce a
|
||||
* malloc()ed COM node (struct cf_om_node *) which, if passed to cf_opt_<repr> would produce
|
||||
* the same original value.
|
||||
* - Each cf_cmp_<repr>() function compares two values of the given 'type' and returns -1, 0
|
||||
* or 1 to indicate the natural ordering of the values. These functions are used to detect
|
||||
* when config elements have their default values, to avoid calling cf_fmt_<repr>(). They
|
||||
* are also used to sort array keys.
|
||||
* 'validatorfunc'
|
||||
* A function that is called after the struct/array is fully parsed and populated. This
|
||||
* function can perform validation checks on the whole struct/array that cannot be performed by
|
||||
@ -239,16 +240,16 @@ END_STRUCT
|
||||
|
||||
STRUCT(monitor)
|
||||
STRING(256, socket, DEFAULT_MONITOR_SOCKET_NAME, str_nonempty,, "Name of socket for monitor interface")
|
||||
ATOM(int, uid, -1, int,, "Allowed UID for monitor socket client")
|
||||
ATOM(uint32_t, uid, 0, uint32_nonzero,, "Allowed UID for monitor socket client")
|
||||
END_STRUCT
|
||||
|
||||
STRUCT(mdp_iftype)
|
||||
ATOM(uint32_t, tick_ms, -1, uint32_nonzero,, "Tick interval for this interface type")
|
||||
ATOM(int, packet_interval, -1, int,, "Minimum interval between packets in microseconds")
|
||||
ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interval between packets in microseconds")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(mdp_iftypelist, NO_DUPLICATES)
|
||||
KEY_ATOM(short, interface_type, cmp_short)
|
||||
KEY_ATOM(short, interface_type)
|
||||
VALUE_SUB_STRUCT(mdp_iftype)
|
||||
END_ARRAY(5)
|
||||
|
||||
@ -263,8 +264,8 @@ ATOM(uint16_t, remote_port,4130, uint16_nonzero,, "Remote port numb
|
||||
ATOM(uint16_t, local_port, 4131, uint16_nonzero,, "Local port number")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(argv, SORTED NO_DUPLICATES, vld_argv)
|
||||
KEY_ATOM(unsigned short, ushort_nonzero, cmp_ushort)
|
||||
ARRAY(argv, NO_DUPLICATES, vld_argv)
|
||||
KEY_ATOM(unsigned short, ushort_nonzero)
|
||||
VALUE_STRING(128, str)
|
||||
END_ARRAY(16)
|
||||
|
||||
@ -346,15 +347,15 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number"
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(host_list, NO_DUPLICATES)
|
||||
KEY_ATOM(sid_t, sid, cmp_sid)
|
||||
KEY_ATOM(sid_t, sid)
|
||||
VALUE_SUB_STRUCT(host)
|
||||
END_ARRAY(32)
|
||||
|
||||
STRUCT(network_interface, vld_network_interface)
|
||||
ATOM(int, exclude, 0, int_boolean,, "If true, do not use matching interfaces")
|
||||
ATOM(struct pattern_list, match, PATTERN_LIST_EMPTY, pattern_list,, "Names that match network interface")
|
||||
ATOM(int, socket_type, SOCK_UNSPECIFIED, socket_type,, "Type of network socket")
|
||||
ATOM(int, encapsulation, ENCAP_OVERLAY, encapsulation,, "Type of packet encapsulation")
|
||||
ATOM(short, socket_type, SOCK_UNSPECIFIED, socket_type,, "Type of network socket")
|
||||
ATOM(short, encapsulation, ENCAP_OVERLAY, encapsulation,, "Type of packet encapsulation")
|
||||
STRING(256, file, "", str_nonempty,, "Path of interface file, absolute or relative to server.interface_path")
|
||||
ATOM(struct in_addr, dummy_address, hton_in_addr(INADDR_LOOPBACK), in_addr,, "Dummy interface address")
|
||||
ATOM(struct in_addr, dummy_netmask, hton_in_addr(0xFFFFFF00), in_addr,, "Dummy interface netmask")
|
||||
@ -362,14 +363,14 @@ ATOM(uint16_t, port, PORT_DNA, uint16_nonzero,, "Port number
|
||||
ATOM(char, drop_broadcasts, 0, char_boolean,, "If true, drop all incoming broadcast packets")
|
||||
ATOM(char, drop_unicasts, 0, char_boolean,, "If true, drop all incoming unicast packets")
|
||||
ATOM(short, type, OVERLAY_INTERFACE_WIFI, interface_type,, "Type of network interface")
|
||||
ATOM(int, packet_interval, -1, int,, "Minimum interval between packets in microseconds")
|
||||
ATOM(int, mdp_tick_ms, -1, int32_nonneg,, "Override MDP tick interval for this interface")
|
||||
ATOM(int32_t, packet_interval, -1, int32_nonneg,, "Minimum interval between packets in microseconds")
|
||||
ATOM(int32_t, mdp_tick_ms, -1, int32_nonneg,, "Override MDP tick interval for this interface")
|
||||
ATOM(char, send_broadcasts, 1, char_boolean,, "If false, don't send any broadcast packets")
|
||||
ATOM(char, default_route, 0, char_boolean,, "If true, use this interface as a default route")
|
||||
ATOM(char, prefer_unicast, 0, char_boolean,, "If true, send unicast data as unicast IP packets if available")
|
||||
END_STRUCT
|
||||
|
||||
ARRAY(interface_list, SORTED NO_DUPLICATES)
|
||||
ARRAY(interface_list, NO_DUPLICATES)
|
||||
KEY_ATOM(unsigned, uint)
|
||||
VALUE_NODE_STRUCT(network_interface, network_interface)
|
||||
END_ARRAY(10)
|
||||
|
@ -61,6 +61,8 @@ __RHIZOME_INLINE int rhizome_is_bk_none(const rhizome_bk_t *bk) {
|
||||
return is_all_matching(bk->binary, sizeof bk->binary, 0);
|
||||
}
|
||||
|
||||
#define alloca_tohex_rhizome_bk_t(bk) alloca_tohex((bk).binary, sizeof (*(rhizome_bk_t*)0).binary)
|
||||
|
||||
extern time_ms_t rhizome_voice_timeout;
|
||||
|
||||
#define RHIZOME_PRIORITY_HIGHEST RHIZOME_PRIORITY_SERVAL_CORE
|
||||
|
11
str.c
11
str.c
@ -88,6 +88,17 @@ char *str_toupper_inplace(char *str)
|
||||
return str;
|
||||
}
|
||||
|
||||
const char *strnchr(const char *s, size_t n, char c)
|
||||
{
|
||||
for (; n; --n, ++s) {
|
||||
if (*s == c)
|
||||
return s;
|
||||
if (!*s)
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int str_startswith(const char *str, const char *substring, const char **afterp)
|
||||
{
|
||||
while (*substring && *substring == *str)
|
||||
|
7
str.h
7
str.h
@ -86,6 +86,13 @@ size_t str_fromprint(unsigned char *dst, const char *src);
|
||||
#define alloca_toprint(dstlen,buf,len) toprint((char *)alloca((dstlen) == -1 ? toprint_len((const char *)(buf),(len), "``") + 1 : (dstlen)), (dstlen), (const char *)(buf), (len), "``")
|
||||
#define alloca_str_toprint(str) toprint_str((char *)alloca(toprint_str_len(str, "``") + 1), -1, (str), "``")
|
||||
|
||||
/* Like strchr(3), but only looks for 'c' in the first 'n' characters of 's', stopping at the first
|
||||
* nul char in 's'.
|
||||
*
|
||||
* @author Andrew Bettison <andrew@servalproject.com>
|
||||
*/
|
||||
const char *strnchr(const char *s, size_t n, char c);
|
||||
|
||||
/* Check if a given nul-terminated string 'str' starts with a given nul-terminated sub-string. If
|
||||
* so, return 1 and, if afterp is not NULL, set *afterp to point to the character in 'str'
|
||||
* immediately following the substring. Otherwise return 0.
|
||||
|
Loading…
Reference in New Issue
Block a user