config.c revision 257147
1247841Sbapt/*- 2247841Sbapt * Copyright (c) 2013 Baptiste Daroussin <bapt@FreeBSD.org> 3257147Sbdrewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 4247841Sbapt * All rights reserved. 5247841Sbapt * 6247841Sbapt * Redistribution and use in source and binary forms, with or without 7247841Sbapt * modification, are permitted provided that the following conditions 8247841Sbapt * are met: 9247841Sbapt * 1. Redistributions of source code must retain the above copyright 10247841Sbapt * notice, this list of conditions and the following disclaimer. 11247841Sbapt * 2. Redistributions in binary form must reproduce the above copyright 12247841Sbapt * notice, this list of conditions and the following disclaimer in the 13247841Sbapt * documentation and/or other materials provided with the distribution. 14247841Sbapt * 15247841Sbapt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16247841Sbapt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17247841Sbapt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18247841Sbapt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19247841Sbapt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20247841Sbapt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21247841Sbapt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22247841Sbapt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23247841Sbapt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24247841Sbapt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25247841Sbapt * SUCH DAMAGE. 26247841Sbapt */ 27247841Sbapt 28247841Sbapt#include <sys/cdefs.h> 29247841Sbapt__FBSDID("$FreeBSD: head/usr.sbin/pkg/config.c 257147 2013-10-26 03:43:02Z bdrewery $"); 30247841Sbapt 31247841Sbapt#include <sys/param.h> 32247841Sbapt#include <sys/sbuf.h> 33247841Sbapt#include <sys/elf_common.h> 34247841Sbapt#include <sys/endian.h> 35247841Sbapt 36255457Sbapt#include <assert.h> 37256450Sbdrewery#include <yaml.h> 38247841Sbapt#include <ctype.h> 39247841Sbapt#include <err.h> 40247841Sbapt#include <errno.h> 41247841Sbapt#include <fcntl.h> 42247841Sbapt#include <gelf.h> 43247841Sbapt#include <inttypes.h> 44247841Sbapt#include <paths.h> 45247841Sbapt#include <stdbool.h> 46247841Sbapt#include <string.h> 47247841Sbapt#include <unistd.h> 48247841Sbapt 49247841Sbapt#include "elf_tables.h" 50247841Sbapt#include "config.h" 51247841Sbapt 52247841Sbapt#define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 53247841Sbapt 54247841Sbaptstruct config_entry { 55247841Sbapt uint8_t type; 56247841Sbapt const char *key; 57247841Sbapt const char *val; 58247841Sbapt char *value; 59247841Sbapt bool envset; 60247841Sbapt}; 61247841Sbapt 62247841Sbaptstatic struct config_entry c[] = { 63247841Sbapt [PACKAGESITE] = { 64247841Sbapt PKG_CONFIG_STRING, 65247841Sbapt "PACKAGESITE", 66257051Sbdrewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 67247841Sbapt NULL, 68247841Sbapt false, 69247841Sbapt }, 70247841Sbapt [ABI] = { 71247841Sbapt PKG_CONFIG_STRING, 72247841Sbapt "ABI", 73247841Sbapt NULL, 74247841Sbapt NULL, 75247841Sbapt false, 76247841Sbapt }, 77247841Sbapt [MIRROR_TYPE] = { 78247841Sbapt PKG_CONFIG_STRING, 79247841Sbapt "MIRROR_TYPE", 80247841Sbapt "SRV", 81247841Sbapt NULL, 82247841Sbapt false, 83247841Sbapt }, 84247841Sbapt [ASSUME_ALWAYS_YES] = { 85247841Sbapt PKG_CONFIG_BOOL, 86247841Sbapt "ASSUME_ALWAYS_YES", 87247841Sbapt "NO", 88247841Sbapt NULL, 89247841Sbapt false, 90257147Sbdrewery }, 91257147Sbdrewery [SIGNATURE_TYPE] = { 92257147Sbdrewery PKG_CONFIG_STRING, 93257147Sbdrewery "SIGNATURE_TYPE", 94257147Sbdrewery NULL, 95257147Sbdrewery NULL, 96257147Sbdrewery false, 97257147Sbdrewery }, 98257147Sbdrewery [FINGERPRINTS] = { 99257147Sbdrewery PKG_CONFIG_STRING, 100257147Sbdrewery "FINGERPRINTS", 101257147Sbdrewery NULL, 102257147Sbdrewery NULL, 103257147Sbdrewery false, 104257147Sbdrewery }, 105247841Sbapt}; 106247841Sbapt 107247841Sbaptstatic const char * 108247841Sbaptelf_corres_to_string(struct _elf_corres *m, int e) 109247841Sbapt{ 110247841Sbapt int i; 111247841Sbapt 112247841Sbapt for (i = 0; m[i].string != NULL; i++) 113247841Sbapt if (m[i].elf_nb == e) 114247841Sbapt return (m[i].string); 115247841Sbapt 116247841Sbapt return ("unknown"); 117247841Sbapt} 118247841Sbapt 119255457Sbaptstatic const char * 120255457Sbaptaeabi_parse_arm_attributes(void *data, size_t length) 121255457Sbapt{ 122255457Sbapt uint32_t sect_len; 123255457Sbapt uint8_t *section = data; 124255457Sbapt 125255457Sbapt#define MOVE(len) do { \ 126255457Sbapt assert(length >= (len)); \ 127255457Sbapt section += (len); \ 128255457Sbapt length -= (len); \ 129255457Sbapt} while (0) 130255457Sbapt 131255457Sbapt if (length == 0 || *section != 'A') 132255457Sbapt return (NULL); 133255457Sbapt 134255457Sbapt MOVE(1); 135255457Sbapt 136255457Sbapt /* Read the section length */ 137255457Sbapt if (length < sizeof(sect_len)) 138255457Sbapt return (NULL); 139255457Sbapt 140255457Sbapt memcpy(§_len, section, sizeof(sect_len)); 141255457Sbapt 142255457Sbapt /* 143255457Sbapt * The section length should be no longer than the section it is within 144255457Sbapt */ 145255457Sbapt if (sect_len > length) 146255457Sbapt return (NULL); 147255457Sbapt 148255457Sbapt MOVE(sizeof(sect_len)); 149255457Sbapt 150255457Sbapt /* Skip the vendor name */ 151255457Sbapt while (length != 0) { 152255457Sbapt if (*section == '\0') 153255457Sbapt break; 154255457Sbapt MOVE(1); 155255457Sbapt } 156255457Sbapt if (length == 0) 157255457Sbapt return (NULL); 158255457Sbapt MOVE(1); 159255457Sbapt 160255457Sbapt while (length != 0) { 161255457Sbapt uint32_t tag_length; 162255457Sbapt 163255457Sbapt switch(*section) { 164255457Sbapt case 1: /* Tag_File */ 165255457Sbapt MOVE(1); 166255457Sbapt if (length < sizeof(tag_length)) 167255457Sbapt return (NULL); 168255457Sbapt memcpy(&tag_length, section, sizeof(tag_length)); 169255457Sbapt break; 170255457Sbapt case 2: /* Tag_Section */ 171255457Sbapt case 3: /* Tag_Symbol */ 172255457Sbapt default: 173255457Sbapt return (NULL); 174255457Sbapt } 175255457Sbapt /* At least space for the tag and size */ 176255457Sbapt if (tag_length <= 5) 177255457Sbapt return (NULL); 178255457Sbapt tag_length--; 179255457Sbapt /* Check the tag fits */ 180255457Sbapt if (tag_length > length) 181255457Sbapt return (NULL); 182255457Sbapt 183255457Sbapt#define MOVE_TAG(len) do { \ 184255457Sbapt assert(tag_length >= (len)); \ 185255457Sbapt MOVE(len); \ 186255457Sbapt tag_length -= (len); \ 187255457Sbapt} while(0) 188255457Sbapt 189255457Sbapt MOVE(sizeof(tag_length)); 190255457Sbapt tag_length -= sizeof(tag_length); 191255457Sbapt 192255457Sbapt while (tag_length != 0) { 193255457Sbapt uint8_t tag; 194255457Sbapt 195255457Sbapt assert(tag_length >= length); 196255457Sbapt 197255457Sbapt tag = *section; 198255457Sbapt MOVE_TAG(1); 199255457Sbapt 200255457Sbapt /* 201255457Sbapt * These tag values come from: 202255457Sbapt * 203255457Sbapt * Addenda to, and Errata in, the ABI for the 204255457Sbapt * ARM Architecture. Release 2.08, section 2.3. 205255457Sbapt */ 206255457Sbapt if (tag == 6) { /* == Tag_CPU_arch */ 207255457Sbapt uint8_t val; 208255457Sbapt 209255457Sbapt val = *section; 210255457Sbapt /* 211255457Sbapt * We don't support values that require 212255457Sbapt * more than one byte. 213255457Sbapt */ 214255457Sbapt if (val & (1 << 7)) 215255457Sbapt return (NULL); 216255457Sbapt 217255457Sbapt /* We have an ARMv4 or ARMv5 */ 218255457Sbapt if (val <= 5) 219255457Sbapt return ("arm"); 220255457Sbapt else /* We have an ARMv6+ */ 221255457Sbapt return ("armv6"); 222255457Sbapt } else if (tag == 4 || tag == 5 || tag == 32 || 223255457Sbapt tag == 65 || tag == 67) { 224255457Sbapt while (*section != '\0' && length != 0) 225255457Sbapt MOVE_TAG(1); 226255457Sbapt if (tag_length == 0) 227255457Sbapt return (NULL); 228255457Sbapt /* Skip the last byte */ 229255457Sbapt MOVE_TAG(1); 230255457Sbapt } else if ((tag >= 7 && tag <= 31) || tag == 34 || 231255457Sbapt tag == 36 || tag == 38 || tag == 42 || tag == 44 || 232255457Sbapt tag == 64 || tag == 66 || tag == 68 || tag == 70) { 233255457Sbapt /* Skip the uleb128 data */ 234255457Sbapt while (*section & (1 << 7) && length != 0) 235255457Sbapt MOVE_TAG(1); 236255457Sbapt if (tag_length == 0) 237255457Sbapt return (NULL); 238255457Sbapt /* Skip the last byte */ 239255457Sbapt MOVE_TAG(1); 240255457Sbapt } else 241255457Sbapt return (NULL); 242255457Sbapt#undef MOVE_TAG 243255457Sbapt } 244255457Sbapt 245255457Sbapt break; 246255457Sbapt } 247255457Sbapt return (NULL); 248255457Sbapt#undef MOVE 249255457Sbapt} 250255457Sbapt 251247841Sbaptstatic int 252247841Sbaptpkg_get_myabi(char *dest, size_t sz) 253247841Sbapt{ 254247841Sbapt Elf *elf; 255247841Sbapt Elf_Data *data; 256247841Sbapt Elf_Note note; 257247841Sbapt Elf_Scn *scn; 258247841Sbapt char *src, *osname; 259255457Sbapt const char *arch, *abi, *fpu, *endian_corres_str; 260255457Sbapt const char *wordsize_corres_str; 261247841Sbapt GElf_Ehdr elfhdr; 262247841Sbapt GElf_Shdr shdr; 263247841Sbapt int fd, i, ret; 264247841Sbapt uint32_t version; 265247841Sbapt 266247841Sbapt version = 0; 267247841Sbapt ret = -1; 268247841Sbapt scn = NULL; 269247841Sbapt abi = NULL; 270247841Sbapt 271247841Sbapt if (elf_version(EV_CURRENT) == EV_NONE) { 272247841Sbapt warnx("ELF library initialization failed: %s", 273247841Sbapt elf_errmsg(-1)); 274247841Sbapt return (-1); 275247841Sbapt } 276247841Sbapt 277247841Sbapt if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) { 278247841Sbapt warn("open()"); 279247841Sbapt return (-1); 280247841Sbapt } 281247841Sbapt 282247841Sbapt if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 283247841Sbapt ret = -1; 284247841Sbapt warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 285247841Sbapt goto cleanup; 286247841Sbapt } 287247841Sbapt 288247841Sbapt if (gelf_getehdr(elf, &elfhdr) == NULL) { 289247841Sbapt ret = -1; 290247841Sbapt warn("getehdr() failed: %s.", elf_errmsg(-1)); 291247841Sbapt goto cleanup; 292247841Sbapt } 293247841Sbapt while ((scn = elf_nextscn(elf, scn)) != NULL) { 294247841Sbapt if (gelf_getshdr(scn, &shdr) != &shdr) { 295247841Sbapt ret = -1; 296247841Sbapt warn("getshdr() failed: %s.", elf_errmsg(-1)); 297247841Sbapt goto cleanup; 298247841Sbapt } 299247841Sbapt 300247841Sbapt if (shdr.sh_type == SHT_NOTE) 301247841Sbapt break; 302247841Sbapt } 303247841Sbapt 304247841Sbapt if (scn == NULL) { 305247841Sbapt ret = -1; 306247841Sbapt warn("failed to get the note section"); 307247841Sbapt goto cleanup; 308247841Sbapt } 309247841Sbapt 310247841Sbapt data = elf_getdata(scn, NULL); 311247841Sbapt src = data->d_buf; 312247841Sbapt for (;;) { 313247841Sbapt memcpy(¬e, src, sizeof(Elf_Note)); 314247841Sbapt src += sizeof(Elf_Note); 315247841Sbapt if (note.n_type == NT_VERSION) 316247841Sbapt break; 317247841Sbapt src += note.n_namesz + note.n_descsz; 318247841Sbapt } 319247841Sbapt osname = src; 320247841Sbapt src += roundup2(note.n_namesz, 4); 321247841Sbapt if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 322247841Sbapt version = be32dec(src); 323247841Sbapt else 324247841Sbapt version = le32dec(src); 325247841Sbapt 326247841Sbapt for (i = 0; osname[i] != '\0'; i++) 327247841Sbapt osname[i] = (char)tolower(osname[i]); 328247841Sbapt 329255457Sbapt wordsize_corres_str = elf_corres_to_string(wordsize_corres, 330255457Sbapt (int)elfhdr.e_ident[EI_CLASS]); 331247841Sbapt 332255457Sbapt arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine); 333255457Sbapt 334255457Sbapt snprintf(dest, sz, "%s:%d", 335255457Sbapt osname, version / 100000); 336255457Sbapt 337247841Sbapt ret = 0; 338247841Sbapt 339247841Sbapt switch (elfhdr.e_machine) { 340247841Sbapt case EM_ARM: 341255457Sbapt endian_corres_str = elf_corres_to_string(endian_corres, 342255457Sbapt (int)elfhdr.e_ident[EI_DATA]); 343255457Sbapt 344253755Sbapt /* FreeBSD doesn't support the hard-float ABI yet */ 345253755Sbapt fpu = "softfp"; 346253755Sbapt if ((elfhdr.e_flags & 0xFF000000) != 0) { 347255457Sbapt const char *sh_name = NULL; 348255457Sbapt size_t shstrndx; 349255457Sbapt 350253755Sbapt /* This is an EABI file, the conformance level is set */ 351253755Sbapt abi = "eabi"; 352255457Sbapt /* Find which TARGET_ARCH we are building for. */ 353255457Sbapt elf_getshdrstrndx(elf, &shstrndx); 354255457Sbapt while ((scn = elf_nextscn(elf, scn)) != NULL) { 355255457Sbapt sh_name = NULL; 356255457Sbapt if (gelf_getshdr(scn, &shdr) != &shdr) { 357255457Sbapt scn = NULL; 358255457Sbapt break; 359255457Sbapt } 360255457Sbapt 361255457Sbapt sh_name = elf_strptr(elf, shstrndx, 362255457Sbapt shdr.sh_name); 363255457Sbapt if (sh_name == NULL) 364255457Sbapt continue; 365255457Sbapt if (strcmp(".ARM.attributes", sh_name) == 0) 366255457Sbapt break; 367255457Sbapt } 368255457Sbapt if (scn != NULL && sh_name != NULL) { 369255457Sbapt data = elf_getdata(scn, NULL); 370255457Sbapt /* 371255457Sbapt * Prior to FreeBSD 10.0 libelf would return 372255457Sbapt * NULL from elf_getdata on the .ARM.attributes 373255457Sbapt * section. As this was the first release to 374255457Sbapt * get armv6 support assume a NULL value means 375255457Sbapt * arm. 376255457Sbapt * 377255457Sbapt * This assumption can be removed when 9.x 378255457Sbapt * is unsupported. 379255457Sbapt */ 380255457Sbapt if (data != NULL) { 381255457Sbapt arch = aeabi_parse_arm_attributes( 382255457Sbapt data->d_buf, data->d_size); 383255457Sbapt if (arch == NULL) { 384255457Sbapt ret = 1; 385255457Sbapt warn("unknown ARM ARCH"); 386255457Sbapt goto cleanup; 387255457Sbapt } 388255457Sbapt } 389255457Sbapt } else { 390255457Sbapt ret = 1; 391255457Sbapt warn("Unable to find the .ARM.attributes " 392255457Sbapt "section"); 393255457Sbapt goto cleanup; 394255457Sbapt } 395253755Sbapt } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) { 396253755Sbapt /* 397253755Sbapt * EABI executables all have this field set to 398253755Sbapt * ELFOSABI_NONE, therefore it must be an oabi file. 399253755Sbapt */ 400253755Sbapt abi = "oabi"; 401253755Sbapt } else { 402253755Sbapt ret = 1; 403255457Sbapt warn("unknown ARM ABI"); 404253755Sbapt goto cleanup; 405253755Sbapt } 406247841Sbapt snprintf(dest + strlen(dest), sz - strlen(dest), 407255457Sbapt ":%s:%s:%s:%s:%s", arch, wordsize_corres_str, 408255457Sbapt endian_corres_str, abi, fpu); 409247841Sbapt break; 410247841Sbapt case EM_MIPS: 411247841Sbapt /* 412247841Sbapt * this is taken from binutils sources: 413247841Sbapt * include/elf/mips.h 414247841Sbapt * mapping is figured out from binutils: 415247841Sbapt * gas/config/tc-mips.c 416247841Sbapt */ 417247841Sbapt switch (elfhdr.e_flags & EF_MIPS_ABI) { 418247841Sbapt case E_MIPS_ABI_O32: 419247841Sbapt abi = "o32"; 420247841Sbapt break; 421247841Sbapt case E_MIPS_ABI_N32: 422247841Sbapt abi = "n32"; 423247841Sbapt break; 424247841Sbapt default: 425247841Sbapt if (elfhdr.e_ident[EI_DATA] == 426247841Sbapt ELFCLASS32) 427247841Sbapt abi = "o32"; 428247841Sbapt else if (elfhdr.e_ident[EI_DATA] == 429247841Sbapt ELFCLASS64) 430247841Sbapt abi = "n64"; 431247841Sbapt break; 432247841Sbapt } 433255457Sbapt endian_corres_str = elf_corres_to_string(endian_corres, 434255457Sbapt (int)elfhdr.e_ident[EI_DATA]); 435255457Sbapt 436255457Sbapt snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s", 437255457Sbapt arch, wordsize_corres_str, endian_corres_str, abi); 438247841Sbapt break; 439255457Sbapt default: 440255457Sbapt snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s", 441255457Sbapt arch, wordsize_corres_str); 442247841Sbapt } 443247841Sbapt 444247841Sbaptcleanup: 445247841Sbapt if (elf != NULL) 446247841Sbapt elf_end(elf); 447247841Sbapt 448247841Sbapt close(fd); 449247841Sbapt return (ret); 450247841Sbapt} 451247841Sbapt 452247841Sbaptstatic void 453247841Sbaptsubst_packagesite(const char *abi) 454247841Sbapt{ 455247841Sbapt struct sbuf *newval; 456247841Sbapt const char *variable_string; 457247841Sbapt const char *oldval; 458247841Sbapt 459247841Sbapt if (c[PACKAGESITE].value != NULL) 460247841Sbapt oldval = c[PACKAGESITE].value; 461247841Sbapt else 462247841Sbapt oldval = c[PACKAGESITE].val; 463247841Sbapt 464247841Sbapt if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 465247841Sbapt return; 466247841Sbapt 467247841Sbapt newval = sbuf_new_auto(); 468247841Sbapt sbuf_bcat(newval, oldval, variable_string - oldval); 469247841Sbapt sbuf_cat(newval, abi); 470247841Sbapt sbuf_cat(newval, variable_string + strlen("${ABI}")); 471247841Sbapt sbuf_finish(newval); 472247841Sbapt 473247841Sbapt free(c[PACKAGESITE].value); 474247841Sbapt c[PACKAGESITE].value = strdup(sbuf_data(newval)); 475247841Sbapt} 476247841Sbapt 477247841Sbaptstatic void 478257145Sbdreweryconfig_parse(yaml_document_t *doc, yaml_node_t *node, pkg_conf_file_t conftype) 479247841Sbapt{ 480247841Sbapt yaml_node_pair_t *pair; 481247841Sbapt yaml_node_t *key, *val; 482247841Sbapt struct sbuf *buf = sbuf_new_auto(); 483247841Sbapt int i; 484247841Sbapt size_t j; 485247841Sbapt 486247841Sbapt pair = node->data.mapping.pairs.start; 487247841Sbapt 488247841Sbapt while (pair < node->data.mapping.pairs.top) { 489247841Sbapt key = yaml_document_get_node(doc, pair->key); 490247841Sbapt val = yaml_document_get_node(doc, pair->value); 491247841Sbapt 492247841Sbapt /* 493247841Sbapt * ignoring silently empty keys can be empty lines 494247841Sbapt * or user mistakes 495247841Sbapt */ 496247841Sbapt if (key->data.scalar.length <= 0) { 497247841Sbapt ++pair; 498247841Sbapt continue; 499247841Sbapt } 500247841Sbapt 501247841Sbapt /* 502247841Sbapt * silently skip on purpose to allow user to leave 503247841Sbapt * empty lines without complaining 504247841Sbapt */ 505247841Sbapt if (val->type == YAML_NO_NODE || 506247841Sbapt (val->type == YAML_SCALAR_NODE && 507247841Sbapt val->data.scalar.length <= 0)) { 508247841Sbapt ++pair; 509247841Sbapt continue; 510247841Sbapt } 511247841Sbapt 512247841Sbapt sbuf_clear(buf); 513247841Sbapt 514257145Sbdrewery if (conftype == CONFFILE_PKG) { 515257145Sbdrewery for (j = 0; j < strlen(key->data.scalar.value); ++j) 516257145Sbdrewery sbuf_putc(buf, 517257145Sbdrewery toupper(key->data.scalar.value[j])); 518257145Sbdrewery sbuf_finish(buf); 519257145Sbdrewery } else if (conftype == CONFFILE_REPO) { 520257145Sbdrewery /* The CONFFILE_REPO type is more restrictive. Only 521257145Sbdrewery parse known elements. */ 522257145Sbdrewery if (strcasecmp(key->data.scalar.value, "url") == 0) 523257145Sbdrewery sbuf_cpy(buf, "PACKAGESITE"); 524257145Sbdrewery else if (strcasecmp(key->data.scalar.value, 525257145Sbdrewery "mirror_type") == 0) 526257145Sbdrewery sbuf_cpy(buf, "MIRROR_TYPE"); 527257147Sbdrewery else if (strcasecmp(key->data.scalar.value, 528257147Sbdrewery "signature_type") == 0) 529257147Sbdrewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 530257147Sbdrewery else if (strcasecmp(key->data.scalar.value, 531257147Sbdrewery "fingerprints") == 0) 532257147Sbdrewery sbuf_cpy(buf, "FINGERPRINTS"); 533257145Sbdrewery else { /* Skip unknown entries for future use. */ 534257145Sbdrewery ++pair; 535257145Sbdrewery continue; 536257145Sbdrewery } 537257145Sbdrewery sbuf_finish(buf); 538257145Sbdrewery } 539257145Sbdrewery 540247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) { 541247841Sbapt if (strcmp(sbuf_data(buf), c[i].key) == 0) 542247841Sbapt break; 543247841Sbapt } 544247841Sbapt 545257145Sbdrewery /* Silently skip unknown keys to be future compatible. */ 546247841Sbapt if (i == CONFIG_SIZE) { 547247841Sbapt ++pair; 548247841Sbapt continue; 549247841Sbapt } 550247841Sbapt 551247841Sbapt /* env has priority over config file */ 552247841Sbapt if (c[i].envset) { 553247841Sbapt ++pair; 554247841Sbapt continue; 555247841Sbapt } 556247841Sbapt 557247841Sbapt c[i].value = strdup(val->data.scalar.value); 558247841Sbapt ++pair; 559247841Sbapt } 560247841Sbapt 561247841Sbapt sbuf_delete(buf); 562247841Sbapt} 563247841Sbapt 564257145Sbdrewery/*- 565257145Sbdrewery * Parse new repo style configs in style: 566257145Sbdrewery * Name: 567257145Sbdrewery * URL: 568257145Sbdrewery * MIRROR_TYPE: 569257145Sbdrewery * etc... 570257145Sbdrewery */ 571257145Sbdrewerystatic void 572257145Sbdreweryparse_repo_file(yaml_document_t *doc, yaml_node_t *node) 573247841Sbapt{ 574257145Sbdrewery yaml_node_pair_t *pair; 575257145Sbdrewery 576257145Sbdrewery pair = node->data.mapping.pairs.start; 577257145Sbdrewery while (pair < node->data.mapping.pairs.top) { 578257145Sbdrewery yaml_node_t *key = yaml_document_get_node(doc, pair->key); 579257145Sbdrewery yaml_node_t *val = yaml_document_get_node(doc, pair->value); 580257145Sbdrewery 581257145Sbdrewery if (key->data.scalar.length <= 0) { 582257145Sbdrewery ++pair; 583257145Sbdrewery continue; 584257145Sbdrewery } 585257145Sbdrewery 586257145Sbdrewery if (val->type != YAML_MAPPING_NODE) { 587257145Sbdrewery ++pair; 588257145Sbdrewery continue; 589257145Sbdrewery } 590257145Sbdrewery 591257145Sbdrewery config_parse(doc, val, CONFFILE_REPO); 592257145Sbdrewery ++pair; 593257145Sbdrewery } 594257145Sbdrewery} 595257145Sbdrewery 596257145Sbdrewery 597257145Sbdrewerystatic int 598257145Sbdreweryread_conf_file(const char *confpath, pkg_conf_file_t conftype) 599257145Sbdrewery{ 600247841Sbapt FILE *fp; 601247841Sbapt yaml_parser_t parser; 602247841Sbapt yaml_document_t doc; 603247841Sbapt yaml_node_t *node; 604247841Sbapt 605247841Sbapt if ((fp = fopen(confpath, "r")) == NULL) { 606247841Sbapt if (errno != ENOENT) 607257142Sbdrewery err(EXIT_FAILURE, "Unable to open configuration " 608257142Sbdrewery "file %s", confpath); 609247841Sbapt /* no configuration present */ 610257145Sbdrewery return (1); 611247841Sbapt } 612247841Sbapt 613247841Sbapt yaml_parser_initialize(&parser); 614247841Sbapt yaml_parser_set_input_file(&parser, fp); 615247841Sbapt yaml_parser_load(&parser, &doc); 616247841Sbapt 617247841Sbapt node = yaml_document_get_root_node(&doc); 618247841Sbapt 619257145Sbdrewery if (node == NULL || node->type != YAML_MAPPING_NODE) 620257142Sbdrewery warnx("Invalid configuration format, ignoring the " 621257145Sbdrewery "configuration file %s", confpath); 622257145Sbdrewery else { 623257145Sbdrewery if (conftype == CONFFILE_PKG) 624257145Sbdrewery config_parse(&doc, node, conftype); 625257145Sbdrewery else if (conftype == CONFFILE_REPO) 626257145Sbdrewery parse_repo_file(&doc, node); 627247841Sbapt } 628247841Sbapt 629247841Sbapt yaml_document_delete(&doc); 630247841Sbapt yaml_parser_delete(&parser); 631247841Sbapt 632257145Sbdrewery return (0); 633257145Sbdrewery} 634257145Sbdrewery 635257145Sbdreweryint 636257145Sbdreweryconfig_init(void) 637257145Sbdrewery{ 638257145Sbdrewery const char *val; 639257145Sbdrewery int i; 640257145Sbdrewery const char *localbase; 641257145Sbdrewery char confpath[MAXPATHLEN]; 642257145Sbdrewery char abi[BUFSIZ]; 643257145Sbdrewery 644257145Sbdrewery for (i = 0; i < CONFIG_SIZE; i++) { 645257145Sbdrewery val = getenv(c[i].key); 646257145Sbdrewery if (val != NULL) { 647257145Sbdrewery c[i].val = val; 648257145Sbdrewery c[i].envset = true; 649257145Sbdrewery } 650257145Sbdrewery } 651257145Sbdrewery 652257145Sbdrewery localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 653257145Sbdrewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 654257145Sbdrewery localbase); 655257145Sbdrewery 656257145Sbdrewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 657257145Sbdrewery CONFFILE_PKG)) 658257145Sbdrewery goto finalize; 659257145Sbdrewery 660257145Sbdrewery snprintf(confpath, sizeof(confpath), "/etc/pkg/FreeBSD.conf"); 661257145Sbdrewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 662257145Sbdrewery CONFFILE_REPO)) 663257145Sbdrewery goto finalize; 664257145Sbdrewery 665247841Sbaptfinalize: 666247841Sbapt if (c[ABI].val == NULL && c[ABI].value == NULL) { 667247841Sbapt if (pkg_get_myabi(abi, BUFSIZ) != 0) 668257142Sbdrewery errx(EXIT_FAILURE, "Failed to determine the system " 669257142Sbdrewery "ABI"); 670247841Sbapt c[ABI].val = abi; 671247841Sbapt } 672247841Sbapt 673247843Sbapt subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 674247841Sbapt 675247841Sbapt return (0); 676247841Sbapt} 677247841Sbapt 678247841Sbaptint 679247841Sbaptconfig_string(pkg_config_key k, const char **val) 680247841Sbapt{ 681247841Sbapt if (c[k].type != PKG_CONFIG_STRING) 682247841Sbapt return (-1); 683247841Sbapt 684247841Sbapt if (c[k].value != NULL) 685247841Sbapt *val = c[k].value; 686247841Sbapt else 687247841Sbapt *val = c[k].val; 688247841Sbapt 689247841Sbapt return (0); 690247841Sbapt} 691247841Sbapt 692247841Sbaptint 693247841Sbaptconfig_bool(pkg_config_key k, bool *val) 694247841Sbapt{ 695247841Sbapt const char *value; 696247841Sbapt 697247841Sbapt if (c[k].type != PKG_CONFIG_BOOL) 698247841Sbapt return (-1); 699247841Sbapt 700247841Sbapt *val = false; 701247841Sbapt 702247841Sbapt if (c[k].value != NULL) 703247841Sbapt value = c[k].value; 704247841Sbapt else 705247841Sbapt value = c[k].val; 706247841Sbapt 707247841Sbapt if (strcasecmp(value, "true") == 0 || 708247841Sbapt strcasecmp(value, "yes") == 0 || 709247841Sbapt strcasecmp(value, "on") == 0 || 710247841Sbapt *value == '1') 711247841Sbapt *val = true; 712247841Sbapt 713247841Sbapt return (0); 714247841Sbapt} 715247841Sbapt 716247841Sbaptvoid 717247841Sbaptconfig_finish(void) { 718247841Sbapt int i; 719247841Sbapt 720247841Sbapt for (i = 0; i < CONFIG_SIZE; i++) 721247841Sbapt free(c[i].value); 722247841Sbapt} 723