config.c revision 287579
1247841Sbapt/*- 2262401Sbapt * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> 3257147Sbdrewery * 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: head/usr.sbin/pkg/config.c 287579 2015-09-08 21:25:36Z bapt $"); 30247841Sbapt 31247841Sbapt#include <sys/param.h> 32260942Sbapt#include <sys/queue.h> 33247841Sbapt#include <sys/sbuf.h> 34259266Sbdrewery#include <sys/types.h> 35273754Snwhitehorn#include <sys/utsname.h> 36273754Snwhitehorn#include <sys/sysctl.h> 37247841Sbapt 38255457Sbapt#include <assert.h> 39259266Sbdrewery#include <dirent.h> 40262400Sbapt#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 55259266Sbdrewerystruct config_value { 56259266Sbdrewery char *value; 57259266Sbdrewery STAILQ_ENTRY(config_value) next; 58259266Sbdrewery}; 59259266Sbdrewery 60247841Sbaptstruct config_entry { 61247841Sbapt uint8_t type; 62247841Sbapt const char *key; 63247841Sbapt const char *val; 64247841Sbapt char *value; 65259266Sbdrewery STAILQ_HEAD(, config_value) *list; 66247841Sbapt bool envset; 67263180Sbdrewery bool main_only; /* Only set in pkg.conf. */ 68247841Sbapt}; 69247841Sbapt 70247841Sbaptstatic struct config_entry c[] = { 71247841Sbapt [PACKAGESITE] = { 72247841Sbapt PKG_CONFIG_STRING, 73247841Sbapt "PACKAGESITE", 74257051Sbdrewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 75247841Sbapt NULL, 76259266Sbdrewery NULL, 77247841Sbapt false, 78263180Sbdrewery false, 79247841Sbapt }, 80247841Sbapt [ABI] = { 81247841Sbapt PKG_CONFIG_STRING, 82247841Sbapt "ABI", 83247841Sbapt NULL, 84247841Sbapt NULL, 85259266Sbdrewery NULL, 86247841Sbapt false, 87263180Sbdrewery true, 88247841Sbapt }, 89247841Sbapt [MIRROR_TYPE] = { 90247841Sbapt PKG_CONFIG_STRING, 91247841Sbapt "MIRROR_TYPE", 92247841Sbapt "SRV", 93247841Sbapt NULL, 94259266Sbdrewery NULL, 95247841Sbapt false, 96263180Sbdrewery false, 97247841Sbapt }, 98247841Sbapt [ASSUME_ALWAYS_YES] = { 99247841Sbapt PKG_CONFIG_BOOL, 100247841Sbapt "ASSUME_ALWAYS_YES", 101247841Sbapt "NO", 102247841Sbapt NULL, 103259266Sbdrewery NULL, 104247841Sbapt false, 105263180Sbdrewery true, 106257147Sbdrewery }, 107257147Sbdrewery [SIGNATURE_TYPE] = { 108257147Sbdrewery PKG_CONFIG_STRING, 109257147Sbdrewery "SIGNATURE_TYPE", 110257147Sbdrewery NULL, 111257147Sbdrewery NULL, 112259266Sbdrewery NULL, 113257147Sbdrewery false, 114263180Sbdrewery false, 115257147Sbdrewery }, 116257147Sbdrewery [FINGERPRINTS] = { 117257147Sbdrewery PKG_CONFIG_STRING, 118257147Sbdrewery "FINGERPRINTS", 119257147Sbdrewery NULL, 120257147Sbdrewery NULL, 121259266Sbdrewery NULL, 122257147Sbdrewery false, 123263180Sbdrewery false, 124257147Sbdrewery }, 125259266Sbdrewery [REPOS_DIR] = { 126259266Sbdrewery PKG_CONFIG_LIST, 127259266Sbdrewery "REPOS_DIR", 128259266Sbdrewery NULL, 129259266Sbdrewery NULL, 130259266Sbdrewery NULL, 131259266Sbdrewery false, 132263180Sbdrewery true, 133259266Sbdrewery }, 134287579Sbapt [PUBKEY] = { 135287579Sbapt PKG_CONFIG_STRING, 136287579Sbapt "PUBKEY", 137287579Sbapt NULL, 138287579Sbapt NULL, 139287579Sbapt NULL, 140287579Sbapt false, 141287579Sbapt false 142287579Sbapt } 143247841Sbapt}; 144247841Sbapt 145273754Snwhitehornstatic int 146273754Snwhitehornpkg_get_myabi(char *dest, size_t sz) 147247841Sbapt{ 148273754Snwhitehorn struct utsname uts; 149273754Snwhitehorn char machine_arch[255]; 150273754Snwhitehorn size_t len; 151273754Snwhitehorn int error; 152247841Sbapt 153273754Snwhitehorn error = uname(&uts); 154273754Snwhitehorn if (error) 155273754Snwhitehorn return (errno); 156247841Sbapt 157273754Snwhitehorn len = sizeof(machine_arch); 158273754Snwhitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 159273754Snwhitehorn if (error) 160273754Snwhitehorn return (errno); 161273754Snwhitehorn machine_arch[len] = '\0'; 162247841Sbapt 163255457Sbapt /* 164273754Snwhitehorn * Use __FreeBSD_version rather than kernel version (uts.release) for 165273754Snwhitehorn * use in jails. This is equivalent to the value of uname -U. 166255457Sbapt */ 167273754Snwhitehorn snprintf(dest, sz, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 168273754Snwhitehorn machine_arch); 169255457Sbapt 170273754Snwhitehorn 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 198259266Sbdrewerystatic int 199259266Sbdreweryboolstr_to_bool(const char *str) 200259266Sbdrewery{ 201259266Sbdrewery if (str != NULL && (strcasecmp(str, "true") == 0 || 202259266Sbdrewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 203259266Sbdrewery str[0] == '1')) 204259266Sbdrewery return (true); 205259266Sbdrewery 206259266Sbdrewery return (false); 207259266Sbdrewery} 208259266Sbdrewery 209247841Sbaptstatic void 210264789Sbaptconfig_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 211247841Sbapt{ 212247841Sbapt struct sbuf *buf = sbuf_new_auto(); 213264789Sbapt const ucl_object_t *cur, *seq; 214262400Sbapt ucl_object_iter_t it = NULL, itseq = NULL; 215259266Sbdrewery struct config_entry *temp_config; 216259266Sbdrewery struct config_value *cv; 217262400Sbapt const char *key; 218247841Sbapt int i; 219247841Sbapt size_t j; 220247841Sbapt 221259266Sbdrewery /* Temporary config for configs that may be disabled. */ 222259266Sbdrewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 223259266Sbdrewery 224262400Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 225262400Sbapt key = ucl_object_key(cur); 226262400Sbapt if (key == NULL) 227247841Sbapt continue; 228247841Sbapt sbuf_clear(buf); 229247841Sbapt 230257145Sbdrewery if (conftype == CONFFILE_PKG) { 231262400Sbapt for (j = 0; j < strlen(key); ++j) 232262400Sbapt sbuf_putc(buf, key[j]); 233257145Sbdrewery sbuf_finish(buf); 234257145Sbdrewery } else if (conftype == CONFFILE_REPO) { 235262400Sbapt if (strcasecmp(key, "url") == 0) 236257145Sbdrewery sbuf_cpy(buf, "PACKAGESITE"); 237262400Sbapt else if (strcasecmp(key, "mirror_type") == 0) 238257145Sbdrewery sbuf_cpy(buf, "MIRROR_TYPE"); 239262400Sbapt else if (strcasecmp(key, "signature_type") == 0) 240257147Sbdrewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 241262400Sbapt else if (strcasecmp(key, "fingerprints") == 0) 242257147Sbdrewery sbuf_cpy(buf, "FINGERPRINTS"); 243287579Sbapt else if (strcasecmp(key, "pubkey") == 0) 244287579Sbapt sbuf_cpy(buf, "PUBKEY"); 245262400Sbapt else if (strcasecmp(key, "enabled") == 0) { 246262400Sbapt if ((cur->type != UCL_BOOLEAN) || 247262400Sbapt !ucl_object_toboolean(cur)) 248259266Sbdrewery goto cleanup; 249262400Sbapt } else 250257145Sbdrewery continue; 251257145Sbdrewery sbuf_finish(buf); 252257145Sbdrewery } 253257145Sbdrewery 254247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) { 255247841Sbapt if (strcmp(sbuf_data(buf), c[i].key) == 0) 256247841Sbapt break; 257247841Sbapt } 258247841Sbapt 259257145Sbdrewery /* Silently skip unknown keys to be future compatible. */ 260262400Sbapt if (i == CONFIG_SIZE) 261247841Sbapt continue; 262247841Sbapt 263247841Sbapt /* env has priority over config file */ 264262400Sbapt if (c[i].envset) 265247841Sbapt continue; 266247841Sbapt 267259266Sbdrewery /* Parse sequence value ["item1", "item2"] */ 268259266Sbdrewery switch (c[i].type) { 269259266Sbdrewery case PKG_CONFIG_LIST: 270262400Sbapt if (cur->type != UCL_ARRAY) { 271262400Sbapt warnx("Skipping invalid array " 272259266Sbdrewery "value for %s.\n", c[i].key); 273259266Sbdrewery continue; 274259266Sbdrewery } 275259266Sbdrewery temp_config[i].list = 276259266Sbdrewery malloc(sizeof(*temp_config[i].list)); 277259266Sbdrewery STAILQ_INIT(temp_config[i].list); 278259266Sbdrewery 279262400Sbapt while ((seq = ucl_iterate_object(cur, &itseq, true))) { 280262400Sbapt if (seq->type != UCL_STRING) 281259266Sbdrewery continue; 282259266Sbdrewery cv = malloc(sizeof(struct config_value)); 283259266Sbdrewery cv->value = 284262400Sbapt strdup(ucl_object_tostring(seq)); 285259266Sbdrewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 286259266Sbdrewery next); 287259266Sbdrewery } 288259266Sbdrewery break; 289263181Sbdrewery case PKG_CONFIG_BOOL: 290263181Sbdrewery temp_config[i].value = 291263181Sbdrewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 292263181Sbdrewery break; 293259266Sbdrewery default: 294259266Sbdrewery /* Normal string value. */ 295262400Sbapt temp_config[i].value = strdup(ucl_object_tostring(cur)); 296259266Sbdrewery break; 297259266Sbdrewery } 298247841Sbapt } 299247841Sbapt 300259266Sbdrewery /* Repo is enabled, copy over all settings from temp_config. */ 301259266Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 302259266Sbdrewery if (c[i].envset) 303259266Sbdrewery continue; 304263180Sbdrewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 305263180Sbdrewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 306263180Sbdrewery continue; 307259266Sbdrewery switch (c[i].type) { 308259266Sbdrewery case PKG_CONFIG_LIST: 309259266Sbdrewery c[i].list = temp_config[i].list; 310259266Sbdrewery break; 311259266Sbdrewery default: 312259266Sbdrewery c[i].value = temp_config[i].value; 313259266Sbdrewery break; 314259266Sbdrewery } 315259266Sbdrewery } 316259266Sbdrewery 317259266Sbdrewerycleanup: 318259266Sbdrewery free(temp_config); 319247841Sbapt sbuf_delete(buf); 320247841Sbapt} 321247841Sbapt 322257145Sbdrewery/*- 323257145Sbdrewery * Parse new repo style configs in style: 324257145Sbdrewery * Name: 325257145Sbdrewery * URL: 326257145Sbdrewery * MIRROR_TYPE: 327257145Sbdrewery * etc... 328257145Sbdrewery */ 329257145Sbdrewerystatic void 330262400Sbaptparse_repo_file(ucl_object_t *obj) 331247841Sbapt{ 332262400Sbapt ucl_object_iter_t it = NULL; 333264789Sbapt const ucl_object_t *cur; 334262400Sbapt const char *key; 335257145Sbdrewery 336262400Sbapt while ((cur = ucl_iterate_object(obj, &it, true))) { 337262400Sbapt key = ucl_object_key(cur); 338257145Sbdrewery 339262400Sbapt if (key == NULL) 340257145Sbdrewery continue; 341257145Sbdrewery 342262400Sbapt if (cur->type != UCL_OBJECT) 343257145Sbdrewery continue; 344257145Sbdrewery 345262400Sbapt config_parse(cur, CONFFILE_REPO); 346257145Sbdrewery } 347257145Sbdrewery} 348257145Sbdrewery 349257145Sbdrewery 350257145Sbdrewerystatic int 351257145Sbdreweryread_conf_file(const char *confpath, pkg_conf_file_t conftype) 352257145Sbdrewery{ 353262400Sbapt struct ucl_parser *p; 354262400Sbapt ucl_object_t *obj = NULL; 355247841Sbapt 356262400Sbapt p = ucl_parser_new(0); 357262400Sbapt 358262400Sbapt if (!ucl_parser_add_file(p, confpath)) { 359247841Sbapt if (errno != ENOENT) 360262400Sbapt errx(EXIT_FAILURE, "Unable to parse configuration " 361262400Sbapt "file %s: %s", confpath, ucl_parser_get_error(p)); 362262400Sbapt ucl_parser_free(p); 363247841Sbapt /* no configuration present */ 364257145Sbdrewery return (1); 365247841Sbapt } 366247841Sbapt 367262400Sbapt obj = ucl_parser_get_object(p); 368262400Sbapt if (obj->type != UCL_OBJECT) 369257142Sbdrewery warnx("Invalid configuration format, ignoring the " 370257145Sbdrewery "configuration file %s", confpath); 371257145Sbdrewery else { 372257145Sbdrewery if (conftype == CONFFILE_PKG) 373262400Sbapt config_parse(obj, conftype); 374257145Sbdrewery else if (conftype == CONFFILE_REPO) 375262400Sbapt parse_repo_file(obj); 376247841Sbapt } 377247841Sbapt 378264789Sbapt ucl_object_unref(obj); 379262400Sbapt ucl_parser_free(p); 380247841Sbapt 381257145Sbdrewery return (0); 382257145Sbdrewery} 383257145Sbdrewery 384259266Sbdrewerystatic int 385259266Sbdreweryload_repositories(const char *repodir) 386259266Sbdrewery{ 387259266Sbdrewery struct dirent *ent; 388259266Sbdrewery DIR *d; 389259266Sbdrewery char *p; 390259266Sbdrewery size_t n; 391259266Sbdrewery char path[MAXPATHLEN]; 392259266Sbdrewery int ret; 393259266Sbdrewery 394259266Sbdrewery ret = 0; 395259266Sbdrewery 396259266Sbdrewery if ((d = opendir(repodir)) == NULL) 397259266Sbdrewery return (1); 398259266Sbdrewery 399259266Sbdrewery while ((ent = readdir(d))) { 400259266Sbdrewery /* Trim out 'repos'. */ 401259266Sbdrewery if ((n = strlen(ent->d_name)) <= 5) 402259266Sbdrewery continue; 403259266Sbdrewery p = &ent->d_name[n - 5]; 404259266Sbdrewery if (strcmp(p, ".conf") == 0) { 405259266Sbdrewery snprintf(path, sizeof(path), "%s%s%s", 406259266Sbdrewery repodir, 407259266Sbdrewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 408259266Sbdrewery ent->d_name); 409259266Sbdrewery if (access(path, F_OK) == 0 && 410259266Sbdrewery read_conf_file(path, CONFFILE_REPO)) { 411259266Sbdrewery ret = 1; 412259266Sbdrewery goto cleanup; 413259266Sbdrewery } 414259266Sbdrewery } 415259266Sbdrewery } 416259266Sbdrewery 417259266Sbdrewerycleanup: 418259266Sbdrewery closedir(d); 419259266Sbdrewery 420259266Sbdrewery return (ret); 421259266Sbdrewery} 422259266Sbdrewery 423257145Sbdreweryint 424257145Sbdreweryconfig_init(void) 425257145Sbdrewery{ 426259266Sbdrewery char *val; 427257145Sbdrewery int i; 428257145Sbdrewery const char *localbase; 429259266Sbdrewery char *env_list_item; 430257145Sbdrewery char confpath[MAXPATHLEN]; 431259266Sbdrewery struct config_value *cv; 432257145Sbdrewery char abi[BUFSIZ]; 433257145Sbdrewery 434257145Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 435257145Sbdrewery val = getenv(c[i].key); 436257145Sbdrewery if (val != NULL) { 437257145Sbdrewery c[i].envset = true; 438259266Sbdrewery switch (c[i].type) { 439259266Sbdrewery case PKG_CONFIG_LIST: 440259266Sbdrewery /* Split up comma-separated items from env. */ 441259266Sbdrewery c[i].list = malloc(sizeof(*c[i].list)); 442259266Sbdrewery STAILQ_INIT(c[i].list); 443259266Sbdrewery for (env_list_item = strtok(val, ","); 444259266Sbdrewery env_list_item != NULL; 445259266Sbdrewery env_list_item = strtok(NULL, ",")) { 446259266Sbdrewery cv = 447259266Sbdrewery malloc(sizeof(struct config_value)); 448259266Sbdrewery cv->value = 449259266Sbdrewery strdup(env_list_item); 450259266Sbdrewery STAILQ_INSERT_TAIL(c[i].list, cv, 451259266Sbdrewery next); 452259266Sbdrewery } 453259266Sbdrewery break; 454259266Sbdrewery default: 455259266Sbdrewery c[i].val = val; 456259266Sbdrewery break; 457259266Sbdrewery } 458257145Sbdrewery } 459257145Sbdrewery } 460257145Sbdrewery 461259266Sbdrewery /* Read LOCALBASE/etc/pkg.conf first. */ 462257145Sbdrewery localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 463257145Sbdrewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 464257145Sbdrewery localbase); 465257145Sbdrewery 466257145Sbdrewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 467257145Sbdrewery CONFFILE_PKG)) 468257145Sbdrewery goto finalize; 469257145Sbdrewery 470259266Sbdrewery /* Then read in all repos from REPOS_DIR list of directories. */ 471259266Sbdrewery if (c[REPOS_DIR].list == NULL) { 472259266Sbdrewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 473259266Sbdrewery STAILQ_INIT(c[REPOS_DIR].list); 474259266Sbdrewery cv = malloc(sizeof(struct config_value)); 475259266Sbdrewery cv->value = strdup("/etc/pkg"); 476259266Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 477259266Sbdrewery cv = malloc(sizeof(struct config_value)); 478259266Sbdrewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 479259266Sbdrewery goto finalize; 480259266Sbdrewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 481259266Sbdrewery } 482257145Sbdrewery 483259266Sbdrewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 484259266Sbdrewery if (load_repositories(cv->value)) 485259266Sbdrewery goto finalize; 486259266Sbdrewery 487247841Sbaptfinalize: 488247841Sbapt if (c[ABI].val == NULL && c[ABI].value == NULL) { 489247841Sbapt if (pkg_get_myabi(abi, BUFSIZ) != 0) 490257142Sbdrewery errx(EXIT_FAILURE, "Failed to determine the system " 491257142Sbdrewery "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 529259266Sbdrewery 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