main.c revision 159554
111820Sjulian/* 211820Sjulian * 311820Sjulian * FreeBSD install - a package for the installation and maintainance 411820Sjulian * of non-core utilities. 511820Sjulian * 611820Sjulian * Redistribution and use in source and binary forms, with or without 711820Sjulian * modification, are permitted provided that the following conditions 811820Sjulian * are met: 911820Sjulian * 1. Redistributions of source code must retain the above copyright 1011820Sjulian * notice, this list of conditions and the following disclaimer. 1111820Sjulian * 2. Redistributions in binary form must reproduce the above copyright 1211820Sjulian * notice, this list of conditions and the following disclaimer in the 1311820Sjulian * documentation and/or other materials provided with the distribution. 1411820Sjulian * 1511820Sjulian * Jordan K. Hubbard 1611820Sjulian * 18 July 1993 1711820Sjulian * 1811820Sjulian * This is the add module. 1911820Sjulian */ 2011820Sjulian 2111820Sjulian#include <sys/cdefs.h> 2211820Sjulian__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 159554 2006-06-12 22:39:32Z obrien $"); 2311820Sjulian 2411820Sjulian#include <err.h> 2511820Sjulian#include <sys/param.h> 2611820Sjulian#include <sys/utsname.h> 2711820Sjulian#include "lib.h" 2811820Sjulian#include "add.h" 2911820Sjulian 3011820Sjulianstatic char Options[] = "hvIRfFnrp:P:SMt:C:K"; 3111820Sjulian 3211820Sjulianchar *Prefix = NULL; 3311820SjulianBoolean PrefixRecursive = FALSE; 3411820Sjulianchar *Chroot = NULL; 3511820SjulianBoolean NoInstall = FALSE; 3611820SjulianBoolean NoRecord = FALSE; 3711820SjulianBoolean Remote = FALSE; 3850479SpeterBoolean KeepPackage = FALSE; 3911820SjulianBoolean FailOnAlreadyInstalled = TRUE; 4011820Sjulian 4111820Sjulianchar *Mode = NULL; 42122760Strhodeschar *Owner = NULL; 4311820Sjulianchar *Group = NULL; 4411820Sjulianchar *PkgName = NULL; 4511820Sjulianchar *PkgAddCmd = NULL; 4611820Sjulianchar *Directory = NULL; 4711820Sjulianchar FirstPen[FILENAME_MAX]; 4811820Sjulianadd_mode_t AddMode = NORMAL; 4911820Sjulian 5011820Sjulian#define MAX_PKGS 200 5111820Sjulianchar pkgnames[MAX_PKGS][MAXPATHLEN]; 5211820Sjulianchar *pkgs[MAX_PKGS]; 5311820Sjulian 5411820Sjulianstruct { 5511820Sjulian int lowver; /* Lowest version number to match */ 5611820Sjulian int hiver; /* Highest version number to match */ 5711820Sjulian const char *directory; /* Directory it lives in */ 5811820Sjulian} releases[] = { 5911820Sjulian { 410000, 410000, "/packages-4.1-release" }, 6011820Sjulian { 420000, 420000, "/packages-4.2-release" }, 6111820Sjulian { 430000, 430000, "/packages-4.3-release" }, 6211820Sjulian { 440000, 440000, "/packages-4.4-release" }, 6311820Sjulian { 450000, 450000, "/packages-4.5-release" }, 6411820Sjulian { 460000, 460001, "/packages-4.6-release" }, 6511820Sjulian { 460002, 460099, "/packages-4.6.2-release" }, 6627244Sjhay { 470000, 470099, "/packages-4.7-release" }, 6711820Sjulian { 480000, 480099, "/packages-4.8-release" }, 6811820Sjulian { 490000, 490099, "/packages-4.9-release" }, 6911820Sjulian { 491000, 491099, "/packages-4.10-release" }, 7011820Sjulian { 492000, 492099, "/packages-4.11-release" }, 7111820Sjulian { 500000, 500099, "/packages-5.0-release" }, 7211820Sjulian { 501000, 501099, "/packages-5.1-release" }, 7311820Sjulian { 502000, 502009, "/packages-5.2-release" }, 7411820Sjulian { 502010, 502099, "/packages-5.2.1-release" }, 7511820Sjulian { 503000, 503099, "/packages-5.3-release" }, 7627244Sjhay { 504000, 504099, "/packages-5.4-release" }, 7711820Sjulian { 600000, 600099, "/packages-6.0-release" }, 7811820Sjulian { 300000, 399000, "/packages-3-stable" }, 7911820Sjulian { 400000, 499000, "/packages-4-stable" }, 8011820Sjulian { 502100, 502128, "/packages-5-current" }, 8111820Sjulian { 503100, 599000, "/packages-5-stable" }, 8211820Sjulian { 600100, 699000, "/packages-6-stable" }, 8311820Sjulian { 700000, 799000, "/packages-7-current" }, 8411820Sjulian { 0, 9999999, "/packages-current" }, 8511820Sjulian { 0, 0, NULL } 8611820Sjulian}; 8711820Sjulian 8811820Sjulianstatic char *getpackagesite(void); 8911820Sjulianint getosreldate(void); 9011820Sjulian 9111820Sjulianstatic void usage __P((void)); 9211820Sjulian 9311820Sjulianint 9411820Sjulianmain(int argc, char **argv) 9511820Sjulian{ 9611820Sjulian int ch, error; 9711820Sjulian char **start; 9811820Sjulian char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr; 9911820Sjulian static char temppackageroot[MAXPATHLEN]; 10011820Sjulian static char pkgaddpath[MAXPATHLEN]; 10111820Sjulian 10211820Sjulian if (*argv[0] != '/' && strchr(argv[0], '/') != NULL) 10311820Sjulian PkgAddCmd = realpath(argv[0], pkgaddpath); 10411820Sjulian else 10511820Sjulian PkgAddCmd = argv[0]; 10611820Sjulian 10711820Sjulian start = argv; 10811820Sjulian while ((ch = getopt(argc, argv, Options)) != -1) { 10911820Sjulian switch(ch) { 11011820Sjulian case 'v': 11111820Sjulian Verbose++; 11211820Sjulian break; 11327244Sjhay 11411820Sjulian case 'p': 11527244Sjhay Prefix = optarg; 11627244Sjhay PrefixRecursive = FALSE; 11711820Sjulian break; 11811820Sjulian 11911820Sjulian case 'P': 12011820Sjulian Prefix = optarg; 12111820Sjulian PrefixRecursive = TRUE; 12211820Sjulian break; 12311820Sjulian 12411820Sjulian case 'I': 12511820Sjulian NoInstall = TRUE; 12611820Sjulian break; 12711820Sjulian 12827244Sjhay case 'R': 12927244Sjhay NoRecord = TRUE; 13011820Sjulian break; 13111820Sjulian 13211820Sjulian case 'f': 13311820Sjulian Force = TRUE; 13411820Sjulian break; 13511820Sjulian 13611820Sjulian case 'F': 13727244Sjhay FailOnAlreadyInstalled = FALSE; 13811820Sjulian break; 13911820Sjulian 14011820Sjulian case 'K': 14111820Sjulian KeepPackage = TRUE; 14227244Sjhay break; 14311820Sjulian 14411820Sjulian case 'n': 14511820Sjulian Fake = TRUE; 14611820Sjulian break; 14711820Sjulian 14811820Sjulian case 'r': 14911820Sjulian Remote = TRUE; 15011820Sjulian break; 15111820Sjulian 15211820Sjulian case 't': 15311820Sjulian if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen)) 15411820Sjulian errx(1, "-t Argument too long."); 15511820Sjulian break; 15611820Sjulian 15711820Sjulian case 'S': 15811820Sjulian AddMode = SLAVE; 15911820Sjulian break; 16011820Sjulian 16111820Sjulian case 'M': 16211820Sjulian AddMode = MASTER; 16311820Sjulian break; 16411820Sjulian 16511820Sjulian case 'C': 16611820Sjulian Chroot = optarg; 16711820Sjulian break; 16811820Sjulian 16911820Sjulian case 'h': 17011820Sjulian case '?': 17111820Sjulian default: 17227244Sjhay usage(); 17327244Sjhay break; 17427244Sjhay } 17527244Sjhay } 17611820Sjulian argc -= optind; 17711820Sjulian argv += optind; 17811820Sjulian 17911820Sjulian if (argc > MAX_PKGS) { 18011820Sjulian errx(1, "too many packages (max %d)", MAX_PKGS); 18111820Sjulian } 18211820Sjulian 18311820Sjulian if (AddMode != SLAVE) { 18411820Sjulian for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ; 18527244Sjhay 18627244Sjhay /* Get all the remaining package names, if any */ 18727244Sjhay for (ch = 0; *argv; ch++, argv++) { 18827244Sjhay if (Remote) { 18927244Sjhay if ((packagesite = getpackagesite()) == NULL) 19027244Sjhay errx(1, "package name too long"); 19127244Sjhay if (strlcpy(temppackageroot, packagesite, 19227244Sjhay sizeof(temppackageroot)) >= sizeof(temppackageroot)) 19327244Sjhay errx(1, "package name too long"); 19427244Sjhay if (strlcat(temppackageroot, *argv, sizeof(temppackageroot)) 19527244Sjhay >= sizeof(temppackageroot)) 19627244Sjhay errx(1, "package name too long"); 19727244Sjhay remotepkg = temppackageroot; 19827244Sjhay if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' && 19927244Sjhay (ptr[2] == 'b' || ptr[2] == 'g') && ptr[3] == 'z' && 20011820Sjulian !ptr[4])) 20111820Sjulian if (strlcat(remotepkg, 20211820Sjulian#if defined(__FreeBSD_version) && __FreeBSD_version >= 500039 20327244Sjhay ".tbz", 20411820Sjulian#else 20511820Sjulian ".tgz", 20611820Sjulian#endif 20711820Sjulian sizeof(temppackageroot)) >= sizeof(temppackageroot)) 20811820Sjulian errx(1, "package name too long"); 20911820Sjulian } 21011820Sjulian if (!strcmp(*argv, "-")) /* stdin? */ 21111820Sjulian pkgs[ch] = (char *)"-"; 21211820Sjulian else if (isURL(*argv)) { /* preserve URLs */ 21311820Sjulian if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 21411820Sjulian >= sizeof(pkgnames[ch])) 21511820Sjulian errx(1, "package name too long"); 21611820Sjulian pkgs[ch] = pkgnames[ch]; 21711820Sjulian } 21811820Sjulian else if ((Remote) && isURL(remotepkg)) { 21911820Sjulian if (strlcpy(pkgnames[ch], remotepkg, sizeof(pkgnames[ch])) 22027244Sjhay >= sizeof(pkgnames[ch])) 22111820Sjulian errx(1, "package name too long"); 22211820Sjulian pkgs[ch] = pkgnames[ch]; 22311820Sjulian } else { /* expand all pathnames to fullnames */ 22411820Sjulian if (fexists(*argv)) /* refers to a file directly */ 22527244Sjhay pkgs[ch] = realpath(*argv, pkgnames[ch]); 22611820Sjulian else { /* look for the file in the expected places */ 22711820Sjulian if (!(cp = fileFindByPath(NULL, *argv))) { 22811820Sjulian /* let pkg_do() fail later, so that error is reported */ 22911820Sjulian if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch])) 23011820Sjulian >= sizeof(pkgnames[ch])) 23111820Sjulian errx(1, "package name too long"); 23211820Sjulian pkgs[ch] = pkgnames[ch]; 23311820Sjulian } else { 23411820Sjulian if (strlcpy(pkgnames[ch], cp, sizeof(pkgnames[ch])) 23511820Sjulian >= sizeof(pkgnames[ch])) 23627244Sjhay errx(1, "package name too long"); 23711820Sjulian pkgs[ch] = pkgnames[ch]; 23811820Sjulian } 23911820Sjulian } 240 } 241 if (packagesite != NULL) 242 packagesite[0] = '\0'; 243 } 244 } 245 /* If no packages, yelp */ 246 else if (!ch) { 247 warnx("missing package name(s)"); 248 usage(); 249 } 250 else if (ch > 1 && AddMode == MASTER) { 251 warnx("only one package name may be specified with master mode"); 252 usage(); 253 } 254 /* Perform chroot if requested */ 255 if (Chroot != NULL) { 256 if (chroot(Chroot)) 257 errx(1, "chroot to %s failed", Chroot); 258 } 259 /* Make sure the sub-execs we invoke get found */ 260 setenv("PATH", 261 "/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin", 262 1); 263 264 /* Set a reasonable umask */ 265 umask(022); 266 267 if ((error = pkg_perform(pkgs)) != 0) { 268 if (Verbose) 269 warnx("%d package addition(s) failed", error); 270 return error; 271 } 272 else 273 return 0; 274} 275 276static char * 277getpackagesite(void) 278{ 279 int reldate, i; 280 static char sitepath[MAXPATHLEN]; 281 struct utsname u; 282 283 if (getenv("PACKAGESITE")) { 284 if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath)) 285 >= sizeof(sitepath)) 286 return NULL; 287 return sitepath; 288 } 289 290 if (getenv("PACKAGEROOT")) { 291 if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath)) 292 >= sizeof(sitepath)) 293 return NULL; 294 } else { 295 if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath)) 296 >= sizeof(sitepath)) 297 return NULL; 298 } 299 300 if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath)) 301 >= sizeof(sitepath)) 302 return NULL; 303 304 uname(&u); 305 if (strlcat(sitepath, u.machine, sizeof(sitepath)) >= sizeof(sitepath)) 306 return NULL; 307 308 reldate = getosreldate(); 309 for(i = 0; releases[i].directory != NULL; i++) { 310 if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) { 311 if (strlcat(sitepath, releases[i].directory, sizeof(sitepath)) 312 >= sizeof(sitepath)) 313 return NULL; 314 break; 315 } 316 } 317 318 if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath)) 319 return NULL; 320 321 return sitepath; 322 323} 324 325static void 326usage() 327{ 328 fprintf(stderr, "%s\n%s\n", 329 "usage: pkg_add [-vInrfRMSK] [-t template] [-p prefix] [-P prefix] [-C chrootdir]", 330 " pkg-name [pkg-name ...]"); 331 exit(1); 332} 333