1327Sjkh/* 2327Sjkh * 3228990Suqs * FreeBSD install - a package for the installation and maintenance 4327Sjkh * of non-core utilities. 5327Sjkh * 6327Sjkh * Redistribution and use in source and binary forms, with or without 7327Sjkh * modification, are permitted provided that the following conditions 8327Sjkh * are met: 9327Sjkh * 1. Redistributions of source code must retain the above copyright 10327Sjkh * notice, this list of conditions and the following disclaimer. 11327Sjkh * 2. Redistributions in binary form must reproduce the above copyright 12327Sjkh * notice, this list of conditions and the following disclaimer in the 13327Sjkh * documentation and/or other materials provided with the distribution. 14327Sjkh * 15327Sjkh * Jordan K. Hubbard 16327Sjkh * 18 July 1993 17327Sjkh * 18327Sjkh * This is the add module. 19327Sjkh */ 20327Sjkh 2193520Sobrien#include <sys/cdefs.h> 2293520Sobrien__FBSDID("$FreeBSD$"); 2376392Sobrien 2412219Sjkh#include <sys/param.h> 25212029Snwhitehorn#include <sys/sysctl.h> 26179433Sflz#include <err.h> 27179433Sflz#include <getopt.h> 28179433Sflz 29222035Sflz#include "lib.h" 30327Sjkh#include "add.h" 31327Sjkh 32327Sjkhchar *Prefix = NULL; 33152329SkrionBoolean PrefixRecursive = FALSE; 34126465Skensmithchar *Chroot = NULL; 35327SjkhBoolean NoInstall = FALSE; 36327SjkhBoolean NoRecord = FALSE; 3742740SbillfBoolean Remote = FALSE; 38154145SflzBoolean KeepPackage = FALSE; 39156497SphkBoolean FailOnAlreadyInstalled = TRUE; 40173513SkrionBoolean IgnoreDeps = FALSE; 41327Sjkh 42327Sjkhchar *Mode = NULL; 43327Sjkhchar *Owner = NULL; 44327Sjkhchar *Group = NULL; 45327Sjkhchar *PkgName = NULL; 46131285Seikchar *PkgAddCmd = NULL; 47327Sjkhchar *Directory = NULL; 4811780Sjkhchar FirstPen[FILENAME_MAX]; 49382Sjkhadd_mode_t AddMode = NORMAL; 50327Sjkh 51166374Sadechar **pkgs; 5212219Sjkh 5376504Skrisstruct { 5476504Skris int lowver; /* Lowest version number to match */ 5576504Skris int hiver; /* Highest version number to match */ 5676504Skris const char *directory; /* Directory it lives in */ 5776504Skris} releases[] = { 5876504Skris { 410000, 410000, "/packages-4.1-release" }, 5976504Skris { 420000, 420000, "/packages-4.2-release" }, 6076504Skris { 430000, 430000, "/packages-4.3-release" }, 6176504Skris { 440000, 440000, "/packages-4.4-release" }, 6276504Skris { 450000, 450000, "/packages-4.5-release" }, 63103150Sbmah { 460000, 460001, "/packages-4.6-release" }, 64103155Sbmah { 460002, 460099, "/packages-4.6.2-release" }, 65104658Sbmah { 470000, 470099, "/packages-4.7-release" }, 66124054Sbmah { 480000, 480099, "/packages-4.8-release" }, 67124054Sbmah { 490000, 490099, "/packages-4.9-release" }, 68129054Sbmah { 491000, 491099, "/packages-4.10-release" }, 69131285Seik { 492000, 492099, "/packages-4.11-release" }, 70124054Sbmah { 500000, 500099, "/packages-5.0-release" }, 71124054Sbmah { 501000, 501099, "/packages-5.1-release" }, 72129054Sbmah { 502000, 502009, "/packages-5.2-release" }, 73129054Sbmah { 502010, 502099, "/packages-5.2.1-release" }, 74131285Seik { 503000, 503099, "/packages-5.3-release" }, 75147932Skensmith { 504000, 504099, "/packages-5.4-release" }, 76162663Skensmith { 505000, 505099, "/packages-5.5-release" }, 77151754Smurray { 600000, 600099, "/packages-6.0-release" }, 78162663Skensmith { 601000, 601099, "/packages-6.1-release" }, 79162663Skensmith { 602000, 602099, "/packages-6.2-release" }, 80176593Skensmith { 603000, 603099, "/packages-6.3-release" }, 81191110Skensmith { 604000, 604099, "/packages-6.4-release" }, 82176593Skensmith { 700000, 700099, "/packages-7.0-release" }, 83186494Sflz { 701000, 701099, "/packages-7.1-release" }, 84191110Skensmith { 702000, 702099, "/packages-7.2-release" }, 85216665Skensmith { 703000, 703099, "/packages-7.3-release" }, 86216665Skensmith { 704000, 704099, "/packages-7.4-release" }, 87196432Skensmith { 800000, 800499, "/packages-8.0-release" }, 88216665Skensmith { 801000, 801499, "/packages-8.1-release" }, 89216665Skensmith { 802000, 802499, "/packages-8.2-release" }, 90232435Skensmith { 803000, 803499, "/packages-8.3-release" }, 91225757Skensmith { 900000, 900499, "/packages-9.0-release" }, 92241975Skensmith { 901000, 901499, "/packages-9.1-release" }, 93254525Sgjb { 902000, 902499, "/packages-9.2-release" }, 9476504Skris { 300000, 399000, "/packages-3-stable" }, 9576504Skris { 400000, 499000, "/packages-4-stable" }, 96136616Sobrien { 502100, 502128, "/packages-5-current" }, 97147939Skensmith { 503100, 599000, "/packages-5-stable" }, 98151754Smurray { 600100, 699000, "/packages-6-stable" }, 99176593Skensmith { 700100, 799000, "/packages-7-stable" }, 100196485Skensmith { 800500, 899000, "/packages-8-stable" }, 101225757Skensmith { 900500, 999000, "/packages-9-stable" }, 102225757Skensmith { 1000000, 1099000, "/packages-10-current" }, 10376504Skris { 0, 9999999, "/packages-current" }, 10476504Skris { 0, 0, NULL } 10576504Skris}; 10676504Skris 10751638Sbillfstatic char *getpackagesite(void); 10842740Sbillfint getosreldate(void); 10942740Sbillf 110173412Skevlostatic void usage(void); 11130221Scharnier 112179433Sflzstatic char opts[] = "hviIRfFnrp:P:SMt:C:K"; 113179433Sflzstatic struct option longopts[] = { 114179433Sflz { "chroot", required_argument, NULL, 'C' }, 115179433Sflz { "dry-run", no_argument, NULL, 'n' }, 116179433Sflz { "force", no_argument, NULL, 'f' }, 117179433Sflz { "help", no_argument, NULL, 'h' }, 118179433Sflz { "keep", no_argument, NULL, 'K' }, 119179433Sflz { "master", no_argument, NULL, 'M' }, 120179433Sflz { "no-deps", no_argument, NULL, 'i' }, 121179433Sflz { "no-record", no_argument, NULL, 'R' }, 122179433Sflz { "no-script", no_argument, NULL, 'I' }, 123179433Sflz { "prefix", required_argument, NULL, 'p' }, 124179433Sflz { "remote", no_argument, NULL, 'r' }, 125179433Sflz { "template", required_argument, NULL, 't' }, 126179433Sflz { "slave", no_argument, NULL, 'S' }, 127179433Sflz { "verbose", no_argument, NULL, 'v' }, 128179433Sflz { NULL, 0, NULL, 0 } 129179433Sflz}; 130179433Sflz 131327Sjkhint 132327Sjkhmain(int argc, char **argv) 133327Sjkh{ 13476504Skris int ch, error; 13512219Sjkh char **start; 13683573Ssobomax char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr; 13753388Scpiazza static char temppackageroot[MAXPATHLEN]; 138131285Seik static char pkgaddpath[MAXPATHLEN]; 13942740Sbillf 140131285Seik if (*argv[0] != '/' && strchr(argv[0], '/') != NULL) 141131285Seik PkgAddCmd = realpath(argv[0], pkgaddpath); 142131285Seik else 143131285Seik PkgAddCmd = argv[0]; 144131285Seik 14512219Sjkh start = argv; 146179433Sflz while ((ch = getopt_long(argc, argv, opts, longopts, NULL)) != -1) { 147327Sjkh switch(ch) { 148327Sjkh case 'v': 149159554Sobrien Verbose++; 150327Sjkh break; 151327Sjkh 152327Sjkh case 'p': 153327Sjkh Prefix = optarg; 154152329Skrion PrefixRecursive = FALSE; 155327Sjkh break; 156327Sjkh 157152329Skrion case 'P': 158152329Skrion Prefix = optarg; 159152329Skrion PrefixRecursive = TRUE; 160152329Skrion break; 161152329Skrion 162327Sjkh case 'I': 163327Sjkh NoInstall = TRUE; 164327Sjkh break; 165327Sjkh 166327Sjkh case 'R': 167327Sjkh NoRecord = TRUE; 168327Sjkh break; 169327Sjkh 1704996Sjkh case 'f': 1714996Sjkh Force = TRUE; 1724996Sjkh break; 1734996Sjkh 174156497Sphk case 'F': 175156497Sphk FailOnAlreadyInstalled = FALSE; 176156497Sphk break; 177156497Sphk 178154145Sflz case 'K': 179154145Sflz KeepPackage = TRUE; 180154145Sflz break; 181154145Sflz 182327Sjkh case 'n': 183327Sjkh Fake = TRUE; 184327Sjkh break; 185327Sjkh 18642740Sbillf case 'r': 18742740Sbillf Remote = TRUE; 18842740Sbillf break; 18942740Sbillf 190382Sjkh case 't': 19181571Sobrien if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen)) 19276504Skris errx(1, "-t Argument too long."); 193382Sjkh break; 194382Sjkh 195382Sjkh case 'S': 196382Sjkh AddMode = SLAVE; 197382Sjkh break; 198382Sjkh 199382Sjkh case 'M': 200382Sjkh AddMode = MASTER; 201382Sjkh break; 202382Sjkh 203126465Skensmith case 'C': 204126465Skensmith Chroot = optarg; 205126465Skensmith break; 206179433Sflz 207173513Skrion case 'i': 208173513Skrion IgnoreDeps = TRUE; 209173513Skrion break; 210126465Skensmith 211327Sjkh case 'h': 212327Sjkh default: 21330221Scharnier usage(); 214327Sjkh break; 215327Sjkh } 21612219Sjkh } 2178857Srgrimes argc -= optind; 218327Sjkh argv += optind; 219327Sjkh 22012219Sjkh if (AddMode != SLAVE) { 221166402Spav pkgs = (char **)malloc((argc+1) * sizeof(char *)); 222166374Sade for (ch = 0; ch <= argc; pkgs[ch++] = NULL) ; 22312219Sjkh 22412219Sjkh /* Get all the remaining package names, if any */ 22512219Sjkh for (ch = 0; *argv; ch++, argv++) { 226166374Sade char temp[MAXPATHLEN]; 22742740Sbillf if (Remote) { 22876504Skris if ((packagesite = getpackagesite()) == NULL) 22976504Skris errx(1, "package name too long"); 23081571Sobrien if (strlcpy(temppackageroot, packagesite, 23181571Sobrien sizeof(temppackageroot)) >= sizeof(temppackageroot)) 23276504Skris errx(1, "package name too long"); 23381571Sobrien if (strlcat(temppackageroot, *argv, sizeof(temppackageroot)) 23481571Sobrien >= sizeof(temppackageroot)) 23576504Skris errx(1, "package name too long"); 23676504Skris remotepkg = temppackageroot; 237213718Sflz if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' && 238213718Sflz (ptr[2] == 'b' || ptr[2] == 'g' || ptr[2] == 'x') && 239236333Sjpaetzel ptr[3] == 'z' && !ptr[4])) { 240236333Sjpaetzel if (getenv("PACKAGESUFFIX")) { 241236333Sjpaetzel if (strlcat(remotepkg, getenv("PACKAGESUFFIX"), 242236333Sjpaetzel sizeof(temppackageroot)) >= sizeof(temppackageroot)) 243236333Sjpaetzel errx(1, "package name too long"); 244236333Sjpaetzel } else { 245236333Sjpaetzel if (strlcat(remotepkg, ".tbz", 246236333Sjpaetzel sizeof(temppackageroot)) >= sizeof(temppackageroot)) 247236333Sjpaetzel errx(1, "package name too long"); 248236333Sjpaetzel } 249236333Sjpaetzel } 25042740Sbillf } 25114582Sjkh if (!strcmp(*argv, "-")) /* stdin? */ 252132789Skan pkgs[ch] = (char *)"-"; 25376504Skris else if (isURL(*argv)) { /* preserve URLs */ 254166374Sade if (strlcpy(temp, *argv, sizeof(temp)) >= sizeof(temp)) 25576504Skris errx(1, "package name too long"); 256166374Sade pkgs[ch] = strdup(temp); 25776504Skris } 25876504Skris else if ((Remote) && isURL(remotepkg)) { 259166374Sade if (strlcpy(temp, remotepkg, sizeof(temp)) >= sizeof(temp)) 26076504Skris errx(1, "package name too long"); 261166374Sade pkgs[ch] = strdup(temp); 26276504Skris } else { /* expand all pathnames to fullnames */ 26312219Sjkh if (fexists(*argv)) /* refers to a file directly */ 264166374Sade pkgs[ch] = strdup(realpath(*argv, temp)); 26512219Sjkh else { /* look for the file in the expected places */ 26679916Skris if (!(cp = fileFindByPath(NULL, *argv))) { 26779916Skris /* let pkg_do() fail later, so that error is reported */ 268166374Sade if (strlcpy(temp, *argv, sizeof(temp)) >= sizeof(temp)) 26979916Skris errx(1, "package name too long"); 270166374Sade pkgs[ch] = strdup(temp); 27179916Skris } else { 272166374Sade if (strlcpy(temp, cp, sizeof(temp)) >= sizeof(temp)) 27376504Skris errx(1, "package name too long"); 274166374Sade pkgs[ch] = strdup(temp); 27576504Skris } 27612219Sjkh } 27712219Sjkh } 27883573Ssobomax if (packagesite != NULL) 27983573Ssobomax packagesite[0] = '\0'; 28012219Sjkh } 28112219Sjkh } 282327Sjkh /* If no packages, yelp */ 283183979Sbrooks if (!ch) { 28438942Sjkh warnx("missing package name(s)"); 28530221Scharnier usage(); 28638942Sjkh } 28738942Sjkh else if (ch > 1 && AddMode == MASTER) { 28838942Sjkh warnx("only one package name may be specified with master mode"); 28938942Sjkh usage(); 29038942Sjkh } 291126465Skensmith /* Perform chroot if requested */ 292126465Skensmith if (Chroot != NULL) { 293240682Sbapt if (chdir(Chroot)) 294240682Sbapt errx(1, "chdir to %s failed", Chroot); 295240682Sbapt if (chroot(".")) 296126465Skensmith errx(1, "chroot to %s failed", Chroot); 297126465Skensmith } 298243553Seadler warnpkgng(); 29938942Sjkh /* Make sure the sub-execs we invoke get found */ 30076015Sache setenv("PATH", 301229831Seadler "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin", 30276015Sache 1); 30339185Sjkh 30439185Sjkh /* Set a reasonable umask */ 30539185Sjkh umask(022); 30639185Sjkh 30776504Skris if ((error = pkg_perform(pkgs)) != 0) { 308327Sjkh if (Verbose) 30976504Skris warnx("%d package addition(s) failed", error); 31076504Skris return error; 311327Sjkh } 312327Sjkh else 313327Sjkh return 0; 314327Sjkh} 315327Sjkh 31642786Sbillfstatic char * 31751638Sbillfgetpackagesite(void) 31842740Sbillf{ 31976504Skris int reldate, i; 32047916Sobrien static char sitepath[MAXPATHLEN]; 321212029Snwhitehorn int archmib[] = { CTL_HW, HW_MACHINE_ARCH }; 322212029Snwhitehorn char arch[64]; 323212029Snwhitehorn size_t archlen = sizeof(arch); 32442740Sbillf 32572430Sobrien if (getenv("PACKAGESITE")) { 32681571Sobrien if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath)) 32781571Sobrien >= sizeof(sitepath)) 32876504Skris return NULL; 32972430Sobrien return sitepath; 33072430Sobrien } 33142740Sbillf 33276504Skris if (getenv("PACKAGEROOT")) { 33381571Sobrien if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath)) 33481571Sobrien >= sizeof(sitepath)) 33576504Skris return NULL; 33676504Skris } else { 33781571Sobrien if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath)) 33881571Sobrien >= sizeof(sitepath)) 33976504Skris return NULL; 34076504Skris } 34172430Sobrien 34281571Sobrien if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath)) 34381571Sobrien >= sizeof(sitepath)) 34476504Skris return NULL; 34572430Sobrien 346212029Snwhitehorn if (sysctl(archmib, 2, arch, &archlen, NULL, 0) == -1) 34776504Skris return NULL; 348212029Snwhitehorn arch[archlen-1] = 0; 349212029Snwhitehorn if (strlcat(sitepath, arch, sizeof(sitepath)) >= sizeof(sitepath)) 350212029Snwhitehorn return NULL; 35147916Sobrien 35272430Sobrien reldate = getosreldate(); 35376504Skris for(i = 0; releases[i].directory != NULL; i++) { 35476504Skris if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) { 35581571Sobrien if (strlcat(sitepath, releases[i].directory, sizeof(sitepath)) 35681571Sobrien >= sizeof(sitepath)) 35776504Skris return NULL; 35880409Skris break; 35976504Skris } 36076504Skris } 36142740Sbillf 36281571Sobrien if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath)) 36376504Skris return NULL; 36472430Sobrien 36547916Sobrien return sitepath; 36642740Sbillf 36742740Sbillf} 36842786Sbillf 36930221Scharnierstatic void 370201226Sedusage(void) 371327Sjkh{ 37230221Scharnier fprintf(stderr, "%s\n%s\n", 373173513Skrion "usage: pkg_add [-viInfFrRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]", 374126465Skensmith " pkg-name [pkg-name ...]"); 375327Sjkh exit(1); 376327Sjkh} 377