diff --git a/commandline.c b/commandline.c index c253dfbb..c66358bf 100644 --- a/commandline.c +++ b/commandline.c @@ -923,6 +923,25 @@ int app_mdp_ping(int argc, const char *const *argv, const struct command_line_op return ret; } +int app_config_schema(int argc, const char *const *argv, const struct command_line_option *o, void *context) +{ + if (debug & DEBUG_VERBOSE) DEBUG_argv("command", argc, argv); + if (create_serval_instance_dir() == -1) + return -1; + struct cf_om_node *root = NULL; + if (cf_sch_config_main(&root) == -1) + 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) { + cli_puts(it.node->fullkey); + cli_delim("="); + cli_puts(it.node->text); + cli_delim("\n"); + } + return 0; +} + int app_config_set(int argc, const char *const *argv, const struct command_line_option *o, void *context) { if (debug & DEBUG_VERBOSE) DEBUG_argv("command", argc, argv); @@ -1910,6 +1929,8 @@ struct command_line_option command_line_options[]={ "Display information about any running Serval Mesh node."}, {app_mdp_ping,{"mdp","ping","","[]",NULL},CLIFLAG_STANDALONE, "Attempts to ping specified node via Mesh Datagram Protocol (MDP)."}, + {app_config_schema,{"config","schema",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG, + "Dump configuration schema."}, {app_config_set,{"config","set","","","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG, "Set and del specified configuration variables."}, {app_config_set,{"config","del","","...",NULL},CLIFLAG_STANDALONE|CLIFLAG_PERMISSIVE_CONFIG, diff --git a/conf.h b/conf.h index a8fdc90b..b2bdd545 100644 --- a/conf.h +++ b/conf.h @@ -236,6 +236,7 @@ int cf_om_parse(const char *source, const char *buf, size_t len, struct cf_om_no int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char *keyend); 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); void cf_om_free_node(struct cf_om_node **nodep); void cf_om_dump_node(const struct cf_om_node *node, int indent); @@ -351,9 +352,10 @@ struct pattern_list { #undef VALUE_NODE_STRUCT #undef END_ARRAY -// Generate config set-default function prototypes, cf_dfl_config_NAME(). +// Generate config function prototypes, cf_dfl_config_NAME(), cf_sch_config_NAME(). #define STRUCT(__name, __validator...) \ - int cf_dfl_config_##__name(struct config_##__name *s); + int cf_dfl_config_##__name(struct config_##__name *s); \ + int cf_sch_config_##__name(struct cf_om_node **parentp); #define NODE(__type, __element, __default, __parser, __flags, __comment) #define ATOM(__type, __element, __default, __parser, __flags, __comment) #define STRING(__size, __element, __default, __parser, __flags, __comment) @@ -361,7 +363,8 @@ struct pattern_list { #define NODE_STRUCT(__name, __element, __parser, __flags) #define END_STRUCT #define ARRAY(__name, __flags, __validator...) \ - int cf_dfl_config_##__name(struct config_##__name *a); + int cf_dfl_config_##__name(struct config_##__name *a); \ + int cf_sch_config_##__name(struct cf_om_node **parentp); #define KEY_ATOM(__type, __eltparser, __cmpfunc...) #define KEY_STRING(__strsize, __eltparser, __cmpfunc...) #define VALUE_ATOM(__type, __eltparser) diff --git a/conf_om.c b/conf_om.c index 7b655381..e54b37d6 100644 --- a/conf_om.c +++ b/conf_om.c @@ -123,6 +123,21 @@ static int cf_om_make_child(struct cf_om_node **const parentp, const char *const return i; } +int cf_om_add_child(struct cf_om_node **const parentp, const char *const key) +{ + size_t parent_fullkey_len = (parentp && *parentp && (*parentp)->fullkey) ? strlen((*parentp)->fullkey) : 0; + size_t fullkey_len = parent_fullkey_len + 1 + strlen(key); + char fullkey[fullkey_len + 1]; + char *pkey = fullkey; + if (parent_fullkey_len) { + strcpy(fullkey, (*parentp)->fullkey); + pkey = fullkey + parent_fullkey_len; + *pkey++ = '.'; + } + strcpy(pkey, key); + return cf_om_make_child(parentp, fullkey, pkey, fullkey + fullkey_len); +} + int cf_om_get_child(const struct cf_om_node *parent, const char *key, const char *keyend) { if (keyend == NULL) diff --git a/conf_parse.c b/conf_parse.c index 36e4bf3a..c73df4b6 100644 --- a/conf_parse.c +++ b/conf_parse.c @@ -331,3 +331,78 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #undef VALUE_NODE_STRUCT #undef END_ARRAY +// Generate config schema dump functions, cf_sch_config_NAME(). +#define STRUCT(__name, __validator...) \ + int cf_sch_config_##__name(struct cf_om_node **rootp) { \ + int i; \ + struct cf_om_node **childp; +#define __ADD_CHILD(__elementstr) \ + if ((i = cf_om_add_child(rootp, __elementstr)) == -1) \ + return -1; \ + childp = &(*rootp)->nodv[i]; +#define __ATOM(__text) \ + if (((*childp)->text = str_edup(__text)) == NULL) \ + return -1; +#define __STRUCT(__structname) \ + if (cf_sch_config_##__structname(childp) == -1) \ + return -1; +#define NODE(__type, __element, __default, __parser, __flags, __comment) \ + __ADD_CHILD(#__element) \ + __ATOM("[" #__parser "]") +#define ATOM(__type, __element, __default, __parser, __flags, __comment) \ + __ADD_CHILD(#__element) \ + __ATOM("[" #__parser "]") +#define STRING(__size, __element, __default, __parser, __flags, __comment) \ + __ADD_CHILD(#__element) \ + __ATOM("[" #__parser "]") +#define SUB_STRUCT(__structname, __element, __flags) \ + __ADD_CHILD(#__element) \ + __STRUCT(__structname) +#define NODE_STRUCT(__structname, __element, __parser, __flags) \ + __ADD_CHILD(#__element) \ + __STRUCT(__structname) +#define END_STRUCT \ + return 0; \ + } +#define ARRAY(__name, __flags, __validator...) \ + int cf_sch_config_##__name(struct cf_om_node **rootp) { \ + int i; \ + struct cf_om_node **childp; +#define KEY_ATOM(__type, __eltparser, __cmpfunc...) \ + __ADD_CHILD("[" #__eltparser "]") +#define KEY_STRING(__strsize, __eltparser, __cmpfunc...) \ + __ADD_CHILD("[" #__eltparser "]") +#define VALUE_ATOM(__type, __eltparser) \ + __ATOM("[" #__eltparser "]") +#define VALUE_STRING(__strsize, __eltparser) \ + __ATOM("[" #__eltparser "]") +#define VALUE_NODE(__type, __eltparser) \ + __ATOM("[" #__eltparser "]") +#define VALUE_SUB_STRUCT(__structname) \ + __STRUCT(__structname) +#define VALUE_NODE_STRUCT(__structname, __eltparser) \ + __STRUCT(__structname) +#define END_ARRAY(__size) \ + return 0; \ + } +#include "conf_schema.h" +#undef __ADD_CHILD +#undef __ATOM +#undef __STRUCT +#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 +