xref: /titanic_44/usr/src/cmd/svr4pkg/pkginstall/quit.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 2005 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 <string.h>
33*5c51f124SMoriah Waterland #include <signal.h>
34*5c51f124SMoriah Waterland #include <sys/utsname.h>
35*5c51f124SMoriah Waterland #include <limits.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <unistd.h>
38*5c51f124SMoriah Waterland #include <pkgdev.h>
39*5c51f124SMoriah Waterland #include <pkglocs.h>
40*5c51f124SMoriah Waterland #include <locale.h>
41*5c51f124SMoriah Waterland #include <libintl.h>
42*5c51f124SMoriah Waterland #include <errno.h>
43*5c51f124SMoriah Waterland #include <pkglib.h>
44*5c51f124SMoriah Waterland #include "install.h"
45*5c51f124SMoriah Waterland #include "dryrun.h"
46*5c51f124SMoriah Waterland #include "libadm.h"
47*5c51f124SMoriah Waterland #include "libinst.h"
48*5c51f124SMoriah Waterland #include "pkginstall.h"
49*5c51f124SMoriah Waterland #include "messages.h"
50*5c51f124SMoriah Waterland 
51*5c51f124SMoriah Waterland /* main.c */
52*5c51f124SMoriah Waterland extern char		*pkgdrtarg;
53*5c51f124SMoriah Waterland extern struct cfextra	**extlist;
54*5c51f124SMoriah Waterland 
55*5c51f124SMoriah Waterland extern struct	admin adm;
56*5c51f124SMoriah Waterland extern struct	pkgdev pkgdev;	/* holds info about the installation device */
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland extern int	dparts;
59*5c51f124SMoriah Waterland extern int	dreboot;	/* != 0 if reboot required after installation */
60*5c51f124SMoriah Waterland extern int	failflag;	/* != 0 if fatal error has occurred (1) */
61*5c51f124SMoriah Waterland extern int	ireboot;	/* != 0 if immediate reboot required */
62*5c51f124SMoriah Waterland extern int	warnflag;	/* != 0 if non-fatal error has occurred (2) */
63*5c51f124SMoriah Waterland 
64*5c51f124SMoriah Waterland extern char	tmpdir[];
65*5c51f124SMoriah Waterland extern char	pkgloc[];
66*5c51f124SMoriah Waterland extern char	pkgloc_sav[];
67*5c51f124SMoriah Waterland extern char	*msgtext;
68*5c51f124SMoriah Waterland extern char	*pkginst;
69*5c51f124SMoriah Waterland extern char	*pkgname;
70*5c51f124SMoriah Waterland extern char	saveSpoolInstallDir[]; /* pkginstall/main.c */
71*5c51f124SMoriah Waterland 
72*5c51f124SMoriah Waterland /*
73*5c51f124SMoriah Waterland  * exported functions
74*5c51f124SMoriah Waterland  */
75*5c51f124SMoriah Waterland 
76*5c51f124SMoriah Waterland void		quit(int retcode);
77*5c51f124SMoriah Waterland void		quitSetZoneName(char *a_zoneName);
78*5c51f124SMoriah Waterland sighdlrFunc_t	*quitGetTrapHandler(void);
79*5c51f124SMoriah Waterland 
80*5c51f124SMoriah Waterland /*
81*5c51f124SMoriah Waterland  * forward declarations
82*5c51f124SMoriah Waterland  */
83*5c51f124SMoriah Waterland 
84*5c51f124SMoriah Waterland static void		trap(int signo);
85*5c51f124SMoriah Waterland static void		mailmsg(int retcode);
86*5c51f124SMoriah Waterland static void		quitmsg(int retcode);
87*5c51f124SMoriah Waterland 
88*5c51f124SMoriah Waterland static boolean_t	silentExit = B_FALSE;
89*5c51f124SMoriah Waterland static boolean_t	pkgaskFlag = B_FALSE;
90*5c51f124SMoriah Waterland static boolean_t	installStarted = B_FALSE;
91*5c51f124SMoriah Waterland static boolean_t	updatingExistingPackage = B_FALSE;
92*5c51f124SMoriah Waterland 
93*5c51f124SMoriah Waterland static char		*dstreamTempDir = (char *)NULL;
94*5c51f124SMoriah Waterland static char		*zoneName = (char *)NULL;
95*5c51f124SMoriah Waterland static int		includeZonename = 0;
96*5c51f124SMoriah Waterland static int		trapEntered = 0;
97*5c51f124SMoriah Waterland 
98*5c51f124SMoriah Waterland /*
99*5c51f124SMoriah Waterland  * *****************************************************************************
100*5c51f124SMoriah Waterland  * global external (public) functions
101*5c51f124SMoriah Waterland  * *****************************************************************************
102*5c51f124SMoriah Waterland  */
103*5c51f124SMoriah Waterland 
104*5c51f124SMoriah Waterland /*
105*5c51f124SMoriah Waterland  * Name:	quitGetTrapHandler
106*5c51f124SMoriah Waterland  * Description:	return address of this modules "signal trap" handler
107*5c51f124SMoriah Waterland  * Arguments:	void
108*5c51f124SMoriah Waterland  * Returns:	sighdlrFunc_t
109*5c51f124SMoriah Waterland  *			The address of the trap handler that can be passed to
110*5c51f124SMoriah Waterland  *			the signal() type system calls
111*5c51f124SMoriah Waterland  */
112*5c51f124SMoriah Waterland 
113*5c51f124SMoriah Waterland sighdlrFunc_t *
114*5c51f124SMoriah Waterland quitGetTrapHandler(void)
115*5c51f124SMoriah Waterland {
116*5c51f124SMoriah Waterland 	return (&trap);
117*5c51f124SMoriah Waterland }
118*5c51f124SMoriah Waterland 
119*5c51f124SMoriah Waterland /*
120*5c51f124SMoriah Waterland  * Name:	quitSetZoneName
121*5c51f124SMoriah Waterland  * Description:	set the zone name the program is running in
122*5c51f124SMoriah Waterland  * Arguments:	a_zoneName - pointer to string representing the name of the zone
123*5c51f124SMoriah Waterland  *			that the program is running in
124*5c51f124SMoriah Waterland  * Returns:	void
125*5c51f124SMoriah Waterland  */
126*5c51f124SMoriah Waterland 
127*5c51f124SMoriah Waterland void
128*5c51f124SMoriah Waterland quitSetZoneName(char *a_zoneName)
129*5c51f124SMoriah Waterland {
130*5c51f124SMoriah Waterland 	zoneName = a_zoneName;
131*5c51f124SMoriah Waterland 	if ((zoneName == (char *)NULL || *zoneName == '\0')) {
132*5c51f124SMoriah Waterland 		includeZonename = 0;
133*5c51f124SMoriah Waterland 	} else {
134*5c51f124SMoriah Waterland 		includeZonename = 1;
135*5c51f124SMoriah Waterland 	}
136*5c51f124SMoriah Waterland }
137*5c51f124SMoriah Waterland 
138*5c51f124SMoriah Waterland /*
139*5c51f124SMoriah Waterland  * Name:	quitSetDstreamTmpdir
140*5c51f124SMoriah Waterland  * Description:	set the name of a temporary directory that contains package
141*5c51f124SMoriah Waterland  *		streams to be removed when quit() is called
142*5c51f124SMoriah Waterland  * Arguments:	a_dstreamTempDir - pointer to string representing the path
143*5c51f124SMoriah Waterland  *			to the temporary directory to remove when quit()
144*5c51f124SMoriah Waterland  *			is called
145*5c51f124SMoriah Waterland  * Returns:	void
146*5c51f124SMoriah Waterland  */
147*5c51f124SMoriah Waterland 
148*5c51f124SMoriah Waterland void
149*5c51f124SMoriah Waterland quitSetDstreamTmpdir(char *a_dstreamTempDir)
150*5c51f124SMoriah Waterland {
151*5c51f124SMoriah Waterland 	dstreamTempDir = a_dstreamTempDir;
152*5c51f124SMoriah Waterland }
153*5c51f124SMoriah Waterland 
154*5c51f124SMoriah Waterland /*
155*5c51f124SMoriah Waterland  * Name:	quitSetUpdatingExisting
156*5c51f124SMoriah Waterland  * Description:	set the "updating existing" flag - used in conjunction
157*5c51f124SMoriah Waterland  *		with the "install started" flag to determine the type
158*5c51f124SMoriah Waterland  *		of cleanup to be done when quit() is called
159*5c51f124SMoriah Waterland  * Arguments:	a_updatingExistingPackage - indicates whether or not existing
160*5c51f124SMoriah Waterland  *			packages are being updated (B_TRUE) or new packages
161*5c51f124SMoriah Waterland  *			are being installed (B_FALSE)
162*5c51f124SMoriah Waterland  * Returns:	void
163*5c51f124SMoriah Waterland  */
164*5c51f124SMoriah Waterland 
165*5c51f124SMoriah Waterland void
166*5c51f124SMoriah Waterland quitSetUpdatingExisting(boolean_t a_updatingExistingPackage)
167*5c51f124SMoriah Waterland {
168*5c51f124SMoriah Waterland 	updatingExistingPackage = a_updatingExistingPackage;
169*5c51f124SMoriah Waterland }
170*5c51f124SMoriah Waterland 
171*5c51f124SMoriah Waterland /*
172*5c51f124SMoriah Waterland  * Name:	quitSetInstallStarted
173*5c51f124SMoriah Waterland  * Description:	set the "install started" flag - used in conjunction
174*5c51f124SMoriah Waterland  *		with the "updating existing" flag to determine the type
175*5c51f124SMoriah Waterland  *		of cleanup to be done when quit() is called, and the
176*5c51f124SMoriah Waterland  *		type of message to be output for the "reason" why quit()
177*5c51f124SMoriah Waterland  *		was called
178*5c51f124SMoriah Waterland  * Arguments:	a_installStarted - indicates whether or not installation
179*5c51f124SMoriah Waterland  *			has started
180*5c51f124SMoriah Waterland  * Returns:	void
181*5c51f124SMoriah Waterland  */
182*5c51f124SMoriah Waterland 
183*5c51f124SMoriah Waterland void
184*5c51f124SMoriah Waterland quitSetInstallStarted(boolean_t a_installStarted)
185*5c51f124SMoriah Waterland {
186*5c51f124SMoriah Waterland 	installStarted = a_installStarted;
187*5c51f124SMoriah Waterland }
188*5c51f124SMoriah Waterland 
189*5c51f124SMoriah Waterland /*
190*5c51f124SMoriah Waterland  * Name:	quitSetPkgask
191*5c51f124SMoriah Waterland  * Description:	set the "pkgask is being run" flag - used to determine
192*5c51f124SMoriah Waterland  *		the type of message to be output for the "reason" why
193*5c51f124SMoriah Waterland  *		quit() was called
194*5c51f124SMoriah Waterland  * Arguments:	a_pkgaskflag - indicates whether or not pkgask is being run
195*5c51f124SMoriah Waterland  * Returns:	void
196*5c51f124SMoriah Waterland  */
197*5c51f124SMoriah Waterland 
198*5c51f124SMoriah Waterland void
199*5c51f124SMoriah Waterland quitSetPkgask(boolean_t a_pkgaskFlag)
200*5c51f124SMoriah Waterland {
201*5c51f124SMoriah Waterland 	pkgaskFlag = a_pkgaskFlag;
202*5c51f124SMoriah Waterland }
203*5c51f124SMoriah Waterland 
204*5c51f124SMoriah Waterland /*
205*5c51f124SMoriah Waterland  * Name:	quitSetSilentExit
206*5c51f124SMoriah Waterland  * Description:	set the "silent exit" flag - if silent exit is TRUE, then
207*5c51f124SMoriah Waterland  *		no messages are output by quit() when it is called
208*5c51f124SMoriah Waterland  * Arguments:	a_silentExit - indicates whether or not silent exit is set
209*5c51f124SMoriah Waterland  * Returns:	void
210*5c51f124SMoriah Waterland  */
211*5c51f124SMoriah Waterland 
212*5c51f124SMoriah Waterland void
213*5c51f124SMoriah Waterland quitSetSilentExit(boolean_t a_silentExit)
214*5c51f124SMoriah Waterland {
215*5c51f124SMoriah Waterland 	silentExit = a_silentExit;
216*5c51f124SMoriah Waterland }
217*5c51f124SMoriah Waterland 
218*5c51f124SMoriah Waterland /*
219*5c51f124SMoriah Waterland  * Name:	quit
220*5c51f124SMoriah Waterland  * Description:	cleanup and exit
221*5c51f124SMoriah Waterland  * Arguments:	a_retcode - the code to use to determine final exit status;
222*5c51f124SMoriah Waterland  *			if this is NOT "99" and if a "ckreturnFunc" is
223*5c51f124SMoriah Waterland  *			set, then that function is called with a_retcode
224*5c51f124SMoriah Waterland  *			to set the final exit status.
225*5c51f124SMoriah Waterland  *		Valid values are:
226*5c51f124SMoriah Waterland  *		0 - success
227*5c51f124SMoriah Waterland  *		1 - package operation failed (fatal error)
228*5c51f124SMoriah Waterland  *		2 - non-fatal error (warning)
229*5c51f124SMoriah Waterland  *		3 - user selected quit (operation interrupted)
230*5c51f124SMoriah Waterland  *		4 - admin settings prevented operation
231*5c51f124SMoriah Waterland  *		5 - interaction required and -n (non-interactive) specified
232*5c51f124SMoriah Waterland  *		"10" is added to indicate "immediate reboot required"
233*5c51f124SMoriah Waterland  *		"20" is be added to indicate "reboot after install required"
234*5c51f124SMoriah Waterland  *		99 - do not interpret the code - just exit "99"
235*5c51f124SMoriah Waterland  * Returns:	<<this function does not return - calls exit()>>
236*5c51f124SMoriah Waterland  */
237*5c51f124SMoriah Waterland 
238*5c51f124SMoriah Waterland void
239*5c51f124SMoriah Waterland quit(int retcode)
240*5c51f124SMoriah Waterland {
241*5c51f124SMoriah Waterland 	char		orig_pkginfo_path[PATH_MAX];
242*5c51f124SMoriah Waterland 	char		pkginfo_path[PATH_MAX];
243*5c51f124SMoriah Waterland 
244*5c51f124SMoriah Waterland 	/* disable interrupts */
245*5c51f124SMoriah Waterland 
246*5c51f124SMoriah Waterland 	(void) signal(SIGINT, SIG_IGN);
247*5c51f124SMoriah Waterland 	(void) signal(SIGHUP, SIG_IGN);
248*5c51f124SMoriah Waterland 
249*5c51f124SMoriah Waterland 	/* process return code if not quit(99) */
250*5c51f124SMoriah Waterland 
251*5c51f124SMoriah Waterland 	if (retcode != 99) {
252*5c51f124SMoriah Waterland 		if ((retcode % 10) == 0) {
253*5c51f124SMoriah Waterland 			if (failflag) {
254*5c51f124SMoriah Waterland 				retcode += 1;
255*5c51f124SMoriah Waterland 			} else if (warnflag) {
256*5c51f124SMoriah Waterland 				retcode += 2;
257*5c51f124SMoriah Waterland 			}
258*5c51f124SMoriah Waterland 		}
259*5c51f124SMoriah Waterland 
260*5c51f124SMoriah Waterland 		if (ireboot) {
261*5c51f124SMoriah Waterland 			retcode = (retcode % 10) + 20;
262*5c51f124SMoriah Waterland 		}
263*5c51f124SMoriah Waterland 		if (dreboot) {
264*5c51f124SMoriah Waterland 			retcode = (retcode % 10) + 10;
265*5c51f124SMoriah Waterland 		}
266*5c51f124SMoriah Waterland 	}
267*5c51f124SMoriah Waterland 
268*5c51f124SMoriah Waterland 	/* if set remove dstream temporary directory */
269*5c51f124SMoriah Waterland 
270*5c51f124SMoriah Waterland 	if (dstreamTempDir != (char *)NULL) {
271*5c51f124SMoriah Waterland 		echoDebug(DBG_REMOVING_DSTREAM_TMPDIR, dstreamTempDir);
272*5c51f124SMoriah Waterland 		(void) rrmdir(dstreamTempDir);
273*5c51f124SMoriah Waterland 		dstreamTempDir = (char *)NULL;
274*5c51f124SMoriah Waterland 	}
275*5c51f124SMoriah Waterland 
276*5c51f124SMoriah Waterland 	/* If we're in dryrun mode, write out the dryrun file(s). */
277*5c51f124SMoriah Waterland 	if (in_dryrun_mode()) {
278*5c51f124SMoriah Waterland 		char exit_msg[200];
279*5c51f124SMoriah Waterland 		set_dr_info(EXITCODE, retcode);
280*5c51f124SMoriah Waterland 		if (failflag || warnflag) {
281*5c51f124SMoriah Waterland 			set_dr_exitmsg(msgtext);
282*5c51f124SMoriah Waterland 		} else {
283*5c51f124SMoriah Waterland 			/* LINTED variable format specified */
284*5c51f124SMoriah Waterland 			(void) snprintf(exit_msg, sizeof (exit_msg),
285*5c51f124SMoriah Waterland 				qreason(1, retcode, installStarted,
286*5c51f124SMoriah Waterland 					includeZonename),
287*5c51f124SMoriah Waterland 					(pkginst ? pkginst : "unknown"),
288*5c51f124SMoriah Waterland 					zoneName);
289*5c51f124SMoriah Waterland 			set_dr_exitmsg(exit_msg);
290*5c51f124SMoriah Waterland 		}
291*5c51f124SMoriah Waterland 
292*5c51f124SMoriah Waterland 		write_dryrun_file(extlist);
293*5c51f124SMoriah Waterland 		ptext(stderr, MSG_DRYRUN_DONE);
294*5c51f124SMoriah Waterland 		ptext(stderr, MSG_NOCHANGE);
295*5c51f124SMoriah Waterland 
296*5c51f124SMoriah Waterland 		if (tmpdir[0] != NULL)
297*5c51f124SMoriah Waterland 			(void) rrmdir(tmpdir);
298*5c51f124SMoriah Waterland 
299*5c51f124SMoriah Waterland 	} else {
300*5c51f124SMoriah Waterland 		/* fix bug #1082589 that deletes root file */
301*5c51f124SMoriah Waterland 		if (tmpdir[0] != NULL) {
302*5c51f124SMoriah Waterland 			(void) rrmdir(tmpdir);
303*5c51f124SMoriah Waterland 		}
304*5c51f124SMoriah Waterland 
305*5c51f124SMoriah Waterland 		/* send mail to appropriate user list */
306*5c51f124SMoriah Waterland 		mailmsg(retcode);
307*5c51f124SMoriah Waterland 
308*5c51f124SMoriah Waterland 		/* display message about this installation */
309*5c51f124SMoriah Waterland 		quitmsg(retcode);
310*5c51f124SMoriah Waterland 	}
311*5c51f124SMoriah Waterland 
312*5c51f124SMoriah Waterland 	/*
313*5c51f124SMoriah Waterland 	 * In the event that this quit() was called prior to completion of
314*5c51f124SMoriah Waterland 	 * the task, do an unlockinst() just in case.
315*5c51f124SMoriah Waterland 	 */
316*5c51f124SMoriah Waterland 	unlockinst();
317*5c51f124SMoriah Waterland 
318*5c51f124SMoriah Waterland 	/* Unmount anything that's our responsibility. */
319*5c51f124SMoriah Waterland 	(void) unmount_client();
320*5c51f124SMoriah Waterland 
321*5c51f124SMoriah Waterland 	/*
322*5c51f124SMoriah Waterland 	 * No need to umount device since calling process
323*5c51f124SMoriah Waterland 	 * was responsible for original mount
324*5c51f124SMoriah Waterland 	 */
325*5c51f124SMoriah Waterland 
326*5c51f124SMoriah Waterland 	if (!updatingExistingPackage) {
327*5c51f124SMoriah Waterland 		if (!installStarted && pkgloc[0]) {
328*5c51f124SMoriah Waterland 			/*
329*5c51f124SMoriah Waterland 			 * install not yet started; if package install
330*5c51f124SMoriah Waterland 			 * location is defined, remove the package.
331*5c51f124SMoriah Waterland 			 */
332*5c51f124SMoriah Waterland 			echoDebug(DBG_QUIT_REMOVING_PKGDIR, pkgloc);
333*5c51f124SMoriah Waterland 
334*5c51f124SMoriah Waterland 			(void) chdir("/");
335*5c51f124SMoriah Waterland 			if (pkgloc[0]) {
336*5c51f124SMoriah Waterland 				(void) rrmdir(pkgloc);
337*5c51f124SMoriah Waterland 			}
338*5c51f124SMoriah Waterland 		}
339*5c51f124SMoriah Waterland 	} else {
340*5c51f124SMoriah Waterland 		if (!installStarted) {
341*5c51f124SMoriah Waterland 			/*
342*5c51f124SMoriah Waterland 			 * If we haven't started, but have already done
343*5c51f124SMoriah Waterland 			 * the <PKGINST>/install directory rename, then
344*5c51f124SMoriah Waterland 			 * remove the new <PKGINST>/install directory
345*5c51f124SMoriah Waterland 			 * and rename <PKGINST>/install.save back to
346*5c51f124SMoriah Waterland 			 * <PKGINST>/install.
347*5c51f124SMoriah Waterland 			 */
348*5c51f124SMoriah Waterland 			if (pkgloc_sav[0] && !access(pkgloc_sav, F_OK)) {
349*5c51f124SMoriah Waterland 				if (pkgloc[0] && !access(pkgloc, F_OK))
350*5c51f124SMoriah Waterland 					(void) rrmdir(pkgloc);
351*5c51f124SMoriah Waterland 				if (rename(pkgloc_sav, pkgloc) == -1) {
352*5c51f124SMoriah Waterland 					progerr(ERR_PACKAGEBINREN,
353*5c51f124SMoriah Waterland 						pkgloc_sav, pkgloc);
354*5c51f124SMoriah Waterland 				}
355*5c51f124SMoriah Waterland 			}
356*5c51f124SMoriah Waterland 		} else {
357*5c51f124SMoriah Waterland 			if (pkgloc_sav[0] && !access(pkgloc_sav, F_OK)) {
358*5c51f124SMoriah Waterland 				echoDebug(DBG_QUIT_REMOVING_PKGSAV, pkgloc_sav);
359*5c51f124SMoriah Waterland 				(void) rrmdir(pkgloc_sav);
360*5c51f124SMoriah Waterland 			}
361*5c51f124SMoriah Waterland 		}
362*5c51f124SMoriah Waterland 
363*5c51f124SMoriah Waterland 		if (isPatchUpdate()) {
364*5c51f124SMoriah Waterland 			if (pkgloc[0] && !access(pkgloc, F_OK) &&
365*5c51f124SMoriah Waterland 				!access(saveSpoolInstallDir, F_OK)) {
366*5c51f124SMoriah Waterland 				/*
367*5c51f124SMoriah Waterland 				 * Copy the pkginfo file to the pspool
368*5c51f124SMoriah Waterland 				 * directory. This propagates patch
369*5c51f124SMoriah Waterland 				 * info to the patched pkg in the local
370*5c51f124SMoriah Waterland 				 * zone.
371*5c51f124SMoriah Waterland 				 */
372*5c51f124SMoriah Waterland 				(void) snprintf(orig_pkginfo_path,
373*5c51f124SMoriah Waterland 					sizeof (orig_pkginfo_path),
374*5c51f124SMoriah Waterland 					"%s/%s/%s", get_PKGLOC(),
375*5c51f124SMoriah Waterland 					pkginst, PKGINFO);
376*5c51f124SMoriah Waterland 
377*5c51f124SMoriah Waterland 				(void) snprintf(pkginfo_path,
378*5c51f124SMoriah Waterland 					sizeof (pkginfo_path), "%s/%s",
379*5c51f124SMoriah Waterland 					saveSpoolInstallDir, PKGINFO);
380*5c51f124SMoriah Waterland 
381*5c51f124SMoriah Waterland 				if (cppath(MODE_SET|DIR_DISPLAY,
382*5c51f124SMoriah Waterland 					orig_pkginfo_path, pkginfo_path,
383*5c51f124SMoriah Waterland 					0644)) {
384*5c51f124SMoriah Waterland 					progerr(ERR_PKGINFO_COPY,
385*5c51f124SMoriah Waterland 							orig_pkginfo_path,
386*5c51f124SMoriah Waterland 							pkginfo_path);
387*5c51f124SMoriah Waterland 				}
388*5c51f124SMoriah Waterland 			}
389*5c51f124SMoriah Waterland 		}
390*5c51f124SMoriah Waterland 	}
391*5c51f124SMoriah Waterland 
392*5c51f124SMoriah Waterland 	/*
393*5c51f124SMoriah Waterland 	 * pkginst can be null if an administration setting doesn't all
394*5c51f124SMoriah Waterland 	 * the package to be installed. Make sure pkginst exeists before
395*5c51f124SMoriah Waterland 	 * updating the DB
396*5c51f124SMoriah Waterland 	 */
397*5c51f124SMoriah Waterland 
398*5c51f124SMoriah Waterland 	if (dparts > 0)
399*5c51f124SMoriah Waterland 		ds_skiptoend(pkgdev.cdevice);
400*5c51f124SMoriah Waterland 	(void) ds_close(1);
401*5c51f124SMoriah Waterland 
402*5c51f124SMoriah Waterland 	/* Free the filesystem table. */
403*5c51f124SMoriah Waterland 	fs_tab_free();
404*5c51f124SMoriah Waterland 
405*5c51f124SMoriah Waterland 	/* Free the package information lists. */
406*5c51f124SMoriah Waterland 	pinfo_free();
407*5c51f124SMoriah Waterland 
408*5c51f124SMoriah Waterland 	/* Free all stragglers. */
409*5c51f124SMoriah Waterland 	bl_free(BL_ALL);
410*5c51f124SMoriah Waterland 	(void) pathdup(NULL);
411*5c51f124SMoriah Waterland 
412*5c51f124SMoriah Waterland 	/* Free regfiles. */
413*5c51f124SMoriah Waterland 	regfiles_free();
414*5c51f124SMoriah Waterland 
415*5c51f124SMoriah Waterland 	/* final exit debugging message */
416*5c51f124SMoriah Waterland 
417*5c51f124SMoriah Waterland 	echoDebug(DBG_EXIT_WITH_CODE, retcode);
418*5c51f124SMoriah Waterland 
419*5c51f124SMoriah Waterland 	exit(retcode);
420*5c51f124SMoriah Waterland 	/*NOTREACHED*/
421*5c51f124SMoriah Waterland }
422*5c51f124SMoriah Waterland 
423*5c51f124SMoriah Waterland /*
424*5c51f124SMoriah Waterland  * *****************************************************************************
425*5c51f124SMoriah Waterland  * static internal (private) functions
426*5c51f124SMoriah Waterland  * *****************************************************************************
427*5c51f124SMoriah Waterland  */
428*5c51f124SMoriah Waterland 
429*5c51f124SMoriah Waterland static void
430*5c51f124SMoriah Waterland quitmsg(int retcode)
431*5c51f124SMoriah Waterland {
432*5c51f124SMoriah Waterland 	if (silentExit == B_TRUE) {
433*5c51f124SMoriah Waterland 		return;
434*5c51f124SMoriah Waterland 	}
435*5c51f124SMoriah Waterland 
436*5c51f124SMoriah Waterland 	(void) putc('\n', stderr);
437*5c51f124SMoriah Waterland 	if (pkgaskFlag) {
438*5c51f124SMoriah Waterland 		ptext(stderr, qreason(0, retcode, installStarted,
439*5c51f124SMoriah Waterland 			includeZonename), zoneName);
440*5c51f124SMoriah Waterland 	} else if (pkginst) {
441*5c51f124SMoriah Waterland 		ptext(stderr, qreason(1, retcode, installStarted,
442*5c51f124SMoriah Waterland 			includeZonename), pkginst, zoneName);
443*5c51f124SMoriah Waterland 	}
444*5c51f124SMoriah Waterland 
445*5c51f124SMoriah Waterland 	if (retcode && !installStarted) {
446*5c51f124SMoriah Waterland 		ptext(stderr, MSG_NOCHANGE);
447*5c51f124SMoriah Waterland 	}
448*5c51f124SMoriah Waterland }
449*5c51f124SMoriah Waterland 
450*5c51f124SMoriah Waterland static void
451*5c51f124SMoriah Waterland mailmsg(int retcode)
452*5c51f124SMoriah Waterland {
453*5c51f124SMoriah Waterland 	struct utsname utsbuf;
454*5c51f124SMoriah Waterland 	FILE	*pp;
455*5c51f124SMoriah Waterland 	char	*cmd;
456*5c51f124SMoriah Waterland 	size_t	len;
457*5c51f124SMoriah Waterland 
458*5c51f124SMoriah Waterland 	if (silentExit == B_TRUE) {
459*5c51f124SMoriah Waterland 		return;
460*5c51f124SMoriah Waterland 	}
461*5c51f124SMoriah Waterland 
462*5c51f124SMoriah Waterland 	if (!installStarted || pkgaskFlag || (adm.mail == NULL)) {
463*5c51f124SMoriah Waterland 		return;
464*5c51f124SMoriah Waterland 	}
465*5c51f124SMoriah Waterland 
466*5c51f124SMoriah Waterland 	len = strlen(adm.mail) + sizeof (MAILCMD) + 2;
467*5c51f124SMoriah Waterland 	cmd = calloc(len, sizeof (char));
468*5c51f124SMoriah Waterland 	if (cmd == NULL) {
469*5c51f124SMoriah Waterland 		logerr(WRN_NOMAIL);
470*5c51f124SMoriah Waterland 		return;
471*5c51f124SMoriah Waterland 	}
472*5c51f124SMoriah Waterland 
473*5c51f124SMoriah Waterland 	(void) snprintf(cmd, len, "%s %s", MAILCMD, adm.mail);
474*5c51f124SMoriah Waterland 	if ((pp = popen(cmd, "w")) == NULL) {
475*5c51f124SMoriah Waterland 		logerr(WRN_NOMAIL);
476*5c51f124SMoriah Waterland 		return;
477*5c51f124SMoriah Waterland 	}
478*5c51f124SMoriah Waterland 
479*5c51f124SMoriah Waterland 	if (msgtext)
480*5c51f124SMoriah Waterland 		ptext(pp, msgtext);
481*5c51f124SMoriah Waterland 
482*5c51f124SMoriah Waterland 	(void) strcpy(utsbuf.nodename, MSG_NODENAME);
483*5c51f124SMoriah Waterland 	(void) uname(&utsbuf);
484*5c51f124SMoriah Waterland 
485*5c51f124SMoriah Waterland 	ptext(pp, qreason(2, retcode, installStarted, includeZonename),
486*5c51f124SMoriah Waterland 		pkgname, utsbuf.nodename, pkginst, zoneName);
487*5c51f124SMoriah Waterland 
488*5c51f124SMoriah Waterland 	if (pclose(pp)) {
489*5c51f124SMoriah Waterland 		logerr(WRN_FLMAIL);
490*5c51f124SMoriah Waterland 	}
491*5c51f124SMoriah Waterland }
492*5c51f124SMoriah Waterland 
493*5c51f124SMoriah Waterland /*
494*5c51f124SMoriah Waterland  * Name:	trap
495*5c51f124SMoriah Waterland  * Description:	signal handler connected via quitGetTrapHandler()
496*5c51f124SMoriah Waterland  * Arguments:	signo - [RO, *RO] - (int)
497*5c51f124SMoriah Waterland  *			Integer representing the signal that caused the trap
498*5c51f124SMoriah Waterland  *			to this function to occur
499*5c51f124SMoriah Waterland  * Returns:	<< NONE >>
500*5c51f124SMoriah Waterland  * NOTE:	This function exits the program after doing mandatory cleanup.
501*5c51f124SMoriah Waterland  * NOTE:	Even though quit() should NOT return, there is a call to _exit()
502*5c51f124SMoriah Waterland  *		put after each call to quit() just in case quit() ever returned
503*5c51f124SMoriah Waterland  *		by mistake.
504*5c51f124SMoriah Waterland  */
505*5c51f124SMoriah Waterland 
506*5c51f124SMoriah Waterland static void
507*5c51f124SMoriah Waterland trap(int signo)
508*5c51f124SMoriah Waterland {
509*5c51f124SMoriah Waterland 	/* prevent reentrance */
510*5c51f124SMoriah Waterland 
511*5c51f124SMoriah Waterland 	if (trapEntered++ != 0) {
512*5c51f124SMoriah Waterland 		return;
513*5c51f124SMoriah Waterland 	}
514*5c51f124SMoriah Waterland 
515*5c51f124SMoriah Waterland 	if ((signo == SIGINT) || (signo == SIGHUP)) {
516*5c51f124SMoriah Waterland 		quit(3);
517*5c51f124SMoriah Waterland 		_exit(3);
518*5c51f124SMoriah Waterland 	}
519*5c51f124SMoriah Waterland 	quit(1);
520*5c51f124SMoriah Waterland 	_exit(1);
521*5c51f124SMoriah Waterland }
522