19950eceeSBaptiste Daroussin /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 40ad5dbacSBaptiste Daroussin * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> 5f12db248SBryan Drewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 69950eceeSBaptiste Daroussin * All rights reserved. 79950eceeSBaptiste Daroussin * 89950eceeSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 99950eceeSBaptiste Daroussin * modification, are permitted provided that the following conditions 109950eceeSBaptiste Daroussin * are met: 119950eceeSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 129950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 139950eceeSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 149950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 159950eceeSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 169950eceeSBaptiste Daroussin * 179950eceeSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 189950eceeSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 199950eceeSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 209950eceeSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 219950eceeSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 229950eceeSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 239950eceeSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 249950eceeSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 259950eceeSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 269950eceeSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 279950eceeSBaptiste Daroussin * SUCH DAMAGE. 289950eceeSBaptiste Daroussin */ 299950eceeSBaptiste Daroussin 309950eceeSBaptiste Daroussin #include <sys/cdefs.h> 319950eceeSBaptiste Daroussin #include <sys/param.h> 32a351c93dSBaptiste Daroussin #include <sys/queue.h> 3360b9a1fcSNathan Whitehorn #include <sys/utsname.h> 3460b9a1fcSNathan Whitehorn #include <sys/sysctl.h> 359950eceeSBaptiste Daroussin 36eb31a574SBryan Drewery #include <dirent.h> 378a7d859eSBaptiste Daroussin #include <ucl.h> 389950eceeSBaptiste Daroussin #include <err.h> 399950eceeSBaptiste Daroussin #include <errno.h> 4056d11d4aSStefan Eßer #include <libutil.h> 411f474190SStefan Eßer #include <paths.h> 429950eceeSBaptiste Daroussin #include <stdbool.h> 439950eceeSBaptiste Daroussin #include <unistd.h> 44e869d3c6SMoritz Schmitt #include <ctype.h> 459950eceeSBaptiste Daroussin 469950eceeSBaptiste Daroussin #include "config.h" 479950eceeSBaptiste Daroussin 48eb31a574SBryan Drewery struct config_value { 49eb31a574SBryan Drewery char *value; 50eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 51eb31a574SBryan Drewery }; 52eb31a574SBryan Drewery 539950eceeSBaptiste Daroussin struct config_entry { 549950eceeSBaptiste Daroussin uint8_t type; 559950eceeSBaptiste Daroussin const char *key; 569950eceeSBaptiste Daroussin const char *val; 579950eceeSBaptiste Daroussin char *value; 58eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 599950eceeSBaptiste Daroussin bool envset; 6097c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 619950eceeSBaptiste Daroussin }; 629950eceeSBaptiste Daroussin 639950eceeSBaptiste Daroussin static struct config_entry c[] = { 649950eceeSBaptiste Daroussin [PACKAGESITE] = { 659950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 669950eceeSBaptiste Daroussin "PACKAGESITE", 6762940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 689950eceeSBaptiste Daroussin NULL, 69eb31a574SBryan Drewery NULL, 709950eceeSBaptiste Daroussin false, 7197c3a766SBryan Drewery false, 729950eceeSBaptiste Daroussin }, 739950eceeSBaptiste Daroussin [ABI] = { 749950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 759950eceeSBaptiste Daroussin "ABI", 769950eceeSBaptiste Daroussin NULL, 779950eceeSBaptiste Daroussin NULL, 78eb31a574SBryan Drewery NULL, 799950eceeSBaptiste Daroussin false, 8097c3a766SBryan Drewery true, 819950eceeSBaptiste Daroussin }, 829950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 839950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 849950eceeSBaptiste Daroussin "MIRROR_TYPE", 859950eceeSBaptiste Daroussin "SRV", 869950eceeSBaptiste Daroussin NULL, 87eb31a574SBryan Drewery NULL, 889950eceeSBaptiste Daroussin false, 8997c3a766SBryan Drewery false, 909950eceeSBaptiste Daroussin }, 919950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 929950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 939950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 949950eceeSBaptiste Daroussin "NO", 959950eceeSBaptiste Daroussin NULL, 96eb31a574SBryan Drewery NULL, 979950eceeSBaptiste Daroussin false, 9897c3a766SBryan Drewery true, 99f12db248SBryan Drewery }, 100f12db248SBryan Drewery [SIGNATURE_TYPE] = { 101f12db248SBryan Drewery PKG_CONFIG_STRING, 102f12db248SBryan Drewery "SIGNATURE_TYPE", 103f12db248SBryan Drewery NULL, 104f12db248SBryan Drewery NULL, 105eb31a574SBryan Drewery NULL, 106f12db248SBryan Drewery false, 10797c3a766SBryan Drewery false, 108f12db248SBryan Drewery }, 109f12db248SBryan Drewery [FINGERPRINTS] = { 110f12db248SBryan Drewery PKG_CONFIG_STRING, 111f12db248SBryan Drewery "FINGERPRINTS", 112f12db248SBryan Drewery NULL, 113f12db248SBryan Drewery NULL, 114eb31a574SBryan Drewery NULL, 115eb31a574SBryan Drewery false, 11697c3a766SBryan Drewery false, 117eb31a574SBryan Drewery }, 118eb31a574SBryan Drewery [REPOS_DIR] = { 119eb31a574SBryan Drewery PKG_CONFIG_LIST, 120eb31a574SBryan Drewery "REPOS_DIR", 121eb31a574SBryan Drewery NULL, 122eb31a574SBryan Drewery NULL, 123eb31a574SBryan Drewery NULL, 124f12db248SBryan Drewery false, 12597c3a766SBryan Drewery true, 126f12db248SBryan Drewery }, 12761acb458SBaptiste Daroussin [PUBKEY] = { 12861acb458SBaptiste Daroussin PKG_CONFIG_STRING, 12961acb458SBaptiste Daroussin "PUBKEY", 13061acb458SBaptiste Daroussin NULL, 13161acb458SBaptiste Daroussin NULL, 13261acb458SBaptiste Daroussin NULL, 13361acb458SBaptiste Daroussin false, 13461acb458SBaptiste Daroussin false 135e869d3c6SMoritz Schmitt }, 136e869d3c6SMoritz Schmitt [PKG_ENV] = { 137e869d3c6SMoritz Schmitt PKG_CONFIG_OBJECT, 138e869d3c6SMoritz Schmitt "PKG_ENV", 139e869d3c6SMoritz Schmitt NULL, 140e869d3c6SMoritz Schmitt NULL, 141e869d3c6SMoritz Schmitt NULL, 142e869d3c6SMoritz Schmitt false, 143e869d3c6SMoritz Schmitt false, 14461acb458SBaptiste Daroussin } 1459950eceeSBaptiste Daroussin }; 1469950eceeSBaptiste Daroussin 147*fd9ae9acSJohn Baldwin static char * 148*fd9ae9acSJohn Baldwin pkg_get_myabi(void) 1499950eceeSBaptiste Daroussin { 15060b9a1fcSNathan Whitehorn struct utsname uts; 15160b9a1fcSNathan Whitehorn char machine_arch[255]; 152*fd9ae9acSJohn Baldwin char *abi; 15360b9a1fcSNathan Whitehorn size_t len; 15460b9a1fcSNathan Whitehorn int error; 1559950eceeSBaptiste Daroussin 15660b9a1fcSNathan Whitehorn error = uname(&uts); 15760b9a1fcSNathan Whitehorn if (error) 158*fd9ae9acSJohn Baldwin return (NULL); 1599950eceeSBaptiste Daroussin 16060b9a1fcSNathan Whitehorn len = sizeof(machine_arch); 16160b9a1fcSNathan Whitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 16260b9a1fcSNathan Whitehorn if (error) 163*fd9ae9acSJohn Baldwin return (NULL); 16460b9a1fcSNathan Whitehorn machine_arch[len] = '\0'; 1659950eceeSBaptiste Daroussin 16640274a2dSBaptiste Daroussin /* 16760b9a1fcSNathan Whitehorn * Use __FreeBSD_version rather than kernel version (uts.release) for 16860b9a1fcSNathan Whitehorn * use in jails. This is equivalent to the value of uname -U. 16940274a2dSBaptiste Daroussin */ 170*fd9ae9acSJohn Baldwin error = asprintf(&abi, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 17160b9a1fcSNathan Whitehorn machine_arch); 172*fd9ae9acSJohn Baldwin if (error < 0) 173*fd9ae9acSJohn Baldwin return (NULL); 17440274a2dSBaptiste Daroussin 175*fd9ae9acSJohn Baldwin return (abi); 1769950eceeSBaptiste Daroussin } 1779950eceeSBaptiste Daroussin 1789950eceeSBaptiste Daroussin static void 1799950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 1809950eceeSBaptiste Daroussin { 181ae659caaSBaptiste Daroussin char *newval; 1829950eceeSBaptiste Daroussin const char *variable_string; 1839950eceeSBaptiste Daroussin const char *oldval; 1849950eceeSBaptiste Daroussin 1859950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 1869950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 1879950eceeSBaptiste Daroussin else 1889950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 1899950eceeSBaptiste Daroussin 1909950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 1919950eceeSBaptiste Daroussin return; 1929950eceeSBaptiste Daroussin 193ae659caaSBaptiste Daroussin asprintf(&newval, "%.*s%s%s", 194ae659caaSBaptiste Daroussin (int)(variable_string - oldval), oldval, abi, 195ae659caaSBaptiste Daroussin variable_string + strlen("${ABI}")); 196ae659caaSBaptiste Daroussin if (newval == NULL) 197ae659caaSBaptiste Daroussin errx(EXIT_FAILURE, "asprintf"); 1989950eceeSBaptiste Daroussin 1999950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 200ae659caaSBaptiste Daroussin c[PACKAGESITE].value = newval; 2019950eceeSBaptiste Daroussin } 2029950eceeSBaptiste Daroussin 203eb31a574SBryan Drewery static int 204eb31a574SBryan Drewery boolstr_to_bool(const char *str) 205eb31a574SBryan Drewery { 206eb31a574SBryan Drewery if (str != NULL && (strcasecmp(str, "true") == 0 || 207eb31a574SBryan Drewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 208eb31a574SBryan Drewery str[0] == '1')) 209eb31a574SBryan Drewery return (true); 210eb31a574SBryan Drewery 211eb31a574SBryan Drewery return (false); 212eb31a574SBryan Drewery } 213eb31a574SBryan Drewery 2149950eceeSBaptiste Daroussin static void 215b04a7a0bSBaptiste Daroussin config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 2169950eceeSBaptiste Daroussin { 217cc9a8a11SBaptiste Daroussin FILE *buffp; 218cc9a8a11SBaptiste Daroussin char *buf = NULL; 219cc9a8a11SBaptiste Daroussin size_t bufsz = 0; 220e869d3c6SMoritz Schmitt const ucl_object_t *cur, *seq, *tmp; 221e869d3c6SMoritz Schmitt ucl_object_iter_t it = NULL, itseq = NULL, it_obj = NULL; 222eb31a574SBryan Drewery struct config_entry *temp_config; 223eb31a574SBryan Drewery struct config_value *cv; 224e869d3c6SMoritz Schmitt const char *key, *evkey; 2259950eceeSBaptiste Daroussin int i; 2269950eceeSBaptiste Daroussin size_t j; 2279950eceeSBaptiste Daroussin 228eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 229eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 230cc9a8a11SBaptiste Daroussin buffp = open_memstream(&buf, &bufsz); 231cc9a8a11SBaptiste Daroussin if (buffp == NULL) 232cc9a8a11SBaptiste Daroussin err(EXIT_FAILURE, "open_memstream()"); 233eb31a574SBryan Drewery 2348a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 2358a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 2368a7d859eSBaptiste Daroussin if (key == NULL) 2379950eceeSBaptiste Daroussin continue; 238cc9a8a11SBaptiste Daroussin if (buf != NULL) 239cc9a8a11SBaptiste Daroussin memset(buf, 0, bufsz); 240cc9a8a11SBaptiste Daroussin rewind(buffp); 2419950eceeSBaptiste Daroussin 242bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) { 2438a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 244cc9a8a11SBaptiste Daroussin fputc(toupper(key[j]), buffp); 245cc9a8a11SBaptiste Daroussin fflush(buffp); 246bc5e9ac0SBryan Drewery } else if (conftype == CONFFILE_REPO) { 2478a7d859eSBaptiste Daroussin if (strcasecmp(key, "url") == 0) 248cc9a8a11SBaptiste Daroussin fputs("PACKAGESITE", buffp); 2498a7d859eSBaptiste Daroussin else if (strcasecmp(key, "mirror_type") == 0) 250cc9a8a11SBaptiste Daroussin fputs("MIRROR_TYPE", buffp); 2518a7d859eSBaptiste Daroussin else if (strcasecmp(key, "signature_type") == 0) 252cc9a8a11SBaptiste Daroussin fputs("SIGNATURE_TYPE", buffp); 2538a7d859eSBaptiste Daroussin else if (strcasecmp(key, "fingerprints") == 0) 254cc9a8a11SBaptiste Daroussin fputs("FINGERPRINTS", buffp); 25561acb458SBaptiste Daroussin else if (strcasecmp(key, "pubkey") == 0) 256cc9a8a11SBaptiste Daroussin fputs("PUBKEY", buffp); 2578a7d859eSBaptiste Daroussin else if (strcasecmp(key, "enabled") == 0) { 2588a7d859eSBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 2598a7d859eSBaptiste Daroussin !ucl_object_toboolean(cur)) 260eb31a574SBryan Drewery goto cleanup; 2618a7d859eSBaptiste Daroussin } else 262bc5e9ac0SBryan Drewery continue; 263cc9a8a11SBaptiste Daroussin fflush(buffp); 264bc5e9ac0SBryan Drewery } 265bc5e9ac0SBryan Drewery 2669950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 267cc9a8a11SBaptiste Daroussin if (strcmp(buf, c[i].key) == 0) 2689950eceeSBaptiste Daroussin break; 2699950eceeSBaptiste Daroussin } 2709950eceeSBaptiste Daroussin 271bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 2728a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 2739950eceeSBaptiste Daroussin continue; 2749950eceeSBaptiste Daroussin 2759950eceeSBaptiste Daroussin /* env has priority over config file */ 2768a7d859eSBaptiste Daroussin if (c[i].envset) 2779950eceeSBaptiste Daroussin continue; 2789950eceeSBaptiste Daroussin 279eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 280eb31a574SBryan Drewery switch (c[i].type) { 281eb31a574SBryan Drewery case PKG_CONFIG_LIST: 2828a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 2838a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 284eb31a574SBryan Drewery "value for %s.\n", c[i].key); 285eb31a574SBryan Drewery continue; 286eb31a574SBryan Drewery } 287eb31a574SBryan Drewery temp_config[i].list = 288eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 289eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 290eb31a574SBryan Drewery 2918a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 2928a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 293eb31a574SBryan Drewery continue; 294eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 295eb31a574SBryan Drewery cv->value = 2968a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 297eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 298eb31a574SBryan Drewery next); 299eb31a574SBryan Drewery } 300eb31a574SBryan Drewery break; 301197372c2SBryan Drewery case PKG_CONFIG_BOOL: 302197372c2SBryan Drewery temp_config[i].value = 303197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 304197372c2SBryan Drewery break; 305e869d3c6SMoritz Schmitt case PKG_CONFIG_OBJECT: 306e869d3c6SMoritz Schmitt if (strcmp(c[i].key, "PKG_ENV") == 0) { 307e869d3c6SMoritz Schmitt while ((tmp = 308e869d3c6SMoritz Schmitt ucl_iterate_object(cur, &it_obj, true))) { 309e869d3c6SMoritz Schmitt evkey = ucl_object_key(tmp); 310e869d3c6SMoritz Schmitt if (evkey != NULL && *evkey != '\0') { 311e869d3c6SMoritz Schmitt setenv(evkey, ucl_object_tostring_forced(tmp), 1); 312e869d3c6SMoritz Schmitt } 313e869d3c6SMoritz Schmitt } 314e869d3c6SMoritz Schmitt } 315e869d3c6SMoritz Schmitt break; 316eb31a574SBryan Drewery default: 317eb31a574SBryan Drewery /* Normal string value. */ 3188a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 319eb31a574SBryan Drewery break; 320eb31a574SBryan Drewery } 3219950eceeSBaptiste Daroussin } 3229950eceeSBaptiste Daroussin 323eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 324eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 325eb31a574SBryan Drewery if (c[i].envset) 326eb31a574SBryan Drewery continue; 32797c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 32897c3a766SBryan Drewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 32997c3a766SBryan Drewery continue; 330eb31a574SBryan Drewery switch (c[i].type) { 331eb31a574SBryan Drewery case PKG_CONFIG_LIST: 332eb31a574SBryan Drewery c[i].list = temp_config[i].list; 333eb31a574SBryan Drewery break; 334eb31a574SBryan Drewery default: 335eb31a574SBryan Drewery c[i].value = temp_config[i].value; 336eb31a574SBryan Drewery break; 337eb31a574SBryan Drewery } 338eb31a574SBryan Drewery } 339eb31a574SBryan Drewery 340eb31a574SBryan Drewery cleanup: 341eb31a574SBryan Drewery free(temp_config); 342cc9a8a11SBaptiste Daroussin fclose(buffp); 343cc9a8a11SBaptiste Daroussin free(buf); 3449950eceeSBaptiste Daroussin } 3459950eceeSBaptiste Daroussin 346bc5e9ac0SBryan Drewery /*- 347bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 348bc5e9ac0SBryan Drewery * Name: 349bc5e9ac0SBryan Drewery * URL: 350bc5e9ac0SBryan Drewery * MIRROR_TYPE: 351bc5e9ac0SBryan Drewery * etc... 352bc5e9ac0SBryan Drewery */ 353bc5e9ac0SBryan Drewery static void 35418418e19SKyle Evans parse_repo_file(ucl_object_t *obj, const char *requested_repo) 355bc5e9ac0SBryan Drewery { 3568a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 357b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 3588a7d859eSBaptiste Daroussin const char *key; 359bc5e9ac0SBryan Drewery 3608a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 3618a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 362bc5e9ac0SBryan Drewery 3638a7d859eSBaptiste Daroussin if (key == NULL) 364bc5e9ac0SBryan Drewery continue; 365bc5e9ac0SBryan Drewery 3668a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 367bc5e9ac0SBryan Drewery continue; 368bc5e9ac0SBryan Drewery 36918418e19SKyle Evans if (requested_repo != NULL && strcmp(requested_repo, key) != 0) 37018418e19SKyle Evans continue; 37118418e19SKyle Evans 3728a7d859eSBaptiste Daroussin config_parse(cur, CONFFILE_REPO); 373bc5e9ac0SBryan Drewery } 374bc5e9ac0SBryan Drewery } 375bc5e9ac0SBryan Drewery 376bc5e9ac0SBryan Drewery 377bc5e9ac0SBryan Drewery static int 37818418e19SKyle Evans read_conf_file(const char *confpath, const char *requested_repo, 37918418e19SKyle Evans pkg_conf_file_t conftype) 3809950eceeSBaptiste Daroussin { 3818a7d859eSBaptiste Daroussin struct ucl_parser *p; 3828a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 383bc5e9ac0SBryan Drewery 3848a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 3858a7d859eSBaptiste Daroussin 3868a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 387bc5e9ac0SBryan Drewery if (errno != ENOENT) 3888a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 3898a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 3908a7d859eSBaptiste Daroussin ucl_parser_free(p); 391bc5e9ac0SBryan Drewery /* no configuration present */ 392bc5e9ac0SBryan Drewery return (1); 393bc5e9ac0SBryan Drewery } 394bc5e9ac0SBryan Drewery 3958a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 3968a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 397bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 398bc5e9ac0SBryan Drewery "configuration file %s", confpath); 399bc5e9ac0SBryan Drewery else { 400bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 4018a7d859eSBaptiste Daroussin config_parse(obj, conftype); 402bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 40318418e19SKyle Evans parse_repo_file(obj, requested_repo); 404bc5e9ac0SBryan Drewery } 405bc5e9ac0SBryan Drewery 406b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 4078a7d859eSBaptiste Daroussin ucl_parser_free(p); 408bc5e9ac0SBryan Drewery 409bc5e9ac0SBryan Drewery return (0); 410bc5e9ac0SBryan Drewery } 411bc5e9ac0SBryan Drewery 412eb31a574SBryan Drewery static int 41318418e19SKyle Evans load_repositories(const char *repodir, const char *requested_repo) 414eb31a574SBryan Drewery { 415eb31a574SBryan Drewery struct dirent *ent; 416eb31a574SBryan Drewery DIR *d; 417eb31a574SBryan Drewery char *p; 418eb31a574SBryan Drewery size_t n; 419eb31a574SBryan Drewery char path[MAXPATHLEN]; 420eb31a574SBryan Drewery int ret; 421eb31a574SBryan Drewery 422eb31a574SBryan Drewery ret = 0; 423eb31a574SBryan Drewery 424eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 425eb31a574SBryan Drewery return (1); 426eb31a574SBryan Drewery 427eb31a574SBryan Drewery while ((ent = readdir(d))) { 428eb31a574SBryan Drewery /* Trim out 'repos'. */ 429eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 430eb31a574SBryan Drewery continue; 431eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 432eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 433eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 434eb31a574SBryan Drewery repodir, 435eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 436eb31a574SBryan Drewery ent->d_name); 43718418e19SKyle Evans if (access(path, F_OK) != 0) 43818418e19SKyle Evans continue; 43918418e19SKyle Evans if (read_conf_file(path, requested_repo, 44018418e19SKyle Evans CONFFILE_REPO)) { 441eb31a574SBryan Drewery ret = 1; 442eb31a574SBryan Drewery goto cleanup; 443eb31a574SBryan Drewery } 444eb31a574SBryan Drewery } 445eb31a574SBryan Drewery } 446eb31a574SBryan Drewery 447eb31a574SBryan Drewery cleanup: 448eb31a574SBryan Drewery closedir(d); 449eb31a574SBryan Drewery 450eb31a574SBryan Drewery return (ret); 451eb31a574SBryan Drewery } 452eb31a574SBryan Drewery 453bc5e9ac0SBryan Drewery int 45418418e19SKyle Evans config_init(const char *requested_repo) 455bc5e9ac0SBryan Drewery { 456eb31a574SBryan Drewery char *val; 4579950eceeSBaptiste Daroussin int i; 4589950eceeSBaptiste Daroussin const char *localbase; 459*fd9ae9acSJohn Baldwin char *abi, *env_list_item; 4609950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 461eb31a574SBryan Drewery struct config_value *cv; 4629950eceeSBaptiste Daroussin 4639950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 4649950eceeSBaptiste Daroussin val = getenv(c[i].key); 4659950eceeSBaptiste Daroussin if (val != NULL) { 4669950eceeSBaptiste Daroussin c[i].envset = true; 467eb31a574SBryan Drewery switch (c[i].type) { 468eb31a574SBryan Drewery case PKG_CONFIG_LIST: 469eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 470eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 471eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 472eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 473eb31a574SBryan Drewery env_list_item != NULL; 474eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 475eb31a574SBryan Drewery cv = 476eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 477eb31a574SBryan Drewery cv->value = 478eb31a574SBryan Drewery strdup(env_list_item); 479eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 480eb31a574SBryan Drewery next); 481eb31a574SBryan Drewery } 482eb31a574SBryan Drewery break; 483eb31a574SBryan Drewery default: 484eb31a574SBryan Drewery c[i].val = val; 485eb31a574SBryan Drewery break; 486eb31a574SBryan Drewery } 4879950eceeSBaptiste Daroussin } 4889950eceeSBaptiste Daroussin } 4899950eceeSBaptiste Daroussin 490eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 49156d11d4aSStefan Eßer localbase = getlocalbase(); 49256d11d4aSStefan Eßer snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); 4939950eceeSBaptiste Daroussin 49418418e19SKyle Evans if (access(confpath, F_OK) == 0 && read_conf_file(confpath, NULL, 495bc5e9ac0SBryan Drewery CONFFILE_PKG)) 4969950eceeSBaptiste Daroussin goto finalize; 4979950eceeSBaptiste Daroussin 498eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 499eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 500eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 501eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 502eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 503eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 504eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 505eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 506eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 507eb31a574SBryan Drewery goto finalize; 508eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 509eb31a574SBryan Drewery } 510eb31a574SBryan Drewery 511eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 51218418e19SKyle Evans if (load_repositories(cv->value, requested_repo)) 513bc5e9ac0SBryan Drewery goto finalize; 5149950eceeSBaptiste Daroussin 5159950eceeSBaptiste Daroussin finalize: 5169950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 517*fd9ae9acSJohn Baldwin abi = pkg_get_myabi(); 518*fd9ae9acSJohn Baldwin if (abi == NULL) 5194ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 5204ff9a7efSBryan Drewery "ABI"); 5219950eceeSBaptiste Daroussin c[ABI].val = abi; 5229950eceeSBaptiste Daroussin } 5239950eceeSBaptiste Daroussin 524d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 5259950eceeSBaptiste Daroussin 5269950eceeSBaptiste Daroussin return (0); 5279950eceeSBaptiste Daroussin } 5289950eceeSBaptiste Daroussin 5299950eceeSBaptiste Daroussin int 5309950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5319950eceeSBaptiste Daroussin { 5329950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5339950eceeSBaptiste Daroussin return (-1); 5349950eceeSBaptiste Daroussin 5359950eceeSBaptiste Daroussin if (c[k].value != NULL) 5369950eceeSBaptiste Daroussin *val = c[k].value; 5379950eceeSBaptiste Daroussin else 5389950eceeSBaptiste Daroussin *val = c[k].val; 5399950eceeSBaptiste Daroussin 5409950eceeSBaptiste Daroussin return (0); 5419950eceeSBaptiste Daroussin } 5429950eceeSBaptiste Daroussin 5439950eceeSBaptiste Daroussin int 5449950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 5459950eceeSBaptiste Daroussin { 5469950eceeSBaptiste Daroussin const char *value; 5479950eceeSBaptiste Daroussin 5489950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 5499950eceeSBaptiste Daroussin return (-1); 5509950eceeSBaptiste Daroussin 5519950eceeSBaptiste Daroussin *val = false; 5529950eceeSBaptiste Daroussin 5539950eceeSBaptiste Daroussin if (c[k].value != NULL) 5549950eceeSBaptiste Daroussin value = c[k].value; 5559950eceeSBaptiste Daroussin else 5569950eceeSBaptiste Daroussin value = c[k].val; 5579950eceeSBaptiste Daroussin 558eb31a574SBryan Drewery if (boolstr_to_bool(value)) 5599950eceeSBaptiste Daroussin *val = true; 5609950eceeSBaptiste Daroussin 5619950eceeSBaptiste Daroussin return (0); 5629950eceeSBaptiste Daroussin } 5639950eceeSBaptiste Daroussin 5649950eceeSBaptiste Daroussin void 5659950eceeSBaptiste Daroussin config_finish(void) { 5669950eceeSBaptiste Daroussin int i; 5679950eceeSBaptiste Daroussin 5689950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 5699950eceeSBaptiste Daroussin free(c[i].value); 5709950eceeSBaptiste Daroussin } 571