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