diff --git a/usr.sbin/bhyve/config.h b/usr.sbin/bhyve/config.h --- a/usr.sbin/bhyve/config.h +++ b/usr.sbin/bhyve/config.h @@ -45,6 +45,16 @@ * OIDs. */ +/* + * Recursively walk the nodes under a parent nvlist. For each node that + * itself references a nvlist, the name of the node is appended to the + * prefix for the recursive call. For nodes representing a configuration + * variable, call the given callback function passing the current prefix, + * name and value of the variable, and the given argument. + */ +void walk_config_nodes(const char *prefix, const nvlist_t *parent, void *arg, + void (*cb)(const char *p, const char *n, const char *v, void *a)); + /* * Fetches the value of a configuration variable. If the "raw" value * contains references to other configuration variables, this function diff --git a/usr.sbin/bhyve/config.c b/usr.sbin/bhyve/config.c --- a/usr.sbin/bhyve/config.c +++ b/usr.sbin/bhyve/config.c @@ -434,31 +434,38 @@ set_config_value_node(parent, name, value ? "true" : "false"); } -static void -dump_tree(const char *prefix, const nvlist_t *nvl) +void +walk_config_nodes(const char *prefix, const nvlist_t *parent, void *arg, + void (*cb)(const char *p, const char *n, const char *v, void *a)) { + void *cookie = NULL; const char *name; - void *cookie; int type; - cookie = NULL; - while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) { + while ((name = nvlist_next(parent, &type, &cookie)) != NULL) { if (type == NV_TYPE_NVLIST) { char *new_prefix; asprintf(&new_prefix, "%s%s.", prefix, name); - dump_tree(new_prefix, nvlist_get_nvlist(nvl, name)); + walk_config_nodes(new_prefix, + nvlist_get_nvlist(parent, name), arg, cb); free(new_prefix); } else { assert(type == NV_TYPE_STRING); - printf("%s%s=%s\n", prefix, name, - nvlist_get_string(nvl, name)); + cb(prefix, name, nvlist_get_string(parent, name), arg); } } } +static void +dump_node_cb(const char *prefix, const char *name, const char *value, + void *arg __unused) +{ + printf("%s%s=%s\n", prefix, name, value); +} + void dump_config(void) { - dump_tree("", config_root); + walk_config_nodes("", config_root, NULL, dump_node_cb); }