main.c revision 131285
1184299Snwhitehorn/* 2184299Snwhitehorn * 3184299Snwhitehorn * FreeBSD install - a package for the installation and maintainance 4184299Snwhitehorn * of non-core utilities. 5184299Snwhitehorn * 6184299Snwhitehorn * Redistribution and use in source and binary forms, with or without 7184299Snwhitehorn * modification, are permitted provided that the following conditions 8184299Snwhitehorn * are met: 9184299Snwhitehorn * 1. Redistributions of source code must retain the above copyright 10184299Snwhitehorn * notice, this list of conditions and the following disclaimer. 11184299Snwhitehorn * 2. Redistributions in binary form must reproduce the above copyright 12184299Snwhitehorn * notice, this list of conditions and the following disclaimer in the 13184299Snwhitehorn * documentation and/or other materials provided with the distribution. 14184299Snwhitehorn * 15184299Snwhitehorn * Jordan K. Hubbard 16184299Snwhitehorn * 18 July 1993 17184299Snwhitehorn * 18184299Snwhitehorn * This is the add module. 19184299Snwhitehorn */ 20184299Snwhitehorn 21184299Snwhitehorn#include <sys/cdefs.h> 22184299Snwhitehorn__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 131285 2004-06-29 19:06:42Z eik $"); 23184299Snwhitehorn 24184299Snwhitehorn#include <err.h> 25184299Snwhitehorn#include <sys/param.h> 26184299Snwhitehorn#include <sys/utsname.h> 27184299Snwhitehorn#include "lib.h" 28184299Snwhitehorn#include "add.h" 29184299Snwhitehorn 30184299Snwhitehornstatic char Options[] = "hvIRfnrp:SMt:C:"; 31184299Snwhitehorn 32184299Snwhitehornchar *Prefix = NULL; 33184299Snwhitehornchar *Chroot = NULL; 34184299SnwhitehornBoolean NoInstall = FALSE; 35184299SnwhitehornBoolean NoRecord = FALSE; 36184299SnwhitehornBoolean Remote = FALSE; 37184299Snwhitehorn 38226449Snwhitehornchar *Mode = NULL; 39184299Snwhitehornchar *Owner = NULL; 40184299Snwhitehornchar *Group = NULL; 41184299Snwhitehornchar *PkgName = NULL; 42184299Snwhitehornchar *PkgAddCmd = NULL; 43184299Snwhitehornchar *Directory = NULL; 44184299Snwhitehornchar FirstPen[FILENAME_MAX]; 45226449Snwhitehornadd_mode_t AddMode = NORMAL; 46226449Snwhitehorn 47184299Snwhitehorn#define MAX_PKGS 200 48184299Snwhitehornchar pkgnames[MAX_PKGS][MAXPATHLEN]; 49184299Snwhitehornchar *pkgs[MAX_PKGS]; 50184299Snwhitehorn 51184299Snwhitehornstruct { 52184299Snwhitehorn int lowver; /* Lowest version number to match */ 53184299Snwhitehorn int hiver; /* Highest version number to match */ 54184299Snwhitehorn const char *directory; /* Directory it lives in */ 55184299Snwhitehorn} releases[] = { 56184299Snwhitehorn { 410000, 410000, "/packages-4.1-release" }, 57184299Snwhitehorn { 420000, 420000, "/packages-4.2-release" }, 58184299Snwhitehorn { 430000, 430000, "/packages-4.3-release" }, 59184299Snwhitehorn { 440000, 440000, "/packages-4.4-release" }, 60184299Snwhitehorn { 450000, 450000, "/packages-4.5-release" }, 61226449Snwhitehorn { 460000, 460001, "/packages-4.6-release" }, 62184299Snwhitehorn { 460002, 460099, "/packages-4.6.2-release" }, 63184299Snwhitehorn { 470000, 470099, "/packages-4.7-release" }, 64184299Snwhitehorn { 480000, 480099, "/packages-4.8-release" }, 65184299Snwhitehorn { 490000, 490099, "/packages-4.9-release" }, 66184299Snwhitehorn { 491000, 491099, "/packages-4.10-release" }, 67184299Snwhitehorn { 492000, 492099, "/packages-4.11-release" }, 68184299Snwhitehorn { 500000, 500099, "/packages-5.0-release" }, 69184299Snwhitehorn { 501000, 501099, "/packages-5.1-release" }, 70184299Snwhitehorn { 502000, 502009, "/packages-5.2-release" }, 71184299Snwhitehorn { 502010, 502099, "/packages-5.2.1-release" }, 72184299Snwhitehorn { 503000, 503099, "/packages-5.3-release" }, 73184299Snwhitehorn { 300000, 399000, "/packages-3-stable" }, 74184299Snwhitehorn { 400000, 499000, "/packages-4-stable" }, 75184299Snwhitehorn { 502100, 599000, "/packages-5-current" }, 76184299Snwhitehorn { 0, 9999999, "/packages-current" }, 77184299Snwhitehorn { 0, 0, NULL } 78184299Snwhitehorn}; 79186906Snwhitehorn 80186906Snwhitehornstatic char *getpackagesite(void); 81186906Snwhitehornint getosreldate(void); 82184299Snwhitehorn 83184299Snwhitehornstatic void usage __P((void)); 84184299Snwhitehorn 85184299Snwhitehornint 86184299Snwhitehornmain(int argc, char **argv) 87184299Snwhitehorn{ 88184299Snwhitehorn int ch, error; 89184299Snwhitehorn char **start; 90184299Snwhitehorn char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr; 91184299Snwhitehorn static char temppackageroot[MAXPATHLEN]; 92184299Snwhitehorn static char pkgaddpath[MAXPATHLEN]; 93184299Snwhitehorn 94184299Snwhitehorn if (*argv[0] != '/' && strchr(argv[0], '/') != NULL) 95184299Snwhitehorn PkgAddCmd = realpath(argv[0], pkgaddpath); 96184299Snwhitehorn else 97184299Snwhitehorn PkgAddCmd = argv[0]; 98184299Snwhitehorn 99184299Snwhitehorn start = argv; 100184299Snwhitehorn while ((ch = getopt(argc, argv, Options)) != -1) { 101184299Snwhitehorn switch(ch) { 102184299Snwhitehorn case 'v': 103184299Snwhitehorn Verbose = TRUE; 104184299Snwhitehorn break; 105184299Snwhitehorn 106184299Snwhitehorn case 'p': 107184299Snwhitehorn Prefix = optarg; 108184299Snwhitehorn break; 109184299Snwhitehorn 110184299Snwhitehorn case 'I': 111184299Snwhitehorn NoInstall = TRUE; 112184299Snwhitehorn break; 113184299Snwhitehorn 114184299Snwhitehorn case 'R': 115186906Snwhitehorn NoRecord = TRUE; 116186906Snwhitehorn break; 117186906Snwhitehorn 118186906Snwhitehorn case 'f': 119186906Snwhitehorn Force = TRUE; 120186906Snwhitehorn break; 121186906Snwhitehorn 122186906Snwhitehorn case 'n': 123186906Snwhitehorn Fake = TRUE; 124186906Snwhitehorn Verbose = TRUE; 125186906Snwhitehorn break; 126184299Snwhitehorn 127184299Snwhitehorn case 'r': 128184299Snwhitehorn Remote = TRUE; 129184299Snwhitehorn break; 130184299Snwhitehorn 131184299Snwhitehorn case 't': 132184299Snwhitehorn if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen)) 133184299Snwhitehorn errx(1, "-t Argument too long."); 134184299Snwhitehorn break; 135186906Snwhitehorn 136186906Snwhitehorn case 'S': 137186906Snwhitehorn AddMode = SLAVE; 138186906Snwhitehorn break; 139186906Snwhitehorn 140186906Snwhitehorn case 'M': 141186906Snwhitehorn AddMode = MASTER; 142186906Snwhitehorn break; 143186906Snwhitehorn 144186906Snwhitehorn case 'C': 145186906Snwhitehorn Chroot = optarg; 146186906Snwhitehorn break; 147186906Snwhitehorn 148186906Snwhitehorn case 'h': 149186906Snwhitehorn case '?': 150186906Snwhitehorn default: 151186906Snwhitehorn usage(); 152186906Snwhitehorn break; 153186906Snwhitehorn } 154186906Snwhitehorn } 155186906Snwhitehorn argc -= optind; 156186906Snwhitehorn argv += optind; 157186906Snwhitehorn 158186906Snwhitehorn if (argc > MAX_PKGS) { 159186906Snwhitehorn errx(1, "too many packages (max %d)", MAX_PKGS); 160186906Snwhitehorn } 161186906Snwhitehorn 162186906Snwhitehorn if (AddMode != SLAVE) { 163186906Snwhitehorn for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ; 164186906Snwhitehorn 165186906Snwhitehorn /* Get all the remaining package names, if any */ 166186906Snwhitehorn for (ch = 0; *argv; ch++, argv++) { 167186906Snwhitehorn if (Remote) { 168186906Snwhitehorn if ((packagesite = getpackagesite()) == NULL) 169186906Snwhitehorn errx(1, "package name too long"); 170186906Snwhitehorn if (strlcpy(temppackageroot, packagesite, 171186906Snwhitehorn sizeof(temppackageroot)) >= sizeof(temppackageroot)) 172186906Snwhitehorn errx(1, "package name too long"); 173186906Snwhitehorn if (strlcat(temppackageroot, *argv, sizeof(temppackageroot)) 174186906Snwhitehorn >= sizeof(temppackageroot)) 175186906Snwhitehorn errx(1, "package name too long"); 176184299Snwhitehorn remotepkg = temppackageroot; 177184299Snwhitehorn if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' && 178184299Snwhitehorn (ptr[2] == 'b' || ptr[2] == 'g') && ptr[3] == 'z' && 179184299Snwhitehorn !ptr[4])) 180184299Snwhitehorn if (strlcat(remotepkg, 181184299Snwhitehorn#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 182184299Snwhitehorn ".tbz", 183184299Snwhitehorn#else 184184299Snwhitehorn ".tgz", 185184299Snwhitehorn#endif 186184299Snwhitehorn sizeof(temppackageroot)) >= sizeof(temppackageroot)) 187184299Snwhitehorn errx(1, "package name too long"); 188184299Snwhitehorn } 189184299Snwhitehorn if (!strcmp(*argv, "-")) /* stdin? */ 190184299Snwhitehorn (const char *)pkgs[ch] = "-"; 191184299Snwhitehorn else if (isURL(*argv)) { /* preserve URLs */ 192184299Snwhitehorn if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 193184299Snwhitehorn >= sizeof(pkgnames[ch])) 194184299Snwhitehorn errx(1, "package name too long"); 195184299Snwhitehorn pkgs[ch] = pkgnames[ch]; 196184299Snwhitehorn } 197184299Snwhitehorn else if ((Remote) && isURL(remotepkg)) { 198184299Snwhitehorn if (strlcpy(pkgnames[ch], remotepkg, sizeof(pkgnames[ch])) 199184299Snwhitehorn >= sizeof(pkgnames[ch])) 200184299Snwhitehorn errx(1, "package name too long"); 201184299Snwhitehorn pkgs[ch] = pkgnames[ch]; 202184299Snwhitehorn } else { /* expand all pathnames to fullnames */ 203184299Snwhitehorn if (fexists(*argv)) /* refers to a file directly */ 204184299Snwhitehorn pkgs[ch] = realpath(*argv, pkgnames[ch]); 205184299Snwhitehorn else { /* look for the file in the expected places */ 206184299Snwhitehorn if (!(cp = fileFindByPath(NULL, *argv))) { 207184299Snwhitehorn /* let pkg_do() fail later, so that error is reported */ 208184299Snwhitehorn if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 209184299Snwhitehorn >= sizeof(pkgnames[ch])) 210184299Snwhitehorn errx(1, "package name too long"); 211184299Snwhitehorn pkgs[ch] = pkgnames[ch]; 212184299Snwhitehorn } else { 213184299Snwhitehorn if (strlcpy(pkgnames[ch], cp, sizeof(pkgnames[ch])) 214184299Snwhitehorn >= sizeof(pkgnames[ch])) 215184299Snwhitehorn errx(1, "package name too long"); 216184299Snwhitehorn pkgs[ch] = pkgnames[ch]; 217184299Snwhitehorn } 218184299Snwhitehorn } 219184299Snwhitehorn } 220184299Snwhitehorn if (packagesite != NULL) 221184299Snwhitehorn packagesite[0] = '\0'; 222184299Snwhitehorn } 223184299Snwhitehorn } 224184299Snwhitehorn /* If no packages, yelp */ 225184299Snwhitehorn else if (!ch) { 226184299Snwhitehorn warnx("missing package name(s)"); 227184299Snwhitehorn usage(); 228184299Snwhitehorn } 229184299Snwhitehorn else if (ch > 1 && AddMode == MASTER) { 230184299Snwhitehorn warnx("only one package name may be specified with master mode"); 231184299Snwhitehorn usage(); 232184299Snwhitehorn } 233184299Snwhitehorn /* Perform chroot if requested */ 234184299Snwhitehorn if (Chroot != NULL) { 235184299Snwhitehorn if (chroot(Chroot)) 236184299Snwhitehorn errx(1, "chroot to %s failed", Chroot); 237184299Snwhitehorn } 238184299Snwhitehorn /* Make sure the sub-execs we invoke get found */ 239184299Snwhitehorn setenv("PATH", 240184299Snwhitehorn "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin", 241184299Snwhitehorn 1); 242184299Snwhitehorn 243184299Snwhitehorn /* Set a reasonable umask */ 244184299Snwhitehorn umask(022); 245184299Snwhitehorn 246184299Snwhitehorn if ((error = pkg_perform(pkgs)) != 0) { 247184299Snwhitehorn if (Verbose) 248184299Snwhitehorn warnx("%d package addition(s) failed", error); 249184299Snwhitehorn return error; 250184299Snwhitehorn } 251184299Snwhitehorn else 252184299Snwhitehorn return 0; 253184299Snwhitehorn} 254184299Snwhitehorn 255184299Snwhitehornstatic char * 256184299Snwhitehorngetpackagesite(void) 257184299Snwhitehorn{ 258184299Snwhitehorn int reldate, i; 259184299Snwhitehorn static char sitepath[MAXPATHLEN]; 260184299Snwhitehorn struct utsname u; 261184299Snwhitehorn 262184299Snwhitehorn if (getenv("PACKAGESITE")) { 263184299Snwhitehorn if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath)) 264184299Snwhitehorn >= sizeof(sitepath)) 265184299Snwhitehorn return NULL; 266184299Snwhitehorn return sitepath; 267184299Snwhitehorn } 268184299Snwhitehorn 269184299Snwhitehorn if (getenv("PACKAGEROOT")) { 270184299Snwhitehorn if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath)) 271184299Snwhitehorn >= sizeof(sitepath)) 272184299Snwhitehorn return NULL; 273184299Snwhitehorn } else { 274184299Snwhitehorn if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath)) 275184299Snwhitehorn >= sizeof(sitepath)) 276184299Snwhitehorn return NULL; 277184299Snwhitehorn } 278184299Snwhitehorn 279184299Snwhitehorn if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath)) 280184299Snwhitehorn >= sizeof(sitepath)) 281184299Snwhitehorn return NULL; 282184299Snwhitehorn 283184299Snwhitehorn uname(&u); 284184299Snwhitehorn if (strlcat(sitepath, u.machine, sizeof(sitepath)) >= sizeof(sitepath)) 285184299Snwhitehorn return NULL; 286184299Snwhitehorn 287184299Snwhitehorn reldate = getosreldate(); 288184299Snwhitehorn for(i = 0; releases[i].directory != NULL; i++) { 289226449Snwhitehorn if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) { 290226449Snwhitehorn if (strlcat(sitepath, releases[i].directory, sizeof(sitepath)) 291184299Snwhitehorn >= sizeof(sitepath)) 292184299Snwhitehorn return NULL; 293184299Snwhitehorn break; 294184299Snwhitehorn } 295184299Snwhitehorn } 296184299Snwhitehorn 297184299Snwhitehorn if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath)) 298184299Snwhitehorn return NULL; 299184299Snwhitehorn 300184299Snwhitehorn return sitepath; 301184299Snwhitehorn 302184299Snwhitehorn} 303184299Snwhitehorn 304184299Snwhitehornstatic void 305184299Snwhitehornusage() 306184299Snwhitehorn{ 307262668Sjhibbits fprintf(stderr, "%s\n%s\n", 308184299Snwhitehorn "usage: pkg_add [-vInrfRMS] [-t template] [-p prefix] [-C chrootdir]", 309184299Snwhitehorn " pkg-name [pkg-name ...]"); 310184299Snwhitehorn exit(1); 311184299Snwhitehorn} 312184299Snwhitehorn