19950eceeSBaptiste Daroussin /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 31de7b4b8SPedro F. Giffuni * 4*eccf736cSBaptiste Daroussin * Copyright (c) 2014-2025 Baptiste Daroussin <bapt@FreeBSD.org> 5f12db248SBryan Drewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 69950eceeSBaptiste Daroussin * 79950eceeSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 89950eceeSBaptiste Daroussin * modification, are permitted provided that the following conditions 99950eceeSBaptiste Daroussin * are met: 109950eceeSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 119950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 129950eceeSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 139950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 149950eceeSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 159950eceeSBaptiste Daroussin * 169950eceeSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 179950eceeSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 189950eceeSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 199950eceeSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 209950eceeSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 219950eceeSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 229950eceeSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 239950eceeSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 249950eceeSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 259950eceeSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 269950eceeSBaptiste Daroussin * SUCH DAMAGE. 279950eceeSBaptiste Daroussin */ 289950eceeSBaptiste Daroussin 299950eceeSBaptiste Daroussin #include <sys/param.h> 30a351c93dSBaptiste Daroussin #include <sys/queue.h> 3160b9a1fcSNathan Whitehorn #include <sys/utsname.h> 3260b9a1fcSNathan Whitehorn #include <sys/sysctl.h> 339950eceeSBaptiste Daroussin 34eb31a574SBryan Drewery #include <dirent.h> 358a7d859eSBaptiste Daroussin #include <ucl.h> 369950eceeSBaptiste Daroussin #include <err.h> 379950eceeSBaptiste Daroussin #include <errno.h> 3856d11d4aSStefan Eßer #include <libutil.h> 391f474190SStefan Eßer #include <paths.h> 409950eceeSBaptiste Daroussin #include <stdbool.h> 419950eceeSBaptiste Daroussin #include <unistd.h> 42e869d3c6SMoritz Schmitt #include <ctype.h> 439950eceeSBaptiste Daroussin 449950eceeSBaptiste Daroussin #include "config.h" 459950eceeSBaptiste Daroussin 46eb31a574SBryan Drewery struct config_value { 47eb31a574SBryan Drewery char *value; 48eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 49eb31a574SBryan Drewery }; 50eb31a574SBryan Drewery 519950eceeSBaptiste Daroussin struct config_entry { 529950eceeSBaptiste Daroussin uint8_t type; 539950eceeSBaptiste Daroussin const char *key; 549950eceeSBaptiste Daroussin const char *val; 559950eceeSBaptiste Daroussin char *value; 56eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 579950eceeSBaptiste Daroussin bool envset; 5897c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 599950eceeSBaptiste Daroussin }; 609950eceeSBaptiste Daroussin 61dc458158SBaptiste Daroussin static struct repositories repositories = STAILQ_HEAD_INITIALIZER(repositories); 62dc458158SBaptiste 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 147fd9ae9acSJohn Baldwin static char * 148fd9ae9acSJohn Baldwin pkg_get_myabi(void) 1499950eceeSBaptiste Daroussin { 15060b9a1fcSNathan Whitehorn struct utsname uts; 15160b9a1fcSNathan Whitehorn char machine_arch[255]; 152fd9ae9acSJohn Baldwin char *abi; 15360b9a1fcSNathan Whitehorn size_t len; 15460b9a1fcSNathan Whitehorn int error; 1559950eceeSBaptiste Daroussin 15660b9a1fcSNathan Whitehorn error = uname(&uts); 15760b9a1fcSNathan Whitehorn if (error) 158fd9ae9acSJohn 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) 163fd9ae9acSJohn 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 */ 170fd9ae9acSJohn Baldwin error = asprintf(&abi, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 17160b9a1fcSNathan Whitehorn machine_arch); 172fd9ae9acSJohn Baldwin if (error < 0) 173fd9ae9acSJohn Baldwin return (NULL); 17440274a2dSBaptiste Daroussin 175fd9ae9acSJohn 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 215dc458158SBaptiste Daroussin config_parse(const ucl_object_t *obj) 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 2428a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 243cc9a8a11SBaptiste Daroussin fputc(toupper(key[j]), buffp); 244cc9a8a11SBaptiste Daroussin fflush(buffp); 245bc5e9ac0SBryan Drewery 2469950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 247cc9a8a11SBaptiste Daroussin if (strcmp(buf, c[i].key) == 0) 2489950eceeSBaptiste Daroussin break; 2499950eceeSBaptiste Daroussin } 2509950eceeSBaptiste Daroussin 251bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 2528a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 2539950eceeSBaptiste Daroussin continue; 2549950eceeSBaptiste Daroussin 2559950eceeSBaptiste Daroussin /* env has priority over config file */ 2568a7d859eSBaptiste Daroussin if (c[i].envset) 2579950eceeSBaptiste Daroussin continue; 2589950eceeSBaptiste Daroussin 259eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 260eb31a574SBryan Drewery switch (c[i].type) { 261eb31a574SBryan Drewery case PKG_CONFIG_LIST: 2628a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 2638a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 264eb31a574SBryan Drewery "value for %s.\n", c[i].key); 265eb31a574SBryan Drewery continue; 266eb31a574SBryan Drewery } 267eb31a574SBryan Drewery temp_config[i].list = 268eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 269eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 270eb31a574SBryan Drewery 2718a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 2728a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 273eb31a574SBryan Drewery continue; 274eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 275eb31a574SBryan Drewery cv->value = 2768a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 277eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 278eb31a574SBryan Drewery next); 279eb31a574SBryan Drewery } 280eb31a574SBryan Drewery break; 281197372c2SBryan Drewery case PKG_CONFIG_BOOL: 282197372c2SBryan Drewery temp_config[i].value = 283197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 284197372c2SBryan Drewery break; 285e869d3c6SMoritz Schmitt case PKG_CONFIG_OBJECT: 286e869d3c6SMoritz Schmitt if (strcmp(c[i].key, "PKG_ENV") == 0) { 287e869d3c6SMoritz Schmitt while ((tmp = 288e869d3c6SMoritz Schmitt ucl_iterate_object(cur, &it_obj, true))) { 289e869d3c6SMoritz Schmitt evkey = ucl_object_key(tmp); 290e869d3c6SMoritz Schmitt if (evkey != NULL && *evkey != '\0') { 291e869d3c6SMoritz Schmitt setenv(evkey, ucl_object_tostring_forced(tmp), 1); 292e869d3c6SMoritz Schmitt } 293e869d3c6SMoritz Schmitt } 294e869d3c6SMoritz Schmitt } 295e869d3c6SMoritz Schmitt break; 296eb31a574SBryan Drewery default: 297eb31a574SBryan Drewery /* Normal string value. */ 2988a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 299eb31a574SBryan Drewery break; 300eb31a574SBryan Drewery } 3019950eceeSBaptiste Daroussin } 3029950eceeSBaptiste Daroussin 303eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 304eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 305eb31a574SBryan Drewery if (c[i].envset) 306eb31a574SBryan Drewery continue; 30797c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 308dc458158SBaptiste Daroussin if (c[i].main_only == true) 30997c3a766SBryan Drewery continue; 310eb31a574SBryan Drewery switch (c[i].type) { 311eb31a574SBryan Drewery case PKG_CONFIG_LIST: 312eb31a574SBryan Drewery c[i].list = temp_config[i].list; 313eb31a574SBryan Drewery break; 314eb31a574SBryan Drewery default: 315eb31a574SBryan Drewery c[i].value = temp_config[i].value; 316eb31a574SBryan Drewery break; 317eb31a574SBryan Drewery } 318eb31a574SBryan Drewery } 319eb31a574SBryan Drewery 320eb31a574SBryan Drewery free(temp_config); 321cc9a8a11SBaptiste Daroussin fclose(buffp); 322cc9a8a11SBaptiste Daroussin free(buf); 3239950eceeSBaptiste Daroussin } 3249950eceeSBaptiste Daroussin 325dc458158SBaptiste Daroussin 326dc458158SBaptiste Daroussin static void 327dc458158SBaptiste Daroussin parse_mirror_type(struct repository *r, const char *mt) 328dc458158SBaptiste Daroussin { 329dc458158SBaptiste Daroussin if (strcasecmp(mt, "srv") == 0) 330dc458158SBaptiste Daroussin r->mirror_type = MIRROR_SRV; 331dc458158SBaptiste Daroussin r->mirror_type = MIRROR_NONE; 332dc458158SBaptiste Daroussin } 333dc458158SBaptiste Daroussin 334*eccf736cSBaptiste Daroussin static void 335*eccf736cSBaptiste Daroussin repo_free(struct repository *r) 336*eccf736cSBaptiste Daroussin { 337*eccf736cSBaptiste Daroussin free(r->name); 338*eccf736cSBaptiste Daroussin free(r->url); 339*eccf736cSBaptiste Daroussin free(r->fingerprints); 340*eccf736cSBaptiste Daroussin free(r->pubkey); 341*eccf736cSBaptiste Daroussin free(r); 342*eccf736cSBaptiste Daroussin } 343*eccf736cSBaptiste Daroussin 344dc458158SBaptiste Daroussin static bool 345dc458158SBaptiste Daroussin parse_signature_type(struct repository *repo, const char *st) 346dc458158SBaptiste Daroussin { 347dc458158SBaptiste Daroussin if (strcasecmp(st, "FINGERPRINTS") == 0) 348dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_FINGERPRINT; 349dc458158SBaptiste Daroussin else if (strcasecmp(st, "PUBKEY") == 0) 350dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_PUBKEY; 351dc458158SBaptiste Daroussin else if (strcasecmp(st, "NONE") == 0) 352dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_NONE; 353dc458158SBaptiste Daroussin else { 35449f4e3d2SBenedict Reuschling warnx("Signature type %s is not supported for bootstrapping," 355dc458158SBaptiste Daroussin " ignoring repository %s", st, repo->name); 356*eccf736cSBaptiste Daroussin repo_free(repo); 357dc458158SBaptiste Daroussin return false; 358dc458158SBaptiste Daroussin } 359dc458158SBaptiste Daroussin return (true); 360dc458158SBaptiste Daroussin } 361dc458158SBaptiste Daroussin 362dc458158SBaptiste Daroussin static void 363dc458158SBaptiste Daroussin parse_repo(const ucl_object_t *o) 364dc458158SBaptiste Daroussin { 365dc458158SBaptiste Daroussin const ucl_object_t *cur; 366dc458158SBaptiste Daroussin const char *key; 367dc458158SBaptiste Daroussin ucl_object_iter_t it = NULL; 368dc458158SBaptiste Daroussin 369dc458158SBaptiste Daroussin struct repository *repo = calloc(1, sizeof(struct repository)); 370dc458158SBaptiste Daroussin if (repo == NULL) 371dc458158SBaptiste Daroussin err(EXIT_FAILURE, "calloc"); 372dc458158SBaptiste Daroussin 373dc458158SBaptiste Daroussin repo->name = strdup(ucl_object_key(o)); 374dc458158SBaptiste Daroussin if (repo->name == NULL) 375dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 376dc458158SBaptiste Daroussin while ((cur = ucl_iterate_object(o, &it, true))) { 377dc458158SBaptiste Daroussin key = ucl_object_key(cur); 378dc458158SBaptiste Daroussin if (key == NULL) 379dc458158SBaptiste Daroussin continue; 380dc458158SBaptiste Daroussin if (strcasecmp(key, "url") == 0) { 381dc458158SBaptiste Daroussin repo->url = strdup(ucl_object_tostring(cur)); 382dc458158SBaptiste Daroussin if (repo->url == NULL) 383dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 384dc458158SBaptiste Daroussin } else if (strcasecmp(key, "mirror_type") == 0) { 385dc458158SBaptiste Daroussin parse_mirror_type(repo, ucl_object_tostring(cur)); 386dc458158SBaptiste Daroussin } else if (strcasecmp(key, "signature_type") == 0) { 387dc458158SBaptiste Daroussin if (!parse_signature_type(repo, ucl_object_tostring(cur))) 388dc458158SBaptiste Daroussin return; 389dc458158SBaptiste Daroussin } else if (strcasecmp(key, "fingerprints") == 0) { 390dc458158SBaptiste Daroussin repo->fingerprints = strdup(ucl_object_tostring(cur)); 391dc458158SBaptiste Daroussin if (repo->fingerprints == NULL) 392dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 393dc458158SBaptiste Daroussin } else if (strcasecmp(key, "pubkey") == 0) { 394dc458158SBaptiste Daroussin repo->pubkey = strdup(ucl_object_tostring(cur)); 395dc458158SBaptiste Daroussin if (repo->pubkey == NULL) 396dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 397dc458158SBaptiste Daroussin } else if (strcasecmp(key, "enabled") == 0) { 398dc458158SBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 399dc458158SBaptiste Daroussin !ucl_object_toboolean(cur)) { 400*eccf736cSBaptiste Daroussin repo_free(repo); 401dc458158SBaptiste Daroussin return; 402dc458158SBaptiste Daroussin } 403dc458158SBaptiste Daroussin } 404dc458158SBaptiste Daroussin } 405*eccf736cSBaptiste Daroussin /* At least we need an url */ 406*eccf736cSBaptiste Daroussin if (repo->url == NULL) { 407*eccf736cSBaptiste Daroussin repo_free(repo); 408*eccf736cSBaptiste Daroussin return; 409*eccf736cSBaptiste Daroussin } 410dc458158SBaptiste Daroussin STAILQ_INSERT_TAIL(&repositories, repo, next); 411dc458158SBaptiste Daroussin return; 412dc458158SBaptiste Daroussin } 413dc458158SBaptiste Daroussin 414bc5e9ac0SBryan Drewery /*- 415bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 416bc5e9ac0SBryan Drewery * Name: 417bc5e9ac0SBryan Drewery * URL: 418bc5e9ac0SBryan Drewery * MIRROR_TYPE: 419bc5e9ac0SBryan Drewery * etc... 420bc5e9ac0SBryan Drewery */ 421bc5e9ac0SBryan Drewery static void 42218418e19SKyle Evans parse_repo_file(ucl_object_t *obj, const char *requested_repo) 423bc5e9ac0SBryan Drewery { 4248a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 425b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 4268a7d859eSBaptiste Daroussin const char *key; 427bc5e9ac0SBryan Drewery 4288a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 4298a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 430bc5e9ac0SBryan Drewery 4318a7d859eSBaptiste Daroussin if (key == NULL) 432bc5e9ac0SBryan Drewery continue; 433bc5e9ac0SBryan Drewery 4348a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 435bc5e9ac0SBryan Drewery continue; 436bc5e9ac0SBryan Drewery 43718418e19SKyle Evans if (requested_repo != NULL && strcmp(requested_repo, key) != 0) 43818418e19SKyle Evans continue; 439dc458158SBaptiste Daroussin parse_repo(cur); 440bc5e9ac0SBryan Drewery } 441bc5e9ac0SBryan Drewery } 442bc5e9ac0SBryan Drewery 443bc5e9ac0SBryan Drewery 444bc5e9ac0SBryan Drewery static int 44518418e19SKyle Evans read_conf_file(const char *confpath, const char *requested_repo, 44618418e19SKyle Evans pkg_conf_file_t conftype) 4479950eceeSBaptiste Daroussin { 4488a7d859eSBaptiste Daroussin struct ucl_parser *p; 4498a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 450dc458158SBaptiste Daroussin const char *abi = pkg_get_myabi(); 451dc458158SBaptiste Daroussin if (abi == NULL) 45249f4e3d2SBenedict Reuschling errx(EXIT_FAILURE, "Failed to determine ABI"); 453bc5e9ac0SBryan Drewery 4548a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 455dc458158SBaptiste Daroussin ucl_parser_register_variable(p, "ABI", abi); 4568a7d859eSBaptiste Daroussin 4578a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 458bc5e9ac0SBryan Drewery if (errno != ENOENT) 4598a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 4608a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 4618a7d859eSBaptiste Daroussin ucl_parser_free(p); 462bc5e9ac0SBryan Drewery /* no configuration present */ 463bc5e9ac0SBryan Drewery return (1); 464bc5e9ac0SBryan Drewery } 465bc5e9ac0SBryan Drewery 4668a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 4678a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 468bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 469bc5e9ac0SBryan Drewery "configuration file %s", confpath); 470bc5e9ac0SBryan Drewery else { 471bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 472dc458158SBaptiste Daroussin config_parse(obj); 473bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 47418418e19SKyle Evans parse_repo_file(obj, requested_repo); 475bc5e9ac0SBryan Drewery } 476bc5e9ac0SBryan Drewery 477b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 4788a7d859eSBaptiste Daroussin ucl_parser_free(p); 479bc5e9ac0SBryan Drewery 480bc5e9ac0SBryan Drewery return (0); 481bc5e9ac0SBryan Drewery } 482bc5e9ac0SBryan Drewery 483dc458158SBaptiste Daroussin static void 48418418e19SKyle Evans load_repositories(const char *repodir, const char *requested_repo) 485eb31a574SBryan Drewery { 486eb31a574SBryan Drewery struct dirent *ent; 487eb31a574SBryan Drewery DIR *d; 488eb31a574SBryan Drewery char *p; 489eb31a574SBryan Drewery size_t n; 490eb31a574SBryan Drewery char path[MAXPATHLEN]; 491eb31a574SBryan Drewery 492eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 493dc458158SBaptiste Daroussin return; 494eb31a574SBryan Drewery 495eb31a574SBryan Drewery while ((ent = readdir(d))) { 496eb31a574SBryan Drewery /* Trim out 'repos'. */ 497eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 498eb31a574SBryan Drewery continue; 499eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 500eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 501eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 502eb31a574SBryan Drewery repodir, 503eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 504eb31a574SBryan Drewery ent->d_name); 50518418e19SKyle Evans if (access(path, F_OK) != 0) 50618418e19SKyle Evans continue; 50718418e19SKyle Evans if (read_conf_file(path, requested_repo, 50818418e19SKyle Evans CONFFILE_REPO)) { 509eb31a574SBryan Drewery goto cleanup; 510eb31a574SBryan Drewery } 511eb31a574SBryan Drewery } 512eb31a574SBryan Drewery } 513eb31a574SBryan Drewery 514eb31a574SBryan Drewery cleanup: 515eb31a574SBryan Drewery closedir(d); 516eb31a574SBryan Drewery } 517eb31a574SBryan Drewery 518bc5e9ac0SBryan Drewery int 51918418e19SKyle Evans config_init(const char *requested_repo) 520bc5e9ac0SBryan Drewery { 521eb31a574SBryan Drewery char *val; 5229950eceeSBaptiste Daroussin int i; 5239950eceeSBaptiste Daroussin const char *localbase; 524fd9ae9acSJohn Baldwin char *abi, *env_list_item; 5259950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 526eb31a574SBryan Drewery struct config_value *cv; 5279950eceeSBaptiste Daroussin 5289950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5299950eceeSBaptiste Daroussin val = getenv(c[i].key); 5309950eceeSBaptiste Daroussin if (val != NULL) { 5319950eceeSBaptiste Daroussin c[i].envset = true; 532eb31a574SBryan Drewery switch (c[i].type) { 533eb31a574SBryan Drewery case PKG_CONFIG_LIST: 534eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 535eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 536eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 537eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 538eb31a574SBryan Drewery env_list_item != NULL; 539eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 540eb31a574SBryan Drewery cv = 541eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 542eb31a574SBryan Drewery cv->value = 543eb31a574SBryan Drewery strdup(env_list_item); 544eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 545eb31a574SBryan Drewery next); 546eb31a574SBryan Drewery } 547eb31a574SBryan Drewery break; 548eb31a574SBryan Drewery default: 549eb31a574SBryan Drewery c[i].val = val; 550eb31a574SBryan Drewery break; 551eb31a574SBryan Drewery } 5529950eceeSBaptiste Daroussin } 5539950eceeSBaptiste Daroussin } 5549950eceeSBaptiste Daroussin 555eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 55656d11d4aSStefan Eßer localbase = getlocalbase(); 55756d11d4aSStefan Eßer snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); 5589950eceeSBaptiste Daroussin 55918418e19SKyle Evans if (access(confpath, F_OK) == 0 && read_conf_file(confpath, NULL, 560bc5e9ac0SBryan Drewery CONFFILE_PKG)) 5619950eceeSBaptiste Daroussin goto finalize; 5629950eceeSBaptiste Daroussin 563eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 564eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 565eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 566eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 567eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 568eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 569eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 570eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 571eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 572eb31a574SBryan Drewery goto finalize; 573eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 574eb31a574SBryan Drewery } 575eb31a574SBryan Drewery 576eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 577dc458158SBaptiste Daroussin load_repositories(cv->value, requested_repo); 5789950eceeSBaptiste Daroussin 5799950eceeSBaptiste Daroussin finalize: 5809950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 581fd9ae9acSJohn Baldwin abi = pkg_get_myabi(); 582fd9ae9acSJohn Baldwin if (abi == NULL) 5834ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 5844ff9a7efSBryan Drewery "ABI"); 5859950eceeSBaptiste Daroussin c[ABI].val = abi; 5869950eceeSBaptiste Daroussin } 5879950eceeSBaptiste Daroussin 5889950eceeSBaptiste Daroussin return (0); 5899950eceeSBaptiste Daroussin } 5909950eceeSBaptiste Daroussin 5919950eceeSBaptiste Daroussin int 5929950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5939950eceeSBaptiste Daroussin { 5949950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5959950eceeSBaptiste Daroussin return (-1); 5969950eceeSBaptiste Daroussin 5979950eceeSBaptiste Daroussin if (c[k].value != NULL) 5989950eceeSBaptiste Daroussin *val = c[k].value; 5999950eceeSBaptiste Daroussin else 6009950eceeSBaptiste Daroussin *val = c[k].val; 6019950eceeSBaptiste Daroussin 6029950eceeSBaptiste Daroussin return (0); 6039950eceeSBaptiste Daroussin } 6049950eceeSBaptiste Daroussin 6059950eceeSBaptiste Daroussin int 6069950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 6079950eceeSBaptiste Daroussin { 6089950eceeSBaptiste Daroussin const char *value; 6099950eceeSBaptiste Daroussin 6109950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 6119950eceeSBaptiste Daroussin return (-1); 6129950eceeSBaptiste Daroussin 6139950eceeSBaptiste Daroussin *val = false; 6149950eceeSBaptiste Daroussin 6159950eceeSBaptiste Daroussin if (c[k].value != NULL) 6169950eceeSBaptiste Daroussin value = c[k].value; 6179950eceeSBaptiste Daroussin else 6189950eceeSBaptiste Daroussin value = c[k].val; 6199950eceeSBaptiste Daroussin 620eb31a574SBryan Drewery if (boolstr_to_bool(value)) 6219950eceeSBaptiste Daroussin *val = true; 6229950eceeSBaptiste Daroussin 6239950eceeSBaptiste Daroussin return (0); 6249950eceeSBaptiste Daroussin } 6259950eceeSBaptiste Daroussin 626dc458158SBaptiste Daroussin struct repositories * 627dc458158SBaptiste Daroussin config_get_repositories(void) 628dc458158SBaptiste Daroussin { 629dc458158SBaptiste Daroussin if (STAILQ_EMPTY(&repositories)) { 630dc458158SBaptiste Daroussin /* Fall back to PACKAGESITE - deprecated - */ 631dc458158SBaptiste Daroussin struct repository *r = calloc(1, sizeof(r)); 632dc458158SBaptiste Daroussin if (r == NULL) 633dc458158SBaptiste Daroussin err(EXIT_FAILURE, "calloc"); 634dc458158SBaptiste Daroussin r->name = strdup("fallback"); 635dc458158SBaptiste Daroussin if (r->name == NULL) 636dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 637dc458158SBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 638dc458158SBaptiste Daroussin r->url = c[PACKAGESITE].value; 639dc458158SBaptiste Daroussin if (c[SIGNATURE_TYPE].value != NULL) 640dc458158SBaptiste Daroussin if (!parse_signature_type(r, c[SIGNATURE_TYPE].value)) 641dc458158SBaptiste Daroussin exit(EXIT_FAILURE); 642dc458158SBaptiste Daroussin if (c[MIRROR_TYPE].value != NULL) 643dc458158SBaptiste Daroussin parse_mirror_type(r, c[MIRROR_TYPE].value); 644dc458158SBaptiste Daroussin if (c[PUBKEY].value != NULL) 645dc458158SBaptiste Daroussin r->pubkey = c[PUBKEY].value; 646dc458158SBaptiste Daroussin if (c[FINGERPRINTS].value != NULL) 647dc458158SBaptiste Daroussin r->fingerprints = c[FINGERPRINTS].value; 648dc458158SBaptiste Daroussin STAILQ_INSERT_TAIL(&repositories, r, next); 649dc458158SBaptiste Daroussin } 650dc458158SBaptiste Daroussin return (&repositories); 651dc458158SBaptiste Daroussin } 652dc458158SBaptiste Daroussin 6539950eceeSBaptiste Daroussin void 6549950eceeSBaptiste Daroussin config_finish(void) { 6559950eceeSBaptiste Daroussin int i; 6569950eceeSBaptiste Daroussin 6579950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 6589950eceeSBaptiste Daroussin free(c[i].value); 6599950eceeSBaptiste Daroussin } 660