13aa4b42aSBaptiste Daroussin /*- 29950eceeSBaptiste Daroussin * Copyright (c) 2012-2013 Baptiste Daroussin <bapt@FreeBSD.org> 33aa4b42aSBaptiste Daroussin * All rights reserved. 43aa4b42aSBaptiste Daroussin * 53aa4b42aSBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 63aa4b42aSBaptiste Daroussin * modification, are permitted provided that the following conditions 73aa4b42aSBaptiste Daroussin * are met: 83aa4b42aSBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 93aa4b42aSBaptiste Daroussin * notice, this list of conditions and the following disclaimer. 103aa4b42aSBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 113aa4b42aSBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 123aa4b42aSBaptiste Daroussin * documentation and/or other materials provided with the distribution. 133aa4b42aSBaptiste Daroussin * 143aa4b42aSBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 153aa4b42aSBaptiste Daroussin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 163aa4b42aSBaptiste Daroussin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 173aa4b42aSBaptiste Daroussin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 183aa4b42aSBaptiste Daroussin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 193aa4b42aSBaptiste Daroussin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 203aa4b42aSBaptiste Daroussin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 213aa4b42aSBaptiste Daroussin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 223aa4b42aSBaptiste Daroussin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 233aa4b42aSBaptiste Daroussin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 243aa4b42aSBaptiste Daroussin * SUCH DAMAGE. 253aa4b42aSBaptiste Daroussin */ 263aa4b42aSBaptiste Daroussin 273aa4b42aSBaptiste Daroussin #include <sys/cdefs.h> 283aa4b42aSBaptiste Daroussin __FBSDID("$FreeBSD$"); 293aa4b42aSBaptiste Daroussin 303aa4b42aSBaptiste Daroussin #include <sys/param.h> 313b05c2a8SBaptiste Daroussin #include <sys/wait.h> 323aa4b42aSBaptiste Daroussin 333aa4b42aSBaptiste Daroussin #include <archive.h> 343aa4b42aSBaptiste Daroussin #include <archive_entry.h> 353aa4b42aSBaptiste Daroussin #include <err.h> 363aa4b42aSBaptiste Daroussin #include <errno.h> 37*b70213b5SBaptiste Daroussin #include <fcntl.h> 383b05c2a8SBaptiste Daroussin #include <fetch.h> 39a6454741SBaptiste Daroussin #include <paths.h> 409950eceeSBaptiste Daroussin #include <stdbool.h> 413aa4b42aSBaptiste Daroussin #include <stdlib.h> 423aa4b42aSBaptiste Daroussin #include <stdio.h> 433aa4b42aSBaptiste Daroussin #include <string.h> 443aa4b42aSBaptiste Daroussin #include <time.h> 453aa4b42aSBaptiste Daroussin #include <unistd.h> 463aa4b42aSBaptiste Daroussin 4729aaa961SBaptiste Daroussin #include "dns_utils.h" 489950eceeSBaptiste Daroussin #include "config.h" 493aa4b42aSBaptiste Daroussin 503aa4b42aSBaptiste Daroussin static int 513aa4b42aSBaptiste Daroussin extract_pkg_static(int fd, char *p, int sz) 523aa4b42aSBaptiste Daroussin { 533aa4b42aSBaptiste Daroussin struct archive *a; 543aa4b42aSBaptiste Daroussin struct archive_entry *ae; 553aa4b42aSBaptiste Daroussin char *end; 563aa4b42aSBaptiste Daroussin int ret, r; 573aa4b42aSBaptiste Daroussin 58a6454741SBaptiste Daroussin ret = -1; 593aa4b42aSBaptiste Daroussin a = archive_read_new(); 60a6454741SBaptiste Daroussin if (a == NULL) { 61a6454741SBaptiste Daroussin warn("archive_read_new"); 62a6454741SBaptiste Daroussin return (ret); 63a6454741SBaptiste Daroussin } 64ff75c36aSBaptiste Daroussin archive_read_support_filter_all(a); 653aa4b42aSBaptiste Daroussin archive_read_support_format_tar(a); 663aa4b42aSBaptiste Daroussin 67a6454741SBaptiste Daroussin if (lseek(fd, 0, 0) == -1) { 68a6454741SBaptiste Daroussin warn("lseek"); 69a6454741SBaptiste Daroussin goto cleanup; 70a6454741SBaptiste Daroussin } 713aa4b42aSBaptiste Daroussin 723aa4b42aSBaptiste Daroussin if (archive_read_open_fd(a, fd, 4096) != ARCHIVE_OK) { 73a6454741SBaptiste Daroussin warnx("archive_read_open_fd: %s", archive_error_string(a)); 743aa4b42aSBaptiste Daroussin goto cleanup; 753aa4b42aSBaptiste Daroussin } 763aa4b42aSBaptiste Daroussin 773aa4b42aSBaptiste Daroussin ae = NULL; 783aa4b42aSBaptiste Daroussin while ((r = archive_read_next_header(a, &ae)) == ARCHIVE_OK) { 793aa4b42aSBaptiste Daroussin end = strrchr(archive_entry_pathname(ae), '/'); 803aa4b42aSBaptiste Daroussin if (end == NULL) 813aa4b42aSBaptiste Daroussin continue; 823aa4b42aSBaptiste Daroussin 833aa4b42aSBaptiste Daroussin if (strcmp(end, "/pkg-static") == 0) { 843aa4b42aSBaptiste Daroussin r = archive_read_extract(a, ae, 853aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_OWNER | ARCHIVE_EXTRACT_PERM | 863aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_ACL | 873aa4b42aSBaptiste Daroussin ARCHIVE_EXTRACT_FFLAGS | ARCHIVE_EXTRACT_XATTR); 88a6454741SBaptiste Daroussin strlcpy(p, archive_entry_pathname(ae), sz); 893aa4b42aSBaptiste Daroussin break; 903aa4b42aSBaptiste Daroussin } 913aa4b42aSBaptiste Daroussin } 923aa4b42aSBaptiste Daroussin 93a6454741SBaptiste Daroussin if (r == ARCHIVE_OK) 94a6454741SBaptiste Daroussin ret = 0; 95a6454741SBaptiste Daroussin else 963aa4b42aSBaptiste Daroussin warnx("fail to extract pkg-static"); 973aa4b42aSBaptiste Daroussin 983aa4b42aSBaptiste Daroussin cleanup: 99ff75c36aSBaptiste Daroussin archive_read_free(a); 1003b05c2a8SBaptiste Daroussin return (ret); 1013aa4b42aSBaptiste Daroussin 1023aa4b42aSBaptiste Daroussin } 1033aa4b42aSBaptiste Daroussin 1043aa4b42aSBaptiste Daroussin static int 1053aa4b42aSBaptiste Daroussin install_pkg_static(char *path, char *pkgpath) 1063aa4b42aSBaptiste Daroussin { 1073aa4b42aSBaptiste Daroussin int pstat; 1083aa4b42aSBaptiste Daroussin pid_t pid; 1093aa4b42aSBaptiste Daroussin 1103aa4b42aSBaptiste Daroussin switch ((pid = fork())) { 1113aa4b42aSBaptiste Daroussin case -1: 1123aa4b42aSBaptiste Daroussin return (-1); 1133aa4b42aSBaptiste Daroussin case 0: 114a6454741SBaptiste Daroussin execl(path, "pkg-static", "add", pkgpath, (char *)NULL); 1153b05c2a8SBaptiste Daroussin _exit(1); 1163aa4b42aSBaptiste Daroussin default: 1173aa4b42aSBaptiste Daroussin break; 1183aa4b42aSBaptiste Daroussin } 1193aa4b42aSBaptiste Daroussin 120a6454741SBaptiste Daroussin while (waitpid(pid, &pstat, 0) == -1) 1213aa4b42aSBaptiste Daroussin if (errno != EINTR) 1223aa4b42aSBaptiste Daroussin return (-1); 1233aa4b42aSBaptiste Daroussin 124a6454741SBaptiste Daroussin if (WEXITSTATUS(pstat)) 1253aa4b42aSBaptiste Daroussin return (WEXITSTATUS(pstat)); 126a6454741SBaptiste Daroussin else if (WIFSIGNALED(pstat)) 127a6454741SBaptiste Daroussin return (128 & (WTERMSIG(pstat))); 128a6454741SBaptiste Daroussin return (pstat); 1293aa4b42aSBaptiste Daroussin } 1303aa4b42aSBaptiste Daroussin 1313aa4b42aSBaptiste Daroussin static int 1323aa4b42aSBaptiste Daroussin bootstrap_pkg(void) 1333aa4b42aSBaptiste Daroussin { 13429aaa961SBaptiste Daroussin struct url *u; 1353aa4b42aSBaptiste Daroussin FILE *remote; 1362fe3761eSBaptiste Daroussin FILE *config; 1372fe3761eSBaptiste Daroussin char *site; 13829aaa961SBaptiste Daroussin struct dns_srvinfo *mirrors, *current; 13929aaa961SBaptiste Daroussin /* To store _https._tcp. + hostname + \0 */ 14029aaa961SBaptiste Daroussin char zone[MAXHOSTNAMELEN + 13]; 1413aa4b42aSBaptiste Daroussin char url[MAXPATHLEN]; 1422fe3761eSBaptiste Daroussin char conf[MAXPATHLEN]; 1433aa4b42aSBaptiste Daroussin char tmppkg[MAXPATHLEN]; 1449950eceeSBaptiste Daroussin const char *packagesite, *mirror_type; 1453aa4b42aSBaptiste Daroussin char buf[10240]; 1463aa4b42aSBaptiste Daroussin char pkgstatic[MAXPATHLEN]; 14729aaa961SBaptiste Daroussin int fd, retry, ret, max_retry; 148a6454741SBaptiste Daroussin struct url_stat st; 1493aa4b42aSBaptiste Daroussin off_t done, r; 150a6454741SBaptiste Daroussin time_t now; 151a6454741SBaptiste Daroussin time_t last; 1523aa4b42aSBaptiste Daroussin 1533aa4b42aSBaptiste Daroussin done = 0; 154a6454741SBaptiste Daroussin last = 0; 15529aaa961SBaptiste Daroussin max_retry = 3; 156a6454741SBaptiste Daroussin ret = -1; 1573aa4b42aSBaptiste Daroussin remote = NULL; 1582fe3761eSBaptiste Daroussin config = NULL; 15929aaa961SBaptiste Daroussin current = mirrors = NULL; 1603aa4b42aSBaptiste Daroussin 16165008e03SGavin Atkinson printf("Bootstrapping pkg, please wait...\n"); 1623aa4b42aSBaptiste Daroussin 1639950eceeSBaptiste Daroussin if (config_string(PACKAGESITE, &packagesite) != 0) { 1649950eceeSBaptiste Daroussin warnx("No PACKAGESITE defined"); 1653b05c2a8SBaptiste Daroussin return (-1); 1663aa4b42aSBaptiste Daroussin } 1679950eceeSBaptiste Daroussin if (config_string(MIRROR_TYPE, &mirror_type) != 0) { 1689950eceeSBaptiste Daroussin warnx("No MIRROR_TYPE defined"); 1699950eceeSBaptiste Daroussin return (-1); 1709950eceeSBaptiste Daroussin } 171968d04c3SBaptiste Daroussin snprintf(url, MAXPATHLEN, "%s/Latest/pkg.txz", packagesite); 1723aa4b42aSBaptiste Daroussin 1733aa4b42aSBaptiste Daroussin snprintf(tmppkg, MAXPATHLEN, "%s/pkg.txz.XXXXXX", 174a6454741SBaptiste Daroussin getenv("TMPDIR") ? getenv("TMPDIR") : _PATH_TMP); 1753aa4b42aSBaptiste Daroussin 1763aa4b42aSBaptiste Daroussin if ((fd = mkstemp(tmppkg)) == -1) { 1773aa4b42aSBaptiste Daroussin warn("mkstemp()"); 1783b05c2a8SBaptiste Daroussin return (-1); 1793aa4b42aSBaptiste Daroussin } 1803aa4b42aSBaptiste Daroussin 18129aaa961SBaptiste Daroussin retry = max_retry; 18229aaa961SBaptiste Daroussin 18329aaa961SBaptiste Daroussin u = fetchParseURL(url); 18429aaa961SBaptiste Daroussin while (remote == NULL) { 18529aaa961SBaptiste Daroussin if (retry == max_retry) { 1869950eceeSBaptiste Daroussin if (strcmp(u->scheme, "file") != 0 && 1879950eceeSBaptiste Daroussin strcasecmp(mirror_type, "srv") == 0) { 18829aaa961SBaptiste Daroussin snprintf(zone, sizeof(zone), 18929aaa961SBaptiste Daroussin "_%s._tcp.%s", u->scheme, u->host); 19029aaa961SBaptiste Daroussin mirrors = dns_getsrvinfo(zone); 19129aaa961SBaptiste Daroussin current = mirrors; 19229aaa961SBaptiste Daroussin } 19329aaa961SBaptiste Daroussin } 19429aaa961SBaptiste Daroussin 19535e07a7aSBaptiste Daroussin if (mirrors != NULL) { 19629aaa961SBaptiste Daroussin strlcpy(u->host, current->host, sizeof(u->host)); 19735e07a7aSBaptiste Daroussin u->port = current->port; 19835e07a7aSBaptiste Daroussin } 19929aaa961SBaptiste Daroussin 20029aaa961SBaptiste Daroussin remote = fetchXGet(u, &st, ""); 20129aaa961SBaptiste Daroussin if (remote == NULL) { 20229aaa961SBaptiste Daroussin --retry; 20329aaa961SBaptiste Daroussin if (retry <= 0) 20429aaa961SBaptiste Daroussin goto fetchfail; 20529aaa961SBaptiste Daroussin if (mirrors == NULL) { 2063aa4b42aSBaptiste Daroussin sleep(1); 20729aaa961SBaptiste Daroussin } else { 20829aaa961SBaptiste Daroussin current = current->next; 20929aaa961SBaptiste Daroussin if (current == NULL) 21029aaa961SBaptiste Daroussin current = mirrors; 21129aaa961SBaptiste Daroussin } 21229aaa961SBaptiste Daroussin } 21329aaa961SBaptiste Daroussin } 214a6454741SBaptiste Daroussin 215a6454741SBaptiste Daroussin if (remote == NULL) 216a6454741SBaptiste Daroussin goto fetchfail; 2173aa4b42aSBaptiste Daroussin 2183aa4b42aSBaptiste Daroussin while (done < st.size) { 2193aa4b42aSBaptiste Daroussin if ((r = fread(buf, 1, sizeof(buf), remote)) < 1) 2203aa4b42aSBaptiste Daroussin break; 2213aa4b42aSBaptiste Daroussin 2223aa4b42aSBaptiste Daroussin if (write(fd, buf, r) != r) { 2233aa4b42aSBaptiste Daroussin warn("write()"); 2243aa4b42aSBaptiste Daroussin goto cleanup; 2253aa4b42aSBaptiste Daroussin } 2263aa4b42aSBaptiste Daroussin 2273aa4b42aSBaptiste Daroussin done += r; 2283aa4b42aSBaptiste Daroussin now = time(NULL); 229a6454741SBaptiste Daroussin if (now > last || done == st.size) 2303aa4b42aSBaptiste Daroussin last = now; 2313aa4b42aSBaptiste Daroussin } 2323aa4b42aSBaptiste Daroussin 233a6454741SBaptiste Daroussin if (ferror(remote)) 234a6454741SBaptiste Daroussin goto fetchfail; 2353aa4b42aSBaptiste Daroussin 2363aa4b42aSBaptiste Daroussin if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) 2373aa4b42aSBaptiste Daroussin ret = install_pkg_static(pkgstatic, tmppkg); 2383aa4b42aSBaptiste Daroussin 2392fe3761eSBaptiste Daroussin snprintf(conf, MAXPATHLEN, "%s/etc/pkg.conf", 2402fe3761eSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 2412fe3761eSBaptiste Daroussin 2422fe3761eSBaptiste Daroussin if (access(conf, R_OK) == -1) { 2432fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 2442fe3761eSBaptiste Daroussin if (site == NULL) 2452fe3761eSBaptiste Daroussin goto cleanup; 2462fe3761eSBaptiste Daroussin site[0] = '\0'; 2472fe3761eSBaptiste Daroussin site = strrchr(url, '/'); 2482fe3761eSBaptiste Daroussin if (site == NULL) 2492fe3761eSBaptiste Daroussin goto cleanup; 2502fe3761eSBaptiste Daroussin site[0] = '\0'; 2512fe3761eSBaptiste Daroussin 2522fe3761eSBaptiste Daroussin config = fopen(conf, "w+"); 2532fe3761eSBaptiste Daroussin if (config == NULL) 2542fe3761eSBaptiste Daroussin goto cleanup; 255514ead92SBaptiste Daroussin fprintf(config, "packagesite: %s\n", url); 2562fe3761eSBaptiste Daroussin fclose(config); 2572fe3761eSBaptiste Daroussin } 2582fe3761eSBaptiste Daroussin 259a6454741SBaptiste Daroussin goto cleanup; 260a6454741SBaptiste Daroussin 261a6454741SBaptiste Daroussin fetchfail: 262a6454741SBaptiste Daroussin warnx("Error fetching %s: %s", url, fetchLastErrString); 26386e220abSBaptiste Daroussin fprintf(stderr, "A pre-built version of pkg could not be found for your system.\n"); 26486e220abSBaptiste Daroussin fprintf(stderr, "Consider changing PACKAGESITE or installing it from ports: 'ports-mgmt/pkg'.\n"); 265a6454741SBaptiste Daroussin 2663aa4b42aSBaptiste Daroussin cleanup: 2672fe3761eSBaptiste Daroussin if (remote != NULL) 2682fe3761eSBaptiste Daroussin fclose(remote); 2693aa4b42aSBaptiste Daroussin close(fd); 2703aa4b42aSBaptiste Daroussin unlink(tmppkg); 2713aa4b42aSBaptiste Daroussin 272a6454741SBaptiste Daroussin return (ret); 2733aa4b42aSBaptiste Daroussin } 2743aa4b42aSBaptiste Daroussin 275e18ad51cSAlexander Kabaev static const char confirmation_message[] = 276e18ad51cSAlexander Kabaev "The package management tool is not yet installed on your system.\n" 277e18ad51cSAlexander Kabaev "Do you want to fetch and install it now? [y/N]: "; 278e18ad51cSAlexander Kabaev 279e18ad51cSAlexander Kabaev static int 280e18ad51cSAlexander Kabaev pkg_query_yes_no(void) 281e18ad51cSAlexander Kabaev { 282e18ad51cSAlexander Kabaev int ret, c; 283e18ad51cSAlexander Kabaev 284e18ad51cSAlexander Kabaev c = getchar(); 285e18ad51cSAlexander Kabaev 286e18ad51cSAlexander Kabaev if (c == 'y' || c == 'Y') 287e18ad51cSAlexander Kabaev ret = 1; 288e18ad51cSAlexander Kabaev else 289e18ad51cSAlexander Kabaev ret = 0; 290e18ad51cSAlexander Kabaev 291e18ad51cSAlexander Kabaev while (c != '\n' && c != EOF) 292e18ad51cSAlexander Kabaev c = getchar(); 293e18ad51cSAlexander Kabaev 294e18ad51cSAlexander Kabaev return (ret); 295e18ad51cSAlexander Kabaev } 296e18ad51cSAlexander Kabaev 2973aa4b42aSBaptiste Daroussin int 2983aa4b42aSBaptiste Daroussin main(__unused int argc, char *argv[]) 2993aa4b42aSBaptiste Daroussin { 3003aa4b42aSBaptiste Daroussin char pkgpath[MAXPATHLEN]; 301*b70213b5SBaptiste Daroussin char pkgstatic[MAXPATHLEN]; 3029950eceeSBaptiste Daroussin bool yes = false; 303*b70213b5SBaptiste Daroussin int fd, ret; 3043aa4b42aSBaptiste Daroussin 3053aa4b42aSBaptiste Daroussin snprintf(pkgpath, MAXPATHLEN, "%s/sbin/pkg", 3063aa4b42aSBaptiste Daroussin getenv("LOCALBASE") ? getenv("LOCALBASE") : _LOCALBASE); 3073aa4b42aSBaptiste Daroussin 308e18ad51cSAlexander Kabaev if (access(pkgpath, X_OK) == -1) { 309e18ad51cSAlexander Kabaev /* 310d482e1f4SMatthew Seaman * To allow 'pkg -N' to be used as a reliable test for whether 311ecfed9f2SMatthew Seaman * a system is configured to use pkg, don't bootstrap pkg 312ecfed9f2SMatthew Seaman * when that argument is given as argv[1]. 313ecfed9f2SMatthew Seaman */ 314d8f9490cSMatthew Seaman if (argv[1] != NULL && strcmp(argv[1], "-N") == 0) 315e41b8acbSMatthew Seaman errx(EXIT_FAILURE, "pkg is not installed"); 316ecfed9f2SMatthew Seaman 317*b70213b5SBaptiste Daroussin if (argc > 2 && strcmp(argv[1], "add") == 0 && 318*b70213b5SBaptiste Daroussin access(argv[2], R_OK) == 0) { 319*b70213b5SBaptiste Daroussin fd = open(argv[2], O_RDONLY); 320*b70213b5SBaptiste Daroussin if (fd == -1) 321*b70213b5SBaptiste Daroussin err(EXIT_FAILURE, "Unable to open %s", argv[2]); 322*b70213b5SBaptiste Daroussin 323*b70213b5SBaptiste Daroussin if ((ret = extract_pkg_static(fd, pkgstatic, MAXPATHLEN)) == 0) 324*b70213b5SBaptiste Daroussin ret = install_pkg_static(pkgstatic, argv[2]); 325*b70213b5SBaptiste Daroussin close(fd); 326*b70213b5SBaptiste Daroussin if (ret != 0) 327*b70213b5SBaptiste Daroussin exit(EXIT_FAILURE); 328*b70213b5SBaptiste Daroussin exit(EXIT_SUCCESS); 329*b70213b5SBaptiste Daroussin } 330ecfed9f2SMatthew Seaman /* 331e18ad51cSAlexander Kabaev * Do not ask for confirmation if either of stdin or stdout is 332e18ad51cSAlexander Kabaev * not tty. Check the environment to see if user has answer 333e18ad51cSAlexander Kabaev * tucked in there already. 334e18ad51cSAlexander Kabaev */ 3359950eceeSBaptiste Daroussin config_init(); 3369950eceeSBaptiste Daroussin config_bool(ASSUME_ALWAYS_YES, &yes); 3379950eceeSBaptiste Daroussin if (!yes) { 338e18ad51cSAlexander Kabaev printf("%s", confirmation_message); 339204ea792SBaptiste Daroussin if (!isatty(fileno(stdin))) 3403a480126SBaptiste Daroussin exit(EXIT_FAILURE); 341204ea792SBaptiste Daroussin 342204ea792SBaptiste Daroussin if (pkg_query_yes_no() == 0) 343e18ad51cSAlexander Kabaev exit(EXIT_FAILURE); 344e18ad51cSAlexander Kabaev } 345a6454741SBaptiste Daroussin if (bootstrap_pkg() != 0) 346a6454741SBaptiste Daroussin exit(EXIT_FAILURE); 3479950eceeSBaptiste Daroussin config_finish(); 348e18ad51cSAlexander Kabaev } 3493aa4b42aSBaptiste Daroussin 3503aa4b42aSBaptiste Daroussin execv(pkgpath, argv); 3513aa4b42aSBaptiste Daroussin 352a6454741SBaptiste Daroussin /* NOT REACHED */ 3533b05c2a8SBaptiste Daroussin return (EXIT_FAILURE); 3543aa4b42aSBaptiste Daroussin } 355