]> CyberLeo.Net >> Repos - FreeBSD/releng/10.1.git/blob - usr.sbin/pkg/config.c
Implement pubkey support for pkg(7) bootstrap. [EN-15:18]
[FreeBSD/releng/10.1.git] / usr.sbin / pkg / config.c
1 /*-
2  * Copyright (c) 2014 Baptiste Daroussin <bapt@FreeBSD.org>
3  * Copyright (c) 2013 Bryan Drewery <bdrewery@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  */
27
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
30
31 #include <sys/param.h>
32 #include <sys/queue.h>
33 #include <sys/sbuf.h>
34 #include <sys/elf_common.h>
35 #include <sys/endian.h>
36 #include <sys/types.h>
37
38 #include <assert.h>
39 #include <dirent.h>
40 #include <ucl.h>
41 #include <ctype.h>
42 #include <err.h>
43 #include <errno.h>
44 #include <fcntl.h>
45 #include <gelf.h>
46 #include <inttypes.h>
47 #include <paths.h>
48 #include <stdbool.h>
49 #include <string.h>
50 #include <unistd.h>
51
52 #include "elf_tables.h"
53 #include "config.h"
54
55 #define roundup2(x, y)  (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
56
57 struct config_value {
58        char *value;
59        STAILQ_ENTRY(config_value) next;
60 };
61
62 struct config_entry {
63         uint8_t type;
64         const char *key;
65         const char *val;
66         char *value;
67         STAILQ_HEAD(, config_value) *list;
68         bool envset;
69         bool main_only;                         /* Only set in pkg.conf. */
70 };
71
72 static struct config_entry c[] = {
73         [PACKAGESITE] = {
74                 PKG_CONFIG_STRING,
75                 "PACKAGESITE",
76                 URL_SCHEME_PREFIX "http://pkg.FreeBSD.org/${ABI}/latest",
77                 NULL,
78                 NULL,
79                 false,
80                 false,
81         },
82         [ABI] = {
83                 PKG_CONFIG_STRING,
84                 "ABI",
85                 NULL,
86                 NULL,
87                 NULL,
88                 false,
89                 true,
90         },
91         [MIRROR_TYPE] = {
92                 PKG_CONFIG_STRING,
93                 "MIRROR_TYPE",
94                 "SRV",
95                 NULL,
96                 NULL,
97                 false,
98                 false,
99         },
100         [ASSUME_ALWAYS_YES] = {
101                 PKG_CONFIG_BOOL,
102                 "ASSUME_ALWAYS_YES",
103                 "NO",
104                 NULL,
105                 NULL,
106                 false,
107                 true,
108         },
109         [SIGNATURE_TYPE] = {
110                 PKG_CONFIG_STRING,
111                 "SIGNATURE_TYPE",
112                 NULL,
113                 NULL,
114                 NULL,
115                 false,
116                 false,
117         },
118         [FINGERPRINTS] = {
119                 PKG_CONFIG_STRING,
120                 "FINGERPRINTS",
121                 NULL,
122                 NULL,
123                 NULL,
124                 false,
125                 false,
126         },
127         [REPOS_DIR] = {
128                 PKG_CONFIG_LIST,
129                 "REPOS_DIR",
130                 NULL,
131                 NULL,
132                 NULL,
133                 false,
134                 true,
135         },
136         [PUBKEY] = {
137                 PKG_CONFIG_STRING,
138                 "PUBKEY",
139                 NULL,
140                 NULL,
141                 NULL,
142                 false,
143                 false
144         }
145 };
146
147 static const char *
148 elf_corres_to_string(struct _elf_corres *m, int e)
149 {
150         int i;
151
152         for (i = 0; m[i].string != NULL; i++)
153                 if (m[i].elf_nb == e)
154                         return (m[i].string);
155
156         return ("unknown");
157 }
158
159 static const char *
160 aeabi_parse_arm_attributes(void *data, size_t length) 
161 {
162         uint32_t sect_len;
163         uint8_t *section = data;
164
165 #define MOVE(len) do {            \
166         assert(length >= (len));  \
167         section += (len);         \
168         length -= (len);          \
169 } while (0)
170
171         if (length == 0 || *section != 'A')
172                 return (NULL);
173
174         MOVE(1);
175
176         /* Read the section length */
177         if (length < sizeof(sect_len))
178                 return (NULL);
179
180         memcpy(&sect_len, section, sizeof(sect_len));
181
182         /*
183          * The section length should be no longer than the section it is within
184          */
185         if (sect_len > length)
186                 return (NULL);
187
188         MOVE(sizeof(sect_len));
189
190         /* Skip the vendor name */
191         while (length != 0) {
192                 if (*section == '\0')
193                         break;
194                 MOVE(1);
195         }
196         if (length == 0)
197                 return (NULL);
198         MOVE(1);
199
200         while (length != 0) {
201                 uint32_t tag_length;
202
203         switch(*section) {
204         case 1: /* Tag_File */
205                 MOVE(1);
206                 if (length < sizeof(tag_length))
207                         return (NULL);
208                 memcpy(&tag_length, section, sizeof(tag_length));
209                 break;
210         case 2: /* Tag_Section */
211         case 3: /* Tag_Symbol */
212         default:
213                 return (NULL);
214         }
215         /* At least space for the tag and size */
216         if (tag_length <= 5)
217                 return (NULL);
218         tag_length--;
219         /* Check the tag fits */
220         if (tag_length > length)
221                 return (NULL);
222
223 #define  MOVE_TAG(len) do {           \
224         assert(tag_length >= (len));  \
225         MOVE(len);                    \
226         tag_length -= (len);          \
227 } while(0)
228
229                 MOVE(sizeof(tag_length));
230                 tag_length -= sizeof(tag_length);
231
232                 while (tag_length != 0) {
233                         uint8_t tag;
234
235                         assert(tag_length >= length);
236
237                         tag = *section;
238                         MOVE_TAG(1);
239
240                         /*
241                          * These tag values come from:
242                          * 
243                          * Addenda to, and Errata in, the ABI for the
244                          * ARM Architecture. Release 2.08, section 2.3.
245                          */
246                         if (tag == 6) { /* == Tag_CPU_arch */
247                                 uint8_t val;
248
249                                 val = *section;
250                                 /*
251                                  * We don't support values that require
252                                  * more than one byte.
253                                  */
254                                 if (val & (1 << 7))
255                                         return (NULL);
256
257                                 /* We have an ARMv4 or ARMv5 */
258                                 if (val <= 5)
259                                         return ("arm");
260                                 else /* We have an ARMv6+ */
261                                         return ("armv6");
262                         } else if (tag == 4 || tag == 5 || tag == 32 ||
263                             tag == 65 || tag == 67) {
264                                 while (*section != '\0' && length != 0)
265                                         MOVE_TAG(1);
266                                 if (tag_length == 0)
267                                         return (NULL);
268                                 /* Skip the last byte */
269                                 MOVE_TAG(1);
270                         } else if ((tag >= 7 && tag <= 31) || tag == 34 ||
271                             tag == 36 || tag == 38 || tag == 42 || tag == 44 ||
272                             tag == 64 || tag == 66 || tag == 68 || tag == 70) {
273                                 /* Skip the uleb128 data */
274                                 while (*section & (1 << 7) && length != 0)
275                                         MOVE_TAG(1);
276                                 if (tag_length == 0)
277                                         return (NULL);
278                                 /* Skip the last byte */
279                                 MOVE_TAG(1);
280                         } else
281                                 return (NULL);
282 #undef MOVE_TAG
283                 }
284
285                 break;
286         }
287         return (NULL);
288 #undef MOVE
289 }
290
291 static int
292 pkg_get_myabi(char *dest, size_t sz)
293 {
294         Elf *elf;
295         Elf_Data *data;
296         Elf_Note note;
297         Elf_Scn *scn;
298         char *src, *osname;
299         const char *arch, *abi, *fpu, *endian_corres_str;
300         const char *wordsize_corres_str;
301         GElf_Ehdr elfhdr;
302         GElf_Shdr shdr;
303         int fd, i, ret;
304         uint32_t version;
305
306         version = 0;
307         ret = -1;
308         scn = NULL;
309         abi = NULL;
310
311         if (elf_version(EV_CURRENT) == EV_NONE) {
312                 warnx("ELF library initialization failed: %s",
313                     elf_errmsg(-1));
314                 return (-1);
315         }
316
317         if ((fd = open(_PATH_BSHELL, O_RDONLY)) < 0) {
318                 warn("open()");
319                 return (-1);
320         }
321
322         if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
323                 ret = -1;
324                 warnx("elf_begin() failed: %s.", elf_errmsg(-1));
325                 goto cleanup;
326         }
327
328         if (gelf_getehdr(elf, &elfhdr) == NULL) {
329                 ret = -1;
330                 warn("getehdr() failed: %s.", elf_errmsg(-1));
331                 goto cleanup;
332         }
333         while ((scn = elf_nextscn(elf, scn)) != NULL) {
334                 if (gelf_getshdr(scn, &shdr) != &shdr) {
335                         ret = -1;
336                         warn("getshdr() failed: %s.", elf_errmsg(-1));
337                         goto cleanup;
338                 }
339
340                 if (shdr.sh_type == SHT_NOTE)
341                         break;
342         }
343
344         if (scn == NULL) {
345                 ret = -1;
346                 warn("failed to get the note section");
347                 goto cleanup;
348         }
349
350         data = elf_getdata(scn, NULL);
351         src = data->d_buf;
352         for (;;) {
353                 memcpy(&note, src, sizeof(Elf_Note));
354                 src += sizeof(Elf_Note);
355                 if (note.n_type == NT_VERSION)
356                         break;
357                 src += note.n_namesz + note.n_descsz;
358         }
359         osname = src;
360         src += roundup2(note.n_namesz, 4);
361         if (elfhdr.e_ident[EI_DATA] == ELFDATA2MSB)
362                 version = be32dec(src);
363         else
364                 version = le32dec(src);
365
366         for (i = 0; osname[i] != '\0'; i++)
367                 osname[i] = (char)tolower(osname[i]);
368
369         wordsize_corres_str = elf_corres_to_string(wordsize_corres,
370             (int)elfhdr.e_ident[EI_CLASS]);
371
372         arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
373
374         snprintf(dest, sz, "%s:%d",
375             osname, version / 100000);
376
377         ret = 0;
378
379         switch (elfhdr.e_machine) {
380         case EM_ARM:
381                 endian_corres_str = elf_corres_to_string(endian_corres,
382                     (int)elfhdr.e_ident[EI_DATA]);
383
384                 /* FreeBSD doesn't support the hard-float ABI yet */
385                 fpu = "softfp";
386                 if ((elfhdr.e_flags & 0xFF000000) != 0) {
387                         const char *sh_name = NULL;
388                         size_t shstrndx;
389
390                         /* This is an EABI file, the conformance level is set */
391                         abi = "eabi";
392                         /* Find which TARGET_ARCH we are building for. */
393                         elf_getshdrstrndx(elf, &shstrndx);
394                         while ((scn = elf_nextscn(elf, scn)) != NULL) {
395                                 sh_name = NULL;
396                                 if (gelf_getshdr(scn, &shdr) != &shdr) {
397                                         scn = NULL;
398                                         break;
399                                 }
400
401                                 sh_name = elf_strptr(elf, shstrndx,
402                                     shdr.sh_name);
403                                 if (sh_name == NULL)
404                                         continue;
405                                 if (strcmp(".ARM.attributes", sh_name) == 0)
406                                         break;
407                         }
408                         if (scn != NULL && sh_name != NULL) {
409                                 data = elf_getdata(scn, NULL);
410                                 /*
411                                  * Prior to FreeBSD 10.0 libelf would return
412                                  * NULL from elf_getdata on the .ARM.attributes
413                                  * section. As this was the first release to
414                                  * get armv6 support assume a NULL value means
415                                  * arm.
416                                  *
417                                  * This assumption can be removed when 9.x
418                                  * is unsupported.
419                                  */
420                                 if (data != NULL) {
421                                         arch = aeabi_parse_arm_attributes(
422                                             data->d_buf, data->d_size);
423                                         if (arch == NULL) {
424                                                 ret = 1;
425                                                 warn("unknown ARM ARCH");
426                                                 goto cleanup;
427                                         }
428                                 }
429                         } else {
430                                 ret = 1;
431                                 warn("Unable to find the .ARM.attributes "
432                                     "section");
433                                 goto cleanup;
434                         }
435                 } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) {
436                         /*
437                          * EABI executables all have this field set to
438                          * ELFOSABI_NONE, therefore it must be an oabi file.
439                          */
440                         abi = "oabi";
441                 } else {
442                         ret = 1;
443                         warn("unknown ARM ABI");
444                         goto cleanup;
445                 }
446                 snprintf(dest + strlen(dest), sz - strlen(dest),
447                     ":%s:%s:%s:%s:%s", arch, wordsize_corres_str,
448                     endian_corres_str, abi, fpu);
449                 break;
450         case EM_MIPS:
451                 /*
452                  * this is taken from binutils sources:
453                  * include/elf/mips.h
454                  * mapping is figured out from binutils:
455                  * gas/config/tc-mips.c
456                  */
457                 switch (elfhdr.e_flags & EF_MIPS_ABI) {
458                 case E_MIPS_ABI_O32:
459                         abi = "o32";
460                         break;
461                 case E_MIPS_ABI_N32:
462                         abi = "n32";
463                         break;
464                 default:
465                         if (elfhdr.e_ident[EI_DATA] ==
466                             ELFCLASS32)
467                                 abi = "o32";
468                         else if (elfhdr.e_ident[EI_DATA] ==
469                             ELFCLASS64)
470                                 abi = "n64";
471                         break;
472                 }
473                 endian_corres_str = elf_corres_to_string(endian_corres,
474                     (int)elfhdr.e_ident[EI_DATA]);
475
476                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s",
477                     arch, wordsize_corres_str, endian_corres_str, abi);
478                 break;
479         default:
480                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s",
481                     arch, wordsize_corres_str);
482         }
483
484 cleanup:
485         if (elf != NULL)
486                 elf_end(elf);
487
488         close(fd);
489         return (ret);
490 }
491
492 static void
493 subst_packagesite(const char *abi)
494 {
495         struct sbuf *newval;
496         const char *variable_string;
497         const char *oldval;
498
499         if (c[PACKAGESITE].value != NULL)
500                 oldval = c[PACKAGESITE].value;
501         else
502                 oldval = c[PACKAGESITE].val;
503
504         if ((variable_string = strstr(oldval, "${ABI}")) == NULL)
505                 return;
506
507         newval = sbuf_new_auto();
508         sbuf_bcat(newval, oldval, variable_string - oldval);
509         sbuf_cat(newval, abi);
510         sbuf_cat(newval, variable_string + strlen("${ABI}"));
511         sbuf_finish(newval);
512
513         free(c[PACKAGESITE].value);
514         c[PACKAGESITE].value = strdup(sbuf_data(newval));
515 }
516
517 static int
518 boolstr_to_bool(const char *str)
519 {
520         if (str != NULL && (strcasecmp(str, "true") == 0 ||
521             strcasecmp(str, "yes") == 0 || strcasecmp(str, "on") == 0 ||
522             str[0] == '1'))
523                 return (true);
524
525         return (false);
526 }
527
528 static void
529 config_parse(const ucl_object_t *obj, pkg_conf_file_t conftype)
530 {
531         struct sbuf *buf = sbuf_new_auto();
532         const ucl_object_t *cur, *seq;
533         ucl_object_iter_t it = NULL, itseq = NULL;
534         struct config_entry *temp_config;
535         struct config_value *cv;
536         const char *key;
537         int i;
538         size_t j;
539
540         /* Temporary config for configs that may be disabled. */
541         temp_config = calloc(CONFIG_SIZE, sizeof(struct config_entry));
542
543         while ((cur = ucl_iterate_object(obj, &it, true))) {
544                 key = ucl_object_key(cur);
545                 if (key == NULL)
546                         continue;
547                 sbuf_clear(buf);
548
549                 if (conftype == CONFFILE_PKG) {
550                         for (j = 0; j < strlen(key); ++j)
551                                 sbuf_putc(buf, key[j]);
552                         sbuf_finish(buf);
553                 } else if (conftype == CONFFILE_REPO) {
554                         if (strcasecmp(key, "url") == 0)
555                                 sbuf_cpy(buf, "PACKAGESITE");
556                         else if (strcasecmp(key, "mirror_type") == 0)
557                                 sbuf_cpy(buf, "MIRROR_TYPE");
558                         else if (strcasecmp(key, "signature_type") == 0)
559                                 sbuf_cpy(buf, "SIGNATURE_TYPE");
560                         else if (strcasecmp(key, "fingerprints") == 0)
561                                 sbuf_cpy(buf, "FINGERPRINTS");
562                         else if (strcasecmp(key, "pubkey") == 0)
563                                 sbuf_cpy(buf, "PUBKEY");
564                         else if (strcasecmp(key, "enabled") == 0) {
565                                 if ((cur->type != UCL_BOOLEAN) ||
566                                     !ucl_object_toboolean(cur))
567                                         goto cleanup;
568                         } else
569                                 continue;
570                         sbuf_finish(buf);
571                 }
572
573                 for (i = 0; i < CONFIG_SIZE; i++) {
574                         if (strcmp(sbuf_data(buf), c[i].key) == 0)
575                                 break;
576                 }
577
578                 /* Silently skip unknown keys to be future compatible. */
579                 if (i == CONFIG_SIZE)
580                         continue;
581
582                 /* env has priority over config file */
583                 if (c[i].envset)
584                         continue;
585
586                 /* Parse sequence value ["item1", "item2"] */
587                 switch (c[i].type) {
588                 case PKG_CONFIG_LIST:
589                         if (cur->type != UCL_ARRAY) {
590                                 warnx("Skipping invalid array "
591                                     "value for %s.\n", c[i].key);
592                                 continue;
593                         }
594                         temp_config[i].list =
595                             malloc(sizeof(*temp_config[i].list));
596                         STAILQ_INIT(temp_config[i].list);
597
598                         while ((seq = ucl_iterate_object(cur, &itseq, true))) {
599                                 if (seq->type != UCL_STRING)
600                                         continue;
601                                 cv = malloc(sizeof(struct config_value));
602                                 cv->value =
603                                     strdup(ucl_object_tostring(seq));
604                                 STAILQ_INSERT_TAIL(temp_config[i].list, cv,
605                                     next);
606                         }
607                         break;
608                 case PKG_CONFIG_BOOL:
609                         temp_config[i].value =
610                             strdup(ucl_object_toboolean(cur) ? "yes" : "no");
611                         break;
612                 default:
613                         /* Normal string value. */
614                         temp_config[i].value = strdup(ucl_object_tostring(cur));
615                         break;
616                 }
617         }
618
619         /* Repo is enabled, copy over all settings from temp_config. */
620         for (i = 0; i < CONFIG_SIZE; i++) {
621                 if (c[i].envset)
622                         continue;
623                 /* Prevent overriding ABI, ASSUME_ALWAYS_YES, etc. */
624                 if (conftype != CONFFILE_PKG && c[i].main_only == true)
625                         continue;
626                 switch (c[i].type) {
627                 case PKG_CONFIG_LIST:
628                         c[i].list = temp_config[i].list;
629                         break;
630                 default:
631                         c[i].value = temp_config[i].value;
632                         break;
633                 }
634         }
635
636 cleanup:
637         free(temp_config);
638         sbuf_delete(buf);
639 }
640
641 /*-
642  * Parse new repo style configs in style:
643  * Name:
644  *   URL:
645  *   MIRROR_TYPE:
646  * etc...
647  */
648 static void
649 parse_repo_file(ucl_object_t *obj)
650 {
651         ucl_object_iter_t it = NULL;
652         const ucl_object_t *cur;
653         const char *key;
654
655         while ((cur = ucl_iterate_object(obj, &it, true))) {
656                 key = ucl_object_key(cur);
657
658                 if (key == NULL)
659                         continue;
660
661                 if (cur->type != UCL_OBJECT)
662                         continue;
663
664                 config_parse(cur, CONFFILE_REPO);
665         }
666 }
667
668
669 static int
670 read_conf_file(const char *confpath, pkg_conf_file_t conftype)
671 {
672         struct ucl_parser *p;
673         ucl_object_t *obj = NULL;
674
675         p = ucl_parser_new(0);
676
677         if (!ucl_parser_add_file(p, confpath)) {
678                 if (errno != ENOENT)
679                         errx(EXIT_FAILURE, "Unable to parse configuration "
680                             "file %s: %s", confpath, ucl_parser_get_error(p));
681                 ucl_parser_free(p);
682                 /* no configuration present */
683                 return (1);
684         }
685
686         obj = ucl_parser_get_object(p);
687         if (obj->type != UCL_OBJECT) 
688                 warnx("Invalid configuration format, ignoring the "
689                     "configuration file %s", confpath);
690         else {
691                 if (conftype == CONFFILE_PKG)
692                         config_parse(obj, conftype);
693                 else if (conftype == CONFFILE_REPO)
694                         parse_repo_file(obj);
695         }
696
697         ucl_object_unref(obj);
698         ucl_parser_free(p);
699
700         return (0);
701 }
702
703 static int
704 load_repositories(const char *repodir)
705 {
706         struct dirent *ent;
707         DIR *d;
708         char *p;
709         size_t n;
710         char path[MAXPATHLEN];
711         int ret;
712
713         ret = 0;
714
715         if ((d = opendir(repodir)) == NULL)
716                 return (1);
717
718         while ((ent = readdir(d))) {
719                 /* Trim out 'repos'. */
720                 if ((n = strlen(ent->d_name)) <= 5)
721                         continue;
722                 p = &ent->d_name[n - 5];
723                 if (strcmp(p, ".conf") == 0) {
724                         snprintf(path, sizeof(path), "%s%s%s",
725                             repodir,
726                             repodir[strlen(repodir) - 1] == '/' ? "" : "/",
727                             ent->d_name);
728                         if (access(path, F_OK) == 0 &&
729                             read_conf_file(path, CONFFILE_REPO)) {
730                                 ret = 1;
731                                 goto cleanup;
732                         }
733                 }
734         }
735
736 cleanup:
737         closedir(d);
738
739         return (ret);
740 }
741
742 int
743 config_init(void)
744 {
745         char *val;
746         int i;
747         const char *localbase;
748         char *env_list_item;
749         char confpath[MAXPATHLEN];
750         struct config_value *cv;
751         char abi[BUFSIZ];
752
753         for (i = 0; i < CONFIG_SIZE; i++) {
754                 val = getenv(c[i].key);
755                 if (val != NULL) {
756                         c[i].envset = true;
757                         switch (c[i].type) {
758                         case PKG_CONFIG_LIST:
759                                 /* Split up comma-separated items from env. */
760                                 c[i].list = malloc(sizeof(*c[i].list));
761                                 STAILQ_INIT(c[i].list);
762                                 for (env_list_item = strtok(val, ",");
763                                     env_list_item != NULL;
764                                     env_list_item = strtok(NULL, ",")) {
765                                         cv =
766                                             malloc(sizeof(struct config_value));
767                                         cv->value =
768                                             strdup(env_list_item);
769                                         STAILQ_INSERT_TAIL(c[i].list, cv,
770                                             next);
771                                 }
772                                 break;
773                         default:
774                                 c[i].val = val;
775                                 break;
776                         }
777                 }
778         }
779
780         /* Read LOCALBASE/etc/pkg.conf first. */
781         localbase = getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE;
782         snprintf(confpath, sizeof(confpath), "%s/etc/pkg.conf",
783             localbase);
784
785         if (access(confpath, F_OK) == 0 && read_conf_file(confpath,
786             CONFFILE_PKG))
787                 goto finalize;
788
789         /* Then read in all repos from REPOS_DIR list of directories. */
790         if (c[REPOS_DIR].list == NULL) {
791                 c[REPOS_DIR].list = malloc(sizeof(*c[REPOS_DIR].list));
792                 STAILQ_INIT(c[REPOS_DIR].list);
793                 cv = malloc(sizeof(struct config_value));
794                 cv->value = strdup("/etc/pkg");
795                 STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
796                 cv = malloc(sizeof(struct config_value));
797                 if (asprintf(&cv->value, "%s/etc/pkg/repos", localbase) < 0)
798                         goto finalize;
799                 STAILQ_INSERT_TAIL(c[REPOS_DIR].list, cv, next);
800         }
801
802         STAILQ_FOREACH(cv, c[REPOS_DIR].list, next)
803                 if (load_repositories(cv->value))
804                         goto finalize;
805
806 finalize:
807         if (c[ABI].val == NULL && c[ABI].value == NULL) {
808                 if (pkg_get_myabi(abi, BUFSIZ) != 0)
809                         errx(EXIT_FAILURE, "Failed to determine the system "
810                             "ABI");
811                 c[ABI].val = abi;
812         }
813
814         subst_packagesite(c[ABI].value != NULL ? c[ABI].value : c[ABI].val);
815
816         return (0);
817 }
818
819 int
820 config_string(pkg_config_key k, const char **val)
821 {
822         if (c[k].type != PKG_CONFIG_STRING)
823                 return (-1);
824
825         if (c[k].value != NULL)
826                 *val = c[k].value;
827         else
828                 *val = c[k].val;
829
830         return (0);
831 }
832
833 int
834 config_bool(pkg_config_key k, bool *val)
835 {
836         const char *value;
837
838         if (c[k].type != PKG_CONFIG_BOOL)
839                 return (-1);
840
841         *val = false;
842
843         if (c[k].value != NULL)
844                 value = c[k].value;
845         else
846                 value = c[k].val;
847
848         if (boolstr_to_bool(value))
849                 *val = true;
850
851         return (0);
852 }
853
854 void
855 config_finish(void) {
856         int i;
857
858         for (i = 0; i < CONFIG_SIZE; i++)
859                 free(c[i].value);
860 }