main.c revision 162663
12089Ssos/* 216565Ssos * 32089Ssos * FreeBSD install - a package for the installation and maintainance 42089Ssos * of non-core utilities. 5146736Sdelphij * 6146736Sdelphij * Redistribution and use in source and binary forms, with or without 7146736Sdelphij * modification, are permitted provided that the following conditions 82089Ssos * are met: 92089Ssos * 1. Redistributions of source code must retain the above copyright 102089Ssos * notice, this list of conditions and the following disclaimer. 112089Ssos * 2. Redistributions in binary form must reproduce the above copyright 125994Ssos * notice, this list of conditions and the following disclaimer in the 135994Ssos * documentation and/or other materials provided with the distribution. 142089Ssos * 152089Ssos * Jordan K. Hubbard 162089Ssos * 18 July 1993 172089Ssos * 1897748Sschweikh * This is the add module. 192089Ssos */ 202089Ssos 212089Ssos#include <sys/cdefs.h> 222089Ssos__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 162663 2006-09-26 14:51:33Z kensmith $"); 232089Ssos 242089Ssos#include <err.h> 252089Ssos#include <sys/param.h> 262089Ssos#include <sys/utsname.h> 272089Ssos#include "lib.h" 282089Ssos#include "add.h" 292089Ssos 30146736Sdelphijstatic char Options[] = "hvIRfFnrp:P:SMt:C:K"; 31146736Sdelphij 322089Ssoschar *Prefix = NULL; 332089SsosBoolean PrefixRecursive = FALSE; 3430764Scharnierchar *Chroot = NULL; 3530764ScharnierBoolean NoInstall = FALSE; 3650479SpeterBoolean NoRecord = FALSE; 3730764ScharnierBoolean Remote = FALSE; 3830764ScharnierBoolean KeepPackage = FALSE; 392089SsosBoolean FailOnAlreadyInstalled = TRUE; 4030764Scharnier 4155849Syokotachar *Mode = NULL; 422089Ssoschar *Owner = NULL; 4323457Sbrianchar *Group = NULL; 4430764Scharnierchar *PkgName = NULL; 4523702Speterchar *PkgAddCmd = NULL; 4666834Sphkchar *Directory = NULL; 4766834Sphkchar FirstPen[FILENAME_MAX]; 482089Ssosadd_mode_t AddMode = NORMAL; 4975344Ssobomax 5075344Ssobomax#define MAX_PKGS 200 512089Ssoschar pkgnames[MAX_PKGS][MAXPATHLEN]; 5223457Sbrianchar *pkgs[MAX_PKGS]; 532089Ssos 5471642Ssobomaxstruct { 55146736Sdelphij int lowver; /* Lowest version number to match */ 56146736Sdelphij int hiver; /* Highest version number to match */ 57102111Ssobomax const char *directory; /* Directory it lives in */ 58102111Ssobomax} releases[] = { 59102111Ssobomax { 410000, 410000, "/packages-4.1-release" }, 60102111Ssobomax { 420000, 420000, "/packages-4.2-release" }, 61102111Ssobomax { 430000, 430000, "/packages-4.3-release" }, 62102111Ssobomax { 440000, 440000, "/packages-4.4-release" }, 63102111Ssobomax { 450000, 450000, "/packages-4.5-release" }, 6476845Ssobomax { 460000, 460001, "/packages-4.6-release" }, 6576845Ssobomax { 460002, 460099, "/packages-4.6.2-release" }, 662089Ssos { 470000, 470099, "/packages-4.7-release" }, 672089Ssos { 480000, 480099, "/packages-4.8-release" }, 682089Ssos { 490000, 490099, "/packages-4.9-release" }, 692089Ssos { 491000, 491099, "/packages-4.10-release" }, 702089Ssos { 492000, 492099, "/packages-4.11-release" }, 716628Ssos { 500000, 500099, "/packages-5.0-release" }, 722089Ssos { 501000, 501099, "/packages-5.1-release" }, 73146736Sdelphij { 502000, 502009, "/packages-5.2-release" }, 74146736Sdelphij { 502010, 502099, "/packages-5.2.1-release" }, 75146736Sdelphij { 503000, 503099, "/packages-5.3-release" }, 76146736Sdelphij { 504000, 504099, "/packages-5.4-release" }, 77146736Sdelphij { 505000, 505099, "/packages-5.5-release" }, 78146736Sdelphij { 600000, 600099, "/packages-6.0-release" }, 79146736Sdelphij { 601000, 601099, "/packages-6.1-release" }, 802089Ssos { 602000, 602099, "/packages-6.2-release" }, 81146736Sdelphij { 300000, 399000, "/packages-3-stable" }, 82146736Sdelphij { 400000, 499000, "/packages-4-stable" }, 83146736Sdelphij { 502100, 502128, "/packages-5-current" }, 84146736Sdelphij { 503100, 599000, "/packages-5-stable" }, 85146736Sdelphij { 600100, 699000, "/packages-6-stable" }, 86146736Sdelphij { 700000, 799000, "/packages-7-current" }, 87146736Sdelphij { 0, 9999999, "/packages-current" }, 88146736Sdelphij { 0, 0, NULL } 89146736Sdelphij}; 90146736Sdelphij 91146736Sdelphijstatic char *getpackagesite(void); 92146736Sdelphijint getosreldate(void); 93146736Sdelphij 94146736Sdelphijstatic void usage __P((void)); 95146736Sdelphij 96146736Sdelphijint 97146736Sdelphijmain(int argc, char **argv) 98146736Sdelphij{ 99146736Sdelphij int ch, error; 100146736Sdelphij char **start; 101146736Sdelphij char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr; 102146736Sdelphij static char temppackageroot[MAXPATHLEN]; 103146736Sdelphij static char pkgaddpath[MAXPATHLEN]; 104146736Sdelphij 105146736Sdelphij if (*argv[0] != '/' && strchr(argv[0], '/') != NULL) 106146736Sdelphij PkgAddCmd = realpath(argv[0], pkgaddpath); 107146736Sdelphij else 108146736Sdelphij PkgAddCmd = argv[0]; 10930764Scharnier 110146736Sdelphij start = argv; 111146736Sdelphij while ((ch = getopt(argc, argv, Options)) != -1) { 112146736Sdelphij switch(ch) { 113146736Sdelphij case 'v': 114146736Sdelphij Verbose++; 115146736Sdelphij break; 116146736Sdelphij 117146736Sdelphij case 'p': 118146736Sdelphij Prefix = optarg; 119146736Sdelphij PrefixRecursive = FALSE; 120146736Sdelphij break; 121146736Sdelphij 122146736Sdelphij case 'P': 123146736Sdelphij Prefix = optarg; 124146736Sdelphij PrefixRecursive = TRUE; 125146736Sdelphij break; 126146736Sdelphij 127146736Sdelphij case 'I': 128146736Sdelphij NoInstall = TRUE; 129146736Sdelphij break; 130146736Sdelphij 131146736Sdelphij case 'R': 132146736Sdelphij NoRecord = TRUE; 133146736Sdelphij break; 134146736Sdelphij 135146736Sdelphij case 'f': 136146736Sdelphij Force = TRUE; 137146736Sdelphij break; 138146736Sdelphij 139146736Sdelphij case 'F': 140146736Sdelphij FailOnAlreadyInstalled = FALSE; 141146736Sdelphij break; 142146736Sdelphij 143146736Sdelphij case 'K': 144146736Sdelphij KeepPackage = TRUE; 145146736Sdelphij break; 146146736Sdelphij 147146736Sdelphij case 'n': 148146736Sdelphij Fake = TRUE; 149146736Sdelphij break; 150146736Sdelphij 151146736Sdelphij case 'r': 152146736Sdelphij Remote = TRUE; 153146736Sdelphij break; 154146736Sdelphij 155146736Sdelphij case 't': 156146736Sdelphij if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen)) 157146736Sdelphij errx(1, "-t Argument too long."); 158146736Sdelphij break; 159146736Sdelphij 160146736Sdelphij case 'S': 161146736Sdelphij AddMode = SLAVE; 162146736Sdelphij break; 163146736Sdelphij 164146736Sdelphij case 'M': 165146736Sdelphij AddMode = MASTER; 166146736Sdelphij break; 167146736Sdelphij 168146736Sdelphij case 'C': 169146736Sdelphij Chroot = optarg; 170146736Sdelphij break; 171146736Sdelphij 172146736Sdelphij case 'h': 173146736Sdelphij case '?': 174146736Sdelphij default: 175146736Sdelphij usage(); 176146736Sdelphij break; 177146736Sdelphij } 178146736Sdelphij } 179146736Sdelphij argc -= optind; 180146736Sdelphij argv += optind; 181146736Sdelphij 182140159Sdelphij if (argc > MAX_PKGS) { 1836628Ssos errx(1, "too many packages (max %d)", MAX_PKGS); 18499706Sdd } 185102111Ssobomax 18677329Sdes if (AddMode != SLAVE) { 18799706Sdd for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ; 18899706Sdd 18999706Sdd /* Get all the remaining package names, if any */ 19030764Scharnier for (ch = 0; *argv; ch++, argv++) { 1916628Ssos if (Remote) { 1926628Ssos if ((packagesite = getpackagesite()) == NULL) 193146736Sdelphij errx(1, "package name too long"); 194146736Sdelphij if (strlcpy(temppackageroot, packagesite, 195146736Sdelphij sizeof(temppackageroot)) >= sizeof(temppackageroot)) 196146736Sdelphij errx(1, "package name too long"); 197146736Sdelphij if (strlcat(temppackageroot, *argv, sizeof(temppackageroot)) 198146736Sdelphij >= sizeof(temppackageroot)) 199140159Sdelphij errx(1, "package name too long"); 20075344Ssobomax remotepkg = temppackageroot; 2012089Ssos if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' && 2022089Ssos (ptr[2] == 'b' || ptr[2] == 'g') && ptr[3] == 'z' && 2032089Ssos !ptr[4])) 204146736Sdelphij if (strlcat(remotepkg, 205146736Sdelphij#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 206146736Sdelphij ".tbz", 20775344Ssobomax#else 208146736Sdelphij ".tgz", 209146736Sdelphij#endif 21075344Ssobomax sizeof(temppackageroot)) >= sizeof(temppackageroot)) 2112089Ssos errx(1, "package name too long"); 2122089Ssos } 213146736Sdelphij if (!strcmp(*argv, "-")) /* stdin? */ 214146736Sdelphij pkgs[ch] = (char *)"-"; 215146736Sdelphij else if (isURL(*argv)) { /* preserve URLs */ 216146736Sdelphij if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 217146736Sdelphij >= sizeof(pkgnames[ch])) 218146736Sdelphij errx(1, "package name too long"); 219140159Sdelphij pkgs[ch] = pkgnames[ch]; 220140159Sdelphij } 2212089Ssos else if ((Remote) && isURL(remotepkg)) { 22292460Ssobomax if (strlcpy(pkgnames[ch], remotepkg, sizeof(pkgnames[ch])) 22392460Ssobomax >= sizeof(pkgnames[ch])) 2242089Ssos errx(1, "package name too long"); 22592460Ssobomax pkgs[ch] = pkgnames[ch]; 22692460Ssobomax } else { /* expand all pathnames to fullnames */ 22792460Ssobomax if (fexists(*argv)) /* refers to a file directly */ 22892460Ssobomax pkgs[ch] = realpath(*argv, pkgnames[ch]); 229146736Sdelphij else { /* look for the file in the expected places */ 230146736Sdelphij if (!(cp = fileFindByPath(NULL, *argv))) { 231146736Sdelphij /* let pkg_do() fail later, so that error is reported */ 23292460Ssobomax if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 233146736Sdelphij >= sizeof(pkgnames[ch])) 23492460Ssobomax errx(1, "package name too long"); 23592460Ssobomax pkgs[ch] = pkgnames[ch]; 236146736Sdelphij } else { 23792460Ssobomax if (strlcpy(pkgnames[ch], cp, sizeof(pkgnames[ch])) 23892460Ssobomax >= sizeof(pkgnames[ch])) 23992460Ssobomax errx(1, "package name too long"); 24092460Ssobomax pkgs[ch] = pkgnames[ch]; 24152262Sbillf } 24292460Ssobomax } 2432089Ssos } 2442089Ssos if (packagesite != NULL) 245146736Sdelphij packagesite[0] = '\0'; 246146736Sdelphij } 247146736Sdelphij } 248146736Sdelphij /* If no packages, yelp */ 249146736Sdelphij else if (!ch) { 250140159Sdelphij warnx("missing package name(s)"); 251140159Sdelphij usage(); 2522089Ssos } 25392460Ssobomax else if (ch > 1 && AddMode == MASTER) { 25492460Ssobomax warnx("only one package name may be specified with master mode"); 2552089Ssos usage(); 2562089Ssos } 257140159Sdelphij /* Perform chroot if requested */ 258140159Sdelphij if (Chroot != NULL) { 259140159Sdelphij if (chroot(Chroot)) 260140159Sdelphij errx(1, "chroot to %s failed", Chroot); 2612089Ssos } 26292460Ssobomax /* Make sure the sub-execs we invoke get found */ 263146736Sdelphij setenv("PATH", 2642089Ssos "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin", 265146736Sdelphij 1); 266146736Sdelphij 2672089Ssos /* Set a reasonable umask */ 268146736Sdelphij umask(022); 2692089Ssos 270146736Sdelphij if ((error = pkg_perform(pkgs)) != 0) { 27175344Ssobomax if (Verbose) 2722089Ssos warnx("%d package addition(s) failed", error); 273146736Sdelphij return error; 274146736Sdelphij } 27530764Scharnier else 27623457Sbrian return 0; 277146736Sdelphij} 278146736Sdelphij 2792089Ssosstatic char * 2802089Ssosgetpackagesite(void) 281146736Sdelphij{ 282146736Sdelphij int reldate, i; 283146736Sdelphij static char sitepath[MAXPATHLEN]; 284146736Sdelphij struct utsname u; 285146736Sdelphij 286146736Sdelphij if (getenv("PACKAGESITE")) { 28723457Sbrian if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath)) 2882089Ssos >= sizeof(sitepath)) 2892089Ssos return NULL; 290146736Sdelphij return sitepath; 291146736Sdelphij } 292146736Sdelphij 293146736Sdelphij if (getenv("PACKAGEROOT")) { 294146736Sdelphij if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath)) 295140159Sdelphij >= sizeof(sitepath)) 296140159Sdelphij return NULL; 2972089Ssos } else { 2986628Ssos if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath)) 2992089Ssos >= sizeof(sitepath)) 3002089Ssos return NULL; 3012089Ssos } 3022089Ssos 303146736Sdelphij if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath)) 304146736Sdelphij >= sizeof(sitepath)) 305146736Sdelphij return NULL; 306146736Sdelphij 307146736Sdelphij uname(&u); 3082089Ssos if (strlcat(sitepath, u.machine, sizeof(sitepath)) >= sizeof(sitepath)) 3092089Ssos return NULL; 310146736Sdelphij 311146736Sdelphij reldate = getosreldate(); 312146736Sdelphij for(i = 0; releases[i].directory != NULL; i++) { 313146736Sdelphij if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) { 314146736Sdelphij if (strlcat(sitepath, releases[i].directory, sizeof(sitepath)) 315140159Sdelphij >= sizeof(sitepath)) 316140159Sdelphij return NULL; 3172089Ssos break; 3182089Ssos } 319140159Sdelphij } 3202089Ssos 321146736Sdelphij if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath)) 322146736Sdelphij return NULL; 323146736Sdelphij 3242089Ssos return sitepath; 3252089Ssos 326140159Sdelphij} 3272089Ssos 328146736Sdelphijstatic void 329146736Sdelphijusage() 3308857Srgrimes{ 3312089Ssos fprintf(stderr, "%s\n%s\n", 3322089Ssos "usage: pkg_add [-vInrfRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]", 3332089Ssos " pkg-name [pkg-name ...]"); 3342089Ssos exit(1); 3352089Ssos} 3362089Ssos