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