12b948146SAndy Fiddaman /*-
2*32640292SAndy Fiddaman * SPDX-License-Identifier: BSD-2-Clause
32b948146SAndy Fiddaman *
42b948146SAndy Fiddaman * Copyright (c) 2021 John H. Baldwin <jhb@FreeBSD.org>
52b948146SAndy Fiddaman *
62b948146SAndy Fiddaman * Redistribution and use in source and binary forms, with or without
72b948146SAndy Fiddaman * modification, are permitted provided that the following conditions
82b948146SAndy Fiddaman * are met:
92b948146SAndy Fiddaman * 1. Redistributions of source code must retain the above copyright
102b948146SAndy Fiddaman * notice, this list of conditions and the following disclaimer.
112b948146SAndy Fiddaman * 2. Redistributions in binary form must reproduce the above copyright
122b948146SAndy Fiddaman * notice, this list of conditions and the following disclaimer in the
132b948146SAndy Fiddaman * documentation and/or other materials provided with the distribution.
142b948146SAndy Fiddaman *
152b948146SAndy Fiddaman * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
162b948146SAndy Fiddaman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
172b948146SAndy Fiddaman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
182b948146SAndy Fiddaman * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
192b948146SAndy Fiddaman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
202b948146SAndy Fiddaman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
212b948146SAndy Fiddaman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
222b948146SAndy Fiddaman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
232b948146SAndy Fiddaman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
242b948146SAndy Fiddaman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
252b948146SAndy Fiddaman * SUCH DAMAGE.
262b948146SAndy Fiddaman */
272b948146SAndy Fiddaman
282b948146SAndy Fiddaman #include <sys/cdefs.h>
292b948146SAndy Fiddaman
302b948146SAndy Fiddaman #include <assert.h>
312b948146SAndy Fiddaman #include <err.h>
322b948146SAndy Fiddaman #include <stdio.h>
332b948146SAndy Fiddaman #include <stdlib.h>
342b948146SAndy Fiddaman #include <string.h>
3559d65d31SAndy Fiddaman #ifndef __FreeBSD__
3659d65d31SAndy Fiddaman #include <sys/sysmacros.h>
3759d65d31SAndy Fiddaman #endif
382b948146SAndy Fiddaman
392b948146SAndy Fiddaman #include "config.h"
402b948146SAndy Fiddaman
412b948146SAndy Fiddaman static nvlist_t *config_root;
422b948146SAndy Fiddaman
432b948146SAndy Fiddaman void
init_config(void)442b948146SAndy Fiddaman init_config(void)
452b948146SAndy Fiddaman {
462b948146SAndy Fiddaman config_root = nvlist_create(0);
472b948146SAndy Fiddaman if (config_root == NULL)
482b948146SAndy Fiddaman err(4, "Failed to create configuration root nvlist");
492b948146SAndy Fiddaman }
502b948146SAndy Fiddaman
512b948146SAndy Fiddaman static nvlist_t *
_lookup_config_node(nvlist_t * parent,const char * path,bool create)522b948146SAndy Fiddaman _lookup_config_node(nvlist_t *parent, const char *path, bool create)
532b948146SAndy Fiddaman {
542b948146SAndy Fiddaman char *copy, *name, *tofree;
552b948146SAndy Fiddaman nvlist_t *nvl, *new_nvl;
562b948146SAndy Fiddaman
572b948146SAndy Fiddaman copy = strdup(path);
582b948146SAndy Fiddaman if (copy == NULL)
592b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
602b948146SAndy Fiddaman tofree = copy;
612b948146SAndy Fiddaman nvl = parent;
622b948146SAndy Fiddaman while ((name = strsep(©, ".")) != NULL) {
632b948146SAndy Fiddaman if (*name == '\0') {
642b948146SAndy Fiddaman warnx("Invalid configuration node: %s", path);
652b948146SAndy Fiddaman nvl = NULL;
662b948146SAndy Fiddaman break;
672b948146SAndy Fiddaman }
682b948146SAndy Fiddaman if (nvlist_exists_nvlist(nvl, name))
6959d65d31SAndy Fiddaman /*
7059d65d31SAndy Fiddaman * XXX-MJ it is incorrect to cast away the const
7159d65d31SAndy Fiddaman * qualifier like this since the contract with nvlist
7259d65d31SAndy Fiddaman * says that values are immutable, and some consumers
7359d65d31SAndy Fiddaman * will indeed add nodes to the returned nvlist. In
7459d65d31SAndy Fiddaman * practice, however, it appears to be harmless with the
7559d65d31SAndy Fiddaman * current nvlist implementation, so we just live with
7659d65d31SAndy Fiddaman * it until the implementation is reworked.
7759d65d31SAndy Fiddaman */
7859d65d31SAndy Fiddaman nvl = __DECONST(nvlist_t *,
7959d65d31SAndy Fiddaman nvlist_get_nvlist(nvl, name));
802b948146SAndy Fiddaman else if (nvlist_exists(nvl, name)) {
812b948146SAndy Fiddaman for (copy = tofree; copy < name; copy++)
822b948146SAndy Fiddaman if (*copy == '\0')
832b948146SAndy Fiddaman *copy = '.';
842b948146SAndy Fiddaman warnx(
852b948146SAndy Fiddaman "Configuration node %s is a child of existing variable %s",
862b948146SAndy Fiddaman path, tofree);
872b948146SAndy Fiddaman nvl = NULL;
882b948146SAndy Fiddaman break;
892b948146SAndy Fiddaman } else if (create) {
9059d65d31SAndy Fiddaman /*
9159d65d31SAndy Fiddaman * XXX-MJ as with the case above, "new_nvl" shouldn't be
9259d65d31SAndy Fiddaman * mutated after its ownership is given to "nvl".
9359d65d31SAndy Fiddaman */
942b948146SAndy Fiddaman new_nvl = nvlist_create(0);
952b948146SAndy Fiddaman if (new_nvl == NULL)
962b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
972b948146SAndy Fiddaman #ifdef __FreeBSD__
982b948146SAndy Fiddaman nvlist_move_nvlist(nvl, name, new_nvl);
992b948146SAndy Fiddaman #else
1002b948146SAndy Fiddaman if (nvlist_add_nvlist(nvl, name, new_nvl) != 0)
1012b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
1022b948146SAndy Fiddaman (void) nvlist_free(new_nvl);
1032b948146SAndy Fiddaman if (nvlist_lookup_nvlist(nvl, name, &new_nvl) != 0)
1042b948146SAndy Fiddaman errx(4, "Failed to retrieve new nvlist");
1052b948146SAndy Fiddaman #endif
1062b948146SAndy Fiddaman nvl = new_nvl;
1072b948146SAndy Fiddaman } else {
1082b948146SAndy Fiddaman nvl = NULL;
1092b948146SAndy Fiddaman break;
1102b948146SAndy Fiddaman }
1112b948146SAndy Fiddaman }
1122b948146SAndy Fiddaman free(tofree);
1132b948146SAndy Fiddaman return (nvl);
1142b948146SAndy Fiddaman }
1152b948146SAndy Fiddaman
1162b948146SAndy Fiddaman nvlist_t *
create_config_node(const char * path)1172b948146SAndy Fiddaman create_config_node(const char *path)
1182b948146SAndy Fiddaman {
1192b948146SAndy Fiddaman
1202b948146SAndy Fiddaman return (_lookup_config_node(config_root, path, true));
1212b948146SAndy Fiddaman }
1222b948146SAndy Fiddaman
1232b948146SAndy Fiddaman nvlist_t *
find_config_node(const char * path)1242b948146SAndy Fiddaman find_config_node(const char *path)
1252b948146SAndy Fiddaman {
1262b948146SAndy Fiddaman
1272b948146SAndy Fiddaman return (_lookup_config_node(config_root, path, false));
1282b948146SAndy Fiddaman }
1292b948146SAndy Fiddaman
1302b948146SAndy Fiddaman nvlist_t *
create_relative_config_node(nvlist_t * parent,const char * path)1312b948146SAndy Fiddaman create_relative_config_node(nvlist_t *parent, const char *path)
1322b948146SAndy Fiddaman {
1332b948146SAndy Fiddaman
1342b948146SAndy Fiddaman return (_lookup_config_node(parent, path, true));
1352b948146SAndy Fiddaman }
1362b948146SAndy Fiddaman
1372b948146SAndy Fiddaman nvlist_t *
find_relative_config_node(nvlist_t * parent,const char * path)1382b948146SAndy Fiddaman find_relative_config_node(nvlist_t *parent, const char *path)
1392b948146SAndy Fiddaman {
1402b948146SAndy Fiddaman
1412b948146SAndy Fiddaman return (_lookup_config_node(parent, path, false));
1422b948146SAndy Fiddaman }
1432b948146SAndy Fiddaman
1442b948146SAndy Fiddaman void
set_config_value_node(nvlist_t * parent,const char * name,const char * value)1452b948146SAndy Fiddaman set_config_value_node(nvlist_t *parent, const char *name, const char *value)
1462b948146SAndy Fiddaman {
1472b948146SAndy Fiddaman
1482b948146SAndy Fiddaman if (strchr(name, '.') != NULL)
1492b948146SAndy Fiddaman errx(4, "Invalid config node name %s", name);
1502b948146SAndy Fiddaman if (parent == NULL)
1512b948146SAndy Fiddaman parent = config_root;
1522b948146SAndy Fiddaman if (nvlist_exists_string(parent, name))
1532b948146SAndy Fiddaman nvlist_free_string(parent, name);
1542b948146SAndy Fiddaman else if (nvlist_exists(parent, name))
1552b948146SAndy Fiddaman errx(4,
156*32640292SAndy Fiddaman "Attempting to add value %s to existing node %s of list %p",
1572b948146SAndy Fiddaman value, name, parent);
1582b948146SAndy Fiddaman nvlist_add_string(parent, name, value);
1592b948146SAndy Fiddaman }
1602b948146SAndy Fiddaman
1612b948146SAndy Fiddaman void
set_config_value_node_if_unset(nvlist_t * const parent,const char * const name,const char * const value)162d7b72f7bSAndy Fiddaman set_config_value_node_if_unset(nvlist_t *const parent, const char *const name,
163d7b72f7bSAndy Fiddaman const char *const value)
164d7b72f7bSAndy Fiddaman {
165d7b72f7bSAndy Fiddaman if (get_config_value_node(parent, name) != NULL) {
166d7b72f7bSAndy Fiddaman return;
167d7b72f7bSAndy Fiddaman }
168d7b72f7bSAndy Fiddaman
169d7b72f7bSAndy Fiddaman set_config_value_node(parent, name, value);
170d7b72f7bSAndy Fiddaman }
171d7b72f7bSAndy Fiddaman
172d7b72f7bSAndy Fiddaman void
set_config_value(const char * path,const char * value)1732b948146SAndy Fiddaman set_config_value(const char *path, const char *value)
1742b948146SAndy Fiddaman {
1752b948146SAndy Fiddaman const char *name;
1762b948146SAndy Fiddaman char *node_name;
1772b948146SAndy Fiddaman nvlist_t *nvl;
1782b948146SAndy Fiddaman
1792b948146SAndy Fiddaman /* Look for last separator. */
1802b948146SAndy Fiddaman name = strrchr(path, '.');
1812b948146SAndy Fiddaman if (name == NULL) {
1822b948146SAndy Fiddaman nvl = config_root;
1832b948146SAndy Fiddaman name = path;
1842b948146SAndy Fiddaman } else {
1852b948146SAndy Fiddaman node_name = strndup(path, name - path);
1862b948146SAndy Fiddaman if (node_name == NULL)
1872b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
1882b948146SAndy Fiddaman nvl = create_config_node(node_name);
1892b948146SAndy Fiddaman if (nvl == NULL)
1902b948146SAndy Fiddaman errx(4, "Failed to create configuration node %s",
1912b948146SAndy Fiddaman node_name);
1922b948146SAndy Fiddaman free(node_name);
1932b948146SAndy Fiddaman
1942b948146SAndy Fiddaman /* Skip over '.'. */
1952b948146SAndy Fiddaman name++;
1962b948146SAndy Fiddaman }
1972b948146SAndy Fiddaman
1982b948146SAndy Fiddaman if (nvlist_exists_nvlist(nvl, name))
1992b948146SAndy Fiddaman errx(4, "Attempting to add value %s to existing node %s",
2002b948146SAndy Fiddaman value, path);
2012b948146SAndy Fiddaman set_config_value_node(nvl, name, value);
2022b948146SAndy Fiddaman }
2032b948146SAndy Fiddaman
204d7b72f7bSAndy Fiddaman void
set_config_value_if_unset(const char * const path,const char * const value)205d7b72f7bSAndy Fiddaman set_config_value_if_unset(const char *const path, const char *const value)
206d7b72f7bSAndy Fiddaman {
207d7b72f7bSAndy Fiddaman if (get_config_value(path) != NULL) {
208d7b72f7bSAndy Fiddaman return;
209d7b72f7bSAndy Fiddaman }
210d7b72f7bSAndy Fiddaman
211d7b72f7bSAndy Fiddaman set_config_value(path, value);
212d7b72f7bSAndy Fiddaman }
213d7b72f7bSAndy Fiddaman
2142b948146SAndy Fiddaman static const char *
get_raw_config_value(const char * path)2152b948146SAndy Fiddaman get_raw_config_value(const char *path)
2162b948146SAndy Fiddaman {
2172b948146SAndy Fiddaman const char *name;
2182b948146SAndy Fiddaman char *node_name;
2192b948146SAndy Fiddaman nvlist_t *nvl;
2202b948146SAndy Fiddaman
2212b948146SAndy Fiddaman /* Look for last separator. */
2222b948146SAndy Fiddaman name = strrchr(path, '.');
2232b948146SAndy Fiddaman if (name == NULL) {
2242b948146SAndy Fiddaman nvl = config_root;
2252b948146SAndy Fiddaman name = path;
2262b948146SAndy Fiddaman } else {
2272b948146SAndy Fiddaman node_name = strndup(path, name - path);
2282b948146SAndy Fiddaman if (node_name == NULL)
2292b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
2302b948146SAndy Fiddaman nvl = find_config_node(node_name);
2312b948146SAndy Fiddaman free(node_name);
2322b948146SAndy Fiddaman if (nvl == NULL)
2332b948146SAndy Fiddaman return (NULL);
2342b948146SAndy Fiddaman
2352b948146SAndy Fiddaman /* Skip over '.'. */
2362b948146SAndy Fiddaman name++;
2372b948146SAndy Fiddaman }
2382b948146SAndy Fiddaman
2392b948146SAndy Fiddaman if (nvlist_exists_string(nvl, name))
2402b948146SAndy Fiddaman return (nvlist_get_string(nvl, name));
2412b948146SAndy Fiddaman if (nvlist_exists_nvlist(nvl, name))
2422b948146SAndy Fiddaman warnx("Attempting to fetch value of node %s", path);
2432b948146SAndy Fiddaman return (NULL);
2442b948146SAndy Fiddaman }
2452b948146SAndy Fiddaman
2462b948146SAndy Fiddaman static char *
_expand_config_value(const char * value,int depth)2472b948146SAndy Fiddaman _expand_config_value(const char *value, int depth)
2482b948146SAndy Fiddaman {
2492b948146SAndy Fiddaman FILE *valfp;
2502b948146SAndy Fiddaman const char *cp, *vp;
2512b948146SAndy Fiddaman char *nestedval, *path, *valbuf;
2522b948146SAndy Fiddaman size_t valsize;
2532b948146SAndy Fiddaman
2542b948146SAndy Fiddaman valfp = open_memstream(&valbuf, &valsize);
2552b948146SAndy Fiddaman if (valfp == NULL)
2562b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
2572b948146SAndy Fiddaman
2582b948146SAndy Fiddaman vp = value;
2592b948146SAndy Fiddaman while (*vp != '\0') {
2602b948146SAndy Fiddaman switch (*vp) {
2612b948146SAndy Fiddaman case '%':
2622b948146SAndy Fiddaman if (depth > 15) {
2632b948146SAndy Fiddaman warnx(
2642b948146SAndy Fiddaman "Too many recursive references in configuration value");
2652b948146SAndy Fiddaman fputc('%', valfp);
2662b948146SAndy Fiddaman vp++;
2672b948146SAndy Fiddaman break;
2682b948146SAndy Fiddaman }
2692b948146SAndy Fiddaman if (vp[1] != '(' || vp[2] == '\0')
2702b948146SAndy Fiddaman cp = NULL;
2712b948146SAndy Fiddaman else
2722b948146SAndy Fiddaman cp = strchr(vp + 2, ')');
2732b948146SAndy Fiddaman if (cp == NULL) {
2742b948146SAndy Fiddaman warnx(
2752b948146SAndy Fiddaman "Invalid reference in configuration value \"%s\"",
2762b948146SAndy Fiddaman value);
2772b948146SAndy Fiddaman fputc('%', valfp);
2782b948146SAndy Fiddaman vp++;
2792b948146SAndy Fiddaman break;
2802b948146SAndy Fiddaman }
2812b948146SAndy Fiddaman vp += 2;
2822b948146SAndy Fiddaman
2832b948146SAndy Fiddaman if (cp == vp) {
2842b948146SAndy Fiddaman warnx(
2852b948146SAndy Fiddaman "Empty reference in configuration value \"%s\"",
2862b948146SAndy Fiddaman value);
2872b948146SAndy Fiddaman vp++;
2882b948146SAndy Fiddaman break;
2892b948146SAndy Fiddaman }
2902b948146SAndy Fiddaman
2912b948146SAndy Fiddaman /* Allocate a C string holding the path. */
2922b948146SAndy Fiddaman path = strndup(vp, cp - vp);
2932b948146SAndy Fiddaman if (path == NULL)
2942b948146SAndy Fiddaman errx(4, "Failed to allocate memory");
2952b948146SAndy Fiddaman
2962b948146SAndy Fiddaman /* Advance 'vp' past the reference. */
2972b948146SAndy Fiddaman vp = cp + 1;
2982b948146SAndy Fiddaman
2992b948146SAndy Fiddaman /* Fetch the referenced value. */
3002b948146SAndy Fiddaman cp = get_raw_config_value(path);
3012b948146SAndy Fiddaman if (cp == NULL)
3022b948146SAndy Fiddaman warnx(
3032b948146SAndy Fiddaman "Failed to fetch referenced configuration variable %s",
3042b948146SAndy Fiddaman path);
3052b948146SAndy Fiddaman else {
3062b948146SAndy Fiddaman nestedval = _expand_config_value(cp, depth + 1);
3072b948146SAndy Fiddaman fputs(nestedval, valfp);
3082b948146SAndy Fiddaman free(nestedval);
3092b948146SAndy Fiddaman }
3102b948146SAndy Fiddaman free(path);
3112b948146SAndy Fiddaman break;
3122b948146SAndy Fiddaman case '\\':
3132b948146SAndy Fiddaman vp++;
3142b948146SAndy Fiddaman if (*vp == '\0') {
3152b948146SAndy Fiddaman warnx(
3162b948146SAndy Fiddaman "Trailing \\ in configuration value \"%s\"",
3172b948146SAndy Fiddaman value);
3182b948146SAndy Fiddaman break;
3192b948146SAndy Fiddaman }
3202b948146SAndy Fiddaman /* FALLTHROUGH */
3212b948146SAndy Fiddaman default:
3222b948146SAndy Fiddaman fputc(*vp, valfp);
3232b948146SAndy Fiddaman vp++;
3242b948146SAndy Fiddaman break;
3252b948146SAndy Fiddaman }
3262b948146SAndy Fiddaman }
3272b948146SAndy Fiddaman fclose(valfp);
3282b948146SAndy Fiddaman return (valbuf);
3292b948146SAndy Fiddaman }
3302b948146SAndy Fiddaman
3314f3f3e9aSAndy Fiddaman static const char *
expand_config_value(const char * value)3322b948146SAndy Fiddaman expand_config_value(const char *value)
3332b948146SAndy Fiddaman {
3342b948146SAndy Fiddaman static char *valbuf;
3352b948146SAndy Fiddaman
3362b948146SAndy Fiddaman if (strchr(value, '%') == NULL)
3372b948146SAndy Fiddaman return (value);
3382b948146SAndy Fiddaman
3392b948146SAndy Fiddaman free(valbuf);
3402b948146SAndy Fiddaman valbuf = _expand_config_value(value, 0);
3412b948146SAndy Fiddaman return (valbuf);
3422b948146SAndy Fiddaman }
3432b948146SAndy Fiddaman
3442b948146SAndy Fiddaman const char *
get_config_value(const char * path)3452b948146SAndy Fiddaman get_config_value(const char *path)
3462b948146SAndy Fiddaman {
3472b948146SAndy Fiddaman const char *value;
3482b948146SAndy Fiddaman
3492b948146SAndy Fiddaman value = get_raw_config_value(path);
3502b948146SAndy Fiddaman if (value == NULL)
3512b948146SAndy Fiddaman return (NULL);
3522b948146SAndy Fiddaman return (expand_config_value(value));
3532b948146SAndy Fiddaman }
3542b948146SAndy Fiddaman
3552b948146SAndy Fiddaman const char *
get_config_value_node(const nvlist_t * parent,const char * name)3562b948146SAndy Fiddaman get_config_value_node(const nvlist_t *parent, const char *name)
3572b948146SAndy Fiddaman {
3582b948146SAndy Fiddaman
3592b948146SAndy Fiddaman if (strchr(name, '.') != NULL)
3602b948146SAndy Fiddaman errx(4, "Invalid config node name %s", name);
3612b948146SAndy Fiddaman if (parent == NULL)
3622b948146SAndy Fiddaman parent = config_root;
3632b948146SAndy Fiddaman
3642b948146SAndy Fiddaman if (nvlist_exists_nvlist(parent, name))
3652b948146SAndy Fiddaman warnx("Attempt to fetch value of node %s of list %p", name,
3662b948146SAndy Fiddaman parent);
3672b948146SAndy Fiddaman if (!nvlist_exists_string(parent, name))
3682b948146SAndy Fiddaman return (NULL);
3692b948146SAndy Fiddaman
3702b948146SAndy Fiddaman return (expand_config_value(nvlist_get_string(parent, name)));
3712b948146SAndy Fiddaman }
3722b948146SAndy Fiddaman
3734f3f3e9aSAndy Fiddaman static bool
_bool_value(const char * name,const char * value)3742b948146SAndy Fiddaman _bool_value(const char *name, const char *value)
3752b948146SAndy Fiddaman {
3762b948146SAndy Fiddaman
3772b948146SAndy Fiddaman if (strcasecmp(value, "true") == 0 ||
3782b948146SAndy Fiddaman strcasecmp(value, "on") == 0 ||
3792b948146SAndy Fiddaman strcasecmp(value, "yes") == 0 ||
3802b948146SAndy Fiddaman strcmp(value, "1") == 0)
3812b948146SAndy Fiddaman return (true);
3822b948146SAndy Fiddaman if (strcasecmp(value, "false") == 0 ||
3832b948146SAndy Fiddaman strcasecmp(value, "off") == 0 ||
3842b948146SAndy Fiddaman strcasecmp(value, "no") == 0 ||
3852b948146SAndy Fiddaman strcmp(value, "0") == 0)
3862b948146SAndy Fiddaman return (false);
3872b948146SAndy Fiddaman err(4, "Invalid value %s for boolean variable %s", value, name);
3882b948146SAndy Fiddaman }
3892b948146SAndy Fiddaman
3902b948146SAndy Fiddaman bool
get_config_bool(const char * path)3912b948146SAndy Fiddaman get_config_bool(const char *path)
3922b948146SAndy Fiddaman {
3932b948146SAndy Fiddaman const char *value;
3942b948146SAndy Fiddaman
3952b948146SAndy Fiddaman value = get_config_value(path);
3962b948146SAndy Fiddaman if (value == NULL)
3972b948146SAndy Fiddaman err(4, "Failed to fetch boolean variable %s", path);
3982b948146SAndy Fiddaman return (_bool_value(path, value));
3992b948146SAndy Fiddaman }
4002b948146SAndy Fiddaman
4012b948146SAndy Fiddaman bool
get_config_bool_default(const char * path,bool def)4022b948146SAndy Fiddaman get_config_bool_default(const char *path, bool def)
4032b948146SAndy Fiddaman {
4042b948146SAndy Fiddaman const char *value;
4052b948146SAndy Fiddaman
4062b948146SAndy Fiddaman value = get_config_value(path);
4072b948146SAndy Fiddaman if (value == NULL)
4082b948146SAndy Fiddaman return (def);
4092b948146SAndy Fiddaman return (_bool_value(path, value));
4102b948146SAndy Fiddaman }
4112b948146SAndy Fiddaman
4122b948146SAndy Fiddaman bool
get_config_bool_node(const nvlist_t * parent,const char * name)4132b948146SAndy Fiddaman get_config_bool_node(const nvlist_t *parent, const char *name)
4142b948146SAndy Fiddaman {
4152b948146SAndy Fiddaman const char *value;
4162b948146SAndy Fiddaman
4172b948146SAndy Fiddaman value = get_config_value_node(parent, name);
4182b948146SAndy Fiddaman if (value == NULL)
4192b948146SAndy Fiddaman err(4, "Failed to fetch boolean variable %s", name);
4202b948146SAndy Fiddaman return (_bool_value(name, value));
4212b948146SAndy Fiddaman }
4222b948146SAndy Fiddaman
4232b948146SAndy Fiddaman bool
get_config_bool_node_default(const nvlist_t * parent,const char * name,bool def)4242b948146SAndy Fiddaman get_config_bool_node_default(const nvlist_t *parent, const char *name,
4252b948146SAndy Fiddaman bool def)
4262b948146SAndy Fiddaman {
4272b948146SAndy Fiddaman const char *value;
4282b948146SAndy Fiddaman
4292b948146SAndy Fiddaman value = get_config_value_node(parent, name);
4302b948146SAndy Fiddaman if (value == NULL)
4312b948146SAndy Fiddaman return (def);
4322b948146SAndy Fiddaman return (_bool_value(name, value));
4332b948146SAndy Fiddaman }
4342b948146SAndy Fiddaman
4352b948146SAndy Fiddaman void
set_config_bool(const char * path,bool value)4362b948146SAndy Fiddaman set_config_bool(const char *path, bool value)
4372b948146SAndy Fiddaman {
4382b948146SAndy Fiddaman
4392b948146SAndy Fiddaman set_config_value(path, value ? "true" : "false");
4402b948146SAndy Fiddaman }
4412b948146SAndy Fiddaman
4422b948146SAndy Fiddaman void
set_config_bool_node(nvlist_t * parent,const char * name,bool value)4432b948146SAndy Fiddaman set_config_bool_node(nvlist_t *parent, const char *name, bool value)
4442b948146SAndy Fiddaman {
4452b948146SAndy Fiddaman
4462b948146SAndy Fiddaman set_config_value_node(parent, name, value ? "true" : "false");
4472b948146SAndy Fiddaman }
4482b948146SAndy Fiddaman
4492b948146SAndy Fiddaman static void
dump_tree(const char * prefix,const nvlist_t * nvl)4502b948146SAndy Fiddaman dump_tree(const char *prefix, const nvlist_t *nvl)
4512b948146SAndy Fiddaman {
4522b948146SAndy Fiddaman const char *name;
4532b948146SAndy Fiddaman void *cookie;
4542b948146SAndy Fiddaman int type;
4552b948146SAndy Fiddaman
4562b948146SAndy Fiddaman cookie = NULL;
4572b948146SAndy Fiddaman while ((name = nvlist_next(nvl, &type, &cookie)) != NULL) {
4582b948146SAndy Fiddaman if (type == NV_TYPE_NVLIST) {
4592b948146SAndy Fiddaman char *new_prefix;
4602b948146SAndy Fiddaman
4612b948146SAndy Fiddaman asprintf(&new_prefix, "%s%s.", prefix, name);
4622b948146SAndy Fiddaman dump_tree(new_prefix, nvlist_get_nvlist(nvl, name));
4632b948146SAndy Fiddaman free(new_prefix);
4642b948146SAndy Fiddaman } else {
4652b948146SAndy Fiddaman assert(type == NV_TYPE_STRING);
4662b948146SAndy Fiddaman printf("%s%s=%s\n", prefix, name,
4672b948146SAndy Fiddaman nvlist_get_string(nvl, name));
4682b948146SAndy Fiddaman }
4692b948146SAndy Fiddaman }
4702b948146SAndy Fiddaman }
4712b948146SAndy Fiddaman
4722b948146SAndy Fiddaman void
dump_config(void)4732b948146SAndy Fiddaman dump_config(void)
4742b948146SAndy Fiddaman {
4752b948146SAndy Fiddaman dump_tree("", config_root);
4762b948146SAndy Fiddaman }
477