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