19950eceeSBaptiste Daroussin /*- 20ad5dbacSBaptiste Daroussin * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org> 3f12db248SBryan Drewery * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org> 49950eceeSBaptiste Daroussin * All rights reserved. 59950eceeSBaptiste Daroussin * 69950eceeSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 79950eceeSBaptiste Daroussin * modification, are permitted provided that the following conditions 89950eceeSBaptiste Daroussin * are met: 99950eceeSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 109950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 119950eceeSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 129950eceeSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 139950eceeSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 149950eceeSBaptiste Daroussin * 159950eceeSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 169950eceeSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 179950eceeSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 189950eceeSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 199950eceeSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 209950eceeSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 219950eceeSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 229950eceeSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 239950eceeSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 249950eceeSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 259950eceeSBaptiste Daroussin * SUCH DAMAGE. 269950eceeSBaptiste Daroussin */ 279950eceeSBaptiste Daroussin 289950eceeSBaptiste Daroussin #include <sys/cdefs.h> 299950eceeSBaptiste Daroussin __FBSDID("$FreeBSD$"); 309950eceeSBaptiste Daroussin 319950eceeSBaptiste Daroussin #include <sys/param.h> 32a351c93dSBaptiste Daroussin #include <sys/queue.h> 339950eceeSBaptiste Daroussin #include <sys/sbuf.h> 349950eceeSBaptiste Daroussin #include <sys/elf_common.h> 359950eceeSBaptiste Daroussin #include <sys/endian.h> 36eb31a574SBryan Drewery #include <sys/types.h> 379950eceeSBaptiste Daroussin 3840274a2dSBaptiste Daroussin #include <assert.h> 39eb31a574SBryan Drewery #include <dirent.h> 408a7d859eSBaptiste Daroussin #include <ucl.h> 419950eceeSBaptiste Daroussin #include <ctype.h> 429950eceeSBaptiste Daroussin #include <err.h> 439950eceeSBaptiste Daroussin #include <errno.h> 449950eceeSBaptiste Daroussin #include <fcntl.h> 459950eceeSBaptiste Daroussin #include <gelf.h> 469950eceeSBaptiste Daroussin #include <inttypes.h> 479950eceeSBaptiste Daroussin #include <paths.h> 489950eceeSBaptiste Daroussin #include <stdbool.h> 499950eceeSBaptiste Daroussin #include <string.h> 509950eceeSBaptiste Daroussin #include <unistd.h> 519950eceeSBaptiste Daroussin 529950eceeSBaptiste Daroussin #include "elf_tables.h" 539950eceeSBaptiste Daroussin #include "config.h" 549950eceeSBaptiste Daroussin 559950eceeSBaptiste Daroussin #define roundup2(x, y) (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */ 569950eceeSBaptiste Daroussin 57eb31a574SBryan Drewery struct config_value { 58eb31a574SBryan Drewery char *value; 59eb31a574SBryan Drewery STAILQ_ENTRY(config_value) next; 60eb31a574SBryan Drewery }; 61eb31a574SBryan Drewery 629950eceeSBaptiste Daroussin struct config_entry { 639950eceeSBaptiste Daroussin uint8_t type; 649950eceeSBaptiste Daroussin const char *key; 659950eceeSBaptiste Daroussin const char *val; 669950eceeSBaptiste Daroussin char *value; 67eb31a574SBryan Drewery STAILQ_HEAD(, config_value) *list; 689950eceeSBaptiste Daroussin bool envset; 6997c3a766SBryan Drewery bool main_only; /* Only set in pkg.conf. */ 709950eceeSBaptiste Daroussin }; 719950eceeSBaptiste Daroussin 729950eceeSBaptiste Daroussin static struct config_entry c[] = { 739950eceeSBaptiste Daroussin [PACKAGESITE] = { 749950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 759950eceeSBaptiste Daroussin "PACKAGESITE", 7662940ea9SBryan Drewery URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest", 779950eceeSBaptiste Daroussin NULL, 78eb31a574SBryan Drewery NULL, 799950eceeSBaptiste Daroussin false, 8097c3a766SBryan Drewery false, 819950eceeSBaptiste Daroussin }, 829950eceeSBaptiste Daroussin [ABI] = { 839950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 849950eceeSBaptiste Daroussin "ABI", 859950eceeSBaptiste Daroussin NULL, 869950eceeSBaptiste Daroussin NULL, 87eb31a574SBryan Drewery NULL, 889950eceeSBaptiste Daroussin false, 8997c3a766SBryan Drewery true, 909950eceeSBaptiste Daroussin }, 919950eceeSBaptiste Daroussin [MIRROR_TYPE] = { 929950eceeSBaptiste Daroussin PKG_CONFIG_STRING, 939950eceeSBaptiste Daroussin "MIRROR_TYPE", 949950eceeSBaptiste Daroussin "SRV", 959950eceeSBaptiste Daroussin NULL, 96eb31a574SBryan Drewery NULL, 979950eceeSBaptiste Daroussin false, 9897c3a766SBryan Drewery false, 999950eceeSBaptiste Daroussin }, 1009950eceeSBaptiste Daroussin [ASSUME_ALWAYS_YES] = { 1019950eceeSBaptiste Daroussin PKG_CONFIG_BOOL, 1029950eceeSBaptiste Daroussin "ASSUME_ALWAYS_YES", 1039950eceeSBaptiste Daroussin "NO", 1049950eceeSBaptiste Daroussin NULL, 105eb31a574SBryan Drewery NULL, 1069950eceeSBaptiste Daroussin false, 10797c3a766SBryan Drewery true, 108f12db248SBryan Drewery }, 109f12db248SBryan Drewery [SIGNATURE_TYPE] = { 110f12db248SBryan Drewery PKG_CONFIG_STRING, 111f12db248SBryan Drewery "SIGNATURE_TYPE", 112f12db248SBryan Drewery NULL, 113f12db248SBryan Drewery NULL, 114eb31a574SBryan Drewery NULL, 115f12db248SBryan Drewery false, 11697c3a766SBryan Drewery false, 117f12db248SBryan Drewery }, 118f12db248SBryan Drewery [FINGERPRINTS] = { 119f12db248SBryan Drewery PKG_CONFIG_STRING, 120f12db248SBryan Drewery "FINGERPRINTS", 121f12db248SBryan Drewery NULL, 122f12db248SBryan Drewery NULL, 123eb31a574SBryan Drewery NULL, 124eb31a574SBryan Drewery false, 12597c3a766SBryan Drewery false, 126eb31a574SBryan Drewery }, 127eb31a574SBryan Drewery [REPOS_DIR] = { 128eb31a574SBryan Drewery PKG_CONFIG_LIST, 129eb31a574SBryan Drewery "REPOS_DIR", 130eb31a574SBryan Drewery NULL, 131eb31a574SBryan Drewery NULL, 132eb31a574SBryan Drewery NULL, 133f12db248SBryan Drewery false, 13497c3a766SBryan Drewery true, 135f12db248SBryan Drewery }, 1369950eceeSBaptiste Daroussin }; 1379950eceeSBaptiste Daroussin 1389950eceeSBaptiste Daroussin static const char * 1399950eceeSBaptiste Daroussin elf_corres_to_string(struct _elf_corres *m, int e) 1409950eceeSBaptiste Daroussin { 1419950eceeSBaptiste Daroussin int i; 1429950eceeSBaptiste Daroussin 1439950eceeSBaptiste Daroussin for (i = 0; m[i].string != NULL; i++) 1449950eceeSBaptiste Daroussin if (m[i].elf_nb == e) 1459950eceeSBaptiste Daroussin return (m[i].string); 1469950eceeSBaptiste Daroussin 1479950eceeSBaptiste Daroussin return ("unknown"); 1489950eceeSBaptiste Daroussin } 1499950eceeSBaptiste Daroussin 15040274a2dSBaptiste Daroussin static const char * 15140274a2dSBaptiste Daroussin aeabi_parse_arm_attributes(void *data, size_t length) 15240274a2dSBaptiste Daroussin { 15340274a2dSBaptiste Daroussin uint32_t sect_len; 15440274a2dSBaptiste Daroussin uint8_t *section = data; 15540274a2dSBaptiste Daroussin 15640274a2dSBaptiste Daroussin #define MOVE(len) do { \ 15740274a2dSBaptiste Daroussin assert(length >= (len)); \ 15840274a2dSBaptiste Daroussin section += (len); \ 15940274a2dSBaptiste Daroussin length -= (len); \ 16040274a2dSBaptiste Daroussin } while (0) 16140274a2dSBaptiste Daroussin 16240274a2dSBaptiste Daroussin if (length == 0 || *section != 'A') 16340274a2dSBaptiste Daroussin return (NULL); 16440274a2dSBaptiste Daroussin 16540274a2dSBaptiste Daroussin MOVE(1); 16640274a2dSBaptiste Daroussin 16740274a2dSBaptiste Daroussin /* Read the section length */ 16840274a2dSBaptiste Daroussin if (length < sizeof(sect_len)) 16940274a2dSBaptiste Daroussin return (NULL); 17040274a2dSBaptiste Daroussin 17140274a2dSBaptiste Daroussin memcpy(§_len, section, sizeof(sect_len)); 17240274a2dSBaptiste Daroussin 17340274a2dSBaptiste Daroussin /* 17440274a2dSBaptiste Daroussin * The section length should be no longer than the section it is within 17540274a2dSBaptiste Daroussin */ 17640274a2dSBaptiste Daroussin if (sect_len > length) 17740274a2dSBaptiste Daroussin return (NULL); 17840274a2dSBaptiste Daroussin 17940274a2dSBaptiste Daroussin MOVE(sizeof(sect_len)); 18040274a2dSBaptiste Daroussin 18140274a2dSBaptiste Daroussin /* Skip the vendor name */ 18240274a2dSBaptiste Daroussin while (length != 0) { 18340274a2dSBaptiste Daroussin if (*section == '\0') 18440274a2dSBaptiste Daroussin break; 18540274a2dSBaptiste Daroussin MOVE(1); 18640274a2dSBaptiste Daroussin } 18740274a2dSBaptiste Daroussin if (length == 0) 18840274a2dSBaptiste Daroussin return (NULL); 18940274a2dSBaptiste Daroussin MOVE(1); 19040274a2dSBaptiste Daroussin 19140274a2dSBaptiste Daroussin while (length != 0) { 19240274a2dSBaptiste Daroussin uint32_t tag_length; 19340274a2dSBaptiste Daroussin 19440274a2dSBaptiste Daroussin switch(*section) { 19540274a2dSBaptiste Daroussin case 1: /* Tag_File */ 19640274a2dSBaptiste Daroussin MOVE(1); 19740274a2dSBaptiste Daroussin if (length < sizeof(tag_length)) 19840274a2dSBaptiste Daroussin return (NULL); 19940274a2dSBaptiste Daroussin memcpy(&tag_length, section, sizeof(tag_length)); 20040274a2dSBaptiste Daroussin break; 20140274a2dSBaptiste Daroussin case 2: /* Tag_Section */ 20240274a2dSBaptiste Daroussin case 3: /* Tag_Symbol */ 20340274a2dSBaptiste Daroussin default: 20440274a2dSBaptiste Daroussin return (NULL); 20540274a2dSBaptiste Daroussin } 20640274a2dSBaptiste Daroussin /* At least space for the tag and size */ 20740274a2dSBaptiste Daroussin if (tag_length <= 5) 20840274a2dSBaptiste Daroussin return (NULL); 20940274a2dSBaptiste Daroussin tag_length--; 21040274a2dSBaptiste Daroussin /* Check the tag fits */ 21140274a2dSBaptiste Daroussin if (tag_length > length) 21240274a2dSBaptiste Daroussin return (NULL); 21340274a2dSBaptiste Daroussin 21440274a2dSBaptiste Daroussin #define MOVE_TAG(len) do { \ 21540274a2dSBaptiste Daroussin assert(tag_length >= (len)); \ 21640274a2dSBaptiste Daroussin MOVE(len); \ 21740274a2dSBaptiste Daroussin tag_length -= (len); \ 21840274a2dSBaptiste Daroussin } while(0) 21940274a2dSBaptiste Daroussin 22040274a2dSBaptiste Daroussin MOVE(sizeof(tag_length)); 22140274a2dSBaptiste Daroussin tag_length -= sizeof(tag_length); 22240274a2dSBaptiste Daroussin 22340274a2dSBaptiste Daroussin while (tag_length != 0) { 22440274a2dSBaptiste Daroussin uint8_t tag; 22540274a2dSBaptiste Daroussin 22640274a2dSBaptiste Daroussin assert(tag_length >= length); 22740274a2dSBaptiste Daroussin 22840274a2dSBaptiste Daroussin tag = *section; 22940274a2dSBaptiste Daroussin MOVE_TAG(1); 23040274a2dSBaptiste Daroussin 23140274a2dSBaptiste Daroussin /* 23240274a2dSBaptiste Daroussin * These tag values come from: 23340274a2dSBaptiste Daroussin * 23440274a2dSBaptiste Daroussin * Addenda to, and Errata in, the ABI for the 23540274a2dSBaptiste Daroussin * ARM Architecture. Release 2.08, section 2.3. 23640274a2dSBaptiste Daroussin */ 23740274a2dSBaptiste Daroussin if (tag == 6) { /* == Tag_CPU_arch */ 23840274a2dSBaptiste Daroussin uint8_t val; 23940274a2dSBaptiste Daroussin 24040274a2dSBaptiste Daroussin val = *section; 24140274a2dSBaptiste Daroussin /* 24240274a2dSBaptiste Daroussin * We don't support values that require 24340274a2dSBaptiste Daroussin * more than one byte. 24440274a2dSBaptiste Daroussin */ 24540274a2dSBaptiste Daroussin if (val & (1 << 7)) 24640274a2dSBaptiste Daroussin return (NULL); 24740274a2dSBaptiste Daroussin 24840274a2dSBaptiste Daroussin /* We have an ARMv4 or ARMv5 */ 24940274a2dSBaptiste Daroussin if (val <= 5) 25040274a2dSBaptiste Daroussin return ("arm"); 25140274a2dSBaptiste Daroussin else /* We have an ARMv6+ */ 25240274a2dSBaptiste Daroussin return ("armv6"); 25340274a2dSBaptiste Daroussin } else if (tag == 4 || tag == 5 || tag == 32 || 25440274a2dSBaptiste Daroussin tag == 65 || tag == 67) { 25540274a2dSBaptiste Daroussin while (*section != '\0' && length != 0) 25640274a2dSBaptiste Daroussin MOVE_TAG(1); 25740274a2dSBaptiste Daroussin if (tag_length == 0) 25840274a2dSBaptiste Daroussin return (NULL); 25940274a2dSBaptiste Daroussin /* Skip the last byte */ 26040274a2dSBaptiste Daroussin MOVE_TAG(1); 26140274a2dSBaptiste Daroussin } else if ((tag >= 7 && tag <= 31) || tag == 34 || 26240274a2dSBaptiste Daroussin tag == 36 || tag == 38 || tag == 42 || tag == 44 || 26340274a2dSBaptiste Daroussin tag == 64 || tag == 66 || tag == 68 || tag == 70) { 26440274a2dSBaptiste Daroussin /* Skip the uleb128 data */ 26540274a2dSBaptiste Daroussin while (*section & (1 << 7) && length != 0) 26640274a2dSBaptiste Daroussin MOVE_TAG(1); 26740274a2dSBaptiste Daroussin if (tag_length == 0) 26840274a2dSBaptiste Daroussin return (NULL); 26940274a2dSBaptiste Daroussin /* Skip the last byte */ 27040274a2dSBaptiste Daroussin MOVE_TAG(1); 27140274a2dSBaptiste Daroussin } else 27240274a2dSBaptiste Daroussin return (NULL); 27340274a2dSBaptiste Daroussin #undef MOVE_TAG 27440274a2dSBaptiste Daroussin } 27540274a2dSBaptiste Daroussin 27640274a2dSBaptiste Daroussin break; 27740274a2dSBaptiste Daroussin } 27840274a2dSBaptiste Daroussin return (NULL); 27940274a2dSBaptiste Daroussin #undef MOVE 28040274a2dSBaptiste Daroussin } 28140274a2dSBaptiste Daroussin 2829950eceeSBaptiste Daroussin static int 2839950eceeSBaptiste Daroussin pkg_get_myabi(char *dest, size_t sz) 2849950eceeSBaptiste Daroussin { 2859950eceeSBaptiste Daroussin Elf *elf; 2869950eceeSBaptiste Daroussin Elf_Data *data; 2879950eceeSBaptiste Daroussin Elf_Note note; 2889950eceeSBaptiste Daroussin Elf_Scn *scn; 2899950eceeSBaptiste Daroussin char *src, *osname; 29040274a2dSBaptiste Daroussin const char *arch, *abi, *fpu, *endian_corres_str; 29140274a2dSBaptiste Daroussin const char *wordsize_corres_str; 2929950eceeSBaptiste Daroussin GElf_Ehdr elfhdr; 2939950eceeSBaptiste Daroussin GElf_Shdr shdr; 2949950eceeSBaptiste Daroussin int fd, i, ret; 2959950eceeSBaptiste Daroussin uint32_t version; 2969950eceeSBaptiste Daroussin 2979950eceeSBaptiste Daroussin version = 0; 2989950eceeSBaptiste Daroussin ret = -1; 2999950eceeSBaptiste Daroussin scn = NULL; 3009950eceeSBaptiste Daroussin abi = NULL; 3019950eceeSBaptiste Daroussin 3029950eceeSBaptiste Daroussin if (elf_version(EV_CURRENT) == EV_NONE) { 3039950eceeSBaptiste Daroussin warnx("ELF library initialization failed: %s", 3049950eceeSBaptiste Daroussin elf_errmsg(-1)); 3059950eceeSBaptiste Daroussin return (-1); 3069950eceeSBaptiste Daroussin } 3079950eceeSBaptiste Daroussin 3089950eceeSBaptiste Daroussin if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) { 3099950eceeSBaptiste Daroussin warn("open()"); 3109950eceeSBaptiste Daroussin return (-1); 3119950eceeSBaptiste Daroussin } 3129950eceeSBaptiste Daroussin 3139950eceeSBaptiste Daroussin if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) { 3149950eceeSBaptiste Daroussin ret = -1; 3159950eceeSBaptiste Daroussin warnx("elf_begin() failed: %s.", elf_errmsg(-1)); 3169950eceeSBaptiste Daroussin goto cleanup; 3179950eceeSBaptiste Daroussin } 3189950eceeSBaptiste Daroussin 3199950eceeSBaptiste Daroussin if (gelf_getehdr(elf, &elfhdr) == NULL) { 3209950eceeSBaptiste Daroussin ret = -1; 3219950eceeSBaptiste Daroussin warn("getehdr() failed: %s.", elf_errmsg(-1)); 3229950eceeSBaptiste Daroussin goto cleanup; 3239950eceeSBaptiste Daroussin } 3249950eceeSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 3259950eceeSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 3269950eceeSBaptiste Daroussin ret = -1; 3279950eceeSBaptiste Daroussin warn("getshdr() failed: %s.", elf_errmsg(-1)); 3289950eceeSBaptiste Daroussin goto cleanup; 3299950eceeSBaptiste Daroussin } 3309950eceeSBaptiste Daroussin 3319950eceeSBaptiste Daroussin if (shdr.sh_type == SHT_NOTE) 3329950eceeSBaptiste Daroussin break; 3339950eceeSBaptiste Daroussin } 3349950eceeSBaptiste Daroussin 3359950eceeSBaptiste Daroussin if (scn == NULL) { 3369950eceeSBaptiste Daroussin ret = -1; 3379950eceeSBaptiste Daroussin warn("failed to get the note section"); 3389950eceeSBaptiste Daroussin goto cleanup; 3399950eceeSBaptiste Daroussin } 3409950eceeSBaptiste Daroussin 3419950eceeSBaptiste Daroussin data = elf_getdata(scn, NULL); 3429950eceeSBaptiste Daroussin src = data->d_buf; 3439950eceeSBaptiste Daroussin for (;;) { 3449950eceeSBaptiste Daroussin memcpy(¬e, src, sizeof(Elf_Note)); 3459950eceeSBaptiste Daroussin src += sizeof(Elf_Note); 3469950eceeSBaptiste Daroussin if (note.n_type == NT_VERSION) 3479950eceeSBaptiste Daroussin break; 3489950eceeSBaptiste Daroussin src += note.n_namesz + note.n_descsz; 3499950eceeSBaptiste Daroussin } 3509950eceeSBaptiste Daroussin osname = src; 3519950eceeSBaptiste Daroussin src += roundup2(note.n_namesz, 4); 3529950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB) 3539950eceeSBaptiste Daroussin version = be32dec(src); 3549950eceeSBaptiste Daroussin else 3559950eceeSBaptiste Daroussin version = le32dec(src); 3569950eceeSBaptiste Daroussin 3579950eceeSBaptiste Daroussin for (i = 0; osname[i] != '\0'; i++) 3589950eceeSBaptiste Daroussin osname[i] = (char)tolower(osname[i]); 3599950eceeSBaptiste Daroussin 36040274a2dSBaptiste Daroussin wordsize_corres_str = elf_corres_to_string(wordsize_corres, 36140274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_CLASS]); 36240274a2dSBaptiste Daroussin 36340274a2dSBaptiste Daroussin arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine); 36440274a2dSBaptiste Daroussin 36540274a2dSBaptiste Daroussin snprintf(dest, sz, "%s:%d", 36640274a2dSBaptiste Daroussin osname, version / 100000); 3679950eceeSBaptiste Daroussin 3689950eceeSBaptiste Daroussin ret = 0; 3699950eceeSBaptiste Daroussin 3709950eceeSBaptiste Daroussin switch (elfhdr.e_machine) { 3719950eceeSBaptiste Daroussin case EM_ARM: 37240274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 37340274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 37440274a2dSBaptiste Daroussin 3754b5ef056SBaptiste Daroussin /* FreeBSD doesn't support the hard-float ABI yet */ 3764b5ef056SBaptiste Daroussin fpu = "softfp"; 3774b5ef056SBaptiste Daroussin if ((elfhdr.e_flags & 0xFF000000) != 0) { 37840274a2dSBaptiste Daroussin const char *sh_name = NULL; 37940274a2dSBaptiste Daroussin size_t shstrndx; 38040274a2dSBaptiste Daroussin 3814b5ef056SBaptiste Daroussin /* This is an EABI file, the conformance level is set */ 3824b5ef056SBaptiste Daroussin abi = "eabi"; 38340274a2dSBaptiste Daroussin /* Find which TARGET_ARCH we are building for. */ 38440274a2dSBaptiste Daroussin elf_getshdrstrndx(elf, &shstrndx); 38540274a2dSBaptiste Daroussin while ((scn = elf_nextscn(elf, scn)) != NULL) { 38640274a2dSBaptiste Daroussin sh_name = NULL; 38740274a2dSBaptiste Daroussin if (gelf_getshdr(scn, &shdr) != &shdr) { 38840274a2dSBaptiste Daroussin scn = NULL; 38940274a2dSBaptiste Daroussin break; 39040274a2dSBaptiste Daroussin } 39140274a2dSBaptiste Daroussin 39240274a2dSBaptiste Daroussin sh_name = elf_strptr(elf, shstrndx, 39340274a2dSBaptiste Daroussin shdr.sh_name); 39440274a2dSBaptiste Daroussin if (sh_name == NULL) 39540274a2dSBaptiste Daroussin continue; 39640274a2dSBaptiste Daroussin if (strcmp(".ARM.attributes", sh_name) == 0) 39740274a2dSBaptiste Daroussin break; 39840274a2dSBaptiste Daroussin } 39940274a2dSBaptiste Daroussin if (scn != NULL && sh_name != NULL) { 40040274a2dSBaptiste Daroussin data = elf_getdata(scn, NULL); 40140274a2dSBaptiste Daroussin /* 40240274a2dSBaptiste Daroussin * Prior to FreeBSD 10.0 libelf would return 40340274a2dSBaptiste Daroussin * NULL from elf_getdata on the .ARM.attributes 40440274a2dSBaptiste Daroussin * section. As this was the first release to 40540274a2dSBaptiste Daroussin * get armv6 support assume a NULL value means 40640274a2dSBaptiste Daroussin * arm. 40740274a2dSBaptiste Daroussin * 40840274a2dSBaptiste Daroussin * This assumption can be removed when 9.x 40940274a2dSBaptiste Daroussin * is unsupported. 41040274a2dSBaptiste Daroussin */ 41140274a2dSBaptiste Daroussin if (data != NULL) { 41240274a2dSBaptiste Daroussin arch = aeabi_parse_arm_attributes( 41340274a2dSBaptiste Daroussin data->d_buf, data->d_size); 41440274a2dSBaptiste Daroussin if (arch == NULL) { 41540274a2dSBaptiste Daroussin ret = 1; 41640274a2dSBaptiste Daroussin warn("unknown ARM ARCH"); 41740274a2dSBaptiste Daroussin goto cleanup; 41840274a2dSBaptiste Daroussin } 41940274a2dSBaptiste Daroussin } 42040274a2dSBaptiste Daroussin } else { 42140274a2dSBaptiste Daroussin ret = 1; 42240274a2dSBaptiste Daroussin warn("Unable to find the .ARM.attributes " 42340274a2dSBaptiste Daroussin "section"); 42440274a2dSBaptiste Daroussin goto cleanup; 42540274a2dSBaptiste Daroussin } 4264b5ef056SBaptiste Daroussin } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) { 4274b5ef056SBaptiste Daroussin /* 4284b5ef056SBaptiste Daroussin * EABI executables all have this field set to 4294b5ef056SBaptiste Daroussin * ELFOSABI_NONE, therefore it must be an oabi file. 4304b5ef056SBaptiste Daroussin */ 4314b5ef056SBaptiste Daroussin abi = "oabi"; 4324b5ef056SBaptiste Daroussin } else { 4334b5ef056SBaptiste Daroussin ret = 1; 43440274a2dSBaptiste Daroussin warn("unknown ARM ABI"); 4354b5ef056SBaptiste Daroussin goto cleanup; 4364b5ef056SBaptiste Daroussin } 4379950eceeSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), 43840274a2dSBaptiste Daroussin ":%s:%s:%s:%s:%s", arch, wordsize_corres_str, 43940274a2dSBaptiste Daroussin endian_corres_str, abi, fpu); 4409950eceeSBaptiste Daroussin break; 4419950eceeSBaptiste Daroussin case EM_MIPS: 4429950eceeSBaptiste Daroussin /* 4439950eceeSBaptiste Daroussin * this is taken from binutils sources: 4449950eceeSBaptiste Daroussin * include/elf/mips.h 4459950eceeSBaptiste Daroussin * mapping is figured out from binutils: 4469950eceeSBaptiste Daroussin * gas/config/tc-mips.c 4479950eceeSBaptiste Daroussin */ 4489950eceeSBaptiste Daroussin switch (elfhdr.e_flags & EF_MIPS_ABI) { 4499950eceeSBaptiste Daroussin case E_MIPS_ABI_O32: 4509950eceeSBaptiste Daroussin abi = "o32"; 4519950eceeSBaptiste Daroussin break; 4529950eceeSBaptiste Daroussin case E_MIPS_ABI_N32: 4539950eceeSBaptiste Daroussin abi = "n32"; 4549950eceeSBaptiste Daroussin break; 4559950eceeSBaptiste Daroussin default: 4569950eceeSBaptiste Daroussin if (elfhdr.e_ident[EI_DATA] == 4579950eceeSBaptiste Daroussin ELFCLASS32) 4589950eceeSBaptiste Daroussin abi = "o32"; 4599950eceeSBaptiste Daroussin else if (elfhdr.e_ident[EI_DATA] == 4609950eceeSBaptiste Daroussin ELFCLASS64) 4619950eceeSBaptiste Daroussin abi = "n64"; 4629950eceeSBaptiste Daroussin break; 4639950eceeSBaptiste Daroussin } 46440274a2dSBaptiste Daroussin endian_corres_str = elf_corres_to_string(endian_corres, 46540274a2dSBaptiste Daroussin (int)elfhdr.e_ident[EI_DATA]); 46640274a2dSBaptiste Daroussin 46740274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s", 46840274a2dSBaptiste Daroussin arch, wordsize_corres_str, endian_corres_str, abi); 4699950eceeSBaptiste Daroussin break; 47040274a2dSBaptiste Daroussin default: 47140274a2dSBaptiste Daroussin snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s", 47240274a2dSBaptiste Daroussin arch, wordsize_corres_str); 4739950eceeSBaptiste Daroussin } 4749950eceeSBaptiste Daroussin 4759950eceeSBaptiste Daroussin cleanup: 4769950eceeSBaptiste Daroussin if (elf != NULL) 4779950eceeSBaptiste Daroussin elf_end(elf); 4789950eceeSBaptiste Daroussin 4799950eceeSBaptiste Daroussin close(fd); 4809950eceeSBaptiste Daroussin return (ret); 4819950eceeSBaptiste Daroussin } 4829950eceeSBaptiste Daroussin 4839950eceeSBaptiste Daroussin static void 4849950eceeSBaptiste Daroussin subst_packagesite(const char *abi) 4859950eceeSBaptiste Daroussin { 4869950eceeSBaptiste Daroussin struct sbuf *newval; 4879950eceeSBaptiste Daroussin const char *variable_string; 4889950eceeSBaptiste Daroussin const char *oldval; 4899950eceeSBaptiste Daroussin 4909950eceeSBaptiste Daroussin if (c[PACKAGESITE].value != NULL) 4919950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].value; 4929950eceeSBaptiste Daroussin else 4939950eceeSBaptiste Daroussin oldval = c[PACKAGESITE].val; 4949950eceeSBaptiste Daroussin 4959950eceeSBaptiste Daroussin if ((variable_string = strstr(oldval, "${ABI}")) == NULL) 4969950eceeSBaptiste Daroussin return; 4979950eceeSBaptiste Daroussin 4989950eceeSBaptiste Daroussin newval = sbuf_new_auto(); 4999950eceeSBaptiste Daroussin sbuf_bcat(newval, oldval, variable_string - oldval); 5009950eceeSBaptiste Daroussin sbuf_cat(newval, abi); 5019950eceeSBaptiste Daroussin sbuf_cat(newval, variable_string + strlen("${ABI}")); 5029950eceeSBaptiste Daroussin sbuf_finish(newval); 5039950eceeSBaptiste Daroussin 5049950eceeSBaptiste Daroussin free(c[PACKAGESITE].value); 5059950eceeSBaptiste Daroussin c[PACKAGESITE].value = strdup(sbuf_data(newval)); 5069950eceeSBaptiste Daroussin } 5079950eceeSBaptiste Daroussin 508eb31a574SBryan Drewery static int 509eb31a574SBryan Drewery boolstr_to_bool(const char *str) 510eb31a574SBryan Drewery { 511eb31a574SBryan Drewery if (str != NULL && (strcasecmp(str, "true") == 0 || 512eb31a574SBryan Drewery strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 || 513eb31a574SBryan Drewery str[0] == '1')) 514eb31a574SBryan Drewery return (true); 515eb31a574SBryan Drewery 516eb31a574SBryan Drewery return (false); 517eb31a574SBryan Drewery } 518eb31a574SBryan Drewery 5199950eceeSBaptiste Daroussin static void 520*b04a7a0bSBaptiste Daroussin config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype) 5219950eceeSBaptiste Daroussin { 5229950eceeSBaptiste Daroussin struct sbuf *buf = sbuf_new_auto(); 523*b04a7a0bSBaptiste Daroussin const ucl_object_t *cur, *seq; 5248a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL, itseq = NULL; 525eb31a574SBryan Drewery struct config_entry *temp_config; 526eb31a574SBryan Drewery struct config_value *cv; 5278a7d859eSBaptiste Daroussin const char *key; 5289950eceeSBaptiste Daroussin int i; 5299950eceeSBaptiste Daroussin size_t j; 5309950eceeSBaptiste Daroussin 531eb31a574SBryan Drewery /* Temporary config for configs that may be disabled. */ 532eb31a574SBryan Drewery temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry)); 533eb31a574SBryan Drewery 5348a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 5358a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 5368a7d859eSBaptiste Daroussin if (key == NULL) 5379950eceeSBaptiste Daroussin continue; 5389950eceeSBaptiste Daroussin sbuf_clear(buf); 5399950eceeSBaptiste Daroussin 540bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) { 5418a7d859eSBaptiste Daroussin for (j = 0; j < strlen(key); ++j) 5428a7d859eSBaptiste Daroussin sbuf_putc(buf, key[j]); 5439950eceeSBaptiste Daroussin sbuf_finish(buf); 544bc5e9ac0SBryan Drewery } else if (conftype == CONFFILE_REPO) { 5458a7d859eSBaptiste Daroussin if (strcasecmp(key, "url") == 0) 546bc5e9ac0SBryan Drewery sbuf_cpy(buf, "PACKAGESITE"); 5478a7d859eSBaptiste Daroussin else if (strcasecmp(key, "mirror_type") == 0) 548bc5e9ac0SBryan Drewery sbuf_cpy(buf, "MIRROR_TYPE"); 5498a7d859eSBaptiste Daroussin else if (strcasecmp(key, "signature_type") == 0) 550f12db248SBryan Drewery sbuf_cpy(buf, "SIGNATURE_TYPE"); 5518a7d859eSBaptiste Daroussin else if (strcasecmp(key, "fingerprints") == 0) 552f12db248SBryan Drewery sbuf_cpy(buf, "FINGERPRINTS"); 5538a7d859eSBaptiste Daroussin else if (strcasecmp(key, "enabled") == 0) { 5548a7d859eSBaptiste Daroussin if ((cur->type != UCL_BOOLEAN) || 5558a7d859eSBaptiste Daroussin !ucl_object_toboolean(cur)) 556eb31a574SBryan Drewery goto cleanup; 5578a7d859eSBaptiste Daroussin } else 558bc5e9ac0SBryan Drewery continue; 559bc5e9ac0SBryan Drewery sbuf_finish(buf); 560bc5e9ac0SBryan Drewery } 561bc5e9ac0SBryan Drewery 5629950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 5639950eceeSBaptiste Daroussin if (strcmp(sbuf_data(buf), c[i].key) == 0) 5649950eceeSBaptiste Daroussin break; 5659950eceeSBaptiste Daroussin } 5669950eceeSBaptiste Daroussin 567bc5e9ac0SBryan Drewery /* Silently skip unknown keys to be future compatible. */ 5688a7d859eSBaptiste Daroussin if (i == CONFIG_SIZE) 5699950eceeSBaptiste Daroussin continue; 5709950eceeSBaptiste Daroussin 5719950eceeSBaptiste Daroussin /* env has priority over config file */ 5728a7d859eSBaptiste Daroussin if (c[i].envset) 5739950eceeSBaptiste Daroussin continue; 5749950eceeSBaptiste Daroussin 575eb31a574SBryan Drewery /* Parse sequence value ["item1", "item2"] */ 576eb31a574SBryan Drewery switch (c[i].type) { 577eb31a574SBryan Drewery case PKG_CONFIG_LIST: 5788a7d859eSBaptiste Daroussin if (cur->type != UCL_ARRAY) { 5798a7d859eSBaptiste Daroussin warnx("Skipping invalid array " 580eb31a574SBryan Drewery "value for %s.\n", c[i].key); 581eb31a574SBryan Drewery continue; 582eb31a574SBryan Drewery } 583eb31a574SBryan Drewery temp_config[i].list = 584eb31a574SBryan Drewery malloc(sizeof(*temp_config[i].list)); 585eb31a574SBryan Drewery STAILQ_INIT(temp_config[i].list); 586eb31a574SBryan Drewery 5878a7d859eSBaptiste Daroussin while ((seq = ucl_iterate_object(cur, &itseq, true))) { 5888a7d859eSBaptiste Daroussin if (seq->type != UCL_STRING) 589eb31a574SBryan Drewery continue; 590eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 591eb31a574SBryan Drewery cv->value = 5928a7d859eSBaptiste Daroussin strdup(ucl_object_tostring(seq)); 593eb31a574SBryan Drewery STAILQ_INSERT_TAIL(temp_config[i].list, cv, 594eb31a574SBryan Drewery next); 595eb31a574SBryan Drewery } 596eb31a574SBryan Drewery break; 597197372c2SBryan Drewery case PKG_CONFIG_BOOL: 598197372c2SBryan Drewery temp_config[i].value = 599197372c2SBryan Drewery strdup(ucl_object_toboolean(cur) ? "yes" : "no"); 600197372c2SBryan Drewery break; 601eb31a574SBryan Drewery default: 602eb31a574SBryan Drewery /* Normal string value. */ 6038a7d859eSBaptiste Daroussin temp_config[i].value = strdup(ucl_object_tostring(cur)); 604eb31a574SBryan Drewery break; 605eb31a574SBryan Drewery } 6069950eceeSBaptiste Daroussin } 6079950eceeSBaptiste Daroussin 608eb31a574SBryan Drewery /* Repo is enabled, copy over all settings from temp_config. */ 609eb31a574SBryan Drewery for (i = 0; i < CONFIG_SIZE; i++) { 610eb31a574SBryan Drewery if (c[i].envset) 611eb31a574SBryan Drewery continue; 61297c3a766SBryan Drewery /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */ 61397c3a766SBryan Drewery if (conftype != CONFFILE_PKG && c[i].main_only == true) 61497c3a766SBryan Drewery continue; 615eb31a574SBryan Drewery switch (c[i].type) { 616eb31a574SBryan Drewery case PKG_CONFIG_LIST: 617eb31a574SBryan Drewery c[i].list = temp_config[i].list; 618eb31a574SBryan Drewery break; 619eb31a574SBryan Drewery default: 620eb31a574SBryan Drewery c[i].value = temp_config[i].value; 621eb31a574SBryan Drewery break; 622eb31a574SBryan Drewery } 623eb31a574SBryan Drewery } 624eb31a574SBryan Drewery 625eb31a574SBryan Drewery cleanup: 626eb31a574SBryan Drewery free(temp_config); 6279950eceeSBaptiste Daroussin sbuf_delete(buf); 6289950eceeSBaptiste Daroussin } 6299950eceeSBaptiste Daroussin 630bc5e9ac0SBryan Drewery /*- 631bc5e9ac0SBryan Drewery * Parse new repo style configs in style: 632bc5e9ac0SBryan Drewery * Name: 633bc5e9ac0SBryan Drewery * URL: 634bc5e9ac0SBryan Drewery * MIRROR_TYPE: 635bc5e9ac0SBryan Drewery * etc... 636bc5e9ac0SBryan Drewery */ 637bc5e9ac0SBryan Drewery static void 6388a7d859eSBaptiste Daroussin parse_repo_file(ucl_object_t *obj) 639bc5e9ac0SBryan Drewery { 6408a7d859eSBaptiste Daroussin ucl_object_iter_t it = NULL; 641*b04a7a0bSBaptiste Daroussin const ucl_object_t *cur; 6428a7d859eSBaptiste Daroussin const char *key; 643bc5e9ac0SBryan Drewery 6448a7d859eSBaptiste Daroussin while ((cur = ucl_iterate_object(obj, &it, true))) { 6458a7d859eSBaptiste Daroussin key = ucl_object_key(cur); 646bc5e9ac0SBryan Drewery 6478a7d859eSBaptiste Daroussin if (key == NULL) 648bc5e9ac0SBryan Drewery continue; 649bc5e9ac0SBryan Drewery 6508a7d859eSBaptiste Daroussin if (cur->type != UCL_OBJECT) 651bc5e9ac0SBryan Drewery continue; 652bc5e9ac0SBryan Drewery 6538a7d859eSBaptiste Daroussin config_parse(cur, CONFFILE_REPO); 654bc5e9ac0SBryan Drewery } 655bc5e9ac0SBryan Drewery } 656bc5e9ac0SBryan Drewery 657bc5e9ac0SBryan Drewery 658bc5e9ac0SBryan Drewery static int 659bc5e9ac0SBryan Drewery read_conf_file(const char *confpath, pkg_conf_file_t conftype) 6609950eceeSBaptiste Daroussin { 6618a7d859eSBaptiste Daroussin struct ucl_parser *p; 6628a7d859eSBaptiste Daroussin ucl_object_t *obj = NULL; 663bc5e9ac0SBryan Drewery 6648a7d859eSBaptiste Daroussin p = ucl_parser_new(0); 6658a7d859eSBaptiste Daroussin 6668a7d859eSBaptiste Daroussin if (!ucl_parser_add_file(p, confpath)) { 667bc5e9ac0SBryan Drewery if (errno != ENOENT) 6688a7d859eSBaptiste Daroussin errx(EXIT_FAILURE, "Unable to parse configuration " 6698a7d859eSBaptiste Daroussin "file %s: %s", confpath, ucl_parser_get_error(p)); 6708a7d859eSBaptiste Daroussin ucl_parser_free(p); 671bc5e9ac0SBryan Drewery /* no configuration present */ 672bc5e9ac0SBryan Drewery return (1); 673bc5e9ac0SBryan Drewery } 674bc5e9ac0SBryan Drewery 6758a7d859eSBaptiste Daroussin obj = ucl_parser_get_object(p); 6768a7d859eSBaptiste Daroussin if (obj->type != UCL_OBJECT) 677bc5e9ac0SBryan Drewery warnx("Invalid configuration format, ignoring the " 678bc5e9ac0SBryan Drewery "configuration file %s", confpath); 679bc5e9ac0SBryan Drewery else { 680bc5e9ac0SBryan Drewery if (conftype == CONFFILE_PKG) 6818a7d859eSBaptiste Daroussin config_parse(obj, conftype); 682bc5e9ac0SBryan Drewery else if (conftype == CONFFILE_REPO) 6838a7d859eSBaptiste Daroussin parse_repo_file(obj); 684bc5e9ac0SBryan Drewery } 685bc5e9ac0SBryan Drewery 686*b04a7a0bSBaptiste Daroussin ucl_object_unref(obj); 6878a7d859eSBaptiste Daroussin ucl_parser_free(p); 688bc5e9ac0SBryan Drewery 689bc5e9ac0SBryan Drewery return (0); 690bc5e9ac0SBryan Drewery } 691bc5e9ac0SBryan Drewery 692eb31a574SBryan Drewery static int 693eb31a574SBryan Drewery load_repositories(const char *repodir) 694eb31a574SBryan Drewery { 695eb31a574SBryan Drewery struct dirent *ent; 696eb31a574SBryan Drewery DIR *d; 697eb31a574SBryan Drewery char *p; 698eb31a574SBryan Drewery size_t n; 699eb31a574SBryan Drewery char path[MAXPATHLEN]; 700eb31a574SBryan Drewery int ret; 701eb31a574SBryan Drewery 702eb31a574SBryan Drewery ret = 0; 703eb31a574SBryan Drewery 704eb31a574SBryan Drewery if ((d = opendir(repodir)) == NULL) 705eb31a574SBryan Drewery return (1); 706eb31a574SBryan Drewery 707eb31a574SBryan Drewery while ((ent = readdir(d))) { 708eb31a574SBryan Drewery /* Trim out 'repos'. */ 709eb31a574SBryan Drewery if ((n = strlen(ent->d_name)) <= 5) 710eb31a574SBryan Drewery continue; 711eb31a574SBryan Drewery p = &ent->d_name[n - 5]; 712eb31a574SBryan Drewery if (strcmp(p, ".conf") == 0) { 713eb31a574SBryan Drewery snprintf(path, sizeof(path), "%s%s%s", 714eb31a574SBryan Drewery repodir, 715eb31a574SBryan Drewery repodir[strlen(repodir) - 1] == '/' ? "" : "/", 716eb31a574SBryan Drewery ent->d_name); 717eb31a574SBryan Drewery if (access(path, F_OK) == 0 && 718eb31a574SBryan Drewery read_conf_file(path, CONFFILE_REPO)) { 719eb31a574SBryan Drewery ret = 1; 720eb31a574SBryan Drewery goto cleanup; 721eb31a574SBryan Drewery } 722eb31a574SBryan Drewery } 723eb31a574SBryan Drewery } 724eb31a574SBryan Drewery 725eb31a574SBryan Drewery cleanup: 726eb31a574SBryan Drewery closedir(d); 727eb31a574SBryan Drewery 728eb31a574SBryan Drewery return (ret); 729eb31a574SBryan Drewery } 730eb31a574SBryan Drewery 731bc5e9ac0SBryan Drewery int 732bc5e9ac0SBryan Drewery config_init(void) 733bc5e9ac0SBryan Drewery { 734eb31a574SBryan Drewery char *val; 7359950eceeSBaptiste Daroussin int i; 7369950eceeSBaptiste Daroussin const char *localbase; 737eb31a574SBryan Drewery char *env_list_item; 7389950eceeSBaptiste Daroussin char confpath[MAXPATHLEN]; 739eb31a574SBryan Drewery struct config_value *cv; 7409950eceeSBaptiste Daroussin char abi[BUFSIZ]; 7419950eceeSBaptiste Daroussin 7429950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) { 7439950eceeSBaptiste Daroussin val = getenv(c[i].key); 7449950eceeSBaptiste Daroussin if (val != NULL) { 7459950eceeSBaptiste Daroussin c[i].envset = true; 746eb31a574SBryan Drewery switch (c[i].type) { 747eb31a574SBryan Drewery case PKG_CONFIG_LIST: 748eb31a574SBryan Drewery /* Split up comma-separated items from env. */ 749eb31a574SBryan Drewery c[i].list = malloc(sizeof(*c[i].list)); 750eb31a574SBryan Drewery STAILQ_INIT(c[i].list); 751eb31a574SBryan Drewery for (env_list_item = strtok(val, ","); 752eb31a574SBryan Drewery env_list_item != NULL; 753eb31a574SBryan Drewery env_list_item = strtok(NULL, ",")) { 754eb31a574SBryan Drewery cv = 755eb31a574SBryan Drewery malloc(sizeof(struct config_value)); 756eb31a574SBryan Drewery cv->value = 757eb31a574SBryan Drewery strdup(env_list_item); 758eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[i].list, cv, 759eb31a574SBryan Drewery next); 760eb31a574SBryan Drewery } 761eb31a574SBryan Drewery break; 762eb31a574SBryan Drewery default: 763eb31a574SBryan Drewery c[i].val = val; 764eb31a574SBryan Drewery break; 765eb31a574SBryan Drewery } 7669950eceeSBaptiste Daroussin } 7679950eceeSBaptiste Daroussin } 7689950eceeSBaptiste Daroussin 769eb31a574SBryan Drewery /* Read LOCALBASE/etc/pkg.conf first. */ 7709950eceeSBaptiste Daroussin localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE; 771bc5e9ac0SBryan Drewery snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf", 772bc5e9ac0SBryan Drewery localbase); 7739950eceeSBaptiste Daroussin 774bc5e9ac0SBryan Drewery if (access(confpath, F_OK) == 0 && read_conf_file(confpath, 775bc5e9ac0SBryan Drewery CONFFILE_PKG)) 7769950eceeSBaptiste Daroussin goto finalize; 7779950eceeSBaptiste Daroussin 778eb31a574SBryan Drewery /* Then read in all repos from REPOS_DIR list of directories. */ 779eb31a574SBryan Drewery if (c[REPOS_DIR].list == NULL) { 780eb31a574SBryan Drewery c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list)); 781eb31a574SBryan Drewery STAILQ_INIT(c[REPOS_DIR].list); 782eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 783eb31a574SBryan Drewery cv->value = strdup("/etc/pkg"); 784eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 785eb31a574SBryan Drewery cv = malloc(sizeof(struct config_value)); 786eb31a574SBryan Drewery if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0) 787eb31a574SBryan Drewery goto finalize; 788eb31a574SBryan Drewery STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next); 789eb31a574SBryan Drewery } 790eb31a574SBryan Drewery 791eb31a574SBryan Drewery STAILQ_FOREACH(cv, c[REPOS_DIR].list, next) 792eb31a574SBryan Drewery if (load_repositories(cv->value)) 793bc5e9ac0SBryan Drewery goto finalize; 7949950eceeSBaptiste Daroussin 7959950eceeSBaptiste Daroussin finalize: 7969950eceeSBaptiste Daroussin if (c[ABI].val == NULL && c[ABI].value == NULL) { 7979950eceeSBaptiste Daroussin if (pkg_get_myabi(abi, BUFSIZ) != 0) 7984ff9a7efSBryan Drewery errx(EXIT_FAILURE, "Failed to determine the system " 7994ff9a7efSBryan Drewery "ABI"); 8009950eceeSBaptiste Daroussin c[ABI].val = abi; 8019950eceeSBaptiste Daroussin } 8029950eceeSBaptiste Daroussin 803d5bf8a8bSBaptiste Daroussin subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val); 8049950eceeSBaptiste Daroussin 8059950eceeSBaptiste Daroussin return (0); 8069950eceeSBaptiste Daroussin } 8079950eceeSBaptiste Daroussin 8089950eceeSBaptiste Daroussin int 8099950eceeSBaptiste Daroussin config_string(pkg_config_key k, const char **val) 8109950eceeSBaptiste Daroussin { 8119950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_STRING) 8129950eceeSBaptiste Daroussin return (-1); 8139950eceeSBaptiste Daroussin 8149950eceeSBaptiste Daroussin if (c[k].value != NULL) 8159950eceeSBaptiste Daroussin *val = c[k].value; 8169950eceeSBaptiste Daroussin else 8179950eceeSBaptiste Daroussin *val = c[k].val; 8189950eceeSBaptiste Daroussin 8199950eceeSBaptiste Daroussin return (0); 8209950eceeSBaptiste Daroussin } 8219950eceeSBaptiste Daroussin 8229950eceeSBaptiste Daroussin int 8239950eceeSBaptiste Daroussin config_bool(pkg_config_key k, bool *val) 8249950eceeSBaptiste Daroussin { 8259950eceeSBaptiste Daroussin const char *value; 8269950eceeSBaptiste Daroussin 8279950eceeSBaptiste Daroussin if (c[k].type != PKG_CONFIG_BOOL) 8289950eceeSBaptiste Daroussin return (-1); 8299950eceeSBaptiste Daroussin 8309950eceeSBaptiste Daroussin *val = false; 8319950eceeSBaptiste Daroussin 8329950eceeSBaptiste Daroussin if (c[k].value != NULL) 8339950eceeSBaptiste Daroussin value = c[k].value; 8349950eceeSBaptiste Daroussin else 8359950eceeSBaptiste Daroussin value = c[k].val; 8369950eceeSBaptiste Daroussin 837eb31a574SBryan Drewery if (boolstr_to_bool(value)) 8389950eceeSBaptiste Daroussin *val = true; 8399950eceeSBaptiste Daroussin 8409950eceeSBaptiste Daroussin return (0); 8419950eceeSBaptiste Daroussin } 8429950eceeSBaptiste Daroussin 8439950eceeSBaptiste Daroussin void 8449950eceeSBaptiste Daroussin config_finish(void) { 8459950eceeSBaptiste Daroussin int i; 8469950eceeSBaptiste Daroussin 8479950eceeSBaptiste Daroussin for (i = 0; i < CONFIG_SIZE; i++) 8489950eceeSBaptiste Daroussin free(c[i].value); 8499950eceeSBaptiste Daroussin } 850