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