1247841Sbapt/*- 2263020Sbapt * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> 3257353Sbdrewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 4247841Sbapt * All rights reserved. 5247841Sbapt * 6247841Sbapt * Redistribution and use in source and binary forms, with or without 7247841Sbapt * modification, are permitted provided that the following conditions 8247841Sbapt * are met: 9247841Sbapt * 1. Redistributions of source code must retain the above copyright 10247841Sbapt * notice, this list of conditions and the following disclaimer. 11247841Sbapt * 2. Redistributions in binary form must reproduce the above copyright 12247841Sbapt * notice, this list of conditions and the following disclaimer in the 13247841Sbapt * documentation and/or other materials provided with the distribution. 14247841Sbapt * 15247841Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16247841Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17247841Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18247841Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19247841Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20247841Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21247841Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22247841Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23247841Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24247841Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25247841Sbapt * SUCH DAMAGE. 26247841Sbapt */ 27247841Sbapt 28247841Sbapt#include <sys/cdefs.h> 29247841Sbapt__FBSDID("$FreeBSD: releng/10.2/usr.sbin/pkg/config.c 287872 2015-09-16 20:59:41Z delphij $"); 30247841Sbapt 31247841Sbapt#include <sys/param.h> 32261144Sbapt#include <sys/queue.h> 33247841Sbapt#include <sys/sbuf.h> 34259613Sbdrewery#include <sys/types.h> 35283791Sbapt#include <sys/utsname.h> 36283791Sbapt#include <sys/sysctl.h> 37247841Sbapt 38255457Sbapt#include <assert.h> 39259613Sbdrewery#include <dirent.h> 40263020Sbapt#include <ucl.h> 41247841Sbapt#include <ctype.h> 42247841Sbapt#include <err.h> 43247841Sbapt#include <errno.h> 44247841Sbapt#include <fcntl.h> 45247841Sbapt#include <inttypes.h> 46247841Sbapt#include <paths.h> 47247841Sbapt#include <stdbool.h> 48247841Sbapt#include <string.h> 49247841Sbapt#include <unistd.h> 50247841Sbapt 51247841Sbapt#include "config.h" 52247841Sbapt 53247841Sbapt#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 54247841Sbapt 55259613Sbdrewerystruct config_value { 56259613Sbdrewery char *value; 57259613Sbdrewery STAILQ_ENTRY(config_value) next; 58259613Sbdrewery}; 59259613Sbdrewery 60247841Sbaptstruct config_entry { 61247841Sbapt uint8_t type; 62247841Sbapt const char *key; 63247841Sbapt const char *val; 64247841Sbapt char *value; 65259613Sbdrewery STAILQ_HEAD(, config_value) *list; 66247841Sbapt bool envset; 67263621Sbdrewery bool main_only; /* Only set in pkg.conf. */ 68247841Sbapt}; 69247841Sbapt 70247841Sbaptstatic struct config_entry c[] = { 71247841Sbapt [PACKAGESITE] = { 72247841Sbapt PKG_CONFIG_STRING, 73247841Sbapt "PACKAGESITE", 74257328Sbdrewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 75247841Sbapt NULL, 76259613Sbdrewery NULL, 77247841Sbapt false, 78263621Sbdrewery false, 79247841Sbapt }, 80247841Sbapt [ABI] = { 81247841Sbapt PKG_CONFIG_STRING, 82247841Sbapt "ABI", 83247841Sbapt NULL, 84247841Sbapt NULL, 85259613Sbdrewery NULL, 86247841Sbapt false, 87263621Sbdrewery true, 88247841Sbapt }, 89247841Sbapt [MIRROR_TYPE] = { 90247841Sbapt PKG_CONFIG_STRING, 91247841Sbapt "MIRROR_TYPE", 92247841Sbapt "SRV", 93247841Sbapt NULL, 94259613Sbdrewery NULL, 95247841Sbapt false, 96263621Sbdrewery false, 97247841Sbapt }, 98247841Sbapt [ASSUME_ALWAYS_YES] = { 99247841Sbapt PKG_CONFIG_BOOL, 100247841Sbapt "ASSUME_ALWAYS_YES", 101247841Sbapt "NO", 102247841Sbapt NULL, 103259613Sbdrewery NULL, 104247841Sbapt false, 105263621Sbdrewery true, 106257353Sbdrewery }, 107257353Sbdrewery [SIGNATURE_TYPE] = { 108257353Sbdrewery PKG_CONFIG_STRING, 109257353Sbdrewery "SIGNATURE_TYPE", 110257353Sbdrewery NULL, 111257353Sbdrewery NULL, 112259613Sbdrewery NULL, 113257353Sbdrewery false, 114263621Sbdrewery false, 115257353Sbdrewery }, 116257353Sbdrewery [FINGERPRINTS] = { 117257353Sbdrewery PKG_CONFIG_STRING, 118257353Sbdrewery "FINGERPRINTS", 119257353Sbdrewery NULL, 120257353Sbdrewery NULL, 121259613Sbdrewery NULL, 122257353Sbdrewery false, 123263621Sbdrewery false, 124257353Sbdrewery }, 125259613Sbdrewery [REPOS_DIR] = { 126259613Sbdrewery PKG_CONFIG_LIST, 127259613Sbdrewery "REPOS_DIR", 128259613Sbdrewery NULL, 129259613Sbdrewery NULL, 130259613Sbdrewery NULL, 131259613Sbdrewery false, 132263621Sbdrewery true, 133259613Sbdrewery }, 134287872Sdelphij [PUBKEY] = { 135287872Sdelphij PKG_CONFIG_STRING, 136287872Sdelphij "PUBKEY", 137287872Sdelphij NULL, 138287872Sdelphij NULL, 139287872Sdelphij NULL, 140287872Sdelphij false, 141287872Sdelphij false 142287872Sdelphij } 143247841Sbapt}; 144247841Sbapt 145283791Sbaptstatic int 146283791Sbaptpkg_get_myabi(char *dest, size_t sz) 147247841Sbapt{ 148283791Sbapt struct utsname uts; 149283791Sbapt char machine_arch[255]; 150283791Sbapt size_t len; 151283791Sbapt int error; 152247841Sbapt 153283791Sbapt error = uname(&uts); 154283791Sbapt if (error) 155283791Sbapt return (errno); 156247841Sbapt 157283791Sbapt len = sizeof(machine_arch); 158283791Sbapt error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 159283791Sbapt if (error) 160283791Sbapt return (errno); 161283791Sbapt machine_arch[len] = '\0'; 162247841Sbapt 163255457Sbapt /* 164283791Sbapt * Use __FreeBSD_version rather than kernel version (uts.release) for 165283791Sbapt * use in jails. This is equivalent to the value of uname -U. 166255457Sbapt */ 167283791Sbapt snprintf(dest, sz, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 168283791Sbapt machine_arch); 169255457Sbapt 170283791Sbapt return (error); 171255457Sbapt} 172255457Sbapt 173247841Sbaptstatic void 174247841Sbaptsubst_packagesite(const char *abi) 175247841Sbapt{ 176247841Sbapt struct sbuf *newval; 177247841Sbapt const char *variable_string; 178247841Sbapt const char *oldval; 179247841Sbapt 180247841Sbapt if (c[PACKAGESITE].value != NULL) 181247841Sbapt oldval = c[PACKAGESITE].value; 182247841Sbapt else 183247841Sbapt oldval = c[PACKAGESITE].val; 184247841Sbapt 185247841Sbapt if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 186247841Sbapt return; 187247841Sbapt 188247841Sbapt newval = sbuf_new_auto(); 189247841Sbapt sbuf_bcat(newval, oldval, variable_string - oldval); 190247841Sbapt sbuf_cat(newval, abi); 191247841Sbapt sbuf_cat(newval, variable_string + strlen("${ABI}")); 192247841Sbapt sbuf_finish(newval); 193247841Sbapt 194247841Sbapt free(c[PACKAGESITE].value); 195247841Sbapt c[PACKAGESITE].value = strdup(sbuf_data(newval)); 196247841Sbapt} 197247841Sbapt 198259613Sbdrewerystatic int 199259613Sbdreweryboolstr_to_bool(const char *str) 200259613Sbdrewery{ 201259613Sbdrewery if (str != NULL && (strcasecmp(str, "true") == 0 || 202259613Sbdrewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 203259613Sbdrewery str[0] == '1')) 204259613Sbdrewery return (true); 205259613Sbdrewery 206259613Sbdrewery return (false); 207259613Sbdrewery} 208259613Sbdrewery 209247841Sbaptstatic void 210268896Sbaptconfig_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 211247841Sbapt{ 212247841Sbapt struct sbuf *buf = sbuf_new_auto(); 213268896Sbapt const ucl_object_t *cur, *seq; 214263020Sbapt ucl_object_iter_t it = NULL, itseq = NULL; 215259613Sbdrewery struct config_entry *temp_config; 216259613Sbdrewery struct config_value *cv; 217263020Sbapt const char *key; 218247841Sbapt int i; 219247841Sbapt size_t j; 220247841Sbapt 221259613Sbdrewery /* Temporary config for configs that may be disabled. */ 222259613Sbdrewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 223259613Sbdrewery 224263020Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 225263020Sbapt key = ucl_object_key(cur); 226263020Sbapt if (key == NULL) 227247841Sbapt continue; 228247841Sbapt sbuf_clear(buf); 229247841Sbapt 230257353Sbdrewery if (conftype == CONFFILE_PKG) { 231263020Sbapt for (j = 0; j < strlen(key); ++j) 232263020Sbapt sbuf_putc(buf, key[j]); 233257353Sbdrewery sbuf_finish(buf); 234257353Sbdrewery } else if (conftype == CONFFILE_REPO) { 235263020Sbapt if (strcasecmp(key, "url") == 0) 236257353Sbdrewery sbuf_cpy(buf, "PACKAGESITE"); 237263020Sbapt else if (strcasecmp(key, "mirror_type") == 0) 238257353Sbdrewery sbuf_cpy(buf, "MIRROR_TYPE"); 239263020Sbapt else if (strcasecmp(key, "signature_type") == 0) 240257353Sbdrewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 241263020Sbapt else if (strcasecmp(key, "fingerprints") == 0) 242257353Sbdrewery sbuf_cpy(buf, "FINGERPRINTS"); 243287872Sdelphij else if (strcasecmp(key, "pubkey") == 0) 244287872Sdelphij sbuf_cpy(buf, "PUBKEY"); 245263020Sbapt else if (strcasecmp(key, "enabled") == 0) { 246263020Sbapt if ((cur->type != UCL_BOOLEAN) || 247263020Sbapt !ucl_object_toboolean(cur)) 248259613Sbdrewery goto cleanup; 249263020Sbapt } else 250257353Sbdrewery continue; 251257353Sbdrewery sbuf_finish(buf); 252257353Sbdrewery } 253257353Sbdrewery 254247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) { 255247841Sbapt if (strcmp(sbuf_data(buf), c[i].key) == 0) 256247841Sbapt break; 257247841Sbapt } 258247841Sbapt 259257353Sbdrewery /* Silently skip unknown keys to be future compatible. */ 260263020Sbapt if (i == CONFIG_SIZE) 261247841Sbapt continue; 262247841Sbapt 263247841Sbapt /* env has priority over config file */ 264263020Sbapt if (c[i].envset) 265247841Sbapt continue; 266247841Sbapt 267259613Sbdrewery /* Parse sequence value ["item1", "item2"] */ 268259613Sbdrewery switch (c[i].type) { 269259613Sbdrewery case PKG_CONFIG_LIST: 270263020Sbapt if (cur->type != UCL_ARRAY) { 271263020Sbapt warnx("Skipping invalid array " 272259613Sbdrewery "value for %s.\n", c[i].key); 273259613Sbdrewery continue; 274259613Sbdrewery } 275259613Sbdrewery temp_config[i].list = 276259613Sbdrewery malloc(sizeof(*temp_config[i].list)); 277259613Sbdrewery STAILQ_INIT(temp_config[i].list); 278259613Sbdrewery 279263020Sbapt while ((seq = ucl_iterate_object(cur, &itseq, true))) { 280263020Sbapt if (seq->type != UCL_STRING) 281259613Sbdrewery continue; 282259613Sbdrewery cv = malloc(sizeof(struct config_value)); 283259613Sbdrewery cv->value = 284263020Sbapt strdup(ucl_object_tostring(seq)); 285259613Sbdrewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 286259613Sbdrewery next); 287259613Sbdrewery } 288259613Sbdrewery break; 289263624Sbdrewery case PKG_CONFIG_BOOL: 290263624Sbdrewery temp_config[i].value = 291263624Sbdrewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 292263624Sbdrewery break; 293259613Sbdrewery default: 294259613Sbdrewery /* Normal string value. */ 295263020Sbapt temp_config[i].value = strdup(ucl_object_tostring(cur)); 296259613Sbdrewery break; 297259613Sbdrewery } 298247841Sbapt } 299247841Sbapt 300259613Sbdrewery /* Repo is enabled, copy over all settings from temp_config. */ 301259613Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 302259613Sbdrewery if (c[i].envset) 303259613Sbdrewery continue; 304263621Sbdrewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 305263621Sbdrewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 306263621Sbdrewery continue; 307259613Sbdrewery switch (c[i].type) { 308259613Sbdrewery case PKG_CONFIG_LIST: 309259613Sbdrewery c[i].list = temp_config[i].list; 310259613Sbdrewery break; 311259613Sbdrewery default: 312259613Sbdrewery c[i].value = temp_config[i].value; 313259613Sbdrewery break; 314259613Sbdrewery } 315259613Sbdrewery } 316259613Sbdrewery 317259613Sbdrewerycleanup: 318259613Sbdrewery free(temp_config); 319247841Sbapt sbuf_delete(buf); 320247841Sbapt} 321247841Sbapt 322257353Sbdrewery/*- 323257353Sbdrewery * Parse new repo style configs in style: 324257353Sbdrewery * Name: 325257353Sbdrewery * URL: 326257353Sbdrewery * MIRROR_TYPE: 327257353Sbdrewery * etc... 328257353Sbdrewery */ 329257353Sbdrewerystatic void 330263020Sbaptparse_repo_file(ucl_object_t *obj) 331247841Sbapt{ 332263020Sbapt ucl_object_iter_t it = NULL; 333268896Sbapt const ucl_object_t *cur; 334263020Sbapt const char *key; 335257353Sbdrewery 336263020Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 337263020Sbapt key = ucl_object_key(cur); 338257353Sbdrewery 339263020Sbapt if (key == NULL) 340257353Sbdrewery continue; 341257353Sbdrewery 342263020Sbapt if (cur->type != UCL_OBJECT) 343257353Sbdrewery continue; 344257353Sbdrewery 345263020Sbapt config_parse(cur, CONFFILE_REPO); 346257353Sbdrewery } 347257353Sbdrewery} 348257353Sbdrewery 349257353Sbdrewery 350257353Sbdrewerystatic int 351257353Sbdreweryread_conf_file(const char *confpath, pkg_conf_file_t conftype) 352257353Sbdrewery{ 353263020Sbapt struct ucl_parser *p; 354263020Sbapt ucl_object_t *obj = NULL; 355257353Sbdrewery 356263020Sbapt p = ucl_parser_new(0); 357263020Sbapt 358263020Sbapt if (!ucl_parser_add_file(p, confpath)) { 359257353Sbdrewery if (errno != ENOENT) 360263020Sbapt errx(EXIT_FAILURE, "Unable to parse configuration " 361263020Sbapt "file %s: %s", confpath, ucl_parser_get_error(p)); 362263020Sbapt ucl_parser_free(p); 363257353Sbdrewery /* no configuration present */ 364257353Sbdrewery return (1); 365257353Sbdrewery } 366257353Sbdrewery 367263020Sbapt obj = ucl_parser_get_object(p); 368263020Sbapt if (obj->type != UCL_OBJECT) 369257353Sbdrewery warnx("Invalid configuration format, ignoring the " 370257353Sbdrewery "configuration file %s", confpath); 371257353Sbdrewery else { 372257353Sbdrewery if (conftype == CONFFILE_PKG) 373263020Sbapt config_parse(obj, conftype); 374257353Sbdrewery else if (conftype == CONFFILE_REPO) 375263020Sbapt parse_repo_file(obj); 376257353Sbdrewery } 377257353Sbdrewery 378268896Sbapt ucl_object_unref(obj); 379263020Sbapt ucl_parser_free(p); 380257353Sbdrewery 381257353Sbdrewery return (0); 382257353Sbdrewery} 383257353Sbdrewery 384259613Sbdrewerystatic int 385259613Sbdreweryload_repositories(const char *repodir) 386259613Sbdrewery{ 387259613Sbdrewery struct dirent *ent; 388259613Sbdrewery DIR *d; 389259613Sbdrewery char *p; 390259613Sbdrewery size_t n; 391259613Sbdrewery char path[MAXPATHLEN]; 392259613Sbdrewery int ret; 393259613Sbdrewery 394259613Sbdrewery ret = 0; 395259613Sbdrewery 396259613Sbdrewery if ((d = opendir(repodir)) == NULL) 397259613Sbdrewery return (1); 398259613Sbdrewery 399259613Sbdrewery while ((ent = readdir(d))) { 400259613Sbdrewery /* Trim out 'repos'. */ 401259613Sbdrewery if ((n = strlen(ent->d_name)) <= 5) 402259613Sbdrewery continue; 403259613Sbdrewery p = &ent->d_name[n - 5]; 404259613Sbdrewery if (strcmp(p, ".conf") == 0) { 405259613Sbdrewery snprintf(path, sizeof(path), "%s%s%s", 406259613Sbdrewery repodir, 407259613Sbdrewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 408259613Sbdrewery ent->d_name); 409259613Sbdrewery if (access(path, F_OK) == 0 && 410259613Sbdrewery read_conf_file(path, CONFFILE_REPO)) { 411259613Sbdrewery ret = 1; 412259613Sbdrewery goto cleanup; 413259613Sbdrewery } 414259613Sbdrewery } 415259613Sbdrewery } 416259613Sbdrewery 417259613Sbdrewerycleanup: 418259613Sbdrewery closedir(d); 419259613Sbdrewery 420259613Sbdrewery return (ret); 421259613Sbdrewery} 422259613Sbdrewery 423257353Sbdreweryint 424257353Sbdreweryconfig_init(void) 425257353Sbdrewery{ 426259613Sbdrewery char *val; 427247841Sbapt int i; 428247841Sbapt const char *localbase; 429259613Sbdrewery char *env_list_item; 430247841Sbapt char confpath[MAXPATHLEN]; 431259613Sbdrewery struct config_value *cv; 432247841Sbapt char abi[BUFSIZ]; 433247841Sbapt 434247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) { 435247841Sbapt val = getenv(c[i].key); 436247841Sbapt if (val != NULL) { 437247841Sbapt c[i].envset = true; 438259613Sbdrewery switch (c[i].type) { 439259613Sbdrewery case PKG_CONFIG_LIST: 440259613Sbdrewery /* Split up comma-separated items from env. */ 441259613Sbdrewery c[i].list = malloc(sizeof(*c[i].list)); 442259613Sbdrewery STAILQ_INIT(c[i].list); 443259613Sbdrewery for (env_list_item = strtok(val, ","); 444259613Sbdrewery env_list_item != NULL; 445259613Sbdrewery env_list_item = strtok(NULL, ",")) { 446259613Sbdrewery cv = 447259613Sbdrewery malloc(sizeof(struct config_value)); 448259613Sbdrewery cv->value = 449259613Sbdrewery strdup(env_list_item); 450259613Sbdrewery STAILQ_INSERT_TAIL(c[i].list, cv, 451259613Sbdrewery next); 452259613Sbdrewery } 453259613Sbdrewery break; 454259613Sbdrewery default: 455259613Sbdrewery c[i].val = val; 456259613Sbdrewery break; 457259613Sbdrewery } 458247841Sbapt } 459247841Sbapt } 460247841Sbapt 461259613Sbdrewery /* Read LOCALBASE/etc/pkg.conf first. */ 462247841Sbapt localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 463257353Sbdrewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 464257353Sbdrewery localbase); 465247841Sbapt 466257353Sbdrewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 467257353Sbdrewery CONFFILE_PKG)) 468247841Sbapt goto finalize; 469247841Sbapt 470259613Sbdrewery /* Then read in all repos from REPOS_DIR list of directories. */ 471259613Sbdrewery if (c[REPOS_DIR].list == NULL) { 472259613Sbdrewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 473259613Sbdrewery STAILQ_INIT(c[REPOS_DIR].list); 474259613Sbdrewery cv = malloc(sizeof(struct config_value)); 475259613Sbdrewery cv->value = strdup("/etc/pkg"); 476259613Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 477259613Sbdrewery cv = malloc(sizeof(struct config_value)); 478259613Sbdrewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 479259613Sbdrewery goto finalize; 480259613Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 481259613Sbdrewery } 482247841Sbapt 483259613Sbdrewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 484259613Sbdrewery if (load_repositories(cv->value)) 485259613Sbdrewery goto finalize; 486259613Sbdrewery 487247841Sbaptfinalize: 488247841Sbapt if (c[ABI].val == NULL && c[ABI].value == NULL) { 489247841Sbapt if (pkg_get_myabi(abi, BUFSIZ) != 0) 490257353Sbdrewery errx(EXIT_FAILURE, "Failed to determine the system " 491257353Sbdrewery "ABI"); 492247841Sbapt c[ABI].val = abi; 493247841Sbapt } 494247841Sbapt 495247843Sbapt subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 496247841Sbapt 497247841Sbapt return (0); 498247841Sbapt} 499247841Sbapt 500247841Sbaptint 501247841Sbaptconfig_string(pkg_config_key k, const char **val) 502247841Sbapt{ 503247841Sbapt if (c[k].type != PKG_CONFIG_STRING) 504247841Sbapt return (-1); 505247841Sbapt 506247841Sbapt if (c[k].value != NULL) 507247841Sbapt *val = c[k].value; 508247841Sbapt else 509247841Sbapt *val = c[k].val; 510247841Sbapt 511247841Sbapt return (0); 512247841Sbapt} 513247841Sbapt 514247841Sbaptint 515247841Sbaptconfig_bool(pkg_config_key k, bool *val) 516247841Sbapt{ 517247841Sbapt const char *value; 518247841Sbapt 519247841Sbapt if (c[k].type != PKG_CONFIG_BOOL) 520247841Sbapt return (-1); 521247841Sbapt 522247841Sbapt *val = false; 523247841Sbapt 524247841Sbapt if (c[k].value != NULL) 525247841Sbapt value = c[k].value; 526247841Sbapt else 527247841Sbapt value = c[k].val; 528247841Sbapt 529259613Sbdrewery if (boolstr_to_bool(value)) 530247841Sbapt *val = true; 531247841Sbapt 532247841Sbapt return (0); 533247841Sbapt} 534247841Sbapt 535247841Sbaptvoid 536247841Sbaptconfig_finish(void) { 537247841Sbapt int i; 538247841Sbapt 539247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) 540247841Sbapt free(c[i].value); 541247841Sbapt} 542