1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 
29 
30 #include <stdio.h>
31 #include <time.h>
32 #include <wait.h>
33 #include <stdlib.h>
34 #include <unistd.h>
35 #include <ulimit.h>
36 #include <sys/stat.h>
37 #include <sys/statvfs.h>
38 #include <fcntl.h>
39 #include <errno.h>
40 #include <ctype.h>
41 #include <dirent.h>
42 #include <string.h>
43 #include <signal.h>
44 #include <locale.h>
45 #include <libintl.h>
46 #include <pkgstrct.h>
47 #include <pkginfo.h>
48 #include <pkgdev.h>
49 #include <pkglocs.h>
50 #include <pwd.h>
51 #include <assert.h>
52 #include <instzones_api.h>
53 #include <pkglib.h>
54 #include <pkgweb.h>
55 #include <install.h>
56 #include <libinst.h>
57 #include <libadm.h>
58 #include <dryrun.h>
59 #include <messages.h>
60 #include "pkginstall.h"
61 
62 /* imported globals */
63 
64 extern char	**environ;
65 extern char	*pkgabrv;
66 extern char	*pkgname;
67 extern char	*pkgarch;
68 extern char	*pkgvers;
69 extern char	pkgwild[];
70 
71 /* libadm(3LIB) */
72 
73 extern char	*get_install_root(void);
74 
75 /* quit.c */
76 
77 extern sighdlrFunc_t	*quitGetTrapHandler(void);
78 extern void		quitSetDstreamTmpdir(char *a_dstreamTempDir);
79 extern void		quitSetInstallStarted(boolean_t a_installStarted);
80 extern void		quitSetPkgask(boolean_t a_pkgaskFlag);
81 extern void		quitSetSilentExit(boolean_t a_silentExit);
82 extern void		quitSetUpdatingExisting(boolean_t a_updatingExisting);
83 extern void		quitSetZoneName(char *a_zoneName);
84 
85 
86 /* static globals */
87 
88 static char	path[PATH_MAX];
89 static int	ck_instbase(void);
90 static int	cp_pkgdirs(void);
91 static int	merg_pkginfos(struct cl_attr **pclass,
92 		struct cl_attr ***mpclass);
93 static int	merg_respfile(void);
94 static int	mv_pkgdirs(void);
95 static int	rdonly(char *p);
96 static void	ck_w_dryrun(int (*func)(), int type);
97 static void	copyright(void), usage(void);
98 static void	do_pkgask(boolean_t a_run_request_as_root);
99 static void	rm_icas(char *casdir);
100 static void	set_dryrun_dir_loc(void);
101 static void	unpack(void);
102 
103 void	ckreturn(int retcode, char *msg);
104 
105 static char	*ro_params[] = {
106 	"PATH", "NAME", "PKG", "PKGINST",
107 	"VERSION", "ARCH",
108 	"INSTDATE", "CATEGORY",
109 	NULL
110 };
111 
112 /*
113  * The following variable is the name of the device to which stdin
114  * is connected during execution of a procedure script. PROC_STDIN is
115  * correct for all ABI compliant packages. For non-ABI-compliant
116  * packages, the '-o' command line switch changes this to PROC_XSTDIN
117  * to allow user interaction during these scripts. -- JST
118  */
119 static char	*script_in = PROC_STDIN;	/* assume ABI compliance */
120 
121 static char	*pkgdrtarg = NULL;
122 static char	*pkgcontsrc = NULL;
123 static int	non_abi_scripts = 0;
124 static char	*respfile = NULL;
125 static char	*srcinst = NULL;
126 static int	suppressCopyright = 0;
127 static int	nointeract = 0;
128 
129 /* exported globals */
130 
131 char		*msgtext;
132 char		*pkginst = (char *)NULL;
133 char		*rw_block_size = NULL;
134 char		ilockfile[PATH_MAX];
135 char		instdir[PATH_MAX];
136 char		saveSpoolInstallDir[PATH_MAX];
137 char		pkgbin[PATH_MAX];
138 char		pkgloc[PATH_MAX];
139 char		pkgloc_sav[PATH_MAX];
140 char		pkgsav[PATH_MAX];
141 char		rlockfile[PATH_MAX];
142 char		savlog[PATH_MAX];
143 char		tmpdir[PATH_MAX];
144 int		dbchg;
145 int		dparts = 0;
146 int		dreboot = 0;
147 int		failflag = 0;
148 static int	askflag = 0;		/* non-zero if invoked as "pkgask" */
149 int		ireboot = 0;
150 int		maxinst = 1;
151 int		nocnflct;
152 int		nosetuid;
153 int		pkgverbose = 0;
154 int		rprcflag;
155 int		warnflag = 0;
156 struct admin	adm;
157 struct cfextra	**extlist; /* pkgmap structure and other path info */
158 struct pkgdev	pkgdev;
159 fsblkcnt_t	pkgmap_blks = 0LL;
160 
161 /*
162  * this global is referenced by:
163  * getinst - [RW] - incremented if:
164  * - installing same instance again
165  * - overwriting an existing instance
166  * - not installing a new instance
167  * quit - [RO] - if non-zero and started non-zero:
168  * - the new <PKGINST>/install directory and rename <PKGINST>/install.save
169  * - back to <PKGINST>/install
170  * main.c - [RO] - if non-zero:
171  * - alter manner in which parameters are setup for scripts
172  * - set UPDATE=yes in environment
173  */
174 static int		update = 0;
175 
176 /* Set by -O debug: debug output is enabled? */
177 
178 static boolean_t	debugFlag = B_FALSE;
179 
180 /* Set by the -G option: install packages in global zone only */
181 
182 static boolean_t	globalZoneOnly = B_FALSE;
183 
184 /* Set by -O preinstallcheck */
185 
186 static boolean_t	preinstallCheck = B_FALSE;
187 
188 /* Set by -O parent-zone-name= */
189 
190 static char		*parentZoneName = (char *)NULL;
191 
192 /* Set by -O parent-zone-type= */
193 
194 static char		*parentZoneType = (char *)NULL;
195 
196 #define	DEFPATH		"/sbin:/usr/sbin:/usr/bin"
197 #define	MALSIZ	4	/* best guess at likely maximum value of MAXINST */
198 #define	LSIZE	256	/* maximum line size supported in copyright file */
199 
200 #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
201 #define	TEXT_DOMAIN "SYS_TEST"
202 #endif
203 
204 /* This is the text for the "-O parent-zone-name=" option */
205 
206 #define	PARENTZONENAME	"parent-zone-name="
207 #define	PARENTZONENAME_LEN	((sizeof (PARENTZONENAME))-1)
208 
209 /* This is the text for the "-O parent-zone-type=" option */
210 
211 #define	PARENTZONETYPE	"parent-zone-type="
212 #define	PARENTZONETYPE_LEN	((sizeof (PARENTZONETYPE))-1)
213 
214 static char *cpio_names[] = {
215 	"root",
216 	"root.cpio",
217 	"reloc",
218 	"reloc.cpio",
219 	"root.Z",
220 	"root.cpio.Z",
221 	"reloc.Z",
222 	"reloc.cpio.Z",
223 	0
224 };
225 
226 int
227 main(int argc, char *argv[])
228 {
229 	VFP_T			*cfTmpVfp = NULL;	/* temporary */
230 	VFP_T			*pkgmapVfp;	/* "../pkgmap" file */
231 	boolean_t		run_request_as_root = B_FALSE;
232 	char			**np;
233 	char			*abi_comp_ptr;
234 	char			*abi_nm_ptr;
235 	char			*abi_sym_ptr;
236 	char			*admnfile = NULL;
237 	char			*device;
238 	char			*p;
239 	char			*prog_full_name = NULL;
240 	char			*pt;
241 	char			*updated = (char *)NULL;
242 	char			*vfstab_file = NULL;
243 	char			*zoneName = (char *)NULL;
244 	char			cbuf[MAX_PKG_PARAM_LENGTH];
245 	char			cmdbin[PATH_MAX];
246 	char			p_pkginfo[PATH_MAX];
247 	char			p_pkgmap[PATH_MAX];
248 	char			param[MAX_PKG_PARAM_LENGTH];
249 	char			script[PATH_MAX];
250 	char			altscript[PATH_MAX];
251 	char			*temp;
252 	int			c;
253 	int			disableAttributes = 0;
254 	int			err;
255 	int			init_install = 0;
256 	int			is_comp_arch;
257 	int			live_continue = 0;
258 	int			map_client = 1;
259 	int			n;
260 	int			nparts;
261 	int			npkgs;
262 	int			part;
263 	int			saveSpoolInstall = 0;
264 	boolean_t		cont_file_read;
265 	struct cl_attr		**pclass = NULL;
266 	struct cl_attr		**mergd_pclass = NULL;
267 	struct pkginfo		*prvinfo;
268 	struct sigaction	nact;
269 	struct sigaction	oact;
270 	struct stat		statb;
271 	struct statvfs64	svfsb;
272 	time_t			clock;
273 	PKGserver		pkgserver = NULL;
274 
275 	/* reset contents of all default paths */
276 
277 	(void) memset(path, '\0', sizeof (path));
278 	(void) memset(cmdbin, '\0', sizeof (cmdbin));
279 	(void) memset(script, '\0', sizeof (script));
280 	(void) memset(cbuf, '\0', sizeof (cbuf));
281 	(void) memset(param, '\0', sizeof (param));
282 
283 	/* initialize locale environment */
284 
285 	(void) setlocale(LC_ALL, "");
286 	(void) textdomain(TEXT_DOMAIN);
287 
288 	/* initialize program name */
289 
290 	prog_full_name = argv[0];
291 	(void) set_prog_name(argv[0]);
292 
293 	/* tell spmi zones interface how to access package output functions */
294 
295 	z_set_output_functions(echo, echoDebug, progerr);
296 
297 	/* exit if not root */
298 
299 	if (getuid()) {
300 		progerr(ERR_NOT_ROOT, get_prog_name());
301 		exit(1);
302 		/* NOTREACHED */
303 	}
304 
305 	/*
306 	 * determine how pkgmap() deals with environment variables:
307 	 *  - MAPALL - resolve all variables
308 	 *  - MAPBUILD - map only build variables
309 	 *  - MAPINSTALL - map only install variables
310 	 *  - MAPNONE - map no variables
311 	 */
312 
313 	setmapmode(MAPINSTALL);
314 
315 	/* set sane umask */
316 
317 	(void) umask(0022);
318 
319 	/* initially no source "device" */
320 
321 	device = NULL;
322 
323 	/* reset npkgs (used as pkg remaining count in quit.c) */
324 
325 	npkgs = 0;
326 
327 	/* Read PKG_INSTALL_ROOT from the environment, if it's there. */
328 
329 	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
330 		progerr(ERR_ROOT_SET);
331 		exit(1);
332 	}
333 
334 	pkgserversetmode(DEFAULTMODE);
335 
336 	/* parse command line options */
337 
338 	while ((c = getopt(argc, argv,
339 		"?Aa:B:b:Cc:D:d:eFf:GhIiMm:N:noO:p:R:r:StV:vyz")) != EOF) {
340 
341 		switch (c) {
342 
343 		/*
344 		 * Same as pkgadd: This disables attribute checking.
345 		 * It speeds up installation a little bit.
346 		 */
347 		case 'A':
348 			disableAttributes++;
349 			break;
350 
351 		/*
352 		 * Same as pkgadd: Define an installation administration
353 		 * file, admin, to be used in place of the default
354 		 * administration file.  The token none overrides the use
355 		 * of any admin file, and thus forces interaction with the
356 		 * user. Unless a full path name is given, pkgadd first
357 		 * looks in the current working directory for the
358 		 * administration file.  If the specified administration
359 		 * file is not in the current working directory, pkgadd
360 		 * looks in the /var/sadm/install/admin directory for the
361 		 * administration file.
362 		 */
363 		case 'a':
364 			admnfile = flex_device(optarg, 0);
365 			break;
366 
367 		/*
368 		 * Same as pkgadd: control block size given to
369 		 * pkginstall - block size used in read()/write() loop;
370 		 * default is st_blksize from stat() of source file.
371 		 */
372 		case 'B':
373 			rw_block_size = optarg;
374 			break;
375 
376 		/*
377 		 * Same as pkgadd: location where executables needed
378 		 * by procedure scripts can be found
379 		 * default is /usr/sadm/install/bin.
380 		 */
381 		case 'b':
382 			if (!path_valid(optarg)) {
383 				progerr(ERR_PATH, optarg);
384 				exit(1);
385 			}
386 			if (isdir(optarg) != 0) {
387 				char *p = strerror(errno);
388 				progerr(ERR_CANNOT_USE_DIR, optarg, p);
389 				exit(1);
390 			}
391 			(void) strlcpy(cmdbin, optarg, sizeof (cmdbin));
392 			break;
393 
394 		/*
395 		 * Same as pkgadd: This disables checksum tests on
396 		 * the source files. It speeds up installation a little bit.
397 		 */
398 		case 'C':
399 			(void) checksum_off();
400 			break;
401 
402 		/*
403 		 * Same as pkgadd: This allows designation of a
404 		 * continuation file. It is the same format as a dryrun file
405 		 * but it is used to take up where the dryrun left off.
406 		 */
407 		case 'c':
408 			pkgcontsrc = optarg;
409 			set_continue_mode();
410 			set_dr_info(DR_TYPE, INSTALL_TYPE);
411 			init_contfile(pkgcontsrc);
412 			break;
413 
414 		/*
415 		 * Same as pkgadd: This allows designation of a
416 		 * dryrun file. This pkgadd will create dryrun files
417 		 * in the directory provided.
418 		 */
419 		case 'D':
420 			pkgdrtarg = optarg;
421 			set_dryrun_mode();
422 			set_dr_info(DR_TYPE, INSTALL_TYPE);
423 			break;
424 
425 		/*
426 		 * Same as pkgadd: Install or copy a package from
427 		 * device. device can be a full path name to a directory
428 		 * or the identifiers for tape, floppy disk, or removable
429 		 * disk - for example, /var/tmp or /floppy/floppy_name.
430 		 * It can also be a device alias - for example,
431 		 * /floppy/floppy0, or a datastream created by pkgtrans.
432 		 */
433 		case 'd':
434 			device = flex_device(optarg, 1);
435 			break;
436 
437 		/*
438 		 * Different from pkgadd: disable the 32 char name
439 		 * limit extension
440 		 */
441 		case 'e':
442 			(void) set_ABI_namelngth();
443 			break;
444 
445 		/*
446 		 * Different from pkgadd: specify file system type for
447 		 * the package device. Must be used with -m.
448 		 */
449 		case 'f':
450 			pkgdev.fstyp = optarg;
451 			break;
452 
453 		/*
454 		 * Same as pkgadd: install package in global zone only.
455 		 */
456 		case 'G':
457 			globalZoneOnly = B_TRUE;
458 			break;
459 
460 		/*
461 		 * Same as pkgadd: Enable hollow package support. When
462 		 * specified, for any package that has SUNW_PKG_HOLLOW=true:
463 		 *  Do not calculate and verify package size against target.
464 		 *  Do not run any package procedure or class action scripts.
465 		 *  Do not create any target directories.
466 		 *  Do not perform any script locking.
467 		 *  Do not install any components of any package.
468 		 *  Do not output any status or database update messages.
469 		 */
470 		case 'h':
471 			set_depend_pkginfo_DB(B_TRUE);
472 			break;
473 
474 		/*
475 		 * Same as pkgadd: Informs scripts that this is
476 		 * an initial install by setting the environment parameter
477 		 * PKG_INIT_INSTALL=TRUE for all scripts. They may use it as
478 		 * they see fit, safe in the knowledge that the target
479 		 * filesystem is tabula rasa.
480 		 */
481 		case 'I':
482 			init_install++;
483 			break;
484 
485 		/*
486 		 * Different from pkgadd: use by pkgask.
487 		 */
488 		case 'i':
489 			askflag++;
490 			quitSetPkgask(B_TRUE);
491 			break;
492 
493 		/*
494 		 * Same as pkgadd: Instruct pkgadd not to use the
495 		 * $root_path/etc/vfstab file for determining the client's
496 		 * mount points. This option assumes the mount points are
497 		 * correct on the server and it behaves consistently with
498 		 * Solaris 2.5 and earlier releases.
499 		 */
500 		case 'M':
501 			map_client = 0;
502 			break;
503 
504 		/*
505 		 * Different from pkgadd: specify device to use for package
506 		 * source.
507 		 */
508 		case 'm':
509 			pkgdev.mount = optarg;
510 			pkgdev.rdonly++;
511 			pkgdev.mntflg++;
512 			break;
513 
514 		/*
515 		 * Different from pkgadd: specify program name to use
516 		 * for messages.
517 		 */
518 		case 'N':
519 			(void) set_prog_name(optarg);
520 			break;
521 
522 		/*
523 		 * Same as pkgadd: installation occurs in
524 		 * non-interactive mode.  Suppress output of the list of
525 		 * installed files. The default mode is interactive.
526 		 */
527 		case 'n':
528 			nointeract++;
529 			(void) echoSetFlag(B_FALSE);
530 			break;
531 
532 		/*
533 		 * Almost same as pkgadd: the -O option allows the behavior
534 		 * of the package tools to be modified. Recognized options:
535 		 * -> debug
536 		 * ---> enable debugging output
537 		 * -> preinstallcheck
538 		 * ---> perform a "pre installation" check of the specified
539 		 * ---> package - suppress all regular output and cause a
540 		 * ---> series of one or more "name=value" pair format lines
541 		 * ---> to be output that describes the "installability" of
542 		 * ---> the specified package
543 		 * -> enable-hollow-package-support
544 		 * --> Enable hollow package support. When specified, for any
545 		 * --> package that has SUNW_PKG_HOLLOW=true:
546 		 * --> Do not calculate and verify package size against target
547 		 * --> Do not run any package procedure or class action scripts
548 		 * --> Do not create or remove any target directories
549 		 * --> Do not perform any script locking
550 		 * --> Do not install or uninstall any components of any package
551 		 * --> Do not output any status or database update messages
552 		 */
553 		case 'O':
554 			for (p = strtok(optarg, ","); p != (char *)NULL;
555 				p = strtok(NULL, ",")) {
556 
557 				/* process debug option */
558 
559 				if (strcmp(p, "debug") == 0) {
560 					/* set debug flag/enable debug output */
561 					if (debugFlag == B_TRUE) {
562 						smlSetVerbose(B_TRUE);
563 					}
564 					debugFlag = B_TRUE;
565 					(void) echoDebugSetFlag(debugFlag);
566 
567 					/* debug info on arguments to pkgadd */
568 					for (n = 0; n < argc && argv[n]; n++) {
569 						echoDebug(DBG_ARG, n, argv[n]);
570 					}
571 
572 					continue;
573 				}
574 
575 				/* process enable-hollow-package-support opt */
576 
577 				if (strcmp(p,
578 					"enable-hollow-package-support") == 0) {
579 					set_depend_pkginfo_DB(B_TRUE);
580 					continue;
581 				}
582 
583 				/* process preinstallcheck option */
584 
585 				if (strcmp(p, "preinstallcheck") == 0) {
586 					preinstallCheck = B_TRUE;
587 					nointeract++;	/* -n */
588 					suppressCopyright++;	/* -S */
589 					quitSetSilentExit(B_TRUE);
590 					continue;
591 				}
592 
593 				/* process addzonename option */
594 
595 				if (strcmp(p, "addzonename") == 0) {
596 					/*
597 					 * set zone name to add to messages;
598 					 * first look in the current environment
599 					 * and use the default package zone name
600 					 * if it is set; otherwise, use the name
601 					 * of the current zone
602 					 */
603 					zoneName =
604 						getenv(PKG_ZONENAME_VARIABLE);
605 
606 					if ((zoneName == (char *)NULL) ||
607 							(*zoneName == '\0')) {
608 						zoneName = z_get_zonename();
609 					}
610 
611 					if (zoneName != (char *)NULL) {
612 						if (*zoneName != '\0') {
613 							quitSetZoneName(
614 								zoneName);
615 						} else {
616 							zoneName = (char *)NULL;
617 						}
618 					}
619 					continue;
620 				}
621 
622 				/* process parent-zone-name option */
623 
624 				if (strncmp(p, PARENTZONENAME,
625 						PARENTZONENAME_LEN) == 0) {
626 					parentZoneName = p+PARENTZONENAME_LEN;
627 					continue;
628 				}
629 
630 				/* process parent-zone-type option */
631 
632 				if (strncmp(p, PARENTZONETYPE,
633 						PARENTZONETYPE_LEN) == 0) {
634 					parentZoneType = p+PARENTZONETYPE_LEN;
635 					continue;
636 				}
637 
638 				if (strncmp(p, PKGSERV_MODE,
639 				    PKGSERV_MODE_LEN) == 0) {
640 					pkgserversetmode(pkgparsemode(p +
641 					    PKGSERV_MODE_LEN));
642 					continue;
643 				}
644 
645 				/* option not recognized - issue warning */
646 
647 				progerr(ERR_INVALID_O_OPTION, p);
648 				continue;
649 
650 			}
651 			break;
652 
653 		/*
654 		 * Different from pkgadd: This is an old non-ABI package
655 		 */
656 		case 'o':
657 			non_abi_scripts++;
658 			break;
659 
660 		/*
661 		 * Different from pkgadd: specify number of parts to package.
662 		 */
663 		case 'p':
664 			dparts = ds_getinfo(optarg);
665 			break;
666 
667 		/*
668 		 * Same as pkgadd: Define the full path name of a
669 		 * directory to use as the root_path.  All files,
670 		 * including package system information files, are
671 		 * relocated to a directory tree starting in the specified
672 		 * root_path. The root_path may be specified when
673 		 * installing to a client from a server (for example,
674 		 * /export/root/client1).
675 		 */
676 		case 'R':
677 			if (!set_inst_root(optarg)) {
678 				progerr(ERR_ROOT_CMD);
679 				exit(1);
680 			}
681 			break;
682 
683 		/*
684 		 * Same as pkgadd: Identify a file or directory which
685 		 * contains output from a previous pkgask(1M)
686 		 * session. This file supplies the interaction responses
687 		 * that would be requested by the package in interactive
688 		 * mode. response must be a full pathname.
689 		 */
690 		case 'r':
691 			respfile = flex_device(optarg, 2);
692 			break;
693 
694 		/*
695 		 * Same as pkgadd: suppress copyright notice being
696 		 * output during installation.
697 		 */
698 		case 'S':
699 			suppressCopyright++;
700 			break;
701 
702 		/*
703 		 * Same as pkgadd: disable save spool area creation;
704 		 * do not spool any partial package contents, that is,
705 		 * suppress the creation and population of the package save
706 		 * spool area (var/sadm/pkg/PKG/save/pspool/PKG).
707 		 */
708 		case 't':
709 			disable_spool_create();
710 			break;
711 
712 		/*
713 		 * Same as pkgadd: Specify an alternative fs_file to map
714 		 * the client's file systems.  For example, used in
715 		 * situations where the $root_path/etc/vfstab file is
716 		 * non-existent or unreliable. Informs the pkginstall
717 		 * portion to mount up a client filesystem based upon the
718 		 * supplied vfstab-like file of stable format.
719 		 */
720 		case 'V':
721 			vfstab_file = flex_device(optarg, 2);
722 			map_client = 1;
723 			break;
724 
725 		/*
726 		 * Same as pkgadd: Trace all of the scripts that get
727 		 * executed by pkgadd, located in the pkginst/install
728 		 * directory. This option is used for debugging the
729 		 * procedural and non-procedural scripts
730 		 */
731 		case 'v':
732 			pkgverbose++;
733 			break;
734 
735 		/*
736 		 * Different from pkgadd: process this package using
737 		 * old non-ABI symlinks
738 		 */
739 		case 'y':
740 			set_nonABI_symlinks();
741 			break;
742 
743 		/*
744 		 * Same as pkgadd: perform fresh install from
745 		 * package save spool area. When set, the package contents
746 		 * are installed from the package spool save area instead
747 		 * of from the package root area, so that the original
748 		 * source packages are not required to install the
749 		 * package. If the -h option is also specified and the
750 		 * package is hollow, then this option is ignored. When -z
751 		 * is specified:
752 		 *  - Editable files are installed from the package instance
753 		 *    save area.
754 		 *  - Volatile files are installed from the package instance
755 		 *    save area.
756 		 *  - Executable and data files are installed from the final
757 		 *    installed location as specified in the pkgmap file.
758 		 *  - Installation scripts are run from the package spool
759 		 *    save area.
760 		 */
761 		case 'z':
762 			saveSpoolInstall++;
763 			break;
764 
765 		/*
766 		 * unrecognized option
767 		 */
768 		default:
769 			usage();
770 			/*NOTREACHED*/
771 			/*
772 			 * Although usage() calls a noreturn function,
773 			 * needed to add return (1);  so that main() would
774 			 * pass compilation checks. The statement below
775 			 * should never be executed.
776 			 */
777 			return (1);
778 		}
779 	}
780 
781 	/*
782 	 * ********************************************************************
783 	 * validate command line options
784 	 * ********************************************************************
785 	 */
786 
787 	/* set "debug echo" flag according to setting of "-O debug" option */
788 
789 	(void) echoDebugSetFlag(debugFlag);
790 	(void) log_set_verbose(debugFlag);
791 
792 	/* output entry debugging information */
793 
794 	if (z_running_in_global_zone()) {
795 		echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
796 	} else {
797 		echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
798 		    z_get_zonename());
799 	}
800 
801 	if (in_continue_mode() && !in_dryrun_mode()) {
802 		progerr(ERR_LIVE_CONTINUE_NOT_SUPPORTED);
803 		usage();
804 		/*NOTREACHED*/
805 	}
806 
807 	/* pkgask requires a response file */
808 
809 	if (askflag && (respfile == NULL)) {
810 		usage();
811 		/*NOTREACHED*/
812 	}
813 
814 	/* if device specified, set appropriate device in pkgdev */
815 
816 	if (device) {
817 		if (pkgdev.mount) {
818 			pkgdev.bdevice = device;
819 		} else {
820 			pkgdev.cdevice = device;
821 		}
822 	}
823 
824 	/* if file system type specified, must have a device to mount */
825 
826 	if (pkgdev.fstyp && !pkgdev.mount) {
827 		progerr(ERR_F_REQUIRES_M);
828 		usage();
829 		/*NOTREACHED*/
830 	}
831 
832 	/* BEGIN DATA GATHERING PHASE */
833 
834 	/*
835 	 * Get the mount table info and store internally.
836 	 */
837 	cont_file_read = B_FALSE;
838 	if (in_continue_mode()) {
839 		int error;
840 		cont_file_read = read_continuation(&error);
841 		if (error == -1) {
842 			quit(99);
843 			/*NOTREACHED*/
844 		}
845 		if (!in_dryrun_mode()) {
846 			live_continue = 1;
847 		}
848 	}
849 	/* Read the mount table if not done in continuation mode */
850 	if (!cont_file_read) {
851 		if (get_mntinfo(map_client, vfstab_file)) {
852 			quit(99);
853 			/*NOTREACHED*/
854 		}
855 	}
856 
857 	/*
858 	 * This function defines the standard /var/... directories used later
859 	 * to construct the paths to the various databases.
860 	 */
861 
862 	set_PKGpaths(get_inst_root());
863 
864 	/*
865 	 * If this is being installed on a client whose /var filesystem is
866 	 * mounted in some odd way, remap the administrative paths to the
867 	 * real filesystem. This could be avoided by simply mounting up the
868 	 * client now; but we aren't yet to the point in the process where
869 	 * modification of the filesystem is permitted.
870 	 */
871 	if (is_an_inst_root()) {
872 		int fsys_value;
873 
874 		fsys_value = fsys(get_PKGLOC());
875 		if (use_srvr_map_n(fsys_value))
876 			set_PKGLOC(server_map(get_PKGLOC(), fsys_value));
877 
878 		fsys_value = fsys(get_PKGADM());
879 		if (use_srvr_map_n(fsys_value))
880 			set_PKGADM(server_map(get_PKGADM(), fsys_value));
881 	}
882 
883 	/*
884 	 * Initialize pkginfo PKGSAV entry, just in case we dryrun to
885 	 * somewhere else.
886 	 */
887 	set_infoloc(get_PKGLOC());
888 
889 	/* pull off directory and package name from end of command line */
890 
891 	switch (argc-optind) {
892 	case 0:	/* missing directory and package instance */
893 		progerr(ERR_MISSING_DIR_AND_PKG);
894 		usage();
895 		/*NOTREACHED*/
896 	case 1: /* missing package instance */
897 		progerr(ERR_MISSING_PKG_INSTANCE);
898 		usage();
899 		/*NOTREACHED*/
900 	case 2:	/* just right! */
901 		pkgdev.dirname = argv[optind++];
902 		srcinst = argv[optind++];
903 		break;
904 	default:	/* too many args! */
905 		progerr(ERR_TOO_MANY_CMD_ARGS);
906 		usage();
907 		break;
908 	}
909 
910 	(void) pkgparam(NULL, NULL);  /* close up prior pkg file if needed */
911 
912 	/*
913 	 * Initialize installation admin parameters by reading
914 	 * the adminfile.
915 	 */
916 
917 	if (!askflag && !live_continue) {
918 		echoDebug(DBG_PKGINSTALL_ADMINFILE, admnfile ? admnfile : "");
919 		setadminFile(admnfile);
920 	}
921 
922 	/*
923 	 * about to perform first operation that could be modified by the
924 	 * preinstall check option - if preinstall check is selected (that is,
925 	 * only gathering dependencies), then output a debug message to
926 	 * indicate that the check is beginning. Also turn echo() output
927 	 * off and set various other flags.
928 	 */
929 
930 	if (preinstallCheck == B_TRUE) {
931 		(void) echoSetFlag(B_FALSE);
932 		echoDebug(DBG_PKGINSTALL_PREINSCHK,
933 			pkginst ? pkginst : (srcinst ? srcinst : ""),
934 			zoneName ? zoneName : "global");
935 		cksetPreinstallCheck(B_TRUE);
936 		cksetZoneName(zoneName);
937 		/* inform quit that the install has started */
938 		quitSetInstallStarted(B_TRUE);
939 	}
940 
941 	/*
942 	 * validate the "rscriptalt" admin file setting
943 	 * The rscriptalt admin file parameter may be set to either
944 	 * RSCRIPTALT_ROOT or RSCRIPTALT_NOACCESS:
945 	 * --> If rscriptalt is not set, or is set to RSCRIPTALT_NOACCESS,
946 	 * --> or is set to any value OTHER than RSCRIPTALT_ROOT, then
947 	 * --> assume that the parameter is set to RSCRIPTALT_NOACCESS
948 	 * If rscriptalt is set to RSCRIPTALT_ROOT, then run request scripts
949 	 * as the "root" user if user "install" is not defined.
950 	 * Otherwise, assume rscriptalt is set to RSCRIPTALT_NOACCESS, and run
951 	 * request scripts as the "alternative" user if user "install" is not
952 	 * defined, as appropriate for the current setting of the NONABI_SCRIPTS
953 	 * environment variable.
954 	 */
955 
956 	if (ADMSET(RSCRIPTALT)) {
957 		p = adm.RSCRIPTALT;
958 		echoDebug(DBG_PKGINSTALL_RSCRIPT_SET_TO, RSCRIPTALT_KEYWORD, p);
959 		if (strcasecmp(p, RSCRIPTALT_ROOT) == 0) {
960 			/* rscriptalt=root */
961 			run_request_as_root = B_TRUE;
962 		} else if (strcasecmp(p, RSCRIPTALT_NOACCESS) == 0) {
963 			/* rscriptalt=noaccess */
964 			run_request_as_root = B_FALSE;
965 		} else {
966 			/* rscriptalt=??? */
967 			logerr(WRN_RSCRIPTALT_BAD, RSCRIPTALT_KEYWORD, p,
968 				RSCRIPTALT_ROOT, RSCRIPTALT_NOACCESS);
969 			logerr(WRN_RSCRIPTALT_USING, RSCRIPTALT_KEYWORD,
970 				RSCRIPTALT_NOACCESS);
971 			run_request_as_root = B_FALSE;
972 		}
973 	} else {
974 		/* rscriptalt not set - assume rscriptalt=noaccess */
975 		echoDebug(DBG_PKGINSTALL_RSCRIPT_NOT_SET, RSCRIPTALT_KEYWORD);
976 		run_request_as_root = B_FALSE;
977 	}
978 
979 	echoDebug(DBG_PKGINSTALL_RSCRIPT_IS_ROOT, run_request_as_root);
980 
981 	/*
982 	 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
983 	 */
984 
985 	/* hold SIGINT/SIGHUP interrupts */
986 
987 	(void) sighold(SIGHUP);
988 	(void) sighold(SIGINT);
989 
990 	/* connect quit.c:trap() to SIGINT */
991 
992 	nact.sa_handler = quitGetTrapHandler();
993 	nact.sa_flags = SA_RESTART;
994 	(void) sigemptyset(&nact.sa_mask);
995 
996 	(void) sigaction(SIGINT, &nact, &oact);
997 
998 	/* connect quit.c:trap() to SIGHUP */
999 
1000 	nact.sa_handler = quitGetTrapHandler();
1001 	nact.sa_flags = SA_RESTART;
1002 	(void) sigemptyset(&nact.sa_mask);
1003 
1004 	(void) sigaction(SIGHUP, &nact, &oact);
1005 
1006 	/* release hold on signals */
1007 
1008 	(void) sigrelse(SIGHUP);
1009 	(void) sigrelse(SIGINT);
1010 
1011 	/*
1012 	 * create required /var... directories if they do not exist;
1013 	 * this function will call quit(99) if any required path cannot
1014 	 * be created.
1015 	 */
1016 
1017 	ckdirs();
1018 
1019 	tzset();
1020 
1021 	/*
1022 	 * create path to temporary directory "installXXXXXX" - if TMPDIR
1023 	 * environment variable is set, create the directory in $TMPDIR;
1024 	 * otherwise, create the directory in P_tmpdir.
1025 	 */
1026 
1027 	pt = getenv("TMPDIR");
1028 	(void) snprintf(tmpdir, sizeof (tmpdir), "%s/installXXXXXX",
1029 		((pt != (char *)NULL) && (*pt != '\0')) ? pt : P_tmpdir);
1030 
1031 	echoDebug(DBG_PKGINSTALL_TMPDIR, tmpdir);
1032 
1033 	if ((mktemp(tmpdir) == NULL) || mkdir(tmpdir, 0771)) {
1034 		progerr(ERR_MKDIR, tmpdir);
1035 		quit(99);
1036 		/*NOTREACHED*/
1037 	}
1038 
1039 	/*
1040 	 * if the package device is a file containing a package stream,
1041 	 * unpack the stream into a temporary directory
1042 	 */
1043 
1044 	if ((isdir(pkgdev.dirname) != 0) &&
1045 		(pkgdev.cdevice == (char *)NULL) &&
1046 		(pkgdev.bdevice == (char *)NULL) &&
1047 		(isfile((char *)NULL, pkgdev.dirname) == 0)) {
1048 
1049 		char		*idsName = (char *)NULL;
1050 		char		*pkgnames[2];
1051 		char		*device = pkgdev.dirname;
1052 		boolean_t	b;
1053 
1054 		echoDebug(DBG_PKGINSTALL_DS_ISFILE, pkgdev.dirname);
1055 
1056 		/*
1057 		 * validate the package source device - return pkgdev info that
1058 		 * describes the package source device.
1059 		 */
1060 
1061 		if (devtype(device, &pkgdev)) {
1062 			progerr(ERR_BAD_DEVICE, device);
1063 			quit(99);
1064 			/* NOTREACHED */
1065 		}
1066 
1067 		/* generate the list of packages to verify */
1068 
1069 		pkgnames[0] = srcinst;
1070 		pkgnames[1] = (char *)NULL;
1071 
1072 		b = open_package_datastream(1, pkgnames, (char *)NULL,
1073 			pkgdev.dirname, (int *)NULL, &idsName, tmpdir, &pkgdev,
1074 			1);
1075 
1076 		if (b == B_FALSE) {
1077 			progerr(ERR_CANNOT_OPEN_PKG_STREAM,
1078 				pkgdev.dirname ? pkgdev.dirname : "?");
1079 			quit(99);
1080 			/*NOTREACHED*/
1081 		}
1082 
1083 		/* make sure temporary directory is removed on exit */
1084 
1085 		quitSetDstreamTmpdir(pkgdev.dirname);
1086 
1087 		/* unpack the package instance from the data stream */
1088 
1089 		b = unpack_package_from_stream(idsName, srcinst,
1090 							pkgdev.dirname);
1091 		if (b == B_FALSE) {
1092 			progerr(ERR_CANNOT_UNPACK_PKGSTRM,
1093 				srcinst ? srcinst : "?",
1094 				idsName ? idsName : "?",
1095 				pkgdev.dirname ? pkgdev.dirname : "?");
1096 			quit(99);
1097 			/*NOTREACHED*/
1098 		}
1099 
1100 		/* close the datastream - no longer needed */
1101 
1102 		echoDebug(DBG_CLOSING_STREAM, idsName, pkgdev.dirname);
1103 		(void) ds_close(1);
1104 	}
1105 
1106 	if (snprintf(instdir, PATH_MAX, "%s/%s", pkgdev.dirname, srcinst)
1107 	    >= PATH_MAX) {
1108 		progerr(ERR_SNPRINTF, instdir);
1109 		quit(99);
1110 		/*NOTREACHED*/
1111 	}
1112 
1113 	zoneName = getenv(PKG_ZONENAME_VARIABLE);
1114 
1115 	/*
1116 	 * If the environment has a CLIENT_BASEDIR, that takes precedence
1117 	 * over anything we will construct. We need to save it here because
1118 	 * in three lines, the current environment goes away.
1119 	 */
1120 	(void) set_env_cbdir();	/* copy over environ */
1121 
1122 	getuserlocale();
1123 
1124 	/*
1125 	 * current environment has been read; clear environment out
1126 	 * so putparam() can be used to populate the new environment
1127 	 * to be passed to any executables/scripts.
1128 	 */
1129 
1130 	environ = NULL;
1131 
1132 	/* write parent condition information to environment */
1133 
1134 	putConditionInfo(parentZoneName, parentZoneType);
1135 
1136 	putuserlocale();
1137 
1138 	if (init_install) {
1139 		putparam("PKG_INIT_INSTALL", "TRUE");
1140 	}
1141 
1142 	if (is_an_inst_root()) {
1143 		export_client_env(get_inst_root());
1144 	}
1145 
1146 	if (zoneName != (char *)NULL) {
1147 		putparam(PKG_ZONENAME_VARIABLE, zoneName);
1148 	}
1149 
1150 	putparam("INST_DATADIR", pkgdev.dirname);
1151 
1152 	if (non_abi_scripts) {
1153 		putparam("NONABI_SCRIPTS", "TRUE");
1154 	}
1155 
1156 	if (nonABI_symlinks()) {
1157 		putparam("PKG_NONABI_SYMLINKS", "TRUE");
1158 	}
1159 
1160 	if (get_ABI_namelngth()) {
1161 		putparam("PKG_ABI_NAMELENGTH", "TRUE");
1162 	}
1163 
1164 	/* establish path and oambase */
1165 
1166 	if (cmdbin[0] == '\0') {
1167 		(void) strlcpy(cmdbin, PKGBIN, sizeof (cmdbin));
1168 	}
1169 
1170 	(void) snprintf(path, sizeof (path), "%s:%s", DEFPATH, cmdbin);
1171 
1172 	putparam("PATH", path);
1173 
1174 	putparam("OAMBASE", OAMBASE);
1175 
1176 	(void) snprintf(p_pkginfo, sizeof (p_pkginfo),
1177 			"%s/%s", instdir, PKGINFO);
1178 	(void) snprintf(p_pkgmap, sizeof (p_pkgmap),
1179 			"%s/%s", instdir, PKGMAP);
1180 
1181 	/* Read the environment (from pkginfo or '-e') ... */
1182 	abi_nm_ptr = getenv("PKG_ABI_NAMELENGTH");
1183 
1184 	/* Disable the 32 char name limit extension */
1185 	if (abi_nm_ptr && strncasecmp(abi_nm_ptr, "TRUE", 4) == 0) {
1186 		(void) set_ABI_namelngth();
1187 	}
1188 
1189 	/*
1190 	 * This tests the pkginfo and pkgmap files for validity and
1191 	 * puts all delivered pkginfo variables (except for PATH) into
1192 	 * our environment. This is where a delivered pkginfo BASEDIR
1193 	 * would come from. See set_basedirs() below.
1194 	 */
1195 
1196 	if (pkgenv(srcinst, p_pkginfo, p_pkgmap)) {
1197 		quit(1);
1198 		/*NOTREACHED*/
1199 	}
1200 
1201 	echo("\n%s(%s) %s", pkgname, pkgarch, pkgvers);
1202 
1203 	/*
1204 	 * If this script was invoked by 'pkgask', just
1205 	 * execute request script and quit (do_pkgask()).
1206 	 */
1207 
1208 	if (askflag) {
1209 		do_pkgask(run_request_as_root);
1210 	}
1211 
1212 	/* validate package contents file */
1213 
1214 	if (vcfile() == 0) {
1215 		quit(99);
1216 	}
1217 
1218 	/* if not in dryrun mode aquire packaging lock */
1219 
1220 	if (!in_dryrun_mode()) {
1221 		/* acquire the package lock - at install initialization */
1222 		if (!lockinst(get_prog_name(), srcinst, "install-initial")) {
1223 			quit(99);
1224 			/*NOTREACHED*/
1225 		}
1226 	}
1227 
1228 	/*
1229 	 * Now do all the various setups based on ABI compliance
1230 	 */
1231 
1232 	/* Read the environment (from pkginfo or '-o') ... */
1233 	abi_comp_ptr = getenv("NONABI_SCRIPTS");
1234 
1235 	/* Read the environment (from pkginfo or '-y') ... */
1236 	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
1237 
1238 	/* bug id 4244631, not ABI compliant */
1239 	if (abi_comp_ptr && strncasecmp(abi_comp_ptr, "TRUE", 4) == 0) {
1240 		script_in = PROC_XSTDIN;
1241 		non_abi_scripts = 1;
1242 	}
1243 
1244 	/* Set symlinks to be processed the old way */
1245 	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
1246 		set_nonABI_symlinks();
1247 	}
1248 
1249 	/*
1250 	 * At this point, script_in, non_abi_scripts & the environment are
1251 	 * all set correctly for the ABI status of the package.
1252 	 */
1253 
1254 	if (pt = getenv("MAXINST")) {
1255 		maxinst = atol(pt);
1256 	}
1257 
1258 	/*
1259 	 * See if were are installing a package that only wants to update
1260 	 * the database or only install files associated with CAS's. We
1261 	 * only check the PKG_HOLLOW_VARIABLE variable if told to do so by
1262 	 * the caller.
1263 	 */
1264 
1265 	if (is_depend_pkginfo_DB()) {
1266 		pt = getenv(PKG_HOLLOW_VARIABLE);
1267 		if ((pt != NULL) && (strncasecmp(pt, "true", 4) == 0)) {
1268 			echoDebug(DBG_PKGREMOVE_HOLLOW_ENABLED);
1269 			if (disableAttributes) {
1270 				disable_attribute_check();
1271 			}
1272 
1273 			/*
1274 			 * this is a hollow package and hollow package support
1275 			 * is enabled -- override admin settings to suppress
1276 			 * checks that do not make sense since no scripts will
1277 			 * be executed and no files will be installed.
1278 			 */
1279 
1280 			setadminSetting("conflict", "nocheck");
1281 			setadminSetting("setuid", "nocheck");
1282 			setadminSetting("action", "nocheck");
1283 			setadminSetting("partial", "nocheck");
1284 			setadminSetting("space", "nocheck");
1285 			setadminSetting("authentication", "nocheck");
1286 		} else {
1287 			echoDebug(DBG_PKGREMOVE_HOLLOW_DISABLED);
1288 			set_depend_pkginfo_DB(B_FALSE);
1289 		}
1290 	}
1291 
1292 	/*
1293 	 * if performing a fresh install to a non-global zone, and doing
1294 	 * more than just updating the package database (that is, the
1295 	 * package to install is NOT "hollow"), then set the global flag
1296 	 * that directs installation is from partially spooled packages
1297 	 * (that is, packages installed in the global zone).
1298 	 */
1299 
1300 	if (saveSpoolInstall && (!is_depend_pkginfo_DB())) {
1301 		set_partial_inst();
1302 	} else {
1303 		saveSpoolInstall = 0;
1304 	}
1305 
1306 	/*
1307 	 * verify that we are not trying to install an
1308 	 * INTONLY package with no interaction
1309 	 */
1310 
1311 	if (pt = getenv("INTONLY")) {
1312 		if (askflag || nointeract) {
1313 			progerr(ERR_INTONLY, pkgabrv ? pkgabrv : "?");
1314 			quit(1);
1315 			/*NOTREACHED*/
1316 		}
1317 	}
1318 
1319 	if (!suppressCopyright && !pkgdev.cdevice) {
1320 		copyright();
1321 	}
1322 
1323 	/*
1324 	 * inspect the system to determine if any instances of the
1325 	 * package being installed already exist on the system
1326 	 */
1327 
1328 	prvinfo = (struct pkginfo *)calloc(MALSIZ, sizeof (struct pkginfo));
1329 	if (prvinfo == NULL) {
1330 		progerr(ERR_MEMORY, errno);
1331 		quit(99);
1332 		/*NOTREACHED*/
1333 	}
1334 
1335 	for (;;) {
1336 		if (pkginfo(&prvinfo[npkgs], pkgwild, NULL, NULL)) {
1337 			if ((errno == ESRCH) || (errno == ENOENT)) {
1338 				break;
1339 			}
1340 			progerr(ERR_SYSINFO, errno);
1341 			quit(99);
1342 			/*NOTREACHED*/
1343 		}
1344 		if ((++npkgs % MALSIZ) == 0) {
1345 			prvinfo = (struct pkginfo *)realloc(prvinfo,
1346 				(npkgs+MALSIZ) * sizeof (struct pkginfo));
1347 			if (prvinfo == NULL) {
1348 				progerr(ERR_MEMORY, errno);
1349 				quit(99);
1350 				/*NOTREACHED*/
1351 			}
1352 		}
1353 	}
1354 
1355 	/*
1356 	 * Determine the correct package instance based on how many packages are
1357 	 * already installed. If there are none (npkgs == 0), getinst() just
1358 	 * returns the package abbreviation. Otherwise, getinst() interacts with
1359 	 * the user (or reads the admin file) to determine if an instance which
1360 	 * is already installed should be overwritten, or possibly install a new
1361 	 * instance of this package
1362 	 */
1363 
1364 	pkginst = getinst(&update, prvinfo, npkgs, preinstallCheck);
1365 
1366 	/* set "update flag" if updating an existing instance of this package */
1367 
1368 	if (update) {
1369 		setUpdate();
1370 	}
1371 
1372 	/*
1373 	 * Some pkgs (SUNWcsr) already spooled to the zone, check the
1374 	 * value of UPDATE in their postinstall script.  After a pkg
1375 	 * has been patched UPDATE exists statically in the pkginfo
1376 	 * file and this value must be reset when installing a zone.
1377 	 */
1378 
1379 	if (saveSpoolInstall != 0 && !isUpdate()) {
1380 		putparam("UPDATE", "");
1381 	}
1382 
1383 	/* inform quit() if updating existing or installing new instance */
1384 
1385 	quitSetUpdatingExisting(update ? B_TRUE : B_FALSE);
1386 
1387 	if (respfile) {
1388 		(void) set_respfile(respfile, pkginst, RESP_RO);
1389 	}
1390 
1391 	(void) snprintf(pkgloc, sizeof (pkgloc),
1392 			"%s/%s", get_PKGLOC(), pkginst);
1393 
1394 	(void) snprintf(pkgbin, sizeof (pkgbin),
1395 			"%s/install", pkgloc);
1396 
1397 	(void) snprintf(pkgsav, sizeof (pkgsav),
1398 			"%s/save", pkgloc);
1399 
1400 	if (snprintf(saveSpoolInstallDir, PATH_MAX, "%s/pspool/%s", pkgsav,
1401 			pkginst) < 0) {
1402 		progerr(ERR_SNPRINTF, saveSpoolInstallDir);
1403 		quit(99);
1404 		/*NOTREACHED*/
1405 	}
1406 
1407 	(void) snprintf(ilockfile, sizeof (ilockfile),
1408 			"%s/!I-Lock!", pkgloc);
1409 	(void) snprintf(rlockfile, sizeof (rlockfile),
1410 			"%s/!R-Lock!", pkgloc);
1411 	(void) snprintf(savlog, sizeof (savlog),
1412 			"%s/logs/%s", get_PKGADM(), pkginst);
1413 
1414 	putparam("PKGINST", pkginst);
1415 	putparam("PKGSAV", pkgsav);
1416 
1417 	/*
1418 	 * Be sure request script has access to PKG_INSTALL_ROOT if there is
1419 	 * one
1420 	 */
1421 
1422 	put_path_params();
1423 
1424 	if (!map_client) {
1425 		putparam("PKG_NO_UNIFIED", "TRUE");
1426 	}
1427 
1428 	/*
1429 	 * This maps the client filesystems into the server's space.
1430 	 */
1431 
1432 	if (map_client && !mount_client()) {
1433 		logerr(MSG_MANMOUNT);
1434 	}
1435 
1436 	/*
1437 	 * If this is an UPDATE then either this is exactly the same version
1438 	 * and architecture of an installed package or a different package is
1439 	 * intended to entirely replace an installed package of the same name
1440 	 * with a different VERSION or ARCH string.
1441 	 * Don't merge any databases if only gathering dependencies.
1442 	 */
1443 
1444 	if ((preinstallCheck == B_FALSE) && (update)) {
1445 		/*
1446 		 * If this version and architecture is already installed,
1447 		 * merge the installed and installing parameters and inform
1448 		 * all procedure scripts by defining UPDATE in the
1449 		 * environment.
1450 		 */
1451 
1452 		if (is_samepkg()) {
1453 			/*
1454 			 * If it's the same ARCH and VERSION, then a merge
1455 			 * and copy operation is necessary.
1456 			 */
1457 
1458 			if (n = merg_pkginfos(pclass, &mergd_pclass)) {
1459 				quit(n);
1460 				/*NOTREACHED*/
1461 			}
1462 
1463 			if (n = cp_pkgdirs()) {
1464 				quit(n);
1465 				/*NOTREACHED*/
1466 			}
1467 
1468 		} else {
1469 			/*
1470 			 * If it's a different ARCH and/or VERSION then this
1471 			 * is an "instance=overwrite" situation. The
1472 			 * installed base needs to be confirmed and the
1473 			 * package directories renamed.
1474 			 */
1475 
1476 			if (n = ck_instbase()) {
1477 				quit(n);
1478 				/*NOTREACHED*/
1479 			}
1480 
1481 			if (n = mv_pkgdirs()) {
1482 				quit(n);
1483 				/*NOTREACHED*/
1484 			}
1485 		}
1486 
1487 		putparam("UPDATE", "yes");
1488 
1489 	}
1490 
1491 	if (in_dryrun_mode()) {
1492 		set_dryrun_dir_loc();
1493 	}
1494 
1495 	if (preinstallCheck == B_FALSE) {
1496 		/*
1497 		 * Determine if the package has been partially installed on or
1498 		 * removed from this system.
1499 		 */
1500 		ck_w_dryrun(ckpartial, PARTIAL);
1501 
1502 		/*
1503 		 * make sure current runlevel is appropriate
1504 		 */
1505 		ck_w_dryrun(ckrunlevel, RUNLEVEL);
1506 	} else {
1507 		int	r;
1508 
1509 		/*
1510 		 * Just gathering dependencies - determine if the package has
1511 		 * been partially installed on or removed from this system and
1512 		 * output information to stdout
1513 		 */
1514 		r = ckpartial();
1515 		(void) fprintf(stdout, "ckpartialinstall=%d\n", r == 8 ? 1 : 0);
1516 		(void) fprintf(stdout, "ckpartialremove=%d\n", r == 9 ? 1 : 0);
1517 
1518 		/*
1519 		 * make sure current runlevel is appropriate
1520 		 */
1521 		r = ckrunlevel();
1522 		(void) fprintf(stdout, "ckrunlevel=%d\n", r);
1523 	}
1524 
1525 	if (pkgdev.cdevice) {
1526 		/* get first volume which contains info files */
1527 		unpack();
1528 		if (!suppressCopyright) {
1529 			copyright();
1530 		}
1531 	}
1532 
1533 	/* update the lock - at the request script */
1534 
1535 	lockupd("request");
1536 
1537 	/*
1538 	 * If no response file has been provided, initialize response file by
1539 	 * executing any request script provided by this package. Initialize
1540 	 * the response file if not gathering dependencies only.
1541 	 */
1542 
1543 	if ((!rdonly_respfile()) && (preinstallCheck == B_FALSE)) {
1544 		(void) snprintf(path, sizeof (path),
1545 			"%s/%s", instdir, REQUEST_FILE);
1546 		n = reqexec(update, path, non_abi_scripts,
1547 			run_request_as_root);
1548 		if (in_dryrun_mode()) {
1549 			set_dr_info(REQUESTEXITCODE, n);
1550 		}
1551 
1552 		ckreturn(n, ERR_REQUEST);
1553 	}
1554 
1555 	/*
1556 	 * Look for all parameters in response file which begin with a
1557 	 * capital letter, and place them in the environment.
1558 	 */
1559 
1560 	if ((is_a_respfile()) && (preinstallCheck == B_FALSE)) {
1561 		if (n = merg_respfile()) {
1562 			quit(n);
1563 			/*NOTREACHED*/
1564 		}
1565 	}
1566 
1567 	/*
1568 	 * Run a checkinstall script if one is provided by the package.
1569 	 * Don't execute checkinstall script if we are only updating the DB.
1570 	 * Don't execute checkinstall script if only gathering dependencies.
1571 	 */
1572 
1573 	/* update the lock - at the checkinstall script */
1574 	lockupd("checkinstall");
1575 
1576 	/* Execute checkinstall script if one is provided. */
1577 	(void) snprintf(script, sizeof (script), "%s/install/checkinstall",
1578 			instdir);
1579 	if (access(script, F_OK) != 0) {
1580 		/* no script present */
1581 		echoDebug(DBG_PKGINSTALL_COC_NONE, pkginst, script,
1582 			zoneName ? zoneName : "global");
1583 	} else if (is_depend_pkginfo_DB()) {
1584 		/* updating db only: skip checkinstall script */
1585 		echoDebug(DBG_PKGINSTALL_COC_DBUPD, pkginst, script,
1586 			zoneName ? zoneName : "global");
1587 	} else if (preinstallCheck == B_TRUE) {
1588 		/* only gathering dependencies: skip checkinstall script */
1589 		echoDebug(DBG_PKGINSTALL_COC_NODEL, pkginst, script,
1590 			zoneName ? zoneName : "global");
1591 	} else {
1592 		/* script present and ok to run: run the script */
1593 		if (zoneName == (char *)NULL) {
1594 			echo(MSG_PKGINSTALL_EXECOC_GZ);
1595 			echoDebug(DBG_PKGINSTALL_EXECOC_GZ, pkginst, script);
1596 		} else {
1597 			echo(MSG_PKGINSTALL_EXECOC_LZ, zoneName);
1598 			echoDebug(DBG_PKGINSTALL_EXECOC_LZ, pkginst, script,
1599 				zoneName);
1600 		}
1601 		n = chkexec(update, script);
1602 		if (in_dryrun_mode()) {
1603 			set_dr_info(CHECKEXITCODE, n);
1604 		}
1605 
1606 		if (n == 3) {
1607 			echo(WRN_CHKINSTALL);
1608 			ckreturn(4, NULL);
1609 		} else if (n == 7) {
1610 			/* access returned error */
1611 			progerr(ERR_CHKINSTALL_NOSCRIPT, script);
1612 			ckreturn(4, ERR_CHKINSTALL);
1613 		} else {
1614 			ckreturn(n, ERR_CHKINSTALL);
1615 		}
1616 	}
1617 
1618 	/*
1619 	 * Now that the internal data structures are initialized, we can
1620 	 * initialize the dryrun files (which may be the same files).
1621 	 */
1622 
1623 	if (pkgdrtarg) {
1624 		init_dryrunfile(pkgdrtarg);
1625 	}
1626 
1627 	/*
1628 	 * Look for all parameters in response file which begin with a
1629 	 * capital letter, and place them in the environment.
1630 	 */
1631 	if (is_a_respfile()) {
1632 		if (n = merg_respfile()) {
1633 			quit(n);
1634 			/*NOTREACHED*/
1635 		}
1636 	}
1637 
1638 	/* update the lock - doing analysis */
1639 
1640 	lockupd("analysis");
1641 
1642 	/*
1643 	 * Determine package base directory and client base directory
1644 	 * if appropriate. Then encapsulate them for future retrieval.
1645 	 */
1646 	if ((err = set_basedirs(isreloc(instdir), adm.basedir, pkginst,
1647 		nointeract)) != 0) {
1648 		quit(err);
1649 		/*NOTREACHED*/
1650 	}
1651 
1652 	/*
1653 	 * Create the base directory if specified.
1654 	 * Don't create if we are only updating the DB.
1655 	 * Don't create if only gathering dependencies.
1656 	 */
1657 
1658 	if (!is_depend_pkginfo_DB() &&
1659 		!preinstallCheck && is_a_basedir()) {
1660 		mkbasedir(!nointeract, get_basedir());
1661 		echo(MSG_BASE_USED, get_basedir());
1662 	}
1663 
1664 	/*
1665 	 * Store PKG_INSTALL_ROOT, BASEDIR & CLIENT_BASEDIR in our
1666 	 * environment for later use by procedure scripts.
1667 	 */
1668 	put_path_params();
1669 
1670 	/*
1671 	 * the following two checks are done in the corresponding
1672 	 * ck() routine, but are repeated here to avoid re-processing
1673 	 * the database if we are administered to not include these
1674 	 * processes
1675 	 */
1676 	if (ADM(setuid, "nochange")) {
1677 		nosetuid++;	/* Clear setuid/gid bits. */
1678 	}
1679 
1680 	if (ADM(conflict, "nochange")) {
1681 		nocnflct++;	/* Don't install conflicting files. */
1682 	}
1683 
1684 	/*
1685 	 * Get the filesystem space information for the filesystem on which
1686 	 * the "contents" file resides.
1687 	 */
1688 
1689 	svfsb.f_bsize = 8192;
1690 	svfsb.f_frsize = 1024;
1691 
1692 	if (statvfs64(get_PKGADM(), &svfsb) == -1) {
1693 		int	lerrno = errno;
1694 		if (!access(get_PKGADM(), F_OK)) {
1695 			progerr(ERR_PKGINSTALL_STATVFS, get_PKGADM(),
1696 				strerror(errno));
1697 			logerr("(errno %d)", lerrno);
1698 			quit(99);
1699 			/*NOTREACHED*/
1700 		}
1701 	}
1702 
1703 	/*
1704 	 * Get the number of blocks used by the pkgmap, ocfile()
1705 	 * needs this to properly determine its space requirements.
1706 	 */
1707 
1708 	if (stat(p_pkgmap, &statb) == -1) {
1709 		progerr(ERR_PKGINSTALL_STATOF, p_pkgmap, strerror(errno));
1710 		quit(99);
1711 		/*NOTREACHED*/
1712 	}
1713 
1714 	pkgmap_blks = nblk(statb.st_size, svfsb.f_bsize, svfsb.f_frsize);
1715 
1716 	/*
1717 	 * Merge information in memory with the "contents" file; this creates
1718 	 * a temporary version of the "contents" file. Note that in dryrun
1719 	 * mode, we still need to record the contents file data somewhere,
1720 	 * but we do it in the dryrun directory.
1721 	 */
1722 
1723 	if (in_dryrun_mode()) {
1724 		if (n = set_cfdir(pkgdrtarg)) {
1725 			quit(n);
1726 			/*NOTREACHED*/
1727 		}
1728 	} else {
1729 		if (n = set_cfdir(NULL)) {
1730 			quit(n);
1731 			/*NOTREACHED*/
1732 		}
1733 	}
1734 	if (!ocfile(&pkgserver, &cfTmpVfp, pkgmap_blks)) {
1735 		quit(99);
1736 		/*NOTREACHED*/
1737 	}
1738 
1739 	/*
1740 	 * if cpio is being used,  tell pkgdbmerg since attributes will
1741 	 * have to be check and repaired on all file and directories
1742 	 */
1743 	for (np = cpio_names; *np != NULL; np++) {
1744 		(void) snprintf(path, sizeof (path),
1745 			"%s/%s", instdir, *np);
1746 		if (iscpio(path, &is_comp_arch)) {
1747 			is_WOS_arch();
1748 			break;
1749 		}
1750 	}
1751 
1752 	/* Establish the class list and the class attributes. */
1753 	cl_sets(getenv("CLASSES"));
1754 	find_CAS(I_ONLY, pkgbin, instdir);
1755 
1756 	if (vfpOpen(&pkgmapVfp, p_pkgmap, "r", VFP_NEEDNOW) != 0) {
1757 		progerr(ERR_PKGMAP, p_pkgmap);
1758 		quit(99);
1759 		/*NOTREACHED*/
1760 	}
1761 
1762 	/*
1763 	 * This modifies the path list entries in memory to reflect
1764 	 * how they should look after the merg is complete
1765 	 */
1766 
1767 	nparts = sortmap(&extlist, pkgmapVfp, pkgserver, cfTmpVfp, zoneName);
1768 
1769 	if ((n = files_installed()) > 0) {
1770 		if (n > 1) {
1771 			echo(MSG_INST_MANY, n);
1772 		} else {
1773 			echo(MSG_INST_ONE, n);
1774 		}
1775 	}
1776 
1777 	/*
1778 	 * Check ulimit requirement (provided in pkginfo). The purpose of
1779 	 * this limit is to terminate pathological file growth resulting from
1780 	 * file edits in scripts. It does not apply to files in the pkgmap
1781 	 * and it does not apply to any database files manipulated by the
1782 	 * installation service.
1783 	 */
1784 	if (pt = getenv("ULIMIT")) {
1785 		if (assign_ulimit(pt) == -1) {
1786 			progerr(ERR_BADULIMIT, pt);
1787 			quit(99);
1788 			/*NOTREACHED*/
1789 		}
1790 		putparam("PKG_ULIMIT", "TRUE");
1791 	}
1792 
1793 	/*
1794 	 * If only gathering dependencies, check and output status of all
1795 	 * remaining dependencies and exit.
1796 	 */
1797 
1798 	if (preinstallCheck == B_TRUE) {
1799 		/* update the lock file - final checking */
1800 
1801 		lockupd("preinstallcheck");
1802 
1803 		/* verify package information files are not corrupt */
1804 
1805 		(void) fprintf(stdout, "ckpkgfiles=%d\n", ckpkgfiles());
1806 
1807 		/* verify package dependencies */
1808 
1809 		(void) fprintf(stdout, "ckdepend=%d\n", ckdepend());
1810 
1811 		/* Check space requirements */
1812 
1813 		(void) fprintf(stdout, "ckspace=%d\n", ckspace());
1814 
1815 		/*
1816 		 * Determine if any objects provided by this package conflict
1817 		 * with the files of previously installed packages.
1818 		 */
1819 
1820 		(void) fprintf(stdout, "ckconflict=%d\n", ckconflct());
1821 
1822 		/*
1823 		 * Determine if any objects provided by this package will be
1824 		 * installed with setuid or setgid enabled.
1825 		 */
1826 
1827 		(void) fprintf(stdout, "cksetuid=%d\n", cksetuid());
1828 
1829 		/*
1830 		 * Determine if any packaging scripts provided with this package
1831 		 * will execute as a priviledged user.
1832 		 */
1833 
1834 		(void) fprintf(stdout, "ckpriv=%d\n", ckpriv());
1835 
1836 		/* Verify neccessary package installation directories exist */
1837 
1838 		(void) fprintf(stdout, "ckpkgdirs=%d\n", ckpkgdirs());
1839 
1840 		/*
1841 		 * ****** preinstall check done - exit ******
1842 		 */
1843 
1844 		echoDebug(DBG_PKGINSTALL_PREINSCHK_OK);
1845 		quit(0);
1846 		/*NOTREACHED*/
1847 	}
1848 
1849 	/*
1850 	 * Not gathering dependencies only, proceed to check dependencies
1851 	 * and continue with the package installation operation.
1852 	 */
1853 
1854 	/*
1855 	 * verify package information files are not corrupt
1856 	 */
1857 	ck_w_dryrun(ckpkgfiles, PKGFILES);
1858 
1859 	/*
1860 	 * verify package dependencies
1861 	 */
1862 	ck_w_dryrun(ckdepend, DEPEND);
1863 
1864 	/*
1865 	 * Check space requirements.
1866 	 */
1867 	ck_w_dryrun(ckspace, SPACE);
1868 
1869 	/*
1870 	 * Determine if any objects provided by this package conflict with
1871 	 * the files of previously installed packages.
1872 	 */
1873 	ck_w_dryrun(ckconflct, CONFLICT);
1874 
1875 	/*
1876 	 * Determine if any objects provided by this package will be
1877 	 * installed with setuid or setgid enabled.
1878 	 */
1879 	ck_w_dryrun(cksetuid, SETUID);
1880 
1881 	/*
1882 	 * Determine if any packaging scripts provided with this package will
1883 	 * execute as a priviledged user.
1884 	 */
1885 	ck_w_dryrun(ckpriv, PRIV);
1886 
1887 	/*
1888 	 * Verify neccessary package installation directories exist.
1889 	 */
1890 	ck_w_dryrun(ckpkgdirs, PKGDIRS);
1891 
1892 	/*
1893 	 * If we have assumed that we were installing setuid or conflicting
1894 	 * files, and the user chose to do otherwise, we need to read in the
1895 	 * package map again and re-merg with the "contents" file
1896 	 */
1897 
1898 	if (rprcflag) {
1899 		nparts = sortmap(&extlist, pkgmapVfp, pkgserver,
1900 				cfTmpVfp, zoneName);
1901 	}
1902 
1903 	(void) vfpClose(&pkgmapVfp);
1904 
1905 	/* BEGIN INSTALLATION PHASE */
1906 	if (in_dryrun_mode()) {
1907 		echo(MSG_PKGINSTALL_DRYRUN, pkgname, pkginst);
1908 	} else if (zoneName == (char *)NULL) {
1909 		echo(MSG_PKGINSTALL_INSIN_GZ, pkgname, pkginst);
1910 	} else {
1911 		echo(MSG_PKGINSTALL_INSIN_LZ, pkgname, pkginst, zoneName);
1912 	}
1913 
1914 	/* inform quit that the install has started */
1915 
1916 	quitSetInstallStarted(B_TRUE);
1917 
1918 	/*
1919 	 * This replaces the contents file with recently created temp version
1920 	 * which contains information about the objects being installed.
1921 	 * Under old lock protocol it closes both files and releases the
1922 	 * locks. Beginning in Solaris 2.7, this lock method should be
1923 	 * reviewed.
1924 	 */
1925 
1926 	n = swapcfile(pkgserver, &cfTmpVfp, pkginst, dbchg);
1927 	if (n == RESULT_WRN) {
1928 		warnflag++;
1929 	} else if (n == RESULT_ERR) {
1930 		quit(99);
1931 		/*NOTREACHED*/
1932 	}
1933 
1934 	/*
1935 	 * Create install-specific lockfile to indicate start of
1936 	 * installation. This is really just an information file. If the
1937 	 * process dies, the initial lockfile (from lockinst(), is
1938 	 * relinquished by the kernel, but this one remains in support of the
1939 	 * post-mortem.
1940 	 */
1941 
1942 	if (access(ilockfile, F_OK) == 0) {
1943 		(void) remove(ilockfile);
1944 	}
1945 
1946 	if (open(ilockfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644) < 0) {
1947 		progerr(ERR_LOCKFILE, ilockfile);
1948 		quit(99);
1949 		/*NOTREACHED*/
1950 	}
1951 
1952 	(void) time(&clock);
1953 
1954 	/*
1955 	 * We do not want the time in locale in the pkginfo.
1956 	 * save the LC_TIME and set it to C. Reset it with saved one
1957 	 * after cftime().
1958 	 */
1959 	temp = setlocale(LC_TIME, NULL);
1960 	(void) setlocale(LC_TIME, "C");
1961 
1962 	/* LINTED warning: do not use cftime(); ... */
1963 	(void) cftime(cbuf, "%b %d \045Y \045H:\045M", &clock);
1964 	putparam("INSTDATE", qstrdup(cbuf));
1965 	(void) setlocale(LC_TIME, temp);
1966 
1967 	/*
1968 	 * Store information about package being installed;
1969 	 * modify installation parameters as neccessary and
1970 	 * copy contents of 'install' directory into $pkgloc
1971 	 */
1972 	merginfo(mergd_pclass, saveSpoolInstall);
1973 
1974 	/* If this was just a dryrun, then quit() will write out that file. */
1975 	if (in_dryrun_mode()) {
1976 		quit(0);
1977 		/*NOTREACHED*/
1978 	}
1979 
1980 	/*
1981 	 * Execute preinstall script, if one was provided with the
1982 	 * package. We check the package to avoid running an old
1983 	 * preinstall script if one was provided with a prior instance.
1984 	 * Don't execute preinstall script if we are only updating the DB.
1985 	 */
1986 
1987 	/* update the lock - at the preinstall altscript */
1988 	lockupd("preinstall");
1989 
1990 	/* preinstall script in the media (package source) */
1991 	(void) snprintf(altscript, sizeof (altscript), "%s/install/preinstall",
1992 			instdir);
1993 
1994 	/* preinstall script in the pkgbin instead of media */
1995 	(void) snprintf(script, sizeof (script), "%s/preinstall", pkgbin);
1996 
1997 	if (access(altscript, F_OK) != 0) {
1998 		/* no script present */
1999 		echoDebug(DBG_PKGINSTALL_POCALT_NONE, pkginst, altscript,
2000 			zoneName ? zoneName : "global");
2001 	} else if (access(script, F_OK) != 0) {
2002 		/* no script present */
2003 		echoDebug(DBG_PKGINSTALL_POC_NONE, pkginst, script,
2004 			zoneName ? zoneName : "global");
2005 	} else if (is_depend_pkginfo_DB()) {
2006 		/* updating db only: skip preinstall script */
2007 		echoDebug(DBG_PKGINSTALL_POC_DBUPD, pkginst, script,
2008 			zoneName ? zoneName : "global");
2009 	} else {
2010 		/* script present and ok to run: run the script */
2011 		assert(preinstallCheck == B_FALSE);
2012 
2013 		set_ulimit("preinstall", ERR_PREINSTALL);
2014 		if (zoneName == (char *)NULL) {
2015 			echo(MSG_PKGINSTALL_EXEPOC_GZ);
2016 			echoDebug(DBG_PKGINSTALL_EXEPOC_GZ, pkginst, script);
2017 		} else {
2018 			echo(MSG_PKGINSTALL_EXEPOC_LZ, zoneName);
2019 			echoDebug(DBG_PKGINSTALL_EXEPOC_LZ, pkginst, script,
2020 				zoneName);
2021 		}
2022 		putparam("PKG_PROC_script", "preinstall");
2023 		if (pkgverbose) {
2024 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
2025 				PROC_USER, PROC_GRP, SHELL, "-x",
2026 				script, NULL), ERR_PREINSTALL);
2027 		} else {
2028 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
2029 				PROC_USER, PROC_GRP, SHELL, script,
2030 				NULL), ERR_PREINSTALL);
2031 		}
2032 
2033 		clr_ulimit();
2034 		(void) remove(script);	/* no longer needed. */
2035 	}
2036 
2037 	/*
2038 	 * Check delivered package for a postinstall script while
2039 	 * we're still on volume 1.
2040 	 */
2041 
2042 	(void) snprintf(script, sizeof (script),
2043 			"%s/install/postinstall", instdir);
2044 	if (access(script, F_OK) == 0) {
2045 		(void) snprintf(script, sizeof (script),
2046 					"%s/postinstall", pkgbin);
2047 	} else {
2048 		script[0] = '\0';
2049 	}
2050 
2051 	/* update the lock - at the install phase */
2052 
2053 	lockupd("install");
2054 
2055 	/*
2056 	 * install package one part (volume) at a time
2057 	 */
2058 
2059 	part = 1;
2060 	while (part <= nparts) {
2061 		if ((part > 1) && pkgdev.cdevice) {
2062 			unpack();
2063 		}
2064 
2065 		instvol(extlist, srcinst, part, nparts,
2066 			pkgserver, &cfTmpVfp, &updated, zoneName);
2067 
2068 		if (part++ >= nparts) {
2069 			break;
2070 		}
2071 	}
2072 
2073 	z_destroyMountTable();
2074 
2075 	/*
2076 	 * Now that all install class action scripts have been used, we
2077 	 * delete them from the package directory.
2078 	 */
2079 	rm_icas(pkgbin);
2080 
2081 	if (globalZoneOnly) {
2082 		boolean_t   b;
2083 		b = pkgAddPackageToGzonlyList(pkginst, get_inst_root());
2084 		if (b == B_FALSE) {
2085 			progerr(ERR_PKGINSTALL_GZONLY_ADD, pkginst);
2086 			ckreturn(1, NULL);
2087 		}
2088 	}
2089 
2090 	/*
2091 	 * Execute postinstall script, if any
2092 	 * Don't execute postinstall script if we are only updating the DB.
2093 	 */
2094 
2095 	echoDebug(DBG_PKGINSTALL_INSDONE, is_depend_pkginfo_DB(),
2096 		is_depend_pkginfo_DB(), saveSpoolInstall,
2097 		updated ? updated : "",
2098 		script ? script : "",
2099 		script ? access(script, F_OK) : -1);
2100 
2101 	/* update the lock - at the postinstall script */
2102 	lockupd("postinstall");
2103 
2104 	if ((script == (char *)NULL) || (*script == '\0')) {
2105 		echoDebug(DBG_PKGINSTALL_POIS_NOPATH, pkginst,
2106 			zoneName ? zoneName : "global");
2107 	} else if (access(script, F_OK) != 0) {
2108 		echoDebug(DBG_PKGINSTALL_POIS_NONE, pkginst, script,
2109 			zoneName ? zoneName : "global");
2110 	} else if (is_depend_pkginfo_DB()) {
2111 		echoDebug(DBG_PKGINSTALL_POIS_DBUPD, pkginst, script,
2112 			zoneName ? zoneName : "global");
2113 	} else if ((saveSpoolInstall != 0) && (updated == (char *)NULL)) {
2114 		/*
2115 		 * fresh installing into non-global zone, no object was
2116 		 * updated (installed/verified in area), so do not run
2117 		 * the postinstall script.
2118 		 */
2119 		echoDebug(DBG_PKGINSTALL_POIS_NOUPDATING,
2120 			zoneName ? zoneName : "global", pkginst, script);
2121 	} else {
2122 		/* script present and ok to run: run the script */
2123 		set_ulimit("postinstall", ERR_POSTINSTALL);
2124 		if (zoneName == (char *)NULL) {
2125 			echo(MSG_PKGINSTALL_EXEPIC_GZ);
2126 			echoDebug(DBG_PKGINSTALL_EXEPIC_GZ, pkginst, script);
2127 		} else {
2128 			echo(MSG_PKGINSTALL_EXEPIC_LZ, zoneName);
2129 			echoDebug(DBG_PKGINSTALL_EXEPIC_LZ, pkginst, script,
2130 				zoneName);
2131 		}
2132 		putparam("PKG_PROC_SCRIPT", "postinstall");
2133 		putparam("TMPDIR", tmpdir);
2134 		if (pkgverbose) {
2135 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
2136 				PROC_USER, PROC_GRP, SHELL, "-x",
2137 				script, NULL), ERR_POSTINSTALL);
2138 		} else {
2139 			ckreturn(pkgexecl(script_in, PROC_STDOUT,
2140 				PROC_USER, PROC_GRP, SHELL, script,
2141 				NULL), ERR_POSTINSTALL);
2142 		}
2143 
2144 		clr_ulimit();
2145 		(void) remove(script);	/* no longer needed */
2146 	}
2147 
2148 	if (!warnflag && !failflag) {
2149 		(void) remove(rlockfile);
2150 		(void) remove(ilockfile);
2151 		(void) remove(savlog);
2152 	}
2153 
2154 	/* release the generic package lock */
2155 
2156 	(void) unlockinst();
2157 
2158 	pkgcloseserver(pkgserver);
2159 
2160 	quit(0);
2161 	/* LINTED: no return */
2162 }
2163 
2164 /*
2165  * This function merges the environment data in the response file with the
2166  * current environment.
2167  */
2168 static int
2169 merg_respfile()
2170 {
2171 	int retcode = 0;
2172 	char *resppath = get_respfile();
2173 	char *locbasedir;
2174 	char param[MAX_PKG_PARAM_LENGTH], *value;
2175 	FILE *fp;
2176 
2177 	if ((fp = fopen(resppath, "r")) == NULL) {
2178 		progerr(ERR_RESPONSE, resppath);
2179 		return (99);
2180 	}
2181 
2182 	param[0] = '\0';
2183 
2184 	while (value = fpkgparam(fp, param)) {
2185 		if (!isupper(param[0])) {
2186 			param[0] = '\0';
2187 			continue;
2188 		}
2189 
2190 		if (rdonly(param)) {
2191 			progerr(ERR_RDONLY, param);
2192 			param[0] = '\0';
2193 			continue;
2194 		}
2195 
2196 		/*
2197 		 * If this is an update, and the response file
2198 		 * specifies the BASEDIR, make sure it matches the
2199 		 * existing installation base. If it doesn't, we have
2200 		 * to quit.
2201 		 */
2202 		if (update && strcmp("BASEDIR", param) == 0) {
2203 			locbasedir = getenv("BASEDIR");
2204 			if (locbasedir && strcmp(value, locbasedir) != 0) {
2205 				char *dotptr;
2206 				/* Get srcinst down to a name. */
2207 				if (dotptr = strchr(srcinst, '.'))
2208 					*dotptr = '\000';
2209 				progerr(ERR_NEWBD, srcinst,
2210 					locbasedir, value);
2211 				retcode = 99;
2212 			}
2213 		}
2214 
2215 		putparam(param, value);
2216 		param[0] = '\0';
2217 	}
2218 	(void) fclose(fp);
2219 
2220 	return (retcode);
2221 }
2222 
2223 /*
2224  * This scans the installed pkginfo file for the current BASEDIR. If this
2225  * BASEDIR is different from the current BASEDIR, there will definitely be
2226  * problems.
2227  */
2228 static int
2229 ck_instbase(void)
2230 {
2231 	int retcode = 0;
2232 	char param[MAX_PKG_PARAM_LENGTH], *value;
2233 	char pkginfo_path[PATH_MAX];
2234 	FILE *fp;
2235 
2236 	/* Open the old pkginfo file. */
2237 	(void) snprintf(pkginfo_path, sizeof (pkginfo_path),
2238 			"%s/%s", pkgloc, PKGINFO);
2239 	if ((fp = fopen(pkginfo_path, "r")) == NULL) {
2240 		progerr(ERR_PKGINFO, pkginfo_path);
2241 		return (99);
2242 	}
2243 
2244 	param[0] = '\000';
2245 
2246 	while (value = fpkgparam(fp, param)) {
2247 		if (strcmp("BASEDIR", param) == 0) {
2248 			if (adm.basedir && *(adm.basedir) &&
2249 				strchr("/$", *(adm.basedir))) {
2250 				char *dotptr;
2251 
2252 				/*
2253 				 * Get srcinst down to a name.
2254 				 */
2255 				if (dotptr = strchr(srcinst, '.'))
2256 					*dotptr = '\000';
2257 				if (strcmp(value,
2258 					adm.basedir) != 0) {
2259 					progerr(ERR_ADMBD, srcinst,
2260 						value, adm.basedir);
2261 					retcode = 4;
2262 					break;
2263 				}
2264 			} else if (ADM(basedir, "ask"))
2265 				/*
2266 				 * If it's going to ask later, let it know
2267 				 * that it *must* agree with the BASEDIR we
2268 				 * just picked up.
2269 				 */
2270 				adm.basedir = "update";
2271 
2272 			putparam(param, value);
2273 			break;
2274 		}
2275 
2276 		param[0] = '\0';
2277 	}
2278 	(void) fclose(fp);
2279 
2280 	return (retcode);
2281 }
2282 
2283 /*
2284  * Since this is an overwrite of a different version of the package, none of
2285  * the old files should remain, so we rename them.
2286  */
2287 static int
2288 mv_pkgdirs(void)
2289 {
2290 	/*
2291 	 * If we're not in dryrun mode and we can find an old set of package
2292 	 * files over which the new ones will be written, do the rename.
2293 	 */
2294 	if (!in_dryrun_mode() && pkgloc[0] && !access(pkgloc, F_OK)) {
2295 		(void) snprintf(pkgloc_sav, sizeof (pkgloc_sav),
2296 			"%s/.save.%s", get_PKGLOC(),
2297 			pkginst);
2298 		if (pkgloc_sav[0] && !access(pkgloc_sav, F_OK)) {
2299 			(void) rrmdir(pkgloc_sav);
2300 		}
2301 
2302 		if (rename(pkgloc, pkgloc_sav) == -1) {
2303 			progerr(ERR_PKGBINREN, pkgloc, pkgloc_sav);
2304 			return (99);
2305 		}
2306 	}
2307 
2308 	return (0);
2309 }
2310 
2311 /*
2312  * Name:	merg_pkginfos
2313  * Description:	This function scans the installed pkginfo and merges that
2314  *		environment with the installing environment according to
2315  *		the following rules:
2316  *
2317  *		1. CLASSES is a union of the installed and installing CLASSES
2318  *			lists.
2319  *		2. The installed BASEDIR takes precedence. If it doesn't agree
2320  *		   with an administratively imposed BASEDIR, an ERROR is issued.
2321  *		3. All other installing parameters are preserved.
2322  *		4. All installed parameters are added if they do not overwrite
2323  *		   an existing installing parameter.
2324  *
2325  *		The current environment contains the pkginfo settings for the
2326  *		new package to be installed or to be updated.
2327  *
2328  * Arguments:	pclass - returned list of current classes involved in install
2329  *		mpclass - pointer to returned list of current install classes
2330  * Returns:	int
2331  *		== 0 - all OK
2332  *		!= 0 - an error code if a fatal error occurred
2333  */
2334 
2335 static int
2336 merg_pkginfos(struct cl_attr **pclass, struct cl_attr ***mpclass)
2337 {
2338 	FILE	*fp;
2339 	char	SUNW_PKG_ALLZONES[MAX_PKG_PARAM_LENGTH] = {'\0'};
2340 	char	SUNW_PKG_HOLLOW[MAX_PKG_PARAM_LENGTH] = {'\0'};
2341 	char	SUNW_PKG_THISZONE[MAX_PKG_PARAM_LENGTH] = {'\0'};
2342 	char	*newValue;
2343 	char	*oldValue;
2344 	char	*pkgName;
2345 	char	*pkgVersion;
2346 	char	param[MAX_PKG_PARAM_LENGTH];
2347 	char	pkginfo_path[PATH_MAX];
2348 	int	retcode = 0;
2349 
2350 	/* obtain the name of the package (for error messages) */
2351 
2352 	pkgName = getenv("PKG");
2353 	if (pkgName == NULL) {
2354 		pkgName = "*current*";	/* default name */
2355 	}
2356 
2357 	/* obtain the version of the package (for error messages) */
2358 
2359 	pkgVersion = getenv("VERSION");
2360 	if (pkgVersion == NULL) {
2361 		pkgVersion = "*current*";	/* default version */
2362 	}
2363 
2364 	/* open installed package pkginfo file */
2365 
2366 	(void) snprintf(pkginfo_path, sizeof (pkginfo_path),
2367 			"%s/%s", pkgloc, PKGINFO);
2368 	if ((fp = fopen(pkginfo_path, "r")) == NULL) {
2369 		progerr(ERR_PKGINFO, pkginfo_path);
2370 		return (99);
2371 	}
2372 
2373 	/* entry debugging info */
2374 
2375 	echoDebug(DBG_MERGINFOS_ENTRY, pkginfo_path);
2376 
2377 	/*
2378 	 * cycle through the currently installed package's pkginfo parameters
2379 	 * and let the currently installed package's settings survive if the
2380 	 * update to the package does not provide an overriding value
2381 	 */
2382 
2383 	for (param[0] = '\0'; (oldValue = fpkgparam(fp, param)) != NULL;
2384 		param[0] = '\0') {
2385 
2386 		boolean_t	setZoneAttribute = B_FALSE;
2387 
2388 		/* debug info - attribute currently set to value */
2389 
2390 		echoDebug(DBG_MERGINFOS_SET_TO, param, oldValue);
2391 
2392 		/*
2393 		 * if zone package attribute is present in the currently
2394 		 * installed package, then remember the value for the
2395 		 * specific zone package attribute, and set the flag that
2396 		 * indicates a zone package attribute is being processed.
2397 		 */
2398 
2399 		if (strcmp(param, PKG_THISZONE_VARIABLE) == 0) {
2400 			/* SUNW_PKG_THISZONE currently set */
2401 			setZoneAttribute = B_TRUE;
2402 			(void) strlcpy(SUNW_PKG_THISZONE, oldValue,
2403 					sizeof (SUNW_PKG_THISZONE));
2404 		} else if (strcmp(param, PKG_ALLZONES_VARIABLE) == 0) {
2405 			/* SUNW_PKG_ALLZONES currently set */
2406 			setZoneAttribute = B_TRUE;
2407 			(void) strlcpy(SUNW_PKG_ALLZONES, oldValue,
2408 					sizeof (SUNW_PKG_ALLZONES));
2409 		} else if (strcmp(param, PKG_HOLLOW_VARIABLE) == 0) {
2410 			/* SUNW_PKG_THISZONE currently set */
2411 			setZoneAttribute = B_TRUE;
2412 			(void) strlcpy(SUNW_PKG_HOLLOW, oldValue,
2413 					sizeof (SUNW_PKG_HOLLOW));
2414 		}
2415 
2416 		/* handle CLASSES currently being set */
2417 
2418 		if (strcmp(param, "CLASSES") == 0) {
2419 			echoDebug(DBG_MERGINFOS_SET_CLASSES, oldValue);
2420 			/* create a list of the current classes */
2421 			(void) setlist(&pclass, qstrdup(oldValue));
2422 			/* set pointer to list of current classes */
2423 			*mpclass = pclass;
2424 			continue;
2425 		}
2426 
2427 		/* handle BASEDIR currently being set */
2428 
2429 		if (strcmp("BASEDIR", param) == 0) {
2430 			if (adm.basedir && *(adm.basedir) &&
2431 				strchr("/$", *(adm.basedir))) {
2432 				char *dotptr;
2433 
2434 				/* Get srcinst down to a* name */
2435 
2436 				if (dotptr = strchr(srcinst, '.')) {
2437 					*dotptr = '\000';
2438 				}
2439 				if (strcmp(oldValue, adm.basedir) != 0) {
2440 					progerr(ERR_ADMBD, srcinst,
2441 						oldValue, adm.basedir);
2442 					/* administration */
2443 					retcode = 4;
2444 					break;
2445 				}
2446 			} else if (ADM(basedir, "ask")) {
2447 				/*
2448 				 * If it's going to ask
2449 				 * later, let it know that it
2450 				 * *must* agree with the
2451 				 * BASEDIR we just picked up.
2452 				 */
2453 				adm.basedir = "update";
2454 				echoDebug(DBG_MERGINFOS_ASK_BASEDIR);
2455 			}
2456 
2457 			echoDebug(DBG_MERGINFOS_SET_BASEDIR, oldValue);
2458 			putparam(param, oldValue);
2459 			continue;
2460 		}
2461 
2462 		/*
2463 		 * determine if there is a new value for this attribute.
2464 		 */
2465 
2466 		newValue = getenv(param);
2467 
2468 		/*
2469 		 * If there is no new value, and a zone attribute
2470 		 * is being changed, it is the same as setting the zone package
2471 		 * attribute to 'false' - make sure current setting is 'false'.
2472 		 */
2473 
2474 		if ((newValue == NULL) &&
2475 		    (setZoneAttribute == B_TRUE) &&
2476 		    (strcasecmp(oldValue, "false") != 0)) {
2477 
2478 			/* unset existing non-"false" zone pkg attr */
2479 			progerr(ERR_MERGINFOS_UNSET_ZONEATTR,
2480 				pkgName, pkgVersion, param, oldValue);
2481 			retcode = 1;
2482 			break;
2483 		}
2484 
2485 		/* retain old value if no new value specified */
2486 
2487 		if (newValue == NULL) {
2488 			/* no new value - retain the old value */
2489 			echoDebug(DBG_MERGINFOS_RETAIN_OLD, param, oldValue);
2490 			putparam(param, oldValue);
2491 			continue;
2492 		}
2493 
2494 		/* note if the old and new values are the same */
2495 
2496 		if (strcmp(newValue, oldValue) == 0) {
2497 			/* set existing package parameter to same value */
2498 			echoDebug(DBG_MERGINFOS_SET_DUPLICATE, param, oldValue);
2499 			continue;
2500 		}
2501 
2502 		/*
2503 		 * Check if old and new values differ.
2504 		 * Error if zone parameter
2505 		 */
2506 
2507 		if (setZoneAttribute == B_TRUE) {
2508 			/* illegal change to zone attribute */
2509 
2510 			progerr(ERR_MERGINFOS_CHANGE_ZONEATTR, pkgName,
2511 				pkgVersion, param, oldValue, newValue);
2512 
2513 			/* set return code to "fatal error" */
2514 			retcode = 1;
2515 			break;
2516 		}
2517 
2518 		/* note valid change to existing package parameter */
2519 
2520 		echoDebug(DBG_MERGINFOS_SET_CHANGE, param,
2521 				oldValue, newValue);
2522 	}
2523 
2524 	/* close handle on currently installed package's pkginfo file */
2525 
2526 	(void) fclose(fp);
2527 
2528 	/* return error if not successful up to this point */
2529 
2530 	if (retcode != 0) {
2531 		echoDebug(DBG_MERGINFOS_EXIT, pkginfo_path, retcode);
2532 
2533 		return (retcode);
2534 	}
2535 
2536 	/*
2537 	 * verify that no zone attribute has been
2538 	 * set to an invalid value
2539 	 */
2540 
2541 	/* SUNW_PKG_ALLZONES */
2542 
2543 	newValue = getenv(PKG_ALLZONES_VARIABLE);
2544 
2545 	/*
2546 	 * complain if setting SUNW_PKG_ALLZONES to other than "false"
2547 	 */
2548 
2549 
2550 	if ((newValue != NULL) && (*SUNW_PKG_ALLZONES == '\0') &&
2551 	    (strcasecmp(newValue, "false") != 0)) {
2552 		/* change ALLZONES from "true" to "false" (unset) */
2553 		progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
2554 		    pkgVersion, PKG_ALLZONES_VARIABLE, newValue);
2555 		return (1);
2556 	}
2557 
2558 	/* SUNW_PKG_THISZONE */
2559 
2560 	newValue = getenv(PKG_THISZONE_VARIABLE);
2561 
2562 	/*
2563 	 * complain if setting SUNW_PKG_THISZONE to other than "false"
2564 	 */
2565 
2566 	if ((newValue != NULL) && (*SUNW_PKG_THISZONE == '\0') &&
2567 	    (strcasecmp(newValue, "false") != 0)) {
2568 		/* change THISZONE from "true" to "false" (unset) */
2569 		progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
2570 		    pkgVersion, PKG_THISZONE_VARIABLE, newValue);
2571 		return (1);
2572 	}
2573 
2574 	/* SUNW_PKG_HOLLOW */
2575 
2576 	newValue = getenv(PKG_HOLLOW_VARIABLE);
2577 
2578 	/* complain if setting SUNW_PKG_HOLLOW to other than "false" */
2579 
2580 	if ((newValue != NULL) && (*SUNW_PKG_HOLLOW == '\0') &&
2581 	    (strcasecmp(newValue, "false") != 0)) {
2582 		/* change HOLLOW from "true" to 'false" (unset) */
2583 		progerr(ERR_MERGINFOS_SET_ZONEATTR, pkgName,
2584 		    pkgVersion, PKG_HOLLOW_VARIABLE, newValue);
2585 		return (1);
2586 	}
2587 
2588 	echoDebug(DBG_MERGINFOS_EXIT, pkginfo_path, 0);
2589 
2590 	return (0);
2591 }
2592 
2593 static void
2594 set_dryrun_dir_loc(void)
2595 {
2596 	/* Set pkg location to the dryrun directory */
2597 	set_PKGLOC(pkgdrtarg);
2598 	(void) snprintf(pkgloc, sizeof (pkgloc),
2599 			"%s/%s", get_PKGLOC(), pkginst);
2600 	(void) snprintf(pkgbin, sizeof (pkgbin),
2601 			"%s/install", pkgloc);
2602 	(void) snprintf(pkgsav, sizeof (pkgsav),
2603 			"%s/save", pkgloc);
2604 	(void) snprintf(ilockfile, sizeof (ilockfile),
2605 			"%s/!I-Lock!", pkgloc);
2606 	(void) snprintf(rlockfile, sizeof (rlockfile),
2607 			"%s/!R-Lock!", pkgloc);
2608 	(void) snprintf(savlog, sizeof (savlog),
2609 			"%s/logs/%s", get_PKGADM(), pkginst);
2610 }
2611 
2612 /*
2613  * If we are updating a pkg, then we need to copy the "old" pkgloc so that
2614  * any scripts that got removed in the new version aren't left around.  So we
2615  * copy it here to .save.pkgloc, then in quit() we can restore our state, or
2616  * remove it.
2617  */
2618 static int
2619 cp_pkgdirs(void)
2620 {
2621 	if (in_dryrun_mode()) {
2622 		set_dryrun_dir_loc();
2623 	}
2624 
2625 	/*
2626 	 * If we're not in dryrun mode and we can find an old set of package
2627 	 * files over which the new ones will be written, do the copy.
2628 	 */
2629 	if (!in_dryrun_mode() && pkgloc[0] && !access(pkgloc, F_OK)) {
2630 		int status;
2631 		int r;
2632 
2633 		(void) snprintf(pkgloc_sav, sizeof (pkgloc_sav), "%s/.save.%s",
2634 			get_PKGLOC(), pkginst);
2635 
2636 		/*
2637 		 * Even though it takes a while, we use a recursive copy here
2638 		 * because if the current pkgadd fails for any reason, we
2639 		 * don't want to lose this data.
2640 		 */
2641 		r = e_ExecCmdList(&status, (char **)NULL, (char *)NULL,
2642 			"/usr/bin/cp", "cp", "-r", pkgloc, pkgloc_sav,
2643 			(char *)NULL);
2644 
2645 		if ((r != 0) || (status == -1) || (WEXITSTATUS(status) != 0)) {
2646 			progerr(ERR_PKGBINCP, pkgloc, pkgloc_sav);
2647 			return (99);
2648 		}
2649 	}
2650 
2651 	return (0);
2652 }
2653 
2654 /*
2655  * This implements the pkgask function. It just executes the request script
2656  * and stores the results in a response file.
2657  */
2658 static void
2659 do_pkgask(boolean_t a_run_request_as_root)
2660 {
2661 	if (pkgdev.cdevice) {
2662 		unpack();
2663 		if (!suppressCopyright) {
2664 			copyright();
2665 		}
2666 	}
2667 	(void) snprintf(path, sizeof (path), "%s/%s", instdir, REQUEST_FILE);
2668 	if (access(path, F_OK)) {
2669 		progerr(ERR_NOREQUEST);
2670 		quit(1);
2671 		/*NOTREACHED*/
2672 	}
2673 
2674 	(void) set_respfile(respfile, srcinst, RESP_WR);
2675 
2676 	if (is_a_respfile()) {
2677 		ckreturn(reqexec(update, path, non_abi_scripts,
2678 			a_run_request_as_root), ERR_REQUEST);
2679 	} else {
2680 		failflag++;
2681 	}
2682 
2683 	if (warnflag || failflag) {
2684 		(void) remove(respfile);
2685 		echo("\nResponse file <%s> was not created.",
2686 			get_respfile());
2687 	} else {
2688 		echo("\nResponse file <%s> was created.",
2689 			get_respfile());
2690 	}
2691 
2692 	quit(0);
2693 	/*NOTREACHED*/
2694 }
2695 
2696 /*
2697  * This function runs a check utility and acts appropriately based upon the
2698  * return code. It deals appropriately with the dryrun file if it is present.
2699  */
2700 static void
2701 ck_w_dryrun(int (*func)(), int type)
2702 {
2703 	int n;
2704 
2705 	n = func();
2706 	if (in_dryrun_mode())
2707 		set_dr_info(type, !n);
2708 
2709 	if (n) {
2710 		quit(n);
2711 		/*NOTREACHED*/
2712 	}
2713 }
2714 
2715 /*
2716  * This function deletes all install class action scripts from the package
2717  * directory on the root filesystem.
2718  */
2719 static void
2720 rm_icas(char *cas_dir)
2721 {
2722 	DIR	*pdirfp;
2723 	struct	dirent *dp;
2724 	char path[PATH_MAX];
2725 
2726 	if ((pdirfp = opendir(cas_dir)) == NULL)
2727 		return;
2728 
2729 	while ((dp = readdir(pdirfp)) != NULL) {
2730 		if (dp->d_name[0] == '.')
2731 			continue;
2732 
2733 		if (dp->d_name[0] == 'i' && dp->d_name[1] == '.') {
2734 			(void) snprintf(path, sizeof (path),
2735 				"%s/%s", cas_dir, dp->d_name);
2736 			(void) remove(path);
2737 		}
2738 	}
2739 	(void) closedir(pdirfp);
2740 }
2741 
2742 void
2743 ckreturn(int retcode, char *msg)
2744 {
2745 	switch (retcode) {
2746 		case 2:
2747 		case 12:
2748 		case 22:
2749 		warnflag++;
2750 		if (msg) {
2751 			progerr("%s", msg);
2752 		}
2753 		/*FALLTHRU*/
2754 		case 10:
2755 		case 20:
2756 		if (retcode >= 10 && retcode < 20) {
2757 			dreboot++;
2758 		}
2759 		if (retcode >= 20) {
2760 			ireboot++;
2761 		}
2762 		/*FALLTHRU*/
2763 		case 0:
2764 		break; /* okay */
2765 
2766 		case -1:
2767 		retcode = 99;
2768 		/*FALLTHRU*/
2769 		case 99:
2770 		case 1:
2771 		case 11:
2772 		case 21:
2773 		case 4:
2774 		case 14:
2775 		case 24:
2776 		case 5:
2777 		case 15:
2778 		case 25:
2779 		if (msg) {
2780 			progerr("%s", msg);
2781 		}
2782 		/*FALLTHRU*/
2783 		case 3:
2784 		case 13:
2785 		case 23:
2786 		quit(retcode);
2787 		/*NOTREACHED*/
2788 		default:
2789 		if (msg) {
2790 			progerr("%s", msg);
2791 		}
2792 		quit(1);
2793 		/*NOTREACHED*/
2794 	}
2795 }
2796 
2797 static void
2798 copyright(void)
2799 {
2800 	FILE	*fp;
2801 	char	line[LSIZE];
2802 	char	path[PATH_MAX];
2803 
2804 	/* Compose full path for copyright file */
2805 	(void) snprintf(path, sizeof (path), "%s/%s", instdir, COPYRIGHT_FILE);
2806 
2807 	if ((fp = fopen(path, "r")) == NULL) {
2808 		if (getenv("VENDOR") != NULL)
2809 			echo(getenv("VENDOR"));
2810 	} else {
2811 		while (fgets(line, LSIZE, fp))
2812 			(void) fprintf(stdout, "%s", line); /* bug #1083713 */
2813 		(void) fclose(fp);
2814 	}
2815 }
2816 
2817 static int
2818 rdonly(char *p)
2819 {
2820 	int	i;
2821 
2822 	for (i = 0; ro_params[i]; i++) {
2823 		if (strcmp(p, ro_params[i]) == 0)
2824 			return (1);
2825 	}
2826 	return (0);
2827 }
2828 
2829 static void
2830 unpack(void)
2831 {
2832 	/*
2833 	 * read in next part from stream, even if we decide
2834 	 * later that we don't need it
2835 	 */
2836 	if (dparts < 1) {
2837 		progerr(ERR_DSTREAMCNT);
2838 		quit(99);
2839 		/*NOTREACHED*/
2840 	}
2841 	if ((access(instdir, F_OK) == 0) && rrmdir(instdir)) {
2842 		progerr(ERR_RMDIR, instdir);
2843 		quit(99);
2844 		/*NOTREACHED*/
2845 	}
2846 	if (mkdir(instdir, 0755)) {
2847 		progerr(ERR_MKDIR, instdir);
2848 		quit(99);
2849 		/*NOTREACHED*/
2850 	}
2851 	if (chdir(instdir)) {
2852 		progerr(ERR_CHDIR, instdir);
2853 		quit(99);
2854 		/*NOTREACHED*/
2855 	}
2856 	if (!ds_fd_open()) {
2857 		dparts = ds_findpkg(pkgdev.cdevice, srcinst);
2858 		if (dparts < 1) {
2859 			progerr(ERR_DSARCH, srcinst);
2860 			quit(99);
2861 			/*NOTREACHED*/
2862 		}
2863 	}
2864 
2865 	dparts--;
2866 
2867 	if (ds_next(pkgdev.cdevice, instdir)) {
2868 		progerr(ERR_DSTREAM);
2869 		quit(99);
2870 		/*NOTREACHED*/
2871 	}
2872 	if (chdir(get_PKGADM())) {
2873 		progerr(ERR_CHDIR, get_PKGADM());
2874 		quit(99);
2875 		/*NOTREACHED*/
2876 	}
2877 	ds_close(1);
2878 }
2879 
2880 static void
2881 usage(void)
2882 {
2883 	(void) fprintf(stderr, ERR_USAGE_PKGINSTALL);
2884 	exit(1);
2885 	/*NOTREACHED*/
2886 }
2887