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/param.h> 31a351c93dSBaptiste Daroussin #include <sys/queue.h> 3260b9a1fcSNathan Whitehorn #include <sys/utsname.h> 3360b9a1fcSNathan Whitehorn #include <sys/sysctl.h> 349950eceeSBaptiste Daroussin 35eb31a574SBryan Drewery #include <dirent.h> 368a7d859eSBaptiste Daroussin #include <ucl.h> 379950eceeSBaptiste Daroussin #include <err.h> 389950eceeSBaptiste Daroussin #include <errno.h> 3956d11d4aSStefan Eßer #include <libutil.h> 401f474190SStefan Eßer #include <paths.h> 419950eceeSBaptiste Daroussin #include <stdbool.h> 429950eceeSBaptiste Daroussin #include <unistd.h> 43e869d3c6SMoritz Schmitt #include <ctype.h> 449950eceeSBaptiste Daroussin 459950eceeSBaptiste Daroussin #include "config.h" 469950eceeSBaptiste Daroussin 47eb31a574SBryan Drewery struct config_value { 48eb31a574SBryan Drewery char *value; 49eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 50eb31a574SBryan Drewery }; 51eb31a574SBryan Drewery 529950eceeSBaptiste Daroussin struct config_entry { 539950eceeSBaptiste Daroussin uint8_t type; 549950eceeSBaptiste Daroussin const char *key; 559950eceeSBaptiste Daroussin const char *val; 569950eceeSBaptiste Daroussin char *value; 57eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 589950eceeSBaptiste Daroussin bool envset; 5997c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 609950eceeSBaptiste Daroussin }; 619950eceeSBaptiste Daroussin 62dc458158SBaptiste Daroussin static struct repositories repositories = STAILQ_HEAD_INITIALIZER(repositories); 63dc458158SBaptiste Daroussin 649950eceeSBaptiste Daroussin static struct config_entry c[] = { 659950eceeSBaptiste Daroussin [PACKAGESITE] = { 669950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 679950eceeSBaptiste Daroussin "PACKAGESITE", 6862940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 699950eceeSBaptiste Daroussin NULL, 70eb31a574SBryan Drewery NULL, 719950eceeSBaptiste Daroussin false, 7297c3a766SBryan Drewery false, 739950eceeSBaptiste Daroussin }, 749950eceeSBaptiste Daroussin [ABI] = { 759950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 769950eceeSBaptiste Daroussin "ABI", 779950eceeSBaptiste Daroussin NULL, 789950eceeSBaptiste Daroussin NULL, 79eb31a574SBryan Drewery NULL, 809950eceeSBaptiste Daroussin false, 8197c3a766SBryan Drewery true, 829950eceeSBaptiste Daroussin }, 839950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 849950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 859950eceeSBaptiste Daroussin "MIRROR_TYPE", 869950eceeSBaptiste Daroussin "SRV", 879950eceeSBaptiste Daroussin NULL, 88eb31a574SBryan Drewery NULL, 899950eceeSBaptiste Daroussin false, 9097c3a766SBryan Drewery false, 919950eceeSBaptiste Daroussin }, 929950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 939950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 949950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 959950eceeSBaptiste Daroussin "NO", 969950eceeSBaptiste Daroussin NULL, 97eb31a574SBryan Drewery NULL, 989950eceeSBaptiste Daroussin false, 9997c3a766SBryan Drewery true, 100f12db248SBryan Drewery }, 101f12db248SBryan Drewery [SIGNATURE_TYPE] = { 102f12db248SBryan Drewery PKG_CONFIG_STRING, 103f12db248SBryan Drewery "SIGNATURE_TYPE", 104f12db248SBryan Drewery NULL, 105f12db248SBryan Drewery NULL, 106eb31a574SBryan Drewery NULL, 107f12db248SBryan Drewery false, 10897c3a766SBryan Drewery false, 109f12db248SBryan Drewery }, 110f12db248SBryan Drewery [FINGERPRINTS] = { 111f12db248SBryan Drewery PKG_CONFIG_STRING, 112f12db248SBryan Drewery "FINGERPRINTS", 113f12db248SBryan Drewery NULL, 114f12db248SBryan Drewery NULL, 115eb31a574SBryan Drewery NULL, 116eb31a574SBryan Drewery false, 11797c3a766SBryan Drewery false, 118eb31a574SBryan Drewery }, 119eb31a574SBryan Drewery [REPOS_DIR] = { 120eb31a574SBryan Drewery PKG_CONFIG_LIST, 121eb31a574SBryan Drewery "REPOS_DIR", 122eb31a574SBryan Drewery NULL, 123eb31a574SBryan Drewery NULL, 124eb31a574SBryan Drewery NULL, 125f12db248SBryan Drewery false, 12697c3a766SBryan Drewery true, 127f12db248SBryan Drewery }, 12861acb458SBaptiste Daroussin [PUBKEY] = { 12961acb458SBaptiste Daroussin PKG_CONFIG_STRING, 13061acb458SBaptiste Daroussin "PUBKEY", 13161acb458SBaptiste Daroussin NULL, 13261acb458SBaptiste Daroussin NULL, 13361acb458SBaptiste Daroussin NULL, 13461acb458SBaptiste Daroussin false, 13561acb458SBaptiste Daroussin false 136e869d3c6SMoritz Schmitt }, 137e869d3c6SMoritz Schmitt [PKG_ENV] = { 138e869d3c6SMoritz Schmitt PKG_CONFIG_OBJECT, 139e869d3c6SMoritz Schmitt "PKG_ENV", 140e869d3c6SMoritz Schmitt NULL, 141e869d3c6SMoritz Schmitt NULL, 142e869d3c6SMoritz Schmitt NULL, 143e869d3c6SMoritz Schmitt false, 144e869d3c6SMoritz Schmitt false, 14561acb458SBaptiste Daroussin } 1469950eceeSBaptiste Daroussin }; 1479950eceeSBaptiste Daroussin 148fd9ae9acSJohn Baldwin static char * 149fd9ae9acSJohn Baldwin pkg_get_myabi(void) 1509950eceeSBaptiste Daroussin { 15160b9a1fcSNathan Whitehorn struct utsname uts; 15260b9a1fcSNathan Whitehorn char machine_arch[255]; 153fd9ae9acSJohn Baldwin char *abi; 15460b9a1fcSNathan Whitehorn size_t len; 15560b9a1fcSNathan Whitehorn int error; 1569950eceeSBaptiste Daroussin 15760b9a1fcSNathan Whitehorn error = uname(&uts); 15860b9a1fcSNathan Whitehorn if (error) 159fd9ae9acSJohn Baldwin return (NULL); 1609950eceeSBaptiste Daroussin 16160b9a1fcSNathan Whitehorn len = sizeof(machine_arch); 16260b9a1fcSNathan Whitehorn error = sysctlbyname("hw.machine_arch", machine_arch, &len, NULL, 0); 16360b9a1fcSNathan Whitehorn if (error) 164fd9ae9acSJohn Baldwin return (NULL); 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 */ 171fd9ae9acSJohn Baldwin error = asprintf(&abi, "%s:%d:%s", uts.sysname, __FreeBSD_version/100000, 17260b9a1fcSNathan Whitehorn machine_arch); 173fd9ae9acSJohn Baldwin if (error < 0) 174fd9ae9acSJohn Baldwin return (NULL); 17540274a2dSBaptiste Daroussin 176fd9ae9acSJohn Baldwin return (abi); 1779950eceeSBaptiste Daroussin } 1789950eceeSBaptiste Daroussin 1799950eceeSBaptiste Daroussin static void 1809950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 1819950eceeSBaptiste Daroussin { 182ae659caaSBaptiste Daroussin char *newval; 1839950eceeSBaptiste Daroussin const char *variable_string; 1849950eceeSBaptiste Daroussin const char *oldval; 1859950eceeSBaptiste Daroussin 1869950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 1879950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 1889950eceeSBaptiste Daroussin else 1899950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 1909950eceeSBaptiste Daroussin 1919950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 1929950eceeSBaptiste Daroussin return; 1939950eceeSBaptiste Daroussin 194ae659caaSBaptiste Daroussin asprintf(&newval, "%.*s%s%s", 195ae659caaSBaptiste Daroussin (int)(variable_string - oldval), oldval, abi, 196ae659caaSBaptiste Daroussin variable_string + strlen("${ABI}")); 197ae659caaSBaptiste Daroussin if (newval == NULL) 198ae659caaSBaptiste Daroussin errx(EXIT_FAILURE, "asprintf"); 1999950eceeSBaptiste Daroussin 2009950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 201ae659caaSBaptiste Daroussin c[PACKAGESITE].value = newval; 2029950eceeSBaptiste Daroussin } 2039950eceeSBaptiste Daroussin 204eb31a574SBryan Drewery static int 205eb31a574SBryan Drewery boolstr_to_bool(const char *str) 206eb31a574SBryan Drewery { 207eb31a574SBryan Drewery if (str != NULL && (strcasecmp(str, "true") == 0 || 208eb31a574SBryan Drewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 209eb31a574SBryan Drewery str[0] == '1')) 210eb31a574SBryan Drewery return (true); 211eb31a574SBryan Drewery 212eb31a574SBryan Drewery return (false); 213eb31a574SBryan Drewery } 214eb31a574SBryan Drewery 2159950eceeSBaptiste Daroussin static void 216dc458158SBaptiste Daroussin config_parse(const ucl_object_t *obj) 2179950eceeSBaptiste Daroussin { 218cc9a8a11SBaptiste Daroussin FILE *buffp; 219cc9a8a11SBaptiste Daroussin char *buf = NULL; 220cc9a8a11SBaptiste Daroussin size_t bufsz = 0; 221e869d3c6SMoritz Schmitt const ucl_object_t *cur, *seq, *tmp; 222e869d3c6SMoritz Schmitt ucl_object_iter_t it = NULL, itseq = NULL, it_obj = NULL; 223eb31a574SBryan Drewery struct config_entry *temp_config; 224eb31a574SBryan Drewery struct config_value *cv; 225e869d3c6SMoritz Schmitt const char *key, *evkey; 2269950eceeSBaptiste Daroussin int i; 2279950eceeSBaptiste Daroussin size_t j; 2289950eceeSBaptiste Daroussin 229eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 230eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 231cc9a8a11SBaptiste Daroussin buffp = open_memstream(&buf, &bufsz); 232cc9a8a11SBaptiste Daroussin if (buffp == NULL) 233cc9a8a11SBaptiste Daroussin err(EXIT_FAILURE, "open_memstream()"); 234eb31a574SBryan Drewery 2358a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 2368a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 2378a7d859eSBaptiste Daroussin if (key == NULL) 2389950eceeSBaptiste Daroussin continue; 239cc9a8a11SBaptiste Daroussin if (buf != NULL) 240cc9a8a11SBaptiste Daroussin memset(buf, 0, bufsz); 241cc9a8a11SBaptiste Daroussin rewind(buffp); 2429950eceeSBaptiste Daroussin 2438a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 244cc9a8a11SBaptiste Daroussin fputc(toupper(key[j]), buffp); 245cc9a8a11SBaptiste Daroussin fflush(buffp); 246bc5e9ac0SBryan Drewery 2479950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 248cc9a8a11SBaptiste Daroussin if (strcmp(buf, c[i].key) == 0) 2499950eceeSBaptiste Daroussin break; 2509950eceeSBaptiste Daroussin } 2519950eceeSBaptiste Daroussin 252bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 2538a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 2549950eceeSBaptiste Daroussin continue; 2559950eceeSBaptiste Daroussin 2569950eceeSBaptiste Daroussin /* env has priority over config file */ 2578a7d859eSBaptiste Daroussin if (c[i].envset) 2589950eceeSBaptiste Daroussin continue; 2599950eceeSBaptiste Daroussin 260eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 261eb31a574SBryan Drewery switch (c[i].type) { 262eb31a574SBryan Drewery case PKG_CONFIG_LIST: 2638a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 2648a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 265eb31a574SBryan Drewery "value for %s.\n", c[i].key); 266eb31a574SBryan Drewery continue; 267eb31a574SBryan Drewery } 268eb31a574SBryan Drewery temp_config[i].list = 269eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 270eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 271eb31a574SBryan Drewery 2728a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 2738a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 274eb31a574SBryan Drewery continue; 275eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 276eb31a574SBryan Drewery cv->value = 2778a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 278eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 279eb31a574SBryan Drewery next); 280eb31a574SBryan Drewery } 281eb31a574SBryan Drewery break; 282197372c2SBryan Drewery case PKG_CONFIG_BOOL: 283197372c2SBryan Drewery temp_config[i].value = 284197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 285197372c2SBryan Drewery break; 286e869d3c6SMoritz Schmitt case PKG_CONFIG_OBJECT: 287e869d3c6SMoritz Schmitt if (strcmp(c[i].key, "PKG_ENV") == 0) { 288e869d3c6SMoritz Schmitt while ((tmp = 289e869d3c6SMoritz Schmitt ucl_iterate_object(cur, &it_obj, true))) { 290e869d3c6SMoritz Schmitt evkey = ucl_object_key(tmp); 291e869d3c6SMoritz Schmitt if (evkey != NULL && *evkey != '\0') { 292e869d3c6SMoritz Schmitt setenv(evkey, ucl_object_tostring_forced(tmp), 1); 293e869d3c6SMoritz Schmitt } 294e869d3c6SMoritz Schmitt } 295e869d3c6SMoritz Schmitt } 296e869d3c6SMoritz Schmitt break; 297eb31a574SBryan Drewery default: 298eb31a574SBryan Drewery /* Normal string value. */ 2998a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 300eb31a574SBryan Drewery break; 301eb31a574SBryan Drewery } 3029950eceeSBaptiste Daroussin } 3039950eceeSBaptiste Daroussin 304eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 305eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 306eb31a574SBryan Drewery if (c[i].envset) 307eb31a574SBryan Drewery continue; 30897c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 309dc458158SBaptiste Daroussin if (c[i].main_only == true) 31097c3a766SBryan Drewery continue; 311eb31a574SBryan Drewery switch (c[i].type) { 312eb31a574SBryan Drewery case PKG_CONFIG_LIST: 313eb31a574SBryan Drewery c[i].list = temp_config[i].list; 314eb31a574SBryan Drewery break; 315eb31a574SBryan Drewery default: 316eb31a574SBryan Drewery c[i].value = temp_config[i].value; 317eb31a574SBryan Drewery break; 318eb31a574SBryan Drewery } 319eb31a574SBryan Drewery } 320eb31a574SBryan Drewery 321eb31a574SBryan Drewery free(temp_config); 322cc9a8a11SBaptiste Daroussin fclose(buffp); 323cc9a8a11SBaptiste Daroussin free(buf); 3249950eceeSBaptiste Daroussin } 3259950eceeSBaptiste Daroussin 326dc458158SBaptiste Daroussin 327dc458158SBaptiste Daroussin static void 328dc458158SBaptiste Daroussin parse_mirror_type(struct repository *r, const char *mt) 329dc458158SBaptiste Daroussin { 330dc458158SBaptiste Daroussin if (strcasecmp(mt, "srv") == 0) 331dc458158SBaptiste Daroussin r->mirror_type = MIRROR_SRV; 332dc458158SBaptiste Daroussin r->mirror_type = MIRROR_NONE; 333dc458158SBaptiste Daroussin } 334dc458158SBaptiste Daroussin 335dc458158SBaptiste Daroussin static bool 336dc458158SBaptiste Daroussin parse_signature_type(struct repository *repo, const char *st) 337dc458158SBaptiste Daroussin { 338dc458158SBaptiste Daroussin if (strcasecmp(st, "FINGERPRINTS") == 0) 339dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_FINGERPRINT; 340dc458158SBaptiste Daroussin else if (strcasecmp(st, "PUBKEY") == 0) 341dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_PUBKEY; 342dc458158SBaptiste Daroussin else if (strcasecmp(st, "NONE") == 0) 343dc458158SBaptiste Daroussin repo->signature_type = SIGNATURE_NONE; 344dc458158SBaptiste Daroussin else { 345*49f4e3d2SBenedict Reuschling warnx("Signature type %s is not supported for bootstrapping," 346dc458158SBaptiste Daroussin " ignoring repository %s", st, repo->name); 347dc458158SBaptiste Daroussin free(repo->url); 348dc458158SBaptiste Daroussin free(repo->name); 349dc458158SBaptiste Daroussin free(repo->fingerprints); 350dc458158SBaptiste Daroussin free(repo->pubkey); 351dc458158SBaptiste Daroussin free(repo); 352dc458158SBaptiste Daroussin return false; 353dc458158SBaptiste Daroussin } 354dc458158SBaptiste Daroussin return (true); 355dc458158SBaptiste Daroussin } 356dc458158SBaptiste Daroussin 357dc458158SBaptiste Daroussin static void 358dc458158SBaptiste Daroussin parse_repo(const ucl_object_t *o) 359dc458158SBaptiste Daroussin { 360dc458158SBaptiste Daroussin const ucl_object_t *cur; 361dc458158SBaptiste Daroussin const char *key; 362dc458158SBaptiste Daroussin ucl_object_iter_t it = NULL; 363dc458158SBaptiste Daroussin 364dc458158SBaptiste Daroussin struct repository *repo = calloc(1, sizeof(struct repository)); 365dc458158SBaptiste Daroussin if (repo == NULL) 366dc458158SBaptiste Daroussin err(EXIT_FAILURE, "calloc"); 367dc458158SBaptiste Daroussin 368dc458158SBaptiste Daroussin repo->name = strdup(ucl_object_key(o)); 369dc458158SBaptiste Daroussin if (repo->name == NULL) 370dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 371dc458158SBaptiste Daroussin while ((cur = ucl_iterate_object(o, &it, true))) { 372dc458158SBaptiste Daroussin key = ucl_object_key(cur); 373dc458158SBaptiste Daroussin if (key == NULL) 374dc458158SBaptiste Daroussin continue; 375dc458158SBaptiste Daroussin if (strcasecmp(key, "url") == 0) { 376dc458158SBaptiste Daroussin repo->url = strdup(ucl_object_tostring(cur)); 377dc458158SBaptiste Daroussin if (repo->url == NULL) 378dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 379dc458158SBaptiste Daroussin } else if (strcasecmp(key, "mirror_type") == 0) { 380dc458158SBaptiste Daroussin parse_mirror_type(repo, ucl_object_tostring(cur)); 381dc458158SBaptiste Daroussin } else if (strcasecmp(key, "signature_type") == 0) { 382dc458158SBaptiste Daroussin if (!parse_signature_type(repo, ucl_object_tostring(cur))) 383dc458158SBaptiste Daroussin return; 384dc458158SBaptiste Daroussin } else if (strcasecmp(key, "fingerprints") == 0) { 385dc458158SBaptiste Daroussin repo->fingerprints = strdup(ucl_object_tostring(cur)); 386dc458158SBaptiste Daroussin if (repo->fingerprints == NULL) 387dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 388dc458158SBaptiste Daroussin } else if (strcasecmp(key, "pubkey") == 0) { 389dc458158SBaptiste Daroussin repo->pubkey = strdup(ucl_object_tostring(cur)); 390dc458158SBaptiste Daroussin if (repo->pubkey == NULL) 391dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 392dc458158SBaptiste Daroussin } else if (strcasecmp(key, "enabled") == 0) { 393dc458158SBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 394dc458158SBaptiste Daroussin !ucl_object_toboolean(cur)) { 395dc458158SBaptiste Daroussin free(repo->url); 396dc458158SBaptiste Daroussin free(repo->name); 397dc458158SBaptiste Daroussin free(repo); 398dc458158SBaptiste Daroussin return; 399dc458158SBaptiste Daroussin } 400dc458158SBaptiste Daroussin } 401dc458158SBaptiste Daroussin } 402dc458158SBaptiste Daroussin STAILQ_INSERT_TAIL(&repositories, repo, next); 403dc458158SBaptiste Daroussin return; 404dc458158SBaptiste Daroussin } 405dc458158SBaptiste Daroussin 406bc5e9ac0SBryan Drewery /*- 407bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 408bc5e9ac0SBryan Drewery * Name: 409bc5e9ac0SBryan Drewery * URL: 410bc5e9ac0SBryan Drewery * MIRROR_TYPE: 411bc5e9ac0SBryan Drewery * etc... 412bc5e9ac0SBryan Drewery */ 413bc5e9ac0SBryan Drewery static void 41418418e19SKyle Evans parse_repo_file(ucl_object_t *obj, const char *requested_repo) 415bc5e9ac0SBryan Drewery { 4168a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 417b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 4188a7d859eSBaptiste Daroussin const char *key; 419bc5e9ac0SBryan Drewery 4208a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 4218a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 422bc5e9ac0SBryan Drewery 4238a7d859eSBaptiste Daroussin if (key == NULL) 424bc5e9ac0SBryan Drewery continue; 425bc5e9ac0SBryan Drewery 4268a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 427bc5e9ac0SBryan Drewery continue; 428bc5e9ac0SBryan Drewery 42918418e19SKyle Evans if (requested_repo != NULL && strcmp(requested_repo, key) != 0) 43018418e19SKyle Evans continue; 431dc458158SBaptiste Daroussin parse_repo(cur); 432bc5e9ac0SBryan Drewery } 433bc5e9ac0SBryan Drewery } 434bc5e9ac0SBryan Drewery 435bc5e9ac0SBryan Drewery 436bc5e9ac0SBryan Drewery static int 43718418e19SKyle Evans read_conf_file(const char *confpath, const char *requested_repo, 43818418e19SKyle Evans pkg_conf_file_t conftype) 4399950eceeSBaptiste Daroussin { 4408a7d859eSBaptiste Daroussin struct ucl_parser *p; 4418a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 442dc458158SBaptiste Daroussin const char *abi = pkg_get_myabi(); 443dc458158SBaptiste Daroussin if (abi == NULL) 444*49f4e3d2SBenedict Reuschling errx(EXIT_FAILURE, "Failed to determine ABI"); 445bc5e9ac0SBryan Drewery 4468a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 447dc458158SBaptiste Daroussin ucl_parser_register_variable(p, "ABI", abi); 4488a7d859eSBaptiste Daroussin 4498a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 450bc5e9ac0SBryan Drewery if (errno != ENOENT) 4518a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 4528a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 4538a7d859eSBaptiste Daroussin ucl_parser_free(p); 454bc5e9ac0SBryan Drewery /* no configuration present */ 455bc5e9ac0SBryan Drewery return (1); 456bc5e9ac0SBryan Drewery } 457bc5e9ac0SBryan Drewery 4588a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 4598a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 460bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 461bc5e9ac0SBryan Drewery "configuration file %s", confpath); 462bc5e9ac0SBryan Drewery else { 463bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 464dc458158SBaptiste Daroussin config_parse(obj); 465bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 46618418e19SKyle Evans parse_repo_file(obj, requested_repo); 467bc5e9ac0SBryan Drewery } 468bc5e9ac0SBryan Drewery 469b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 4708a7d859eSBaptiste Daroussin ucl_parser_free(p); 471bc5e9ac0SBryan Drewery 472bc5e9ac0SBryan Drewery return (0); 473bc5e9ac0SBryan Drewery } 474bc5e9ac0SBryan Drewery 475dc458158SBaptiste Daroussin static void 47618418e19SKyle Evans load_repositories(const char *repodir, const char *requested_repo) 477eb31a574SBryan Drewery { 478eb31a574SBryan Drewery struct dirent *ent; 479eb31a574SBryan Drewery DIR *d; 480eb31a574SBryan Drewery char *p; 481eb31a574SBryan Drewery size_t n; 482eb31a574SBryan Drewery char path[MAXPATHLEN]; 483eb31a574SBryan Drewery 484eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 485dc458158SBaptiste Daroussin return; 486eb31a574SBryan Drewery 487eb31a574SBryan Drewery while ((ent = readdir(d))) { 488eb31a574SBryan Drewery /* Trim out 'repos'. */ 489eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 490eb31a574SBryan Drewery continue; 491eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 492eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 493eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 494eb31a574SBryan Drewery repodir, 495eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 496eb31a574SBryan Drewery ent->d_name); 49718418e19SKyle Evans if (access(path, F_OK) != 0) 49818418e19SKyle Evans continue; 49918418e19SKyle Evans if (read_conf_file(path, requested_repo, 50018418e19SKyle Evans CONFFILE_REPO)) { 501eb31a574SBryan Drewery goto cleanup; 502eb31a574SBryan Drewery } 503eb31a574SBryan Drewery } 504eb31a574SBryan Drewery } 505eb31a574SBryan Drewery 506eb31a574SBryan Drewery cleanup: 507eb31a574SBryan Drewery closedir(d); 508eb31a574SBryan Drewery } 509eb31a574SBryan Drewery 510bc5e9ac0SBryan Drewery int 51118418e19SKyle Evans config_init(const char *requested_repo) 512bc5e9ac0SBryan Drewery { 513eb31a574SBryan Drewery char *val; 5149950eceeSBaptiste Daroussin int i; 5159950eceeSBaptiste Daroussin const char *localbase; 516fd9ae9acSJohn Baldwin char *abi, *env_list_item; 5179950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 518eb31a574SBryan Drewery struct config_value *cv; 5199950eceeSBaptiste Daroussin 5209950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5219950eceeSBaptiste Daroussin val = getenv(c[i].key); 5229950eceeSBaptiste Daroussin if (val != NULL) { 5239950eceeSBaptiste Daroussin c[i].envset = true; 524eb31a574SBryan Drewery switch (c[i].type) { 525eb31a574SBryan Drewery case PKG_CONFIG_LIST: 526eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 527eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 528eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 529eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 530eb31a574SBryan Drewery env_list_item != NULL; 531eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 532eb31a574SBryan Drewery cv = 533eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 534eb31a574SBryan Drewery cv->value = 535eb31a574SBryan Drewery strdup(env_list_item); 536eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 537eb31a574SBryan Drewery next); 538eb31a574SBryan Drewery } 539eb31a574SBryan Drewery break; 540eb31a574SBryan Drewery default: 541eb31a574SBryan Drewery c[i].val = val; 542eb31a574SBryan Drewery break; 543eb31a574SBryan Drewery } 5449950eceeSBaptiste Daroussin } 5459950eceeSBaptiste Daroussin } 5469950eceeSBaptiste Daroussin 547eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 54856d11d4aSStefan Eßer localbase = getlocalbase(); 54956d11d4aSStefan Eßer snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", localbase); 5509950eceeSBaptiste Daroussin 55118418e19SKyle Evans if (access(confpath, F_OK) == 0 && read_conf_file(confpath, NULL, 552bc5e9ac0SBryan Drewery CONFFILE_PKG)) 5539950eceeSBaptiste Daroussin goto finalize; 5549950eceeSBaptiste Daroussin 555eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 556eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 557eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 558eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 559eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 560eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 561eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 562eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 563eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 564eb31a574SBryan Drewery goto finalize; 565eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 566eb31a574SBryan Drewery } 567eb31a574SBryan Drewery 568eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 569dc458158SBaptiste Daroussin load_repositories(cv->value, requested_repo); 5709950eceeSBaptiste Daroussin 5719950eceeSBaptiste Daroussin finalize: 5729950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 573fd9ae9acSJohn Baldwin abi = pkg_get_myabi(); 574fd9ae9acSJohn Baldwin if (abi == NULL) 5754ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 5764ff9a7efSBryan Drewery "ABI"); 5779950eceeSBaptiste Daroussin c[ABI].val = abi; 5789950eceeSBaptiste Daroussin } 5799950eceeSBaptiste Daroussin 5809950eceeSBaptiste Daroussin return (0); 5819950eceeSBaptiste Daroussin } 5829950eceeSBaptiste Daroussin 5839950eceeSBaptiste Daroussin int 5849950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 5859950eceeSBaptiste Daroussin { 5869950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 5879950eceeSBaptiste Daroussin return (-1); 5889950eceeSBaptiste Daroussin 5899950eceeSBaptiste Daroussin if (c[k].value != NULL) 5909950eceeSBaptiste Daroussin *val = c[k].value; 5919950eceeSBaptiste Daroussin else 5929950eceeSBaptiste Daroussin *val = c[k].val; 5939950eceeSBaptiste Daroussin 5949950eceeSBaptiste Daroussin return (0); 5959950eceeSBaptiste Daroussin } 5969950eceeSBaptiste Daroussin 5979950eceeSBaptiste Daroussin int 5989950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 5999950eceeSBaptiste Daroussin { 6009950eceeSBaptiste Daroussin const char *value; 6019950eceeSBaptiste Daroussin 6029950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 6039950eceeSBaptiste Daroussin return (-1); 6049950eceeSBaptiste Daroussin 6059950eceeSBaptiste Daroussin *val = false; 6069950eceeSBaptiste Daroussin 6079950eceeSBaptiste Daroussin if (c[k].value != NULL) 6089950eceeSBaptiste Daroussin value = c[k].value; 6099950eceeSBaptiste Daroussin else 6109950eceeSBaptiste Daroussin value = c[k].val; 6119950eceeSBaptiste Daroussin 612eb31a574SBryan Drewery if (boolstr_to_bool(value)) 6139950eceeSBaptiste Daroussin *val = true; 6149950eceeSBaptiste Daroussin 6159950eceeSBaptiste Daroussin return (0); 6169950eceeSBaptiste Daroussin } 6179950eceeSBaptiste Daroussin 618dc458158SBaptiste Daroussin struct repositories * 619dc458158SBaptiste Daroussin config_get_repositories(void) 620dc458158SBaptiste Daroussin { 621dc458158SBaptiste Daroussin if (STAILQ_EMPTY(&repositories)) { 622dc458158SBaptiste Daroussin /* Fall back to PACKAGESITE - deprecated - */ 623dc458158SBaptiste Daroussin struct repository *r = calloc(1, sizeof(r)); 624dc458158SBaptiste Daroussin if (r == NULL) 625dc458158SBaptiste Daroussin err(EXIT_FAILURE, "calloc"); 626dc458158SBaptiste Daroussin r->name = strdup("fallback"); 627dc458158SBaptiste Daroussin if (r->name == NULL) 628dc458158SBaptiste Daroussin err(EXIT_FAILURE, "strdup"); 629dc458158SBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 630dc458158SBaptiste Daroussin r->url = c[PACKAGESITE].value; 631dc458158SBaptiste Daroussin if (c[SIGNATURE_TYPE].value != NULL) 632dc458158SBaptiste Daroussin if (!parse_signature_type(r, c[SIGNATURE_TYPE].value)) 633dc458158SBaptiste Daroussin exit(EXIT_FAILURE); 634dc458158SBaptiste Daroussin if (c[MIRROR_TYPE].value != NULL) 635dc458158SBaptiste Daroussin parse_mirror_type(r, c[MIRROR_TYPE].value); 636dc458158SBaptiste Daroussin if (c[PUBKEY].value != NULL) 637dc458158SBaptiste Daroussin r->pubkey = c[PUBKEY].value; 638dc458158SBaptiste Daroussin if (c[FINGERPRINTS].value != NULL) 639dc458158SBaptiste Daroussin r->fingerprints = c[FINGERPRINTS].value; 640dc458158SBaptiste Daroussin STAILQ_INSERT_TAIL(&repositories, r, next); 641dc458158SBaptiste Daroussin } 642dc458158SBaptiste Daroussin return (&repositories); 643dc458158SBaptiste Daroussin } 644dc458158SBaptiste Daroussin 6459950eceeSBaptiste Daroussin void 6469950eceeSBaptiste Daroussin config_finish(void) { 6479950eceeSBaptiste Daroussin int i; 6489950eceeSBaptiste Daroussin 6499950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 6509950eceeSBaptiste Daroussin free(c[i].value); 6519950eceeSBaptiste Daroussin } 652