main.c revision 152329
138032Speter/* 2261363Sgshapiro * 364562Sgshapiro * FreeBSD install - a package for the installation and maintainance 438032Speter * of non-core utilities. 538032Speter * 638032Speter * Redistribution and use in source and binary forms, with or without 738032Speter * modification, are permitted provided that the following conditions 838032Speter * are met: 938032Speter * 1. Redistributions of source code must retain the above copyright 1038032Speter * notice, this list of conditions and the following disclaimer. 1138032Speter * 2. Redistributions in binary form must reproduce the above copyright 1238032Speter * notice, this list of conditions and the following disclaimer in the 1338032Speter * documentation and/or other materials provided with the distribution. 1464562Sgshapiro * 1538032Speter * Jordan K. Hubbard 16266692Sgshapiro * 18 July 1993 1790792Sgshapiro * 18168515Sgshapiro * This is the add module. 1971345Sgshapiro */ 2071345Sgshapiro 2171345Sgshapiro#include <sys/cdefs.h> 2238032Speter__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 152329 2005-11-12 11:45:01Z krion $"); 2390792Sgshapiro 24173340Sgshapiro#include <err.h> 25173340Sgshapiro#include <sys/param.h> 26173340Sgshapiro#include <sys/utsname.h> 27173340Sgshapiro#include "lib.h" 28173340Sgshapiro#include "add.h" 29173340Sgshapiro 30173340Sgshapirostatic char Options[] = "hvIRfnrp:P:SMt:C:"; 31173340Sgshapiro 32173340Sgshapirochar *Prefix = NULL; 33173340SgshapiroBoolean PrefixRecursive = FALSE; 34173340Sgshapirochar *Chroot = NULL; 35173340SgshapiroBoolean NoInstall = FALSE; 36173340SgshapiroBoolean NoRecord = FALSE; 37173340SgshapiroBoolean Remote = FALSE; 38173340Sgshapiro 39173340Sgshapirochar *Mode = NULL; 40173340Sgshapirochar *Owner = NULL; 41173340Sgshapirochar *Group = NULL; 42173340Sgshapirochar *PkgName = NULL; 43173340Sgshapirochar *PkgAddCmd = NULL; 44173340Sgshapirochar *Directory = NULL; 45173340Sgshapirochar FirstPen[FILENAME_MAX]; 46173340Sgshapiroadd_mode_t AddMode = NORMAL; 47173340Sgshapiro 48173340Sgshapiro#define MAX_PKGS 200 49173340Sgshapirochar pkgnames[MAX_PKGS][MAXPATHLEN]; 50173340Sgshapirochar *pkgs[MAX_PKGS]; 51173340Sgshapiro 52173340Sgshapirostruct { 53173340Sgshapiro int lowver; /* Lowest version number to match */ 54173340Sgshapiro int hiver; /* Highest version number to match */ 55173340Sgshapiro const char *directory; /* Directory it lives in */ 56173340Sgshapiro} releases[] = { 57173340Sgshapiro { 410000, 410000, "/packages-4.1-release" }, 58173340Sgshapiro { 420000, 420000, "/packages-4.2-release" }, 59173340Sgshapiro { 430000, 430000, "/packages-4.3-release" }, 60173340Sgshapiro { 440000, 440000, "/packages-4.4-release" }, 61173340Sgshapiro { 450000, 450000, "/packages-4.5-release" }, 62173340Sgshapiro { 460000, 460001, "/packages-4.6-release" }, 63173340Sgshapiro { 460002, 460099, "/packages-4.6.2-release" }, 64173340Sgshapiro { 470000, 470099, "/packages-4.7-release" }, 65173340Sgshapiro { 480000, 480099, "/packages-4.8-release" }, 66173340Sgshapiro { 490000, 490099, "/packages-4.9-release" }, 67173340Sgshapiro { 491000, 491099, "/packages-4.10-release" }, 68173340Sgshapiro { 492000, 492099, "/packages-4.11-release" }, 69173340Sgshapiro { 500000, 500099, "/packages-5.0-release" }, 70173340Sgshapiro { 501000, 501099, "/packages-5.1-release" }, 71173340Sgshapiro { 502000, 502009, "/packages-5.2-release" }, 72173340Sgshapiro { 502010, 502099, "/packages-5.2.1-release" }, 73173340Sgshapiro { 503000, 503099, "/packages-5.3-release" }, 74173340Sgshapiro { 504000, 504099, "/packages-5.4-release" }, 75173340Sgshapiro { 600000, 600099, "/packages-6.0-release" }, 76173340Sgshapiro { 300000, 399000, "/packages-3-stable" }, 77173340Sgshapiro { 400000, 499000, "/packages-4-stable" }, 78173340Sgshapiro { 502100, 502128, "/packages-5-current" }, 79173340Sgshapiro { 503100, 599000, "/packages-5-stable" }, 80173340Sgshapiro { 600100, 699000, "/packages-6-stable" }, 81173340Sgshapiro { 700000, 799000, "/packages-7-current" }, 8290792Sgshapiro { 0, 9999999, "/packages-current" }, 83173340Sgshapiro { 0, 0, NULL } 84173340Sgshapiro}; 8538032Speter 86168515Sgshapirostatic char *getpackagesite(void); 8738032Speterint getosreldate(void); 8890792Sgshapiro 8990792Sgshapirostatic void usage __P((void)); 9090792Sgshapiro 9190792Sgshapiroint 9290792Sgshapiromain(int argc, char **argv) 9390792Sgshapiro{ 9490792Sgshapiro int ch, error; 9590792Sgshapiro char **start; 9690792Sgshapiro char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr; 9790792Sgshapiro static char temppackageroot[MAXPATHLEN]; 9890792Sgshapiro static char pkgaddpath[MAXPATHLEN]; 9990792Sgshapiro 10090792Sgshapiro if (*argv[0] != '/' && strchr(argv[0], '/') != NULL) 10190792Sgshapiro PkgAddCmd = realpath(argv[0], pkgaddpath); 10290792Sgshapiro else 10390792Sgshapiro PkgAddCmd = argv[0]; 10490792Sgshapiro 10590792Sgshapiro start = argv; 10690792Sgshapiro while ((ch = getopt(argc, argv, Options)) != -1) { 10790792Sgshapiro switch(ch) { 10890792Sgshapiro case 'v': 10990792Sgshapiro Verbose = TRUE; 11090792Sgshapiro break; 11190792Sgshapiro 11290792Sgshapiro case 'p': 11390792Sgshapiro Prefix = optarg; 11490792Sgshapiro PrefixRecursive = FALSE; 11590792Sgshapiro break; 11690792Sgshapiro 11790792Sgshapiro case 'P': 11890792Sgshapiro Prefix = optarg; 11990792Sgshapiro PrefixRecursive = TRUE; 12090792Sgshapiro break; 12190792Sgshapiro 12290792Sgshapiro case 'I': 12390792Sgshapiro NoInstall = TRUE; 12490792Sgshapiro break; 12590792Sgshapiro 12690792Sgshapiro case 'R': 12790792Sgshapiro NoRecord = TRUE; 12890792Sgshapiro break; 12990792Sgshapiro 13090792Sgshapiro case 'f': 13190792Sgshapiro Force = TRUE; 132168515Sgshapiro break; 13390792Sgshapiro 134168515Sgshapiro case 'n': 135168515Sgshapiro Fake = TRUE; 13690792Sgshapiro Verbose = TRUE; 13790792Sgshapiro break; 13890792Sgshapiro 13990792Sgshapiro case 'r': 14090792Sgshapiro Remote = TRUE; 14190792Sgshapiro break; 14290792Sgshapiro 14390792Sgshapiro case 't': 14490792Sgshapiro if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen)) 14590792Sgshapiro errx(1, "-t Argument too long."); 14690792Sgshapiro break; 14790792Sgshapiro 14890792Sgshapiro case 'S': 14990792Sgshapiro AddMode = SLAVE; 15090792Sgshapiro break; 15190792Sgshapiro 15290792Sgshapiro case 'M': 15390792Sgshapiro AddMode = MASTER; 15490792Sgshapiro break; 15590792Sgshapiro 15690792Sgshapiro case 'C': 15790792Sgshapiro Chroot = optarg; 15890792Sgshapiro break; 159168515Sgshapiro 16090792Sgshapiro case 'h': 161168515Sgshapiro case '?': 16238032Speter default: 163168515Sgshapiro usage(); 164168515Sgshapiro break; 165168515Sgshapiro } 166168515Sgshapiro } 16738032Speter argc -= optind; 16838032Speter argv += optind; 16938032Speter 17038032Speter if (argc > MAX_PKGS) { 171168515Sgshapiro errx(1, "too many packages (max %d)", MAX_PKGS); 17238032Speter } 17338032Speter 17438032Speter if (AddMode != SLAVE) { 17538032Speter for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ; 17638032Speter 17738032Speter /* Get all the remaining package names, if any */ 17838032Speter for (ch = 0; *argv; ch++, argv++) { 17938032Speter if (Remote) { 18038032Speter if ((packagesite = getpackagesite()) == NULL) 181168515Sgshapiro errx(1, "package name too long"); 182168515Sgshapiro if (strlcpy(temppackageroot, packagesite, 183168515Sgshapiro sizeof(temppackageroot)) >= sizeof(temppackageroot)) 184168515Sgshapiro errx(1, "package name too long"); 185168515Sgshapiro if (strlcat(temppackageroot, *argv, sizeof(temppackageroot)) 186168515Sgshapiro >= sizeof(temppackageroot)) 18738032Speter errx(1, "package name too long"); 188168515Sgshapiro remotepkg = temppackageroot; 189168515Sgshapiro if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' && 19038032Speter (ptr[2] == 'b' || ptr[2] == 'g') && ptr[3] == 'z' && 191168515Sgshapiro !ptr[4])) 192168515Sgshapiro if (strlcat(remotepkg, 19338032Speter#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 19490792Sgshapiro ".tbz", 19590792Sgshapiro#else 19638032Speter ".tgz", 19738032Speter#endif 198168515Sgshapiro sizeof(temppackageroot)) >= sizeof(temppackageroot)) 19938032Speter errx(1, "package name too long"); 20038032Speter } 20138032Speter if (!strcmp(*argv, "-")) /* stdin? */ 20238032Speter pkgs[ch] = (char *)"-"; 20390792Sgshapiro else if (isURL(*argv)) { /* preserve URLs */ 204132943Sgshapiro if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 20590792Sgshapiro >= sizeof(pkgnames[ch])) 20638032Speter errx(1, "package name too long"); 20738032Speter pkgs[ch] = pkgnames[ch]; 20890792Sgshapiro } 20990792Sgshapiro else if ((Remote) && isURL(remotepkg)) { 21038032Speter if (strlcpy(pkgnames[ch], remotepkg, sizeof(pkgnames[ch])) 21138032Speter >= sizeof(pkgnames[ch])) 212168515Sgshapiro errx(1, "package name too long"); 21338032Speter pkgs[ch] = pkgnames[ch]; 21438032Speter } else { /* expand all pathnames to fullnames */ 21538032Speter if (fexists(*argv)) /* refers to a file directly */ 21638032Speter pkgs[ch] = realpath(*argv, pkgnames[ch]); 21738032Speter else { /* look for the file in the expected places */ 21838032Speter if (!(cp = fileFindByPath(NULL, *argv))) { 21938032Speter /* let pkg_do() fail later, so that error is reported */ 22038032Speter if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 22138032Speter >= sizeof(pkgnames[ch])) 22238032Speter errx(1, "package name too long"); 22338032Speter pkgs[ch] = pkgnames[ch]; 22438032Speter } else { 225168515Sgshapiro if (strlcpy(pkgnames[ch], cp, sizeof(pkgnames[ch])) 226168515Sgshapiro >= sizeof(pkgnames[ch])) 227168515Sgshapiro errx(1, "package name too long"); 22838032Speter pkgs[ch] = pkgnames[ch]; 229168515Sgshapiro } 230168515Sgshapiro } 231168515Sgshapiro } 232168515Sgshapiro if (packagesite != NULL) 233168515Sgshapiro packagesite[0] = '\0'; 234168515Sgshapiro } 23538032Speter } 23638032Speter /* If no packages, yelp */ 237168515Sgshapiro else if (!ch) { 23838032Speter warnx("missing package name(s)"); 23938032Speter usage(); 24038032Speter } 24164562Sgshapiro else if (ch > 1 && AddMode == MASTER) { 24264562Sgshapiro warnx("only one package name may be specified with master mode"); 24364562Sgshapiro usage(); 24464562Sgshapiro } 24564562Sgshapiro /* Perform chroot if requested */ 24664562Sgshapiro if (Chroot != NULL) { 24738032Speter if (chroot(Chroot)) 24838032Speter errx(1, "chroot to %s failed", Chroot); 24938032Speter } 25038032Speter /* Make sure the sub-execs we invoke get found */ 25190792Sgshapiro setenv("PATH", 25238032Speter "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin", 25338032Speter 1); 25438032Speter 25538032Speter /* Set a reasonable umask */ 25638032Speter umask(022); 25738032Speter 25890792Sgshapiro if ((error = pkg_perform(pkgs)) != 0) { 25938032Speter if (Verbose) 26038032Speter warnx("%d package addition(s) failed", error); 26190792Sgshapiro return error; 26238032Speter } 26338032Speter else 26438032Speter return 0; 26538032Speter} 26638032Speter 26771345Sgshapirostatic char * 26838032Spetergetpackagesite(void) 26938032Speter{ 27038032Speter int reldate, i; 27138032Speter static char sitepath[MAXPATHLEN]; 27238032Speter struct utsname u; 27338032Speter 27438032Speter if (getenv("PACKAGESITE")) { 27538032Speter if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath)) 27638032Speter >= sizeof(sitepath)) 27738032Speter return NULL; 278168515Sgshapiro return sitepath; 279168515Sgshapiro } 280168515Sgshapiro 281168515Sgshapiro if (getenv("PACKAGEROOT")) { 282168515Sgshapiro if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath)) 28338032Speter >= sizeof(sitepath)) 28438032Speter return NULL; 28538032Speter } else { 28638032Speter if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath)) 28738032Speter >= sizeof(sitepath)) 28838032Speter return NULL; 289168515Sgshapiro } 290168515Sgshapiro 29138032Speter if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath)) 29238032Speter >= sizeof(sitepath)) 29338032Speter return NULL; 29438032Speter 29538032Speter uname(&u); 29638032Speter if (strlcat(sitepath, u.machine, sizeof(sitepath)) >= sizeof(sitepath)) 297168515Sgshapiro return NULL; 298168515Sgshapiro 299168515Sgshapiro reldate = getosreldate(); 300168515Sgshapiro for(i = 0; releases[i].directory != NULL; i++) { 30138032Speter if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) { 30238032Speter if (strlcat(sitepath, releases[i].directory, sizeof(sitepath)) 303168515Sgshapiro >= sizeof(sitepath)) 30490792Sgshapiro return NULL; 30538032Speter break; 306168515Sgshapiro } 307168515Sgshapiro } 308168515Sgshapiro 30938032Speter if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath)) 31038032Speter return NULL; 31138032Speter 31238032Speter return sitepath; 31338032Speter 314168515Sgshapiro} 31538032Speter 316168515Sgshapirostatic void 317132943Sgshapirousage() 31890792Sgshapiro{ 31938032Speter fprintf(stderr, "%s\n%s\n", 32038032Speter "usage: pkg_add [-vInrfRMS] [-t template] [-p prefix] [-P prefix] [-C chrootdir]", 32138032Speter " pkg-name [pkg-name ...]"); 32238032Speter exit(1); 32338032Speter} 32438032Speter