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> 36ae659caaSBaptiste Daroussin #include <sys/sbuf.h> 3760b9a1fcSNathan Whitehorn #include <sys/sysctl.h> 389950eceeSBaptiste Daroussin 39eb31a574SBryan Drewery #include <dirent.h> 408a7d859eSBaptiste Daroussin #include <ucl.h> 419950eceeSBaptiste Daroussin #include <err.h> 429950eceeSBaptiste Daroussin #include <errno.h> 4356d11d4aSStefan Eßer #include <libutil.h> 441f474190SStefan Eßer #include <paths.h> 459950eceeSBaptiste Daroussin #include <stdbool.h> 469950eceeSBaptiste Daroussin #include <unistd.h> 47*e869d3c6SMoritz Schmitt #include <ctype.h> 489950eceeSBaptiste Daroussin 499950eceeSBaptiste Daroussin #include "config.h" 509950eceeSBaptiste Daroussin 51eb31a574SBryan Drewery struct config_value { 52eb31a574SBryan Drewery char *value; 53eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 54eb31a574SBryan Drewery }; 55eb31a574SBryan Drewery 569950eceeSBaptiste Daroussin struct config_entry { 579950eceeSBaptiste Daroussin uint8_t type; 589950eceeSBaptiste Daroussin const char *key; 599950eceeSBaptiste Daroussin const char *val; 609950eceeSBaptiste Daroussin char *value; 61eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 629950eceeSBaptiste Daroussin bool envset; 6397c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 649950eceeSBaptiste Daroussin }; 659950eceeSBaptiste Daroussin 669950eceeSBaptiste Daroussin static struct config_entry c[] = { 679950eceeSBaptiste Daroussin [PACKAGESITE] = { 689950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 699950eceeSBaptiste Daroussin "PACKAGESITE", 7062940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 719950eceeSBaptiste Daroussin NULL, 72eb31a574SBryan Drewery NULL, 739950eceeSBaptiste Daroussin false, 7497c3a766SBryan Drewery false, 759950eceeSBaptiste Daroussin }, 769950eceeSBaptiste Daroussin [ABI] = { 779950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 789950eceeSBaptiste Daroussin "ABI", 799950eceeSBaptiste Daroussin NULL, 809950eceeSBaptiste Daroussin NULL, 81eb31a574SBryan Drewery NULL, 829950eceeSBaptiste Daroussin false, 8397c3a766SBryan Drewery true, 849950eceeSBaptiste Daroussin }, 859950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 869950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 879950eceeSBaptiste Daroussin "MIRROR_TYPE", 889950eceeSBaptiste Daroussin "SRV", 899950eceeSBaptiste Daroussin NULL, 90eb31a574SBryan Drewery NULL, 919950eceeSBaptiste Daroussin false, 9297c3a766SBryan Drewery false, 939950eceeSBaptiste Daroussin }, 949950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 959950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 969950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 979950eceeSBaptiste Daroussin "NO", 989950eceeSBaptiste Daroussin NULL, 99eb31a574SBryan Drewery NULL, 1009950eceeSBaptiste Daroussin false, 10197c3a766SBryan Drewery true, 102f12db248SBryan Drewery }, 103f12db248SBryan Drewery [SIGNATURE_TYPE] = { 104f12db248SBryan Drewery PKG_CONFIG_STRING, 105f12db248SBryan Drewery "SIGNATURE_TYPE", 106f12db248SBryan Drewery NULL, 107f12db248SBryan Drewery NULL, 108eb31a574SBryan Drewery NULL, 109f12db248SBryan Drewery false, 11097c3a766SBryan Drewery false, 111f12db248SBryan Drewery }, 112f12db248SBryan Drewery [FINGERPRINTS] = { 113f12db248SBryan Drewery PKG_CONFIG_STRING, 114f12db248SBryan Drewery "FINGERPRINTS", 115f12db248SBryan Drewery NULL, 116f12db248SBryan Drewery NULL, 117eb31a574SBryan Drewery NULL, 118eb31a574SBryan Drewery false, 11997c3a766SBryan Drewery false, 120eb31a574SBryan Drewery }, 121eb31a574SBryan Drewery [REPOS_DIR] = { 122eb31a574SBryan Drewery PKG_CONFIG_LIST, 123eb31a574SBryan Drewery "REPOS_DIR", 124eb31a574SBryan Drewery NULL, 125eb31a574SBryan Drewery NULL, 126eb31a574SBryan Drewery NULL, 127f12db248SBryan Drewery false, 12897c3a766SBryan Drewery true, 129f12db248SBryan Drewery }, 13061acb458SBaptiste Daroussin [PUBKEY] = { 13161acb458SBaptiste Daroussin PKG_CONFIG_STRING, 13261acb458SBaptiste Daroussin "PUBKEY", 13361acb458SBaptiste Daroussin NULL, 13461acb458SBaptiste Daroussin NULL, 13561acb458SBaptiste Daroussin NULL, 13661acb458SBaptiste Daroussin false, 13761acb458SBaptiste Daroussin false 138*e869d3c6SMoritz Schmitt }, 139*e869d3c6SMoritz Schmitt [PKG_ENV] = { 140*e869d3c6SMoritz Schmitt PKG_CONFIG_OBJECT, 141*e869d3c6SMoritz Schmitt "PKG_ENV", 142*e869d3c6SMoritz Schmitt NULL, 143*e869d3c6SMoritz Schmitt NULL, 144*e869d3c6SMoritz Schmitt NULL, 145*e869d3c6SMoritz Schmitt false, 146*e869d3c6SMoritz Schmitt false, 14761acb458SBaptiste Daroussin } 1489950eceeSBaptiste Daroussin }; 1499950eceeSBaptiste Daroussin 1509950eceeSBaptiste Daroussin static int 1519950eceeSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 1529950eceeSBaptiste Daroussin { 15360b9a1fcSNathan Whitehorn struct utsname uts; 15460b9a1fcSNathan Whitehorn char machine_arch[255]; 15560b9a1fcSNathan Whitehorn size_t len; 15660b9a1fcSNathan Whitehorn int error; 1579950eceeSBaptiste Daroussin 15860b9a1fcSNathan Whitehorn error = uname(&uts); 15960b9a1fcSNathan Whitehorn if (error) 16060b9a1fcSNathan Whitehorn return (errno); 1619950eceeSBaptiste Daroussin 16260b9a1fcSNathan Whitehorn len = sizeof(machine_arch); 16360b9a1fcSNathan Whitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 16460b9a1fcSNathan Whitehorn if (error) 16560b9a1fcSNathan Whitehorn return (errno); 16660b9a1fcSNathan Whitehorn machine_arch[len] = '\0'; 1679950eceeSBaptiste Daroussin 16840274a2dSBaptiste Daroussin /* 16960b9a1fcSNathan Whitehorn * Use __FreeBSD_version rather than kernel version (uts.release) for 17060b9a1fcSNathan Whitehorn * use in jails. This is equivalent to the value of uname -U. 17140274a2dSBaptiste Daroussin */ 17260b9a1fcSNathan Whitehorn snprintf(dest, sz, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 17360b9a1fcSNathan Whitehorn machine_arch); 17440274a2dSBaptiste Daroussin 17560b9a1fcSNathan Whitehorn return (error); 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 { 2179950eceeSBaptiste Daroussin struct sbuf *buf = sbuf_new_auto(); 218*e869d3c6SMoritz Schmitt const ucl_object_t *cur, *seq, *tmp; 219*e869d3c6SMoritz Schmitt ucl_object_iter_t it = NULL, itseq = NULL, it_obj = NULL; 220eb31a574SBryan Drewery struct config_entry *temp_config; 221eb31a574SBryan Drewery struct config_value *cv; 222*e869d3c6SMoritz Schmitt const char *key, *evkey; 2239950eceeSBaptiste Daroussin int i; 2249950eceeSBaptiste Daroussin size_t j; 2259950eceeSBaptiste Daroussin 226eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 227eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 228eb31a574SBryan Drewery 2298a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 2308a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 2318a7d859eSBaptiste Daroussin if (key == NULL) 2329950eceeSBaptiste Daroussin continue; 2339950eceeSBaptiste Daroussin sbuf_clear(buf); 2349950eceeSBaptiste Daroussin 235bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) { 2368a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 237*e869d3c6SMoritz Schmitt sbuf_putc(buf, toupper(key[j])); 2389950eceeSBaptiste Daroussin sbuf_finish(buf); 239bc5e9ac0SBryan Drewery } else if (conftype == CONFFILE_REPO) { 2408a7d859eSBaptiste Daroussin if (strcasecmp(key, "url") == 0) 241bc5e9ac0SBryan Drewery sbuf_cpy(buf, "PACKAGESITE"); 2428a7d859eSBaptiste Daroussin else if (strcasecmp(key, "mirror_type") == 0) 243bc5e9ac0SBryan Drewery sbuf_cpy(buf, "MIRROR_TYPE"); 2448a7d859eSBaptiste Daroussin else if (strcasecmp(key, "signature_type") == 0) 245f12db248SBryan Drewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 2468a7d859eSBaptiste Daroussin else if (strcasecmp(key, "fingerprints") == 0) 247f12db248SBryan Drewery sbuf_cpy(buf, "FINGERPRINTS"); 24861acb458SBaptiste Daroussin else if (strcasecmp(key, "pubkey") == 0) 24961acb458SBaptiste Daroussin sbuf_cpy(buf, "PUBKEY"); 2508a7d859eSBaptiste Daroussin else if (strcasecmp(key, "enabled") == 0) { 2518a7d859eSBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 2528a7d859eSBaptiste Daroussin !ucl_object_toboolean(cur)) 253eb31a574SBryan Drewery goto cleanup; 2548a7d859eSBaptiste Daroussin } else 255bc5e9ac0SBryan Drewery continue; 256bc5e9ac0SBryan Drewery sbuf_finish(buf); 257bc5e9ac0SBryan Drewery } 258bc5e9ac0SBryan Drewery 2599950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 2609950eceeSBaptiste Daroussin if (strcmp(sbuf_data(buf), c[i].key) == 0) 2619950eceeSBaptiste Daroussin break; 2629950eceeSBaptiste Daroussin } 2639950eceeSBaptiste Daroussin 264bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 2658a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 2669950eceeSBaptiste Daroussin continue; 2679950eceeSBaptiste Daroussin 2689950eceeSBaptiste Daroussin /* env has priority over config file */ 2698a7d859eSBaptiste Daroussin if (c[i].envset) 2709950eceeSBaptiste Daroussin continue; 2719950eceeSBaptiste Daroussin 272eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 273eb31a574SBryan Drewery switch (c[i].type) { 274eb31a574SBryan Drewery case PKG_CONFIG_LIST: 2758a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 2768a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 277eb31a574SBryan Drewery "value for %s.\n", c[i].key); 278eb31a574SBryan Drewery continue; 279eb31a574SBryan Drewery } 280eb31a574SBryan Drewery temp_config[i].list = 281eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 282eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 283eb31a574SBryan Drewery 2848a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 2858a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 286eb31a574SBryan Drewery continue; 287eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 288eb31a574SBryan Drewery cv->value = 2898a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 290eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 291eb31a574SBryan Drewery next); 292eb31a574SBryan Drewery } 293eb31a574SBryan Drewery break; 294197372c2SBryan Drewery case PKG_CONFIG_BOOL: 295197372c2SBryan Drewery temp_config[i].value = 296197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 297197372c2SBryan Drewery break; 298*e869d3c6SMoritz Schmitt case PKG_CONFIG_OBJECT: 299*e869d3c6SMoritz Schmitt if (strcmp(c[i].key, "PKG_ENV") == 0) { 300*e869d3c6SMoritz Schmitt while ((tmp = 301*e869d3c6SMoritz Schmitt ucl_iterate_object(cur, &it_obj, true))) { 302*e869d3c6SMoritz Schmitt evkey = ucl_object_key(tmp); 303*e869d3c6SMoritz Schmitt if (evkey != NULL && *evkey != '\0') { 304*e869d3c6SMoritz Schmitt setenv(evkey, ucl_object_tostring_forced(tmp), 1); 305*e869d3c6SMoritz Schmitt } 306*e869d3c6SMoritz Schmitt } 307*e869d3c6SMoritz Schmitt } 308*e869d3c6SMoritz Schmitt break; 309eb31a574SBryan Drewery default: 310eb31a574SBryan Drewery /* Normal string value. */ 3118a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 312eb31a574SBryan Drewery break; 313eb31a574SBryan Drewery } 3149950eceeSBaptiste Daroussin } 3159950eceeSBaptiste Daroussin 316eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 317eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 318eb31a574SBryan Drewery if (c[i].envset) 319eb31a574SBryan Drewery continue; 32097c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 32197c3a766SBryan Drewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 32297c3a766SBryan Drewery continue; 323eb31a574SBryan Drewery switch (c[i].type) { 324eb31a574SBryan Drewery case PKG_CONFIG_LIST: 325eb31a574SBryan Drewery c[i].list = temp_config[i].list; 326eb31a574SBryan Drewery break; 327eb31a574SBryan Drewery default: 328eb31a574SBryan Drewery c[i].value = temp_config[i].value; 329eb31a574SBryan Drewery break; 330eb31a574SBryan Drewery } 331eb31a574SBryan Drewery } 332eb31a574SBryan Drewery 333eb31a574SBryan Drewery cleanup: 334eb31a574SBryan Drewery free(temp_config); 3359950eceeSBaptiste Daroussin sbuf_delete(buf); 3369950eceeSBaptiste Daroussin } 3379950eceeSBaptiste Daroussin 338bc5e9ac0SBryan Drewery /*- 339bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 340bc5e9ac0SBryan Drewery * Name: 341bc5e9ac0SBryan Drewery * URL: 342bc5e9ac0SBryan Drewery * MIRROR_TYPE: 343bc5e9ac0SBryan Drewery * etc... 344bc5e9ac0SBryan Drewery */ 345bc5e9ac0SBryan Drewery static void 34618418e19SKyle Evans parse_repo_file(ucl_object_t *obj, const char *requested_repo) 347bc5e9ac0SBryan Drewery { 3488a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 349b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 3508a7d859eSBaptiste Daroussin const char *key; 351bc5e9ac0SBryan Drewery 3528a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 3538a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 354bc5e9ac0SBryan Drewery 3558a7d859eSBaptiste Daroussin if (key == NULL) 356bc5e9ac0SBryan Drewery continue; 357bc5e9ac0SBryan Drewery 3588a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 359bc5e9ac0SBryan Drewery continue; 360bc5e9ac0SBryan Drewery 36118418e19SKyle Evans if (requested_repo != NULL && strcmp(requested_repo, key) != 0) 36218418e19SKyle Evans continue; 36318418e19SKyle Evans 3648a7d859eSBaptiste Daroussin config_parse(cur, CONFFILE_REPO); 365bc5e9ac0SBryan Drewery } 366bc5e9ac0SBryan Drewery } 367bc5e9ac0SBryan Drewery 368bc5e9ac0SBryan Drewery 369bc5e9ac0SBryan Drewery static int 37018418e19SKyle Evans read_conf_file(const char *confpath, const char *requested_repo, 37118418e19SKyle Evans pkg_conf_file_t conftype) 3729950eceeSBaptiste Daroussin { 3738a7d859eSBaptiste Daroussin struct ucl_parser *p; 3748a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 375bc5e9ac0SBryan Drewery 3768a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 3778a7d859eSBaptiste Daroussin 3788a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 379bc5e9ac0SBryan Drewery if (errno != ENOENT) 3808a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 3818a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 3828a7d859eSBaptiste Daroussin ucl_parser_free(p); 383bc5e9ac0SBryan Drewery /* no configuration present */ 384bc5e9ac0SBryan Drewery return (1); 385bc5e9ac0SBryan Drewery } 386bc5e9ac0SBryan Drewery 3878a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 3888a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 389bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 390bc5e9ac0SBryan Drewery "configuration file %s", confpath); 391bc5e9ac0SBryan Drewery else { 392bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 3938a7d859eSBaptiste Daroussin config_parse(obj, conftype); 394bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 39518418e19SKyle Evans parse_repo_file(obj, requested_repo); 396bc5e9ac0SBryan Drewery } 397bc5e9ac0SBryan Drewery 398b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 3998a7d859eSBaptiste Daroussin ucl_parser_free(p); 400bc5e9ac0SBryan Drewery 401bc5e9ac0SBryan Drewery return (0); 402bc5e9ac0SBryan Drewery } 403bc5e9ac0SBryan Drewery 404eb31a574SBryan Drewery static int 40518418e19SKyle Evans load_repositories(const char *repodir, const char *requested_repo) 406eb31a574SBryan Drewery { 407eb31a574SBryan Drewery struct dirent *ent; 408eb31a574SBryan Drewery DIR *d; 409eb31a574SBryan Drewery char *p; 410eb31a574SBryan Drewery size_t n; 411eb31a574SBryan Drewery char path[MAXPATHLEN]; 412eb31a574SBryan Drewery int ret; 413eb31a574SBryan Drewery 414eb31a574SBryan Drewery ret = 0; 415eb31a574SBryan Drewery 416eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 417eb31a574SBryan Drewery return (1); 418eb31a574SBryan Drewery 419eb31a574SBryan Drewery while ((ent = readdir(d))) { 420eb31a574SBryan Drewery /* Trim out 'repos'. */ 421eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 422eb31a574SBryan Drewery continue; 423eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 424eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 425eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 426eb31a574SBryan Drewery repodir, 427eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 428eb31a574SBryan Drewery ent->d_name); 42918418e19SKyle Evans if (access(path, F_OK) != 0) 43018418e19SKyle Evans continue; 43118418e19SKyle Evans if (read_conf_file(path, requested_repo, 43218418e19SKyle Evans CONFFILE_REPO)) { 433eb31a574SBryan Drewery ret = 1; 434eb31a574SBryan Drewery goto cleanup; 435eb31a574SBryan Drewery } 436eb31a574SBryan Drewery } 437eb31a574SBryan Drewery } 438eb31a574SBryan Drewery 439eb31a574SBryan Drewery cleanup: 440eb31a574SBryan Drewery closedir(d); 441eb31a574SBryan Drewery 442eb31a574SBryan Drewery return (ret); 443eb31a574SBryan Drewery } 444eb31a574SBryan Drewery 445bc5e9ac0SBryan Drewery int 44618418e19SKyle Evans config_init(const char *requested_repo) 447bc5e9ac0SBryan Drewery { 448eb31a574SBryan Drewery char *val; 4499950eceeSBaptiste Daroussin int i; 4509950eceeSBaptiste Daroussin const char *localbase; 451eb31a574SBryan Drewery char *env_list_item; 4529950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 453eb31a574SBryan Drewery struct config_value *cv; 4549950eceeSBaptiste Daroussin char abi[BUFSIZ]; 4559950eceeSBaptiste Daroussin 4569950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 4579950eceeSBaptiste Daroussin val = getenv(c[i].key); 4589950eceeSBaptiste Daroussin if (val != NULL) { 4599950eceeSBaptiste Daroussin c[i].envset = true; 460eb31a574SBryan Drewery switch (c[i].type) { 461eb31a574SBryan Drewery case PKG_CONFIG_LIST: 462eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 463eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 464eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 465eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 466eb31a574SBryan Drewery env_list_item != NULL; 467eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 468eb31a574SBryan Drewery cv = 469eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 470eb31a574SBryan Drewery cv->value = 471eb31a574SBryan Drewery strdup(env_list_item); 472eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 473eb31a574SBryan Drewery next); 474eb31a574SBryan Drewery } 475eb31a574SBryan Drewery break; 476eb31a574SBryan Drewery default: 477eb31a574SBryan Drewery c[i].val = val; 478eb31a574SBryan Drewery break; 479eb31a574SBryan Drewery } 4809950eceeSBaptiste Daroussin } 4819950eceeSBaptiste Daroussin } 4829950eceeSBaptiste Daroussin 483eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 48456d11d4aSStefan Eßer localbase = getlocalbase(); 48556d11d4aSStefan Eßer snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); 4869950eceeSBaptiste Daroussin 48718418e19SKyle Evans if (access(confpath, F_OK) == 0 && read_conf_file(confpath, NULL, 488bc5e9ac0SBryan Drewery CONFFILE_PKG)) 4899950eceeSBaptiste Daroussin goto finalize; 4909950eceeSBaptiste Daroussin 491eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 492eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 493eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 494eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 495eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 496eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 497eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 498eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 499eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 500eb31a574SBryan Drewery goto finalize; 501eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 502eb31a574SBryan Drewery } 503eb31a574SBryan Drewery 504eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 50518418e19SKyle Evans if (load_repositories(cv->value, requested_repo)) 506bc5e9ac0SBryan Drewery goto finalize; 5079950eceeSBaptiste Daroussin 5089950eceeSBaptiste Daroussin finalize: 5099950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 5109950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 5114ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 5124ff9a7efSBryan Drewery "ABI"); 5139950eceeSBaptiste Daroussin c[ABI].val = abi; 5149950eceeSBaptiste Daroussin } 5159950eceeSBaptiste Daroussin 516d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 5179950eceeSBaptiste Daroussin 5189950eceeSBaptiste Daroussin return (0); 5199950eceeSBaptiste Daroussin } 5209950eceeSBaptiste Daroussin 5219950eceeSBaptiste Daroussin int 5229950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5239950eceeSBaptiste Daroussin { 5249950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5259950eceeSBaptiste Daroussin return (-1); 5269950eceeSBaptiste Daroussin 5279950eceeSBaptiste Daroussin if (c[k].value != NULL) 5289950eceeSBaptiste Daroussin *val = c[k].value; 5299950eceeSBaptiste Daroussin else 5309950eceeSBaptiste Daroussin *val = c[k].val; 5319950eceeSBaptiste Daroussin 5329950eceeSBaptiste Daroussin return (0); 5339950eceeSBaptiste Daroussin } 5349950eceeSBaptiste Daroussin 5359950eceeSBaptiste Daroussin int 5369950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 5379950eceeSBaptiste Daroussin { 5389950eceeSBaptiste Daroussin const char *value; 5399950eceeSBaptiste Daroussin 5409950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 5419950eceeSBaptiste Daroussin return (-1); 5429950eceeSBaptiste Daroussin 5439950eceeSBaptiste Daroussin *val = false; 5449950eceeSBaptiste Daroussin 5459950eceeSBaptiste Daroussin if (c[k].value != NULL) 5469950eceeSBaptiste Daroussin value = c[k].value; 5479950eceeSBaptiste Daroussin else 5489950eceeSBaptiste Daroussin value = c[k].val; 5499950eceeSBaptiste Daroussin 550eb31a574SBryan Drewery if (boolstr_to_bool(value)) 5519950eceeSBaptiste Daroussin *val = true; 5529950eceeSBaptiste Daroussin 5539950eceeSBaptiste Daroussin return (0); 5549950eceeSBaptiste Daroussin } 5559950eceeSBaptiste Daroussin 5569950eceeSBaptiste Daroussin void 5579950eceeSBaptiste Daroussin config_finish(void) { 5589950eceeSBaptiste Daroussin int i; 5599950eceeSBaptiste Daroussin 5609950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 5619950eceeSBaptiste Daroussin free(c[i].value); 5629950eceeSBaptiste Daroussin } 563