19950eceeSBaptiste Daroussin /*- 21de7b4b8SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 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 __FBSDID("$FreeBSD$"); 329950eceeSBaptiste Daroussin 339950eceeSBaptiste Daroussin #include <sys/param.h> 34a351c93dSBaptiste Daroussin #include <sys/queue.h> 3560b9a1fcSNathan Whitehorn #include <sys/utsname.h> 3660b9a1fcSNathan Whitehorn #include <sys/sysctl.h> 379950eceeSBaptiste Daroussin 38eb31a574SBryan Drewery #include <dirent.h> 398a7d859eSBaptiste Daroussin #include <ucl.h> 409950eceeSBaptiste Daroussin #include <err.h> 419950eceeSBaptiste Daroussin #include <errno.h> 4256d11d4aSStefan Eßer #include <libutil.h> 431f474190SStefan Eßer #include <paths.h> 449950eceeSBaptiste Daroussin #include <stdbool.h> 459950eceeSBaptiste Daroussin #include <unistd.h> 46e869d3c6SMoritz Schmitt #include <ctype.h> 479950eceeSBaptiste Daroussin 489950eceeSBaptiste Daroussin #include "config.h" 499950eceeSBaptiste Daroussin 50eb31a574SBryan Drewery struct config_value { 51eb31a574SBryan Drewery char *value; 52eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 53eb31a574SBryan Drewery }; 54eb31a574SBryan Drewery 559950eceeSBaptiste Daroussin struct config_entry { 569950eceeSBaptiste Daroussin uint8_t type; 579950eceeSBaptiste Daroussin const char *key; 589950eceeSBaptiste Daroussin const char *val; 599950eceeSBaptiste Daroussin char *value; 60eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 619950eceeSBaptiste Daroussin bool envset; 6297c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 639950eceeSBaptiste Daroussin }; 649950eceeSBaptiste Daroussin 659950eceeSBaptiste Daroussin static struct config_entry c[] = { 669950eceeSBaptiste Daroussin [PACKAGESITE] = { 679950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 689950eceeSBaptiste Daroussin "PACKAGESITE", 6962940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 709950eceeSBaptiste Daroussin NULL, 71eb31a574SBryan Drewery NULL, 729950eceeSBaptiste Daroussin false, 7397c3a766SBryan Drewery false, 749950eceeSBaptiste Daroussin }, 759950eceeSBaptiste Daroussin [ABI] = { 769950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 779950eceeSBaptiste Daroussin "ABI", 789950eceeSBaptiste Daroussin NULL, 799950eceeSBaptiste Daroussin NULL, 80eb31a574SBryan Drewery NULL, 819950eceeSBaptiste Daroussin false, 8297c3a766SBryan Drewery true, 839950eceeSBaptiste Daroussin }, 849950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 859950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 869950eceeSBaptiste Daroussin "MIRROR_TYPE", 879950eceeSBaptiste Daroussin "SRV", 889950eceeSBaptiste Daroussin NULL, 89eb31a574SBryan Drewery NULL, 909950eceeSBaptiste Daroussin false, 9197c3a766SBryan Drewery false, 929950eceeSBaptiste Daroussin }, 939950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 949950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 959950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 969950eceeSBaptiste Daroussin "NO", 979950eceeSBaptiste Daroussin NULL, 98eb31a574SBryan Drewery NULL, 999950eceeSBaptiste Daroussin false, 10097c3a766SBryan Drewery true, 101f12db248SBryan Drewery }, 102f12db248SBryan Drewery [SIGNATURE_TYPE] = { 103f12db248SBryan Drewery PKG_CONFIG_STRING, 104f12db248SBryan Drewery "SIGNATURE_TYPE", 105f12db248SBryan Drewery NULL, 106f12db248SBryan Drewery NULL, 107eb31a574SBryan Drewery NULL, 108f12db248SBryan Drewery false, 10997c3a766SBryan Drewery false, 110f12db248SBryan Drewery }, 111f12db248SBryan Drewery [FINGERPRINTS] = { 112f12db248SBryan Drewery PKG_CONFIG_STRING, 113f12db248SBryan Drewery "FINGERPRINTS", 114f12db248SBryan Drewery NULL, 115f12db248SBryan Drewery NULL, 116eb31a574SBryan Drewery NULL, 117eb31a574SBryan Drewery false, 11897c3a766SBryan Drewery false, 119eb31a574SBryan Drewery }, 120eb31a574SBryan Drewery [REPOS_DIR] = { 121eb31a574SBryan Drewery PKG_CONFIG_LIST, 122eb31a574SBryan Drewery "REPOS_DIR", 123eb31a574SBryan Drewery NULL, 124eb31a574SBryan Drewery NULL, 125eb31a574SBryan Drewery NULL, 126f12db248SBryan Drewery false, 12797c3a766SBryan Drewery true, 128f12db248SBryan Drewery }, 12961acb458SBaptiste Daroussin [PUBKEY] = { 13061acb458SBaptiste Daroussin PKG_CONFIG_STRING, 13161acb458SBaptiste Daroussin "PUBKEY", 13261acb458SBaptiste Daroussin NULL, 13361acb458SBaptiste Daroussin NULL, 13461acb458SBaptiste Daroussin NULL, 13561acb458SBaptiste Daroussin false, 13661acb458SBaptiste Daroussin false 137e869d3c6SMoritz Schmitt }, 138e869d3c6SMoritz Schmitt [PKG_ENV] = { 139e869d3c6SMoritz Schmitt PKG_CONFIG_OBJECT, 140e869d3c6SMoritz Schmitt "PKG_ENV", 141e869d3c6SMoritz Schmitt NULL, 142e869d3c6SMoritz Schmitt NULL, 143e869d3c6SMoritz Schmitt NULL, 144e869d3c6SMoritz Schmitt false, 145e869d3c6SMoritz Schmitt false, 14661acb458SBaptiste Daroussin } 1479950eceeSBaptiste Daroussin }; 1489950eceeSBaptiste Daroussin 1499950eceeSBaptiste Daroussin static int 1509950eceeSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 1519950eceeSBaptiste Daroussin { 15260b9a1fcSNathan Whitehorn struct utsname uts; 15360b9a1fcSNathan Whitehorn char machine_arch[255]; 15460b9a1fcSNathan Whitehorn size_t len; 15560b9a1fcSNathan Whitehorn int error; 1569950eceeSBaptiste Daroussin 15760b9a1fcSNathan Whitehorn error = uname(&uts); 15860b9a1fcSNathan Whitehorn if (error) 15960b9a1fcSNathan Whitehorn return (errno); 1609950eceeSBaptiste Daroussin 16160b9a1fcSNathan Whitehorn len = sizeof(machine_arch); 16260b9a1fcSNathan Whitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 16360b9a1fcSNathan Whitehorn if (error) 16460b9a1fcSNathan Whitehorn return (errno); 16560b9a1fcSNathan Whitehorn machine_arch[len] = '\0'; 1669950eceeSBaptiste Daroussin 16740274a2dSBaptiste Daroussin /* 16860b9a1fcSNathan Whitehorn * Use __FreeBSD_version rather than kernel version (uts.release) for 16960b9a1fcSNathan Whitehorn * use in jails. This is equivalent to the value of uname -U. 17040274a2dSBaptiste Daroussin */ 17160b9a1fcSNathan Whitehorn snprintf(dest, sz, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 17260b9a1fcSNathan Whitehorn machine_arch); 17340274a2dSBaptiste Daroussin 17460b9a1fcSNathan Whitehorn return (error); 1759950eceeSBaptiste Daroussin } 1769950eceeSBaptiste Daroussin 1779950eceeSBaptiste Daroussin static void 1789950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 1799950eceeSBaptiste Daroussin { 180ae659caaSBaptiste Daroussin char *newval; 1819950eceeSBaptiste Daroussin const char *variable_string; 1829950eceeSBaptiste Daroussin const char *oldval; 1839950eceeSBaptiste Daroussin 1849950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 1859950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 1869950eceeSBaptiste Daroussin else 1879950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 1889950eceeSBaptiste Daroussin 1899950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 1909950eceeSBaptiste Daroussin return; 1919950eceeSBaptiste Daroussin 192ae659caaSBaptiste Daroussin asprintf(&newval, "%.*s%s%s", 193ae659caaSBaptiste Daroussin (int)(variable_string - oldval), oldval, abi, 194ae659caaSBaptiste Daroussin variable_string + strlen("${ABI}")); 195ae659caaSBaptiste Daroussin if (newval == NULL) 196ae659caaSBaptiste Daroussin errx(EXIT_FAILURE, "asprintf"); 1979950eceeSBaptiste Daroussin 1989950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 199ae659caaSBaptiste Daroussin c[PACKAGESITE].value = newval; 2009950eceeSBaptiste Daroussin } 2019950eceeSBaptiste Daroussin 202eb31a574SBryan Drewery static int 203eb31a574SBryan Drewery boolstr_to_bool(const char *str) 204eb31a574SBryan Drewery { 205eb31a574SBryan Drewery if (str != NULL && (strcasecmp(str, "true") == 0 || 206eb31a574SBryan Drewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 207eb31a574SBryan Drewery str[0] == '1')) 208eb31a574SBryan Drewery return (true); 209eb31a574SBryan Drewery 210eb31a574SBryan Drewery return (false); 211eb31a574SBryan Drewery } 212eb31a574SBryan Drewery 2139950eceeSBaptiste Daroussin static void 214b04a7a0bSBaptiste Daroussin config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 2159950eceeSBaptiste Daroussin { 216*cc9a8a11SBaptiste Daroussin FILE *buffp; 217*cc9a8a11SBaptiste Daroussin char *buf = NULL; 218*cc9a8a11SBaptiste Daroussin size_t bufsz = 0; 219e869d3c6SMoritz Schmitt const ucl_object_t *cur, *seq, *tmp; 220e869d3c6SMoritz Schmitt ucl_object_iter_t it = NULL, itseq = NULL, it_obj = NULL; 221eb31a574SBryan Drewery struct config_entry *temp_config; 222eb31a574SBryan Drewery struct config_value *cv; 223e869d3c6SMoritz Schmitt const char *key, *evkey; 2249950eceeSBaptiste Daroussin int i; 2259950eceeSBaptiste Daroussin size_t j; 2269950eceeSBaptiste Daroussin 227eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 228eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 229*cc9a8a11SBaptiste Daroussin buffp = open_memstream(&buf, &bufsz); 230*cc9a8a11SBaptiste Daroussin if (buffp == NULL) 231*cc9a8a11SBaptiste Daroussin err(EXIT_FAILURE, "open_memstream()"); 232eb31a574SBryan Drewery 2338a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 2348a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 2358a7d859eSBaptiste Daroussin if (key == NULL) 2369950eceeSBaptiste Daroussin continue; 237*cc9a8a11SBaptiste Daroussin if (buf != NULL) 238*cc9a8a11SBaptiste Daroussin memset(buf, 0, bufsz); 239*cc9a8a11SBaptiste Daroussin rewind(buffp); 2409950eceeSBaptiste Daroussin 241bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) { 2428a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 243*cc9a8a11SBaptiste Daroussin fputc(toupper(key[j]), buffp); 244*cc9a8a11SBaptiste Daroussin fflush(buffp); 245bc5e9ac0SBryan Drewery } else if (conftype == CONFFILE_REPO) { 2468a7d859eSBaptiste Daroussin if (strcasecmp(key, "url") == 0) 247*cc9a8a11SBaptiste Daroussin fputs("PACKAGESITE", buffp); 2488a7d859eSBaptiste Daroussin else if (strcasecmp(key, "mirror_type") == 0) 249*cc9a8a11SBaptiste Daroussin fputs("MIRROR_TYPE", buffp); 2508a7d859eSBaptiste Daroussin else if (strcasecmp(key, "signature_type") == 0) 251*cc9a8a11SBaptiste Daroussin fputs("SIGNATURE_TYPE", buffp); 2528a7d859eSBaptiste Daroussin else if (strcasecmp(key, "fingerprints") == 0) 253*cc9a8a11SBaptiste Daroussin fputs("FINGERPRINTS", buffp); 25461acb458SBaptiste Daroussin else if (strcasecmp(key, "pubkey") == 0) 255*cc9a8a11SBaptiste Daroussin fputs("PUBKEY", buffp); 2568a7d859eSBaptiste Daroussin else if (strcasecmp(key, "enabled") == 0) { 2578a7d859eSBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 2588a7d859eSBaptiste Daroussin !ucl_object_toboolean(cur)) 259eb31a574SBryan Drewery goto cleanup; 2608a7d859eSBaptiste Daroussin } else 261bc5e9ac0SBryan Drewery continue; 262*cc9a8a11SBaptiste Daroussin fflush(buffp); 263bc5e9ac0SBryan Drewery } 264bc5e9ac0SBryan Drewery 2659950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 266*cc9a8a11SBaptiste Daroussin if (strcmp(buf, c[i].key) == 0) 2679950eceeSBaptiste Daroussin break; 2689950eceeSBaptiste Daroussin } 2699950eceeSBaptiste Daroussin 270bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 2718a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 2729950eceeSBaptiste Daroussin continue; 2739950eceeSBaptiste Daroussin 2749950eceeSBaptiste Daroussin /* env has priority over config file */ 2758a7d859eSBaptiste Daroussin if (c[i].envset) 2769950eceeSBaptiste Daroussin continue; 2779950eceeSBaptiste Daroussin 278eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 279eb31a574SBryan Drewery switch (c[i].type) { 280eb31a574SBryan Drewery case PKG_CONFIG_LIST: 2818a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 2828a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 283eb31a574SBryan Drewery "value for %s.\n", c[i].key); 284eb31a574SBryan Drewery continue; 285eb31a574SBryan Drewery } 286eb31a574SBryan Drewery temp_config[i].list = 287eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 288eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 289eb31a574SBryan Drewery 2908a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 2918a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 292eb31a574SBryan Drewery continue; 293eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 294eb31a574SBryan Drewery cv->value = 2958a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 296eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 297eb31a574SBryan Drewery next); 298eb31a574SBryan Drewery } 299eb31a574SBryan Drewery break; 300197372c2SBryan Drewery case PKG_CONFIG_BOOL: 301197372c2SBryan Drewery temp_config[i].value = 302197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 303197372c2SBryan Drewery break; 304e869d3c6SMoritz Schmitt case PKG_CONFIG_OBJECT: 305e869d3c6SMoritz Schmitt if (strcmp(c[i].key, "PKG_ENV") == 0) { 306e869d3c6SMoritz Schmitt while ((tmp = 307e869d3c6SMoritz Schmitt ucl_iterate_object(cur, &it_obj, true))) { 308e869d3c6SMoritz Schmitt evkey = ucl_object_key(tmp); 309e869d3c6SMoritz Schmitt if (evkey != NULL && *evkey != '\0') { 310e869d3c6SMoritz Schmitt setenv(evkey, ucl_object_tostring_forced(tmp), 1); 311e869d3c6SMoritz Schmitt } 312e869d3c6SMoritz Schmitt } 313e869d3c6SMoritz Schmitt } 314e869d3c6SMoritz Schmitt break; 315eb31a574SBryan Drewery default: 316eb31a574SBryan Drewery /* Normal string value. */ 3178a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 318eb31a574SBryan Drewery break; 319eb31a574SBryan Drewery } 3209950eceeSBaptiste Daroussin } 3219950eceeSBaptiste Daroussin 322eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 323eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 324eb31a574SBryan Drewery if (c[i].envset) 325eb31a574SBryan Drewery continue; 32697c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 32797c3a766SBryan Drewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 32897c3a766SBryan Drewery continue; 329eb31a574SBryan Drewery switch (c[i].type) { 330eb31a574SBryan Drewery case PKG_CONFIG_LIST: 331eb31a574SBryan Drewery c[i].list = temp_config[i].list; 332eb31a574SBryan Drewery break; 333eb31a574SBryan Drewery default: 334eb31a574SBryan Drewery c[i].value = temp_config[i].value; 335eb31a574SBryan Drewery break; 336eb31a574SBryan Drewery } 337eb31a574SBryan Drewery } 338eb31a574SBryan Drewery 339eb31a574SBryan Drewery cleanup: 340eb31a574SBryan Drewery free(temp_config); 341*cc9a8a11SBaptiste Daroussin fclose(buffp); 342*cc9a8a11SBaptiste Daroussin free(buf); 3439950eceeSBaptiste Daroussin } 3449950eceeSBaptiste Daroussin 345bc5e9ac0SBryan Drewery /*- 346bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 347bc5e9ac0SBryan Drewery * Name: 348bc5e9ac0SBryan Drewery * URL: 349bc5e9ac0SBryan Drewery * MIRROR_TYPE: 350bc5e9ac0SBryan Drewery * etc... 351bc5e9ac0SBryan Drewery */ 352bc5e9ac0SBryan Drewery static void 35318418e19SKyle Evans parse_repo_file(ucl_object_t *obj, const char *requested_repo) 354bc5e9ac0SBryan Drewery { 3558a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 356b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 3578a7d859eSBaptiste Daroussin const char *key; 358bc5e9ac0SBryan Drewery 3598a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 3608a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 361bc5e9ac0SBryan Drewery 3628a7d859eSBaptiste Daroussin if (key == NULL) 363bc5e9ac0SBryan Drewery continue; 364bc5e9ac0SBryan Drewery 3658a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 366bc5e9ac0SBryan Drewery continue; 367bc5e9ac0SBryan Drewery 36818418e19SKyle Evans if (requested_repo != NULL && strcmp(requested_repo, key) != 0) 36918418e19SKyle Evans continue; 37018418e19SKyle Evans 3718a7d859eSBaptiste Daroussin config_parse(cur, CONFFILE_REPO); 372bc5e9ac0SBryan Drewery } 373bc5e9ac0SBryan Drewery } 374bc5e9ac0SBryan Drewery 375bc5e9ac0SBryan Drewery 376bc5e9ac0SBryan Drewery static int 37718418e19SKyle Evans read_conf_file(const char *confpath, const char *requested_repo, 37818418e19SKyle Evans pkg_conf_file_t conftype) 3799950eceeSBaptiste Daroussin { 3808a7d859eSBaptiste Daroussin struct ucl_parser *p; 3818a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 382bc5e9ac0SBryan Drewery 3838a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 3848a7d859eSBaptiste Daroussin 3858a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 386bc5e9ac0SBryan Drewery if (errno != ENOENT) 3878a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 3888a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 3898a7d859eSBaptiste Daroussin ucl_parser_free(p); 390bc5e9ac0SBryan Drewery /* no configuration present */ 391bc5e9ac0SBryan Drewery return (1); 392bc5e9ac0SBryan Drewery } 393bc5e9ac0SBryan Drewery 3948a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 3958a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 396bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 397bc5e9ac0SBryan Drewery "configuration file %s", confpath); 398bc5e9ac0SBryan Drewery else { 399bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 4008a7d859eSBaptiste Daroussin config_parse(obj, conftype); 401bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 40218418e19SKyle Evans parse_repo_file(obj, requested_repo); 403bc5e9ac0SBryan Drewery } 404bc5e9ac0SBryan Drewery 405b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 4068a7d859eSBaptiste Daroussin ucl_parser_free(p); 407bc5e9ac0SBryan Drewery 408bc5e9ac0SBryan Drewery return (0); 409bc5e9ac0SBryan Drewery } 410bc5e9ac0SBryan Drewery 411eb31a574SBryan Drewery static int 41218418e19SKyle Evans load_repositories(const char *repodir, const char *requested_repo) 413eb31a574SBryan Drewery { 414eb31a574SBryan Drewery struct dirent *ent; 415eb31a574SBryan Drewery DIR *d; 416eb31a574SBryan Drewery char *p; 417eb31a574SBryan Drewery size_t n; 418eb31a574SBryan Drewery char path[MAXPATHLEN]; 419eb31a574SBryan Drewery int ret; 420eb31a574SBryan Drewery 421eb31a574SBryan Drewery ret = 0; 422eb31a574SBryan Drewery 423eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 424eb31a574SBryan Drewery return (1); 425eb31a574SBryan Drewery 426eb31a574SBryan Drewery while ((ent = readdir(d))) { 427eb31a574SBryan Drewery /* Trim out 'repos'. */ 428eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 429eb31a574SBryan Drewery continue; 430eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 431eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 432eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 433eb31a574SBryan Drewery repodir, 434eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 435eb31a574SBryan Drewery ent->d_name); 43618418e19SKyle Evans if (access(path, F_OK) != 0) 43718418e19SKyle Evans continue; 43818418e19SKyle Evans if (read_conf_file(path, requested_repo, 43918418e19SKyle Evans CONFFILE_REPO)) { 440eb31a574SBryan Drewery ret = 1; 441eb31a574SBryan Drewery goto cleanup; 442eb31a574SBryan Drewery } 443eb31a574SBryan Drewery } 444eb31a574SBryan Drewery } 445eb31a574SBryan Drewery 446eb31a574SBryan Drewery cleanup: 447eb31a574SBryan Drewery closedir(d); 448eb31a574SBryan Drewery 449eb31a574SBryan Drewery return (ret); 450eb31a574SBryan Drewery } 451eb31a574SBryan Drewery 452bc5e9ac0SBryan Drewery int 45318418e19SKyle Evans config_init(const char *requested_repo) 454bc5e9ac0SBryan Drewery { 455eb31a574SBryan Drewery char *val; 4569950eceeSBaptiste Daroussin int i; 4579950eceeSBaptiste Daroussin const char *localbase; 458eb31a574SBryan Drewery char *env_list_item; 4599950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 460eb31a574SBryan Drewery struct config_value *cv; 4619950eceeSBaptiste Daroussin char abi[BUFSIZ]; 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) { 5179950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 5184ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 5194ff9a7efSBryan Drewery "ABI"); 5209950eceeSBaptiste Daroussin c[ABI].val = abi; 5219950eceeSBaptiste Daroussin } 5229950eceeSBaptiste Daroussin 523d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 5249950eceeSBaptiste Daroussin 5259950eceeSBaptiste Daroussin return (0); 5269950eceeSBaptiste Daroussin } 5279950eceeSBaptiste Daroussin 5289950eceeSBaptiste Daroussin int 5299950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5309950eceeSBaptiste Daroussin { 5319950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5329950eceeSBaptiste Daroussin return (-1); 5339950eceeSBaptiste Daroussin 5349950eceeSBaptiste Daroussin if (c[k].value != NULL) 5359950eceeSBaptiste Daroussin *val = c[k].value; 5369950eceeSBaptiste Daroussin else 5379950eceeSBaptiste Daroussin *val = c[k].val; 5389950eceeSBaptiste Daroussin 5399950eceeSBaptiste Daroussin return (0); 5409950eceeSBaptiste Daroussin } 5419950eceeSBaptiste Daroussin 5429950eceeSBaptiste Daroussin int 5439950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 5449950eceeSBaptiste Daroussin { 5459950eceeSBaptiste Daroussin const char *value; 5469950eceeSBaptiste Daroussin 5479950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 5489950eceeSBaptiste Daroussin return (-1); 5499950eceeSBaptiste Daroussin 5509950eceeSBaptiste Daroussin *val = false; 5519950eceeSBaptiste Daroussin 5529950eceeSBaptiste Daroussin if (c[k].value != NULL) 5539950eceeSBaptiste Daroussin value = c[k].value; 5549950eceeSBaptiste Daroussin else 5559950eceeSBaptiste Daroussin value = c[k].val; 5569950eceeSBaptiste Daroussin 557eb31a574SBryan Drewery if (boolstr_to_bool(value)) 5589950eceeSBaptiste Daroussin *val = true; 5599950eceeSBaptiste Daroussin 5609950eceeSBaptiste Daroussin return (0); 5619950eceeSBaptiste Daroussin } 5629950eceeSBaptiste Daroussin 5639950eceeSBaptiste Daroussin void 5649950eceeSBaptiste Daroussin config_finish(void) { 5659950eceeSBaptiste Daroussin int i; 5669950eceeSBaptiste Daroussin 5679950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 5689950eceeSBaptiste Daroussin free(c[i].value); 5699950eceeSBaptiste Daroussin } 570