1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
3*9781SMoriah.Waterland@Sun.COM  *
4*9781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
5*9781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
6*9781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
7*9781SMoriah.Waterland@Sun.COM  *
8*9781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
11*9781SMoriah.Waterland@Sun.COM  * and limitations under the License.
12*9781SMoriah.Waterland@Sun.COM  *
13*9781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9781SMoriah.Waterland@Sun.COM  *
19*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
20*9781SMoriah.Waterland@Sun.COM  */
21*9781SMoriah.Waterland@Sun.COM 
22*9781SMoriah.Waterland@Sun.COM /*
23*9781SMoriah.Waterland@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*9781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
25*9781SMoriah.Waterland@Sun.COM  */
26*9781SMoriah.Waterland@Sun.COM 
27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
29*9781SMoriah.Waterland@Sun.COM 
30*9781SMoriah.Waterland@Sun.COM 
31*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
32*9781SMoriah.Waterland@Sun.COM #include <fcntl.h>
33*9781SMoriah.Waterland@Sun.COM #include <ctype.h>
34*9781SMoriah.Waterland@Sun.COM #include <errno.h>
35*9781SMoriah.Waterland@Sun.COM #include <string.h>
36*9781SMoriah.Waterland@Sun.COM #include <signal.h>
37*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
38*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
39*9781SMoriah.Waterland@Sun.COM #include <pkginfo.h>
40*9781SMoriah.Waterland@Sun.COM #include <pkgstrct.h>
41*9781SMoriah.Waterland@Sun.COM #include <pkglocs.h>
42*9781SMoriah.Waterland@Sun.COM #include <locale.h>
43*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
44*9781SMoriah.Waterland@Sun.COM #include <instzones_api.h>
45*9781SMoriah.Waterland@Sun.COM #include <pkglib.h>
46*9781SMoriah.Waterland@Sun.COM #include <install.h>
47*9781SMoriah.Waterland@Sun.COM #include <libadm.h>
48*9781SMoriah.Waterland@Sun.COM #include <libinst.h>
49*9781SMoriah.Waterland@Sun.COM #include "installf.h"
50*9781SMoriah.Waterland@Sun.COM 
51*9781SMoriah.Waterland@Sun.COM #define	BASEDIR	"/BASEDIR/"
52*9781SMoriah.Waterland@Sun.COM 
53*9781SMoriah.Waterland@Sun.COM #define	INSTALF	(*prog == 'i')
54*9781SMoriah.Waterland@Sun.COM #define	REMOVEF	(*prog == 'r')
55*9781SMoriah.Waterland@Sun.COM 
56*9781SMoriah.Waterland@Sun.COM #define	MSG_MANMOUNT	"Assuming mounts were provided."
57*9781SMoriah.Waterland@Sun.COM 
58*9781SMoriah.Waterland@Sun.COM #define	ERR_PKGNAME_TOO_LONG	\
59*9781SMoriah.Waterland@Sun.COM "The package name specified on the command line\n" \
60*9781SMoriah.Waterland@Sun.COM "exceeds the maximum package name length: a package name may contain a\n" \
61*9781SMoriah.Waterland@Sun.COM "maximum of <%d> characters; however, the package name specified on\n" \
62*9781SMoriah.Waterland@Sun.COM "the command line contains <%d> characters, which exceeds the maximum\n" \
63*9781SMoriah.Waterland@Sun.COM "package name length by <%d> characters. Please specify a package name\n" \
64*9781SMoriah.Waterland@Sun.COM "that contains no more than <%d> characters."
65*9781SMoriah.Waterland@Sun.COM 
66*9781SMoriah.Waterland@Sun.COM #define	ERR_DB_GET "unable to retrieve entries from the database."
67*9781SMoriah.Waterland@Sun.COM #define	ERR_DB_PUT "unable to update the package database."
68*9781SMoriah.Waterland@Sun.COM #define	ERR_ROOT_SET	"Could not set install root from the environment."
69*9781SMoriah.Waterland@Sun.COM #define	ERR_ROOT_CMD	"Command line install root contends with environment."
70*9781SMoriah.Waterland@Sun.COM #define	ERR_CLASSLONG	"classname argument too long"
71*9781SMoriah.Waterland@Sun.COM #define	ERR_CLASSCHAR	"bad character in classname"
72*9781SMoriah.Waterland@Sun.COM #define	ERR_INVAL	"package instance <%s> is invalid"
73*9781SMoriah.Waterland@Sun.COM #define	ERR_NOTINST	"package instance <%s> is not installed"
74*9781SMoriah.Waterland@Sun.COM #define	ERR_MERG	"unable to merge contents file"
75*9781SMoriah.Waterland@Sun.COM #define	ERR_SORT	"unable to sort contents file"
76*9781SMoriah.Waterland@Sun.COM #define	ERR_I_FAIL	"installf did not complete successfully"
77*9781SMoriah.Waterland@Sun.COM #define	ERR_R_FAIL	"removef did not complete successfully"
78*9781SMoriah.Waterland@Sun.COM #define	ERR_NOTROOT	"You must be \"root\" for %s to execute properly."
79*9781SMoriah.Waterland@Sun.COM #define	ERR_USAGE0	"usage:\n" \
80*9781SMoriah.Waterland@Sun.COM 	"\t%s [[-M|-A] -R host_path] [-V ...] pkginst path " \
81*9781SMoriah.Waterland@Sun.COM 	"[path ...]\n" \
82*9781SMoriah.Waterland@Sun.COM 	"\t%s [[-M|-A] -R host_path] [-V ...] pkginst path\n"
83*9781SMoriah.Waterland@Sun.COM 
84*9781SMoriah.Waterland@Sun.COM #define	ERR_USAGE1	"usage:\n" \
85*9781SMoriah.Waterland@Sun.COM 	"\t%s [[-M] -R host_path] [-V ...] [-c class] <pkginst> " \
86*9781SMoriah.Waterland@Sun.COM 	"<path>\n" \
87*9781SMoriah.Waterland@Sun.COM 	"\t%s [[-M] -R host_path] [-V ...] [-c class] <pkginst> " \
88*9781SMoriah.Waterland@Sun.COM 	"<path> <specs>\n" \
89*9781SMoriah.Waterland@Sun.COM 	"\t   where <specs> may be defined as:\n" \
90*9781SMoriah.Waterland@Sun.COM 	"\t\tf <mode> <owner> <group>\n" \
91*9781SMoriah.Waterland@Sun.COM 	"\t\tv <mode> <owner> <group>\n" \
92*9781SMoriah.Waterland@Sun.COM 	"\t\te <mode> <owner> <group>\n" \
93*9781SMoriah.Waterland@Sun.COM 	"\t\td <mode> <owner> <group>\n" \
94*9781SMoriah.Waterland@Sun.COM 	"\t\tx <mode> <owner> <group>\n" \
95*9781SMoriah.Waterland@Sun.COM 	"\t\tp <mode> <owner> <group>\n" \
96*9781SMoriah.Waterland@Sun.COM 	"\t\tc <major> <minor> <mode> <owner> <group>\n" \
97*9781SMoriah.Waterland@Sun.COM 	"\t\tb <major> <minor> <mode> <owner> <group>\n" \
98*9781SMoriah.Waterland@Sun.COM 	"\t\ts <path>=<srcpath>\n" \
99*9781SMoriah.Waterland@Sun.COM 	"\t\tl <path>=<srcpath>\n" \
100*9781SMoriah.Waterland@Sun.COM 	"\t%s [[-M] -R host_path] [-V ...] [-c class] -f pkginst\n"
101*9781SMoriah.Waterland@Sun.COM 
102*9781SMoriah.Waterland@Sun.COM #define	CMD_SORT	"sort +0 -1"
103*9781SMoriah.Waterland@Sun.COM 
104*9781SMoriah.Waterland@Sun.COM #define	LINK	1
105*9781SMoriah.Waterland@Sun.COM 
106*9781SMoriah.Waterland@Sun.COM extern char	dbst; 			/* libinst/pkgdbmerg.c */
107*9781SMoriah.Waterland@Sun.COM 
108*9781SMoriah.Waterland@Sun.COM struct cfextra **extlist;
109*9781SMoriah.Waterland@Sun.COM struct pinfo **eptlist;
110*9781SMoriah.Waterland@Sun.COM 
111*9781SMoriah.Waterland@Sun.COM char	*classname = NULL;
112*9781SMoriah.Waterland@Sun.COM char	*pkginst;
113*9781SMoriah.Waterland@Sun.COM char	*uniTmp;
114*9781SMoriah.Waterland@Sun.COM char 	*abi_sym_ptr;
115*9781SMoriah.Waterland@Sun.COM char 	*ulim;
116*9781SMoriah.Waterland@Sun.COM char 	*script;
117*9781SMoriah.Waterland@Sun.COM 
118*9781SMoriah.Waterland@Sun.COM int	eptnum;
119*9781SMoriah.Waterland@Sun.COM int	sortflag;
120*9781SMoriah.Waterland@Sun.COM int	nosetuid;
121*9781SMoriah.Waterland@Sun.COM int	nocnflct;
122*9781SMoriah.Waterland@Sun.COM int	warnflag = 0;
123*9781SMoriah.Waterland@Sun.COM 
124*9781SMoriah.Waterland@Sun.COM /* libadm/pkgparam.c */
125*9781SMoriah.Waterland@Sun.COM extern void	set_PKGADM(char *newpath);
126*9781SMoriah.Waterland@Sun.COM extern void	set_PKGLOC(char *newpath);
127*9781SMoriah.Waterland@Sun.COM 
128*9781SMoriah.Waterland@Sun.COM extern void set_limit(void);
129*9781SMoriah.Waterland@Sun.COM 
130*9781SMoriah.Waterland@Sun.COM int
131*9781SMoriah.Waterland@Sun.COM main(int argc, char **argv)
132*9781SMoriah.Waterland@Sun.COM {
133*9781SMoriah.Waterland@Sun.COM 	FILE		*pp;
134*9781SMoriah.Waterland@Sun.COM 	VFP_T		*cfTmpVfp;
135*9781SMoriah.Waterland@Sun.COM 	VFP_T		*cfVfp;
136*9781SMoriah.Waterland@Sun.COM 	char		*cmd;
137*9781SMoriah.Waterland@Sun.COM 	char		*tp;
138*9781SMoriah.Waterland@Sun.COM 	char		*prog;
139*9781SMoriah.Waterland@Sun.COM 	char		*pt;
140*9781SMoriah.Waterland@Sun.COM 	char		*vfstab_file = NULL;
141*9781SMoriah.Waterland@Sun.COM 	char		line[1024];
142*9781SMoriah.Waterland@Sun.COM 	char		outbuf[PATH_MAX];
143*9781SMoriah.Waterland@Sun.COM 	int		c;
144*9781SMoriah.Waterland@Sun.COM 	int		dbchg;
145*9781SMoriah.Waterland@Sun.COM 	int		err;
146*9781SMoriah.Waterland@Sun.COM 	int		fflag = 0;
147*9781SMoriah.Waterland@Sun.COM 	int		map_client = 1;
148*9781SMoriah.Waterland@Sun.COM 	int		n;
149*9781SMoriah.Waterland@Sun.COM 	int		pkgrmremote = 0;	/* don't remove remote files */
150*9781SMoriah.Waterland@Sun.COM 	struct cfent	*ept;
151*9781SMoriah.Waterland@Sun.COM 
152*9781SMoriah.Waterland@Sun.COM 	/* hookup signals */
153*9781SMoriah.Waterland@Sun.COM 
154*9781SMoriah.Waterland@Sun.COM 	(void) signal(SIGHUP, exit);
155*9781SMoriah.Waterland@Sun.COM 	(void) signal(SIGINT, exit);
156*9781SMoriah.Waterland@Sun.COM 	(void) signal(SIGQUIT, exit);
157*9781SMoriah.Waterland@Sun.COM 
158*9781SMoriah.Waterland@Sun.COM 	/* initialize locale mechanism */
159*9781SMoriah.Waterland@Sun.COM 
160*9781SMoriah.Waterland@Sun.COM 	(void) setlocale(LC_ALL, "");
161*9781SMoriah.Waterland@Sun.COM 
162*9781SMoriah.Waterland@Sun.COM #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
163*9781SMoriah.Waterland@Sun.COM #define	TEXT_DOMAIN "SYS_TEST"
164*9781SMoriah.Waterland@Sun.COM #endif	/* !defined(TEXT_DOMAIN) */
165*9781SMoriah.Waterland@Sun.COM 
166*9781SMoriah.Waterland@Sun.COM 	(void) textdomain(TEXT_DOMAIN);
167*9781SMoriah.Waterland@Sun.COM 
168*9781SMoriah.Waterland@Sun.COM 	/* determine program name */
169*9781SMoriah.Waterland@Sun.COM 
170*9781SMoriah.Waterland@Sun.COM 	prog = set_prog_name(argv[0]);
171*9781SMoriah.Waterland@Sun.COM 
172*9781SMoriah.Waterland@Sun.COM 	/* tell instzones interface how to access package output functions */
173*9781SMoriah.Waterland@Sun.COM 
174*9781SMoriah.Waterland@Sun.COM 	z_set_output_functions(echo, echoDebug, progerr);
175*9781SMoriah.Waterland@Sun.COM 
176*9781SMoriah.Waterland@Sun.COM 	/* only allow root to run this program */
177*9781SMoriah.Waterland@Sun.COM 
178*9781SMoriah.Waterland@Sun.COM 	if (getuid() != 0) {
179*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_NOTROOT), prog);
180*9781SMoriah.Waterland@Sun.COM 		exit(1);
181*9781SMoriah.Waterland@Sun.COM 	}
182*9781SMoriah.Waterland@Sun.COM 
183*9781SMoriah.Waterland@Sun.COM 	ulim = getenv("PKG_ULIMIT");
184*9781SMoriah.Waterland@Sun.COM 	script = getenv("PKG_PROC_SCRIPT");
185*9781SMoriah.Waterland@Sun.COM 
186*9781SMoriah.Waterland@Sun.COM 	if (ulim && script) {
187*9781SMoriah.Waterland@Sun.COM 		set_limit();
188*9781SMoriah.Waterland@Sun.COM 		clr_ulimit();
189*9781SMoriah.Waterland@Sun.COM 	}
190*9781SMoriah.Waterland@Sun.COM 
191*9781SMoriah.Waterland@Sun.COM 	/* bug id 4244631, not ABI compliant */
192*9781SMoriah.Waterland@Sun.COM 	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
193*9781SMoriah.Waterland@Sun.COM 	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0)
194*9781SMoriah.Waterland@Sun.COM 		set_nonABI_symlinks();
195*9781SMoriah.Waterland@Sun.COM 
196*9781SMoriah.Waterland@Sun.COM 	/* bugId 4012147 */
197*9781SMoriah.Waterland@Sun.COM 	if ((uniTmp = getenv("PKG_NO_UNIFIED")) != NULL)
198*9781SMoriah.Waterland@Sun.COM 		map_client = 0;
199*9781SMoriah.Waterland@Sun.COM 	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
200*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_ROOT_SET));
201*9781SMoriah.Waterland@Sun.COM 		exit(1);
202*9781SMoriah.Waterland@Sun.COM 	}
203*9781SMoriah.Waterland@Sun.COM 
204*9781SMoriah.Waterland@Sun.COM 	while ((c = getopt(argc, argv, "c:V:fAMR:?")) != EOF) {
205*9781SMoriah.Waterland@Sun.COM 		switch (c) {
206*9781SMoriah.Waterland@Sun.COM 			case 'f':
207*9781SMoriah.Waterland@Sun.COM 			fflag++;
208*9781SMoriah.Waterland@Sun.COM 			break;
209*9781SMoriah.Waterland@Sun.COM 
210*9781SMoriah.Waterland@Sun.COM 			case 'c':
211*9781SMoriah.Waterland@Sun.COM 			classname = optarg;
212*9781SMoriah.Waterland@Sun.COM 			/* validate that classname is acceptable */
213*9781SMoriah.Waterland@Sun.COM 			if (strlen(classname) > (size_t)CLSSIZ) {
214*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_CLASSLONG));
215*9781SMoriah.Waterland@Sun.COM 				exit(1);
216*9781SMoriah.Waterland@Sun.COM 			}
217*9781SMoriah.Waterland@Sun.COM 			for (pt = classname; *pt; pt++) {
218*9781SMoriah.Waterland@Sun.COM 				if (!isalpha(*pt) && !isdigit(*pt)) {
219*9781SMoriah.Waterland@Sun.COM 					progerr(gettext(ERR_CLASSCHAR));
220*9781SMoriah.Waterland@Sun.COM 					exit(1);
221*9781SMoriah.Waterland@Sun.COM 				}
222*9781SMoriah.Waterland@Sun.COM 			}
223*9781SMoriah.Waterland@Sun.COM 			break;
224*9781SMoriah.Waterland@Sun.COM 
225*9781SMoriah.Waterland@Sun.COM 		/*
226*9781SMoriah.Waterland@Sun.COM 		 * Don't map the client filesystem onto the server's. Assume
227*9781SMoriah.Waterland@Sun.COM 		 * the mounts have been made for us.
228*9781SMoriah.Waterland@Sun.COM 		 */
229*9781SMoriah.Waterland@Sun.COM 			case 'M':
230*9781SMoriah.Waterland@Sun.COM 			map_client = 0;
231*9781SMoriah.Waterland@Sun.COM 			break;
232*9781SMoriah.Waterland@Sun.COM 
233*9781SMoriah.Waterland@Sun.COM 		/*
234*9781SMoriah.Waterland@Sun.COM 		 * Allow admin to establish the client filesystem using a
235*9781SMoriah.Waterland@Sun.COM 		 * vfstab-like file of stable format.
236*9781SMoriah.Waterland@Sun.COM 		 */
237*9781SMoriah.Waterland@Sun.COM 			case 'V':
238*9781SMoriah.Waterland@Sun.COM 			vfstab_file = flex_device(optarg, 2);
239*9781SMoriah.Waterland@Sun.COM 			map_client = 1;
240*9781SMoriah.Waterland@Sun.COM 			break;
241*9781SMoriah.Waterland@Sun.COM 
242*9781SMoriah.Waterland@Sun.COM 			case 'A':
243*9781SMoriah.Waterland@Sun.COM 			pkgrmremote++;
244*9781SMoriah.Waterland@Sun.COM 			break;
245*9781SMoriah.Waterland@Sun.COM 
246*9781SMoriah.Waterland@Sun.COM 			case 'R':	/* added for newroot option */
247*9781SMoriah.Waterland@Sun.COM 			if (!set_inst_root(optarg)) {
248*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_ROOT_CMD));
249*9781SMoriah.Waterland@Sun.COM 				exit(1);
250*9781SMoriah.Waterland@Sun.COM 			}
251*9781SMoriah.Waterland@Sun.COM 			break;
252*9781SMoriah.Waterland@Sun.COM 
253*9781SMoriah.Waterland@Sun.COM 			default:
254*9781SMoriah.Waterland@Sun.COM 			usage();
255*9781SMoriah.Waterland@Sun.COM 			/*NOTREACHED*/
256*9781SMoriah.Waterland@Sun.COM 			/*
257*9781SMoriah.Waterland@Sun.COM 			 * Although usage() calls a noreturn function,
258*9781SMoriah.Waterland@Sun.COM 			 * needed to add return (1);  so that main() would
259*9781SMoriah.Waterland@Sun.COM 			 * pass compilation checks. The statement below
260*9781SMoriah.Waterland@Sun.COM 			 * should never be executed.
261*9781SMoriah.Waterland@Sun.COM 			 */
262*9781SMoriah.Waterland@Sun.COM 			return (1);
263*9781SMoriah.Waterland@Sun.COM 		}
264*9781SMoriah.Waterland@Sun.COM 	}
265*9781SMoriah.Waterland@Sun.COM 
266*9781SMoriah.Waterland@Sun.COM 	if (pkgrmremote && (!is_an_inst_root() || fflag || INSTALF)) {
267*9781SMoriah.Waterland@Sun.COM 		usage();
268*9781SMoriah.Waterland@Sun.COM 		/*NOTREACHED*/
269*9781SMoriah.Waterland@Sun.COM 	}
270*9781SMoriah.Waterland@Sun.COM 
271*9781SMoriah.Waterland@Sun.COM 	/*
272*9781SMoriah.Waterland@Sun.COM 	 * Get the mount table info and store internally.
273*9781SMoriah.Waterland@Sun.COM 	 */
274*9781SMoriah.Waterland@Sun.COM 	if (get_mntinfo(map_client, vfstab_file))
275*9781SMoriah.Waterland@Sun.COM 		exit(1);
276*9781SMoriah.Waterland@Sun.COM 
277*9781SMoriah.Waterland@Sun.COM 	/*
278*9781SMoriah.Waterland@Sun.COM 	 * This function defines the standard /var/... directories used later
279*9781SMoriah.Waterland@Sun.COM 	 * to construct the paths to the various databases.
280*9781SMoriah.Waterland@Sun.COM 	 */
281*9781SMoriah.Waterland@Sun.COM 	(void) set_PKGpaths(get_inst_root());
282*9781SMoriah.Waterland@Sun.COM 
283*9781SMoriah.Waterland@Sun.COM 	/*
284*9781SMoriah.Waterland@Sun.COM 	 * If this is being installed on a client whose /var filesystem is
285*9781SMoriah.Waterland@Sun.COM 	 * mounted in some odd way, remap the administrative paths to the
286*9781SMoriah.Waterland@Sun.COM 	 * real filesystem. This could be avoided by simply mounting up the
287*9781SMoriah.Waterland@Sun.COM 	 * client now; but we aren't yet to the point in the process where
288*9781SMoriah.Waterland@Sun.COM 	 * modification of the filesystem is permitted.
289*9781SMoriah.Waterland@Sun.COM 	 */
290*9781SMoriah.Waterland@Sun.COM 	if (is_an_inst_root()) {
291*9781SMoriah.Waterland@Sun.COM 		int fsys_value;
292*9781SMoriah.Waterland@Sun.COM 
293*9781SMoriah.Waterland@Sun.COM 		fsys_value = fsys(get_PKGLOC());
294*9781SMoriah.Waterland@Sun.COM 		if (use_srvr_map_n(fsys_value))
295*9781SMoriah.Waterland@Sun.COM 			set_PKGLOC(server_map(get_PKGLOC(), fsys_value));
296*9781SMoriah.Waterland@Sun.COM 
297*9781SMoriah.Waterland@Sun.COM 		fsys_value = fsys(get_PKGADM());
298*9781SMoriah.Waterland@Sun.COM 		if (use_srvr_map_n(fsys_value))
299*9781SMoriah.Waterland@Sun.COM 			set_PKGADM(server_map(get_PKGADM(), fsys_value));
300*9781SMoriah.Waterland@Sun.COM 	}
301*9781SMoriah.Waterland@Sun.COM 
302*9781SMoriah.Waterland@Sun.COM 	sortflag = 0;
303*9781SMoriah.Waterland@Sun.COM 
304*9781SMoriah.Waterland@Sun.COM 	/*
305*9781SMoriah.Waterland@Sun.COM 	 * get the package name and verify length is not too long
306*9781SMoriah.Waterland@Sun.COM 	 */
307*9781SMoriah.Waterland@Sun.COM 
308*9781SMoriah.Waterland@Sun.COM 	pkginst = argv[optind++];
309*9781SMoriah.Waterland@Sun.COM 	if (pkginst == NULL) {
310*9781SMoriah.Waterland@Sun.COM 		usage();
311*9781SMoriah.Waterland@Sun.COM 		/*NOTREACHED*/
312*9781SMoriah.Waterland@Sun.COM 
313*9781SMoriah.Waterland@Sun.COM 	}
314*9781SMoriah.Waterland@Sun.COM 
315*9781SMoriah.Waterland@Sun.COM 	n = strlen(pkginst);
316*9781SMoriah.Waterland@Sun.COM 	if (n > PKGSIZ) {
317*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_PKGNAME_TOO_LONG), PKGSIZ, n, n-PKGSIZ,
318*9781SMoriah.Waterland@Sun.COM 		    PKGSIZ);
319*9781SMoriah.Waterland@Sun.COM 		usage();
320*9781SMoriah.Waterland@Sun.COM 		/*NOTREACHED*/
321*9781SMoriah.Waterland@Sun.COM 	}
322*9781SMoriah.Waterland@Sun.COM 
323*9781SMoriah.Waterland@Sun.COM 	/*
324*9781SMoriah.Waterland@Sun.COM 	 * The following is used to setup the environment. Note that the
325*9781SMoriah.Waterland@Sun.COM 	 * variable 'BASEDIR' is only meaningful for this utility if there
326*9781SMoriah.Waterland@Sun.COM 	 * is an install root, recorded in PKG_INSTALL_ROOT. Otherwise, this
327*9781SMoriah.Waterland@Sun.COM 	 * utility can create a file or directory anywhere unfettered by
328*9781SMoriah.Waterland@Sun.COM 	 * the basedir associated with the package instance.
329*9781SMoriah.Waterland@Sun.COM 	 */
330*9781SMoriah.Waterland@Sun.COM 	if ((err = set_basedirs(0, NULL, pkginst, 1)) != 0)
331*9781SMoriah.Waterland@Sun.COM 		exit(err);
332*9781SMoriah.Waterland@Sun.COM 
333*9781SMoriah.Waterland@Sun.COM 	if (INSTALF)
334*9781SMoriah.Waterland@Sun.COM 		mkbasedir(0, get_basedir());
335*9781SMoriah.Waterland@Sun.COM 
336*9781SMoriah.Waterland@Sun.COM 	if (fflag) {
337*9781SMoriah.Waterland@Sun.COM 		/* installf and removef must only have pkginst */
338*9781SMoriah.Waterland@Sun.COM 		if (optind != argc) {
339*9781SMoriah.Waterland@Sun.COM 			usage();
340*9781SMoriah.Waterland@Sun.COM 			/*NOTREACHED*/
341*9781SMoriah.Waterland@Sun.COM 		}
342*9781SMoriah.Waterland@Sun.COM 	} else {
343*9781SMoriah.Waterland@Sun.COM 		/*
344*9781SMoriah.Waterland@Sun.COM 		 * installf and removef must have at minimum
345*9781SMoriah.Waterland@Sun.COM 		 * pkginst & pathname specified on command line
346*9781SMoriah.Waterland@Sun.COM 		 */
347*9781SMoriah.Waterland@Sun.COM 		if (optind >= argc) {
348*9781SMoriah.Waterland@Sun.COM 			usage();
349*9781SMoriah.Waterland@Sun.COM 			/*NOTREACHED*/
350*9781SMoriah.Waterland@Sun.COM 		}
351*9781SMoriah.Waterland@Sun.COM 	}
352*9781SMoriah.Waterland@Sun.COM 	if (REMOVEF) {
353*9781SMoriah.Waterland@Sun.COM 		if (classname) {
354*9781SMoriah.Waterland@Sun.COM 			usage();
355*9781SMoriah.Waterland@Sun.COM 		}
356*9781SMoriah.Waterland@Sun.COM 	}
357*9781SMoriah.Waterland@Sun.COM 	if (pkgnmchk(pkginst, "all", 0)) {
358*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_INVAL), pkginst);
359*9781SMoriah.Waterland@Sun.COM 		exit(1);
360*9781SMoriah.Waterland@Sun.COM 	}
361*9781SMoriah.Waterland@Sun.COM 	if (fpkginst(pkginst, NULL, NULL) == NULL) {
362*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_NOTINST), pkginst);
363*9781SMoriah.Waterland@Sun.COM 		exit(1);
364*9781SMoriah.Waterland@Sun.COM 	}
365*9781SMoriah.Waterland@Sun.COM 
366*9781SMoriah.Waterland@Sun.COM #ifdef	ALLOW_EXCEPTION_PKG_LIST
367*9781SMoriah.Waterland@Sun.COM 	/*
368*9781SMoriah.Waterland@Sun.COM 	 * *********************************************************************
369*9781SMoriah.Waterland@Sun.COM 	 * this feature is removed starting with Solaris 10 - there is no built
370*9781SMoriah.Waterland@Sun.COM 	 * in list of packages that should be run "the old way"
371*9781SMoriah.Waterland@Sun.COM 	 * *********************************************************************
372*9781SMoriah.Waterland@Sun.COM 	 */
373*9781SMoriah.Waterland@Sun.COM 	/* Until 2.9, set it from the execption list */
374*9781SMoriah.Waterland@Sun.COM 	if (pkginst && exception_pkg(pkginst, LINK))
375*9781SMoriah.Waterland@Sun.COM 		set_nonABI_symlinks();
376*9781SMoriah.Waterland@Sun.COM #endif
377*9781SMoriah.Waterland@Sun.COM 	/*
378*9781SMoriah.Waterland@Sun.COM 	 * This maps the client filesystems into the server's space.
379*9781SMoriah.Waterland@Sun.COM 	 */
380*9781SMoriah.Waterland@Sun.COM 	if (map_client && !mount_client())
381*9781SMoriah.Waterland@Sun.COM 		logerr(gettext(MSG_MANMOUNT));
382*9781SMoriah.Waterland@Sun.COM 
383*9781SMoriah.Waterland@Sun.COM 	/* open the package database (contents) file */
384*9781SMoriah.Waterland@Sun.COM 
385*9781SMoriah.Waterland@Sun.COM 	if (!ocfile(&cfVfp, &cfTmpVfp, 0L)) {
386*9781SMoriah.Waterland@Sun.COM 		quit(1);
387*9781SMoriah.Waterland@Sun.COM 	}
388*9781SMoriah.Waterland@Sun.COM 
389*9781SMoriah.Waterland@Sun.COM 	if (fflag) {
390*9781SMoriah.Waterland@Sun.COM 		dbchg = dofinal(cfVfp, cfTmpVfp, REMOVEF, classname, prog);
391*9781SMoriah.Waterland@Sun.COM 	} else {
392*9781SMoriah.Waterland@Sun.COM 		if (INSTALF) {
393*9781SMoriah.Waterland@Sun.COM 			dbst = INST_RDY;
394*9781SMoriah.Waterland@Sun.COM 			if (installf(argc-optind, &argv[optind]))
395*9781SMoriah.Waterland@Sun.COM 				quit(1);
396*9781SMoriah.Waterland@Sun.COM 		} else {
397*9781SMoriah.Waterland@Sun.COM 			dbst = RM_RDY;
398*9781SMoriah.Waterland@Sun.COM 			removef(argc-optind, &argv[optind]);
399*9781SMoriah.Waterland@Sun.COM 		}
400*9781SMoriah.Waterland@Sun.COM 
401*9781SMoriah.Waterland@Sun.COM 		dbchg = pkgdbmerg(cfVfp, cfTmpVfp, extlist, 0);
402*9781SMoriah.Waterland@Sun.COM 		if (dbchg < 0) {
403*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_MERG));
404*9781SMoriah.Waterland@Sun.COM 			quit(99);
405*9781SMoriah.Waterland@Sun.COM 		}
406*9781SMoriah.Waterland@Sun.COM 	}
407*9781SMoriah.Waterland@Sun.COM 
408*9781SMoriah.Waterland@Sun.COM 	if (dbchg) {
409*9781SMoriah.Waterland@Sun.COM 		if ((n = swapcfile(&cfVfp, &cfTmpVfp, pkginst, 1))
410*9781SMoriah.Waterland@Sun.COM 			== RESULT_WRN) {
411*9781SMoriah.Waterland@Sun.COM 		    warnflag++;
412*9781SMoriah.Waterland@Sun.COM 		} else if (n == RESULT_ERR) {
413*9781SMoriah.Waterland@Sun.COM 		    quit(99);
414*9781SMoriah.Waterland@Sun.COM 		}
415*9781SMoriah.Waterland@Sun.COM 	}
416*9781SMoriah.Waterland@Sun.COM 
417*9781SMoriah.Waterland@Sun.COM 	relslock();
418*9781SMoriah.Waterland@Sun.COM 
419*9781SMoriah.Waterland@Sun.COM 	if (REMOVEF && !fflag) {
420*9781SMoriah.Waterland@Sun.COM 		for (n = 0; extlist[n]; n++) {
421*9781SMoriah.Waterland@Sun.COM 			ept = &(extlist[n]->cf_ent);
422*9781SMoriah.Waterland@Sun.COM 
423*9781SMoriah.Waterland@Sun.COM 			/* Skip duplicated paths */
424*9781SMoriah.Waterland@Sun.COM 			if ((n > 0) && (strncmp(ept->path,
425*9781SMoriah.Waterland@Sun.COM 			    extlist[n-1]->cf_ent.path, PATH_MAX) == 0)) {
426*9781SMoriah.Waterland@Sun.COM 				continue;
427*9781SMoriah.Waterland@Sun.COM 			}
428*9781SMoriah.Waterland@Sun.COM 
429*9781SMoriah.Waterland@Sun.COM 			if (!extlist[n]->mstat.shared) {
430*9781SMoriah.Waterland@Sun.COM 				/*
431*9781SMoriah.Waterland@Sun.COM 				 * Only output paths that can be deleted.
432*9781SMoriah.Waterland@Sun.COM 				 * so need to skip if the object is owned
433*9781SMoriah.Waterland@Sun.COM 				 * by a remote server and removal is not
434*9781SMoriah.Waterland@Sun.COM 				 * being forced.
435*9781SMoriah.Waterland@Sun.COM 				 */
436*9781SMoriah.Waterland@Sun.COM 				if (ept->pinfo &&
437*9781SMoriah.Waterland@Sun.COM 				    (ept->pinfo->status == SERVED_FILE) &&
438*9781SMoriah.Waterland@Sun.COM 				    !pkgrmremote)
439*9781SMoriah.Waterland@Sun.COM 					continue;
440*9781SMoriah.Waterland@Sun.COM 
441*9781SMoriah.Waterland@Sun.COM 				c = 0;
442*9781SMoriah.Waterland@Sun.COM 				if (is_a_cl_basedir() && !is_an_inst_root()) {
443*9781SMoriah.Waterland@Sun.COM 					c = strlen(get_client_basedir());
444*9781SMoriah.Waterland@Sun.COM 					(void) snprintf(outbuf, sizeof (outbuf),
445*9781SMoriah.Waterland@Sun.COM 						"%s/%s\n", get_basedir(),
446*9781SMoriah.Waterland@Sun.COM 						&(ept->path[c]));
447*9781SMoriah.Waterland@Sun.COM 				} else if (is_an_inst_root()) {
448*9781SMoriah.Waterland@Sun.COM 					(void) snprintf(outbuf, sizeof (outbuf),
449*9781SMoriah.Waterland@Sun.COM 						"%s/%s\n", get_inst_root(),
450*9781SMoriah.Waterland@Sun.COM 						&(ept->path[c]));
451*9781SMoriah.Waterland@Sun.COM 				} else {
452*9781SMoriah.Waterland@Sun.COM 					(void) snprintf(outbuf, sizeof (outbuf),
453*9781SMoriah.Waterland@Sun.COM 						"%s\n", &(ept->path[c]));
454*9781SMoriah.Waterland@Sun.COM 				}
455*9781SMoriah.Waterland@Sun.COM 				canonize(outbuf);
456*9781SMoriah.Waterland@Sun.COM 				(void) printf("%s", outbuf);
457*9781SMoriah.Waterland@Sun.COM 			}
458*9781SMoriah.Waterland@Sun.COM 		}
459*9781SMoriah.Waterland@Sun.COM 	} else if (INSTALF && !fflag) {
460*9781SMoriah.Waterland@Sun.COM 		for (n = 0; extlist[n]; n++) {
461*9781SMoriah.Waterland@Sun.COM 			ept = &(extlist[n]->cf_ent);
462*9781SMoriah.Waterland@Sun.COM 
463*9781SMoriah.Waterland@Sun.COM 			if (strchr("dxcbp", ept->ftype)) {
464*9781SMoriah.Waterland@Sun.COM 				tp = fixpath(ept->path);
465*9781SMoriah.Waterland@Sun.COM 				(void) averify(1, &ept->ftype,
466*9781SMoriah.Waterland@Sun.COM 					tp, &ept->ainfo);
467*9781SMoriah.Waterland@Sun.COM 			}
468*9781SMoriah.Waterland@Sun.COM 		}
469*9781SMoriah.Waterland@Sun.COM 	}
470*9781SMoriah.Waterland@Sun.COM 
471*9781SMoriah.Waterland@Sun.COM 	/* Sort the contents files if needed */
472*9781SMoriah.Waterland@Sun.COM 	if (sortflag) {
473*9781SMoriah.Waterland@Sun.COM 		int n;
474*9781SMoriah.Waterland@Sun.COM 
475*9781SMoriah.Waterland@Sun.COM 		warnflag += (ocfile(&cfVfp, &cfTmpVfp, 0L)) ? 0 : 1;
476*9781SMoriah.Waterland@Sun.COM 		if (!warnflag) {
477*9781SMoriah.Waterland@Sun.COM 			size_t	len;
478*9781SMoriah.Waterland@Sun.COM 
479*9781SMoriah.Waterland@Sun.COM 			len = strlen(CMD_SORT) + strlen(get_PKGADM()) +
480*9781SMoriah.Waterland@Sun.COM 				strlen("/contents") + 5;
481*9781SMoriah.Waterland@Sun.COM 			cmd = (char *)malloc(len);
482*9781SMoriah.Waterland@Sun.COM 			(void) snprintf(cmd, len, "%s %s/contents",
483*9781SMoriah.Waterland@Sun.COM 				CMD_SORT, get_PKGADM());
484*9781SMoriah.Waterland@Sun.COM 			pp = popen(cmd, "r");
485*9781SMoriah.Waterland@Sun.COM 			if (pp == NULL) {
486*9781SMoriah.Waterland@Sun.COM 				(void) vfpClose(&cfVfp);
487*9781SMoriah.Waterland@Sun.COM 				(void) vfpClose(&cfTmpVfp);
488*9781SMoriah.Waterland@Sun.COM 				free(cmd);
489*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_SORT));
490*9781SMoriah.Waterland@Sun.COM 				quit(1);
491*9781SMoriah.Waterland@Sun.COM 			}
492*9781SMoriah.Waterland@Sun.COM 			while (fgets(line, 1024, pp) != NULL) {
493*9781SMoriah.Waterland@Sun.COM 				if (line[0] != DUP_ENTRY) {
494*9781SMoriah.Waterland@Sun.COM 					vfpPuts(cfTmpVfp, line);
495*9781SMoriah.Waterland@Sun.COM 				}
496*9781SMoriah.Waterland@Sun.COM 			}
497*9781SMoriah.Waterland@Sun.COM 			free(cmd);
498*9781SMoriah.Waterland@Sun.COM 			(void) pclose(pp);
499*9781SMoriah.Waterland@Sun.COM 			n = swapcfile(&cfVfp, &cfTmpVfp, pkginst, 1);
500*9781SMoriah.Waterland@Sun.COM 			if (n == RESULT_WRN) {
501*9781SMoriah.Waterland@Sun.COM 				warnflag++;
502*9781SMoriah.Waterland@Sun.COM 			} else if (n == RESULT_ERR) {
503*9781SMoriah.Waterland@Sun.COM 				quit(99);
504*9781SMoriah.Waterland@Sun.COM 			}
505*9781SMoriah.Waterland@Sun.COM 
506*9781SMoriah.Waterland@Sun.COM 			relslock();	/* Unlock the database. */
507*9781SMoriah.Waterland@Sun.COM 		}
508*9781SMoriah.Waterland@Sun.COM 	}
509*9781SMoriah.Waterland@Sun.COM 
510*9781SMoriah.Waterland@Sun.COM 	z_destroyMountTable();
511*9781SMoriah.Waterland@Sun.COM 
512*9781SMoriah.Waterland@Sun.COM 	quit(warnflag ? 1 : 0);
513*9781SMoriah.Waterland@Sun.COM 	/* LINTED: no return */
514*9781SMoriah.Waterland@Sun.COM }
515*9781SMoriah.Waterland@Sun.COM 
516*9781SMoriah.Waterland@Sun.COM void
517*9781SMoriah.Waterland@Sun.COM quit(int n)
518*9781SMoriah.Waterland@Sun.COM {
519*9781SMoriah.Waterland@Sun.COM 	char *prog = get_prog_name();
520*9781SMoriah.Waterland@Sun.COM 
521*9781SMoriah.Waterland@Sun.COM 	unmount_client();
522*9781SMoriah.Waterland@Sun.COM 
523*9781SMoriah.Waterland@Sun.COM 	if (ulim && script) {
524*9781SMoriah.Waterland@Sun.COM 		if (REMOVEF) {
525*9781SMoriah.Waterland@Sun.COM 			set_ulimit(script, gettext(ERR_R_FAIL));
526*9781SMoriah.Waterland@Sun.COM 		} else {
527*9781SMoriah.Waterland@Sun.COM 			set_ulimit(script, gettext(ERR_I_FAIL));
528*9781SMoriah.Waterland@Sun.COM 		}
529*9781SMoriah.Waterland@Sun.COM 	}
530*9781SMoriah.Waterland@Sun.COM 
531*9781SMoriah.Waterland@Sun.COM 	exit(n);
532*9781SMoriah.Waterland@Sun.COM }
533*9781SMoriah.Waterland@Sun.COM 
534*9781SMoriah.Waterland@Sun.COM void
535*9781SMoriah.Waterland@Sun.COM usage(void)
536*9781SMoriah.Waterland@Sun.COM {
537*9781SMoriah.Waterland@Sun.COM 	char *prog = get_prog_name();
538*9781SMoriah.Waterland@Sun.COM 
539*9781SMoriah.Waterland@Sun.COM 	if (REMOVEF) {
540*9781SMoriah.Waterland@Sun.COM 		(void) fprintf(stderr, gettext(ERR_USAGE0), prog, prog);
541*9781SMoriah.Waterland@Sun.COM 	} else {
542*9781SMoriah.Waterland@Sun.COM 		(void) fprintf(stderr, gettext(ERR_USAGE1), prog, prog, prog);
543*9781SMoriah.Waterland@Sun.COM 	}
544*9781SMoriah.Waterland@Sun.COM 	exit(1);
545*9781SMoriah.Waterland@Sun.COM }
546