/ libpkg / pkg_config.c
pkg_config.c
   1  /*
   2   * Copyright (c) 2011-2025 Baptiste Daroussin <bapt@FreeBSD.org>
   3   * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
   4   * Copyright (c) 2014 Matthew Seaman <matthew@FreeBSD.org>
   5   * Copyright (c) 2016 Vsevolod Stakhov <vsevolod@FreeBSD.org>
   6   * All rights reserved.
   7   *
   8   * Redistribution and use in source and binary forms, with or without
   9   * modification, are permitted provided that the following conditions
  10   * are met:
  11   * 1. Redistributions of source code must retain the above copyright
  12   *    notice, this list of conditions and the following disclaimer
  13   *    in this position and unchanged.
  14   * 2. Redistributions in binary form must reproduce the above copyright
  15   *    notice, this list of conditions and the following disclaimer in the
  16   *    documentation and/or other materials provided with the distribution.
  17   *
  18   * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
  19   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  20   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
  21   * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
  22   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  23   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  24   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  25   * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  27   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28   */
  29  
  30  #include "pkg_config.h"
  31  
  32  #include <assert.h>
  33  #include <sys/socket.h>
  34  #include <sys/un.h>
  35  #include <ctype.h>
  36  #include <dirent.h>
  37  #include <dlfcn.h>
  38  #include <errno.h>
  39  #include <fcntl.h>
  40  #if __has_include(<osreldate.h>)
  41  #include <osreldate.h>
  42  #endif
  43  #include <ucl.h>
  44  
  45  #include <archive.h>
  46  #include <sqlite3.h>
  47  #include <openssl/crypto.h>
  48  
  49  #include "pkg.h"
  50  #include "private/pkg.h"
  51  #include "private/pkg_abi.h"
  52  #include "private/event.h"
  53  #include "private/fetch.h"
  54  #include "pkg_repos.h"
  55  
  56  #ifndef PORTSDIR
  57  #define PORTSDIR "/usr/ports"
  58  #endif
  59  #ifndef DEFAULT_VULNXML_URL
  60  #define DEFAULT_VULNXML_URL "https://vuxml.freebsd.org/freebsd/vuln.xml.xz"
  61  #endif
  62  
  63  #ifdef	OSMAJOR
  64  #define STRINGIFY(X)	TEXT(X)
  65  #define TEXT(X)		#X
  66  #define INDEXFILE	"INDEX-" STRINGIFY(OSMAJOR)
  67  #else
  68  #define INDEXFILE	"INDEX"
  69  #endif
  70  
  71  #define dbg(x, ...) pkg_dbg(PKG_DBG_CONFIG, x, __VA_ARGS__)
  72  
  73  struct pkg_ctx ctx = {
  74  	.eventpipe = -1,
  75  	.debug_level = 0,
  76  	.developer_mode = false,
  77  	.pkg_rootdir = NULL,
  78  	.metalog = NULL,
  79  	.dbdir = NULL,
  80  	.cachedir = NULL,
  81  	.rootfd = -1,
  82  	.cachedirfd = -1,
  83  	.pkg_dbdirfd = -1,
  84  	.pkg_reposdirfd = -1,
  85  	.devnullfd = -1,
  86  	.backup_libraries = false,
  87  	.triggers = true,
  88  	.compression_format = NULL,
  89  	.compression_level = -1,
  90  	.compression_threads = -1,
  91  	.defer_triggers = false,
  92  	.no_version_for_deps = false,
  93  };
  94  
  95  struct config_entry {
  96  	uint8_t type;
  97  	const char *key;
  98  	const char *def;
  99  };
 100  
 101  static struct pkg_repo *repos = NULL;
 102  ucl_object_t *config = NULL;
 103  
 104  static struct config_entry c[] = {
 105  	{
 106  		PKG_STRING,
 107  		"PKG_DBDIR",
 108  		"/var/db/pkg",
 109  	},
 110  	{
 111  		PKG_STRING,
 112  		"PKG_CACHEDIR",
 113  		"/var/cache/pkg",
 114  	},
 115  	{
 116  		PKG_STRING,
 117  		"PORTSDIR",
 118  		"/usr/ports",
 119  	},
 120  	{
 121  		PKG_STRING,
 122  		"INDEXDIR",
 123  		NULL,		/* Default to PORTSDIR unless defined */
 124  	},
 125  	{
 126  		PKG_STRING,
 127  		"INDEXFILE",
 128  		INDEXFILE,
 129  	},
 130  	{
 131  		PKG_BOOL,
 132  		"HANDLE_RC_SCRIPTS",
 133  		"NO",
 134  	},
 135  	{
 136  		PKG_BOOL,
 137  		"DEFAULT_ALWAYS_YES",
 138  		"NO",
 139  	},
 140  	{
 141  		PKG_BOOL,
 142  		"ASSUME_ALWAYS_YES",
 143  		"NO",
 144  	},
 145  	{
 146  		PKG_ARRAY,
 147  		"REPOS_DIR",
 148  		"/etc/pkg/,"PREFIX"/etc/pkg/repos/",
 149  	},
 150  	{
 151  		PKG_STRING,
 152  		"PLIST_KEYWORDS_DIR",
 153  		NULL,
 154  	},
 155  	{
 156  		PKG_BOOL,
 157  		"SYSLOG",
 158  		"YES",
 159  	},
 160  	{
 161  		PKG_BOOL,
 162  		"DEVELOPER_MODE",
 163  		"NO",
 164  	},
 165  	{
 166  		PKG_STRING,
 167  		"VULNXML_SITE",
 168  		DEFAULT_VULNXML_URL,
 169  	},
 170  	{
 171  		PKG_INT,
 172  		"FETCH_RETRY",
 173  		"3",
 174  	},
 175  	{
 176  		PKG_STRING,
 177  		"PKG_PLUGINS_DIR",
 178  		PREFIX"/lib/pkg/",
 179  	},
 180  	{
 181  		PKG_BOOL,
 182  		"PKG_ENABLE_PLUGINS",
 183  		"YES",
 184  	},
 185  	{
 186  		PKG_ARRAY,
 187  		"PLUGINS",
 188  		NULL,
 189  	},
 190  	{
 191  		PKG_BOOL,
 192  		"DEBUG_SCRIPTS",
 193  		"NO",
 194  	},
 195  	{
 196  		PKG_STRING,
 197  		"PLUGINS_CONF_DIR",
 198  		PREFIX"/etc/pkg/",
 199  	},
 200  	{
 201  		PKG_BOOL,
 202  		"PERMISSIVE",
 203  		"NO",
 204  	},
 205  	{
 206  		PKG_BOOL,
 207  		"REPO_AUTOUPDATE",
 208  		"YES",
 209  	},
 210  	{
 211  		PKG_STRING,
 212  		"NAMESERVER",
 213  		NULL,
 214  	},
 215  	{
 216  		PKG_STRING,
 217  		"HTTP_USER_AGENT",
 218  		"pkg/"PKGVERSION,
 219  	},
 220  	{
 221  		PKG_STRING,
 222  		"EVENT_PIPE",
 223  		NULL,
 224  	},
 225  	{
 226  		PKG_INT,
 227  		"FETCH_TIMEOUT",
 228  		"30",
 229  	},
 230  	{
 231  		PKG_BOOL,
 232  		"UNSET_TIMESTAMP",
 233  		"NO",
 234  	},
 235  	{
 236  		PKG_STRING,
 237  		"SSH_RESTRICT_DIR",
 238  		NULL,
 239  	},
 240  	{
 241  		PKG_OBJECT,
 242  		"PKG_ENV",
 243  		NULL,
 244  	},
 245  	{
 246  		PKG_STRING,
 247  		"PKG_SSH_ARGS",
 248  		NULL,
 249  	},
 250  	{
 251  		PKG_INT,
 252  		"DEBUG_LEVEL",
 253  		"0",
 254  	},
 255  	{
 256  		PKG_OBJECT,
 257  		"ALIAS",
 258  		NULL,
 259  	},
 260  	{
 261  		PKG_STRING,
 262  		"CUDF_SOLVER",
 263  		NULL,
 264  	},
 265  	{
 266  		PKG_STRING,
 267  		"SAT_SOLVER",
 268  		NULL,
 269  	},
 270  	{
 271  		PKG_BOOL,
 272  		"RUN_SCRIPTS",
 273  		"YES",
 274  	},
 275  	{
 276  		PKG_BOOL,
 277  		"CASE_SENSITIVE_MATCH",
 278  		"YES",
 279  	},
 280  	{
 281  		PKG_INT,
 282  		"LOCK_WAIT",
 283  		"1",
 284  	},
 285  	{
 286  		PKG_INT,
 287  		"LOCK_RETRIES",
 288  		"5",
 289  	},
 290  	{
 291  		PKG_BOOL,
 292  		"SQLITE_PROFILE",
 293  		"NO",
 294  	},
 295  	{
 296  		PKG_INT,
 297  		"WORKERS_COUNT",
 298  		"0",
 299  	},
 300  	{
 301  		PKG_BOOL,
 302  		"READ_LOCK",
 303  		"NO",
 304  	},
 305  	{
 306  		PKG_INT,
 307  		"IP_VERSION",
 308  		"0",
 309  	},
 310  	{
 311  		PKG_BOOL,
 312  		"AUTOMERGE",
 313  		"YES",
 314  	},
 315  	{
 316  		PKG_STRING,
 317  		"MERGETOOL",
 318  		NULL,
 319  	},
 320  	{
 321  		PKG_STRING,
 322  		"VERSION_SOURCE",
 323  		NULL,
 324  	},
 325  	{
 326  		PKG_BOOL,
 327  		"CONSERVATIVE_UPGRADE",
 328  		"YES",
 329  	},
 330  	{
 331  		PKG_BOOL,
 332  		"FORCE_CAN_REMOVE_VITAL",
 333  		"YES",
 334  	},
 335  	{
 336  		PKG_BOOL,
 337  		"PKG_CREATE_VERBOSE",
 338  		"NO",
 339  	},
 340  	{
 341  		PKG_BOOL,
 342  		"AUTOCLEAN",
 343  		"NO",
 344  	},
 345  	{
 346  		PKG_BOOL,
 347  		"AUTOREMOVE",
 348  		"NO",
 349  	},
 350  	{
 351  		PKG_STRING,
 352  		"DOT_FILE",
 353  		NULL,
 354  	},
 355  	{
 356  		PKG_STRING,
 357  		"DEBUG_SCHEDULER_DOT_FILE",
 358  		NULL,
 359  	},
 360  	{
 361  		PKG_OBJECT,
 362  		"REPOSITORIES",
 363  		NULL,
 364  	},
 365  	{
 366  		PKG_ARRAY,
 367  		"VALID_URL_SCHEME",
 368  		"pkg+http,pkg+https,https,http,file,ssh,tcp",
 369  	},
 370  	{
 371  		PKG_INT,
 372  		"WARN_SIZE_LIMIT",
 373  		"1048576", /* 1 meg */
 374  	},
 375  	{
 376  		PKG_STRING,
 377  		"METALOG",
 378  		NULL,
 379  	},
 380  	{
 381  		PKG_BOOL,
 382  		"IGNORE_OSVERSION",
 383  		"NO",
 384  	},
 385  	{
 386  		PKG_BOOL,
 387  		"BACKUP_LIBRARIES",
 388  		"NO",
 389  	},
 390  	{
 391  		PKG_STRING,
 392  		"BACKUP_LIBRARY_PATH",
 393  		PREFIX "/lib/compat/pkg",
 394  	},
 395  	{
 396  		PKG_ARRAY,
 397  		"PKG_TRIGGERS_DIR",
 398  		"/usr/share/pkg/triggers/,"PREFIX"/share/pkg/triggers",
 399  	},
 400  	{
 401  		PKG_BOOL,
 402  		"PKG_TRIGGERS_ENABLE",
 403  		"YES",
 404  	},
 405  	{
 406  		PKG_ARRAY,
 407  		"AUDIT_IGNORE_GLOB",
 408  		NULL,
 409  	},
 410  	{
 411  		PKG_ARRAY,
 412  		"AUDIT_IGNORE_REGEX",
 413  		NULL,
 414  	},
 415  	{
 416  		PKG_STRING,
 417  		"COMPRESSION_FORMAT",
 418  		NULL,
 419  	},
 420  	{
 421  		PKG_INT,
 422  		"COMPRESSION_LEVEL",
 423  		"-1",
 424  	},
 425  	{
 426  		PKG_BOOL,
 427  		"REPO_ACCEPT_LEGACY_PKG",
 428  		"FALSE",
 429  	},
 430  	{
 431  		PKG_ARRAY,
 432  		"FILES_IGNORE_GLOB",
 433  		NULL,
 434  	},
 435  	{
 436  		PKG_ARRAY,
 437  		"FILES_IGNORE_REGEX",
 438  		NULL,
 439  	},
 440  	{
 441  		PKG_ARRAY,
 442  		"SHLIB_PROVIDE_PATHS_NATIVE",
 443  		NULL,
 444  	},
 445  	{
 446  		PKG_ARRAY,
 447  		"SHLIB_PROVIDE_PATHS_COMPAT_32",
 448  		NULL,
 449  	},
 450  	{
 451  		PKG_ARRAY,
 452  		"SHLIB_PROVIDE_PATHS_COMPAT_LINUX",
 453  		NULL,
 454  	},
 455  	{
 456  		PKG_ARRAY,
 457  		"SHLIB_PROVIDE_PATHS_COMPAT_LINUX_32",
 458  		NULL,
 459  	},
 460  	{
 461  		PKG_ARRAY,
 462  		"SHLIB_PROVIDE_IGNORE_GLOB",
 463  		NULL,
 464  	},
 465  	{
 466  		PKG_ARRAY,
 467  		"SHLIB_PROVIDE_IGNORE_REGEX",
 468  		NULL,
 469  	},
 470  	{
 471  		PKG_ARRAY,
 472  		"SHLIB_REQUIRE_IGNORE_GLOB",
 473  		NULL,
 474  	},
 475  	{
 476  		PKG_ARRAY,
 477  		"SHLIB_REQUIRE_IGNORE_REGEX",
 478  		NULL,
 479  	},
 480  	{
 481  		PKG_ARRAY,
 482  		"PKG_DEBUG_FLAGS",
 483  		"all",
 484  	},
 485  	{
 486  		PKG_INT,
 487  		"COMPRESSION_THREADS",
 488  		"-1",
 489  	},
 490  	{
 491  		PKG_BOOL,
 492  		"PKG_REINSTALL_ON_OPTIONS_CHANGE",
 493  		"TRUE",
 494  	},
 495  	{
 496  		PKG_BOOL,
 497  		"TRACK_LINUX_COMPAT_SHLIBS",
 498  		"FALSE",
 499  	},
 500  };
 501  
 502  static bool parsed = false;
 503  static size_t c_size = NELEM(c);
 504  
 505  static struct pkg_repo* pkg_repo_new(const char *name,
 506  	const char *url, const char *type);
 507  static void pkg_repo_overwrite(struct pkg_repo*, const char *name,
 508  	const char *url, const char *type);
 509  static void pkg_repo_free(struct pkg_repo *r);
 510  
 511  static void
 512  connect_evpipe(const char *evpipe) {
 513  	struct stat st;
 514  	struct sockaddr_un sock;
 515  	int flag = O_WRONLY;
 516  
 517  	if (stat(evpipe, &st) != 0) {
 518  		pkg_emit_error("No such event pipe: %s", evpipe);
 519  		return;
 520  	}
 521  
 522  	if (!S_ISFIFO(st.st_mode) && !S_ISSOCK(st.st_mode)) {
 523  		pkg_emit_error("%s is not a fifo or socket", evpipe);
 524  		return;
 525  	}
 526  
 527  	if (S_ISFIFO(st.st_mode)) {
 528  		flag |= O_NONBLOCK;
 529  		if ((ctx.eventpipe = open(evpipe, flag)) == -1)
 530  			pkg_emit_errno("Open event pipe", evpipe);
 531  		return;
 532  	}
 533  
 534  	if (S_ISSOCK(st.st_mode)) {
 535  		if ((ctx.eventpipe = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
 536  			pkg_emit_errno("Open event pipe", evpipe);
 537  			return;
 538  		}
 539  		memset(&sock, 0, sizeof(struct sockaddr_un));
 540  		sock.sun_family = AF_UNIX;
 541  		if (strlcpy(sock.sun_path, evpipe, sizeof(sock.sun_path)) >=
 542  		    sizeof(sock.sun_path)) {
 543  			pkg_emit_error("Socket path too long: %s", evpipe);
 544  			close(ctx.eventpipe);
 545  			ctx.eventpipe = -1;
 546  			return;
 547  		}
 548  
 549  		if (connect(ctx.eventpipe, (struct sockaddr *)&sock, SUN_LEN(&sock)) == -1) {
 550  			pkg_emit_errno("Connect event pipe", evpipe);
 551  			close(ctx.eventpipe);
 552  			ctx.eventpipe = -1;
 553  			return;
 554  		}
 555  	}
 556  
 557  }
 558  
 559  const char *
 560  pkg_libversion(void)
 561  {
 562  	return PKGVERSION;
 563  }
 564  
 565  pkg_kvl_t *
 566  pkg_external_libs_version(void)
 567  {
 568  	pkg_kvl_t *kvl = xcalloc(1, sizeof(*kvl));
 569  
 570  	vec_push(kvl, pkg_kv_new("libarchive", archive_version_string()));
 571  	vec_push(kvl, pkg_kv_new("sqlite", sqlite3_libversion()));
 572  	vec_push(kvl, pkg_kv_new("openssl", OpenSSL_version(OPENSSL_VERSION)));
 573  
 574  	return (kvl);
 575  }
 576  
 577  
 578  int
 579  pkg_initialized(void)
 580  {
 581  	return (parsed);
 582  }
 583  
 584  const pkg_object *
 585  pkg_config_get(const char *key) {
 586  	return (ucl_object_find_key(config, key));
 587  }
 588  
 589  char *
 590  pkg_config_dump(void)
 591  {
 592  	return (pkg_object_dump(config));
 593  }
 594  
 595  static void
 596  disable_plugins_if_static(void)
 597  {
 598  	void *dlh;
 599  
 600  	dlh = dlopen(0, RTLD_NOW);
 601  
 602  	/* if dlh is NULL then we are in static binary */
 603  	if (dlh == NULL)
 604  		ucl_object_replace_key(config, ucl_object_frombool(false), "PKG_ENABLE_PLUGINS", 18, false);
 605  	else
 606  		dlclose(dlh);
 607  
 608  	return;
 609  }
 610  
 611  static void
 612  add_repo(const ucl_object_t *obj, struct pkg_repo *r, const char *rname, pkg_init_flags flags)
 613  {
 614  	const ucl_object_t *cur, *enabled, *env;
 615  	ucl_object_iter_t it = NULL;
 616  	struct pkg_kv *kv;
 617  	bool enable = true;
 618  	const char *url = NULL, *pubkey = NULL, *mirror_type = NULL;
 619  	const char *signature_type = NULL, *fingerprints = NULL;
 620  	const char *ssh_args = NULL;
 621  	const char *key;
 622  	const char *type = NULL;
 623  	int use_ipvx = 0;
 624  	int priority = 0;
 625  
 626  	dbg(1, "parsing repository object %s", rname);
 627  
 628  	env = NULL;
 629  	enabled = ucl_object_find_key(obj, "enabled");
 630  	if (enabled == NULL)
 631  		enabled = ucl_object_find_key(obj, "ENABLED");
 632  	if (enabled != NULL) {
 633  		enable = ucl_object_toboolean(enabled);
 634  		if (!enable && r != NULL) {
 635  			/*
 636  			 * We basically want to remove the existing repo r and
 637  			 * forget all stuff parsed
 638  			 */
 639  			dbg(1, "disabling repo %s", rname);
 640  			DL_DELETE(repos, r);
 641  			pkg_repo_free(r);
 642  			return;
 643  		}
 644  	}
 645  
 646  	while ((cur = ucl_iterate_object(obj, &it, true))) {
 647  		key = ucl_object_key(cur);
 648  		if (key == NULL)
 649  			continue;
 650  
 651  		if (STRIEQ(key, "url")) {
 652  			if (cur->type != UCL_STRING) {
 653  				pkg_emit_error("Expecting a string for the "
 654  				    "'%s' key of the '%s' repo",
 655  				    key, rname);
 656  				return;
 657  			}
 658  			url = ucl_object_tostring(cur);
 659  		} else if (STRIEQ(key, "pubkey")) {
 660  			if (cur->type != UCL_STRING) {
 661  				pkg_emit_error("Expecting a string for the "
 662  				    "'%s' key of the '%s' repo",
 663  				    key, rname);
 664  				return;
 665  			}
 666  			pubkey = ucl_object_tostring(cur);
 667  		} else if (STRIEQ(key, "mirror_type")) {
 668  			if (cur->type != UCL_STRING) {
 669  				pkg_emit_error("Expecting a string for the "
 670  				    "'%s' key of the '%s' repo",
 671  				    key, rname);
 672  				return;
 673  			}
 674  			mirror_type = ucl_object_tostring(cur);
 675  		} else if (STRIEQ(key, "signature_type")) {
 676  			if (cur->type != UCL_STRING) {
 677  				pkg_emit_error("Expecting a string for the "
 678  				    "'%s' key of the '%s' repo",
 679  				    key, rname);
 680  				return;
 681  			}
 682  			signature_type = ucl_object_tostring(cur);
 683  		} else if (STRIEQ(key, "fingerprints")) {
 684  			if (cur->type != UCL_STRING) {
 685  				pkg_emit_error("Expecting a string for the "
 686  				    "'%s' key of the '%s' repo",
 687  				    key, rname);
 688  				return;
 689  			}
 690  			fingerprints = ucl_object_tostring(cur);
 691  		} else if (STRIEQ(key, "type")) {
 692  			if (cur->type != UCL_STRING) {
 693  				pkg_emit_error("Expecting a string for the "
 694  					"'%s' key of the '%s' repo",
 695  					key, rname);
 696  				return;
 697  			}
 698  			type = ucl_object_tostring(cur);
 699  		} else if (STRIEQ(key, "ip_version")) {
 700  			if (cur->type != UCL_INT) {
 701  				pkg_emit_error("Expecting a integer for the "
 702  					"'%s' key of the '%s' repo",
 703  					key, rname);
 704  				return;
 705  			}
 706  			use_ipvx = ucl_object_toint(cur);
 707  			if (use_ipvx != 4 && use_ipvx != 6)
 708  				use_ipvx = 0;
 709  		} else if (STRIEQ(key, "priority")) {
 710  			if (cur->type != UCL_INT) {
 711  				pkg_emit_error("Expecting a integer for the "
 712  					"'%s' key of the '%s' repo",
 713  					key, rname);
 714  				return;
 715  			}
 716  			priority = ucl_object_toint(cur);
 717  		} else if (STRIEQ(key, "ssh_args")) {
 718  			if (cur->type != UCL_STRING) {
 719  				pkg_emit_error("Expecting a string for the "
 720  					"'%s' key of the '%s' repo",
 721  					key, rname);
 722  				return;
 723  			}
 724  			ssh_args = ucl_object_tostring(cur);
 725  		} else if (STRIEQ(key, "env")) {
 726  			if (cur->type != UCL_OBJECT) {
 727  				pkg_emit_error("Expecting an object for the "
 728  					"'%s' key of the '%s' repo",
 729  					key, rname);
 730  			}
 731  			env = cur;
 732  		}
 733  	}
 734  
 735  	if (r == NULL && url == NULL) {
 736  		dbg(1, "No repo and no url for %s", rname);
 737  		return;
 738  	}
 739  
 740  	if (r == NULL)
 741  		r = pkg_repo_new(rname, url, type);
 742  	else
 743  		pkg_repo_overwrite(r, rname, url, type);
 744  
 745  	if (signature_type != NULL) {
 746  		if (STRIEQ(signature_type, "pubkey"))
 747  			r->signature_type = SIG_PUBKEY;
 748  		else if (STRIEQ(signature_type, "fingerprints"))
 749  			r->signature_type = SIG_FINGERPRINT;
 750  		else
 751  			r->signature_type = SIG_NONE;
 752  	}
 753  
 754  
 755  	if (fingerprints != NULL) {
 756  		free(r->fingerprints);
 757  		r->fingerprints = xstrdup(fingerprints);
 758  	}
 759  
 760  	if (pubkey != NULL) {
 761  		free(r->pubkey);
 762  		r->pubkey = xstrdup(pubkey);
 763  	}
 764  
 765  	if (ssh_args != NULL) {
 766  		free(r->ssh_args);
 767  		r->ssh_args = xstrdup(ssh_args);
 768  	}
 769  
 770  	r->enable = enable;
 771  	r->priority = priority;
 772  
 773  	if (mirror_type != NULL) {
 774  		if (STRIEQ(mirror_type, "srv"))
 775  			r->mirror_type = SRV;
 776  		else if (STRIEQ(mirror_type, "http"))
 777  			r->mirror_type = HTTP;
 778  		else
 779  			r->mirror_type = NOMIRROR;
 780  	}
 781  
 782  	if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
 783  		use_ipvx = 4;
 784  	else if ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)
 785  		use_ipvx = 6;
 786  
 787  	if (use_ipvx != 4 && use_ipvx != 6)
 788  		use_ipvx = pkg_object_int(pkg_config_get("IP_VERSION"));
 789  
 790  	if (use_ipvx == 4)
 791  		r->ip = IPV4;
 792  	else if (use_ipvx == 6)
 793  		r->ip = IPV6;
 794  
 795  	if (env != NULL) {
 796  		it = NULL;
 797  		while ((cur = ucl_iterate_object(env, &it, true))) {
 798  			kv = pkg_kv_new(ucl_object_key(cur),
 799  			    ucl_object_tostring_forced(cur));
 800  			vec_push(&r->env, kv);
 801  		}
 802  	}
 803  }
 804  
 805  static void
 806  add_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
 807  {
 808  	struct pkg_repo *r;
 809  	const char *key;
 810  
 811  	key = ucl_object_key(obj);
 812  	dbg(1, "parsing repo key '%s' in file '%s'", key, file);
 813  	r = pkg_repo_find(key);
 814  	if (r != NULL)
 815  		dbg(1, "overwriting repository %s", key);
 816         add_repo(obj, r, key, flags);
 817  }
 818  
 819  static void
 820  walk_repo_obj(const ucl_object_t *obj, const char *file, pkg_init_flags flags)
 821  {
 822  	const ucl_object_t *cur;
 823  	ucl_object_iter_t it = NULL;
 824  	struct pkg_repo *r;
 825  	const char *key;
 826  	char *yaml;
 827  
 828  	while ((cur = ucl_iterate_object(obj, &it, true))) {
 829  		key = ucl_object_key(cur);
 830  		dbg(1, "parsing key '%s'", key);
 831  		r = pkg_repo_find(key);
 832  		if (r != NULL)
 833  			dbg(1, "overwriting repository %s", key);
 834  		if (cur->type == UCL_OBJECT)
 835  			add_repo(cur, r, key, flags);
 836  		else {
 837  			yaml = ucl_object_emit(cur, UCL_EMIT_YAML);
 838  			pkg_emit_error("Ignoring bad configuration entry in %s: %s",
 839  			    file, yaml);
 840  			free(yaml);
 841  		}
 842  	}
 843  }
 844  
 845  struct config_parser_vars {
 846  	char *abi;
 847  	char *altabi;
 848  	char *osversion;
 849  	char *release;
 850  	char *version_major;
 851  	char *version_minor;
 852  };
 853  
 854  /* Register parser variables based on ctx.abi.
 855   * The returned struct must be free'd with config_parser_variables_free()
 856   * after parsing is complete. */
 857  static struct config_parser_vars *
 858  config_parser_vars_register(struct ucl_parser *p)
 859  {
 860  	struct config_parser_vars *vars = xcalloc(1, sizeof(struct config_parser_vars));
 861  
 862  	vars->abi = pkg_abi_to_string(&ctx.abi);
 863  	ucl_parser_register_variable(p, "ABI", vars->abi);
 864  
 865  	char altabi_buffer[BUFSIZ];
 866  	pkg_arch_to_legacy(vars->abi, altabi_buffer, sizeof(altabi_buffer));
 867  	vars->altabi = xstrdup(altabi_buffer);
 868  	ucl_parser_register_variable(p, "ALTABI", vars->altabi);
 869  
 870  	if (ctx.abi.os == PKG_OS_FREEBSD) {
 871  		xasprintf(&vars->osversion, "%d",
 872  		    pkg_abi_get_freebsd_osversion(&ctx.abi));
 873  		ucl_parser_register_variable(p, "OSVERSION", vars->osversion);
 874  	}
 875  	ucl_parser_register_variable(p, "OSNAME", pkg_os_to_string(ctx.abi.os));
 876  
 877  	if (pkg_abi_string_only_major_version(ctx.abi.os)) {
 878  		xasprintf(&vars->release, "%d", ctx.abi.major);
 879  	} else {
 880  		xasprintf(&vars->release, "%d.%d", ctx.abi.major, ctx.abi.minor);
 881  	}
 882  	ucl_parser_register_variable(p, "RELEASE", vars->release);
 883  
 884  	xasprintf(&vars->version_major, "%d", ctx.abi.major);
 885  	ucl_parser_register_variable(p, "VERSION_MAJOR", vars->version_major);
 886  
 887  	xasprintf(&vars->version_minor, "%d", ctx.abi.minor);
 888  	ucl_parser_register_variable(p, "VERSION_MINOR", vars->version_minor);
 889  
 890  	ucl_parser_register_variable(p, "ARCH",
 891  	    pkg_arch_to_string(ctx.abi.os, ctx.abi.arch));
 892  
 893  	return vars;
 894  }
 895  
 896  static void
 897  config_parser_vars_free(struct config_parser_vars *vars)
 898  {
 899  	free(vars->abi);
 900  	free(vars->altabi);
 901  	free(vars->osversion);
 902  	free(vars->release);
 903  	free(vars->version_major);
 904  	free(vars->version_minor);
 905  	free(vars);
 906  }
 907  static void
 908  load_repo_file(int dfd, const char *repodir, const char *repofile,
 909      pkg_init_flags flags)
 910  {
 911  	struct ucl_parser *p;
 912  	ucl_object_t *obj = NULL;
 913  	int fd;
 914  
 915  	p = ucl_parser_new(0);
 916  
 917  	struct config_parser_vars *parser_vars = config_parser_vars_register(p);
 918  
 919  	errno = 0;
 920  	obj = NULL;
 921  
 922  	dbg(1, "loading %s/%s", repodir, repofile);
 923  	fd = openat(dfd, repofile, O_RDONLY);
 924  	if (fd == -1) {
 925  		pkg_errno("Unable to open '%s/%s'", repodir, repofile);
 926  		goto out_parser_vars;
 927  	}
 928  	if (!ucl_parser_add_fd(p, fd)) {
 929  		pkg_emit_error("Error parsing: '%s/%s': %s", repodir,
 930  		    repofile, ucl_parser_get_error(p));
 931  		goto out_fd;
 932  	}
 933  
 934  	obj = ucl_parser_get_object(p);
 935  	if (obj == NULL) {
 936  		goto out_fd;
 937  	}
 938  
 939  	if (obj->type == UCL_OBJECT)
 940  		walk_repo_obj(obj, repofile, flags);
 941  
 942  	ucl_object_unref(obj);
 943  out_fd:
 944  	close(fd);
 945  out_parser_vars:
 946  	ucl_parser_free(p);
 947  	config_parser_vars_free(parser_vars);
 948  }
 949  
 950  static int
 951  configfile(const struct dirent *dp)
 952  {
 953  	const char *p;
 954  	size_t n;
 955  
 956  	if (dp->d_name[0] == '.')
 957  		return (0);
 958  
 959  	n = strlen(dp->d_name);
 960  	if (n <= 5)
 961  		return (0);
 962  
 963  	p = &dp->d_name[n - 5];
 964  	if (!STREQ(p, ".conf"))
 965  		return (0);
 966  	return (1);
 967  }
 968  
 969  static void
 970  load_repo_files(const char *repodir, pkg_init_flags flags)
 971  {
 972  	struct dirent **ent;
 973  	int nents, i, fd;
 974  
 975  	dbg(1, "loading repositories in %s", repodir);
 976  	if ((fd = open(repodir, O_DIRECTORY|O_CLOEXEC)) == -1)
 977  		return;
 978  
 979  	nents = scandir(repodir, &ent, configfile, alphasort);
 980  	for (i = 0; i < nents; i++) {
 981  		load_repo_file(fd, repodir, ent[i]->d_name, flags);
 982  		free(ent[i]);
 983  	}
 984  	if (nents >= 0)
 985  		free(ent);
 986  	close(fd);
 987  }
 988  
 989  static void
 990  load_repositories(const char *repodir, pkg_init_flags flags)
 991  {
 992  	const pkg_object *reposlist, *cur;
 993  	pkg_iter it = NULL;
 994  
 995  	if (repodir != NULL) {
 996  		load_repo_files(repodir, flags);
 997  		return;
 998  	}
 999  
1000  	reposlist = pkg_config_get("REPOS_DIR");
1001  	while ((cur = pkg_object_iterate(reposlist, &it)))
1002  		load_repo_files(pkg_object_string(cur), flags);
1003  }
1004  
1005  bool
1006  pkg_compiled_for_same_os_major(void)
1007  {
1008  #ifdef OSMAJOR
1009  	if (getenv("IGNORE_OSMAJOR") != NULL)
1010  		return (true);
1011  
1012  	return (ctx.abi.major == OSMAJOR);
1013  #else
1014  	return (true);		/* Can't tell, so assume yes  */
1015  #endif
1016  }
1017  
1018  
1019  int
1020  pkg_init(const char *path, const char *reposdir)
1021  {
1022  	return (pkg_ini(path, reposdir, 0));
1023  }
1024  
1025  static const char *
1026  type_to_string(int type)
1027  {
1028  	if (type == UCL_ARRAY)
1029  		return ("array");
1030  	if (type == UCL_OBJECT)
1031  		return ("object");
1032  	if (type == UCL_STRING)
1033  		return ("string");
1034  	if (type == UCL_INT)
1035  		return ("integer");
1036  	if (type == UCL_BOOLEAN)
1037  		return ("boolean");
1038  	return ("unknown");
1039  }
1040  
1041  static const struct pkg_dbg_flags *
1042  _find_flag(const char *str)
1043  {
1044  	for (size_t i = 0; i < NELEM(debug_flags); i++) {
1045  		if (STRIEQ(debug_flags[i].name, str))
1046  			return (&debug_flags[i]);
1047  	}
1048  	return (NULL);
1049  }
1050  static uint64_t
1051  config_validate_debug_flags(const ucl_object_t *o)
1052  {
1053  	ucl_object_iter_t it = NULL;
1054  	const ucl_object_t *cur;
1055  	int ret = EPKG_OK;
1056  	const struct pkg_dbg_flags *f;
1057  
1058  	if (o == NULL)
1059  		return (ret);
1060  
1061  	while ((cur = ucl_iterate_object(o, &it, true))) {
1062  		const char *str = ucl_object_tostring(cur);
1063  		f = _find_flag(str);
1064  		if (f == NULL) {
1065  			pkg_emit_error("Invalid debug flag %s",
1066  			    ucl_object_tostring(cur));
1067  			ret = EPKG_FATAL;
1068  			continue;
1069  		}
1070  		ctx.debug_flags |= f->flag;
1071  	}
1072  	return (ret);
1073  }
1074  
1075  static bool
1076  config_validate_shlib_provide_paths(void) {
1077  	const char *config_options[] = {
1078  		"SHLIB_PROVIDE_PATHS_NATIVE",
1079  		"SHLIB_PROVIDE_PATHS_COMPAT_32",
1080  		"SHLIB_PROVIDE_PATHS_COMPAT_LINUX",
1081  		"SHLIB_PROVIDE_PATHS_COMPAT_LINUX_32",
1082  		NULL,
1083  	};
1084  	bool valid = true;
1085  	for (const char **option = config_options; *option != NULL; option++) {
1086  		const ucl_object_t *paths = pkg_config_get(*option);
1087  		const ucl_object_t *cur;
1088  		ucl_object_iter_t it = NULL;
1089  		while ((cur = ucl_object_iterate(paths, &it, true))) {
1090  			const char *path = ucl_object_tostring(cur);
1091  			if (path[0] != '/') {
1092  				pkg_emit_error("Invalid value for config option %s, "
1093  				    "'%s' is not an absolute path.",
1094  				    *option, path);
1095  				valid = false;
1096  			}
1097  		}
1098  	}
1099  	return valid;
1100  }
1101  
1102  /* Parses ABI_FILE, ABI, ALTABI, and OSVERSION from the given ucl file and sets
1103   * the values in the environment. These values must be parsed separately from
1104   * the rest of the config because they are made available as variable expansions
1105   * when parsing the rest of the config (See config_parser_vars_register()). */
1106  static void
1107  config_parse_abi_options(int conffd)
1108  {
1109  	if (conffd < 0) {
1110  		return;
1111  	}
1112  
1113  	struct ucl_parser *p = ucl_parser_new(0);
1114  
1115  	if (!ucl_parser_add_fd(p, conffd)) {
1116  		pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
1117  	}
1118  
1119  	ucl_object_t *obj = ucl_parser_get_object(p);
1120  
1121  	ucl_object_iter_t it = NULL;
1122  	const ucl_object_t *cur;
1123  	xstring *ukey = NULL;
1124  	while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
1125  		xstring_renew(ukey);
1126  		const char *key = ucl_object_key(cur);
1127  		for (size_t i = 0; key[i] != '\0'; i++)
1128  			fputc(toupper(key[i]), ukey->fp);
1129  		fflush(ukey->fp);
1130  
1131  		if (STREQ(ukey->buf, "ABI_FILE") ||
1132  		    STREQ(ukey->buf, "ABI") ||
1133  		    STREQ(ukey->buf, "ALTABI")) {
1134  			if (cur->type == UCL_STRING) {
1135  				/* Don't overwrite the value already set on the
1136  				   command line or in the environment */
1137  				setenv(ukey->buf, ucl_object_tostring(cur), 0);
1138  			} else {
1139  				pkg_emit_error("Malformed key %s, got '%s' expecting "
1140  				    "'string', ignoring", key,
1141  				    type_to_string(cur->type));
1142  			}
1143  		} else if (STREQ(ukey->buf, "OSVERSION")) {
1144  			if (cur->type == UCL_INT) {
1145  				int64_t osversion = ucl_object_toint(cur);
1146  				char *str_osversion;
1147  				xasprintf(&str_osversion, "%" PRIi64, osversion);
1148  				/* Don't overwrite the value already set on the
1149  				   command line or in the environment */
1150  				setenv(ukey->buf, str_osversion, 0);
1151  				free(str_osversion);
1152  			} else {
1153  				pkg_emit_error("Malformed key %s, got '%s' expecting "
1154  				    "'integer', ignoring", key,
1155  				    type_to_string(cur->type));
1156  			}
1157  
1158  
1159  		}
1160  	}
1161  
1162  	ucl_object_unref(obj);
1163  	ucl_parser_free(p);
1164  }
1165  
1166  static bool
1167  config_init_abi(struct pkg_abi *abi)
1168  {
1169  	if (getenv("ALTABI") != NULL) {
1170  		pkg_emit_error("Setting ALTABI manually is no longer supported, "
1171  		    "set ABI and OSVERSION or ABI_FILE instead.");
1172  	}
1173  
1174  	const char *env_abi_file = getenv("ABI_FILE");
1175  	const char *env_abi_string = getenv("ABI");
1176  	const char *env_osversion_string = getenv("OSVERSION");
1177  
1178  	if (env_abi_file != NULL && env_abi_string != NULL) {
1179  		pkg_emit_error("Both ABI_FILE and ABI are set, ABI_FILE overrides ABI");
1180  	}
1181  
1182  	if (env_abi_file != NULL && env_osversion_string != NULL) {
1183  		pkg_emit_error("Both ABI_FILE and OSVERSION are set, ABI_FILE overrides OSVERSION");
1184  	}
1185  
1186  	if (env_abi_string != NULL) {
1187  		if (!pkg_abi_from_string(abi, env_abi_string)) {
1188  			return (false);
1189  		}
1190  
1191  		if (abi->os == PKG_OS_FREEBSD) {
1192  			if (env_osversion_string == NULL) {
1193  				pkg_emit_error("Setting ABI requires setting OSVERSION, guessing the OSVERSION as: %d",
1194  				    pkg_abi_get_freebsd_osversion(abi));
1195  				return (true);
1196  			}
1197  
1198  			const char *errstr = NULL;
1199  			int env_osversion = strtonum(env_osversion_string, 1, INT_MAX, &errstr);
1200  			if (errstr != NULL) {
1201  				pkg_emit_error("Invalid OSVERSION %s, %s", env_osversion_string, errstr);
1202  				return (false);
1203  			}
1204  
1205  			pkg_abi_set_freebsd_osversion(abi, env_osversion);
1206  		} else {
1207  			if (env_osversion_string != NULL) {
1208  				pkg_emit_notice("OSVERSION is ignored on %s",
1209  				    pkg_os_to_string(abi->os));
1210  			}
1211  		}
1212  	} else {
1213  		if (env_osversion_string != NULL) {
1214  			dbg(1, "Setting OSVERSION requires setting ABI as well (ignoring)");
1215  			unsetenv("OSVERSION");
1216  		}
1217  		if (pkg_abi_from_file(abi) != EPKG_OK) {
1218  			return (false);
1219  		}
1220  	}
1221  
1222  	return (true);
1223  }
1224  
1225  int
1226  pkg_ini(const char *path, const char *reposdir, pkg_init_flags flags)
1227  {
1228  	struct ucl_parser *p = NULL;
1229  	size_t i;
1230  	const char *val = NULL;
1231  	const char *buf, *walk, *value, *key, *k;
1232  	const char *evkey = NULL;
1233  	const char *nsname = NULL;
1234  	const char *useragent = NULL;
1235  	const char *evpipe = NULL;
1236  	const char *url;
1237  	struct pkg_repo *repo = NULL;
1238  	const ucl_object_t *cur, *object;
1239  	ucl_object_t *obj = NULL, *o, *ncfg;
1240  	ucl_object_iter_t it = NULL;
1241  	xstring *ukey = NULL;
1242  	bool fatal_errors = false;
1243  	int conffd = -1;
1244  	char *tmp = NULL;
1245  	size_t ukeylen;
1246  	int err = EPKG_OK;
1247  
1248  	k = NULL;
1249  	o = NULL;
1250  	if (ctx.rootfd == -1 && (ctx.rootfd = open("/", O_DIRECTORY|O_RDONLY|O_CLOEXEC)) < 0) {
1251  		pkg_emit_error("Unable to open /");
1252  		return (EPKG_FATAL);
1253  	}
1254  
1255  	if (parsed != false) {
1256  		pkg_emit_error("pkg_init() must only be called once");
1257  		return (EPKG_FATAL);
1258  	}
1259  
1260  	if (path == NULL)
1261  		conffd = openat(ctx.rootfd, &PREFIX"/etc/pkg.conf"[1], 0);
1262  	else
1263  		conffd = open(path, O_RDONLY);
1264  	if (conffd == -1 && errno != ENOENT) {
1265  		pkg_errno("Cannot open %s/%s",
1266  		    ctx.pkg_rootdir != NULL ? ctx.pkg_rootdir : "",
1267  		    path);
1268  	}
1269  
1270  	config_parse_abi_options(conffd);
1271  	if (!config_init_abi(&ctx.abi)) {
1272  		return (EPKG_FATAL);
1273  	}
1274  
1275  	if (((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4) &&
1276  	    ((flags & PKG_INIT_FLAG_USE_IPV6) == PKG_INIT_FLAG_USE_IPV6)) {
1277  		pkg_emit_error("Invalid flags for pkg_init()");
1278  		return (EPKG_FATAL);
1279  	}
1280  	if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
1281  		ctx.ip = IPV4;
1282  	if ((flags & PKG_INIT_FLAG_USE_IPV4) == PKG_INIT_FLAG_USE_IPV4)
1283  		ctx.ip = IPV6;
1284  
1285  	config = ucl_object_typed_new(UCL_OBJECT);
1286  
1287  	for (i = 0; i < c_size; i++) {
1288  		switch (c[i].type) {
1289  		case PKG_STRING:
1290  			tmp = NULL;
1291  			if (c[i].def != NULL && c[i].def[0] == '/' &&
1292  			    ctx.pkg_rootdir != NULL) {
1293  				xasprintf(&tmp, "%s%s", ctx.pkg_rootdir, c[i].def);
1294  			}
1295  			obj = ucl_object_fromstring_common(
1296  			    c[i].def != NULL ? tmp != NULL ? tmp : c[i].def : "", 0, UCL_STRING_TRIM);
1297  			free(tmp);
1298  			ucl_object_insert_key(config, obj,
1299  			    c[i].key, strlen(c[i].key), false);
1300  			break;
1301  		case PKG_INT:
1302  			ucl_object_insert_key(config,
1303  			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_INT),
1304  			    c[i].key, strlen(c[i].key), false);
1305  			break;
1306  		case PKG_BOOL:
1307  			ucl_object_insert_key(config,
1308  			    ucl_object_fromstring_common(c[i].def, 0, UCL_STRING_PARSE_BOOLEAN),
1309  			    c[i].key, strlen(c[i].key), false);
1310  			break;
1311  		case PKG_OBJECT:
1312  			obj = ucl_object_typed_new(UCL_OBJECT);
1313  			if (c[i].def != NULL) {
1314  				walk = buf = c[i].def;
1315  				while ((buf = strchr(buf, ',')) != NULL) {
1316  					key = walk;
1317  					value = walk;
1318  					while (*value != ',') {
1319  						if (*value == '=')
1320  							break;
1321  						value++;
1322  					}
1323  					ucl_object_insert_key(obj,
1324  					    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
1325  					    key, value - key, false);
1326  					buf++;
1327  					walk = buf;
1328  				}
1329  				key = walk;
1330  				value = walk;
1331  				while (*value != ',') {
1332  					if (*value == '=')
1333  						break;
1334  					value++;
1335  				}
1336  				if (o == NULL)
1337  					o = ucl_object_typed_new(UCL_OBJECT);
1338  				ucl_object_insert_key(o,
1339  				    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
1340  				    key, value - key, false);
1341  			}
1342  			ucl_object_insert_key(config, obj,
1343  			    c[i].key, strlen(c[i].key), false);
1344  			break;
1345  		case PKG_ARRAY:
1346  			obj = ucl_object_typed_new(UCL_ARRAY);
1347  			if (c[i].def != NULL) {
1348  				walk = buf = c[i].def;
1349  				while ((buf = strchr(buf, ',')) != NULL) {
1350  					ucl_array_append(obj,
1351  					    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
1352  					buf++;
1353  					walk = buf;
1354  				}
1355  				ucl_array_append(obj,
1356  				    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
1357  			}
1358  			ucl_object_insert_key(config, obj,
1359  			    c[i].key, strlen(c[i].key), false);
1360  			break;
1361  		}
1362  	}
1363  
1364  	p = ucl_parser_new(0);
1365  
1366  	struct config_parser_vars *parser_vars = config_parser_vars_register(p);
1367  
1368  	errno = 0;
1369  	obj = NULL;
1370  	if (conffd != -1) {
1371  		if (!ucl_parser_add_fd(p, conffd)) {
1372  			pkg_emit_error("Invalid configuration file: %s", ucl_parser_get_error(p));
1373  		}
1374  		close(conffd);
1375  	}
1376  
1377  	obj = ucl_parser_get_object(p);
1378  	ncfg = NULL;
1379  	ukey = NULL;
1380  	while (obj != NULL && (cur = ucl_iterate_object(obj, &it, true))) {
1381  		xstring_renew(ukey);
1382  		key = ucl_object_key(cur);
1383  		for (i = 0; key[i] != '\0'; i++)
1384  			fputc(toupper(key[i]), ukey->fp);
1385  		fflush(ukey->fp);
1386  		ukeylen = strlen(ukey->buf);
1387  		object = ucl_object_find_keyl(config, ukey->buf, ukeylen);
1388  
1389  		if (STREQ(ukey->buf, "PACKAGESITE") ||
1390  		    STREQ(ukey->buf, "PUBKEY") ||
1391  		    STREQ(ukey->buf, "MIRROR_TYPE")) {
1392  			pkg_emit_error("%s in pkg.conf is no longer "
1393  			    "supported.  Convert to the new repository style."
1394  			    "  See pkg.conf(5)", ukey->buf);
1395  			fatal_errors = true;
1396  			continue;
1397  		}
1398  
1399  		if (STREQ(ukey->buf, "ABI_FILE") ||
1400  		    STREQ(ukey->buf, "ABI") ||
1401  		    STREQ(ukey->buf, "ALTABI") ||
1402  		    STREQ(ukey->buf, "OSVERSION")) {
1403  			continue; /* Already parsed in config_parse_abi_options() */
1404  		}
1405  
1406  		/* ignore unknown keys */
1407  		if (object == NULL)
1408  			continue;
1409  
1410  		if (object->type != cur->type) {
1411  			pkg_emit_error("Malformed key %s, got '%s' expecting "
1412  			    "'%s', ignoring", key,
1413  			    type_to_string(cur->type),
1414  			    type_to_string(object->type));
1415  			continue;
1416  		}
1417  
1418  		if (ncfg == NULL)
1419  			ncfg = ucl_object_typed_new(UCL_OBJECT);
1420  		ucl_object_insert_key(ncfg, ucl_object_copy(cur), ukey->buf,
1421  		    ukeylen, true);
1422  	}
1423  	xstring_free(ukey);
1424  
1425  	if (fatal_errors) {
1426  		ucl_object_unref(ncfg);
1427  		ucl_parser_free(p);
1428  		err = EPKG_FATAL;
1429  		goto out;
1430  	}
1431  
1432  	if (ncfg != NULL) {
1433  		it = NULL;
1434  		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
1435  			key = ucl_object_key(cur);
1436  			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
1437  		}
1438  	}
1439  	ncfg = NULL;
1440  	it = NULL;
1441  	while ((cur = ucl_iterate_object(config, &it, true))) {
1442  		o = NULL;
1443  		key = ucl_object_key(cur);
1444  		val = getenv(key);
1445  		if (val == NULL)
1446  			continue;
1447  		switch (cur->type) {
1448  		case UCL_STRING:
1449  			o = ucl_object_fromstring_common(val, 0, UCL_STRING_TRIM);
1450  			break;
1451  		case UCL_INT:
1452  			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_INT);
1453  			if (o->type != UCL_INT) {
1454  				pkg_emit_error("Invalid type for environment "
1455  				    "variable %s, got %s, while expecting an integer",
1456  				    key, val);
1457  				ucl_object_unref(o);
1458  				continue;
1459  			}
1460  			break;
1461  		case UCL_BOOLEAN:
1462  			o = ucl_object_fromstring_common(val, 0, UCL_STRING_PARSE_BOOLEAN);
1463  			if (o->type != UCL_BOOLEAN) {
1464  				pkg_emit_error("Invalid type for environment "
1465  				    "variable %s, got %s, while expecting a boolean",
1466  				    key, val);
1467  				ucl_object_unref(o);
1468  				continue;
1469  			}
1470  			break;
1471  		case UCL_OBJECT:
1472  			o = ucl_object_typed_new(UCL_OBJECT);
1473  			walk = buf = val;
1474  			while ((buf = strchr(buf, ',')) != NULL) {
1475  				k = walk;
1476  				value = walk;
1477  				while (*value != ',') {
1478  					if (*value == '=')
1479  						break;
1480  					value++;
1481  				}
1482  				ucl_object_insert_key(o,
1483  				    ucl_object_fromstring_common(value + 1, buf - value - 1, UCL_STRING_TRIM),
1484  				    k, value - k, false);
1485  				buf++;
1486  				walk = buf;
1487  			}
1488  			k = walk;
1489  			value = walk;
1490  			while (*value != '\0') {
1491  				if (*value == '=')
1492  					break;
1493  				value++;
1494  			}
1495  			ucl_object_insert_key(o,
1496  			    ucl_object_fromstring_common(value + 1, strlen(value + 1), UCL_STRING_TRIM),
1497  			    k, value - k, false);
1498  			break;
1499  		case UCL_ARRAY:
1500  			o = ucl_object_typed_new(UCL_ARRAY);
1501  			walk = buf = val;
1502  			while ((buf = strchr(buf, ',')) != NULL) {
1503  				ucl_array_append(o,
1504  				    ucl_object_fromstring_common(walk, buf - walk, UCL_STRING_TRIM));
1505  				buf++;
1506  				walk = buf;
1507  			}
1508  			ucl_array_append(o,
1509  			    ucl_object_fromstring_common(walk, strlen(walk), UCL_STRING_TRIM));
1510  			break;
1511  		default:
1512  			/* ignore other types */
1513  			break;
1514  		}
1515  		if (o != NULL) {
1516  			if (ncfg == NULL)
1517  				ncfg = ucl_object_typed_new(UCL_OBJECT);
1518  			ucl_object_insert_key(ncfg, o, key, strlen(key), true);
1519  		}
1520  	}
1521  
1522  	if (ncfg != NULL) {
1523  		it = NULL;
1524  		while (( cur = ucl_iterate_object(ncfg, &it, true))) {
1525  			key = ucl_object_key(cur);
1526  			ucl_object_replace_key(config, ucl_object_ref(cur), key, strlen(key), true);
1527  		}
1528  		ucl_object_unref(ncfg);
1529  	}
1530  
1531  	disable_plugins_if_static();
1532  
1533  	parsed = true;
1534  	ucl_object_unref(obj);
1535  	ucl_parser_free(p);
1536  
1537  	if (!config_validate_shlib_provide_paths()) {
1538  		err = EPKG_FATAL;
1539  		goto out;
1540  	}
1541  
1542  	{
1543  		/* Even though we no longer support setting ABI/ALTABI/OSVERSION
1544  		   in the pkg.conf config file, we still need to expose these
1545  		   values through e.g. `pkg config ABI`. */
1546  		char *abi_string = pkg_abi_to_string(&ctx.abi);
1547  		char altabi_string[BUFSIZ];
1548  		pkg_arch_to_legacy(abi_string, altabi_string, sizeof(altabi_string));
1549  
1550  		ucl_object_insert_key(config,
1551  		    ucl_object_fromstring(abi_string), "ABI", 0, true);
1552  		ucl_object_insert_key(config,
1553  		    ucl_object_fromstring(altabi_string), "ALTABI", 0, true);
1554  
1555  		free(abi_string);
1556  
1557  		if (ctx.abi.os == PKG_OS_FREEBSD) {
1558  			char *osversion;
1559  			xasprintf(&osversion, "%d", pkg_abi_get_freebsd_osversion(&ctx.abi));
1560  			ucl_object_insert_key(config,
1561  			    ucl_object_fromstring(osversion), "OSVERSION", 0, true);
1562  			free(osversion);
1563  		}
1564  	}
1565  
1566  	dbg(1, "pkg initialized");
1567  
1568  	/* Start the event pipe */
1569  	evpipe = pkg_object_string(pkg_config_get("EVENT_PIPE"));
1570  	if (evpipe != NULL)
1571  		connect_evpipe(evpipe);
1572  
1573  	ctx.debug_level = pkg_object_int(pkg_config_get("DEBUG_LEVEL"));
1574  	err = config_validate_debug_flags(ucl_object_find_key(config, "PKG_DEBUG_FLAGS"));
1575  	if (err != EPKG_OK)
1576  		goto out;
1577  	ctx.developer_mode = pkg_object_bool(pkg_config_get("DEVELOPER_MODE"));
1578  	ctx.metalog = pkg_object_string(pkg_config_get("METALOG"));
1579  	ctx.dbdir = pkg_object_string(pkg_config_get("PKG_DBDIR"));
1580  	ctx.cachedir = pkg_object_string(pkg_config_get("PKG_CACHEDIR"));
1581  	ctx.backup_libraries = pkg_object_bool(pkg_config_get("BACKUP_LIBRARIES"));
1582  	ctx.backup_library_path = pkg_object_string(pkg_config_get("BACKUP_LIBRARY_PATH"));
1583  	ctx.triggers = pkg_object_bool(pkg_config_get("PKG_TRIGGERS_ENABLE"));
1584  	ctx.compression_format = pkg_object_string(pkg_config_get("COMPRESSION_FORMAT"));
1585  	ctx.compression_level = pkg_object_int(pkg_config_get("COMPRESSION_LEVEL"));
1586  	ctx.compression_threads = pkg_object_int(pkg_config_get("COMPRESSION_THREADS"));
1587  	ctx.repo_accept_legacy_pkg = pkg_object_bool(pkg_config_get("REPO_ACCEPT_LEGACY_PKG"));
1588  	ctx.no_version_for_deps = (getenv("PKG_NO_VERSION_FOR_DEPS") != NULL);
1589  	ctx.track_linux_compat_shlibs = pkg_object_bool(pkg_config_get("TRACK_LINUX_COMPAT_SHLIBS"));
1590          ctx.case_sensitive = pkg_object_bool(pkg_config_get("CASE_SENSITIVE_MATCH"));
1591  
1592  	it = NULL;
1593  	object = ucl_object_find_key(config, "PKG_ENV");
1594  	while ((cur = ucl_iterate_object(object, &it, true))) {
1595  		evkey = ucl_object_key(cur);
1596  		dbg(1, "Setting env var: %s", evkey);
1597  		if (evkey != NULL && evkey[0] != '\0')
1598  			setenv(evkey, ucl_object_tostring_forced(cur), 1);
1599  	}
1600  
1601  	/* Set user-agent */
1602  	useragent = pkg_object_string(pkg_config_get("HTTP_USER_AGENT"));
1603  	if (useragent != NULL)
1604  		setenv("HTTP_USER_AGENT", useragent, 1);
1605  	else
1606  		setenv("HTTP_USER_AGENT", "pkg/"PKGVERSION, 1);
1607  
1608  	/* load the repositories */
1609  	load_repositories(reposdir, flags);
1610  
1611  	object = ucl_object_find_key(config, "REPOSITORIES");
1612  	while ((cur = ucl_iterate_object(object, &it, true))) {
1613  		add_repo_obj(cur, path, flags);
1614  	}
1615  
1616  	/* validate the different scheme */
1617  	while (pkg_repos(&repo) == EPKG_OK) {
1618  		object = ucl_object_find_key(config, "VALID_URL_SCHEME");
1619  		url = pkg_repo_url(repo);
1620  		buf = strstr(url, ":/");
1621  		if (buf == NULL) {
1622  			pkg_emit_error("invalid url: %s", url);
1623  			err = EPKG_FATAL;
1624  			goto out;
1625  		}
1626  		fatal_errors = true;
1627  		it = NULL;
1628  		while ((cur = ucl_iterate_object(object, &it, true))) {
1629  			if (strncmp(url, ucl_object_tostring_forced(cur),
1630  			    buf - url) == 0) {
1631  				fatal_errors = false;
1632  				break;
1633  			}
1634  		}
1635  
1636  		if (fatal_errors) {
1637  			pkg_emit_error("invalid scheme %.*s", (int)(buf - url), url);
1638  			err = EPKG_FATAL;
1639  			goto out;
1640  		}
1641  	}
1642  
1643  	/* bypass resolv.conf with specified NAMESERVER if any */
1644  	nsname = pkg_object_string(pkg_config_get("NAMESERVER"));
1645  	if (nsname != NULL && set_nameserver(nsname) != 0)
1646  			pkg_emit_error("Unable to set nameserver, ignoring");
1647  
1648  	/* Open metalog */
1649  	if (ctx.metalog != NULL && metalog_open(ctx.metalog) != EPKG_OK) {
1650  		err = EPKG_FATAL;
1651  		goto out;
1652  	}
1653  
1654  out:
1655  	config_parser_vars_free(parser_vars);
1656  
1657  	return err;
1658  }
1659  
1660  static struct pkg_repo_ops*
1661  pkg_repo_find_type(const char *type)
1662  {
1663  	struct pkg_repo_ops *found = NULL, **cur;
1664  
1665  	/* Default repo type */
1666  	if (type == NULL)
1667  		return (pkg_repo_find_type("binary"));
1668  
1669  	cur = &repos_ops[0];
1670  	while (*cur != NULL) {
1671  		if (STRIEQ(type, (*cur)->type)) {
1672  			found = *cur;
1673  		}
1674  		cur ++;
1675  	}
1676  
1677  	if (found == NULL)
1678  		return (pkg_repo_find_type("binary"));
1679  
1680  	return (found);
1681  }
1682  
1683  static struct pkg_repo *
1684  pkg_repo_new(const char *name, const char *url, const char *type)
1685  {
1686  	struct pkg_repo *r;
1687  
1688  	r = xcalloc(1, sizeof(struct pkg_repo));
1689  	r->dfd = -1;
1690  	r->ops = pkg_repo_find_type(type);
1691  	r->url = xstrdup(url);
1692  	r->signature_type = SIG_NONE;
1693  	r->mirror_type = NOMIRROR;
1694  	r->enable = true;
1695  	r->meta = pkg_repo_meta_default();
1696  	r->name = xstrdup(name);
1697  	DL_APPEND(repos, r);
1698  
1699  	return (r);
1700  }
1701  
1702  static void
1703  pkg_repo_overwrite(struct pkg_repo *r, const char *name, const char *url,
1704      const char *type)
1705  {
1706  
1707  	free(r->name);
1708  	r->name = xstrdup(name);
1709  	if (url != NULL) {
1710  		free(r->url);
1711  		r->url = xstrdup(url);
1712  	}
1713  	r->ops = pkg_repo_find_type(type);
1714  }
1715  
1716  static void
1717  pkg_repo_free(struct pkg_repo *r)
1718  {
1719  	free(r->url);
1720  	free(r->name);
1721  	free(r->pubkey);
1722  	free(r->fingerprints);
1723  	free(r->ssh_args);
1724  	pkg_repo_meta_free(r->meta);
1725  	if (r->fetcher != NULL && r->fetcher->cleanup != NULL)
1726  		r->fetcher->cleanup(r);
1727  	vec_free_and_free(&r->env, pkg_kv_free);
1728  	free(r->dbpath);
1729  	free(r);
1730  }
1731  
1732  void
1733  pkg_shutdown(void)
1734  {
1735  	if (!parsed) {
1736  		pkg_emit_error("pkg_shutdown() must be called after pkg_init()");
1737  		_exit(EXIT_FAILURE);
1738  		/* NOTREACHED */
1739  	}
1740  
1741  	metalog_close();
1742  	ucl_object_unref(config);
1743  	LL_FREE(repos, pkg_repo_free);
1744  
1745  	if (ctx.rootfd != -1) {
1746  		close(ctx.rootfd);
1747  		ctx.rootfd = -1;
1748  	}
1749  	if (ctx.cachedirfd != -1) {
1750  		close(ctx.cachedirfd);
1751  		ctx.cachedirfd = -1;
1752  	}
1753  	if (ctx.pkg_dbdirfd != -1) {
1754  		close(ctx.pkg_dbdirfd);
1755  		ctx.pkg_dbdirfd = -1;
1756  	}
1757  
1758  	parsed = false;
1759  
1760  	return;
1761  }
1762  
1763  int
1764  pkg_repos_total_count(void)
1765  {
1766  	int cnt = 0;
1767  	struct pkg_repo *r;
1768  
1769  	LL_COUNT(repos, r, cnt);
1770  	return (cnt);
1771  }
1772  
1773  int
1774  pkg_repos_activated_count(void)
1775  {
1776  	struct pkg_repo *r = NULL;
1777  	int count = 0;
1778  
1779  	LL_FOREACH(repos, r) {
1780  		if (r->enable)
1781  			count++;
1782  	}
1783  
1784  	return (count);
1785  }
1786  
1787  int
1788  pkg_repos(struct pkg_repo **r)
1789  {
1790  	if (*r == NULL)
1791  		*r = repos;
1792  	else
1793  		*r = (*r)->next;
1794  	if (*r == NULL)
1795  		return (EPKG_END);
1796  	return (EPKG_OK);
1797  }
1798  
1799  const char *
1800  pkg_repo_url(struct pkg_repo *r)
1801  {
1802  	return (r->url);
1803  }
1804  
1805  /* The basename of the sqlite DB file and the database name */
1806  const char *
1807  pkg_repo_name(struct pkg_repo *r)
1808  {
1809  	return (r->name);
1810  }
1811  
1812  const char *
1813  pkg_repo_key(struct pkg_repo *r)
1814  {
1815  	return (r->pubkey);
1816  }
1817  
1818  const char *
1819  pkg_repo_fingerprints(struct pkg_repo *r)
1820  {
1821  	return (r->fingerprints);
1822  }
1823  
1824  const char *
1825  pkg_repo_ssh_args(struct pkg_repo *r)
1826  {
1827  	return (r->ssh_args);
1828  }
1829  
1830  signature_t
1831  pkg_repo_signature_type(struct pkg_repo *r)
1832  {
1833  	return (r->signature_type);
1834  }
1835  
1836  bool
1837  pkg_repo_enabled(struct pkg_repo *r)
1838  {
1839  	return (r->enable);
1840  }
1841  
1842  mirror_t
1843  pkg_repo_mirror_type(struct pkg_repo *r)
1844  {
1845  	return (r->mirror_type);
1846  }
1847  
1848  int
1849  pkg_repo_priority(struct pkg_repo *r)
1850  {
1851  	return (r->priority);
1852  }
1853  
1854  unsigned int
1855  pkg_repo_ip_version(struct pkg_repo *r)
1856  {
1857  	if (r->ip == IPV4)
1858  		return 4;
1859  	if (r->ip == IPV6)
1860  		return 6;
1861  	return 0;
1862  }
1863  
1864  /* Locate the repo by the file basename / database name */
1865  struct pkg_repo *
1866  pkg_repo_find(const char *reponame)
1867  {
1868  	struct pkg_repo *r;
1869  
1870  	LL_FOREACH(repos, r) {
1871  		if (STREQ(r->name, reponame))
1872  			return (r);
1873  	}
1874  	return (NULL);
1875  }
1876  
1877  int64_t
1878  pkg_set_debug_level(int64_t new_debug_level) {
1879  	int64_t old_debug_level = ctx.debug_level;
1880  
1881  	ctx.debug_level = new_debug_level;
1882  	return old_debug_level;
1883  }
1884  
1885  int
1886  pkg_set_ignore_osversion(bool ignore) {
1887  	if (pkg_initialized())
1888  		return (EPKG_FATAL);
1889  
1890  	ucl_object_insert_key(config,
1891  		ucl_object_frombool(ignore),
1892  		"IGNORE_OSVERSION", sizeof("IGNORE_OSVERSION"), false);
1893  
1894  	return (EPKG_OK);
1895  }
1896  
1897  int
1898  pkg_set_rootdir(const char *rootdir) {
1899  	if (pkg_initialized())
1900  		return (EPKG_FATAL);
1901  
1902  	if (ctx.rootfd != -1)
1903  		close(ctx.rootfd);
1904  
1905  	if ((ctx.rootfd = open(rootdir, O_DIRECTORY|O_RDONLY|O_CLOEXEC)) < 0) {
1906  		pkg_emit_error("Unable to open %s", rootdir);
1907  		return (EPKG_FATAL);
1908  	}
1909  	ctx.pkg_rootdir = rootdir;
1910  	ctx.defer_triggers = true;
1911  
1912  	return (EPKG_OK);
1913  }
1914  
1915  int
1916  pkg_set_ischrooted(bool ischrooted) {
1917  	if (pkg_initialized())
1918  		return (EPKG_FATAL);
1919  
1920  	ctx.ischrooted = ischrooted;
1921  
1922  	return (EPKG_OK);
1923  }
1924  
1925  const char *
1926  pkg_get_cachedir(void)
1927  {
1928  
1929  	return (ctx.cachedir);
1930  }
1931  
1932  int
1933  pkg_get_cachedirfd(void)
1934  {
1935  
1936  	if (ctx.cachedirfd == -1) {
1937  		/*
1938  		 * do not check the value as if we cannot open it means
1939  		 * it has not been created yet
1940  		 */
1941  		ctx.cachedirfd = open(ctx.cachedir, O_DIRECTORY|O_CLOEXEC);
1942  	}
1943  
1944  	return (ctx.cachedirfd);
1945  }
1946  
1947  int
1948  pkg_get_dbdirfd(void)
1949  {
1950  
1951  	if (ctx.pkg_dbdirfd == -1) {
1952  		/*
1953  		 * do not check the value as if we cannot open it means
1954  		 * it has not been created yet
1955  		 */
1956  		ctx.pkg_dbdirfd = open(ctx.dbdir, O_DIRECTORY|O_CLOEXEC);
1957  	}
1958  
1959  	return (ctx.pkg_dbdirfd);
1960  }
1961  
1962  int
1963  pkg_get_reposdirfd(void)
1964  {
1965  	int dbfd = pkg_get_dbdirfd();
1966  	if (dbfd == -1)
1967  		return (-1);
1968  	if (ctx.pkg_reposdirfd == -1) {
1969  		ctx.pkg_reposdirfd = openat(dbfd, "repos", O_DIRECTORY|O_CLOEXEC);
1970  		if (ctx.pkg_reposdirfd == -1) {
1971  			if (mkdirat(dbfd, "repos", 0755) == -1) {
1972  				return (-1);
1973  			}
1974  			ctx.pkg_reposdirfd = openat(dbfd, "repos", O_DIRECTORY|O_CLOEXEC);
1975  		}
1976  	}
1977  	return (ctx.pkg_reposdirfd);
1978  }
1979  
1980  int
1981  pkg_open_devnull(void) {
1982  	pkg_close_devnull();
1983  
1984  	if ((ctx.devnullfd = open("/dev/null", O_RDWR)) < 0) {
1985  		pkg_emit_error("Cannot open /dev/null");
1986  		return (EPKG_FATAL);
1987  	}
1988  
1989  	return (EPKG_OK);
1990  }
1991  
1992  void
1993  pkg_close_devnull(void) {
1994  	if (ctx.devnullfd != 1) {
1995  		close(ctx.devnullfd);
1996  	}
1997  
1998  	return;
1999  }