main.c revision 102383
11543Srgrimes/*
21543Srgrimes *
31543Srgrimes * FreeBSD install - a package for the installation and maintainance
41543Srgrimes * of non-core utilities.
51543Srgrimes *
61543Srgrimes * Redistribution and use in source and binary forms, with or without
71543Srgrimes * modification, are permitted provided that the following conditions
81543Srgrimes * are met:
91543Srgrimes * 1. Redistributions of source code must retain the above copyright
101543Srgrimes *    notice, this list of conditions and the following disclaimer.
111543Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
121543Srgrimes *    notice, this list of conditions and the following disclaimer in the
131543Srgrimes *    documentation and/or other materials provided with the distribution.
141543Srgrimes *
151543Srgrimes * Jordan K. Hubbard
161543Srgrimes * 18 July 1993
171543Srgrimes *
181543Srgrimes * This is the add module.
191543Srgrimes */
201543Srgrimes
211543Srgrimes#include <sys/cdefs.h>
221543Srgrimes__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/add/main.c 102383 2002-08-25 01:00:16Z obrien $");
231543Srgrimes
241543Srgrimes#include <err.h>
251543Srgrimes#include <sys/param.h>
261543Srgrimes#include <sys/utsname.h>
271543Srgrimes#include "lib.h"
281543Srgrimes#include "add.h"
291543Srgrimes
301543Srgrimesstatic char Options[] = "hvIRfnrp:SMt:";
311543Srgrimes
321543Srgrimeschar	*Prefix		= NULL;
331543SrgrimesBoolean	NoInstall	= FALSE;
341543SrgrimesBoolean	NoRecord	= FALSE;
351543SrgrimesBoolean Remote		= FALSE;
361543Srgrimes
371543Srgrimeschar	*Mode		= NULL;
381543Srgrimeschar	*Owner		= NULL;
3923184Sbdechar	*Group		= NULL;
401543Srgrimeschar	*PkgName	= NULL;
411543Srgrimeschar	*Directory	= NULL;
421543Srgrimeschar	FirstPen[FILENAME_MAX];
431543Srgrimesadd_mode_t AddMode	= NORMAL;
441543Srgrimes
451543Srgrimes#define MAX_PKGS	200
461543Srgrimeschar	pkgnames[MAX_PKGS][MAXPATHLEN];
4722415Sphkchar	*pkgs[MAX_PKGS];
4823184Sbde
4923184Sbdestruct {
5023184Sbde	int lowver;	/* Lowest version number to match */
5122415Sphk	int hiver;	/* Highest version number to match */
5223184Sbde	const char *directory;	/* Directory it lives in */
5322415Sphk} releases[] = {
5422415Sphk	{ 410000, 410000, "/packages-4.1-release" },
551543Srgrimes	{ 420000, 420000, "/packages-4.2-release" },
561543Srgrimes	{ 430000, 430000, "/packages-4.3-release" },
571543Srgrimes	{ 440000, 440000, "/packages-4.4-release" },
581543Srgrimes	{ 450000, 450000, "/packages-4.5-release" },
591543Srgrimes	{ 300000, 399000, "/packages-3-stable" },
601543Srgrimes	{ 400000, 499000, "/packages-4-stable" },
611543Srgrimes	{ 510000, 599000, "/packages-5-stable" },
621543Srgrimes	{ 0, 9999999, "/packages-current" },
631543Srgrimes	{ 0, 0, NULL }
641543Srgrimes};
651543Srgrimes
661543Srgrimesstatic char *getpackagesite(void);
671543Srgrimesint getosreldate(void);
681543Srgrimes
691543Srgrimesstatic void usage __P((void));
701543Srgrimes
71int
72main(int argc, char **argv)
73{
74    int ch, error;
75    char **start;
76    char *cp, *packagesite = NULL, *remotepkg = NULL, *ptr;
77    static char temppackageroot[MAXPATHLEN];
78
79    start = argv;
80    while ((ch = getopt(argc, argv, Options)) != -1) {
81	switch(ch) {
82	case 'v':
83	    Verbose = TRUE;
84	    break;
85
86	case 'p':
87	    Prefix = optarg;
88	    break;
89
90	case 'I':
91	    NoInstall = TRUE;
92	    break;
93
94	case 'R':
95	    NoRecord = TRUE;
96	    break;
97
98	case 'f':
99	    Force = TRUE;
100	    break;
101
102	case 'n':
103	    Fake = TRUE;
104	    Verbose = TRUE;
105	    break;
106
107	case 'r':
108	    Remote = TRUE;
109	    break;
110
111	case 't':
112	    if (strlcpy(FirstPen, optarg, sizeof(FirstPen)) >= sizeof(FirstPen))
113		errx(1, "-t Argument too long.");
114	    break;
115
116	case 'S':
117	    AddMode = SLAVE;
118	    break;
119
120	case 'M':
121	    AddMode = MASTER;
122	    break;
123
124	case 'h':
125	case '?':
126	default:
127	    usage();
128	    break;
129	}
130    }
131    argc -= optind;
132    argv += optind;
133
134    if (argc > MAX_PKGS) {
135	errx(1, "too many packages (max %d)", MAX_PKGS);
136    }
137
138    if (AddMode != SLAVE) {
139	for (ch = 0; ch < MAX_PKGS; pkgs[ch++] = NULL) ;
140
141	/* Get all the remaining package names, if any */
142	for (ch = 0; *argv; ch++, argv++) {
143    	    if (Remote) {
144		if ((packagesite = getpackagesite()) == NULL)
145		    errx(1, "package name too long");
146		if (strlcpy(temppackageroot, packagesite,
147		    sizeof(temppackageroot)) >= sizeof(temppackageroot))
148		    errx(1, "package name too long");
149		if (strlcat(temppackageroot, *argv, sizeof(temppackageroot))
150		    >= sizeof(temppackageroot))
151		    errx(1, "package name too long");
152		remotepkg = temppackageroot;
153		if (!((ptr = strrchr(remotepkg, '.')) && ptr[1] == 't' &&
154			(ptr[2] == 'b' || ptr[2] == 'g') && ptr[3] == 'z' &&
155			!ptr[4]))
156		    /* XXX: need to handle .tgz also */
157		    if (strlcat(remotepkg, ".tbz", sizeof(temppackageroot))
158			>= sizeof(temppackageroot))
159			errx(1, "package name too long");
160    	    }
161	    if (!strcmp(*argv, "-"))	/* stdin? */
162		(const char *)pkgs[ch] = "-";
163	    else if (isURL(*argv)) {  	/* preserve URLs */
164		if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch]))
165		    >= sizeof(pkgnames[ch]))
166		    errx(1, "package name too long");
167		pkgs[ch] = pkgnames[ch];
168	    }
169	    else if ((Remote) && isURL(remotepkg)) {
170	    	if (strlcpy(pkgnames[ch], remotepkg, sizeof(pkgnames[ch]))
171		    >= sizeof(pkgnames[ch]))
172		    errx(1, "package name too long");
173		pkgs[ch] = pkgnames[ch];
174	    } else {			/* expand all pathnames to fullnames */
175		if (fexists(*argv)) /* refers to a file directly */
176		    pkgs[ch] = realpath(*argv, pkgnames[ch]);
177		else {		/* look for the file in the expected places */
178		    if (!(cp = fileFindByPath(NULL, *argv))) {
179			/* let pkg_do() fail later, so that error is reported */
180			if (strlcpy(pkgnames[ch], *argv, sizeof(pkgnames[ch]))
181			    >= sizeof(pkgnames[ch]))
182			    errx(1, "package name too long");
183			pkgs[ch] = pkgnames[ch];
184		    } else {
185			if (strlcpy(pkgnames[ch], cp, sizeof(pkgnames[ch]))
186			    >= sizeof(pkgnames[ch]))
187			    errx(1, "package name too long");
188			pkgs[ch] = pkgnames[ch];
189		    }
190		}
191	    }
192	    if (packagesite != NULL)
193		packagesite[0] = '\0';
194	}
195    }
196    /* If no packages, yelp */
197    else if (!ch) {
198	warnx("missing package name(s)");
199	usage();
200    }
201    else if (ch > 1 && AddMode == MASTER) {
202	warnx("only one package name may be specified with master mode");
203	usage();
204    }
205    /* Make sure the sub-execs we invoke get found */
206    setenv("PATH",
207	   "/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin",
208	   1);
209
210    /* Set a reasonable umask */
211    umask(022);
212
213    if ((error = pkg_perform(pkgs)) != 0) {
214	if (Verbose)
215	    warnx("%d package addition(s) failed", error);
216	return error;
217    }
218    else
219	return 0;
220}
221
222static char *
223getpackagesite(void)
224{
225    int reldate, i;
226    static char sitepath[MAXPATHLEN];
227    struct utsname u;
228
229    if (getenv("PACKAGESITE")) {
230	if (strlcpy(sitepath, getenv("PACKAGESITE"), sizeof(sitepath))
231	    >= sizeof(sitepath))
232	    return NULL;
233	return sitepath;
234    }
235
236    if (getenv("PACKAGEROOT")) {
237	if (strlcpy(sitepath, getenv("PACKAGEROOT"), sizeof(sitepath))
238	    >= sizeof(sitepath))
239	    return NULL;
240    } else {
241	if (strlcat(sitepath, "ftp://ftp.freebsd.org", sizeof(sitepath))
242	    >= sizeof(sitepath))
243	    return NULL;
244    }
245
246    if (strlcat(sitepath, "/pub/FreeBSD/ports/", sizeof(sitepath))
247	>= sizeof(sitepath))
248	return NULL;
249
250    uname(&u);
251    if (strlcat(sitepath, u.machine, sizeof(sitepath)) >= sizeof(sitepath))
252	return NULL;
253
254    reldate = getosreldate();
255    for(i = 0; releases[i].directory != NULL; i++) {
256	if (reldate >= releases[i].lowver && reldate <= releases[i].hiver) {
257	    if (strlcat(sitepath, releases[i].directory, sizeof(sitepath))
258		>= sizeof(sitepath))
259		return NULL;
260	    break;
261	}
262    }
263
264    if (strlcat(sitepath, "/Latest/", sizeof(sitepath)) >= sizeof(sitepath))
265	return NULL;
266
267    return sitepath;
268
269}
270
271static void
272usage()
273{
274    fprintf(stderr, "%s\n%s\n",
275		"usage: pkg_add [-vInrfRMS] [-t template] [-p prefix]",
276		"               pkg-name [pkg-name ...]");
277    exit(1);
278}
279