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