xref: /titanic_52/usr/src/cmd/svr4pkg/pkgremove/main.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland #include <stdio.h>
32*5c51f124SMoriah Waterland #include <limits.h>
33*5c51f124SMoriah Waterland #include <stdlib.h>
34*5c51f124SMoriah Waterland #include <unistd.h>
35*5c51f124SMoriah Waterland #include <string.h>
36*5c51f124SMoriah Waterland #include <signal.h>
37*5c51f124SMoriah Waterland #include <errno.h>
38*5c51f124SMoriah Waterland #include <fcntl.h>
39*5c51f124SMoriah Waterland #include <sys/stat.h>
40*5c51f124SMoriah Waterland #include <sys/types.h>
41*5c51f124SMoriah Waterland #include <pkgstrct.h>
42*5c51f124SMoriah Waterland #include <pkginfo.h>
43*5c51f124SMoriah Waterland #include <pkglocs.h>
44*5c51f124SMoriah Waterland #include <locale.h>
45*5c51f124SMoriah Waterland #include <libintl.h>
46*5c51f124SMoriah Waterland #include <assert.h>
47*5c51f124SMoriah Waterland #include <cfext.h>
48*5c51f124SMoriah Waterland #include <instzones_api.h>
49*5c51f124SMoriah Waterland #include <pkglib.h>
50*5c51f124SMoriah Waterland #include <install.h>
51*5c51f124SMoriah Waterland #include <libinst.h>
52*5c51f124SMoriah Waterland #include <libadm.h>
53*5c51f124SMoriah Waterland #include <messages.h>
54*5c51f124SMoriah Waterland 
55*5c51f124SMoriah Waterland struct cfent **eptlist;
56*5c51f124SMoriah Waterland extern int	eptnum;
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland extern char	*pkgdir;
59*5c51f124SMoriah Waterland extern char	**environ;
60*5c51f124SMoriah Waterland 
61*5c51f124SMoriah Waterland /* quit.c */
62*5c51f124SMoriah Waterland extern sighdlrFunc_t	*quitGetTrapHandler(void);
63*5c51f124SMoriah Waterland extern void		quitSetSilentExit(boolean_t a_silentExit);
64*5c51f124SMoriah Waterland extern void		quitSetZoneName(char *a_zoneName);
65*5c51f124SMoriah Waterland 
66*5c51f124SMoriah Waterland 
67*5c51f124SMoriah Waterland 
68*5c51f124SMoriah Waterland /* check.c */
69*5c51f124SMoriah Waterland extern void	rcksetPreremoveCheck(boolean_t);
70*5c51f124SMoriah Waterland extern void	rcksetZoneName(char *);
71*5c51f124SMoriah Waterland extern int	rckpriv(void);
72*5c51f124SMoriah Waterland extern int	rckdepend(void);
73*5c51f124SMoriah Waterland extern int	rckrunlevel(void);
74*5c51f124SMoriah Waterland 
75*5c51f124SMoriah Waterland /* predepend.c */
76*5c51f124SMoriah Waterland extern void	predepend(char *oldpkg);
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland /* delmap.c */
79*5c51f124SMoriah Waterland extern int delmap(int flag, char *pkginst);
80*5c51f124SMoriah Waterland 
81*5c51f124SMoriah Waterland #define	DEFPATH		"/sbin:/usr/sbin:/usr/bin"
82*5c51f124SMoriah Waterland 
83*5c51f124SMoriah Waterland #ifdef	ALLOW_EXCEPTION_PKG_LIST
84*5c51f124SMoriah Waterland #define	SCRIPT	0	/* Tells exception_pkg() which pkg list to use */
85*5c51f124SMoriah Waterland #define	LINK	1
86*5c51f124SMoriah Waterland #endif
87*5c51f124SMoriah Waterland 
88*5c51f124SMoriah Waterland #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
89*5c51f124SMoriah Waterland #define	TEXT_DOMAIN "SYS_TEST"
90*5c51f124SMoriah Waterland #endif
91*5c51f124SMoriah Waterland 
92*5c51f124SMoriah Waterland /* This is the text for the "-O inherited-filesystem=" option */
93*5c51f124SMoriah Waterland 
94*5c51f124SMoriah Waterland #define	INHERITFS	"inherited-filesystem="
95*5c51f124SMoriah Waterland #define	INHERITFS_LEN	((sizeof (INHERITFS))-1)
96*5c51f124SMoriah Waterland 
97*5c51f124SMoriah Waterland /* This is the text for the "-O parent-zone-name=" option */
98*5c51f124SMoriah Waterland 
99*5c51f124SMoriah Waterland #define	PARENTZONENAME	"parent-zone-name="
100*5c51f124SMoriah Waterland #define	PARENTZONENAME_LEN	((sizeof (PARENTZONENAME))-1)
101*5c51f124SMoriah Waterland 
102*5c51f124SMoriah Waterland /* This is the text for the "-O parent-zone-type=" option */
103*5c51f124SMoriah Waterland 
104*5c51f124SMoriah Waterland #define	PARENTZONETYPE	"parent-zone-type="
105*5c51f124SMoriah Waterland #define	PARENTZONETYPE_LEN	((sizeof (PARENTZONETYPE))-1)
106*5c51f124SMoriah Waterland 
107*5c51f124SMoriah Waterland struct	admin adm; 	/* holds info about installation admin */
108*5c51f124SMoriah Waterland int	dreboot; 	/* non-zero if reboot required after installation */
109*5c51f124SMoriah Waterland int	ireboot;	/* non-zero if immediate reboot required */
110*5c51f124SMoriah Waterland int	failflag;	/* non-zero if fatal error has occurred */
111*5c51f124SMoriah Waterland int	warnflag;	/* non-zero if non-fatal error has occurred */
112*5c51f124SMoriah Waterland int	pkgverbose;	/* non-zero if verbose mode is selected */
113*5c51f124SMoriah Waterland int	started;
114*5c51f124SMoriah Waterland int	nocnflct = 0; 	/* pkgdbmerg needs this defined */
115*5c51f124SMoriah Waterland int	nosetuid = 0; 	/* pkgdbmerg needs this defined */
116*5c51f124SMoriah Waterland 
117*5c51f124SMoriah Waterland char	*pkginst; 	/* current package (source) instance to process */
118*5c51f124SMoriah Waterland 
119*5c51f124SMoriah Waterland int	dbchg;
120*5c51f124SMoriah Waterland char	*msgtext;
121*5c51f124SMoriah Waterland char	pkgloc[PATH_MAX];
122*5c51f124SMoriah Waterland 
123*5c51f124SMoriah Waterland /*
124*5c51f124SMoriah Waterland  * The following variable is the name of the device to which stdin
125*5c51f124SMoriah Waterland  * is connected during execution of a procedure script. /dev/null is
126*5c51f124SMoriah Waterland  * correct for all ABI compliant packages. For non-ABI-compliant
127*5c51f124SMoriah Waterland  * packages, the '-o' command line switch changes this to /dev/tty
128*5c51f124SMoriah Waterland  * to allow user interaction during these scripts. -- JST
129*5c51f124SMoriah Waterland  */
130*5c51f124SMoriah Waterland static char 	*script_in = PROC_STDIN;	/* assume ABI compliance */
131*5c51f124SMoriah Waterland 
132*5c51f124SMoriah Waterland static char	*client_mntdir; 	/* mount point for client's basedir */
133*5c51f124SMoriah Waterland static char	pkgbin[PATH_MAX],
134*5c51f124SMoriah Waterland 		rlockfile[PATH_MAX],
135*5c51f124SMoriah Waterland 		*admnfile, 		/* file to use for installation admin */
136*5c51f124SMoriah Waterland 		*tmpdir; 		/* location to place temporary files */
137*5c51f124SMoriah Waterland 
138*5c51f124SMoriah Waterland static boolean_t	path_valid(char *path);
139*5c51f124SMoriah Waterland static void		ckreturn(int retcode, char *msg);
140*5c51f124SMoriah Waterland static void		rmclass(char *aclass, int rm_remote, char *a_zoneName);
141*5c51f124SMoriah Waterland static void		usage(void);
142*5c51f124SMoriah Waterland 
143*5c51f124SMoriah Waterland /*
144*5c51f124SMoriah Waterland  * Set by -O debug: debug output is enabled?
145*5c51f124SMoriah Waterland  */
146*5c51f124SMoriah Waterland static boolean_t	debugFlag = B_FALSE;
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland /*
149*5c51f124SMoriah Waterland  * Set by -O preremovecheck: do remove dependency checking only
150*5c51f124SMoriah Waterland  */
151*5c51f124SMoriah Waterland static boolean_t	preremoveCheck = B_FALSE;
152*5c51f124SMoriah Waterland 
153*5c51f124SMoriah Waterland /* Set by -O parent-zone-name= */
154*5c51f124SMoriah Waterland 
155*5c51f124SMoriah Waterland static char		*parentZoneName = (char *)NULL;
156*5c51f124SMoriah Waterland 
157*5c51f124SMoriah Waterland /* Set by -O parent-zone-type= */
158*5c51f124SMoriah Waterland 
159*5c51f124SMoriah Waterland static char		*parentZoneType = (char *)NULL;
160*5c51f124SMoriah Waterland 
161*5c51f124SMoriah Waterland static int	nointeract;	/* != 0 no interaction with user should occur */
162*5c51f124SMoriah Waterland 
163*5c51f124SMoriah Waterland 
164*5c51f124SMoriah Waterland 
165*5c51f124SMoriah Waterland int
166*5c51f124SMoriah Waterland main(int argc, char *argv[])
167*5c51f124SMoriah Waterland {
168*5c51f124SMoriah Waterland 	FILE		*fp;
169*5c51f124SMoriah Waterland 	char		*abi_comp_ptr;
170*5c51f124SMoriah Waterland 	char		*abi_sym_ptr;
171*5c51f124SMoriah Waterland 	char		*p;
172*5c51f124SMoriah Waterland 	char		*prog_full_name = NULL;
173*5c51f124SMoriah Waterland 	char		*pt;
174*5c51f124SMoriah Waterland 	char		*value;
175*5c51f124SMoriah Waterland 	char		*vfstab_file = NULL;
176*5c51f124SMoriah Waterland 	char		*zoneName = (char *)NULL;
177*5c51f124SMoriah Waterland 	char		cmdbin[PATH_MAX];
178*5c51f124SMoriah Waterland 	char		param[MAX_PKG_PARAM_LENGTH];
179*5c51f124SMoriah Waterland 	char		path[PATH_MAX];
180*5c51f124SMoriah Waterland 	char		script[PATH_MAX];
181*5c51f124SMoriah Waterland 	int		c;
182*5c51f124SMoriah Waterland 	int		err;
183*5c51f124SMoriah Waterland 	int		fd;
184*5c51f124SMoriah Waterland 	int		i;
185*5c51f124SMoriah Waterland 	int		map_client = 1;
186*5c51f124SMoriah Waterland 	int		n;
187*5c51f124SMoriah Waterland 	int		nodelete = 0; 	/* do not delete file or run scripts */
188*5c51f124SMoriah Waterland 	int		pkgrmremote = 0;	/* dont remove remote objects */
189*5c51f124SMoriah Waterland 	struct sigaction	nact;
190*5c51f124SMoriah Waterland 	struct sigaction	oact;
191*5c51f124SMoriah Waterland 
192*5c51f124SMoriah Waterland 	/* reset contents of all default paths */
193*5c51f124SMoriah Waterland 
194*5c51f124SMoriah Waterland 	(void) memset(cmdbin, '\0', sizeof (cmdbin));
195*5c51f124SMoriah Waterland 
196*5c51f124SMoriah Waterland 	/* initialize locale environment */
197*5c51f124SMoriah Waterland 
198*5c51f124SMoriah Waterland 	(void) setlocale(LC_ALL, "");
199*5c51f124SMoriah Waterland 	(void) textdomain(TEXT_DOMAIN);
200*5c51f124SMoriah Waterland 
201*5c51f124SMoriah Waterland 	/* initialize program name */
202*5c51f124SMoriah Waterland 
203*5c51f124SMoriah Waterland 	prog_full_name = argv[0];
204*5c51f124SMoriah Waterland 	(void) set_prog_name(argv[0]);
205*5c51f124SMoriah Waterland 
206*5c51f124SMoriah Waterland 	/* tell spmi zones interface how to access package output functions */
207*5c51f124SMoriah Waterland 
208*5c51f124SMoriah Waterland 	z_set_output_functions(echo, echoDebug, progerr);
209*5c51f124SMoriah Waterland 
210*5c51f124SMoriah Waterland 	/* exit if not root */
211*5c51f124SMoriah Waterland 
212*5c51f124SMoriah Waterland 	if (getuid()) {
213*5c51f124SMoriah Waterland 		progerr(ERR_NOT_ROOT, get_prog_name());
214*5c51f124SMoriah Waterland 		exit(1);
215*5c51f124SMoriah Waterland 		/* NOTREACHED */
216*5c51f124SMoriah Waterland 	}
217*5c51f124SMoriah Waterland 
218*5c51f124SMoriah Waterland 	/* Read PKG_INSTALL_ROOT from the environment, if it's there. */
219*5c51f124SMoriah Waterland 
220*5c51f124SMoriah Waterland 	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
221*5c51f124SMoriah Waterland 		progerr(ERR_ROOT_SET);
222*5c51f124SMoriah Waterland 		exit(1);
223*5c51f124SMoriah Waterland 	}
224*5c51f124SMoriah Waterland 
225*5c51f124SMoriah Waterland 	/* parse command line options */
226*5c51f124SMoriah Waterland 
227*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, "?Aa:b:FMN:nO:oR:V:vy")) != EOF) {
228*5c51f124SMoriah Waterland 		switch (c) {
229*5c51f124SMoriah Waterland 		/*
230*5c51f124SMoriah Waterland 		 * Same as pkgrm: Allow admin to remove package objects from
231*5c51f124SMoriah Waterland 		 * a shared area from a reference client.
232*5c51f124SMoriah Waterland 		 */
233*5c51f124SMoriah Waterland 		case 'A':
234*5c51f124SMoriah Waterland 		    pkgrmremote++;
235*5c51f124SMoriah Waterland 		    break;
236*5c51f124SMoriah Waterland 
237*5c51f124SMoriah Waterland 		/*
238*5c51f124SMoriah Waterland 		 * Same as pkgrm: Use the installation
239*5c51f124SMoriah Waterland 		 * administration file, admin, in place of the
240*5c51f124SMoriah Waterland 		 * default admin file. pkgrm first looks in the
241*5c51f124SMoriah Waterland 		 * current working directory for the administration
242*5c51f124SMoriah Waterland 		 * file.  If the specified administration file is not
243*5c51f124SMoriah Waterland 		 * in the current working directory, pkgrm looks in
244*5c51f124SMoriah Waterland 		 * the /var/sadm/install/admin directory for the
245*5c51f124SMoriah Waterland 		 * administration file.
246*5c51f124SMoriah Waterland 		 */
247*5c51f124SMoriah Waterland 		case 'a':
248*5c51f124SMoriah Waterland 		    admnfile = flex_device(optarg, 0);
249*5c51f124SMoriah Waterland 		    break;
250*5c51f124SMoriah Waterland 
251*5c51f124SMoriah Waterland 		/*
252*5c51f124SMoriah Waterland 		 * Same as pkgrm: location where package executables
253*5c51f124SMoriah Waterland 		 * can be found - default is /usr/sadm/install/bin.
254*5c51f124SMoriah Waterland 		 */
255*5c51f124SMoriah Waterland 		case 'b':
256*5c51f124SMoriah Waterland 			if (!path_valid(optarg)) {
257*5c51f124SMoriah Waterland 				progerr(ERR_PATH, optarg);
258*5c51f124SMoriah Waterland 				exit(1);
259*5c51f124SMoriah Waterland 			}
260*5c51f124SMoriah Waterland 			if (isdir(optarg) != 0) {
261*5c51f124SMoriah Waterland 				char *p = strerror(errno);
262*5c51f124SMoriah Waterland 				progerr(ERR_CANNOT_USE_DIR, optarg, p);
263*5c51f124SMoriah Waterland 				exit(1);
264*5c51f124SMoriah Waterland 			}
265*5c51f124SMoriah Waterland 			(void) strlcpy(cmdbin, optarg, sizeof (cmdbin));
266*5c51f124SMoriah Waterland 			break;
267*5c51f124SMoriah Waterland 
268*5c51f124SMoriah Waterland 		/*
269*5c51f124SMoriah Waterland 		 * Same as pkgrm: suppresses the removal of any
270*5c51f124SMoriah Waterland 		 * files and any class action scripts, and suppresses
271*5c51f124SMoriah Waterland 		 * the running of any class action scripts.  The
272*5c51f124SMoriah Waterland 		 * package files remain but the package looks like it
273*5c51f124SMoriah Waterland 		 * is not installed. This is mainly for use by the
274*5c51f124SMoriah Waterland 		 * upgrade process.
275*5c51f124SMoriah Waterland 		 */
276*5c51f124SMoriah Waterland 		case 'F':
277*5c51f124SMoriah Waterland 		    nodelete++;
278*5c51f124SMoriah Waterland 		    break;
279*5c51f124SMoriah Waterland 
280*5c51f124SMoriah Waterland 		/*
281*5c51f124SMoriah Waterland 		 * Same as pkgrm: Instruct pkgrm not to use the
282*5c51f124SMoriah Waterland 		 * $root_path/etc/vfstab file for determining the
283*5c51f124SMoriah Waterland 		 * client's mount points. This option assumes the
284*5c51f124SMoriah Waterland 		 * mount points are correct on the server and it
285*5c51f124SMoriah Waterland 		 * behaves consistently with Solaris 2.5 and earlier
286*5c51f124SMoriah Waterland 		 * releases.
287*5c51f124SMoriah Waterland 		 */
288*5c51f124SMoriah Waterland 		case 'M':
289*5c51f124SMoriah Waterland 		    map_client = 0;
290*5c51f124SMoriah Waterland 		    break;
291*5c51f124SMoriah Waterland 
292*5c51f124SMoriah Waterland 		/*
293*5c51f124SMoriah Waterland 		 * Different from pkgrm: specify program name to use
294*5c51f124SMoriah Waterland 		 * for messages.
295*5c51f124SMoriah Waterland 		 */
296*5c51f124SMoriah Waterland 		case 'N':
297*5c51f124SMoriah Waterland 		    (void) set_prog_name(optarg);
298*5c51f124SMoriah Waterland 		    break;
299*5c51f124SMoriah Waterland 
300*5c51f124SMoriah Waterland 		/*
301*5c51f124SMoriah Waterland 		 * Same as pkgrm: package removal occurs in
302*5c51f124SMoriah Waterland 		 * non-interactive mode.  Suppress output of the list of
303*5c51f124SMoriah Waterland 		 * removed files. The default mode is interactive.
304*5c51f124SMoriah Waterland 		 */
305*5c51f124SMoriah Waterland 		case 'n':
306*5c51f124SMoriah Waterland 		    nointeract++;
307*5c51f124SMoriah Waterland 		    (void) echoSetFlag(B_FALSE);
308*5c51f124SMoriah Waterland 		    break;
309*5c51f124SMoriah Waterland 
310*5c51f124SMoriah Waterland 		/*
311*5c51f124SMoriah Waterland 		 * Almost same as pkgrm: the -O option allows the behavior
312*5c51f124SMoriah Waterland 		 * of the package tools to be modified. Recognized options:
313*5c51f124SMoriah Waterland 		 * -> debug
314*5c51f124SMoriah Waterland 		 * ---> enable debugging output
315*5c51f124SMoriah Waterland 		 * -> preremovecheck
316*5c51f124SMoriah Waterland 		 * ---> perform a "pre removal" check of the specified
317*5c51f124SMoriah Waterland 		 * ---> package - suppress all regular output and cause a
318*5c51f124SMoriah Waterland 		 * ---> series of one or more "name=value" pair format lines
319*5c51f124SMoriah Waterland 		 * ---> to be output that describes the "removability" of
320*5c51f124SMoriah Waterland 		 * ---> the specified package
321*5c51f124SMoriah Waterland 		 * -> enable-hollow-package-support
322*5c51f124SMoriah Waterland 		 * --> Enable hollow package support. When specified, for any
323*5c51f124SMoriah Waterland 		 * --> package that has SUNW_PKG_HOLLOW=true:
324*5c51f124SMoriah Waterland 		 * --> Do not calculate and verify package size against target
325*5c51f124SMoriah Waterland 		 * --> Do not run any package procedure or class action scripts
326*5c51f124SMoriah Waterland 		 * --> Do not create or remove any target directories
327*5c51f124SMoriah Waterland 		 * --> Do not perform any script locking
328*5c51f124SMoriah Waterland 		 * --> Do not install or uninstall any components of any package
329*5c51f124SMoriah Waterland 		 * --> Do not output any status or database update messages
330*5c51f124SMoriah Waterland 		 */
331*5c51f124SMoriah Waterland 		case 'O':
332*5c51f124SMoriah Waterland 			for (p = strtok(optarg, ","); p != (char *)NULL;
333*5c51f124SMoriah Waterland 				p = strtok(NULL, ",")) {
334*5c51f124SMoriah Waterland 
335*5c51f124SMoriah Waterland 				/* process debug option */
336*5c51f124SMoriah Waterland 
337*5c51f124SMoriah Waterland 				if (strcmp(p, "debug") == 0) {
338*5c51f124SMoriah Waterland 					/* set debug flag/enable debug output */
339*5c51f124SMoriah Waterland 					debugFlag = B_TRUE;
340*5c51f124SMoriah Waterland 					(void) echoDebugSetFlag(debugFlag);
341*5c51f124SMoriah Waterland 
342*5c51f124SMoriah Waterland 					/* debug info on arguments to pkgadd */
343*5c51f124SMoriah Waterland 					for (n = 0; n < argc && argv[n]; n++) {
344*5c51f124SMoriah Waterland 						echoDebug(DBG_ARG, n, argv[n]);
345*5c51f124SMoriah Waterland 					}
346*5c51f124SMoriah Waterland 
347*5c51f124SMoriah Waterland 					continue;
348*5c51f124SMoriah Waterland 				}
349*5c51f124SMoriah Waterland 
350*5c51f124SMoriah Waterland 				/* process enable-hollow-package-support opt */
351*5c51f124SMoriah Waterland 
352*5c51f124SMoriah Waterland 				if (strcmp(p,
353*5c51f124SMoriah Waterland 					"enable-hollow-package-support") == 0) {
354*5c51f124SMoriah Waterland 					set_depend_pkginfo_DB(B_TRUE);
355*5c51f124SMoriah Waterland 					continue;
356*5c51f124SMoriah Waterland 				}
357*5c51f124SMoriah Waterland 
358*5c51f124SMoriah Waterland 				/* process inherited-filesystem= option */
359*5c51f124SMoriah Waterland 
360*5c51f124SMoriah Waterland 				if (strncmp(p, INHERITFS, INHERITFS_LEN) == 0) {
361*5c51f124SMoriah Waterland 					if (z_add_inherited_file_system(
362*5c51f124SMoriah Waterland 						p+INHERITFS_LEN) == B_FALSE) {
363*5c51f124SMoriah Waterland 						progerr(ERR_NOSUCH_INHERITED,
364*5c51f124SMoriah Waterland 							p+INHERITFS_LEN);
365*5c51f124SMoriah Waterland 						quit(1);
366*5c51f124SMoriah Waterland 						/* NOTREACHED */
367*5c51f124SMoriah Waterland 					}
368*5c51f124SMoriah Waterland 					continue;
369*5c51f124SMoriah Waterland 				}
370*5c51f124SMoriah Waterland 
371*5c51f124SMoriah Waterland 				/* process preremovecheck option */
372*5c51f124SMoriah Waterland 
373*5c51f124SMoriah Waterland 				if (strcmp(p, "preremovecheck") == 0) {
374*5c51f124SMoriah Waterland 					preremoveCheck = B_TRUE;
375*5c51f124SMoriah Waterland 					nointeract++;	/* -n */
376*5c51f124SMoriah Waterland 					nodelete++;	/* -F */
377*5c51f124SMoriah Waterland 					quitSetSilentExit(B_TRUE);
378*5c51f124SMoriah Waterland 					continue;
379*5c51f124SMoriah Waterland 				}
380*5c51f124SMoriah Waterland 
381*5c51f124SMoriah Waterland 				/* process addzonename option */
382*5c51f124SMoriah Waterland 
383*5c51f124SMoriah Waterland 				if (strcmp(p, "addzonename") == 0) {
384*5c51f124SMoriah Waterland 					zoneName = z_get_zonename();
385*5c51f124SMoriah Waterland 					quitSetZoneName(zoneName);
386*5c51f124SMoriah Waterland 					continue;
387*5c51f124SMoriah Waterland 				}
388*5c51f124SMoriah Waterland 
389*5c51f124SMoriah Waterland 				/* process parent-zone-name option */
390*5c51f124SMoriah Waterland 
391*5c51f124SMoriah Waterland 				if (strncmp(p, PARENTZONENAME,
392*5c51f124SMoriah Waterland 						PARENTZONENAME_LEN) == 0) {
393*5c51f124SMoriah Waterland 					parentZoneName = p+PARENTZONENAME_LEN;
394*5c51f124SMoriah Waterland 					continue;
395*5c51f124SMoriah Waterland 				}
396*5c51f124SMoriah Waterland 
397*5c51f124SMoriah Waterland 				/* process parent-zone-type option */
398*5c51f124SMoriah Waterland 
399*5c51f124SMoriah Waterland 				if (strncmp(p, PARENTZONETYPE,
400*5c51f124SMoriah Waterland 						PARENTZONETYPE_LEN) == 0) {
401*5c51f124SMoriah Waterland 					parentZoneType = p+PARENTZONETYPE_LEN;
402*5c51f124SMoriah Waterland 					continue;
403*5c51f124SMoriah Waterland 				}
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland 				/* option not recognized - issue warning */
406*5c51f124SMoriah Waterland 
407*5c51f124SMoriah Waterland 				progerr(ERR_INVALID_O_OPTION, p);
408*5c51f124SMoriah Waterland 				continue;
409*5c51f124SMoriah Waterland 			}
410*5c51f124SMoriah Waterland 			break;
411*5c51f124SMoriah Waterland 
412*5c51f124SMoriah Waterland 		/*
413*5c51f124SMoriah Waterland 		 * Different from pkgrm: This is an old non-ABI package
414*5c51f124SMoriah Waterland 		 */
415*5c51f124SMoriah Waterland 
416*5c51f124SMoriah Waterland 		case 'o':
417*5c51f124SMoriah Waterland 		    script_in = PROC_XSTDIN;
418*5c51f124SMoriah Waterland 		    break;
419*5c51f124SMoriah Waterland 
420*5c51f124SMoriah Waterland 		/*
421*5c51f124SMoriah Waterland 		 * Same as pkgrm: defines the full path name of a
422*5c51f124SMoriah Waterland 		 * directory to use as the root_path.  All files,
423*5c51f124SMoriah Waterland 		 * including package system information files, are
424*5c51f124SMoriah Waterland 		 * relocated to a directory tree starting in the
425*5c51f124SMoriah Waterland 		 * specified root_path.
426*5c51f124SMoriah Waterland 		 */
427*5c51f124SMoriah Waterland 		case 'R':
428*5c51f124SMoriah Waterland 		    if (!set_inst_root(optarg)) {
429*5c51f124SMoriah Waterland 			    progerr(ERR_ROOT_CMD);
430*5c51f124SMoriah Waterland 			    exit(1);
431*5c51f124SMoriah Waterland 		    }
432*5c51f124SMoriah Waterland 		    break;
433*5c51f124SMoriah Waterland 
434*5c51f124SMoriah Waterland 		/*
435*5c51f124SMoriah Waterland 		 * Same as pkgrm: allow admin to establish the client
436*5c51f124SMoriah Waterland 		 * filesystem using a vfstab-like file of stable format.
437*5c51f124SMoriah Waterland 		 */
438*5c51f124SMoriah Waterland 		case 'V':
439*5c51f124SMoriah Waterland 		    vfstab_file = flex_device(optarg, 2);
440*5c51f124SMoriah Waterland 		    map_client = 1;
441*5c51f124SMoriah Waterland 		    break;
442*5c51f124SMoriah Waterland 
443*5c51f124SMoriah Waterland 		/*
444*5c51f124SMoriah Waterland 		 * Same as pkgrm: trace all of the scripts that
445*5c51f124SMoriah Waterland 		 * get executed by pkgrm, located in the
446*5c51f124SMoriah Waterland 		 * pkginst/install directory. This option is used for
447*5c51f124SMoriah Waterland 		 * debugging the procedural and non-procedural
448*5c51f124SMoriah Waterland 		 * scripts.
449*5c51f124SMoriah Waterland 		 */
450*5c51f124SMoriah Waterland 		case 'v':
451*5c51f124SMoriah Waterland 		    pkgverbose++;
452*5c51f124SMoriah Waterland 		    break;
453*5c51f124SMoriah Waterland 
454*5c51f124SMoriah Waterland 		/*
455*5c51f124SMoriah Waterland 		 * Different from pkgrm: process this package using
456*5c51f124SMoriah Waterland 		 * old non-ABI symlinks
457*5c51f124SMoriah Waterland 		 */
458*5c51f124SMoriah Waterland 		case 'y':
459*5c51f124SMoriah Waterland 		    set_nonABI_symlinks();
460*5c51f124SMoriah Waterland 		    break;
461*5c51f124SMoriah Waterland 
462*5c51f124SMoriah Waterland 		default:
463*5c51f124SMoriah Waterland 		    usage();
464*5c51f124SMoriah Waterland 		    /*NOTREACHED*/
465*5c51f124SMoriah Waterland 		    /*
466*5c51f124SMoriah Waterland 		     * Although usage() calls a noreturn function,
467*5c51f124SMoriah Waterland 		     * needed to add return (1);  so that main() would
468*5c51f124SMoriah Waterland 		     * pass compilation checks. The statement below
469*5c51f124SMoriah Waterland    		     * should never be executed.
470*5c51f124SMoriah Waterland 		     */
471*5c51f124SMoriah Waterland 		    return (1);
472*5c51f124SMoriah Waterland 		}
473*5c51f124SMoriah Waterland 	}
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland 	/*
476*5c51f124SMoriah Waterland 	 * ********************************************************************
477*5c51f124SMoriah Waterland 	 * validate command line options
478*5c51f124SMoriah Waterland 	 * ********************************************************************
479*5c51f124SMoriah Waterland 	 */
480*5c51f124SMoriah Waterland 
481*5c51f124SMoriah Waterland 	(void) echoDebugSetFlag(debugFlag);
482*5c51f124SMoriah Waterland 	(void) log_set_verbose(debugFlag);
483*5c51f124SMoriah Waterland 
484*5c51f124SMoriah Waterland 	if (z_running_in_global_zone()) {
485*5c51f124SMoriah Waterland 		echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
486*5c51f124SMoriah Waterland 	} else {
487*5c51f124SMoriah Waterland 		echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
488*5c51f124SMoriah Waterland 			z_get_zonename());
489*5c51f124SMoriah Waterland 	}
490*5c51f124SMoriah Waterland 
491*5c51f124SMoriah Waterland 	/* establish cmdbin path */
492*5c51f124SMoriah Waterland 
493*5c51f124SMoriah Waterland 	if (cmdbin[0] == '\0') {
494*5c51f124SMoriah Waterland 		(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
495*5c51f124SMoriah Waterland 	}
496*5c51f124SMoriah Waterland 
497*5c51f124SMoriah Waterland 	/* Read the mount table */
498*5c51f124SMoriah Waterland 
499*5c51f124SMoriah Waterland 	if (get_mntinfo(map_client, vfstab_file)) {
500*5c51f124SMoriah Waterland 		quit(99);
501*5c51f124SMoriah Waterland 	}
502*5c51f124SMoriah Waterland 
503*5c51f124SMoriah Waterland 	/*
504*5c51f124SMoriah Waterland 	 * This function defines the standard /var/... directories used later
505*5c51f124SMoriah Waterland 	 * to construct the paths to the various databases.
506*5c51f124SMoriah Waterland 	 */
507*5c51f124SMoriah Waterland 
508*5c51f124SMoriah Waterland 	set_PKGpaths(get_inst_root());
509*5c51f124SMoriah Waterland 
510*5c51f124SMoriah Waterland 	/*
511*5c51f124SMoriah Waterland 	 * If this is being removed from a client whose /var filesystem is
512*5c51f124SMoriah Waterland 	 * mounted in some odd way, remap the administrative paths to the
513*5c51f124SMoriah Waterland 	 * real filesystem. This could be avoided by simply mounting up the
514*5c51f124SMoriah Waterland 	 * client now; but we aren't yet to the point in the process where
515*5c51f124SMoriah Waterland 	 * modification of the filesystem is permitted.
516*5c51f124SMoriah Waterland 	 */
517*5c51f124SMoriah Waterland 	if (is_an_inst_root()) {
518*5c51f124SMoriah Waterland 		int fsys_value;
519*5c51f124SMoriah Waterland 
520*5c51f124SMoriah Waterland 		fsys_value = fsys(get_PKGLOC());
521*5c51f124SMoriah Waterland 		if (use_srvr_map_n(fsys_value))
522*5c51f124SMoriah Waterland 			set_PKGLOC(server_map(get_PKGLOC(), fsys_value));
523*5c51f124SMoriah Waterland 
524*5c51f124SMoriah Waterland 		fsys_value = fsys(get_PKGADM());
525*5c51f124SMoriah Waterland 		if (use_srvr_map_n(fsys_value))
526*5c51f124SMoriah Waterland 			set_PKGADM(server_map(get_PKGADM(), fsys_value));
527*5c51f124SMoriah Waterland 	} else {
528*5c51f124SMoriah Waterland 		pkgrmremote = 0;	/* Makes no sense on local host. */
529*5c51f124SMoriah Waterland 	}
530*5c51f124SMoriah Waterland 
531*5c51f124SMoriah Waterland 	/*
532*5c51f124SMoriah Waterland 	 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
533*5c51f124SMoriah Waterland 	 */
534*5c51f124SMoriah Waterland 
535*5c51f124SMoriah Waterland 	/* hold SIGINT/SIGHUP interrupts */
536*5c51f124SMoriah Waterland 
537*5c51f124SMoriah Waterland 	(void) sighold(SIGHUP);
538*5c51f124SMoriah Waterland 	(void) sighold(SIGINT);
539*5c51f124SMoriah Waterland 
540*5c51f124SMoriah Waterland 	/* connect quit.c:trap() to SIGINT */
541*5c51f124SMoriah Waterland 
542*5c51f124SMoriah Waterland 	nact.sa_handler = quitGetTrapHandler();
543*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
544*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
545*5c51f124SMoriah Waterland 
546*5c51f124SMoriah Waterland 	(void) sigaction(SIGINT, &nact, &oact);
547*5c51f124SMoriah Waterland 
548*5c51f124SMoriah Waterland 	/* connect quit.c:trap() to SIGHUP */
549*5c51f124SMoriah Waterland 
550*5c51f124SMoriah Waterland 	nact.sa_handler = quitGetTrapHandler();
551*5c51f124SMoriah Waterland 	nact.sa_flags = SA_RESTART;
552*5c51f124SMoriah Waterland 	(void) sigemptyset(&nact.sa_mask);
553*5c51f124SMoriah Waterland 
554*5c51f124SMoriah Waterland 	(void) sigaction(SIGHUP, &nact, &oact);
555*5c51f124SMoriah Waterland 
556*5c51f124SMoriah Waterland 	/* release hold on signals */
557*5c51f124SMoriah Waterland 
558*5c51f124SMoriah Waterland 	(void) sigrelse(SIGHUP);
559*5c51f124SMoriah Waterland 	(void) sigrelse(SIGINT);
560*5c51f124SMoriah Waterland 
561*5c51f124SMoriah Waterland 	pkginst = argv[optind++];
562*5c51f124SMoriah Waterland 	if (optind != argc) {
563*5c51f124SMoriah Waterland 		usage();
564*5c51f124SMoriah Waterland 	}
565*5c51f124SMoriah Waterland 
566*5c51f124SMoriah Waterland 	/* validate package software database (contents) file */
567*5c51f124SMoriah Waterland 
568*5c51f124SMoriah Waterland 	if (vcfile() == 0) {
569*5c51f124SMoriah Waterland 		quit(99);
570*5c51f124SMoriah Waterland 	}
571*5c51f124SMoriah Waterland 
572*5c51f124SMoriah Waterland 	/*
573*5c51f124SMoriah Waterland 	 * Acquire the package lock - currently at "remove initialization"
574*5c51f124SMoriah Waterland 	 */
575*5c51f124SMoriah Waterland 
576*5c51f124SMoriah Waterland 	if (!lockinst(get_prog_name(), pkginst, "remove-initial")) {
577*5c51f124SMoriah Waterland 		quit(99);
578*5c51f124SMoriah Waterland 	}
579*5c51f124SMoriah Waterland 
580*5c51f124SMoriah Waterland 	/* establish temporary directory to use */
581*5c51f124SMoriah Waterland 
582*5c51f124SMoriah Waterland 	tmpdir = getenv("TMPDIR");
583*5c51f124SMoriah Waterland 	if (tmpdir == NULL) {
584*5c51f124SMoriah Waterland 		tmpdir = P_tmpdir;
585*5c51f124SMoriah Waterland 	}
586*5c51f124SMoriah Waterland 
587*5c51f124SMoriah Waterland 	echoDebug(DBG_PKGREMOVE_TMPDIR, tmpdir);
588*5c51f124SMoriah Waterland 
589*5c51f124SMoriah Waterland 	/*
590*5c51f124SMoriah Waterland 	 * Initialize installation admin parameters by reading
591*5c51f124SMoriah Waterland 	 * the adminfile.
592*5c51f124SMoriah Waterland 	 */
593*5c51f124SMoriah Waterland 
594*5c51f124SMoriah Waterland 	echoDebug(DBG_PKGREMOVE_ADMINFILE, admnfile ? admnfile : "");
595*5c51f124SMoriah Waterland 	setadminFile(admnfile);
596*5c51f124SMoriah Waterland 
597*5c51f124SMoriah Waterland 	/*
598*5c51f124SMoriah Waterland 	 * about to perform first operation that could be modified by the
599*5c51f124SMoriah Waterland 	 * preremove check option - if preremove check is selected (that is,
600*5c51f124SMoriah Waterland 	 * only gathering dependencies), then output a debug message to
601*5c51f124SMoriah Waterland 	 * indicate that the check is beginning. Also turn echo() output
602*5c51f124SMoriah Waterland 	 * off and set various other flags.
603*5c51f124SMoriah Waterland 	 */
604*5c51f124SMoriah Waterland 
605*5c51f124SMoriah Waterland 	if (preremoveCheck == B_TRUE) {
606*5c51f124SMoriah Waterland 		(void) echoSetFlag(B_FALSE);
607*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PRERMCHK, pkginst ? pkginst : "",
608*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
609*5c51f124SMoriah Waterland 		rcksetPreremoveCheck(B_TRUE);
610*5c51f124SMoriah Waterland 		rcksetZoneName(zoneName);
611*5c51f124SMoriah Waterland 	}
612*5c51f124SMoriah Waterland 
613*5c51f124SMoriah Waterland 	(void) snprintf(pkgloc, sizeof (pkgloc), "%s/%s", get_PKGLOC(),
614*5c51f124SMoriah Waterland 			pkginst);
615*5c51f124SMoriah Waterland 	(void) snprintf(pkgbin, sizeof (pkgbin), "%s/install", pkgloc);
616*5c51f124SMoriah Waterland 	(void) snprintf(rlockfile, sizeof (rlockfile), "%s/!R-Lock!", pkgloc);
617*5c51f124SMoriah Waterland 
618*5c51f124SMoriah Waterland 	if (chdir(pkgbin)) {
619*5c51f124SMoriah Waterland 		progerr(ERR_CHDIR, pkgbin);
620*5c51f124SMoriah Waterland 		quit(99);
621*5c51f124SMoriah Waterland 	}
622*5c51f124SMoriah Waterland 
623*5c51f124SMoriah Waterland 	echo(MSG_PREREMOVE_REMINST, pkginst);
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland 	/*
626*5c51f124SMoriah Waterland 	 * if a lock file is present, then a previous attempt to remove this
627*5c51f124SMoriah Waterland 	 * package may have been unsuccessful.
628*5c51f124SMoriah Waterland 	 */
629*5c51f124SMoriah Waterland 
630*5c51f124SMoriah Waterland 	if (access(rlockfile, F_OK) == 0) {
631*5c51f124SMoriah Waterland 		echo(ERR_UNSUCC);
632*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGINSTALL_HAS_LOCKFILE, pkginst, rlockfile,
633*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
634*5c51f124SMoriah Waterland 	}
635*5c51f124SMoriah Waterland 
636*5c51f124SMoriah Waterland 	/*
637*5c51f124SMoriah Waterland 	 * Process all parameters from the pkginfo file
638*5c51f124SMoriah Waterland 	 * and place them in the execution environment
639*5c51f124SMoriah Waterland 	 */
640*5c51f124SMoriah Waterland 
641*5c51f124SMoriah Waterland 	/* Add DB retreival of the pkginfo parameters here */
642*5c51f124SMoriah Waterland 	(void) snprintf(path, sizeof (path), "%s/pkginfo", pkgloc);
643*5c51f124SMoriah Waterland 	if ((fp = fopen(path, "r")) == NULL) {
644*5c51f124SMoriah Waterland 		progerr(ERR_PKGINFO, path);
645*5c51f124SMoriah Waterland 		quit(99);
646*5c51f124SMoriah Waterland 	}
647*5c51f124SMoriah Waterland 
648*5c51f124SMoriah Waterland 	/* Mount up the client if necessary. */
649*5c51f124SMoriah Waterland 	if (map_client && !mount_client()) {
650*5c51f124SMoriah Waterland 		logerr(MSG_MANMOUNT);
651*5c51f124SMoriah Waterland 	}
652*5c51f124SMoriah Waterland 
653*5c51f124SMoriah Waterland 	/* Get mount point of client */
654*5c51f124SMoriah Waterland 	client_mntdir = getenv("CLIENT_MNTDIR");
655*5c51f124SMoriah Waterland 
656*5c51f124SMoriah Waterland 	getuserlocale();
657*5c51f124SMoriah Waterland 
658*5c51f124SMoriah Waterland 	/*
659*5c51f124SMoriah Waterland 	 * current environment has been read; clear environment out
660*5c51f124SMoriah Waterland 	 * so putparam() can be used to populate the new environment
661*5c51f124SMoriah Waterland 	 * to be passed to any executables/scripts.
662*5c51f124SMoriah Waterland 	 */
663*5c51f124SMoriah Waterland 
664*5c51f124SMoriah Waterland 	environ = NULL;
665*5c51f124SMoriah Waterland 
666*5c51f124SMoriah Waterland 	if (nonABI_symlinks()) {
667*5c51f124SMoriah Waterland 		putparam("PKG_NONABI_SYMLINKS", "TRUE");
668*5c51f124SMoriah Waterland 	}
669*5c51f124SMoriah Waterland 
670*5c51f124SMoriah Waterland 	/*
671*5c51f124SMoriah Waterland 	 * read the pkginfo file and fix any PKGSAV path - the correct
672*5c51f124SMoriah Waterland 	 * install_root will be prepended to the existing path.
673*5c51f124SMoriah Waterland 	 */
674*5c51f124SMoriah Waterland 
675*5c51f124SMoriah Waterland 	param[0] = '\0';
676*5c51f124SMoriah Waterland 	while (value = fpkgparam(fp, param)) {
677*5c51f124SMoriah Waterland 		int validx = 0;
678*5c51f124SMoriah Waterland 		char *newvalue;
679*5c51f124SMoriah Waterland 
680*5c51f124SMoriah Waterland 		/* strip out any setting of PATH */
681*5c51f124SMoriah Waterland 
682*5c51f124SMoriah Waterland 		if (strcmp(param, "PATH") == 0) {
683*5c51f124SMoriah Waterland 			free(value);
684*5c51f124SMoriah Waterland 			param[0] = '\0';
685*5c51f124SMoriah Waterland 			continue;
686*5c51f124SMoriah Waterland 		}
687*5c51f124SMoriah Waterland 
688*5c51f124SMoriah Waterland 		/* if not PKGSAV then write out unchanged */
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland 		if (strcmp(param, "PKGSAV") != 0) {
691*5c51f124SMoriah Waterland 			putparam(param, value);
692*5c51f124SMoriah Waterland 			free(value);
693*5c51f124SMoriah Waterland 			param[0] = '\0';
694*5c51f124SMoriah Waterland 			continue;
695*5c51f124SMoriah Waterland 		}
696*5c51f124SMoriah Waterland 
697*5c51f124SMoriah Waterland 		/*
698*5c51f124SMoriah Waterland 		 * PKGSAV parameter found - interpret the directory:
699*5c51f124SMoriah Waterland 		 * If in host:path format or marked with the leading "//",
700*5c51f124SMoriah Waterland 		 * then there is no client-relative translation - take it
701*5c51f124SMoriah Waterland 		 * literally later rather than use fixpath().
702*5c51f124SMoriah Waterland 		 */
703*5c51f124SMoriah Waterland 
704*5c51f124SMoriah Waterland 		if (strstr(value, ":/")) {
705*5c51f124SMoriah Waterland 			/* no modification needed */
706*5c51f124SMoriah Waterland 			validx = 0;
707*5c51f124SMoriah Waterland 		} else if (strstr(value, "//") == value) {
708*5c51f124SMoriah Waterland 			validx = 1;
709*5c51f124SMoriah Waterland 		} else if (is_an_inst_root()) {
710*5c51f124SMoriah Waterland 			/* This PKGSAV needs to be made client-relative. */
711*5c51f124SMoriah Waterland 			newvalue = fixpath(value);
712*5c51f124SMoriah Waterland 			free(value);
713*5c51f124SMoriah Waterland 			value = newvalue;
714*5c51f124SMoriah Waterland 		}
715*5c51f124SMoriah Waterland 		putparam(param, value+validx);
716*5c51f124SMoriah Waterland 		free(value);
717*5c51f124SMoriah Waterland 		param[0] = '\0';
718*5c51f124SMoriah Waterland 	}
719*5c51f124SMoriah Waterland 
720*5c51f124SMoriah Waterland 	(void) fclose(fp);
721*5c51f124SMoriah Waterland 
722*5c51f124SMoriah Waterland 	/* write parent condition information to environment */
723*5c51f124SMoriah Waterland 
724*5c51f124SMoriah Waterland 	putConditionInfo(parentZoneName, parentZoneType);
725*5c51f124SMoriah Waterland 
726*5c51f124SMoriah Waterland 	putuserlocale();
727*5c51f124SMoriah Waterland 
728*5c51f124SMoriah Waterland 	/*
729*5c51f124SMoriah Waterland 	 * Now do all the various setups based on ABI compliance
730*5c51f124SMoriah Waterland 	 */
731*5c51f124SMoriah Waterland 
732*5c51f124SMoriah Waterland 	/* Read the environment provided by the pkginfo file */
733*5c51f124SMoriah Waterland 	abi_comp_ptr = getenv("NONABI_SCRIPTS");
734*5c51f124SMoriah Waterland 
735*5c51f124SMoriah Waterland 	/* if not ABI compliant set global flag */
736*5c51f124SMoriah Waterland 	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
737*5c51f124SMoriah Waterland 	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
738*5c51f124SMoriah Waterland 		set_nonABI_symlinks();
739*5c51f124SMoriah Waterland 	}
740*5c51f124SMoriah Waterland 
741*5c51f124SMoriah Waterland 	/*
742*5c51f124SMoriah Waterland 	 * If pkginfo says it's not compliant then set non_abi_scripts.
743*5c51f124SMoriah Waterland 	 * Oh, for two releases, set it from exception package names as
744*5c51f124SMoriah Waterland 	 * well.
745*5c51f124SMoriah Waterland 	 */
746*5c51f124SMoriah Waterland 	/*
747*5c51f124SMoriah Waterland 	 * *********************************************************************
748*5c51f124SMoriah Waterland 	 * this feature is removed starting with Solaris 10 - there is no built
749*5c51f124SMoriah Waterland 	 * in list of packages that should be run "the old way"
750*5c51f124SMoriah Waterland 	 * *********************************************************************
751*5c51f124SMoriah Waterland 	 */
752*5c51f124SMoriah Waterland 
753*5c51f124SMoriah Waterland #ifdef	ALLOW_EXCEPTION_PKG_LIST
754*5c51f124SMoriah Waterland 	if (exception_pkg(pkginst, SCRIPT) ||
755*5c51f124SMoriah Waterland 	    (abi_comp_ptr && strncmp(abi_comp_ptr, "TRUE", 4) == 0))
756*5c51f124SMoriah Waterland 		script_in = PROC_XSTDIN;
757*5c51f124SMoriah Waterland #else
758*5c51f124SMoriah Waterland 	if (abi_comp_ptr && strncmp(abi_comp_ptr, "TRUE", 4) == 0) {
759*5c51f124SMoriah Waterland 		script_in = PROC_XSTDIN;
760*5c51f124SMoriah Waterland 	}
761*5c51f124SMoriah Waterland #endif
762*5c51f124SMoriah Waterland 	/*
763*5c51f124SMoriah Waterland 	 * *********************************************************************
764*5c51f124SMoriah Waterland 	 * this feature is removed starting with Solaris 10 - there is no built
765*5c51f124SMoriah Waterland 	 * in list of packages that should be run "the old way"
766*5c51f124SMoriah Waterland 	 * *********************************************************************
767*5c51f124SMoriah Waterland 	 */
768*5c51f124SMoriah Waterland 
769*5c51f124SMoriah Waterland #ifdef	ALLOW_EXCEPTION_PKG_LIST
770*5c51f124SMoriah Waterland 	/* Until 2.9, set it from the execption list */
771*5c51f124SMoriah Waterland 	if (exception_pkg(pkginst, LINK)) {
772*5c51f124SMoriah Waterland 		set_nonABI_symlinks();
773*5c51f124SMoriah Waterland 	}
774*5c51f124SMoriah Waterland #endif
775*5c51f124SMoriah Waterland 
776*5c51f124SMoriah Waterland 	/*
777*5c51f124SMoriah Waterland 	 * Since this is a removal, we can tell whether it's absolute or
778*5c51f124SMoriah Waterland 	 * not from the resident pkginfo file read above.
779*5c51f124SMoriah Waterland 	 */
780*5c51f124SMoriah Waterland 	if ((err = set_basedirs((getenv("BASEDIR") != NULL), adm.basedir,
781*5c51f124SMoriah Waterland 	    pkginst, nointeract)) != 0) {
782*5c51f124SMoriah Waterland 		quit(err);
783*5c51f124SMoriah Waterland 	}
784*5c51f124SMoriah Waterland 
785*5c51f124SMoriah Waterland 	/*
786*5c51f124SMoriah Waterland 	 * See if were are removing a package that only wants to update
787*5c51f124SMoriah Waterland 	 * the database or only remove files associated with CAS's. We
788*5c51f124SMoriah Waterland 	 * only check the PKG_HOLLOW_VARIABLE variable if told to do so by
789*5c51f124SMoriah Waterland 	 * the caller.
790*5c51f124SMoriah Waterland 	 */
791*5c51f124SMoriah Waterland 
792*5c51f124SMoriah Waterland 	if (is_depend_pkginfo_DB()) {
793*5c51f124SMoriah Waterland 		pt = getenv(PKG_HOLLOW_VARIABLE);
794*5c51f124SMoriah Waterland 
795*5c51f124SMoriah Waterland 		if ((pt != NULL) && (strncasecmp(pt, "true", 4) == 0)) {
796*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED);
797*5c51f124SMoriah Waterland 
798*5c51f124SMoriah Waterland 			/*
799*5c51f124SMoriah Waterland 			 * this is a hollow package and hollow package support
800*5c51f124SMoriah Waterland 			 * is enabled -- override admin settings to suppress
801*5c51f124SMoriah Waterland 			 * checks that do not make sense since no scripts will
802*5c51f124SMoriah Waterland 			 * be executed and no files will be removed.
803*5c51f124SMoriah Waterland 			 */
804*5c51f124SMoriah Waterland 
805*5c51f124SMoriah Waterland 			setadminSetting("conflict", "nocheck");
806*5c51f124SMoriah Waterland 			setadminSetting("setuid", "nocheck");
807*5c51f124SMoriah Waterland 			setadminSetting("action", "nocheck");
808*5c51f124SMoriah Waterland 			setadminSetting("partial", "nocheck");
809*5c51f124SMoriah Waterland 			setadminSetting("space", "nocheck");
810*5c51f124SMoriah Waterland 			setadminSetting("authentication", "nocheck");
811*5c51f124SMoriah Waterland 		} else {
812*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_HOLLOW_DISABLED);
813*5c51f124SMoriah Waterland 			set_depend_pkginfo_DB(B_FALSE);
814*5c51f124SMoriah Waterland 		}
815*5c51f124SMoriah Waterland 	}
816*5c51f124SMoriah Waterland 
817*5c51f124SMoriah Waterland 	put_path_params();
818*5c51f124SMoriah Waterland 
819*5c51f124SMoriah Waterland 	/* If client mount point, add it to pkgremove environment */
820*5c51f124SMoriah Waterland 
821*5c51f124SMoriah Waterland 	if (client_mntdir != NULL) {
822*5c51f124SMoriah Waterland 		putparam("CLIENT_MNTDIR", client_mntdir);
823*5c51f124SMoriah Waterland 	}
824*5c51f124SMoriah Waterland 
825*5c51f124SMoriah Waterland 	/* Establish the class list and the class attributes. */
826*5c51f124SMoriah Waterland 
827*5c51f124SMoriah Waterland 	if ((value = getenv("CLASSES")) != NULL) {
828*5c51f124SMoriah Waterland 		cl_sets(qstrdup(value));
829*5c51f124SMoriah Waterland 	} else {
830*5c51f124SMoriah Waterland 		progerr(ERR_CLASSES, path);
831*5c51f124SMoriah Waterland 		quit(99);
832*5c51f124SMoriah Waterland 	}
833*5c51f124SMoriah Waterland 
834*5c51f124SMoriah Waterland 	/* establish path and tmpdir */
835*5c51f124SMoriah Waterland 
836*5c51f124SMoriah Waterland 	if (cmdbin[0] == '\0') {
837*5c51f124SMoriah Waterland 		(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
838*5c51f124SMoriah Waterland 	}
839*5c51f124SMoriah Waterland 
840*5c51f124SMoriah Waterland 	(void) snprintf(path, sizeof (path), "%s:%s", DEFPATH, cmdbin);
841*5c51f124SMoriah Waterland 	putparam("PATH", path);
842*5c51f124SMoriah Waterland 
843*5c51f124SMoriah Waterland 	putparam("TMPDIR", tmpdir);
844*5c51f124SMoriah Waterland 
845*5c51f124SMoriah Waterland 	/*
846*5c51f124SMoriah Waterland 	 * Check ulimit requirement (provided in pkginfo). The purpose of
847*5c51f124SMoriah Waterland 	 * this limit is to terminate pathological file growth resulting from
848*5c51f124SMoriah Waterland 	 * file edits in scripts. It does not apply to files in the pkgmap
849*5c51f124SMoriah Waterland 	 * and it does not apply to any database files manipulated by the
850*5c51f124SMoriah Waterland 	 * installation service.
851*5c51f124SMoriah Waterland 	 */
852*5c51f124SMoriah Waterland 	if (value = getenv("ULIMIT")) {
853*5c51f124SMoriah Waterland 		if (assign_ulimit(value) == -1) {
854*5c51f124SMoriah Waterland 			progerr(ERR_BADULIMIT, value);
855*5c51f124SMoriah Waterland 			warnflag++;
856*5c51f124SMoriah Waterland 		}
857*5c51f124SMoriah Waterland 		putparam("PKG_ULIMIT", "TRUE");
858*5c51f124SMoriah Waterland 	}
859*5c51f124SMoriah Waterland 
860*5c51f124SMoriah Waterland 	/*
861*5c51f124SMoriah Waterland 	 * If only gathering dependencies, check and output status of all
862*5c51f124SMoriah Waterland 	 * remaining dependencies and exit.
863*5c51f124SMoriah Waterland 	 */
864*5c51f124SMoriah Waterland 
865*5c51f124SMoriah Waterland 	if (preremoveCheck == B_TRUE) {
866*5c51f124SMoriah Waterland 		/*
867*5c51f124SMoriah Waterland 		 * make sure current runlevel is appropriate
868*5c51f124SMoriah Waterland 		 */
869*5c51f124SMoriah Waterland 
870*5c51f124SMoriah Waterland 		(void) fprintf(stdout, "rckrunlevel=%d\n", rckrunlevel());
871*5c51f124SMoriah Waterland 
872*5c51f124SMoriah Waterland 		/*
873*5c51f124SMoriah Waterland 		 * determine if any packaging scripts provided with
874*5c51f124SMoriah Waterland 		 * this package will execute as a priviledged user
875*5c51f124SMoriah Waterland 		 */
876*5c51f124SMoriah Waterland 
877*5c51f124SMoriah Waterland 		(void) fprintf(stdout, "rckpriv=%d\n", rckpriv());
878*5c51f124SMoriah Waterland 
879*5c51f124SMoriah Waterland 		/*
880*5c51f124SMoriah Waterland 		 * verify package dependencies
881*5c51f124SMoriah Waterland 		 */
882*5c51f124SMoriah Waterland 
883*5c51f124SMoriah Waterland 		(void) fprintf(stdout, "rckdepend=%d\n", rckdepend());
884*5c51f124SMoriah Waterland 
885*5c51f124SMoriah Waterland 		/*
886*5c51f124SMoriah Waterland 		 * ****** preremove check done - exit ******
887*5c51f124SMoriah Waterland 		 */
888*5c51f124SMoriah Waterland 
889*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PRERMCHK_OK);
890*5c51f124SMoriah Waterland 		quit(0);
891*5c51f124SMoriah Waterland 		/*NOTREACHED*/
892*5c51f124SMoriah Waterland 	}
893*5c51f124SMoriah Waterland 
894*5c51f124SMoriah Waterland 	/*
895*5c51f124SMoriah Waterland 	 * Not gathering dependencies only, proceed to check dependencies
896*5c51f124SMoriah Waterland 	 * and continue with the package removal operation.
897*5c51f124SMoriah Waterland 	 */
898*5c51f124SMoriah Waterland 
899*5c51f124SMoriah Waterland 	/*
900*5c51f124SMoriah Waterland 	 * make sure current runlevel is appropriate
901*5c51f124SMoriah Waterland 	 */
902*5c51f124SMoriah Waterland 
903*5c51f124SMoriah Waterland 	n = rckrunlevel();
904*5c51f124SMoriah Waterland 
905*5c51f124SMoriah Waterland 	if (n != 0) {
906*5c51f124SMoriah Waterland 		quit(n);
907*5c51f124SMoriah Waterland 		/* NOTREACHED */
908*5c51f124SMoriah Waterland 	}
909*5c51f124SMoriah Waterland 
910*5c51f124SMoriah Waterland 	/*
911*5c51f124SMoriah Waterland 	 * determine if any packaging scripts provided with
912*5c51f124SMoriah Waterland 	 * this package will execute as a priviledged user
913*5c51f124SMoriah Waterland 	 */
914*5c51f124SMoriah Waterland 
915*5c51f124SMoriah Waterland 	n = rckpriv();
916*5c51f124SMoriah Waterland 
917*5c51f124SMoriah Waterland 	if (n != 0) {
918*5c51f124SMoriah Waterland 		quit(n);
919*5c51f124SMoriah Waterland 		/* NOTREACHED */
920*5c51f124SMoriah Waterland 	}
921*5c51f124SMoriah Waterland 
922*5c51f124SMoriah Waterland 	/*
923*5c51f124SMoriah Waterland 	 * verify package dependencies
924*5c51f124SMoriah Waterland 	 */
925*5c51f124SMoriah Waterland 	n = rckdepend();
926*5c51f124SMoriah Waterland 
927*5c51f124SMoriah Waterland 	if (n != 0) {
928*5c51f124SMoriah Waterland 		quit(n);
929*5c51f124SMoriah Waterland 		/* NOTREACHED */
930*5c51f124SMoriah Waterland 	}
931*5c51f124SMoriah Waterland 
932*5c51f124SMoriah Waterland 	/*
933*5c51f124SMoriah Waterland 	 * *********************************************************************
934*5c51f124SMoriah Waterland 	 * the actual removal of the package begins here
935*5c51f124SMoriah Waterland 	 * *********************************************************************
936*5c51f124SMoriah Waterland 	 */
937*5c51f124SMoriah Waterland 
938*5c51f124SMoriah Waterland 	/*
939*5c51f124SMoriah Waterland 	 * create lockfile to indicate start of removal
940*5c51f124SMoriah Waterland 	 */
941*5c51f124SMoriah Waterland 	started++;
942*5c51f124SMoriah Waterland 	if ((fd = open(rlockfile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) {
943*5c51f124SMoriah Waterland 		progerr(ERR_LOCKFILE, rlockfile);
944*5c51f124SMoriah Waterland 		quit(99);
945*5c51f124SMoriah Waterland 	} else {
946*5c51f124SMoriah Waterland 		(void) close(fd);
947*5c51f124SMoriah Waterland 	}
948*5c51f124SMoriah Waterland 
949*5c51f124SMoriah Waterland 	if (zoneName == (char *)NULL) {
950*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_PROCPKG_GZ);
951*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PROCPKG_GZ, pkginst, rlockfile);
952*5c51f124SMoriah Waterland 	} else {
953*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_PROCPKG_LZ, zoneName);
954*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PROCPKG_LZ, pkginst, rlockfile,
955*5c51f124SMoriah Waterland 			zoneName);
956*5c51f124SMoriah Waterland 	}
957*5c51f124SMoriah Waterland 	if (delmap(0, pkginst) != 0) {
958*5c51f124SMoriah Waterland 		progerr(ERR_DB_QUERY, pkginst);
959*5c51f124SMoriah Waterland 		quit(99);
960*5c51f124SMoriah Waterland 	}
961*5c51f124SMoriah Waterland 
962*5c51f124SMoriah Waterland 	/*
963*5c51f124SMoriah Waterland 	 * Run a preremove script if one is provided by the package.
964*5c51f124SMoriah Waterland 	 * Don't execute preremove script if only updating the DB.
965*5c51f124SMoriah Waterland 	 * Don't execute preremove script if files are not being deleted.
966*5c51f124SMoriah Waterland 	 * Don't execute preremove script if one or more files reside in
967*5c51f124SMoriah Waterland 	 * an inherited FS.
968*5c51f124SMoriah Waterland 	 */
969*5c51f124SMoriah Waterland 
970*5c51f124SMoriah Waterland 	/* update the lock - at the preremove script */
971*5c51f124SMoriah Waterland 	lockupd("preremove");
972*5c51f124SMoriah Waterland 
973*5c51f124SMoriah Waterland 	/* execute preremove script if one is provided */
974*5c51f124SMoriah Waterland 	(void) snprintf(script, sizeof (script), "%s/preremove", pkgbin);
975*5c51f124SMoriah Waterland 	if (access(script, F_OK) != 0) {
976*5c51f124SMoriah Waterland 		/* no script present */
977*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_POC_NONE, pkginst,
978*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
979*5c51f124SMoriah Waterland 	} else if (nodelete) {
980*5c51f124SMoriah Waterland 		/* not deleting files: skip preremove script */
981*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_POC_NODEL, pkginst, script,
982*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
983*5c51f124SMoriah Waterland 	} else if (is_depend_pkginfo_DB()) {
984*5c51f124SMoriah Waterland 		/* updating db only: skip preremove script */
985*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_POC_DBUPD, pkginst, script,
986*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
987*5c51f124SMoriah Waterland 	} else {
988*5c51f124SMoriah Waterland 		/* script present and ok to run: run the script */
989*5c51f124SMoriah Waterland 		set_ulimit("preremove", ERR_PREREMOVE);
990*5c51f124SMoriah Waterland 		if (zoneName == (char *)NULL) {
991*5c51f124SMoriah Waterland 			echo(MSG_PKGREMOVE_EXEPOC_GZ);
992*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_EXEPOC_GZ, pkginst, script);
993*5c51f124SMoriah Waterland 		} else {
994*5c51f124SMoriah Waterland 			echo(MSG_PKGREMOVE_EXEPOC_LZ, zoneName);
995*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_EXEPOC_LZ, pkginst, script,
996*5c51f124SMoriah Waterland 				zoneName);
997*5c51f124SMoriah Waterland 		}
998*5c51f124SMoriah Waterland 		putparam("PKG_PROC_SCRIPT", "preremove");
999*5c51f124SMoriah Waterland 		if (pkgverbose) {
1000*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
1001*5c51f124SMoriah Waterland 				PROC_USER, PROC_GRP, SHELL, "-x",
1002*5c51f124SMoriah Waterland 				script, NULL), ERR_PREREMOVE);
1003*5c51f124SMoriah Waterland 		} else {
1004*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
1005*5c51f124SMoriah Waterland 				PROC_USER, PROC_GRP, SHELL, script,
1006*5c51f124SMoriah Waterland 				NULL), ERR_PREREMOVE);
1007*5c51f124SMoriah Waterland 		}
1008*5c51f124SMoriah Waterland 		clr_ulimit();
1009*5c51f124SMoriah Waterland 	}
1010*5c51f124SMoriah Waterland 
1011*5c51f124SMoriah Waterland 	/* update the lock - doing removal */
1012*5c51f124SMoriah Waterland 
1013*5c51f124SMoriah Waterland 	lockupd("remove");
1014*5c51f124SMoriah Waterland 
1015*5c51f124SMoriah Waterland 	/*
1016*5c51f124SMoriah Waterland 	 * Ensure that the contents file is updated even if the db has
1017*5c51f124SMoriah Waterland 	 * been upgraded, in the case that there are relevant entries
1018*5c51f124SMoriah Waterland 	 * in a special_contents file.  The return value is ignored
1019*5c51f124SMoriah Waterland 	 * since we do not want special_contents operation to prevent
1020*5c51f124SMoriah Waterland 	 * pkgremove from succeeding.  We do report errors to stderr.
1021*5c51f124SMoriah Waterland 	 */
1022*5c51f124SMoriah Waterland 
1023*5c51f124SMoriah Waterland 	/*
1024*5c51f124SMoriah Waterland 	 * Remove all components belonging to this package.
1025*5c51f124SMoriah Waterland 	 * Don't remove components if only updating the DB.
1026*5c51f124SMoriah Waterland 	 * Don't remove components if files are not being deleted.
1027*5c51f124SMoriah Waterland 	 */
1028*5c51f124SMoriah Waterland 
1029*5c51f124SMoriah Waterland 	if (nodelete) {
1030*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_REM_NODEL, pkginst,
1031*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1032*5c51f124SMoriah Waterland 	} else if (is_depend_pkginfo_DB()) {
1033*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_REM_DBUPD, pkginst,
1034*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1035*5c51f124SMoriah Waterland 	} else {
1036*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_REM, pkginst,
1037*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1038*5c51f124SMoriah Waterland 		/*
1039*5c51f124SMoriah Waterland 		 * remove package one class at a time
1040*5c51f124SMoriah Waterland 		 */
1041*5c51f124SMoriah Waterland 
1042*5c51f124SMoriah Waterland 		/* reverse order of classes */
1043*5c51f124SMoriah Waterland 		for (i = cl_getn() - 1; i >= 0; i--) {
1044*5c51f124SMoriah Waterland 			rmclass(cl_nam(i), pkgrmremote, zoneName);
1045*5c51f124SMoriah Waterland 		}
1046*5c51f124SMoriah Waterland 
1047*5c51f124SMoriah Waterland 		rmclass(NULL, pkgrmremote, zoneName);
1048*5c51f124SMoriah Waterland 	}
1049*5c51f124SMoriah Waterland 
1050*5c51f124SMoriah Waterland 	z_destroyMountTable();
1051*5c51f124SMoriah Waterland 
1052*5c51f124SMoriah Waterland 	/*
1053*5c51f124SMoriah Waterland 	 * Execute postremove script, if any
1054*5c51f124SMoriah Waterland 	 * Don't execute postremove script if only updating the DB.
1055*5c51f124SMoriah Waterland 	 * Don't execute postremove script if files are not being deleted.
1056*5c51f124SMoriah Waterland 	 */
1057*5c51f124SMoriah Waterland 
1058*5c51f124SMoriah Waterland 	/* update the lock - at the postremove script */
1059*5c51f124SMoriah Waterland 	lockupd("postremove");
1060*5c51f124SMoriah Waterland 
1061*5c51f124SMoriah Waterland 	/* execute postremove script if one is provided */
1062*5c51f124SMoriah Waterland 	(void) snprintf(script, sizeof (script), "%s/postremove", pkgbin);
1063*5c51f124SMoriah Waterland 	if (access(script, F_OK) != 0) {
1064*5c51f124SMoriah Waterland 		/* no script present */
1065*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PIC_NONE, pkginst,
1066*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1067*5c51f124SMoriah Waterland 	} else if (nodelete) {
1068*5c51f124SMoriah Waterland 		/* not deleting files: skip postremove script */
1069*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PIC_NODEL, pkginst, script,
1070*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1071*5c51f124SMoriah Waterland 	} else if (is_depend_pkginfo_DB()) {
1072*5c51f124SMoriah Waterland 		/* updating db only: skip postremove script */
1073*5c51f124SMoriah Waterland 		echoDebug(DBG_PKGREMOVE_PIC_DBUPD, pkginst, script,
1074*5c51f124SMoriah Waterland 			zoneName ? zoneName : "global");
1075*5c51f124SMoriah Waterland 	} else {
1076*5c51f124SMoriah Waterland 		/* script present and ok to run: run the script */
1077*5c51f124SMoriah Waterland 		set_ulimit("postremove", ERR_POSTREMOVE);
1078*5c51f124SMoriah Waterland 		if (zoneName == (char *)NULL) {
1079*5c51f124SMoriah Waterland 			echo(MSG_PKGREMOVE_EXEPIC_GZ);
1080*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_EXEPIC_GZ, pkginst, script);
1081*5c51f124SMoriah Waterland 		} else {
1082*5c51f124SMoriah Waterland 			echo(MSG_PKGREMOVE_EXEPIC_LZ, zoneName);
1083*5c51f124SMoriah Waterland 			echoDebug(DBG_PKGREMOVE_EXEPIC_LZ, pkginst, script,
1084*5c51f124SMoriah Waterland 				zoneName);
1085*5c51f124SMoriah Waterland 		}
1086*5c51f124SMoriah Waterland 		putparam("PKG_PROC_SCRIPT", "postremove");
1087*5c51f124SMoriah Waterland 		putparam("TMPDIR", tmpdir);
1088*5c51f124SMoriah Waterland 		if (pkgverbose) {
1089*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER,
1090*5c51f124SMoriah Waterland 			    PROC_GRP, SHELL, "-x", script, NULL),
1091*5c51f124SMoriah Waterland 			    ERR_POSTREMOVE);
1092*5c51f124SMoriah Waterland 		} else {
1093*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(script_in, PROC_STDOUT, PROC_USER,
1094*5c51f124SMoriah Waterland 			    PROC_GRP, SHELL, script, NULL),
1095*5c51f124SMoriah Waterland 			    ERR_POSTREMOVE);
1096*5c51f124SMoriah Waterland 		}
1097*5c51f124SMoriah Waterland 		clr_ulimit();
1098*5c51f124SMoriah Waterland 	}
1099*5c51f124SMoriah Waterland 
1100*5c51f124SMoriah Waterland 	if (zoneName == (char *)NULL) {
1101*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_UPDINF_GZ);
1102*5c51f124SMoriah Waterland 	} else {
1103*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_UPDINF_LZ, zoneName);
1104*5c51f124SMoriah Waterland 	}
1105*5c51f124SMoriah Waterland 
1106*5c51f124SMoriah Waterland 	if (delmap(1, pkginst) != 0) {
1107*5c51f124SMoriah Waterland 		progerr(ERR_DB_QUERY, pkginst);
1108*5c51f124SMoriah Waterland 		quit(99);
1109*5c51f124SMoriah Waterland 	}
1110*5c51f124SMoriah Waterland 
1111*5c51f124SMoriah Waterland 	if (!warnflag && !failflag) {
1112*5c51f124SMoriah Waterland 		if (pt = getenv("PREDEPEND"))
1113*5c51f124SMoriah Waterland 			predepend(pt);
1114*5c51f124SMoriah Waterland 		(void) chdir("/");
1115*5c51f124SMoriah Waterland 		if (rrmdir(pkgloc))
1116*5c51f124SMoriah Waterland 			warnflag++;
1117*5c51f124SMoriah Waterland 	}
1118*5c51f124SMoriah Waterland 
1119*5c51f124SMoriah Waterland 	if ((z_running_in_global_zone() == B_TRUE) &&
1120*5c51f124SMoriah Waterland 		(pkgIsPkgInGzOnly(get_inst_root(), pkginst) == B_TRUE)) {
1121*5c51f124SMoriah Waterland 		boolean_t	b;
1122*5c51f124SMoriah Waterland 
1123*5c51f124SMoriah Waterland 		b = pkgRemovePackageFromGzonlyList(get_inst_root(), pkginst);
1124*5c51f124SMoriah Waterland 		if (b == B_FALSE) {
1125*5c51f124SMoriah Waterland 			progerr(ERR_PKGREMOVE_GZONLY_REMOVE, pkginst);
1126*5c51f124SMoriah Waterland 			ckreturn(1, NULL);
1127*5c51f124SMoriah Waterland 		}
1128*5c51f124SMoriah Waterland 	}
1129*5c51f124SMoriah Waterland 
1130*5c51f124SMoriah Waterland 	/* release the generic package lock */
1131*5c51f124SMoriah Waterland 
1132*5c51f124SMoriah Waterland 	(void) unlockinst();
1133*5c51f124SMoriah Waterland 
1134*5c51f124SMoriah Waterland 	quit(0);
1135*5c51f124SMoriah Waterland 	/* LINTED: no return */
1136*5c51f124SMoriah Waterland }
1137*5c51f124SMoriah Waterland 
1138*5c51f124SMoriah Waterland int
1139*5c51f124SMoriah Waterland issymlink(char *path)
1140*5c51f124SMoriah Waterland {
1141*5c51f124SMoriah Waterland 	struct stat statbuf;
1142*5c51f124SMoriah Waterland 
1143*5c51f124SMoriah Waterland 	/*
1144*5c51f124SMoriah Waterland 	 * Obtain status of path; if symbolic link get link's status
1145*5c51f124SMoriah Waterland 	 */
1146*5c51f124SMoriah Waterland 
1147*5c51f124SMoriah Waterland 	if (lstat(path, &statbuf) != 0) {
1148*5c51f124SMoriah Waterland 		return (1);	/* not symlink */
1149*5c51f124SMoriah Waterland 	}
1150*5c51f124SMoriah Waterland 
1151*5c51f124SMoriah Waterland 	/*
1152*5c51f124SMoriah Waterland 	 * Status obtained - if symbolic link, return 0
1153*5c51f124SMoriah Waterland 	 */
1154*5c51f124SMoriah Waterland 
1155*5c51f124SMoriah Waterland 	if ((statbuf.st_mode & S_IFMT) == S_IFLNK) {
1156*5c51f124SMoriah Waterland 		return (0);	/* is a symlink */
1157*5c51f124SMoriah Waterland 	}
1158*5c51f124SMoriah Waterland 
1159*5c51f124SMoriah Waterland 	/*
1160*5c51f124SMoriah Waterland 	 * Not a symbolic link - return 1
1161*5c51f124SMoriah Waterland 	 */
1162*5c51f124SMoriah Waterland 
1163*5c51f124SMoriah Waterland 	return (1);		/* not symlink */
1164*5c51f124SMoriah Waterland }
1165*5c51f124SMoriah Waterland 
1166*5c51f124SMoriah Waterland static void
1167*5c51f124SMoriah Waterland rmclass(char *aclass, int rm_remote, char *a_zoneName)
1168*5c51f124SMoriah Waterland {
1169*5c51f124SMoriah Waterland 	struct cfent	*ept;
1170*5c51f124SMoriah Waterland 	FILE	*fp;
1171*5c51f124SMoriah Waterland 	char	tmpfile[PATH_MAX];
1172*5c51f124SMoriah Waterland 	char	script[PATH_MAX];
1173*5c51f124SMoriah Waterland 	int	i;
1174*5c51f124SMoriah Waterland 	char	*tmp_path;
1175*5c51f124SMoriah Waterland 	char	*save_path = NULL;
1176*5c51f124SMoriah Waterland 	struct stat st;
1177*5c51f124SMoriah Waterland 
1178*5c51f124SMoriah Waterland 	if (aclass == NULL) {
1179*5c51f124SMoriah Waterland 		for (i = 0; i < eptnum; i++) {
1180*5c51f124SMoriah Waterland 			if (eptlist[i] != NULL) {
1181*5c51f124SMoriah Waterland 				rmclass(eptlist[i]->pkg_class,
1182*5c51f124SMoriah Waterland 					rm_remote, a_zoneName);
1183*5c51f124SMoriah Waterland 			}
1184*5c51f124SMoriah Waterland 		}
1185*5c51f124SMoriah Waterland 		return;
1186*5c51f124SMoriah Waterland 	}
1187*5c51f124SMoriah Waterland 
1188*5c51f124SMoriah Waterland 	/* locate class action script to execute */
1189*5c51f124SMoriah Waterland 	(void) snprintf(script, sizeof (script), "%s/r.%s", pkgbin, aclass);
1190*5c51f124SMoriah Waterland 	if (access(script, F_OK) != 0) {
1191*5c51f124SMoriah Waterland 		(void) snprintf(script, sizeof (script), "%s/r.%s",
1192*5c51f124SMoriah Waterland 		    PKGSCR, aclass);
1193*5c51f124SMoriah Waterland 		if (access(script, F_OK) != 0)
1194*5c51f124SMoriah Waterland 			script[0] = '\0';
1195*5c51f124SMoriah Waterland 	}
1196*5c51f124SMoriah Waterland 	if (script[0] != '\0') {
1197*5c51f124SMoriah Waterland 		int td;
1198*5c51f124SMoriah Waterland 
1199*5c51f124SMoriah Waterland 		(void) snprintf(tmpfile, sizeof (tmpfile), "%s/RMLISTXXXXXX",
1200*5c51f124SMoriah Waterland 		    tmpdir);
1201*5c51f124SMoriah Waterland 		td = mkstemp(tmpfile);
1202*5c51f124SMoriah Waterland 		if (td == -1) {
1203*5c51f124SMoriah Waterland 			progerr(ERR_TMPFILE);
1204*5c51f124SMoriah Waterland 			quit(99);
1205*5c51f124SMoriah Waterland 		}
1206*5c51f124SMoriah Waterland 		if ((fp = fdopen(td, "w")) == NULL) {
1207*5c51f124SMoriah Waterland 			progerr(ERR_WTMPFILE, tmpfile);
1208*5c51f124SMoriah Waterland 			quit(99);
1209*5c51f124SMoriah Waterland 		}
1210*5c51f124SMoriah Waterland 	}
1211*5c51f124SMoriah Waterland 
1212*5c51f124SMoriah Waterland 	if (a_zoneName == (char *)NULL) {
1213*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_REMPATHCLASS_GZ, aclass);
1214*5c51f124SMoriah Waterland 	} else {
1215*5c51f124SMoriah Waterland 		echo(MSG_PKGREMOVE_REMPATHCLASS_LZ, aclass, a_zoneName);
1216*5c51f124SMoriah Waterland 	}
1217*5c51f124SMoriah Waterland 
1218*5c51f124SMoriah Waterland 	/* process paths in reverse order */
1219*5c51f124SMoriah Waterland 	i = eptnum;
1220*5c51f124SMoriah Waterland 	while (--i >= 0) {
1221*5c51f124SMoriah Waterland 		ept = eptlist[i];
1222*5c51f124SMoriah Waterland 
1223*5c51f124SMoriah Waterland 		if ((ept == NULL) || strcmp(aclass, ept->pkg_class)) {
1224*5c51f124SMoriah Waterland 			continue;
1225*5c51f124SMoriah Waterland 		}
1226*5c51f124SMoriah Waterland 
1227*5c51f124SMoriah Waterland 		/* save the path, and prepend the ir */
1228*5c51f124SMoriah Waterland 		if (is_an_inst_root()) {
1229*5c51f124SMoriah Waterland 			save_path = ept->path;
1230*5c51f124SMoriah Waterland 			tmp_path = fixpath(ept->path);
1231*5c51f124SMoriah Waterland 			ept->path = tmp_path;
1232*5c51f124SMoriah Waterland 		}
1233*5c51f124SMoriah Waterland 
1234*5c51f124SMoriah Waterland 		if (!ept->ftype || (ept->ftype == '^' && !script[0])) {
1235*5c51f124SMoriah Waterland 			/*
1236*5c51f124SMoriah Waterland 			 * A path owned by more than one package is marked with
1237*5c51f124SMoriah Waterland 			 * a NULL ftype (seems odd, but that's how it's
1238*5c51f124SMoriah Waterland 			 * done). Such files are sacro sanct. Shared editable
1239*5c51f124SMoriah Waterland 			 * files are a special case, and are marked with an
1240*5c51f124SMoriah Waterland 			 * ftype of '^'. These files should only be ignored if
1241*5c51f124SMoriah Waterland 			 * no class action script is present. It is the CAS's
1242*5c51f124SMoriah Waterland 			 * responsibility to not remove the editable object.
1243*5c51f124SMoriah Waterland 			 */
1244*5c51f124SMoriah Waterland 			echo(MSG_SHARED, ept->path);
1245*5c51f124SMoriah Waterland 		} else if (ept->pinfo->status == SERVED_FILE && !rm_remote) {
1246*5c51f124SMoriah Waterland 			/*
1247*5c51f124SMoriah Waterland 			 * If the path is provided to the client from a
1248*5c51f124SMoriah Waterland 			 * server, don't remove anything unless explicitly
1249*5c51f124SMoriah Waterland 			 * requested through the "-f" option.
1250*5c51f124SMoriah Waterland 			 */
1251*5c51f124SMoriah Waterland 			echo(MSG_SERVER, ept->path);
1252*5c51f124SMoriah Waterland 		} else if (z_path_is_inherited(ept->path, ept->ftype,
1253*5c51f124SMoriah Waterland 		    get_inst_root())) {
1254*5c51f124SMoriah Waterland 			/*
1255*5c51f124SMoriah Waterland 			 * object is in an area inherited from the global zone,
1256*5c51f124SMoriah Waterland 			 * and the object cannot be removed - output a message
1257*5c51f124SMoriah Waterland 			 * indicating the object cannot be removed and continue.
1258*5c51f124SMoriah Waterland 			 */
1259*5c51f124SMoriah Waterland 			echo(MSG_NOTREMOVED_INHERITED, ept->path);
1260*5c51f124SMoriah Waterland 		} else if (script[0]) {
1261*5c51f124SMoriah Waterland 			/*
1262*5c51f124SMoriah Waterland 			 * If there's a class action script, just put the
1263*5c51f124SMoriah Waterland 			 * path name into the list.
1264*5c51f124SMoriah Waterland 			 */
1265*5c51f124SMoriah Waterland 			(void) fprintf(fp, "%s\n", ept->path);
1266*5c51f124SMoriah Waterland 		} else if (strchr("dx", ept->ftype) != NULL ||
1267*5c51f124SMoriah Waterland 		    (lstat(ept->path, &st) == 0 && S_ISDIR(st.st_mode))) {
1268*5c51f124SMoriah Waterland 			/* Directories are rmdir()'d. */
1269*5c51f124SMoriah Waterland 
1270*5c51f124SMoriah Waterland 			if (rmdir(ept->path)) {
1271*5c51f124SMoriah Waterland 				if (errno == EBUSY) {
1272*5c51f124SMoriah Waterland 					echo(MSG_DIRBUSY, ept->path);
1273*5c51f124SMoriah Waterland 				} else if (errno == EEXIST) {
1274*5c51f124SMoriah Waterland 					echo(MSG_NOTEMPTY, ept->path);
1275*5c51f124SMoriah Waterland 				} else if (errno != ENOENT) {
1276*5c51f124SMoriah Waterland 					progerr(ERR_RMDIR, ept->path);
1277*5c51f124SMoriah Waterland 					warnflag++;
1278*5c51f124SMoriah Waterland 				}
1279*5c51f124SMoriah Waterland 			} else {
1280*5c51f124SMoriah Waterland 				if (ept->pinfo->status == SERVED_FILE) {
1281*5c51f124SMoriah Waterland 					echo(MSG_RMSRVR, ept->path);
1282*5c51f124SMoriah Waterland 				} else {
1283*5c51f124SMoriah Waterland 					echo("%s", ept->path);
1284*5c51f124SMoriah Waterland 				}
1285*5c51f124SMoriah Waterland 			}
1286*5c51f124SMoriah Waterland 
1287*5c51f124SMoriah Waterland 		} else {
1288*5c51f124SMoriah Waterland 			/*
1289*5c51f124SMoriah Waterland 			 * Before removing this object one more
1290*5c51f124SMoriah Waterland 			 * check should be done to assure that a
1291*5c51f124SMoriah Waterland 			 * shared object is not removed.
1292*5c51f124SMoriah Waterland 			 * This can happen if the original object
1293*5c51f124SMoriah Waterland 			 * was incorrectly updated with the
1294*5c51f124SMoriah Waterland 			 * incorrect class identifier.
1295*5c51f124SMoriah Waterland 			 * This handles pathologcal cases that
1296*5c51f124SMoriah Waterland 			 * weren't handled above.
1297*5c51f124SMoriah Waterland 			 */
1298*5c51f124SMoriah Waterland 			if (ept->npkgs > 1) {
1299*5c51f124SMoriah Waterland 				echo(MSG_SHARED, ept->path);
1300*5c51f124SMoriah Waterland 				continue;
1301*5c51f124SMoriah Waterland 			}
1302*5c51f124SMoriah Waterland 
1303*5c51f124SMoriah Waterland 			/* Regular files are unlink()'d. */
1304*5c51f124SMoriah Waterland 
1305*5c51f124SMoriah Waterland 			if (unlink(ept->path)) {
1306*5c51f124SMoriah Waterland 				if (errno != ENOENT) {
1307*5c51f124SMoriah Waterland 					progerr(ERR_RMPATH, ept->path);
1308*5c51f124SMoriah Waterland 					warnflag++;
1309*5c51f124SMoriah Waterland 				}
1310*5c51f124SMoriah Waterland 			} else {
1311*5c51f124SMoriah Waterland 				if (ept->pinfo->status == SERVED_FILE) {
1312*5c51f124SMoriah Waterland 					echo(MSG_RMSRVR, ept->path);
1313*5c51f124SMoriah Waterland 				} else {
1314*5c51f124SMoriah Waterland 					echo("%s", ept->path);
1315*5c51f124SMoriah Waterland 				}
1316*5c51f124SMoriah Waterland 			}
1317*5c51f124SMoriah Waterland 		}
1318*5c51f124SMoriah Waterland 
1319*5c51f124SMoriah Waterland 		/* restore the original path */
1320*5c51f124SMoriah Waterland 
1321*5c51f124SMoriah Waterland 		if (is_an_inst_root()) {
1322*5c51f124SMoriah Waterland 			ept->path = save_path;
1323*5c51f124SMoriah Waterland 		}
1324*5c51f124SMoriah Waterland 
1325*5c51f124SMoriah Waterland 		/*
1326*5c51f124SMoriah Waterland 		 * free memory allocated for this entry memory used for
1327*5c51f124SMoriah Waterland 		 * pathnames will be freed later by a call to pathdup()
1328*5c51f124SMoriah Waterland 		 */
1329*5c51f124SMoriah Waterland 
1330*5c51f124SMoriah Waterland 		if (eptlist[i]) {
1331*5c51f124SMoriah Waterland 			free(eptlist[i]);
1332*5c51f124SMoriah Waterland 		}
1333*5c51f124SMoriah Waterland 		eptlist[i] = NULL;
1334*5c51f124SMoriah Waterland 	}
1335*5c51f124SMoriah Waterland 	if (script[0]) {
1336*5c51f124SMoriah Waterland 		(void) fclose(fp);
1337*5c51f124SMoriah Waterland 		set_ulimit(script, ERR_CASFAIL);
1338*5c51f124SMoriah Waterland 		if (pkgverbose)
1339*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(tmpfile, CAS_STDOUT, CAS_USER,
1340*5c51f124SMoriah Waterland 			    CAS_GRP, SHELL, "-x", script, NULL),
1341*5c51f124SMoriah Waterland 			    ERR_CASFAIL);
1342*5c51f124SMoriah Waterland 		else
1343*5c51f124SMoriah Waterland 			ckreturn(pkgexecl(tmpfile, CAS_STDOUT, CAS_USER,
1344*5c51f124SMoriah Waterland 			    CAS_GRP, SHELL, script, NULL),
1345*5c51f124SMoriah Waterland 			    ERR_CASFAIL);
1346*5c51f124SMoriah Waterland 		clr_ulimit();
1347*5c51f124SMoriah Waterland 		if (isfile(NULL, tmpfile) == 0) {
1348*5c51f124SMoriah Waterland 			if (unlink(tmpfile) == -1)
1349*5c51f124SMoriah Waterland 				progerr(ERR_RMPATH, tmpfile);
1350*5c51f124SMoriah Waterland 		}
1351*5c51f124SMoriah Waterland 	}
1352*5c51f124SMoriah Waterland }
1353*5c51f124SMoriah Waterland 
1354*5c51f124SMoriah Waterland static void
1355*5c51f124SMoriah Waterland ckreturn(int retcode, char *msg)
1356*5c51f124SMoriah Waterland {
1357*5c51f124SMoriah Waterland 	switch (retcode) {
1358*5c51f124SMoriah Waterland 	    case 2:
1359*5c51f124SMoriah Waterland 	    case 12:
1360*5c51f124SMoriah Waterland 	    case 22:
1361*5c51f124SMoriah Waterland 		warnflag++;
1362*5c51f124SMoriah Waterland 		/*FALLTHRU*/
1363*5c51f124SMoriah Waterland 		if (msg)
1364*5c51f124SMoriah Waterland 			progerr(msg);
1365*5c51f124SMoriah Waterland 	    case 10:
1366*5c51f124SMoriah Waterland 	    case 20:
1367*5c51f124SMoriah Waterland 		if (retcode >= 10)
1368*5c51f124SMoriah Waterland 			dreboot++;
1369*5c51f124SMoriah Waterland 		if (retcode >= 20)
1370*5c51f124SMoriah Waterland 			ireboot++;
1371*5c51f124SMoriah Waterland 		/*FALLTHRU*/
1372*5c51f124SMoriah Waterland 	    case 0:
1373*5c51f124SMoriah Waterland 		break; /* okay */
1374*5c51f124SMoriah Waterland 
1375*5c51f124SMoriah Waterland 	    case -1:
1376*5c51f124SMoriah Waterland 		retcode = 99;
1377*5c51f124SMoriah Waterland 		/*FALLTHRU*/
1378*5c51f124SMoriah Waterland 	    case 99:
1379*5c51f124SMoriah Waterland 	    case 1:
1380*5c51f124SMoriah Waterland 	    case 11:
1381*5c51f124SMoriah Waterland 	    case 21:
1382*5c51f124SMoriah Waterland 	    case 4:
1383*5c51f124SMoriah Waterland 	    case 14:
1384*5c51f124SMoriah Waterland 	    case 24:
1385*5c51f124SMoriah Waterland 	    case 5:
1386*5c51f124SMoriah Waterland 	    case 15:
1387*5c51f124SMoriah Waterland 	    case 25:
1388*5c51f124SMoriah Waterland 		if (msg)
1389*5c51f124SMoriah Waterland 			progerr(msg);
1390*5c51f124SMoriah Waterland 		/*FALLTHRU*/
1391*5c51f124SMoriah Waterland 	    case 3:
1392*5c51f124SMoriah Waterland 	    case 13:
1393*5c51f124SMoriah Waterland 	    case 23:
1394*5c51f124SMoriah Waterland 		quit(retcode);
1395*5c51f124SMoriah Waterland 		/* NOT REACHED */
1396*5c51f124SMoriah Waterland 	    default:
1397*5c51f124SMoriah Waterland 		if (msg)
1398*5c51f124SMoriah Waterland 			progerr(msg);
1399*5c51f124SMoriah Waterland 		quit(1);
1400*5c51f124SMoriah Waterland 	}
1401*5c51f124SMoriah Waterland }
1402*5c51f124SMoriah Waterland 
1403*5c51f124SMoriah Waterland static void
1404*5c51f124SMoriah Waterland usage(void)
1405*5c51f124SMoriah Waterland {
1406*5c51f124SMoriah Waterland 	(void) fprintf(stderr, ERR_USAGE_PKGREMOVE);
1407*5c51f124SMoriah Waterland 
1408*5c51f124SMoriah Waterland 	exit(1);
1409*5c51f124SMoriah Waterland }
1410*5c51f124SMoriah Waterland 
1411*5c51f124SMoriah Waterland /*
1412*5c51f124SMoriah Waterland  * Name:		path_valid
1413*5c51f124SMoriah Waterland  * Description:	Checks a string for being a valid path
1414*5c51f124SMoriah Waterland  *
1415*5c51f124SMoriah Waterland  * Arguments:	path - path to validate
1416*5c51f124SMoriah Waterland  *
1417*5c51f124SMoriah Waterland  * Returns :	B_TRUE - success, B_FALSE otherwise.
1418*5c51f124SMoriah Waterland  *		B_FALSE means path was null, too long (>PATH_MAX),
1419*5c51f124SMoriah Waterland  *		or too short (<1)
1420*5c51f124SMoriah Waterland  */
1421*5c51f124SMoriah Waterland static boolean_t
1422*5c51f124SMoriah Waterland path_valid(char *path)
1423*5c51f124SMoriah Waterland {
1424*5c51f124SMoriah Waterland 	if (path == NULL) {
1425*5c51f124SMoriah Waterland 		return (B_FALSE);
1426*5c51f124SMoriah Waterland 	} else if (strlen(path) > PATH_MAX) {
1427*5c51f124SMoriah Waterland 		return (B_FALSE);
1428*5c51f124SMoriah Waterland 	} else if (strlen(path) >= 1) {
1429*5c51f124SMoriah Waterland 		return (B_TRUE);
1430*5c51f124SMoriah Waterland 	} else {
1431*5c51f124SMoriah Waterland 		/* path < 1 */
1432*5c51f124SMoriah Waterland 		return (B_FALSE);
1433*5c51f124SMoriah Waterland 	}
1434*5c51f124SMoriah Waterland }
1435