1247841Sbapt/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 4262401Sbapt * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> 5257147Sbdrewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 6247841Sbapt * All rights reserved. 7247841Sbapt * 8247841Sbapt * Redistribution and use in source and binary forms, with or without 9247841Sbapt * modification, are permitted provided that the following conditions 10247841Sbapt * are met: 11247841Sbapt * 1. Redistributions of source code must retain the above copyright 12247841Sbapt * notice, this list of conditions and the following disclaimer. 13247841Sbapt * 2. Redistributions in binary form must reproduce the above copyright 14247841Sbapt * notice, this list of conditions and the following disclaimer in the 15247841Sbapt * documentation and/or other materials provided with the distribution. 16247841Sbapt * 17247841Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18247841Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19247841Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20247841Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21247841Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22247841Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23247841Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24247841Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25247841Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26247841Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27247841Sbapt * SUCH DAMAGE. 28247841Sbapt */ 29247841Sbapt 30247841Sbapt#include <sys/cdefs.h> 31247841Sbapt__FBSDID("$FreeBSD: stable/11/usr.sbin/pkg/config.c 330449 2018-03-05 07:26:05Z eadler $"); 32247841Sbapt 33247841Sbapt#include <sys/param.h> 34260942Sbapt#include <sys/queue.h> 35247841Sbapt#include <sys/sbuf.h> 36273754Snwhitehorn#include <sys/utsname.h> 37273754Snwhitehorn#include <sys/sysctl.h> 38247841Sbapt 39259266Sbdrewery#include <dirent.h> 40262400Sbapt#include <ucl.h> 41247841Sbapt#include <err.h> 42247841Sbapt#include <errno.h> 43247841Sbapt#include <stdbool.h> 44247841Sbapt#include <unistd.h> 45247841Sbapt 46247841Sbapt#include "config.h" 47247841Sbapt 48247841Sbapt#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 49247841Sbapt 50259266Sbdrewerystruct config_value { 51259266Sbdrewery char *value; 52259266Sbdrewery STAILQ_ENTRY(config_value) next; 53259266Sbdrewery}; 54259266Sbdrewery 55247841Sbaptstruct config_entry { 56247841Sbapt uint8_t type; 57247841Sbapt const char *key; 58247841Sbapt const char *val; 59247841Sbapt char *value; 60259266Sbdrewery STAILQ_HEAD(, config_value) *list; 61247841Sbapt bool envset; 62263180Sbdrewery bool main_only; /* Only set in pkg.conf. */ 63247841Sbapt}; 64247841Sbapt 65247841Sbaptstatic struct config_entry c[] = { 66247841Sbapt [PACKAGESITE] = { 67247841Sbapt PKG_CONFIG_STRING, 68247841Sbapt "PACKAGESITE", 69257051Sbdrewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 70247841Sbapt NULL, 71259266Sbdrewery NULL, 72247841Sbapt false, 73263180Sbdrewery false, 74247841Sbapt }, 75247841Sbapt [ABI] = { 76247841Sbapt PKG_CONFIG_STRING, 77247841Sbapt "ABI", 78247841Sbapt NULL, 79247841Sbapt NULL, 80259266Sbdrewery NULL, 81247841Sbapt false, 82263180Sbdrewery true, 83247841Sbapt }, 84247841Sbapt [MIRROR_TYPE] = { 85247841Sbapt PKG_CONFIG_STRING, 86247841Sbapt "MIRROR_TYPE", 87247841Sbapt "SRV", 88247841Sbapt NULL, 89259266Sbdrewery NULL, 90247841Sbapt false, 91263180Sbdrewery false, 92247841Sbapt }, 93247841Sbapt [ASSUME_ALWAYS_YES] = { 94247841Sbapt PKG_CONFIG_BOOL, 95247841Sbapt "ASSUME_ALWAYS_YES", 96247841Sbapt "NO", 97247841Sbapt NULL, 98259266Sbdrewery NULL, 99247841Sbapt false, 100263180Sbdrewery true, 101257147Sbdrewery }, 102257147Sbdrewery [SIGNATURE_TYPE] = { 103257147Sbdrewery PKG_CONFIG_STRING, 104257147Sbdrewery "SIGNATURE_TYPE", 105257147Sbdrewery NULL, 106257147Sbdrewery NULL, 107259266Sbdrewery NULL, 108257147Sbdrewery false, 109263180Sbdrewery false, 110257147Sbdrewery }, 111257147Sbdrewery [FINGERPRINTS] = { 112257147Sbdrewery PKG_CONFIG_STRING, 113257147Sbdrewery "FINGERPRINTS", 114257147Sbdrewery NULL, 115257147Sbdrewery NULL, 116259266Sbdrewery NULL, 117257147Sbdrewery false, 118263180Sbdrewery false, 119257147Sbdrewery }, 120259266Sbdrewery [REPOS_DIR] = { 121259266Sbdrewery PKG_CONFIG_LIST, 122259266Sbdrewery "REPOS_DIR", 123259266Sbdrewery NULL, 124259266Sbdrewery NULL, 125259266Sbdrewery NULL, 126259266Sbdrewery false, 127263180Sbdrewery true, 128259266Sbdrewery }, 129287579Sbapt [PUBKEY] = { 130287579Sbapt PKG_CONFIG_STRING, 131287579Sbapt "PUBKEY", 132287579Sbapt NULL, 133287579Sbapt NULL, 134287579Sbapt NULL, 135287579Sbapt false, 136287579Sbapt false 137287579Sbapt } 138247841Sbapt}; 139247841Sbapt 140273754Snwhitehornstatic int 141273754Snwhitehornpkg_get_myabi(char *dest, size_t sz) 142247841Sbapt{ 143273754Snwhitehorn struct utsname uts; 144273754Snwhitehorn char machine_arch[255]; 145273754Snwhitehorn size_t len; 146273754Snwhitehorn int error; 147247841Sbapt 148273754Snwhitehorn error = uname(&uts); 149273754Snwhitehorn if (error) 150273754Snwhitehorn return (errno); 151247841Sbapt 152273754Snwhitehorn len = sizeof(machine_arch); 153273754Snwhitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 154273754Snwhitehorn if (error) 155273754Snwhitehorn return (errno); 156273754Snwhitehorn machine_arch[len] = '\0'; 157247841Sbapt 158255457Sbapt /* 159273754Snwhitehorn * Use __FreeBSD_version rather than kernel version (uts.release) for 160273754Snwhitehorn * use in jails. This is equivalent to the value of uname -U. 161255457Sbapt */ 162273754Snwhitehorn snprintf(dest, sz, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 163273754Snwhitehorn machine_arch); 164255457Sbapt 165273754Snwhitehorn return (error); 166255457Sbapt} 167255457Sbapt 168247841Sbaptstatic void 169247841Sbaptsubst_packagesite(const char *abi) 170247841Sbapt{ 171247841Sbapt struct sbuf *newval; 172247841Sbapt const char *variable_string; 173247841Sbapt const char *oldval; 174247841Sbapt 175247841Sbapt if (c[PACKAGESITE].value != NULL) 176247841Sbapt oldval = c[PACKAGESITE].value; 177247841Sbapt else 178247841Sbapt oldval = c[PACKAGESITE].val; 179247841Sbapt 180247841Sbapt if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 181247841Sbapt return; 182247841Sbapt 183247841Sbapt newval = sbuf_new_auto(); 184247841Sbapt sbuf_bcat(newval, oldval, variable_string - oldval); 185247841Sbapt sbuf_cat(newval, abi); 186247841Sbapt sbuf_cat(newval, variable_string + strlen("${ABI}")); 187247841Sbapt sbuf_finish(newval); 188247841Sbapt 189247841Sbapt free(c[PACKAGESITE].value); 190247841Sbapt c[PACKAGESITE].value = strdup(sbuf_data(newval)); 191247841Sbapt} 192247841Sbapt 193259266Sbdrewerystatic int 194259266Sbdreweryboolstr_to_bool(const char *str) 195259266Sbdrewery{ 196259266Sbdrewery if (str != NULL && (strcasecmp(str, "true") == 0 || 197259266Sbdrewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 198259266Sbdrewery str[0] == '1')) 199259266Sbdrewery return (true); 200259266Sbdrewery 201259266Sbdrewery return (false); 202259266Sbdrewery} 203259266Sbdrewery 204247841Sbaptstatic void 205264789Sbaptconfig_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 206247841Sbapt{ 207247841Sbapt struct sbuf *buf = sbuf_new_auto(); 208264789Sbapt const ucl_object_t *cur, *seq; 209262400Sbapt ucl_object_iter_t it = NULL, itseq = NULL; 210259266Sbdrewery struct config_entry *temp_config; 211259266Sbdrewery struct config_value *cv; 212262400Sbapt const char *key; 213247841Sbapt int i; 214247841Sbapt size_t j; 215247841Sbapt 216259266Sbdrewery /* Temporary config for configs that may be disabled. */ 217259266Sbdrewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 218259266Sbdrewery 219262400Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 220262400Sbapt key = ucl_object_key(cur); 221262400Sbapt if (key == NULL) 222247841Sbapt continue; 223247841Sbapt sbuf_clear(buf); 224247841Sbapt 225257145Sbdrewery if (conftype == CONFFILE_PKG) { 226262400Sbapt for (j = 0; j < strlen(key); ++j) 227262400Sbapt sbuf_putc(buf, key[j]); 228257145Sbdrewery sbuf_finish(buf); 229257145Sbdrewery } else if (conftype == CONFFILE_REPO) { 230262400Sbapt if (strcasecmp(key, "url") == 0) 231257145Sbdrewery sbuf_cpy(buf, "PACKAGESITE"); 232262400Sbapt else if (strcasecmp(key, "mirror_type") == 0) 233257145Sbdrewery sbuf_cpy(buf, "MIRROR_TYPE"); 234262400Sbapt else if (strcasecmp(key, "signature_type") == 0) 235257147Sbdrewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 236262400Sbapt else if (strcasecmp(key, "fingerprints") == 0) 237257147Sbdrewery sbuf_cpy(buf, "FINGERPRINTS"); 238287579Sbapt else if (strcasecmp(key, "pubkey") == 0) 239287579Sbapt sbuf_cpy(buf, "PUBKEY"); 240262400Sbapt else if (strcasecmp(key, "enabled") == 0) { 241262400Sbapt if ((cur->type != UCL_BOOLEAN) || 242262400Sbapt !ucl_object_toboolean(cur)) 243259266Sbdrewery goto cleanup; 244262400Sbapt } else 245257145Sbdrewery continue; 246257145Sbdrewery sbuf_finish(buf); 247257145Sbdrewery } 248257145Sbdrewery 249247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) { 250247841Sbapt if (strcmp(sbuf_data(buf), c[i].key) == 0) 251247841Sbapt break; 252247841Sbapt } 253247841Sbapt 254257145Sbdrewery /* Silently skip unknown keys to be future compatible. */ 255262400Sbapt if (i == CONFIG_SIZE) 256247841Sbapt continue; 257247841Sbapt 258247841Sbapt /* env has priority over config file */ 259262400Sbapt if (c[i].envset) 260247841Sbapt continue; 261247841Sbapt 262259266Sbdrewery /* Parse sequence value ["item1", "item2"] */ 263259266Sbdrewery switch (c[i].type) { 264259266Sbdrewery case PKG_CONFIG_LIST: 265262400Sbapt if (cur->type != UCL_ARRAY) { 266262400Sbapt warnx("Skipping invalid array " 267259266Sbdrewery "value for %s.\n", c[i].key); 268259266Sbdrewery continue; 269259266Sbdrewery } 270259266Sbdrewery temp_config[i].list = 271259266Sbdrewery malloc(sizeof(*temp_config[i].list)); 272259266Sbdrewery STAILQ_INIT(temp_config[i].list); 273259266Sbdrewery 274262400Sbapt while ((seq = ucl_iterate_object(cur, &itseq, true))) { 275262400Sbapt if (seq->type != UCL_STRING) 276259266Sbdrewery continue; 277259266Sbdrewery cv = malloc(sizeof(struct config_value)); 278259266Sbdrewery cv->value = 279262400Sbapt strdup(ucl_object_tostring(seq)); 280259266Sbdrewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 281259266Sbdrewery next); 282259266Sbdrewery } 283259266Sbdrewery break; 284263181Sbdrewery case PKG_CONFIG_BOOL: 285263181Sbdrewery temp_config[i].value = 286263181Sbdrewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 287263181Sbdrewery break; 288259266Sbdrewery default: 289259266Sbdrewery /* Normal string value. */ 290262400Sbapt temp_config[i].value = strdup(ucl_object_tostring(cur)); 291259266Sbdrewery break; 292259266Sbdrewery } 293247841Sbapt } 294247841Sbapt 295259266Sbdrewery /* Repo is enabled, copy over all settings from temp_config. */ 296259266Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 297259266Sbdrewery if (c[i].envset) 298259266Sbdrewery continue; 299263180Sbdrewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 300263180Sbdrewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 301263180Sbdrewery continue; 302259266Sbdrewery switch (c[i].type) { 303259266Sbdrewery case PKG_CONFIG_LIST: 304259266Sbdrewery c[i].list = temp_config[i].list; 305259266Sbdrewery break; 306259266Sbdrewery default: 307259266Sbdrewery c[i].value = temp_config[i].value; 308259266Sbdrewery break; 309259266Sbdrewery } 310259266Sbdrewery } 311259266Sbdrewery 312259266Sbdrewerycleanup: 313259266Sbdrewery free(temp_config); 314247841Sbapt sbuf_delete(buf); 315247841Sbapt} 316247841Sbapt 317257145Sbdrewery/*- 318257145Sbdrewery * Parse new repo style configs in style: 319257145Sbdrewery * Name: 320257145Sbdrewery * URL: 321257145Sbdrewery * MIRROR_TYPE: 322257145Sbdrewery * etc... 323257145Sbdrewery */ 324257145Sbdrewerystatic void 325262400Sbaptparse_repo_file(ucl_object_t *obj) 326247841Sbapt{ 327262400Sbapt ucl_object_iter_t it = NULL; 328264789Sbapt const ucl_object_t *cur; 329262400Sbapt const char *key; 330257145Sbdrewery 331262400Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 332262400Sbapt key = ucl_object_key(cur); 333257145Sbdrewery 334262400Sbapt if (key == NULL) 335257145Sbdrewery continue; 336257145Sbdrewery 337262400Sbapt if (cur->type != UCL_OBJECT) 338257145Sbdrewery continue; 339257145Sbdrewery 340262400Sbapt config_parse(cur, CONFFILE_REPO); 341257145Sbdrewery } 342257145Sbdrewery} 343257145Sbdrewery 344257145Sbdrewery 345257145Sbdrewerystatic int 346257145Sbdreweryread_conf_file(const char *confpath, pkg_conf_file_t conftype) 347257145Sbdrewery{ 348262400Sbapt struct ucl_parser *p; 349262400Sbapt ucl_object_t *obj = NULL; 350247841Sbapt 351262400Sbapt p = ucl_parser_new(0); 352262400Sbapt 353262400Sbapt if (!ucl_parser_add_file(p, confpath)) { 354247841Sbapt if (errno != ENOENT) 355262400Sbapt errx(EXIT_FAILURE, "Unable to parse configuration " 356262400Sbapt "file %s: %s", confpath, ucl_parser_get_error(p)); 357262400Sbapt ucl_parser_free(p); 358247841Sbapt /* no configuration present */ 359257145Sbdrewery return (1); 360247841Sbapt } 361247841Sbapt 362262400Sbapt obj = ucl_parser_get_object(p); 363262400Sbapt if (obj->type != UCL_OBJECT) 364257142Sbdrewery warnx("Invalid configuration format, ignoring the " 365257145Sbdrewery "configuration file %s", confpath); 366257145Sbdrewery else { 367257145Sbdrewery if (conftype == CONFFILE_PKG) 368262400Sbapt config_parse(obj, conftype); 369257145Sbdrewery else if (conftype == CONFFILE_REPO) 370262400Sbapt parse_repo_file(obj); 371247841Sbapt } 372247841Sbapt 373264789Sbapt ucl_object_unref(obj); 374262400Sbapt ucl_parser_free(p); 375247841Sbapt 376257145Sbdrewery return (0); 377257145Sbdrewery} 378257145Sbdrewery 379259266Sbdrewerystatic int 380259266Sbdreweryload_repositories(const char *repodir) 381259266Sbdrewery{ 382259266Sbdrewery struct dirent *ent; 383259266Sbdrewery DIR *d; 384259266Sbdrewery char *p; 385259266Sbdrewery size_t n; 386259266Sbdrewery char path[MAXPATHLEN]; 387259266Sbdrewery int ret; 388259266Sbdrewery 389259266Sbdrewery ret = 0; 390259266Sbdrewery 391259266Sbdrewery if ((d = opendir(repodir)) == NULL) 392259266Sbdrewery return (1); 393259266Sbdrewery 394259266Sbdrewery while ((ent = readdir(d))) { 395259266Sbdrewery /* Trim out 'repos'. */ 396259266Sbdrewery if ((n = strlen(ent->d_name)) <= 5) 397259266Sbdrewery continue; 398259266Sbdrewery p = &ent->d_name[n - 5]; 399259266Sbdrewery if (strcmp(p, ".conf") == 0) { 400259266Sbdrewery snprintf(path, sizeof(path), "%s%s%s", 401259266Sbdrewery repodir, 402259266Sbdrewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 403259266Sbdrewery ent->d_name); 404259266Sbdrewery if (access(path, F_OK) == 0 && 405259266Sbdrewery read_conf_file(path, CONFFILE_REPO)) { 406259266Sbdrewery ret = 1; 407259266Sbdrewery goto cleanup; 408259266Sbdrewery } 409259266Sbdrewery } 410259266Sbdrewery } 411259266Sbdrewery 412259266Sbdrewerycleanup: 413259266Sbdrewery closedir(d); 414259266Sbdrewery 415259266Sbdrewery return (ret); 416259266Sbdrewery} 417259266Sbdrewery 418257145Sbdreweryint 419257145Sbdreweryconfig_init(void) 420257145Sbdrewery{ 421259266Sbdrewery char *val; 422257145Sbdrewery int i; 423257145Sbdrewery const char *localbase; 424259266Sbdrewery char *env_list_item; 425257145Sbdrewery char confpath[MAXPATHLEN]; 426259266Sbdrewery struct config_value *cv; 427257145Sbdrewery char abi[BUFSIZ]; 428257145Sbdrewery 429257145Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 430257145Sbdrewery val = getenv(c[i].key); 431257145Sbdrewery if (val != NULL) { 432257145Sbdrewery c[i].envset = true; 433259266Sbdrewery switch (c[i].type) { 434259266Sbdrewery case PKG_CONFIG_LIST: 435259266Sbdrewery /* Split up comma-separated items from env. */ 436259266Sbdrewery c[i].list = malloc(sizeof(*c[i].list)); 437259266Sbdrewery STAILQ_INIT(c[i].list); 438259266Sbdrewery for (env_list_item = strtok(val, ","); 439259266Sbdrewery env_list_item != NULL; 440259266Sbdrewery env_list_item = strtok(NULL, ",")) { 441259266Sbdrewery cv = 442259266Sbdrewery malloc(sizeof(struct config_value)); 443259266Sbdrewery cv->value = 444259266Sbdrewery strdup(env_list_item); 445259266Sbdrewery STAILQ_INSERT_TAIL(c[i].list, cv, 446259266Sbdrewery next); 447259266Sbdrewery } 448259266Sbdrewery break; 449259266Sbdrewery default: 450259266Sbdrewery c[i].val = val; 451259266Sbdrewery break; 452259266Sbdrewery } 453257145Sbdrewery } 454257145Sbdrewery } 455257145Sbdrewery 456259266Sbdrewery /* Read LOCALBASE/etc/pkg.conf first. */ 457257145Sbdrewery localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 458257145Sbdrewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 459257145Sbdrewery localbase); 460257145Sbdrewery 461257145Sbdrewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 462257145Sbdrewery CONFFILE_PKG)) 463257145Sbdrewery goto finalize; 464257145Sbdrewery 465259266Sbdrewery /* Then read in all repos from REPOS_DIR list of directories. */ 466259266Sbdrewery if (c[REPOS_DIR].list == NULL) { 467259266Sbdrewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 468259266Sbdrewery STAILQ_INIT(c[REPOS_DIR].list); 469259266Sbdrewery cv = malloc(sizeof(struct config_value)); 470259266Sbdrewery cv->value = strdup("/etc/pkg"); 471259266Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 472259266Sbdrewery cv = malloc(sizeof(struct config_value)); 473259266Sbdrewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 474259266Sbdrewery goto finalize; 475259266Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 476259266Sbdrewery } 477257145Sbdrewery 478259266Sbdrewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 479259266Sbdrewery if (load_repositories(cv->value)) 480259266Sbdrewery goto finalize; 481259266Sbdrewery 482247841Sbaptfinalize: 483247841Sbapt if (c[ABI].val == NULL && c[ABI].value == NULL) { 484247841Sbapt if (pkg_get_myabi(abi, BUFSIZ) != 0) 485257142Sbdrewery errx(EXIT_FAILURE, "Failed to determine the system " 486257142Sbdrewery "ABI"); 487247841Sbapt c[ABI].val = abi; 488247841Sbapt } 489247841Sbapt 490247843Sbapt subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 491247841Sbapt 492247841Sbapt return (0); 493247841Sbapt} 494247841Sbapt 495247841Sbaptint 496247841Sbaptconfig_string(pkg_config_key k, const char **val) 497247841Sbapt{ 498247841Sbapt if (c[k].type != PKG_CONFIG_STRING) 499247841Sbapt return (-1); 500247841Sbapt 501247841Sbapt if (c[k].value != NULL) 502247841Sbapt *val = c[k].value; 503247841Sbapt else 504247841Sbapt *val = c[k].val; 505247841Sbapt 506247841Sbapt return (0); 507247841Sbapt} 508247841Sbapt 509247841Sbaptint 510247841Sbaptconfig_bool(pkg_config_key k, bool *val) 511247841Sbapt{ 512247841Sbapt const char *value; 513247841Sbapt 514247841Sbapt if (c[k].type != PKG_CONFIG_BOOL) 515247841Sbapt return (-1); 516247841Sbapt 517247841Sbapt *val = false; 518247841Sbapt 519247841Sbapt if (c[k].value != NULL) 520247841Sbapt value = c[k].value; 521247841Sbapt else 522247841Sbapt value = c[k].val; 523247841Sbapt 524259266Sbdrewery if (boolstr_to_bool(value)) 525247841Sbapt *val = true; 526247841Sbapt 527247841Sbapt return (0); 528247841Sbapt} 529247841Sbapt 530247841Sbaptvoid 531247841Sbaptconfig_finish(void) { 532247841Sbapt int i; 533247841Sbapt 534247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) 535247841Sbapt free(c[i].value); 536247841Sbapt} 537