xref: /titanic_41/usr/src/cmd/svr4pkg/pkgadd/main.c (revision b9aa66a73c9016cf5c71fe80efe90ce9f2ca5c73)
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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29 
30 
31 /*
32  * Program:	pkgadd / pkgask
33  *
34  * Function:	public command and private utility functions that
35  *		implement the package add and package ask operations.
36  *
37  */
38 
39 /*
40  * System includes
41  */
42 
43 #include <stdio.h>
44 #include <limits.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <signal.h>
52 #include <errno.h>
53 #include <pkgdev.h>
54 #include <pkginfo.h>
55 #include <pkglocs.h>
56 #include <locale.h>
57 #include <libintl.h>
58 #include <pkgtrans.h>
59 #include <boot_http.h>
60 #include <assert.h>
61 
62 /*
63  * consolidation pkg command library includes
64  */
65 #include <pkglib.h>
66 #include <pkgerr.h>
67 #include <pkgweb.h>
68 
69 #include <instzones_api.h>
70 
71 /*
72  * local pkg command library includes
73  */
74 #include <install.h>
75 #include <libinst.h>
76 #include <libadm.h>
77 #include <messages.h>
78 
79 
80 /*
81  * pkgadd local includes
82  */
83 
84 #include "quit.h"
85 
86 /*
87  * imported global variables/functions
88  */
89 
90 /* presvr4.c */
91 extern int	presvr4(char **ppkg, int a_nointeract);
92 
93 /* check.c */
94 extern int	preinstall_verify(char **a_pkgList, zoneList_t a_zlst,
95 			char *a_zoneTempDir);
96 
97 /*
98  * ckquit is a global that controls 'ckyorn' (defined in libadm)
99  * If ckquit is non-zero, then "quit" is allowed as an answer when
100  * ckyorn is called. If is it zero, then "quit" is not an allowed answer.
101  */
102 extern int	ckquit;
103 
104 /*
105  * exported global variables
106  */
107 
108 /* these globals are set by ckreturn and used by quit.c */
109 
110 int	admnflag = 0;	/* != 0 if any pkg op admin setting failure (4) */
111 int	doreboot = 0;	/* != 0 if reboot required after installation */
112 int	failflag = 0;	/* != 0 if fatal error has occurred (1) */
113 int	intrflag = 0;	/* != 0 if user selected quit (3) */
114 int	ireboot = 0;	/* != 0 if immediate reboot required */
115 int	nullflag = 0;	/* != 0 if admin interaction required (5) */
116 int	warnflag = 0;	/* != 0 if non-fatal error has occurred (2) */
117 
118 /* imported by quit.c */
119 int	npkgs = 0;	/* the number of packages yet to be installed */
120 
121 /* imported by various (many) */
122 char	*respfile = NULL;	/* response pathname (or NULL) */
123 char	*tmpdir = NULL;		/* location to place temporary files */
124 
125 struct admin	adm;		/* holds info about installation admin */
126 struct pkgdev	pkgdev;		/* holds info about the installation device */
127 
128 /*
129  * internal global variables
130  */
131 
132 static char	*admnfile = NULL;	/* file to use for installation admin */
133 static char	*ids_name = NULL;	/* name of data stream device */
134 static char	*pkgcontsrc = NULL;	/* continuation file (-c option) */
135 static char	*pkgdrtarg = NULL;	/* dry run file (-D option) */
136 static char	*pkginst = NULL;	/* current pkg/src instance 2 process */
137 static char	*respdir = NULL;	/* respfile is a directory spec */
138 static char	*rw_block_size = NULL;
139 static char	*vfstab_file = NULL;
140 static int	askflag = 0;		/* non-zero if invoked as "pkgask" */
141 static int	disableAttributes = 0;	/* Disabling attribute checking */
142 static int	disableChecksum = 0;	/* Disable checksumming */
143 static int	disableSaveSpool = 0;	/* Disable partial spool dir create */
144 static int	init_install = 0;	/* inform scripts initial install */
145 static int	no_map_client = 0;	/* do not map from vfstab file */
146 static int	nointeract = 0;		/* non-zero - no user interaction */
147 static int	pkgverbose = 0;		/* non-zero if verbose mode selected */
148 static int	saveSpoolInstall = 0;	/* installing from save spool dir */
149 static int	suppressCopyright = 0;	/* suppress copyright notices */
150 
151 /* set by ckreturn() */
152 
153 static int	interrupted = 0;	/* last pkg op was quit (1,2,3,4,5) */
154 static int	needconsult = 0;	/* essential ask admin now (1,2,3,5) */
155 
156 /* Set by -O nozones: do not process any zones */
157 
158 static boolean_t	noZones = B_FALSE;
159 
160 /* Set by -O zonelist=<names...>: process only named zones */
161 
162 static boolean_t	usedZoneList = B_FALSE;
163 
164 /* Set by -O debug: debug output is enabled? */
165 
166 static boolean_t	debugFlag = B_FALSE;
167 
168 /* Set by the -G option: install packages in global zone only */
169 
170 static boolean_t	globalZoneOnly = B_FALSE;
171 
172 /* Set by -O patchPkgRemoval */
173 
174 static boolean_t	patchPkgRemoval = B_FALSE;
175 
176 /*
177  * Assume the package is ABI and POSIX compliant as regards user
178  * interactiion during procedure scripts.
179  */
180 
181 static int	old_pkg = 0;
182 
183 /* Assume pkg should be installed according to the ABI */
184 
185 static int	old_symlinks = 0;
186 
187 /*
188  * Default name length will be 32 chars - if this is set,
189  * disable the 32 char name limit extension
190  */
191 
192 static int	ABI_namelength = 0;
193 
194 #if	!defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
195 #define	TEXT_DOMAIN	"SYS_TEST"
196 #endif
197 
198 /* printable string - if string is null results in ??? */
199 
200 #define	PSTR(STR) (((STR) == (char *)NULL) ? "???" : (STR))
201 
202 #define	MAX_FDS	20
203 
204 #define	INHERITFS	"inherited-filesystem="
205 #define	INHERITFS_LEN	((sizeof (INHERITFS))-1)
206 
207 /*
208  * forward declarations
209  */
210 
211 static int		boot_and_pkginstall_check_in_zones(zoneList_t a_zlst,
212 				char *a_idsName, char *a_altBinDir,
213 				char *a_zoneAdminFile, char *a_zoneTempDir);
214 static int		boot_and_install_in_zones(zoneList_t a_zlst,
215 				char *a_idsName, char *a_altBinDir,
216 				char *a_zoneAdminFile, char *a_zoneTempDir);
217 static void		pkginstall_check_in_one_zone(char **a_inheritedPkgDirs,
218 				char *a_zoneName, char *a_idsName,
219 				char *a_zoneAdminFile, char *a_zoneTempDir,
220 				char *a_altBinDir, char *a_scratchName,
221 				zone_state_t a_zoneState);
222 static void		ckreturn(int retcode);
223 static void		create_zone_adminfile(char **r_zoneAdminFile,
224 				char *a_zoneTempDir, char *a_admnfile);
225 static void		create_zone_tempdir(char **r_zoneTempDir,
226 				char *a_tmpdir);
227 static void		install_in_one_zone(char **a_inheritedPkgDirs,
228 				char *a_zoneName, char *a_idsName,
229 				char *a_zoneAdminFile, char *a_zoneTempDir,
230 				char *a_altBinDir, zone_state_t a_zoneState);
231 static int		pkginstall_check_in_zones(zoneList_t a_zlst,
232 				char *a_idsName, char *a_altBinDir,
233 				char *a_zoneAdminFile, char *a_zoneTempDir);
234 static int		install_in_zones(zoneList_t a_zlst, char *a_idsName,
235 				char *a_altBinDir, char *a_zoneAdminFile,
236 				char *a_zoneTempDir);
237 static int		pkgInstall(char *ir, char *a_idsName, char *a_pkgDir,
238 				char *a_altBinDir, char **a_inheritedPkgDirs);
239 static int		pkgZoneCheckInstall(char *a_zoneName,
240 				char **a_inheritedPkgDirs,
241 				zone_state_t a_zoneState,
242 				char *a_idsName, char *a_altBinDir,
243 				char *a_adminFile, char *a_stdoutPath);
244 static int		pkgZoneInstall(char *a_zoneName,
245 				char **a_inheritedPkgDirs,
246 				zone_state_t a_zoneState,
247 				char *a_idsName, char *a_altBinDir,
248 				char *a_adminFile);
249 static void		resetreturn();
250 static void		usage(void);
251 static boolean_t	add_packages(char **a_pkgList, char *a_uri,
252 				char *a_idsName, int a_repeat,
253 				char *a_altBinDir, char *a_device,
254 				boolean_t a_noZones);
255 static boolean_t	add_packages_in_global_no_zones(char **a_pkgList,
256 				char *a_uri, char *a_idsName, int a_repeat,
257 				char *a_altBinDir, char *a_device);
258 static boolean_t	add_packages_in_global_with_zones(char **a_pkgList,
259 				char *a_uri, char *a_idsName, int a_repeat,
260 				char *a_altBinDir, char *a_device,
261 				zoneList_t a_zlst);
262 static boolean_t	add_packages_in_nonglobal_zone(char **a_pkgList,
263 				char *a_uri, char *a_idsName, int a_repeat,
264 				char *a_altBinDir, char *a_device);
265 static boolean_t	check_applicability(char *a_packageDir,
266 				char *a_pkgInst, char *a_rootPath,
267 				CAF_T a_flags);
268 static boolean_t	get_package_list(char ***r_pkgList, char **a_argv,
269 				char *a_categories, char **a_categoryList,
270 				int a_ignoreSignatures, PKG_ERR *a_err,
271 				ushort_t a_httpProxyPort, char *a_httpProxyName,
272 				keystore_handle_t a_keystore,
273 				char *a_keystoreFile, char *a_idsName,
274 				int *r_repeat);
275 static boolean_t	continue_installation(void);
276 static boolean_t	unpack_and_check_packages(char **a_pkgList,
277 				char *a_idsName, char *a_packageDir);
278 /*
279  * *****************************************************************************
280  * global external (public) functions
281  * *****************************************************************************
282  */
283 
284 /*
285  * Name:	main
286  * Description:	main entry point for pkgadd/pkgask
287  * Returns:	int
288  *   0        Successful completion
289  *   1        Fatal error.
290  *   2        Warning.
291  *   3        Interruption.
292  *   4        Administration.
293  *   5        Administration. Interaction is required. Do not use pkgadd -n.
294  * In addition, one of the following values may be added to the previous value
295  * as appropriate:
296  *  10       Reboot after installation of all packages.
297  *  20       Reboot after installation of this package.
298  * For example, "14" would indicate both "administration" and "reboot after
299  * installation of all packages".
300  */
301 
302 int
303 main(int argc, char **argv)
304 {
305 	PKG_ERR			*err = NULL;
306 	WebScheme		scheme = none;
307 	char			**category = NULL;
308 	char			*abiPtr;
309 	char			*altBinDir = (char *)NULL;
310 	char			*catg_arg = NULL;
311 	char			*device = NULL;		/* dev pkg stored on */
312 	char			*dwnld_dir = NULL;
313 	char			*keystore_file = NULL;
314 	char			*p;
315 	char			*q;
316 	char			*prog;
317 	char			*prog_full_name = NULL;
318 	char			*proxy = NULL;
319 	char			*spoolDir = NULL;	/* specified with -s */
320 	char			*uri = NULL;
321 	char			Rpath[PATH_MAX+1] = {'\0'};
322 	int			c;
323 	int			ignore_sig = 0;
324 	int			n;
325 	int			repeat;
326 	int			retries = NET_RETRIES_DEFAULT;
327 	int			timeout = NET_TIMEOUT_DEFAULT;
328 	keystore_handle_t	keystore = NULL;
329 	struct sigaction	nact;
330 	struct sigaction	oact;
331 	ushort_t		proxy_port = 0;
332 
333 	/* initialize locale environment */
334 
335 	(void) setlocale(LC_ALL, "");
336 	(void) textdomain(TEXT_DOMAIN);
337 
338 	/* initialize program name */
339 
340 	prog_full_name = argv[0];
341 	prog = set_prog_name(argv[0]);
342 
343 	/* tell spmi zones interface how to access package output functions */
344 
345 	z_set_output_functions(echo, echoDebug, progerr);
346 
347 	askflag = (strcmp(prog, "pkgask") == 0);
348 
349 	/* set sane umask */
350 
351 	(void) umask(0022);
352 
353 	/* tell quit which ckreturn function to call */
354 
355 	quitSetCkreturnFunc(&ckreturn);
356 
357 	/* initially no source "device" */
358 
359 	device = NULL;
360 
361 	/* reset npkgs (used as pkg remaining count in quit.c) */
362 
363 	npkgs = 0;
364 
365 	/* set default password prompt for encrypted packages */
366 
367 	set_passphrase_prompt(MSG_PASSPROMPT);
368 
369 	/* initialize security operations structures and libraries */
370 
371 	sec_init();
372 
373 	if (z_running_in_global_zone() && !enable_local_fs()) {
374 		progerr(ERR_CANNOT_ENABLE_LOCAL_FS);
375 	}
376 
377 	/*
378 	 * ********************************************************************
379 	 * parse command line options
380 	 * ********************************************************************
381 	 */
382 
383 	while ((c = getopt(argc, argv,
384 		"?Aa:b:B:Cc:D:d:GhIik:MnO:P:R:r:Ss:tV:vx:Y:zZ")) != EOF) {
385 		switch (c) {
386 
387 		/*
388 		 * Not a public interface: This disables attribute checking.
389 		 * It speeds up installation a little bit.
390 		 */
391 		case 'A':
392 			disableAttributes++;
393 			break;
394 
395 		/*
396 		 * Public interface: Define an installation administration
397 		 * file, admin, to be used in place of the default
398 		 * administration file.	 The token none overrides the use
399 		 * of any admin file, and thus forces interaction with the
400 		 * user. Unless a full path name is given, pkgadd first
401 		 * looks in the current working directory for the
402 		 * administration file.	 If the specified administration
403 		 * file is not in the current working directory, pkgadd
404 		 * looks in the /var/sadm/install/admin directory for the
405 		 * administration file.
406 		 */
407 		case 'a':
408 			admnfile = flex_device(optarg, 0);
409 			break;
410 
411 		/*
412 		 * Not a public interface: control block size given to
413 		 * pkginstall - block size used in read()/write() loop;
414 		 * default is st_blksize from stat() of source file.
415 		 */
416 		case 'B':
417 			if (optarg[0] == '-') {
418 				usage();
419 				quit(1);
420 			}
421 			rw_block_size = optarg;
422 			break;
423 
424 		/*
425 		 * Not a public interface:  location where package executables
426 		 * can be found - default is /usr/sadm/install/bin.
427 		 */
428 		case 'b':
429 			if (optarg[0] == '-') {
430 				usage();
431 				quit(1);
432 			}
433 			if (!path_valid(optarg)) {
434 				progerr(ERR_PATH, optarg);
435 				quit(1);
436 			}
437 			if (isdir(optarg) != 0) {
438 				p = strerror(errno);
439 				progerr(ERR_CANNOT_USE_DIR, optarg, p);
440 				quit(1);
441 			}
442 			altBinDir = optarg;
443 			break;
444 
445 		/*
446 		 * Not a public interface: This disables checksum tests on
447 		 * the source files. It speeds up installation a little bit.
448 		 */
449 		case 'C':
450 			disableChecksum++;
451 			break;
452 
453 		/*
454 		 * Not a public interface: This allows designation of a
455 		 * continuation file. It is the same format as a dryrun file
456 		 * but it is used to take up where the dryrun left off.
457 		 */
458 		case 'c':
459 			pkgcontsrc = flex_device(optarg, 0);
460 			break;
461 
462 		/*
463 		 * Not a public interface: This allows designation of a
464 		 * dryrun file. This pkgadd will create dryrun files
465 		 * in the directory provided.
466 		 */
467 		case 'D':
468 			if (optarg[0] == '-') {
469 				usage();
470 				quit(1);
471 			}
472 			pkgdrtarg = flex_device(optarg, 0);
473 			break;
474 
475 		/*
476 		 * Public interface: Install or copy a package from
477 		 * device. device can be a full path name to a directory
478 		 * or the identifiers for tape, floppy disk, or removable
479 		 * disk - for example, /var/tmp or /floppy/floppy_name.
480 		 * It can also be a device alias - for example,
481 		 * /floppy/floppy0, or a datastream created by pkgtrans.
482 		 */
483 		case 'd':
484 			if (optarg[0] == '-') {
485 				usage();
486 				quit(1);
487 			}
488 			if (!path_valid(optarg)) {
489 				progerr(ERR_PATH, optarg);
490 				quit(1);
491 				/* NOTREACHED */
492 			}
493 
494 			if (strncmp(optarg, HTTP, 7) == 0) {
495 				scheme = web_http;
496 			} else if (strncmp(optarg, HTTPS, 8) == 0) {
497 				scheme = web_https;
498 			}
499 
500 			if (scheme == web_https || scheme == web_http) {
501 				uri = optarg;
502 				if ((device = malloc(PATH_MAX)) == NULL) {
503 					progerr(ERR_MEM);
504 					exit(1);
505 				}
506 				(void) memset(device, '\0', PATH_MAX);
507 			} else {
508 				device = flex_device(optarg, 1);
509 			}
510 			break;
511 
512 		/*
513 		 * Public interface: install package in global zone only.
514 		 */
515 		case 'G':
516 			globalZoneOnly = B_TRUE;
517 			break;
518 
519 		/*
520 		 * Not a public interface: Enable hollow package support. When
521 		 * specified, for any package that has SUNW_PKG_HOLLOW=true:
522 		 *  Do not calculate and verify package size against target.
523 		 *  Do not run any package procedure or class action scripts.
524 		 *  Do not create any target directories.
525 		 *  Do not perform any script locking.
526 		 *  Do not install any components of any package.
527 		 *  Do not output any status or database update messages.
528 		 */
529 		case 'h':
530 			set_depend_pkginfo_DB(B_TRUE);
531 			break;
532 
533 		/*
534 		 * Not a public interface: Informs scripts that this is
535 		 * an initial install by setting the environment parameter
536 		 * PKG_INIT_INSTALL=TRUE for all scripts. They may use it as
537 		 * they see fit, safe in the knowledge that the target
538 		 * filesystem is tabula rasa.
539 		 */
540 		case 'I':
541 			init_install++;
542 			break;
543 
544 		/*
545 		 * Not a public interface: ignore signatures.
546 		 */
547 		case 'i':
548 			ignore_sig++;
549 			break;
550 
551 		/*
552 		 * Public interface: Use keystore as the location from which to
553 		 * get trusted certificate authority certificates when verifying
554 		 * digital signatures found in packages. If no keystore is
555 		 * specified, then the default keystore locations are searched
556 		 * for valid trusted certificates.
557 		 */
558 		case 'k':
559 			if (!path_valid(optarg)) {
560 				progerr(ERR_PATH, optarg);
561 				quit(1);
562 				/* NOTREACHED */
563 			}
564 			keystore_file = optarg;
565 			break;
566 
567 		/*
568 		 * Public interface: Instruct pkgadd not to use the
569 		 * $root_path/etc/vfstab file for determining the client's
570 		 * mount points. This option assumes the mount points are
571 		 * correct on the server and it behaves consistently with
572 		 * Solaris 2.5 and earlier releases.
573 		 */
574 		case 'M':
575 			no_map_client = 1;
576 			break;
577 
578 		/*
579 		 * Not a public interface: the -O option allows the behavior
580 		 * of the package tools to be modified. Recognized options:
581 		 * -> debug
582 		 * ---> enable debugging output
583 		 * -> addzonename
584 		 * ---> add zone name to appropriate messages
585 		 * -> nozones
586 		 * ---> act as though in global zone with no non-global zones
587 		 * -> inherited-filesystems
588 		 * ---> add specified file system to list of file systems
589 		 * ---> that are inherited from the global zone
590 		 * -> enable-hollow-package-support
591 		 * ---> Enable hollow package support. When specified, for any
592 		 * ---> package that has SUNW_PKG_HOLLOW=true:
593 		 * ---> Do not calculate and verify package size against target
594 		 * ---> Do not run any package procedure or class action scripts
595 		 * ---> Do not create any target directories
596 		 * ---> Do not perform any script locking
597 		 * ---> Do not install any components of any package
598 		 * ---> Do not output any status or database update messages
599 		 * -> zonelist="<names...>"
600 		 * ---> add package to space/colon separated list of zones only
601 		 */
602 
603 		case 'O':
604 			for (p = strtok(optarg, ","); p != (char *)NULL;
605 				p = strtok(NULL, ",")) {
606 
607 				if (strcmp(p, "debug") == 0) {
608 					/* set debug flag/enable debug output */
609 					debugFlag = B_TRUE;
610 					(void) echoDebugSetFlag(debugFlag);
611 
612 					/* debug info on arguments to pkgadd */
613 					for (n = 0; n < argc && argv[n]; n++) {
614 						echoDebug(DBG_ARG, n, argv[n]);
615 					}
616 
617 					continue;
618 				}
619 
620 				if (strcmp(p,
621 					"enable-hollow-package-support") == 0) {
622 					set_depend_pkginfo_DB(B_TRUE);
623 					continue;
624 				}
625 
626 				if (strncmp(p, INHERITFS, INHERITFS_LEN) == 0) {
627 					if (z_add_inherited_file_system(
628 						p+INHERITFS_LEN) == B_FALSE) {
629 						progerr(ERR_NOSUCH_INHERITED,
630 							p+INHERITFS_LEN);
631 						quit(1);
632 						/* NOTREACHED */
633 					}
634 					continue;
635 				}
636 
637 				if (strcmp(p, "addzonename") == 0) {
638 					quitSetZoneName(z_get_zonename());
639 					continue;
640 				}
641 
642 				if (strcmp(p, "nozones") == 0) {
643 					noZones = B_TRUE;
644 					continue;
645 				}
646 
647 				/*
648 				 * Private interface: package is being
649 				 * installed as a patch package.
650 				 */
651 
652 				if (strcmp(p, "patchPkgInstall") == 0) {
653 					setPatchUpdate();
654 					continue;
655 				}
656 
657 				/*
658 				 * If this is a patch removal
659 				 * then call setPatchUpdate() and set
660 				 * patchPkgRemoval flag.
661 				 */
662 				if (strcmp(p, "patchPkgRemoval") == 0) {
663 					setPatchUpdate();
664 					patchPkgRemoval = B_TRUE;
665 					continue;
666 				}
667 
668 				if (strncmp(p, "zonelist=", 9) == 0) {
669 					/*
670 					 * If colons used as separators,
671 					 * convert to spaces.
672 					 */
673 					q = p + 9;
674 					while (*q != '\0') {
675 						if (*q == ':') {
676 							*q = ' ';
677 						}
678 						q++;
679 					}
680 
681 					if (z_set_zone_spec(p + 9) == -1)
682 						quit(1);
683 					usedZoneList = B_TRUE;
684 					continue;
685 				}
686 
687 				progerr(ERR_INVALID_O_OPTION, p);
688 				continue;
689 			}
690 			break;
691 
692 		/*
693 		 * Public interface: installation occurs in
694 		 * non-interactive mode.  Suppress output of the list of
695 		 * installed files. The default mode is interactive.
696 		 */
697 		case 'n':
698 			nointeract++;
699 			(void) echoSetFlag(B_FALSE);
700 			break;
701 
702 		/*
703 		 * Public interface: Password to use to decrypt keystore
704 		 * specified with -k, if required. See PASS PHRASE
705 		 * ARGUMENTS for more information about the format of this
706 		 * option's argument.
707 		 */
708 		case 'P':
709 			if (optarg[0] == '-') {
710 				usage();
711 				quit(1);
712 			}
713 			set_passphrase_passarg(optarg);
714 			if (ci_strneq(optarg, "pass:", 5)) {
715 				/*
716 				 * passwords on the command line are highly
717 				 * insecure.  complain.
718 				 */
719 				logerr(PASSWD_CMDLINE, "pass:<pass>");
720 			}
721 			break;
722 
723 		/*
724 		 * Public interface: Define the full path name of a
725 		 * directory to use as the root_path.  All files,
726 		 * including package system information files, are
727 		 * relocated to a directory tree starting in the specified
728 		 * root_path. The root_path may be specified when
729 		 * installing to a client from a server (for example,
730 		 * /export/root/client1).
731 		 */
732 		case 'R':
733 			if (optarg[0] == '-') {
734 				usage();
735 				quit(1);
736 			}
737 			/* determine the real path specified */
738 
739 			n = resolvepath(optarg, Rpath, sizeof (Rpath)-1);
740 
741 			/* use supplied path if not resolvable */
742 
743 			if (n == -1) {
744 				(void) strlcpy(Rpath, optarg, sizeof (Rpath));
745 			} else {
746 				/* null terminate string */
747 				Rpath[n] = '\0';
748 			}
749 
750 			/* set the alternative root path */
751 
752 			if (!set_inst_root(Rpath)) {
753 				progerr(ERR_ROOT_CMD);
754 				exit(1);
755 			}
756 			break;
757 
758 		/*
759 		 * Public interface: Identify a file or directory which
760 		 * contains output from a previous pkgask(1M)
761 		 * session. This file supplies the interaction responses
762 		 * that would be requested by the package in interactive
763 		 * mode. response must be a full pathname.
764 		 */
765 		case 'r':
766 			if (optarg[0] == '-') {
767 				usage();
768 				quit(1);
769 			}
770 			respfile = flex_device(optarg, 2);
771 			if (isdir(respfile) == 0)
772 				respdir = respfile;
773 			break;
774 
775 		/*
776 		 * Not a public interface: suppress copyright notice being
777 		 * output during installation.
778 		 */
779 		case 'S':
780 			suppressCopyright++;
781 			break;
782 
783 		/*
784 		 * Public interface: Write the package into the directory
785 		 * spool instead of installing it. The default directory
786 		 * for spooled packages is /var/sadm/pkg.
787 		 */
788 		case 's':
789 			spoolDir = flex_device(optarg, 1);
790 			break;
791 
792 		/*
793 		 * Not a public interface: disable save spool area creation;
794 		 * suppress the creation and population of the package save
795 		 * spool area (var/sadm/pkg/PKG/save/pspool/PKG).
796 		 */
797 		case 't':
798 			disableSaveSpool++;
799 			break;
800 
801 		/*
802 		 * Public interface: Specify an alternative fs_file to map
803 		 * the client's file systems.  For example, used in
804 		 * situations where the $root_path/etc/vfstab file is
805 		 * non-existent or unreliable. Informs the pkginstall
806 		 * portion to mount up a client filesystem based upon the
807 		 * supplied vfstab-like file of stable format.
808 		 */
809 		case 'V':
810 			vfstab_file = flex_device(optarg, 2);
811 			no_map_client = 0;
812 			break;
813 
814 		/*
815 		 * Public interface: Trace all of the scripts that get
816 		 * executed by pkgadd, located in the pkginst/install
817 		 * directory. This option is used for debugging the
818 		 * procedural and non-procedural scripts
819 		 */
820 		case 'v':
821 			pkgverbose++;
822 			break;
823 
824 		/*
825 		 * Public interface: Specify a HTTP[S] proxy to use when
826 		 * downloading packages The format of proxy is host:port,
827 		 * where host is the hostname of the HTTP[S] proxy, and
828 		 * port is the port number associated with the proxy. This
829 		 * switch overrides all other methods of specifying a
830 		 * proxy. See ENVIRONMENT VARIABLES for more information
831 		 * on alternate methods of specifying a default proxy.
832 		 */
833 		case 'x':
834 			if (!path_valid(optarg)) {
835 				progerr(ERR_PATH, optarg);
836 				quit(1);
837 				/* NOTREACHED */
838 			}
839 			proxy = optarg;
840 			break;
841 
842 		/*
843 		 * Public interface: Install packages based on the value
844 		 * of the CATEGORY parameter stored in the package's
845 		 * pkginfo(4) file. All packages on the source medium
846 		 * whose CATEGORY matches one of the specified categories
847 		 * will be selected for installation or spooling. Install
848 		 * packages that contain the same CATEGORY as the one
849 		 * provided on the command line.
850 		 */
851 		case 'Y':
852 			if (optarg[0] == '-') {
853 				usage();
854 				quit(1);
855 			}
856 			catg_arg = strdup(optarg);
857 
858 			if ((category = get_categories(catg_arg)) == NULL) {
859 				progerr(ERR_CAT_INV, catg_arg);
860 				exit(1);
861 			} else if (is_not_valid_length(category)) {
862 				progerr(ERR_CAT_LNGTH);
863 				exit(1);
864 			}
865 			break;
866 
867 		/*
868 		 * Not a public interface: perform fresh install from
869 		 * package save spool area. When set, the package contents
870 		 * are installed from the package spool save area instead
871 		 * of from the package root area, so that the original
872 		 * source packages are not required to install the
873 		 * package. If the -h option is also specified and the
874 		 * package is hollow, then this option is ignored. When -z
875 		 * is specified:
876 		 *  - Editable files are installed from the package instance
877 		 *    save area.
878 		 *  - Volatile files are installed from the package instance
879 		 *    save area.
880 		 *  - Executable and data files are installed from the final
881 		 *    installed location as specified in the pkgmap file.
882 		 *  - Installation scripts are run from the package spool
883 		 *    save area.
884 		 */
885 		case 'z':
886 			saveSpoolInstall++;
887 			break;
888 
889 		/*
890 		 * unrecognized option
891 		 */
892 
893 		default:
894 			usage();
895 			return (1);
896 		}
897 	}
898 
899 	/*
900 	 * ********************************************************************
901 	 * validate command line options
902 	 * ********************************************************************
903 	 */
904 
905 	/* set "debug echo" flag according to setting of "-O debug" option */
906 
907 	(void) echoDebugSetFlag(debugFlag);
908 
909 	/* output entry debugging information */
910 
911 	if (z_running_in_global_zone()) {
912 		echoDebug(DBG_ENTRY_IN_GZ, prog_full_name);
913 	} else {
914 		echoDebug(DBG_ENTRY_IN_LZ, prog_full_name, getzoneid(),
915 			z_get_zonename());
916 	}
917 
918 	/*
919 	 * Later, it may be decided to pursue this ability to continue to an
920 	 * actual installation based only on the dryrun data. At this time,
921 	 * it is too risky.
922 	 */
923 
924 	if (pkgcontsrc && !pkgdrtarg) {
925 		progerr(ERR_NO_LIVE_MODE);
926 		usage();
927 		return (1);
928 	}
929 
930 	/* ignore -G option if not used in the global zone */
931 
932 	if (!z_running_in_global_zone()) {
933 		globalZoneOnly = B_FALSE;
934 	}
935 
936 	/* if zonelist used, must be in global zone */
937 
938 	if (usedZoneList && !z_running_in_global_zone()) {
939 		progerr(ERR_Z_USED_IN_NONGLOBAL_ZONE);
940 		return (1);
941 	}
942 
943 	/* -G and zonelist cannot be used together */
944 
945 	if (globalZoneOnly && usedZoneList) {
946 		progerr(ERR_GZ_USED_TOGETHER);
947 		usage();
948 		return (1);
949 	}
950 
951 	/* -s cannot be used with either -G or zonelist */
952 
953 	if (spoolDir != NULL) {
954 		if (globalZoneOnly) {
955 			progerr(ERR_SPOOLDIR_USED_WITH_G);
956 			usage();
957 			return (1);
958 		}
959 		if (usedZoneList) {
960 			progerr(ERR_SPOOLDIR_USED_WITH_Z);
961 			usage();
962 			return (1);
963 		}
964 		if (strcmp(spoolDir, "/var/sadm/pkg") == 0) {
965 			progerr(ERR_SPOOLDIR_CANNOT_BE_SYS, "/var/sadm/pkg");
966 			usage();
967 			return (1);
968 		}
969 	}
970 
971 	/* pkgask does not support the same options as pkgadd */
972 
973 	if (askflag && proxy) {
974 		progerr(ERR_PKGASK_AND_PROXY);
975 		usage();
976 		return (1);
977 	}
978 
979 	if (askflag && uri) {
980 		progerr(ERR_PKGASK_AND_URI);
981 		usage();
982 		return (1);
983 	}
984 
985 	if (askflag && keystore_file) {
986 		progerr(ERR_PKGASK_AND_KEYSTORE_FILE);
987 		usage();
988 		return (1);
989 	}
990 
991 	if (askflag && ignore_sig) {
992 		progerr(ERR_PKGASK_AND_IGNORE_SIG);
993 		usage();
994 		return (1);
995 	}
996 
997 	if (askflag && spoolDir) {
998 		progerr(ERR_PKGASK_AND_SPOOLDIR);
999 		usage();
1000 		return (1);
1001 	}
1002 
1003 	if (askflag && nointeract) {
1004 		progerr(ERR_PKGASK_AND_NOINTERACT);
1005 		usage();
1006 		return (1);
1007 	}
1008 
1009 	/* cannot use response file and web address together */
1010 
1011 	if (respfile && uri) {
1012 		progerr(ERR_RESPFILE_AND_URI);
1013 		usage();
1014 		return (1);
1015 	}
1016 
1017 	/* cannot use response file/not-interactive and spool-to directory */
1018 
1019 	if (spoolDir && nointeract) {
1020 		progerr(ERR_SPOOLDIR_AND_NOINTERACT);
1021 		usage();
1022 		return (1);
1023 	}
1024 
1025 	if (spoolDir && respfile) {
1026 		progerr(ERR_SPOOLDIR_AND_RESPFILE);
1027 		usage();
1028 		return (1);
1029 	}
1030 
1031 	if (usedZoneList) {
1032 		/* Verify supplied zone list valid for the target */
1033 		if (z_verify_zone_spec() == -1)
1034 			return (1);
1035 
1036 		/* -z zonelist=global is logically the same as -G */
1037 		if (z_global_only() && z_running_in_global_zone())
1038 			globalZoneOnly = B_TRUE;
1039 	}
1040 
1041 	/*
1042 	 * hook SIGINT and SIGHUP interrupts into quit.c's trap handler
1043 	 */
1044 
1045 	/* hold SIGINT/SIGHUP interrupts */
1046 
1047 	(void) sighold(SIGHUP);
1048 	(void) sighold(SIGINT);
1049 
1050 	/* connect quit.c:trap() to SIGINT */
1051 
1052 	nact.sa_handler = quitGetTrapHandler();
1053 	nact.sa_flags = SA_RESTART;
1054 	(void) sigemptyset(&nact.sa_mask);
1055 
1056 	(void) sigaction(SIGINT, &nact, &oact);
1057 
1058 	/* connect quit.c:trap() to SIGHUP */
1059 
1060 	nact.sa_handler = quitGetTrapHandler();
1061 	nact.sa_flags = SA_RESTART;
1062 	(void) sigemptyset(&nact.sa_mask);
1063 
1064 	(void) sigaction(SIGHUP, &nact, &oact);
1065 
1066 	/* release hold on signals */
1067 
1068 	(void) sigrelse(SIGHUP);
1069 	(void) sigrelse(SIGINT);
1070 
1071 	/*
1072 	 * This function is in the libadm library; it sets:
1073 	 * -> get_PKGLOC() = <install_root>/var/sadm/pkg
1074 	 * -> get_PKGOLD() = <install_root>/usr/options
1075 	 * -> get_PKGADM() = <install_root>/var/sadm/install
1076 	 * -> pkgdir = <install_root>/var/sadm/pkg
1077 	 * -> pkg_install_root = <install_root>
1078 	 * This controls operations of libadm functions such as:
1079 	 * -> pkginfofind, pkginfopen, fpkgparam, pkgparam, get_PKGLOC,
1080 	 * -> get_PKGOLD, get_PKGADM, get_install_root
1081 	 */
1082 
1083 	set_PKGpaths(get_inst_root());
1084 	echoDebug(DBG_PKGADD_PKGPATHS,
1085 		get_PKGLOC() ? get_PKGLOC() : "",
1086 		get_PKGADM() ? get_PKGADM() : "");
1087 
1088 	/*
1089 	 * This function is in the libinst library; it reads the specified
1090 	 * admin(4) file and, using fpkgparam(), sets the global "adm" structure
1091 	 * values to match what is in the specified admin file.
1092 	 */
1093 
1094 	echoDebug(DBG_PKGADD_ADMINFILE, admnfile ? admnfile : "");
1095 	setadminFile(admnfile);
1096 
1097 	/*
1098 	 * if running in the global zone, and non-global zones exist, then
1099 	 * enable hollow package support so that any packages that are marked
1100 	 * SUNW_PKG_HOLLOW=true will be correctly installed in non-global zones
1101 	 * when added directly in the global zone by the global zone admin.
1102 	 */
1103 
1104 	if (is_depend_pkginfo_DB()) {
1105 		echoDebug(DBG_PKGADD_HOLLOW_ENABLED);
1106 	} else if ((z_running_in_global_zone() == B_TRUE) &&
1107 		(z_non_global_zones_exist() == B_TRUE)) {
1108 		echoDebug(DBG_PKGADD_ENABLING_HOLLOW);
1109 		set_depend_pkginfo_DB(B_TRUE);
1110 	}
1111 
1112 	/* if no device and no url, get and validate default device */
1113 
1114 	if ((device == NULL) && (uri == NULL)) {
1115 		device = devattr("spool", "pathname");
1116 		if (device == NULL) {
1117 			progerr(ERR_NODEVICE);
1118 			quit(1);
1119 			/* NOTREACHED */
1120 		}
1121 	}
1122 
1123 	/* must be root if not directing results to spool directory */
1124 
1125 	if ((getuid() != 0) && (spoolDir == NULL)) {
1126 		progerr(ERR_NOT_ROOT, prog);
1127 		exit(1);
1128 	}
1129 
1130 	/*
1131 	 * process response file argument
1132 	 */
1133 
1134 	if (respfile) {
1135 		echoDebug(DBG_PKGADD_RESPFILE,
1136 			respfile, respdir ? respdir : "");
1137 
1138 		if (respfile[0] != '/') {
1139 			progerr(ERR_RSP_FILE_NOTFULLPATH, respfile);
1140 			quit(1);
1141 			/* NOTREACHED */
1142 		}
1143 		if (respdir == NULL) {
1144 			if (askflag) {
1145 				if (access(respfile, F_OK) == 0) {
1146 					progerr(ERR_NORESP, respfile);
1147 					quit(1);
1148 					/* NOTREACHED */
1149 				}
1150 			} else if (access(respfile, F_OK) != 0) {
1151 				progerr(ERR_ACCRESP, respfile);
1152 				quit(1);
1153 				/* NOTREACHED */
1154 			}
1155 		}
1156 	} else if (askflag) {
1157 		progerr(ERR_RSP_FILE_NOT_GIVEN);
1158 		usage();
1159 		quit(1);
1160 		/* NOTREACHED */
1161 	}
1162 
1163 	/* establish temporary directory to use */
1164 
1165 	if ((tmpdir = getenv("TMPDIR")) == NULL) {
1166 		/* use default - no override specified */
1167 		tmpdir = P_tmpdir;
1168 	}
1169 
1170 	echoDebug(DBG_PKGADD_TMPDIR, tmpdir);
1171 
1172 	/*
1173 	 * setup and prepare secure package operations
1174 	 */
1175 
1176 	/* initialize error object used by security functions */
1177 
1178 	err = pkgerr_new();
1179 
1180 	/* validate keystore file */
1181 
1182 	if (!check_keystore_admin(&keystore_file)) {
1183 		progerr(ERR_ADM_KEYSTORE);
1184 		quit(1);
1185 		/* NOTREACHED */
1186 	}
1187 
1188 	/* if uri provided, establish session */
1189 
1190 	if (uri != NULL) {
1191 		boolean_t	b;
1192 		int		len;
1193 		char		*bname = (char *)NULL;
1194 
1195 		set_web_install();
1196 
1197 		if (!get_proxy_port(err, &proxy, &proxy_port)) {
1198 			pkgerr(err);
1199 			quit(1);
1200 			/* NOTREACHED */
1201 		}
1202 
1203 		if (proxy == NULL) {
1204 			if (!get_proxy_port_admin(&proxy, &proxy_port)) {
1205 				progerr(ERR_ADM_PROXY);
1206 				quit(1);
1207 				/* NOTREACHED */
1208 			}
1209 		}
1210 
1211 		if ((retries = web_ck_retries()) == 0) {
1212 			pkgerr(err);
1213 			quit(1);
1214 			/* NOTREACHED */
1215 		}
1216 
1217 		if ((timeout = web_ck_timeout()) == 0) {
1218 			pkgerr(err);
1219 			quit(1);
1220 			/* NOTREACHED */
1221 		}
1222 
1223 		/* create temporary directory */
1224 
1225 		b = setup_temporary_directory(&dwnld_dir, tmpdir, "dwnld");
1226 		if (b != B_TRUE) {
1227 			progerr(ERR_DWNLDTEMPDIR, tmpdir, strerror(errno));
1228 			quit(1);
1229 			/* NOTREACHED */
1230 		}
1231 		canonize_slashes(dwnld_dir);
1232 
1233 		/* register with quit() so directory is removed on exit */
1234 
1235 		quitSetDwnldTmpdir(dwnld_dir);	/* DO NOT FREE() */
1236 
1237 		/* open keystore if this is a secure download */
1238 		if (scheme == web_https) {
1239 			if (open_keystore(err, keystore_file,
1240 			    get_prog_name(),  pkg_passphrase_cb,
1241 			    KEYSTORE_DFLT_FLAGS, &keystore) != 0) {
1242 				pkgerr(err);
1243 				web_cleanup();
1244 				quit(1);
1245 				/* NOTREACHED */
1246 			}
1247 		}
1248 
1249 		if (!web_session_control(err, uri, dwnld_dir, keystore, proxy,
1250 			proxy_port, retries, timeout, nointeract, &bname)) {
1251 			pkgerr(err);
1252 			web_cleanup();
1253 			quit(1);
1254 			/* NOTREACHED */
1255 		}
1256 
1257 		/*
1258 		 * reset device to point to newly-downloaded file; note
1259 		 * when (scheme == web_https || scheme == web_http) that
1260 		 * device gets preloaded with a pointer to PATH_MAX bytes
1261 		 * allocated via malloc().
1262 		 */
1263 
1264 		len = snprintf(device, PATH_MAX, "%s/%s", dwnld_dir, bname);
1265 		if ((len < 0) || (len >= PATH_MAX)) {
1266 			progerr(ERR_DIR_CONST, tmpdir);
1267 			quit(1);
1268 			/* NOTREACHED */
1269 		}
1270 	}
1271 
1272 	/*
1273 	 * See if user wants this to be handled as an old style pkg.
1274 	 * NOTE : the ``exception_pkg()'' stuff is to be used only
1275 	 * through on495. This function comes out for on1095. See
1276 	 * PSARC 1993-546. -- JST
1277 	 */
1278 
1279 	if (getenv("NONABI_SCRIPTS") != NULL) {
1280 		old_pkg = 1;
1281 	}
1282 
1283 	/*
1284 	 * See if the user wants to process symlinks consistent with
1285 	 * the old behavior.
1286 	 */
1287 
1288 	if (getenv("PKG_NONABI_SYMLINKS") != NULL) {
1289 		old_symlinks = 1;
1290 	}
1291 
1292 	/*
1293 	 * See if the user wants the package name length restricted.
1294 	 */
1295 
1296 	abiPtr = getenv("PKG_ABI_NAMELENGTH");
1297 	if (abiPtr && strncasecmp(abiPtr, "TRUE", 4) == 0) {
1298 		ABI_namelength = 1;
1299 	}
1300 
1301 	/*
1302 	 * validate the package source device - return pkgdev info that
1303 	 * describes the package source device.
1304 	 */
1305 
1306 	if (devtype(device, &pkgdev)) {
1307 		progerr(ERR_BAD_DEVICE, device);
1308 		quit(1);
1309 		/* NOTREACHED */
1310 	}
1311 
1312 	/*
1313 	 * If writing the packages into a spool directory instead of
1314 	 * installing the packages, open the package datastream and
1315 	 * invoke pkgtrans to perform the conversion and exit.
1316 	 */
1317 
1318 	if (spoolDir != (char *)NULL) {
1319 		boolean_t	b;
1320 		int		n;
1321 
1322 		echoDebug(DBG_INSTALLING_TO_SPOOL, spoolDir);
1323 
1324 		b = open_package_datastream(argc, argv, spoolDir, device,
1325 						&repeat, &ids_name, tmpdir,
1326 						&pkgdev, optind);
1327 
1328 		quitSetIdsName(ids_name);
1329 
1330 		if (b != B_TRUE) {
1331 			progerr(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1332 			quit(1);
1333 		}
1334 
1335 		n = pkgtrans(device, spoolDir, &argv[optind],
1336 				0, NULL, NULL);
1337 		quit(n);
1338 		/* NOTREACHED */
1339 	}
1340 
1341 	/*
1342 	 * error if there are packages on the command line and a category
1343 	 * was specified
1344 	 */
1345 
1346 	if ((optind < argc) && (catg_arg != NULL)) {
1347 		progerr(ERR_PKGS_AND_CAT_PKGADD);
1348 		usage();
1349 		quit(1);
1350 		/* NOTREACHED */
1351 	}
1352 
1353 	/*
1354 	 * ********************************************************************
1355 	 * main package processing "loop"
1356 	 * ********************************************************************
1357 	 */
1358 
1359 	ids_name = NULL;
1360 	quitSetIdsName(ids_name);
1361 
1362 	for (;;) {
1363 		boolean_t	b;
1364 		char		**pkglist;	/* points to array of pkgs */
1365 
1366 		/*
1367 		 * open next package data stream
1368 		 */
1369 
1370 		b = open_package_datastream(argc, argv, spoolDir, device,
1371 						&repeat, &ids_name, tmpdir,
1372 						&pkgdev, optind);
1373 
1374 		quitSetIdsName(ids_name);
1375 
1376 		if (b == B_FALSE) {
1377 			echoDebug(ERR_CANNOT_OPEN_PKG_STREAM, PSTR(device));
1378 			continue;
1379 		}
1380 
1381 		/*
1382 		 * package source data stream open - get the package list
1383 		 */
1384 
1385 		b = get_package_list(&pkglist, argv, catg_arg, category,
1386 			ignore_sig, err, proxy_port, proxy, keystore,
1387 			keystore_file, ids_name, &repeat);
1388 
1389 		if (b == B_FALSE) {
1390 			char	path[PATH_MAX];
1391 
1392 			echoDebug(DBG_CANNOT_GET_PKGLIST);
1393 
1394 			/* check for existence of pre-SVR4 package */
1395 			(void) snprintf(path, sizeof (path),
1396 				"%s/install/INSTALL", pkgdev.dirname);
1397 			if (access(path, F_OK) == 0) {
1398 				pkginst = ((optind < argc) ?
1399 					argv[optind++] : NULL);
1400 				ckreturn(presvr4(&pkginst, nointeract));
1401 				if (repeat || (optind < argc)) {
1402 					continue;
1403 				}
1404 				quit(0);
1405 			}
1406 			progerr(ERR_NOPKGS, pkgdev.dirname);
1407 			quit(1);
1408 			/* NOTREACHED */
1409 		}
1410 
1411 		/*
1412 		 * count the number of packages to install
1413 		 * NOTE: npkgs is a global variable that is referenced by quit.c
1414 		 * when error messages are generated - it is referenced directly
1415 		 * by the other functions called below...
1416 		 */
1417 
1418 		for (npkgs = 0; pkglist[npkgs] != (char *)NULL; /* void */) {
1419 			echoDebug(DBG_PKG_SELECTED, npkgs, pkglist[npkgs]);
1420 			npkgs++;
1421 		}
1422 
1423 		/* output number of packages to be added */
1424 
1425 		echoDebug(DBG_NUM_PKGS_TO_ADD, npkgs);
1426 
1427 		/*
1428 		 * if pkgask and response container is a file (not a directory),
1429 		 * and there is more than one package to install, then it is an
1430 		 * error - too many packages to install when response container
1431 		 * is a file.
1432 		 */
1433 
1434 		if ((askflag != 0) && (respdir == (char *)NULL) &&
1435 			(npkgs > 1)) {
1436 			progerr(ERR_TOO_MANY_PKGS);
1437 			quit(1);
1438 			/* NOTREACHED */
1439 		}
1440 
1441 		/*
1442 		 * package list generated - add packages
1443 		 */
1444 
1445 		b = add_packages(pkglist, uri, ids_name, repeat,
1446 					altBinDir, device, noZones);
1447 
1448 		/*
1449 		 * close open input data stream (source package) if left open.
1450 		 */
1451 
1452 		if (ids_name) {
1453 			echoDebug(DBG_CLOSING_STREAM, ids_name,
1454 					PSTR(pkgdev.dirname));
1455 			(void) ds_close(1);
1456 			rrmdir(pkgdev.dirname);
1457 			ids_name = NULL;
1458 			quitSetIdsName(ids_name);
1459 		}
1460 
1461 		/*
1462 		 * continue with next sequence of packages if continue set
1463 		 */
1464 
1465 		if (b == B_TRUE) {
1466 			continue;
1467 		}
1468 
1469 		/*
1470 		 * not continuing - quit with 0 exit code
1471 		 */
1472 
1473 		quit(0);
1474 		/* NOTREACHED */
1475 	}
1476 
1477 	/* NOTREACHED */
1478 }
1479 
1480 /*
1481  * *****************************************************************************
1482  * static internal (private) functions
1483  * *****************************************************************************
1484  */
1485 
1486 /*
1487  * Name:	pkgZoneCheckInstall
1488  * Description:	Invoke pkginstall in a specified zone to perform a preinstall
1489  *		check of the a single package in the specified zone
1490  * Arguments:	a_zoneName - pointer to string representing the name of the
1491  *			zone to check install the package in.
1492  *		a_inheritedPkgDirs - pointer to array of strings, each one
1493  *			representing the non-global zones full path of a
1494  *			directory that is inherited from the global zone.
1495  *		a_zoneState - current state of the zone; must be mounted or
1496  *			running.
1497  *		a_idsName - pointer to string representing the data stream
1498  *			device (input data stream) containing the package to
1499  *			be check installed.
1500  *		a_altBinDir - pointer to string representing an alternative
1501  *			binary location directory to pass to pkginstall.
1502  *			If this is == NULL no alternative binary location is
1503  *			passed to pkginstall.
1504  *		a_adminFile - pointer to string representing the admin
1505  *			file to pass to pkginstall when installing the package.
1506  *			If this is == NULL no admin file is given to pkginstall.
1507  *		a_stdoutPath - pointer to string representing the local path
1508  *			into which all output written by pkginstall to stdout
1509  *			is stored.
1510  *			If this is == NULL stdout is redirected to /dev/null
1511  * Returns:	int	(see ckreturn() function for details)
1512  *		0 - success
1513  *		1 - package operation failed (fatal error)
1514  *		2 - non-fatal error (warning)
1515  *		3 - user selected quit (operation interrupted)
1516  *		4 - admin settings prevented operation
1517  *		5 - interaction required and -n (non-interactive) specified
1518  *		"10" will be added to indicate "immediate reboot required"
1519  *		"20" will be added to indicate "reboot after install required"
1520  */
1521 
1522 static int
1523 pkgZoneCheckInstall(char *a_zoneName, char **a_inheritedPkgDirs,
1524 	zone_state_t a_zoneState, char *a_idsName, char *a_altBinDir,
1525 	char *a_adminFile, char *a_stdoutPath)
1526 {
1527 	char	*arg[MAXARGS];
1528 	char	*p;
1529 	char	adminfd_path[PATH_MAX];
1530 	char	path[PATH_MAX];
1531 	char	pkgstreamfd_path[PATH_MAX];
1532 	int	fds[MAX_FDS];
1533 	int	maxfds;
1534 	int	n;
1535 	int	nargs;
1536 
1537 	/* entry assertions */
1538 
1539 	assert(a_zoneName != (char *)NULL);
1540 	assert(*a_zoneName != '\0');
1541 
1542 	/* entry debugging info */
1543 
1544 	echoDebug(DBG_PKGZONECHECKINSTALL_ENTRY);
1545 	echoDebug(DBG_PKGZONECHECKINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1546 		PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1547 		a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "/",
1548 		PSTR(a_idsName), PSTR(a_adminFile), PSTR(a_stdoutPath));
1549 
1550 	/* generate full path to 'phatinstall' to run in zone */
1551 
1552 	(void) snprintf(path, sizeof (path), "%s/pkginstall",
1553 			"/usr/sadm/install/bin");
1554 
1555 	/* start at first file descriptor */
1556 
1557 	maxfds = 0;
1558 
1559 	/*
1560 	 * generate argument list for call to pkginstall
1561 	 */
1562 
1563 	/* start at argument 0 */
1564 
1565 	nargs = 0;
1566 
1567 	/* first argument is always: full path to executable */
1568 
1569 	arg[nargs++] = path;
1570 
1571 	/*
1572 	 * second argument is always: pass -O debug to pkginstall: debug mode
1573 	 */
1574 	if (debugFlag == B_TRUE) {
1575 		arg[nargs++] = "-O";
1576 		arg[nargs++] = "debug";
1577 	}
1578 
1579 	/* pkgadd -G: pass -G to pkginstall */
1580 
1581 	if (globalZoneOnly == B_TRUE) {
1582 		arg[nargs++] = "-G";
1583 	}
1584 
1585 	/* pkgadd -b dir: pass -b to pkginstall */
1586 
1587 	if (a_altBinDir != (char *)NULL) {
1588 		arg[nargs++] = "-b";
1589 		arg[nargs++] = a_altBinDir;
1590 	}
1591 
1592 	/* pkgadd -C: pass -C to pkginstall: disable checksum */
1593 
1594 	if (disableChecksum) {
1595 		arg[nargs++] = "-C";
1596 	}
1597 
1598 	/* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1599 
1600 	if (disableAttributes) {
1601 		arg[nargs++] = "-A";
1602 	}
1603 
1604 	/*
1605 	 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1606 	 * pkg requiring operator interaction during a procedure script
1607 	 * (common before on1093)
1608 	 */
1609 
1610 	if (old_pkg) {
1611 		arg[nargs++] = "-o";
1612 	}
1613 
1614 	/*
1615 	 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1616 	 * symlinks consistent with old behavior
1617 	 */
1618 
1619 	if (old_symlinks) {
1620 		arg[nargs++] = "-y";
1621 	}
1622 
1623 	/*
1624 	 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1625 	 * package name length to be restricted
1626 	 */
1627 
1628 	if (ABI_namelength) {
1629 		arg[nargs++] = "-e";
1630 	}
1631 
1632 	/* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1633 
1634 	arg[nargs++] = "-S";
1635 
1636 	/* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1637 
1638 	arg[nargs++] = "-M";
1639 
1640 	/* pkgadd -v: pass -v to pkginstall: never trace scripts */
1641 
1642 	/* if running pkgask, pass -i to pkginstall: running pkgask */
1643 
1644 	if (askflag) {
1645 		return (0);
1646 	}
1647 
1648 	/* pass "-O enable-hollow-package-support" */
1649 
1650 	if (is_depend_pkginfo_DB()) {
1651 		arg[nargs++] = "-O";
1652 		arg[nargs++] = "enable-hollow-package-support";
1653 	}
1654 
1655 	/* check is always in non-interactive mode */
1656 
1657 	arg[nargs++] = "-n";
1658 
1659 	/* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1660 
1661 	if (a_adminFile) {
1662 		int fd;
1663 		fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1664 		if (fd < 0) {
1665 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1666 				errno, strerror(errno));
1667 			return (1);
1668 		}
1669 		(void) snprintf(adminfd_path, sizeof (adminfd_path),
1670 			"/proc/self/fd/%d", fd);
1671 		fds[maxfds++] = fd;
1672 		arg[nargs++] = "-a";
1673 		arg[nargs++] = adminfd_path;
1674 	}
1675 
1676 	/* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1677 
1678 	if (a_zoneState == ZONE_STATE_MOUNTED) {
1679 		arg[nargs++] = "-R";
1680 		arg[nargs++] = "/a";
1681 	}
1682 
1683 	/* pass -N to pkginstall: program name to report */
1684 
1685 	arg[nargs++] = "-N";
1686 	arg[nargs++] = get_prog_name();
1687 
1688 	/* pass "-O preinstallcheck" */
1689 
1690 	arg[nargs++] = "-O";
1691 	arg[nargs++] = "preinstallcheck";
1692 
1693 	/* add "-O addzonename" */
1694 
1695 	arg[nargs++] = "-O";
1696 	arg[nargs++] = "addzonename";
1697 
1698 	if (isPatchUpdate()) {
1699 		if (patchPkgRemoval == B_TRUE) {
1700 			arg[nargs++] = "-O";
1701 			arg[nargs++] = "patchPkgRemoval";
1702 		} else {
1703 			arg[nargs++] = "-O";
1704 			arg[nargs++] = "patchPkgInstall";
1705 		}
1706 	}
1707 
1708 	/* add all inherited file systems */
1709 
1710 	if (a_inheritedPkgDirs != (char **)NULL) {
1711 		for (n = 0; a_inheritedPkgDirs[n] != (char *)NULL; n++) {
1712 			char	ifs[MAXPATHLEN+22];
1713 			(void) snprintf(ifs, sizeof (ifs),
1714 				"inherited-filesystem=%s",
1715 				a_inheritedPkgDirs[n]);
1716 			arg[nargs++] = "-O";
1717 			arg[nargs++] = strdup(ifs);
1718 		}
1719 	}
1720 
1721 	/*
1722 	 * add parent zone info/type
1723 	 */
1724 
1725 	p = z_get_zonename();
1726 	if ((p != NULL) && (*p != '\0')) {
1727 			char	zn[MAXPATHLEN];
1728 			(void) snprintf(zn, sizeof (zn),
1729 				"parent-zone-name=%s", p);
1730 			arg[nargs++] = "-O";
1731 			arg[nargs++] = strdup(zn);
1732 	}
1733 
1734 	/* current zone type */
1735 
1736 	arg[nargs++] = "-O";
1737 	if (z_running_in_global_zone() == B_TRUE) {
1738 			char	zn[MAXPATHLEN];
1739 			(void) snprintf(zn, sizeof (zn),
1740 				"parent-zone-type=%s",
1741 				TAG_VALUE_GLOBAL_ZONE);
1742 			arg[nargs++] = strdup(zn);
1743 	} else {
1744 			char	zn[MAXPATHLEN];
1745 			(void) snprintf(zn, sizeof (zn),
1746 				"parent-zone-type=%s",
1747 				TAG_VALUE_NONGLOBAL_ZONE);
1748 			arg[nargs++] = strdup(zn);
1749 	}
1750 
1751 	/* add in the package stream file */
1752 
1753 	if (a_idsName != NULL) {
1754 		int fd;
1755 		fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1756 		if (fd < 0) {
1757 			progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1758 				pkginst, strerror(errno));
1759 			quit(1);
1760 		}
1761 		(void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1762 			"/proc/self/fd/%d", fd);
1763 		fds[maxfds++] = fd;
1764 		arg[nargs++] = pkgstreamfd_path;
1765 	} else {
1766 		progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1767 		quit(1);
1768 	}
1769 
1770 	/* add package instance name */
1771 
1772 	arg[nargs++] = pkginst;
1773 
1774 	/* terminate the argument list */
1775 
1776 	arg[nargs++] = NULL;
1777 
1778 	/*
1779 	 * run the appropriate pkginstall command in the specified zone
1780 	 */
1781 
1782 	if (debugFlag == B_TRUE) {
1783 		echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
1784 		for (n = 0; arg[n]; n++) {
1785 			echoDebug(DBG_ARG, n, arg[n]);
1786 		}
1787 	}
1788 
1789 	/* terminate file descriptor list */
1790 
1791 	fds[maxfds] = -1;
1792 
1793 	/* exec command in zone */
1794 
1795 	n = z_zone_exec(a_zoneName, path, arg, a_stdoutPath, (char *)NULL, fds);
1796 
1797 	echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n,
1798 			PSTR(a_stdoutPath));
1799 
1800 	/*
1801 	 * close any files that were opened for use by the
1802 	 * /proc/self/fd interface so they could be passed to programs
1803 	 * via the z_zone_exec() interface
1804 	 */
1805 
1806 	for (; maxfds > 0; maxfds--) {
1807 		(void) close(fds[maxfds-1]);
1808 	}
1809 
1810 	/* return results of pkginstall in zone execution */
1811 
1812 	return (n);
1813 }
1814 
1815 /*
1816  * Name:	pkgZoneInstall
1817  * Description:	Invoke pkginstall in a specified zone to perform an install
1818  *		of a single package in the specified zone
1819  * Arguments:	a_zoneName - pointer to string representing the name of the
1820  *			zone to install the package in.
1821  *		a_inheritedPkgDirs - pointer to array of strings, each one
1822  *			representing the non-global zones full path of a
1823  *			directory that is inherited from the global zone.
1824  *		a_zoneState - current state of the zone; must be mounted or
1825  *			running.
1826  *		a_idsName - pointer to string representing the data stream
1827  *			device (input data stream) containing the package to
1828  *			be installed.
1829  *		a_altBinDir - pointer to string representing an alternative
1830  *			binary location directory to pass to pkginstall.
1831  *			If this is == NULL no alternative binary location is
1832  *			passed to pkginstall.
1833  *		a_adminFile - pointer to string representing the admin
1834  *			file to pass to pkginstall when installing the package.
1835  *			If this is == NULL no admin file is given to pkginstall.
1836  *		a_stdoutPath - pointer to string representing the local path
1837  *			into which all output written by pkginstall to stdout
1838  *			is stored.
1839  *			If this is == NULL stdout is redirected to /dev/null
1840  * Returns:	int	(see ckreturn() function for details)
1841  *		0 - success
1842  *		1 - package operation failed (fatal error)
1843  *		2 - non-fatal error (warning)
1844  *		3 - user selected quit (operation interrupted)
1845  *		4 - admin settings prevented operation
1846  *		5 - interaction required and -n (non-interactive) specified
1847  *		"10" will be added to indicate "immediate reboot required"
1848  *		"20" will be added to indicate "reboot after install required"
1849  */
1850 
1851 static int
1852 pkgZoneInstall(char *a_zoneName, char **a_inheritedPkgDirs,
1853     zone_state_t a_zoneState, char *a_idsName, char *a_altBinDir,
1854     char *a_adminFile)
1855 {
1856 	char	*arg[MAXARGS];
1857 	char	*p;
1858 	char	adminfd_path[PATH_MAX];
1859 	char	path[PATH_MAX];
1860 	char	pkgstreamfd_path[PATH_MAX];
1861 	char	respfilefd_path[PATH_MAX];
1862 	int	fds[MAX_FDS];
1863 	int	maxfds;
1864 	int	n;
1865 	int	nargs;
1866 
1867 	/* entry assertions */
1868 
1869 	assert(a_zoneName != (char *)NULL);
1870 	assert(*a_zoneName != '\0');
1871 
1872 	/* entry debugging info */
1873 
1874 	echoDebug(DBG_PKGZONEINSTALL_ENTRY);
1875 	echoDebug(DBG_PKGZONEINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1876 		PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1877 		a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "", PSTR(a_idsName),
1878 		a_adminFile);
1879 
1880 	/* generate path to pkginstall */
1881 
1882 	(void) snprintf(path, sizeof (path), "%s/pkginstall", PKGBIN);
1883 
1884 	/* start at first file descriptor */
1885 
1886 	maxfds = 0;
1887 
1888 	/*
1889 	 * generate argument list for call to pkginstall
1890 	 */
1891 
1892 	/* start at argument 0 */
1893 
1894 	nargs = 0;
1895 
1896 	/* first argument is path to executable */
1897 
1898 	arg[nargs++] = path;
1899 
1900 	/*
1901 	 * second argument is always: pass -O debug to pkginstall: debug mode
1902 	 */
1903 	if (debugFlag == B_TRUE) {
1904 		arg[nargs++] = "-O";
1905 		arg[nargs++] = "debug";
1906 	}
1907 
1908 	/* pkgadd -G: pass -G to pkginstall */
1909 
1910 	if (globalZoneOnly == B_TRUE) {
1911 		arg[nargs++] = "-G";
1912 	}
1913 
1914 	/* pkgadd -b dir: pass -b to pkginstall in zone */
1915 
1916 	if (a_altBinDir != (char *)NULL) {
1917 		arg[nargs++] = "-b";
1918 		arg[nargs++] = a_altBinDir;
1919 	}
1920 
1921 	/* pkgadd -B blocksize: pass -B to pkginstall in zone */
1922 
1923 	if (rw_block_size != NULL) {
1924 		arg[nargs++] = "-B";
1925 		arg[nargs++] = rw_block_size;
1926 	}
1927 
1928 	/* pkgadd -C: pass -C to pkgadd in zone: disable checksum */
1929 
1930 	if (disableChecksum) {
1931 		arg[nargs++] = "-C";
1932 	}
1933 
1934 	/* pkgadd -A: pass -A to pkgadd in zone: disable attribute checking */
1935 
1936 	if (disableAttributes) {
1937 		arg[nargs++] = "-A";
1938 	}
1939 
1940 	/* pkgadd -S: pass -S to pkgadd in zone: suppress copyright notices */
1941 
1942 	arg[nargs++] = "-S";
1943 
1944 	/* pkgadd -I: pass -I to pkgadd in zone: initial install */
1945 
1946 	if (init_install) {
1947 		arg[nargs++] = "-I";
1948 	}
1949 
1950 	/* pkgadd -M: pass -M to pkgadd in zone: dont mount client file sys */
1951 
1952 	arg[nargs++] = "-M";
1953 
1954 	/* pkgadd -v: pass -v to pkgadd in zone: trace scripts */
1955 
1956 	if (pkgverbose) {
1957 		arg[nargs++] = "-v";
1958 	}
1959 
1960 	/* pkgadd -z: pass -z to pkgadd in zone fresh inst from pkg save area */
1961 
1962 	if (saveSpoolInstall) {
1963 		arg[nargs++] = "-z";
1964 	}
1965 
1966 	/* pass "-O enable-hollow-package-support" */
1967 
1968 	if (is_depend_pkginfo_DB()) {
1969 		arg[nargs++] = "-O";
1970 		arg[nargs++] = "enable-hollow-package-support";
1971 	}
1972 
1973 	/* pkgadd -t pass -t to pkgadd in zone disable save spool area create */
1974 
1975 	if (disableSaveSpool) {
1976 		arg[nargs++] = "-t";
1977 	}
1978 
1979 	/* if running pkgask, pass -i to pkgadd in zone: running pkgask */
1980 
1981 	if (askflag) {
1982 		echo(MSG_BYPASSING_ZONE, a_zoneName);
1983 		return (0);
1984 	}
1985 
1986 	/*
1987 	 * pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode
1988 	 */
1989 	if (nointeract && !askflag) {
1990 		arg[nargs++] = "-n";
1991 	}
1992 
1993 	/* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1994 
1995 	if (a_adminFile) {
1996 		int fd;
1997 		fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1998 		if (fd < 0) {
1999 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
2000 				errno, strerror(errno));
2001 			return (1);
2002 		}
2003 		(void) snprintf(adminfd_path, sizeof (adminfd_path),
2004 			"/proc/self/fd/%d", fd);
2005 		fds[maxfds++] = fd;
2006 		arg[nargs++] = "-a";
2007 		arg[nargs++] = adminfd_path;
2008 	}
2009 
2010 	/* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
2011 	if (a_zoneState == ZONE_STATE_MOUNTED) {
2012 		arg[nargs++] = "-R";
2013 		arg[nargs++] = "/a";
2014 	}
2015 
2016 	/*
2017 	 * pkgadd -D arg: pass -D dryrun to pkginstall in zone: dryrun
2018 	 * mode/file
2019 	 */
2020 	if (pkgdrtarg) {
2021 		arg[nargs++] = "-D";
2022 		arg[nargs++] = pkgdrtarg;
2023 	}
2024 
2025 	/*
2026 	 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation
2027 	 * file
2028 	 */
2029 	if (pkgcontsrc) {
2030 		arg[nargs++] = "-c";
2031 		arg[nargs++] = pkgcontsrc;
2032 	}
2033 
2034 	/* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */
2035 
2036 	if (respfile) {
2037 		int fd;
2038 		fd = openLocal(respfile, O_RDONLY, tmpdir);
2039 		if (fd < 0) {
2040 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
2041 				errno, strerror(errno));
2042 			return (1);
2043 		}
2044 		(void) snprintf(respfilefd_path,
2045 			sizeof (respfilefd_path),
2046 			"/proc/self/fd/%d", fd);
2047 		fds[maxfds++] = fd;
2048 		arg[nargs++] = "-r";
2049 		arg[nargs++] = respfilefd_path;
2050 	}
2051 
2052 	/* add "-O addzonename" */
2053 
2054 	arg[nargs++] = "-O";
2055 	arg[nargs++] = "addzonename";
2056 
2057 	if (isPatchUpdate()) {
2058 		if (patchPkgRemoval == B_TRUE) {
2059 			arg[nargs++] = "-O";
2060 			arg[nargs++] = "patchPkgRemoval";
2061 		} else {
2062 			arg[nargs++] = "-O";
2063 			arg[nargs++] = "patchPkgInstall";
2064 		}
2065 	}
2066 
2067 	/* add all inherited file systems */
2068 
2069 	if (a_inheritedPkgDirs != (char **)NULL) {
2070 		for (n = 0; a_inheritedPkgDirs[n] != (char *)NULL; n++) {
2071 			char	ifs[MAXPATHLEN+22];
2072 			(void) snprintf(ifs, sizeof (ifs),
2073 				"inherited-filesystem=%s",
2074 				a_inheritedPkgDirs[n]);
2075 			arg[nargs++] = "-O";
2076 			arg[nargs++] = strdup(ifs);
2077 		}
2078 	}
2079 
2080 	/*
2081 	 * add parent zone info/type
2082 	 */
2083 
2084 	p = z_get_zonename();
2085 	if ((p != NULL) && (*p != '\0')) {
2086 			char	zn[MAXPATHLEN];
2087 			(void) snprintf(zn, sizeof (zn),
2088 				"parent-zone-name=%s", p);
2089 			arg[nargs++] = "-O";
2090 			arg[nargs++] = strdup(zn);
2091 	}
2092 
2093 	/* current zone type */
2094 
2095 	arg[nargs++] = "-O";
2096 	if (z_running_in_global_zone() == B_TRUE) {
2097 			char	zn[MAXPATHLEN];
2098 			(void) snprintf(zn, sizeof (zn),
2099 				"parent-zone-type=%s",
2100 				TAG_VALUE_GLOBAL_ZONE);
2101 			arg[nargs++] = strdup(zn);
2102 	} else {
2103 			char	zn[MAXPATHLEN];
2104 			(void) snprintf(zn, sizeof (zn),
2105 				"parent-zone-type=%s",
2106 				TAG_VALUE_NONGLOBAL_ZONE);
2107 			arg[nargs++] = strdup(zn);
2108 	}
2109 
2110 	/* add in the package stream file */
2111 
2112 	if (a_idsName != NULL) {
2113 		int fd;
2114 		fd = openLocal(a_idsName, O_RDONLY, tmpdir);
2115 		if (fd < 0) {
2116 			progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
2117 				pkginst, strerror(errno));
2118 			quit(1);
2119 		}
2120 		(void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
2121 			"/proc/self/fd/%d", fd);
2122 		fds[maxfds++] = fd;
2123 		arg[nargs++] = pkgstreamfd_path;
2124 	} else {
2125 		progerr(ERR_PKGZONEINSTALL_NO_STREAM);
2126 		quit(1);
2127 	}
2128 
2129 	/* add package instance name */
2130 
2131 	arg[nargs++] = pkginst;
2132 
2133 	/* terminate the argument list */
2134 
2135 	arg[nargs++] = NULL;
2136 
2137 	/*
2138 	 * run the appropriate pkginstall command in the specified zone
2139 	 */
2140 
2141 	if (debugFlag == B_TRUE) {
2142 		echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
2143 		for (n = 0; arg[n]; n++) {
2144 			echoDebug(DBG_ARG, n, arg[n]);
2145 		}
2146 	}
2147 
2148 	/* terminate file descriptor list */
2149 
2150 	fds[maxfds] = -1;
2151 
2152 	/* exec command in zone */
2153 
2154 	n = z_zone_exec(a_zoneName, path, arg, (char *)NULL, (char *)NULL, fds);
2155 
2156 	echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n, "");
2157 
2158 	/*
2159 	 * close any files that were opened for use by the
2160 	 * /proc/self/fd interface so they could be passed to programs
2161 	 * via the z_zone_exec() interface
2162 	 */
2163 
2164 	for (; maxfds > 0; maxfds--) {
2165 		(void) close(fds[maxfds-1]);
2166 	}
2167 
2168 	/* return results of pkginstall in zone execution */
2169 
2170 	return (n);
2171 }
2172 
2173 /*
2174  * Name:	pkgInstall
2175  * Description:	Invoke pkginstall in the current zone to perform an install
2176  *		of a single package to the current zone or standalone system
2177  * Arguments:	a_altRoot - pointer to string representing the alternative
2178  *			root to use for the install
2179  *		a_idsName - pointer to string representing the data stream
2180  *			device (input data stream) containing the package to
2181  *			be installed.
2182  *		a_pkgDir - pointer to string representing the path to the
2183  *			directory containing the package
2184  *		a_altBinDir - pointer to string representing location of the
2185  *			pkginstall executable to run. If not NULL, then pass
2186  *			the path specified to the -b option to pkginstall.
2187  *		a_inheritedPkgDirs - pointer to array of strings, each one
2188  *			representing the non-global zones full path of a
2189  *			directory that is inherited from the global zone.
2190  * Returns:	int	(see ckreturn() function for details)
2191  *		0 - success
2192  *		1 - package operation failed (fatal error)
2193  *		2 - non-fatal error (warning)
2194  *		3 - user selected quit (operation interrupted)
2195  *		4 - admin settings prevented operation
2196  *		5 - interaction required and -n (non-interactive) specified
2197  *		"10" will be added to indicate "immediate reboot required"
2198  *		"20" will be added to indicate "reboot after install required"
2199  * NOTE:	Both a_idsName and a_pkgDir are used to determine where the
2200  *		package to be installed is located. If a_idsName is != NULL
2201  *		then it must be the path to a device containing a package
2202  *		stream that contains the package to be installed. If a_idsName
2203  *		is == NULL then a_pkgDir must contain a full path to a directory
2204  *		that contains the package to be installed.
2205  */
2206 
2207 static int
2208 pkgInstall(char *a_altRoot, char *a_idsName, char *a_pkgDir, char *a_altBinDir,
2209 	char **a_inheritedPkgDirs)
2210 {
2211 	char	*arg[MAXARGS];
2212 	char	*p;
2213 	char	path[PATH_MAX];
2214 	char	buffer[256];
2215 	int	n, nargs;
2216 
2217 	/* entry debugging info */
2218 
2219 	echoDebug(DBG_PKGINSTALL_ENTRY);
2220 	echoDebug(DBG_PKGINSTALL_ARGS, PSTR(pkginst), PSTR(pkgdev.dirname),
2221 		PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), PSTR(a_altRoot),
2222 		PSTR(a_idsName), PSTR(a_pkgDir));
2223 
2224 	/* generate full path to 'pkginstall' to run in zone */
2225 
2226 	(void) snprintf(path, sizeof (path), "%s/pkginstall",
2227 		a_altBinDir == (char *)NULL ? PKGBIN : a_altBinDir);
2228 	/*
2229 	 * generate argument list for call to pkginstall
2230 	 */
2231 
2232 	/* start at argument 0 */
2233 
2234 	nargs = 0;
2235 
2236 	/* first argument is path to executable */
2237 
2238 	arg[nargs++] = path;
2239 
2240 	/*
2241 	 * second argument is always: pass -O debug to pkginstall: debug mode
2242 	 */
2243 	if (debugFlag == B_TRUE) {
2244 		arg[nargs++] = "-O";
2245 		arg[nargs++] = "debug";
2246 	}
2247 
2248 	/* Installation is from a patch package. */
2249 
2250 	if (isPatchUpdate()) {
2251 		if (patchPkgRemoval == B_TRUE) {
2252 			arg[nargs++] = "-O";
2253 			arg[nargs++] = "patchPkgRemoval";
2254 		} else {
2255 			arg[nargs++] = "-O";
2256 			arg[nargs++] = "patchPkgInstall";
2257 		}
2258 	}
2259 
2260 	/*
2261 	 * pkgadd -G: pass -G to pkginstall if:
2262 	 *  - the -G option is specified on the pkgadd command line
2263 	 *  - this package is marked 'this zone only':
2264 	 *  -- package has SUNW_PKG_THISZONE=true, or
2265 	 *  -- package has a request script
2266 	 * Setting -G for pkginstall causes pkginstall to install the package
2267 	 * in the target zone. If running in the global zone, will install the
2268 	 * package and mark the package as installed "in the global zone only".
2269 	 * If running in a non-global zone, will just install the package.
2270 	 */
2271 
2272 	if (globalZoneOnly == B_TRUE) {
2273 		arg[nargs++] = "-G";
2274 	} else if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
2275 		arg[nargs++] = "-G";
2276 	}
2277 
2278 	/* pkgadd -b dir: pass -b to pkginstall */
2279 
2280 	if (a_altBinDir != (char *)NULL) {
2281 		arg[nargs++] = "-b";
2282 		arg[nargs++] = a_altBinDir;
2283 	}
2284 
2285 	/* pkgadd -B blocksize: pass -B to pkginstall */
2286 
2287 	if (rw_block_size != NULL) {
2288 		arg[nargs++] = "-B";
2289 		arg[nargs++] = rw_block_size;
2290 	}
2291 
2292 	/* pkgadd -C: pass -C to pkginstall: disable checksum */
2293 
2294 	if (disableChecksum) {
2295 		arg[nargs++] = "-C";
2296 	}
2297 
2298 	/* pkgadd -A: pass -A to pkginstall: disable attribute checking */
2299 
2300 	if (disableAttributes) {
2301 		arg[nargs++] = "-A";
2302 	}
2303 
2304 	/*
2305 	 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
2306 	 * pkg requiring operator interaction during a procedure script
2307 	 * (common before on1093)
2308 	 */
2309 
2310 	if (old_pkg) {
2311 		arg[nargs++] = "-o";
2312 	}
2313 
2314 	/*
2315 	 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
2316 	 * symlinks consistent with old behavior
2317 	 */
2318 
2319 	if (old_symlinks) {
2320 		arg[nargs++] = "-y";
2321 	}
2322 
2323 	/*
2324 	 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
2325 	 * package name length to be restricted
2326 	 */
2327 
2328 	if (ABI_namelength) {
2329 		arg[nargs++] = "-e";
2330 	}
2331 
2332 	/* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
2333 
2334 	if (suppressCopyright) {
2335 		arg[nargs++] = "-S";
2336 	}
2337 
2338 	/* pkgadd -I: pass -I to pkginstall: initial install being performed */
2339 
2340 	if (init_install) {
2341 		arg[nargs++] = "-I";
2342 	}
2343 
2344 	/* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
2345 
2346 	if (no_map_client) {
2347 		arg[nargs++] = "-M";
2348 	}
2349 
2350 	/* pkgadd -v: pass -v to pkginstall: trace scripts */
2351 
2352 	if (pkgverbose) {
2353 		arg[nargs++] = "-v";
2354 	}
2355 
2356 	/* pkgadd -z: pass -z to pkginstall: fresh install from pkg save area */
2357 
2358 	if (saveSpoolInstall) {
2359 		arg[nargs++] = "-z";
2360 	}
2361 
2362 	/*
2363 	 * if running in a non-global zone and the 'hollow' attribute is
2364 	 * passed in, then pass -h to pkginstall so that it knows how to
2365 	 * handle hollow packages for this local zone.
2366 	 */
2367 
2368 	if (!z_running_in_global_zone() && is_depend_pkginfo_DB()) {
2369 		arg[nargs++] = "-h";
2370 	}
2371 
2372 	/* pkgadd -t: pass -t to pkginstall: disable save spool area creation */
2373 
2374 	if (disableSaveSpool) {
2375 		arg[nargs++] = "-t";
2376 	}
2377 
2378 	/* if running pkgask, pass -i to pkginstall: running pkgask */
2379 
2380 	if (askflag) {
2381 		arg[nargs++] = "-i";
2382 	}
2383 
2384 	/* pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode */
2385 
2386 	if (nointeract && !askflag) {
2387 		arg[nargs++] = "-n";
2388 	}
2389 
2390 	/* pkgadd -a admin: pass -a admin to pkginstall: admin file */
2391 
2392 	if (admnfile) {
2393 		arg[nargs++] = "-a";
2394 		arg[nargs++] = admnfile;
2395 	}
2396 
2397 	/* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */
2398 
2399 	if (pkgdrtarg) {
2400 		arg[nargs++] = "-D";
2401 		arg[nargs++] = pkgdrtarg;
2402 	}
2403 
2404 	/* pkgadd -c cont: pass -c cont to pkginstall: continuation file */
2405 
2406 	if (pkgcontsrc) {
2407 		arg[nargs++] = "-c";
2408 		arg[nargs++] = pkgcontsrc;
2409 	}
2410 
2411 	/* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */
2412 
2413 	if (vfstab_file) {
2414 		arg[nargs++] = "-V";
2415 		arg[nargs++] = vfstab_file;
2416 	}
2417 
2418 	/* pkgadd -r resp: pass -r resp to pkginstall: response file */
2419 
2420 	if (respfile) {
2421 		arg[nargs++] = "-r";
2422 		arg[nargs++] = respfile;
2423 	}
2424 
2425 	/* pkgadd -R root: pass -R root to pkginstall: alternative root */
2426 
2427 	if (a_altRoot && *a_altRoot) {
2428 		arg[nargs++] = "-R";
2429 		arg[nargs++] = a_altRoot;
2430 	}
2431 
2432 	/*
2433 	 * If input data stream is available,
2434 	 * - add: -d ids_name -p number_of_parts
2435 	 * else,
2436 	 * - add: -d device -m mount [-f type]
2437 	 */
2438 
2439 	if (a_idsName != NULL) {
2440 		arg[nargs++] = "-d";
2441 		arg[nargs++] = a_idsName;
2442 		arg[nargs++] = "-p";
2443 		ds_close(1);
2444 		ds_putinfo(buffer);
2445 		arg[nargs++] = buffer;
2446 	} else if (pkgdev.mount != NULL) {
2447 		arg[nargs++] = "-d";
2448 		arg[nargs++] = pkgdev.bdevice;
2449 		arg[nargs++] = "-m";
2450 		arg[nargs++] = pkgdev.mount;
2451 		if (pkgdev.fstyp != NULL) {
2452 			arg[nargs++] = "-f";
2453 			arg[nargs++] = pkgdev.fstyp;
2454 		}
2455 	}
2456 
2457 	/* add all inherited file systems */
2458 
2459 	if (a_inheritedPkgDirs != (char **)NULL) {
2460 		for (n = 0; a_inheritedPkgDirs[n] != (char *)NULL; n++) {
2461 			char	ifs[MAXPATHLEN+22];
2462 			(void) snprintf(ifs, sizeof (ifs),
2463 				"inherited-filesystem=%s",
2464 				a_inheritedPkgDirs[n]);
2465 			arg[nargs++] = "-O";
2466 			arg[nargs++] = strdup(ifs);
2467 		}
2468 	}
2469 
2470 	/*
2471 	 * add parent zone info/type
2472 	 */
2473 
2474 	p = z_get_zonename();
2475 	if ((p != NULL) && (*p != '\0')) {
2476 			char	zn[MAXPATHLEN];
2477 			(void) snprintf(zn, sizeof (zn),
2478 				"parent-zone-name=%s", p);
2479 			arg[nargs++] = "-O";
2480 			arg[nargs++] = strdup(zn);
2481 	}
2482 
2483 	/* current zone type */
2484 
2485 	arg[nargs++] = "-O";
2486 	if (z_running_in_global_zone() == B_TRUE) {
2487 			char	zn[MAXPATHLEN];
2488 			(void) snprintf(zn, sizeof (zn),
2489 				"parent-zone-type=%s",
2490 				TAG_VALUE_GLOBAL_ZONE);
2491 			arg[nargs++] = strdup(zn);
2492 	} else {
2493 			char	zn[MAXPATHLEN];
2494 			(void) snprintf(zn, sizeof (zn),
2495 				"parent-zone-type=%s",
2496 				TAG_VALUE_NONGLOBAL_ZONE);
2497 			arg[nargs++] = strdup(zn);
2498 	}
2499 
2500 	/* pass -N to pkginstall: program name to report */
2501 
2502 	arg[nargs++] = "-N";
2503 	arg[nargs++] = get_prog_name();
2504 
2505 	/* add package directory name */
2506 
2507 	arg[nargs++] = a_pkgDir;
2508 
2509 	/* add package instance name */
2510 
2511 	arg[nargs++] = pkginst;
2512 
2513 	/* terminate the argument list */
2514 
2515 	arg[nargs++] = NULL;
2516 
2517 	/*
2518 	 * run the appropriate pkginstall command in the specified zone
2519 	 */
2520 
2521 	if (debugFlag == B_TRUE) {
2522 		echoDebug(DBG_ZONE_EXEC_ENTER, "global", arg[0]);
2523 		for (n = 0; arg[n]; n++) {
2524 			echoDebug(DBG_ARG, n, arg[n]);
2525 		}
2526 	}
2527 
2528 	/* execute pkginstall command */
2529 
2530 	n = pkgexecv(NULL, NULL, NULL, NULL, arg);
2531 
2532 	/* return results of pkginstall execution */
2533 
2534 	return (n);
2535 }
2536 
2537 /*
2538  *  function to clear out any exisiting error return conditions that may have
2539  *  been set by previous calls to ckreturn()
2540  */
2541 static void
2542 resetreturn()
2543 {
2544 	admnflag = 0;	/* != 0 if any pkg op admin setting failure (4) */
2545 	doreboot = 0;	/* != 0 if reboot required after installation (>= 10) */
2546 	failflag = 0;	/* != 0 if fatal error has occurred (1) */
2547 	intrflag = 0;	/* != 0 if user selected quit (3) */
2548 	ireboot = 0;	/* != 0 if immediate reboot required (>= 20) */
2549 	nullflag = 0;	/* != 0 if admin interaction required (5) */
2550 	warnflag = 0;	/* != 0 if non-fatal error has occurred (2) */
2551 	interrupted = 0;	/* last pkg op was quit (1,2,3,4,5) */
2552 	needconsult = 0;	/* essential ask admin now (1,2,3,5) */
2553 }
2554 
2555 /*
2556  *  function which checks the indicated return value
2557  *  and indicates disposition of installation
2558  */
2559 static void
2560 ckreturn(int retcode)
2561 {
2562 	/*
2563 	 * entry debugging info
2564 	 */
2565 
2566 	echoDebug(DBG_PKGADD_CKRETURN, retcode, PSTR(pkginst));
2567 
2568 	/* reset needconsult so it only reflects this call to ckreturn */
2569 	needconsult = 0;
2570 
2571 	switch (retcode) {
2572 	    case  0:		/* successful */
2573 	    case 10:
2574 	    case 20:
2575 		break; /* empty case */
2576 
2577 	    case  1:		/* package operation failed (fatal error) */
2578 	    case 11:
2579 	    case 21:
2580 		failflag++;
2581 		interrupted++;
2582 		needconsult++;
2583 		break;
2584 
2585 	    case  2:		/* non-fatal error (warning) */
2586 	    case 12:
2587 	    case 22:
2588 		warnflag++;
2589 		interrupted++;
2590 		needconsult++;
2591 		break;
2592 
2593 	    case  3:		/* user selected quit; operation interrupted */
2594 	    case 13:
2595 	    case 23:
2596 		intrflag++;
2597 		interrupted++;
2598 		needconsult++;
2599 		break;
2600 
2601 	    case  4:		/* admin settings prevented operation */
2602 	    case 14:
2603 	    case 24:
2604 		admnflag++;
2605 		interrupted++;
2606 		break;
2607 
2608 	    case  5:		/* administration: interaction req (no -n) */
2609 	    case 15:
2610 	    case 25:
2611 		nullflag++;
2612 		interrupted++;
2613 		needconsult++;
2614 		break;
2615 
2616 	    default:
2617 		failflag++;
2618 		interrupted++;
2619 		needconsult++;
2620 		return;
2621 	}
2622 
2623 	if (retcode >= 20) {
2624 		ireboot++;
2625 	} else if (retcode >= 10) {
2626 		doreboot++;
2627 	}
2628 }
2629 
2630 static void
2631 usage(void)
2632 {
2633 	char *prog = get_prog_name();
2634 
2635 	if (askflag) {
2636 		(void) fprintf(stderr, ERR_USAGE_PKGASK, prog);
2637 	} else if (z_running_in_global_zone() == B_FALSE) {
2638 		(void) fprintf(stderr, ERR_USAGE_PKGADD_NONGLOBALZONE,
2639 			prog, prog);
2640 	} else {
2641 		(void) fprintf(stderr, ERR_USAGE_PKGADD_GLOBALZONE,
2642 			prog, prog);
2643 	}
2644 }
2645 
2646 /*
2647  * Name:	check_applicability
2648  * Description:	determine if a package is installable in this zone; that is,
2649  *		does the scope of install conflict with existing installation
2650  *		or can the package be installed
2651  * Arguments:	a_packageDir - [RO, *RO] - (char *)
2652  *			Pointer to string representing the directory where the
2653  *			package is located
2654  *		a_pkgInst - [RO, *RO] - (char *)
2655  *			Pointer to string representing the name of the package
2656  *			to check
2657  *		a_rootPath - [RO, *RO] - (char *)
2658  *			Pointer to string representing path to the root of the
2659  *			file system where the package is to be installed - this
2660  *			is usually the same as the "-R" argument to pkgadd
2661  *		a_flags - [RO, *RO] - (CAF_T)
2662  *			Flags set by the caller to indicate the conditions
2663  *			under which the package is to be installed:
2664  *				CAF_IN_GLOBAL_ZONE - in global zone
2665  *				CAF_SCOPE_GLOBAL - -G specified
2666  *				CAF_SCOPE_NONGLOBAL - -Z specified
2667  * Returns:	boolean_t
2668  *			B_TRUE - the package can be installed
2669  *			B_FALSE - the package can not be installed
2670  */
2671 
2672 static boolean_t
2673 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath,
2674 	CAF_T a_flags)
2675 {
2676 	FILE		*pkginfoFP;
2677 	FILE		*pkgmapFP;
2678 	boolean_t	all_zones;	/* pkg is "all zones" only */
2679 	boolean_t	in_gz_only;	/* pkg installed in global zone only */
2680 	boolean_t	is_hollow;	/* pkg is "hollow" */
2681 	boolean_t	pkg_installed;	/* pkg is installed */
2682 	boolean_t	this_zone;	/* pkg is "this zone" only */
2683 	boolean_t	reqfile_found = B_FALSE;
2684 	char		instPkg[PKGSIZ+1];	/* installed pkg instance nam */
2685 	char		instPkgPath[PATH_MAX];	/* installed pkg toplevel dir */
2686 	char		pkginfoPath[PATH_MAX];	/* pkg 2 install pkginfo file */
2687 	char		pkgmapPath[PATH_MAX];	/* pkg 2 install pkgmap file */
2688 	char		pkgpath[PATH_MAX];	/* pkg 2 install toplevel dir */
2689 	int		len;
2690 	char		line[LINE_MAX];
2691 
2692 	/* entry assertions */
2693 
2694 	assert(a_packageDir != (char *)NULL);
2695 	assert(*a_packageDir != '\0');
2696 	assert(a_pkgInst != (char *)NULL);
2697 	assert(*a_pkgInst != '\0');
2698 
2699 	/* normalize root path */
2700 
2701 	if (a_rootPath == (char *)NULL) {
2702 		a_rootPath = "";
2703 	}
2704 
2705 	/* entry debugging info */
2706 
2707 	echoDebug(DBG_CHECKAPP_ENTRY);
2708 	echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath);
2709 
2710 	/*
2711 	 * calculate paths to various objects
2712 	 */
2713 
2714 	/* path to package to be installed top level (main) directory */
2715 
2716 	len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir,
2717 			a_pkgInst);
2718 	if (len > sizeof (pkgpath)) {
2719 		progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst);
2720 		return (B_FALSE);
2721 	}
2722 
2723 	/* error if package top level directory does not exist */
2724 
2725 	if (isdir(pkgpath) != 0) {
2726 		progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno));
2727 		return (B_FALSE);
2728 	}
2729 
2730 	/* path to pkginfo file within the package to be installed */
2731 
2732 	len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo",
2733 			pkgpath);
2734 	if (len > sizeof (pkginfoPath)) {
2735 		progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo");
2736 		return (B_FALSE);
2737 	}
2738 
2739 	/* path to highest instance of package currently installed */
2740 
2741 	pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath),
2742 		instPkg, sizeof (instPkg), a_rootPath, a_pkgInst);
2743 
2744 	/*
2745 	 * gather information from this package's pkginfo file
2746 	 */
2747 
2748 	pkginfoFP = fopen(pkginfoPath, "r");
2749 
2750 	if (pkginfoFP == (FILE *)NULL) {
2751 		progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath,
2752 							strerror(errno));
2753 		return (B_FALSE);
2754 	}
2755 
2756 	/* determine "HOLLOW" setting for this package */
2757 
2758 	is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
2759 			"true", B_FALSE);
2760 
2761 	/* determine "ALLZONES" setting for this package */
2762 
2763 	all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
2764 			"true", B_FALSE);
2765 
2766 	/* determine "THISZONE" setting for this package */
2767 
2768 	this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
2769 			"true", B_FALSE);
2770 
2771 	/* close pkginfo file */
2772 
2773 	(void) fclose(pkginfoFP);
2774 
2775 	/*
2776 	 * If request file is not found, it may be in the datastream which
2777 	 * is not yet unpacked. Check in the pkgmap file.
2778 	 */
2779 	if (isfile(pkgpath, REQUEST_FILE) != 0) {
2780 
2781 		/* path to pkgmap file within the package to be installed */
2782 		(void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap",
2783 		    pkgpath);
2784 
2785 		pkgmapFP = fopen(pkgmapPath, "r");
2786 
2787 		if (pkgmapFP == NULL) {
2788 			progerr(ERR_NO_PKG_MAPFILE, a_pkgInst,
2789 			    pkgmapPath, strerror(errno));
2790 			return (B_FALSE);
2791 		}
2792 
2793 		while (fgets(line, LINE_MAX, pkgmapFP) != NULL) {
2794 			if (strstr(line, " i request") != NULL) {
2795 				reqfile_found = B_TRUE;
2796 				break;
2797 			}
2798 		}
2799 		(void) fclose(pkgmapFP);
2800 	} else {
2801 		reqfile_found = B_TRUE;
2802 	}
2803 
2804 	/*
2805 	 * If this package is not marked for installation in this zone only,
2806 	 * check to see if this package has a request script. If this package
2807 	 * does have a request script, then mark the package for installation
2808 	 * in this zone only. Any package with a request script cannot be
2809 	 * installed outside of the zone the pkgadd command is being run in,
2810 	 * nor can such a package be installed as part of a new zone install.
2811 	 * A new zone install must be non-interactive, which is required
2812 	 * by all packages integrated into the Solaris WOS.
2813 	 */
2814 
2815 	if ((!this_zone) && (reqfile_found)) {
2816 		if (a_flags & CAF_IN_GLOBAL_ZONE) {
2817 			echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst);
2818 		}
2819 		this_zone = B_TRUE;
2820 	}
2821 
2822 	/*
2823 	 * If this package is already installed, see if the current installation
2824 	 * of the package has a request file - if it does, then act as though
2825 	 * the current package to be added has a request file - install the
2826 	 * package in the current zone only.
2827 	 */
2828 
2829 	if ((!this_zone) && (instPkgPath[0] != '\0') &&
2830 		(isfile(instPkgPath, REQUEST_FILE) == 0)) {
2831 		if (a_flags & CAF_IN_GLOBAL_ZONE) {
2832 			echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ,
2833 				a_pkgInst, instPkg);
2834 		}
2835 		this_zone = B_TRUE;
2836 	}
2837 
2838 	/* gather information from the global zone only file */
2839 
2840 	in_gz_only = B_FALSE;
2841 	if (a_flags & CAF_IN_GLOBAL_ZONE) {
2842 		in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst);
2843 	}
2844 
2845 	/* determine if this package is currently installed */
2846 
2847 	pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL,
2848 								a_pkgInst);
2849 
2850 	/*
2851 	 * verify package applicability based on information gathered,
2852 	 * and validate the three SUNW_PKG_ options:
2853 	 *
2854 	 * -----------|--------------|-------------|-------------|-----------
2855 	 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE	 | LOCAL ZONE
2856 	 * - - - - - -|	- - pkgadd - | pkgadd -G   | pkgadd	 | pkgadd -G
2857 	 * ----1------|--------------|-------------|-------------|------------
2858 	 * ALLZONES f | add to gz    | add to gz   | add to ls	 | add to ls
2859 	 * HOLLOW   f | current lz   | not to curr | only - - - -| only - - -
2860 	 * THISZONE f | futr lz - - -| or futr lz  | - - - - - - | - - - - - -
2861 	 * ----2------|--------------|-------------|-------------|------------
2862 	 * ALLZONES T | add to gz    | operation   | operation	 | operation
2863 	 * HOLLOW   f | current lz   | not allowed | not allowed | not allowed
2864 	 * THISZONE f | future lz    | - - - - - - | - - - - - - | - - - - - -
2865 	 * ----3------|--------------|-------------|-------------|------------
2866 	 * ALLZONES T | add to gz    | operation   | operation	 | operation
2867 	 * HOLLOW   T | pkg db only  | not allowed | not allowed | not allowed
2868 	 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2869 	 * ----4------|--------------|-------------|-------------|------------
2870 	 * ALLZONES T | bad option   | bad option  | bad option	 | bad option
2871 	 * HOLLOW   * | combo - - - -| combo - - - | combo - - - | combo - -
2872 	 * THISZONE T |	- - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2873 	 * ----5------|--------------|-------------|-------------|------------
2874 	 * ALLZONES f | bad option   | bad option  | bad option	 | bad option
2875 	 * HOLLOW   T | combo - - - -| combo - - - | combo - - - | combo - - -
2876 	 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2877 	 * ----6------|--------------|-------------|-------------|------------
2878 	 * ALLZONES f | add to gz    | add to gz   | add to lz	 | add to lz
2879 	 * HOLLOW   f | not current  | not current | only - - -	 | only - - -
2880 	 * THISZONE T | or future lz | or futr lz  | - - - - - - | - - - - - -
2881 	 * -----------|--------------|-------------|-------------|-----------
2882 	 */
2883 
2884 	/* pkg "all zones" && "this zone" (#4) */
2885 
2886 	if (all_zones && this_zone) {
2887 		progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst,
2888 			PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
2889 		return (B_FALSE);
2890 	}
2891 
2892 	/* pkg "!all zones" && "hollow" (#5) */
2893 
2894 	if ((!all_zones) && is_hollow) {
2895 		progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst,
2896 			PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
2897 		return (B_FALSE);
2898 	}
2899 
2900 	/* pkg ALLZONES=true && -Z specified */
2901 
2902 	if (all_zones && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2903 		progerr(ERR_ALLZONES_AND_Z_USED, a_pkgInst);
2904 		return (B_FALSE);
2905 	}
2906 
2907 	/* pkg ALLZONES=true & not running in global zone (#2/#3) */
2908 
2909 	if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) {
2910 		progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst);
2911 		return (B_FALSE);
2912 	}
2913 
2914 	/* pkg "in gz only" & pkg "NOT installed" */
2915 
2916 	if (in_gz_only && (!pkg_installed)) {
2917 		/* MAKE A WARNING */
2918 		echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst,
2919 			pkgGetGzOnlyPath());
2920 	}
2921 
2922 	/* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2923 
2924 	if (all_zones && in_gz_only && pkg_installed) {
2925 		progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst);
2926 		return (B_FALSE);
2927 	}
2928 
2929 	/* pkg ALLZONES=true && -G specified (#2/#3) */
2930 
2931 	if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) {
2932 		progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst);
2933 		return (B_FALSE);
2934 	}
2935 
2936 	/* pkg "!this zone" && "in gz only" & -G not specified */
2937 
2938 	if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) {
2939 		progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst);
2940 		return (B_FALSE);
2941 	}
2942 
2943 	/* pkg "NOT in gz only" & -Z specified */
2944 
2945 	if ((!in_gz_only) && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2946 		progerr(ERR_NOT_IN_GZ_AND_Z_USED, a_pkgInst);
2947 		return (B_FALSE);
2948 	}
2949 
2950 	/* pkg "this zone" && -Z specified */
2951 
2952 	if (this_zone && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2953 		progerr(ERR_THISZONE_AND_Z_USED, PKG_THISZONE_VARIABLE,
2954 			a_pkgInst);
2955 		return (B_FALSE);
2956 	}
2957 
2958 	/*
2959 	 * If this package is marked 'this zone only', then mark the package
2960 	 * as "add to this zone only". This is referenced by the various
2961 	 * add_package_... functions to determine if the package should be
2962 	 * added to the current zone, or to all zones, depending on the
2963 	 * zone in which the command is being run.
2964 	 */
2965 
2966 	if (this_zone) {
2967 		pkgAddThisZonePackage(a_pkgInst);
2968 	}
2969 
2970 	return (B_TRUE);
2971 }
2972 
2973 /*
2974  * Name:	create_zone_adminfile
2975  * Description: Given a zone temporary directory and optionally an existing
2976  *		administration file, generate an administration file that
2977  *		can be used to perform "non-interactive" operations in a
2978  *		non-global zone.
2979  * Arguments:	r_zoneAdminFile - pointer to handle that will contain a
2980  *			string representing the path to the temporary
2981  *			administration file created - this must be NULL
2982  *			before the first call to this function - on
2983  *			subsequent calls if the pointer is NOT null then
2984  *			the existing string will NOT be overwritten.
2985  *		a_zoneTempDir - pointer to string representing the path
2986  *			to the zone temporary directory to create the
2987  *			temporary administration file in
2988  *		a_admnfile - pointer to string representing the path to
2989  *			an existing "user" administration file - the
2990  *			administration file created will contain the
2991  *			settings contained in this file, modified as
2992  *			appropriate to supress any interaction;
2993  *			If this is == NULL then the administration file
2994  *			created will not contain any extra settings
2995  * Returns:	void
2996  * NOTE:	Any string returned is placed in new storage for the
2997  *		calling method. The caller must use 'free' to dispose
2998  *		of the storage once the string is no longer needed.
2999  * NOTE:	On any error this function will call 'quit(1)'
3000  */
3001 
3002 static void
3003 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir,
3004 	char *a_admnfile)
3005 {
3006 	boolean_t	b;
3007 
3008 	/* entry assertions */
3009 
3010 	assert(r_zoneAdminFile != (char **)NULL);
3011 	assert(a_zoneTempDir != (char *)NULL);
3012 	assert(*a_zoneTempDir != '\0');
3013 
3014 	/* entry debugging info */
3015 
3016 	echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile));
3017 
3018 	/* if temporary name already exists, do not overwrite */
3019 
3020 	if (*r_zoneAdminFile != (char *)NULL) {
3021 		return;
3022 	}
3023 
3024 	/* create temporary name */
3025 
3026 	*r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn");
3027 	b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile);
3028 	if (b == B_FALSE) {
3029 		progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile,
3030 			strerror(errno));
3031 		quit(1);
3032 		/* NOTREACHED */
3033 	}
3034 
3035 	echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile);
3036 }
3037 
3038 /*
3039  * Name:	create_zone_tempdir
3040  * Description: Given a system temporary directory, create a "zone" specific
3041  *		temporary directory and return the path to the directory
3042  *		created.
3043  * Arguments:	r_zoneTempDir - pointer to handle that will contain a
3044  *			string representing the path to the temporary
3045  *			directory created - this must be NULL before the
3046  *			first call to this function - on subsequent calls
3047  *			if the pointer is NOT null then the existing string
3048  *			will NOT be overwritten.
3049  *		a_zoneTempDir - pointer to string representing the path
3050  *			to the system temporary directory to create the
3051  *			temporary zone directory in
3052  * Returns:	void
3053  * NOTE:	Any string returned is placed in new storage for the
3054  *		calling method. The caller must use 'free' to dispose
3055  *		of the storage once the string is no longer needed.
3056  * NOTE:	On any error this function will call 'quit(1)'
3057  * NOTE:	This function calls "quitSetZoneTmpdir" on success to
3058  *		register the directory created with quit() so that the
3059  *		directory will be automatically deleted on exit.
3060  */
3061 
3062 static void
3063 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir)
3064 {
3065 	boolean_t	b;
3066 
3067 	/* entry assertions */
3068 
3069 	assert(r_zoneTempDir != (char **)NULL);
3070 	assert(a_tmpdir != (char *)NULL);
3071 	assert(*a_tmpdir != '\0');
3072 
3073 	/* entry debugging info */
3074 
3075 	echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir);
3076 
3077 	/* if temporary directory already exists, do not overwrite */
3078 
3079 	if (*r_zoneTempDir != (char *)NULL) {
3080 		return;
3081 	}
3082 
3083 	/* create temporary directory */
3084 
3085 	b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp");
3086 	if (b == B_FALSE) {
3087 		progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno));
3088 		quit(1);
3089 		/* NOTREACHED */
3090 	}
3091 
3092 	/* register with quit() so directory is removed on exit */
3093 
3094 	quitSetZoneTmpdir(*r_zoneTempDir);
3095 
3096 	/* exit debugging info */
3097 
3098 	echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir);
3099 }
3100 
3101 /*
3102  * Name:	continue_installation
3103  * Description: Called from within a loop that is installing packages,
3104  *		this function examines various global variables and decides
3105  *		whether or not to ask an appropriate question, and wait for
3106  *		and appropriate reply.
3107  * Arguments:	<<global variables>>
3108  * Returns:	B_TRUE - continue processing with next package
3109  *		B_FALSE - do not continue processing with next package
3110  */
3111 
3112 static boolean_t
3113 continue_installation(void)
3114 {
3115 	char	ans[MAX_INPUT];
3116 	int	n;
3117 
3118 	/* return TRUE if not interrupted */
3119 
3120 	if (!interrupted) {
3121 		return (B_TRUE);
3122 	}
3123 
3124 	/*
3125 	 * process interrupted - determine whether or not to continue
3126 	 */
3127 
3128 	/* output appropriate interrupted message */
3129 
3130 	if (askflag) {
3131 		echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs);
3132 	} else {
3133 		echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs);
3134 	}
3135 
3136 	/* if running with no interaction (-n) do not ask question */
3137 
3138 	if (nointeract) {
3139 		/* if admin required return 'dont continue' */
3140 		if (needconsult) {
3141 			return (B_FALSE);
3142 		}
3143 		ckquit = 1;
3144 		return (B_TRUE);
3145 	}
3146 
3147 	/* interaction possible: ask question */
3148 
3149 	ckquit = 0;
3150 	n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD);
3151 	if (n != 0) {
3152 		quit(n);
3153 		/* NOTREACHED */
3154 	}
3155 	ckquit = 1;
3156 	if (strchr("yY", *ans) == NULL) {
3157 		return (B_FALSE);
3158 	}
3159 	return (B_TRUE);
3160 }
3161 
3162 /*
3163  * package can be in a number of formats:
3164  * - file containing package stream (pkgadd -d file [pkgs])
3165  * - directory containing packages (pkgadd -d /dir [pkgs])
3166  * - device containing packages (pkgadd -d diskette1 [pkgs])
3167  * non-global zones can be passed open files and strings as arguments
3168  * - for file containing package stream
3169  * -- the stream can be passed directly to the non-global zone
3170  * - for directory
3171  * -- convert packages to datastream to pass to the non-global zone
3172  * - for device
3173  * -- ?
3174  */
3175 
3176 static boolean_t
3177 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir)
3178 {
3179 	int	savenpkgs = npkgs;
3180 	int	i;
3181 	CAF_T	flags = 0;
3182 
3183 	/* entry assertions */
3184 
3185 	assert(a_pkgList != (char **)NULL);
3186 
3187 	/* entry debugging info */
3188 
3189 	echoDebug(DBG_UNPACKCHECK_ENTRY);
3190 	echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir));
3191 
3192 	/*
3193 	 * set flags for applicability check
3194 	 */
3195 
3196 	/* determine if running in the global zone */
3197 
3198 	if (z_running_in_global_zone() == B_TRUE) {
3199 		flags |= CAF_IN_GLOBAL_ZONE;
3200 	}
3201 
3202 	/* set -G flag */
3203 
3204 	if (globalZoneOnly == B_TRUE) {
3205 		flags |= CAF_SCOPE_GLOBAL;
3206 	}
3207 
3208 	/*
3209 	 * for each package to install:
3210 	 * - if packages from datastream, unpack package into package dir
3211 	 * - check applicability of installing package on this system/zone
3212 	 */
3213 
3214 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3215 		if (a_idsName != (char *)NULL) {
3216 			/* create stream out of package if not already one */
3217 			if (unpack_package_from_stream(a_idsName, pkginst,
3218 				a_packageDir) == B_FALSE) {
3219 				progerr(ERR_CANNOT_UNPACK_PKGSTRM,
3220 					PSTR(pkginst), PSTR(a_idsName),
3221 					PSTR(a_packageDir));
3222 
3223 				npkgs = savenpkgs;
3224 				return (B_FALSE);
3225 			}
3226 		} else {
3227 			echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir);
3228 		}
3229 
3230 		/* check package applicability */
3231 		if (check_applicability(a_packageDir,
3232 			pkginst, get_inst_root(), flags) == B_FALSE) {
3233 			progerr(ERR_PKG_NOT_INSTALLABLE, pkginst);
3234 			npkgs = savenpkgs;
3235 			return (B_FALSE);
3236 		}
3237 		npkgs--;
3238 	}
3239 
3240 	npkgs = savenpkgs;
3241 	return (B_TRUE);
3242 }
3243 
3244 /*
3245  * returns:
3246  *	B_TRUE - package list generated
3247  *	B_FALSE - failed to generate package list
3248  *	Will call quit(n) on fatal error.
3249  */
3250 
3251 static boolean_t
3252 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories,
3253 	char **a_categoryList, int a_ignoreSignatures, PKG_ERR *a_err,
3254 	ushort_t a_httpProxyPort, char *a_httpProxyName,
3255 	keystore_handle_t a_keystore, char *a_keystoreFile,
3256 	char *a_idsName, int *r_repeat)
3257 {
3258 	int		n;
3259 	url_hport_t	*proxytmp = NULL;
3260 
3261 	/* entry assertions */
3262 
3263 	assert(r_repeat != (int *)NULL);
3264 
3265 	/* entry debugging info */
3266 
3267 	echoDebug(DBG_GETPKGLIST_ENTRY);
3268 	echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname),
3269 			*r_repeat);
3270 
3271 	/*
3272 	 * get the list of the packages to add
3273 	 */
3274 
3275 	n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories,
3276 				a_categoryList, &pkgdev);
3277 
3278 	switch (n) {
3279 		case -1:	/* no packages found */
3280 			echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName),
3281 					pkgdev.dirname);
3282 			return (B_FALSE);
3283 
3284 		case 0:		/* packages found */
3285 			break;
3286 
3287 		default:	/* "quit" error */
3288 			echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName),
3289 				pkgdev.dirname, n);
3290 			quit(n);
3291 			/* NOTREACHED */
3292 	}
3293 
3294 	/*
3295 	 * If we are not ignoring signatures, check the package's
3296 	 * signature if one exists.  pkgask doesn't care about
3297 	 * signatures though.
3298 	 */
3299 	if (!askflag && !a_ignoreSignatures && a_idsName &&
3300 		(web_ck_authentication() == AUTH_QUIT)) {
3301 
3302 		PKCS7		*sig = NULL;
3303 		STACK_OF(X509)	*cas = NULL;
3304 
3305 		/* Retrieve signature */
3306 		if (!get_signature(a_err, a_idsName, &pkgdev, &sig)) {
3307 			pkgerr(a_err);
3308 			web_cleanup();
3309 			quit(1);
3310 			/* NOTREACHED */
3311 		}
3312 
3313 		if (sig != NULL) {
3314 			/* Found signature.  Verify. */
3315 			if (a_httpProxyName != NULL) {
3316 				/* Proxy will be needed for OCSP */
3317 				proxytmp = malloc(sizeof (url_hport_t));
3318 				if (url_parse_hostport(a_httpProxyName,
3319 					proxytmp, a_httpProxyPort)
3320 					!= URL_PARSE_SUCCESS) {
3321 					progerr(ERR_PROXY,
3322 						a_httpProxyName);
3323 					PKCS7_free(sig);
3324 					quit(99);
3325 					/* NOTREACHED */
3326 				}
3327 			}
3328 
3329 			/* Start with fresh error stack */
3330 			pkgerr_clear(a_err);
3331 
3332 			if (a_keystore == NULL) {
3333 				/* keystore not opened - open it */
3334 				if (open_keystore(a_err, a_keystoreFile,
3335 					get_prog_name(), pkg_passphrase_cb,
3336 					KEYSTORE_DFLT_FLAGS,
3337 					&a_keystore) != 0) {
3338 					pkgerr(a_err);
3339 					web_cleanup();
3340 					PKCS7_free(sig);
3341 					quit(1);
3342 					/* NOTREACHED */
3343 				}
3344 			}
3345 
3346 			/* get trusted CA certs */
3347 			if (find_ca_certs(a_err, a_keystore, &cas) != 0) {
3348 				pkgerr(a_err);
3349 				PKCS7_free(sig);
3350 				web_cleanup();
3351 				quit(1);
3352 				/* NOTREACHED */
3353 			}
3354 
3355 			/* Verify signature */
3356 			if (!ds_validate_signature(a_err, &pkgdev,
3357 				&a_argv[optind], a_idsName, sig,
3358 				cas, proxytmp, nointeract)) {
3359 				pkgerr(a_err);
3360 				quit(99);
3361 				/* NOTREACHED */
3362 			}
3363 
3364 			/* cleanup */
3365 			PKCS7_free(sig);
3366 			web_cleanup();
3367 			pkgerr_free(a_err);
3368 		}
3369 	}
3370 
3371 	/* order package list if input data stream specified */
3372 
3373 	if (a_idsName) {
3374 		ds_order(*r_pkgList);
3375 	}
3376 
3377 	return (B_TRUE);
3378 }
3379 
3380 /*
3381  * Name:	install_in_one_zone
3382  * Description:	Install a single package in a single zone
3383  * Arguments:	a_inheritedPkgDirs - pointer to array of strings, each one
3384  *			representing the non-global zones full path of a
3385  *			directory that is inherited from the global zone.
3386  *		a_zoneName - pointer to string representing the name of the
3387  *			zone to install the package into.
3388  *		a_idsName - pointer to string representing the data stream
3389  *			device (input data stream) containing the package to
3390  *			be installed.
3391  *			If this is == NULL the package is assumed to be
3392  *			spooled in the zone temporary directory.
3393  *		a_zoneAdminFile - pointer to string representing the admin
3394  *			file to pass to pkginstall when installing the package.
3395  *			If this is == NULL no admin file is given to pkginstall.
3396  *		a_zoneTempDir - pointer to string representing the temporary
3397  *			directory in which spooled packages can be found if
3398  *			a_idsName is == NULL.
3399  *		a_altBinDir - pointer to string representing an alternative
3400  *			binary location directory to pass to pkginstall.
3401  *			If this is == NULL no alternative binary location is
3402  *			passed to pkginstall.
3403  *		a_scratchName - pointer to string representing the name of the
3404  *			scratch zone to use for installation.
3405  *		a_zoneState - state of the zone; must be mounted or running.
3406  * Returns:	void
3407  * NOTE:	As a side effect, "ckreturn" is called on the result returned
3408  *		from running 'pkginstall' in the zone; this sets several global
3409  *		variables which allows the caller to determine the result of
3410  *		the installation operation.
3411  */
3412 
3413 static void
3414 install_in_one_zone(char **a_inheritedPkgDirs, char *a_zoneName,
3415 	char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3416 	char *a_altBinDir, zone_state_t a_zoneState)
3417 {
3418 	char	zoneStreamName[PATH_MAX] = {'\0'};
3419 	int	n;
3420 
3421 	/* entry assertions */
3422 
3423 	assert(a_zoneName != (char *)NULL);
3424 	assert(*a_zoneName != '\0');
3425 
3426 	/* entry debugging info */
3427 
3428 	echoDebug(DBG_INSTINONEZONE_ENTRY);
3429 	echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName),
3430 			PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir),
3431 			PSTR(a_altBinDir));
3432 
3433 	/* echo operation to perform to stdout */
3434 
3435 	echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3436 
3437 	/* determine path to the package stream */
3438 
3439 	if (a_idsName == (char *)NULL) {
3440 		/* locate temp stream created earlier */
3441 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3442 			"%s/%s.dstream", a_zoneTempDir, pkginst);
3443 	} else {
3444 		/* use stream passed in on command line */
3445 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3446 			"%s", a_idsName);
3447 	}
3448 
3449 	echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName);
3450 
3451 	n = pkgZoneInstall(a_zoneName, a_inheritedPkgDirs, a_zoneState,
3452 		zoneStreamName, a_altBinDir, a_zoneAdminFile);
3453 
3454 	/* set success/fail condition variables */
3455 
3456 	ckreturn(n);
3457 
3458 	/* exit debugging info */
3459 
3460 	echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot,
3461 		failflag, interrupted, intrflag, ireboot, needconsult,
3462 		nullflag, warnflag);
3463 }
3464 
3465 /*
3466  * Name:	install_in_zones
3467  * Description:	Install a single package in the zones that are running from
3468  *		a list of zones
3469  * Arguments:	a_zlst - list of zones to install the package into
3470  *		a_idsName - pointer to string representing the data stream
3471  *			device (input data stream) containing the package to
3472  *			be installed.
3473  *			If this is == NULL the package is assumed to be
3474  *			spooled in the zone temporary directory.
3475  *		a_altBinDir - pointer to string representing an alternative
3476  *			binary location directory to pass to pkginstall.
3477  *			If this is == NULL no alternative binary location is
3478  *			passed to pkginstall.
3479  *		a_zoneAdminFile - pointer to string representing the admin
3480  *			file to pass to pkginstall when installing the package.
3481  *			If this is == NULL no admin file is given to pkginstall.
3482  *		a_zoneTempDir - pointer to string representing the temporary
3483  *			directory in which spooled packages can be found if
3484  *			a_idsName is == NULL.
3485  */
3486 
3487 static int
3488 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3489 	char *a_zoneAdminFile, char *a_zoneTempDir)
3490 {
3491 	char		**inheritedPkgDirs;
3492 	char		*zoneName;
3493 	int		zoneIndex;
3494 	int		zonesSkipped = 0;
3495 	zone_state_t	zst;
3496 
3497 	/* entry assertions */
3498 
3499 	assert(a_zlst != (zoneList_t)NULL);
3500 
3501 	/* entry debugging info */
3502 
3503 	echoDebug(DBG_INSTALLINZONES_ENTRY);
3504 	echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName),
3505 			PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3506 
3507 	/* process each zone in the list */
3508 
3509 	for (zoneIndex = 0;
3510 		(zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3511 		zoneIndex++) {
3512 
3513 		/* skip the zone if it is NOT running */
3514 
3515 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3516 		if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3517 			zonesSkipped++;
3518 			echoDebug(DBG_SKIPPING_ZONE, zoneName);
3519 			continue;
3520 		}
3521 
3522 		/* determine list of directories inherited from global zone */
3523 
3524 		inheritedPkgDirs = z_zlist_get_inherited_pkg_dirs(a_zlst,
3525 					zoneIndex);
3526 
3527 		/* install the package in this zone */
3528 
3529 		install_in_one_zone(inheritedPkgDirs,
3530 		    z_zlist_get_scratch(a_zlst, zoneIndex), a_idsName,
3531 		    a_zoneAdminFile, a_zoneTempDir, a_altBinDir, zst);
3532 	}
3533 
3534 	return (zonesSkipped);
3535 }
3536 
3537 /*
3538  * Name:	boot_and_install_in_zones
3539  * Description:	Install a single package in the zones that are NOT running from
3540  *		a list of zones - each zone is booted, the package installed,
3541  *		and the zone is halted
3542  * Arguments:	a_zlst - list of zones to install the package into
3543  *		a_idsName - pointer to string representing the data stream
3544  *			device (input data stream) containing the package to
3545  *			be installed.
3546  *			If this is == NULL the package is assumed to be
3547  *			spooled in the zone temporary directory.
3548  *		a_altBinDir - pointer to string representing an alternative
3549  *			binary location directory to pass to pkginstall.
3550  *			If this is == NULL no alternative binary location is
3551  *			passed to pkginstall.
3552  *		a_zoneAdminFile - pointer to string representing the admin
3553  *			file to pass to pkginstall when installing the package.
3554  *			If this is == NULL no admin file is given to pkginstall.
3555  *		a_zoneTempDir - pointer to string representing the temporary
3556  *			directory in which spooled packages can be found if
3557  *			a_idsName is == NULL.
3558  */
3559 
3560 static int
3561 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3562 	char *a_zoneAdminFile, char *a_zoneTempDir)
3563 {
3564 	boolean_t	b;
3565 	char		**inheritedPkgDirs;
3566 	char		*zoneName;
3567 	int		zoneIndex;
3568 	int		zonesSkipped = 0;
3569 	zone_state_t	zst;
3570 
3571 	/* entry assertions */
3572 
3573 	assert(a_zlst != (zoneList_t)NULL);
3574 
3575 	/* entry debugging info */
3576 
3577 	echoDebug(DBG_BOOTINSTALLINZONES_ENTRY);
3578 	echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName),
3579 			PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3580 
3581 	/* process each zone in the list */
3582 
3583 	for (zoneIndex = 0;
3584 		(zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3585 		zoneIndex++) {
3586 
3587 		/* skip the zone if it IS running */
3588 
3589 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3590 		if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3591 			echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3592 			continue;
3593 		}
3594 
3595 		/* skip the zone if it is NOT bootable */
3596 
3597 		if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3598 			echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3599 			echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3600 			continue;
3601 		}
3602 
3603 		/* mount up the zone */
3604 
3605 		echo(MSG_BOOTING_ZONE, zoneName);
3606 		echoDebug(DBG_BOOTING_ZONE, zoneName);
3607 
3608 		b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3609 					ZONE_STATE_MOUNTED);
3610 		if (b == B_FALSE) {
3611 			progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3612 			/* set fatal error return condition */
3613 			ckreturn(1);
3614 			zonesSkipped++;
3615 			continue;
3616 		}
3617 
3618 		/* determine list of directories inherited from global zone */
3619 
3620 		inheritedPkgDirs = z_zlist_get_inherited_pkg_dirs(a_zlst,
3621 					zoneIndex);
3622 
3623 		/* install the package in this zone */
3624 
3625 		install_in_one_zone(inheritedPkgDirs,
3626 		    z_zlist_get_scratch(a_zlst, zoneIndex), a_idsName,
3627 		    a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3628 		    ZONE_STATE_MOUNTED);
3629 
3630 		/* restore original state of zone */
3631 
3632 		echo(MSG_RESTORE_ZONE_STATE, zoneName);
3633 		echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3634 
3635 		b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3636 	}
3637 
3638 	return (zonesSkipped);
3639 }
3640 
3641 /*
3642  * Name:	pkginstall_check_in_one_zone
3643  * Description:	Do a pre install check of a single package in a single zone
3644  * Arguments:	a_inheritedPkgDirs - pointer to array of strings, each one
3645  *			representing the non-global zones full path of a
3646  *			directory that is inherited from the global zone.
3647  *		a_zoneName - pointer to string representing the name of the
3648  *			zone to check install the package in.
3649  *		a_idsName - pointer to string representing the data stream
3650  *			device (input data stream) containing the package to
3651  *			be check installed.
3652  *			If this is == NULL the package is assumed to be
3653  *			spooled in the zone temporary directory.
3654  *		a_zoneAdminFile - pointer to string representing the admin
3655  *			file to pass to pkginstall when installing the package.
3656  *			If this is == NULL no admin file is given to pkginstall.
3657  *		a_zoneTempDir - pointer to string representing the temporary
3658  *			directory in which spooled packages can be found if
3659  *			a_idsName is == NULL.
3660  *		a_altBinDir - pointer to string representing an alternative
3661  *			binary location directory to pass to pkginstall.
3662  *			If this is == NULL no alternative binary location is
3663  *			passed to pkginstall.
3664  *		a_scratchName - pointer to string representing the name of the
3665  *			scratch zone to use for installation.
3666  *		a_zoneState - state of the zone; must be mounted or running.
3667  * Returns:	void
3668  * NOTE:	As a side effect, "ckreturn" is called on the result returned
3669  *		from running 'pkginstall' in the zone; this sets several global
3670  *		variables which allows the caller to determine the result of
3671  *		the pre installation check operation.
3672  */
3673 
3674 static void
3675 pkginstall_check_in_one_zone(char **a_inheritedPkgDirs, char *a_zoneName,
3676 	char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3677 	char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState)
3678 {
3679 	char	preinstallcheckPath[PATH_MAX+1];
3680 	char	zoneStreamName[PATH_MAX] = {'\0'};
3681 	int	n;
3682 
3683 	echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3684 	echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3685 
3686 	(void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath),
3687 		"%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst,
3688 		a_zoneName);
3689 
3690 	if (a_idsName == (char *)NULL) {
3691 		/* locate temporary stream created earlier */
3692 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3693 			"%s/%s.dstream", a_zoneTempDir, pkginst);
3694 	} else {
3695 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3696 			"%s", a_idsName);
3697 	}
3698 
3699 	echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName,
3700 						zoneStreamName);
3701 
3702 	n = pkgZoneCheckInstall(a_scratchName, a_inheritedPkgDirs,
3703 	    a_zoneState, zoneStreamName, a_altBinDir, a_zoneAdminFile,
3704 	    preinstallcheckPath);
3705 
3706 	/* set success/fail condition variables */
3707 
3708 	ckreturn(n);
3709 
3710 	echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check",
3711 		admnflag, doreboot, failflag, interrupted, intrflag,
3712 		ireboot, needconsult, nullflag, warnflag);
3713 }
3714 
3715 /*
3716  * Name:	pkginstall_check_in_zones
3717  * Description:	Check installation of a single package in the zones that
3718  *		are running from a list of zones
3719  * Arguments:	a_zlst - list of zones to check install the package
3720  *		a_idsName - pointer to string representing the data stream
3721  *			device (input data stream) containing the package to
3722  *			be check installed.
3723  *			If this is == NULL the package is assumed to be
3724  *			spooled in the zone temporary directory.
3725  *		a_altBinDir - pointer to string representing an alternative
3726  *			binary location directory to pass to pkginstall.
3727  *			If this is == NULL no alternative binary location is
3728  *			passed to pkginstall.
3729  *		a_zoneAdminFile - pointer to string representing the admin
3730  *			file to pass to pkginstall when checking the installing
3731  *			of the package.
3732  *			If this is == NULL no admin file is given to pkginstall.
3733  *		a_zoneTempDir - pointer to string representing the temporary
3734  *			directory in which spooled packages can be found if
3735  *			a_idsName is == NULL.
3736  */
3737 
3738 static int
3739 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3740 	char *a_zoneAdminFile, char *a_zoneTempDir)
3741 {
3742 	char		**inheritedPkgDirs;
3743 	char		*zoneName;
3744 	int		zoneIndex;
3745 	int		zonesSkipped = 0;
3746 	zone_state_t	zst;
3747 
3748 	for (zoneIndex = 0;
3749 		(zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3750 		zoneIndex++) {
3751 
3752 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3753 		if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3754 			zonesSkipped++;
3755 			echoDebug(DBG_SKIPPING_ZONE, zoneName);
3756 			continue;
3757 		}
3758 
3759 		inheritedPkgDirs = z_zlist_get_inherited_pkg_dirs(a_zlst,
3760 					zoneIndex);
3761 
3762 		pkginstall_check_in_one_zone(inheritedPkgDirs, zoneName,
3763 		    a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3764 		    z_zlist_get_scratch(a_zlst, zoneIndex), zst);
3765 	}
3766 
3767 	return (zonesSkipped);
3768 }
3769 
3770 /*
3771  * Name:	boot_and_pkginstall_check_in_zones
3772  * Description:	Check installation of a single package in the zones that
3773  *		are NOT running from a list of zones - each zone is booted,
3774  *		the package installation is checked, and the zone is halted.
3775  * Arguments:	a_zlst - list of zones to install the package into
3776  *		a_idsName - pointer to string representing the data stream
3777  *			device (input data stream) containing the package to
3778  *			be check installed.
3779  *			If this is == NULL the package is assumed to be
3780  *			spooled in the zone temporary directory.
3781  *		a_altBinDir - pointer to string representing an alternative
3782  *			binary location directory to pass to pkginstall.
3783  *			If this is == NULL no alternative binary location is
3784  *			passed to pkginstall.
3785  *		a_zoneAdminFile - pointer to string representing the admin
3786  *			file to pass to pkginstall when check installing the
3787  *			package.
3788  *			If this is == NULL no admin file is given to pkginstall.
3789  *		a_zoneTempDir - pointer to string representing the temporary
3790  *			directory in which spooled packages can be found if
3791  *			a_idsName is == NULL.
3792  */
3793 
3794 static int
3795 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName,
3796 	char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir)
3797 {
3798 	int		zoneIndex;
3799 	int		zonesSkipped = 0;
3800 	char		*zoneName;
3801 	boolean_t	b;
3802 	char		**inheritedPkgDirs;
3803 	zone_state_t	zst;
3804 
3805 	/* entry assertions */
3806 
3807 	assert(a_zlst != (zoneList_t)NULL);
3808 
3809 	/* entry debugging info */
3810 
3811 	echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY);
3812 	echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName),
3813 			PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3814 
3815 	/* process each zone in the list */
3816 
3817 	for (zoneIndex = 0;
3818 		(zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3819 		zoneIndex++) {
3820 
3821 		/* skip the zone if it IS running */
3822 
3823 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3824 		if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3825 			echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3826 			continue;
3827 		}
3828 
3829 		/* skip the zone if it is NOT bootable */
3830 
3831 		if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3832 			echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3833 			echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3834 			continue;
3835 		}
3836 
3837 		/* mount up the zone */
3838 
3839 		echo(MSG_BOOTING_ZONE, zoneName);
3840 		echoDebug(DBG_BOOTING_ZONE, zoneName);
3841 
3842 		b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3843 		    ZONE_STATE_MOUNTED);
3844 		if (b == B_FALSE) {
3845 			progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3846 			/* set fatal error return condition */
3847 			ckreturn(1);
3848 			zonesSkipped++;
3849 			continue;
3850 		}
3851 
3852 		/* determine list of directories inherited from global zone */
3853 
3854 		inheritedPkgDirs = z_zlist_get_inherited_pkg_dirs(a_zlst,
3855 					zoneIndex);
3856 
3857 		/* pre-installation check of the package in this zone */
3858 
3859 		pkginstall_check_in_one_zone(inheritedPkgDirs, zoneName,
3860 		    a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3861 		    z_zlist_get_scratch(a_zlst, zoneIndex),
3862 		    ZONE_STATE_MOUNTED);
3863 
3864 		/* restore original state of zone */
3865 
3866 		echo(MSG_RESTORE_ZONE_STATE, zoneName);
3867 		echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3868 
3869 		b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3870 	}
3871 
3872 	return (zonesSkipped);
3873 }
3874 
3875 /*
3876  * Function:	add_packages_in_global_with_zones
3877  * Description: call this function to add a list of packages in the global zone
3878  *		when one or more non-global zones exist
3879  * returns:
3880  *	B_TRUE to process next data stream
3881  *	B_FALSE to exit
3882  */
3883 
3884 static boolean_t
3885 add_packages_in_global_with_zones(char **a_pkgList, char *a_uri,
3886 	char *a_idsName, int a_repeat, char *a_altBinDir,
3887 	char *a_device, zoneList_t a_zlst)
3888 {
3889 static	char		*zoneTempDir = (char *)NULL;
3890 static	char		*zoneAdminFile = (char *)NULL;
3891 
3892 	boolean_t	b;
3893 	char		*packageDir;
3894 	char		instdir[PATH_MAX];
3895 	char		respfile_path[PATH_MAX];
3896 	char		zoneStreamName[PATH_MAX] = {'\0'};
3897 	int		i;
3898 	int		n;
3899 	int		savenpkgs = npkgs;
3900 	int		zonesSkipped;
3901 	boolean_t	globalPresent;
3902 
3903 	/* entry assertions */
3904 
3905 	assert(a_pkgList != (char **)NULL);
3906 	assert(a_zlst != (zoneList_t)NULL);
3907 
3908 	echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY);
3909 	echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs, PSTR(a_uri),
3910 			PSTR(a_idsName), a_repeat, PSTR(a_device));
3911 
3912 	/* create temporary directory for use by zone operations */
3913 
3914 	create_zone_tempdir(&zoneTempDir, tmpdir);
3915 
3916 	/* create hands off settings admin file for use in a non-global zone */
3917 
3918 	create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile);
3919 
3920 	/* determine directory where packages can be found */
3921 
3922 	if (a_idsName == (char *)NULL) {
3923 		/* no stream - directory containing packages provided */
3924 		packageDir = pkgdev.dirname;
3925 	} else {
3926 		packageDir = zoneTempDir;
3927 	}
3928 
3929 	/* unpack and check all packages */
3930 
3931 	b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3932 	if (b != B_TRUE) {
3933 		quit(1);
3934 	}
3935 
3936 	/*
3937 	 * if the packages are contained in a directory, convert the
3938 	 * packages into individual streams because pkgZoneInstall is only able
3939 	 * to pass a stream to the non-global zone's pkginstall command.
3940 	 * After this code is executed:
3941 	 * if the original input was a datastream:
3942 	 * -> that datastream has been unpacked into "instdir"
3943 	 * if the original input was a directory with packages in it:
3944 	 * -> those packages have been placed into a single datastream
3945 	 */
3946 
3947 	if (a_idsName == (char *)NULL) {
3948 		for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3949 			char	*pkgs[2];
3950 
3951 			/* package is not a stream - create one */
3952 
3953 			(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3954 				"%s/%s.dstream", zoneTempDir, pkginst);
3955 
3956 			echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst,
3957 				zoneStreamName);
3958 
3959 			/* set up list of packages to be this package only */
3960 
3961 			pkgs[0] = pkginst;
3962 			pkgs[1] = (char *)NULL;
3963 
3964 			n = pkgtrans(packageDir, zoneStreamName, pkgs,
3965 					PT_SILENT|PT_ODTSTREAM, NULL, NULL);
3966 			if (n != 0) {
3967 				progerr(ERR_CANNOT_CONVERT_PKGSTRM,
3968 					pkginst, packageDir, zoneStreamName);
3969 				quit(1);
3970 			}
3971 			npkgs--;
3972 		}
3973 		npkgs = savenpkgs;
3974 	}
3975 
3976 	/*
3977 	 * Phase I - run collect dependency information for all packages for all
3978 	 * zones - this involves running pkginstall with the "preinstallcheck"
3979 	 * option which causes all dependency checks to be performed without
3980 	 * actually doing the installation of the packages. This information is
3981 	 * gathered in the zone temporary directory and is used later to present
3982 	 * the dependency check results to the system administrator depending
3983 	 * on the administration settings.
3984 	 */
3985 
3986 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3987 
3988 		/* reset interrupted flag before calling pkginstall */
3989 
3990 		interrupted = 0;	/* last action was NOT quit */
3991 
3992 		/*
3993 		 * if this package is marked "install in this zone only", then
3994 		 * do not check dependencies in any other zone
3995 		 */
3996 
3997 		if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3998 			echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst);
3999 			npkgs--;
4000 			continue;
4001 		}
4002 
4003 		/*
4004 		 * if operation failed in global zone do not propagate
4005 		 * to any non-global zones
4006 		 */
4007 
4008 		if (interrupted != 0) {
4009 			echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
4010 			echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
4011 			break;
4012 		}
4013 
4014 		echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall",
4015 			admnflag, doreboot, failflag, interrupted, intrflag,
4016 			ireboot, needconsult, nullflag, warnflag);
4017 
4018 		/*
4019 		 * call pkginstall to verify this package for all non-global
4020 		 * zones that are currently booted
4021 		 */
4022 
4023 		zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName,
4024 				a_altBinDir, admnfile, zoneTempDir);
4025 
4026 		/*
4027 		 * if any zones were skipped (becuase they are not currently
4028 		 * booted), boot each zone one at a time and call pkginstall
4029 		 * to verify this package for each such non-global zone
4030 		 */
4031 
4032 		if (zonesSkipped > 0) {
4033 			echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
4034 
4035 			zonesSkipped =
4036 				boot_and_pkginstall_check_in_zones(a_zlst,
4037 				a_idsName, a_altBinDir, admnfile,
4038 				zoneTempDir);
4039 
4040 			if (zonesSkipped > 0) {
4041 				progerr(ERR_INSTALL_ZONES_SKIPPED,
4042 							zonesSkipped);
4043 			}
4044 		}
4045 
4046 		npkgs--;
4047 	}
4048 
4049 	/*
4050 	 * At this point, all of the dependency information has been gathered
4051 	 * and is ready to be analyzed. This function processes all of that
4052 	 * dependency information and presents the results to the system
4053 	 * administrator, depending on the current administration settings.
4054 	 */
4055 
4056 	i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir);
4057 	if (i != 0) {
4058 		/* dependency checks failed - exit */
4059 		quit(i);
4060 	}
4061 
4062 	npkgs = savenpkgs;
4063 
4064 	/*
4065 	 * reset all error return condition variables that may have been
4066 	 * set during package installation dependency checking so that they
4067 	 * do not reflect on the success/failure of the actual package
4068 	 * installation operations
4069 	 */
4070 
4071 	resetreturn();
4072 
4073 	/*
4074 	 * At this point, all of the dependency checking is completed, and
4075 	 * the installation of the packages can proceed. Install each package
4076 	 * one at a time, starting with the global zone, and the for each
4077 	 * non-global zone that is booted, and then for each non-global zone
4078 	 * that is not currently booted.
4079 	 */
4080 
4081 	globalPresent = z_on_zone_spec(GLOBAL_ZONENAME);
4082 
4083 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4084 		/*
4085 		 * if immediate reboot required from last package and this is
4086 		 * not 'pkgask' then suspend installation of remaining packages
4087 		 */
4088 
4089 		if ((ireboot != 0) && (askflag == 0)) {
4090 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4091 				continue;
4092 		}
4093 
4094 		/*
4095 		 * handle interrupt if the previous pkginstall was interrupted
4096 		 */
4097 
4098 		if (continue_installation() == B_FALSE) {
4099 			return (B_FALSE);
4100 		}
4101 
4102 		/*
4103 		 * if pkgask, handle response file creation:
4104 		 * - if the response file is a directory, then create a path to
4105 		 * -- a package instance within the response file directory.
4106 		 * - If the response file is NOT a directory, if more than one
4107 		 * -- package is to be installed.
4108 		 */
4109 
4110 		if ((askflag != 0) && (respdir != (char *)NULL)) {
4111 			(void) snprintf(respfile_path, sizeof (respfile_path),
4112 					"%s/%s", respdir, pkginst);
4113 			respfile = respfile_path;
4114 		}
4115 
4116 		echo(MSG_PROC_INST, pkginst,
4117 			(a_uri && a_idsName) ? a_uri : a_device);
4118 
4119 		/*
4120 		 * If we're installing another package in the same
4121 		 * session, the second through nth pkginstall, must
4122 		 * continue from where the prior one left off. For this
4123 		 * reason, the continuation feature (implied by the
4124 		 * nature of the command) is used for the remaining
4125 		 * packages.
4126 		 */
4127 
4128 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4129 			pkgcontsrc = pkgdrtarg;
4130 		}
4131 
4132 		if (globalPresent) {
4133 			/*
4134 			 * call pkginstall for this package for the global zone
4135 			 */
4136 
4137 			echo(MSG_INSTALLING_PKG_IN_GZ, pkginst);
4138 
4139 			/* reset interrupted flag before calling pkginstall */
4140 
4141 			interrupted = 0;	/* last action was NOT quit */
4142 
4143 			n = pkgInstall(get_inst_root(), NULL, packageDir,
4144 			    a_altBinDir,  NULL);
4145 
4146 			/* set success/fail condition variables */
4147 
4148 			ckreturn(n);
4149 
4150 			/*
4151 			 * if operation failed in global zone do not propagate
4152 			 * to any non-global zones
4153 			 */
4154 
4155 			if (interrupted != 0) {
4156 				echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst);
4157 				echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES,
4158 				    pkginst);
4159 				break;
4160 			}
4161 		}
4162 
4163 		/*
4164 		 * if this package is marked "install in this zone only",
4165 		 * then only need to install the package in the global zone;
4166 		 * skip installation in any non-global zones.
4167 		 */
4168 
4169 		if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
4170 			echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst);
4171 			npkgs--;
4172 			continue;
4173 		}
4174 
4175 		echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones",
4176 			admnflag, doreboot, failflag, interrupted, intrflag,
4177 			ireboot, needconsult, nullflag, warnflag);
4178 
4179 		/* install package in currently booted zones */
4180 
4181 		zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir,
4182 					zoneAdminFile, zoneTempDir);
4183 
4184 		/* install package in zones that are not currently booted */
4185 
4186 		if (zonesSkipped > 0) {
4187 			echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
4188 
4189 			zonesSkipped = boot_and_install_in_zones(a_zlst,
4190 				a_idsName, a_altBinDir, zoneAdminFile,
4191 				zoneTempDir);
4192 
4193 			if (zonesSkipped > 0) {
4194 				progerr(ERR_INSTALL_ZONES_SKIPPED,
4195 							zonesSkipped);
4196 			}
4197 		}
4198 
4199 		/*
4200 		 * package completely installed - remove any temporary stream
4201 		 * of the package that might have been created
4202 		 */
4203 
4204 		if (a_idsName == (char *)NULL) {
4205 			/* locate temporary stream created earlier */
4206 			(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
4207 				"%s/%s.dstream", zoneTempDir, pkginst);
4208 			/* remove stream - no longer needed */
4209 			echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName,
4210 					pkginst);
4211 			(void) remove(zoneStreamName);
4212 		} else {
4213 			/* remove package - no longer needed */
4214 			if (snprintf(instdir, sizeof (instdir), "%s/%s",
4215 					zoneTempDir, pkginst) >= PATH_MAX) {
4216 				progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir);
4217 				quit(1);
4218 			}
4219 			echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst);
4220 			(void) remove(instdir);
4221 		}
4222 
4223 		/* decrement number of packages left to install */
4224 
4225 		npkgs--;
4226 
4227 		/*
4228 		 * if no packages left to install, unmount package source
4229 		 * device if appropriate
4230 		 */
4231 
4232 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4233 			(void) chdir("/");
4234 			if (!a_idsName) {
4235 				echoDebug(DBG_UNMOUNTING_DEV,
4236 							PSTR(pkgdev.mount));
4237 				(void) pkgumount(&pkgdev);
4238 			}
4239 		}
4240 	}
4241 
4242 	/*
4243 	 * all packages in the package list have been installed.
4244 	 * Continue with installation if:
4245 	 * -- immediate reboot is NOT required
4246 	 * -- there are more packages to install
4247 	 * -- the package source is a path to a file
4248 	 * else return do NOT continue.
4249 	 */
4250 
4251 	if ((ireboot == 0) && (a_repeat != 0) &&
4252 		(pkgdev.pathname == (char *)NULL)) {
4253 		return (B_TRUE);
4254 	}
4255 
4256 	/* return 'dont continue' */
4257 
4258 	return (B_FALSE);
4259 }
4260 
4261 /*
4262  * Function:	add_packages_in_nonglobal_zone
4263  * Description: call this function to add a list of packages in a non-global
4264  *		zone
4265  * returns:
4266  *	B_TRUE to process next data stream
4267  *	B_FALSE to exit
4268  */
4269 
4270 static boolean_t
4271 add_packages_in_nonglobal_zone(char **a_pkgList, char *a_uri,
4272 	char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
4273 {
4274 static	char		*zoneTempDir = (char *)NULL;
4275 
4276 	char		*packageDir;
4277 	char		respfile_path[PATH_MAX];
4278 	int		i;
4279 	int		n;
4280 	boolean_t	b;
4281 	int		savenpkgs = npkgs;
4282 
4283 	/* entry assertions */
4284 
4285 	assert(a_pkgList != (char **)NULL);
4286 
4287 	/* entry debugging info */
4288 
4289 	echoDebug(DBG_ADDPACKAGES_LZ_ENTRY);
4290 	echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_uri), PSTR(a_idsName),
4291 		a_repeat, PSTR(a_device));
4292 
4293 	/* create temporary directory for use by zone operations */
4294 
4295 	create_zone_tempdir(&zoneTempDir, tmpdir);
4296 
4297 	/*
4298 	 * package can be in a number of formats:
4299 	 * - file containing package stream (pkgadd -d file [pkgs])
4300 	 * - directory containing packages (pkgadd -d /dir [pkgs])
4301 	 * - device containing packages (pkgadd -d diskette1 [pkgs])
4302 	 * non-global zones can be passed open file drescriptors and
4303 	 * strings as arguments
4304 	 * - for file containing package stream
4305 	 * -- the stream can be passed directly to the non-global zone
4306 	 * - for directory
4307 	 * -- convert packages to datastream to pass to the non-global zone
4308 	 * - for device
4309 	 */
4310 
4311 	/* determine directory where packages can be found */
4312 
4313 	if (a_idsName == (char *)NULL) {
4314 		/* no stream - directory containing packages provided */
4315 		packageDir = pkgdev.dirname;
4316 	} else {
4317 		packageDir = zoneTempDir;
4318 	}
4319 
4320 	b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
4321 	if (b != B_TRUE) {
4322 		quit(1);
4323 	}
4324 
4325 	/*
4326 	 * this is the main loop where all of the packages (as listed in the
4327 	 * package list) are added one at a time.
4328 	 */
4329 
4330 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4331 		npkgs--;
4332 	}
4333 
4334 	npkgs = savenpkgs;
4335 
4336 	/*
4337 	 * this is the main loop where all of the packages (as listed in the
4338 	 * package list) are added one at a time.
4339 	 */
4340 
4341 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4342 		/*
4343 		 * if immediate reboot required from last package and this is
4344 		 * not 'pkgask' then suspend installation of remaining packages
4345 		 */
4346 
4347 		if ((ireboot != 0) && (askflag == 0)) {
4348 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4349 				continue;
4350 		}
4351 
4352 		/*
4353 		 * handle interrupt if the previous pkginstall was interrupted
4354 		 */
4355 
4356 		if (continue_installation() == B_FALSE) {
4357 			return (B_FALSE);
4358 		}
4359 
4360 		/*
4361 		 * if pkgask, handle response file creation:
4362 		 * - if the response file is a directory, then create a path to
4363 		 * -- a package instance within the response file directory.
4364 		 * - If the response file is NOT a directory, if more than one
4365 		 * -- package is to be installed.
4366 		 */
4367 
4368 		if ((askflag != 0) && (respdir != (char *)NULL)) {
4369 			(void) snprintf(respfile_path, sizeof (respfile_path),
4370 					"%s/%s", respdir, pkginst);
4371 			respfile = respfile_path;
4372 		}
4373 
4374 		echo(MSG_PROC_INST, pkginst,
4375 			(a_uri && a_idsName) ? a_uri : a_device);
4376 
4377 		/*
4378 		 * If we're installing another package in the same
4379 		 * session, the second through nth pkginstall, must
4380 		 * continue from where the prior one left off. For this
4381 		 * reason, the continuation feature (implied by the
4382 		 * nature of the command) is used for the remaining
4383 		 * packages.
4384 		 */
4385 
4386 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4387 			pkgcontsrc = pkgdrtarg;
4388 		}
4389 
4390 		/* reset interrupted flag before calling pkginstall */
4391 
4392 		interrupted = 0;	/* last action was NOT quit */
4393 
4394 		/* call pkginstall for this package */
4395 
4396 		n = pkgInstall(get_inst_root(), NULL,
4397 				packageDir, a_altBinDir,
4398 				(char **)NULL);
4399 
4400 		/* set success/fail condition variables */
4401 
4402 		ckreturn(n);
4403 
4404 		/* decrement number of packages left to install */
4405 
4406 		npkgs--;
4407 
4408 		/*
4409 		 * if no packages left to install, unmount package source
4410 		 * device if appropriate
4411 		 */
4412 
4413 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4414 			(void) chdir("/");
4415 			if (!a_idsName) {
4416 				(void) pkgumount(&pkgdev);
4417 			}
4418 		}
4419 	}
4420 
4421 	/*
4422 	 * all packages in the package list have been installed.
4423 	 * Continue with installation if:
4424 	 * -- immediate reboot is NOT required
4425 	 * -- there are more packages to install
4426 	 * -- the package source is a path to a file
4427 	 * else return do NOT continue.
4428 	 */
4429 
4430 	if ((ireboot == 0) && (a_repeat != 0) &&
4431 		(pkgdev.pathname == (char *)NULL)) {
4432 		return (B_TRUE);
4433 	}
4434 
4435 	/* return 'dont continue' */
4436 
4437 	return (B_FALSE);
4438 }
4439 
4440 /*
4441  * Function:	add_packages_in_global_no_zones
4442  * Description: call this function to add a list of packages in the global zone
4443  *		when no non-global zones exist
4444  * returns:
4445  *	B_TRUE to process next data stream
4446  *	B_FALSE to exit
4447  */
4448 
4449 static boolean_t
4450 add_packages_in_global_no_zones(char **a_pkgList, char *a_uri,
4451 	char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
4452 {
4453 	int		n;
4454 	int		i;
4455 	char		respfile_path[PATH_MAX];
4456 	CAF_T		flags = 0;
4457 
4458 	/* entry assertions */
4459 
4460 	assert(a_pkgList != (char **)NULL);
4461 
4462 	echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY);
4463 	echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs, PSTR(a_uri),
4464 		PSTR(a_idsName), a_repeat, PSTR(a_device));
4465 
4466 	/*
4467 	 * set flags for applicability check
4468 	 */
4469 
4470 	/* in the global zone */
4471 
4472 	flags |= CAF_IN_GLOBAL_ZONE;
4473 
4474 	/* set -G flag */
4475 
4476 	if (globalZoneOnly == B_TRUE) {
4477 		flags |= CAF_SCOPE_GLOBAL;
4478 	}
4479 
4480 	/*
4481 	 * this is the main loop where all of the packages (as listed in the
4482 	 * package list) are added one at a time.
4483 	 */
4484 
4485 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4486 		/*
4487 		 * if immediate reboot required from last package and this is
4488 		 * not 'pkgask' then suspend installation of remaining packages
4489 		 */
4490 
4491 		if ((ireboot != 0) && (askflag == 0)) {
4492 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4493 				continue;
4494 		}
4495 
4496 		/*
4497 		 * handle interrupt if the previous pkginstall was interrupted
4498 		 */
4499 
4500 		if (continue_installation() == B_FALSE) {
4501 			return (B_FALSE);
4502 		}
4503 
4504 		/*
4505 		 * check package applicability to install in this context
4506 		 */
4507 
4508 		if (check_applicability(pkgdev.dirname,
4509 			pkginst, get_inst_root(), flags) == B_FALSE) {
4510 			progerr(ERR_PKG_NOT_APPLICABLE, pkginst);
4511 			quit(1);
4512 		}
4513 
4514 		/*
4515 		 * if pkgask, handle response file creation:
4516 		 * - if the response file is a directory, then create a path to
4517 		 * -- a package instance within the response file directory.
4518 		 * - If the response file is NOT a directory, if more than one
4519 		 * -- package is to be installed.
4520 		 */
4521 
4522 		if ((askflag != 0) && (respdir != (char *)NULL)) {
4523 			(void) snprintf(respfile_path, sizeof (respfile_path),
4524 					"%s/%s", respdir, pkginst);
4525 			respfile = respfile_path;
4526 		}
4527 
4528 		echo(MSG_PROC_INST, pkginst,
4529 			(a_uri && a_idsName) ? a_uri : a_device);
4530 
4531 		/*
4532 		 * If we're installing another package in the same
4533 		 * session, the second through nth pkginstall, must
4534 		 * continue from where the prior one left off. For this
4535 		 * reason, the continuation feature (implied by the
4536 		 * nature of the command) is used for the remaining
4537 		 * packages.
4538 		 */
4539 
4540 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4541 			pkgcontsrc = pkgdrtarg;
4542 		}
4543 
4544 		/* reset interrupted flag before calling pkginstall */
4545 
4546 		interrupted = 0;	/* last action was NOT quit */
4547 
4548 		/* call pkginstall for this package */
4549 
4550 		n = pkgInstall(get_inst_root(), a_idsName,
4551 				pkgdev.dirname, a_altBinDir,
4552 				z_get_inherited_file_systems());
4553 
4554 		/* set success/fail condition variables */
4555 
4556 		ckreturn(n);
4557 
4558 		/* decrement number of packages left to install */
4559 
4560 		npkgs--;
4561 
4562 		/*
4563 		 * if no packages left to install, unmount package source
4564 		 * device if appropriate
4565 		 */
4566 
4567 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4568 			(void) chdir("/");
4569 			if (!a_idsName) {
4570 				(void) pkgumount(&pkgdev);
4571 			}
4572 		}
4573 	}
4574 
4575 	/*
4576 	 * all packages in the package list have been installed.
4577 	 * Continue with installation if:
4578 	 * -- immediate reboot is NOT required
4579 	 * -- there are more packages to install
4580 	 * -- the package source is a path to a file
4581 	 * else return do NOT continue.
4582 	 */
4583 
4584 	if ((ireboot == 0) && (a_repeat != 0) &&
4585 		(pkgdev.pathname == (char *)NULL)) {
4586 		return (B_TRUE);
4587 	}
4588 
4589 	/* return 'dont continue' */
4590 
4591 	return (B_FALSE);
4592 }
4593 
4594 /*
4595  * returns:
4596  *	B_TRUE to process next data stream
4597  *	B_FALSE to exit
4598  */
4599 
4600 static boolean_t
4601 add_packages(char **a_pkgList, char *a_uri,
4602 	char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device,
4603 	boolean_t a_noZones)
4604 {
4605 	zoneList_t	zlst;
4606 	boolean_t	b;
4607 
4608 	/* entry assertions */
4609 
4610 	assert(a_pkgList != (char **)NULL);
4611 
4612 	echoDebug(DBG_ADDPACKAGES_ENTRY);
4613 	echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_uri), PSTR(a_idsName),
4614 		a_repeat, PSTR(a_altBinDir), PSTR(a_device));
4615 
4616 	/*
4617 	 * if running in the global zone AND one or more non-global
4618 	 * zones exist, add packages in a 'zones aware' manner, else
4619 	 * add packages in the standard 'non-zones aware' manner.
4620 	 */
4621 
4622 	if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) {
4623 		/* in non-global zone */
4624 
4625 		echoDebug(DBG_IN_LZ);
4626 
4627 		b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4628 		if (b != B_TRUE) {
4629 			progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4630 			/* set fatal error return condition */
4631 			ckreturn(1);
4632 			return (B_FALSE);
4633 		}
4634 
4635 		b = add_packages_in_nonglobal_zone(a_pkgList, a_uri, a_idsName,
4636 			a_repeat, a_altBinDir, a_device);
4637 
4638 		(void) z_unlock_this_zone(ZLOCKS_ALL);
4639 
4640 		return (B_FALSE);
4641 	}
4642 
4643 	/* running in the global zone */
4644 
4645 	b = z_non_global_zones_exist();
4646 	if ((a_noZones == B_FALSE) && (b == B_TRUE) &&
4647 					(globalZoneOnly == B_FALSE)) {
4648 
4649 		echoDebug(DBG_IN_GZ_WITH_LZ);
4650 
4651 		/* error if -V specified - what to use in non-global zone? */
4652 
4653 		if (vfstab_file) {
4654 			progerr(ERR_V_USED_WITH_GZS);
4655 			quit(1);
4656 		}
4657 
4658 		/* get a list of all non-global zones */
4659 		zlst = z_get_nonglobal_zone_list();
4660 		if (zlst == (zoneList_t)NULL) {
4661 			progerr(ERR_CANNOT_GET_ZONE_LIST);
4662 			quit(1);
4663 		}
4664 
4665 		/* need to lock all of the zones */
4666 
4667 		quitSetZonelist(zlst);
4668 		b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN);
4669 		if (b == B_FALSE) {
4670 			z_free_zone_list(zlst);
4671 			progerr(ERR_CANNOT_LOCK_ZONES);
4672 			/* set fatal error return condition */
4673 			ckreturn(1);
4674 			return (B_FALSE);
4675 		}
4676 
4677 		/* add packages to all zones */
4678 
4679 		b = add_packages_in_global_with_zones(a_pkgList, a_uri,
4680 			a_idsName, a_repeat, a_altBinDir, a_device, zlst);
4681 
4682 		/* unlock all zones */
4683 
4684 		(void) z_unlock_zones(zlst, ZLOCKS_ALL);
4685 		quitSetZonelist((zoneList_t)NULL);
4686 
4687 		/* free list of all non-global zones */
4688 
4689 		z_free_zone_list(zlst);
4690 
4691 		return (B_FALSE);
4692 	}
4693 
4694 	/* in global zone no non-global zones */
4695 
4696 	echoDebug(DBG_IN_GZ_NO_LZ);
4697 
4698 	b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4699 	if (b != B_TRUE) {
4700 		progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4701 		/* set fatal error return condition */
4702 		ckreturn(1);
4703 		return (B_FALSE);
4704 	}
4705 
4706 	b = add_packages_in_global_no_zones(a_pkgList, a_uri, a_idsName,
4707 		a_repeat, a_altBinDir, a_device);
4708 
4709 	(void) z_unlock_this_zone(ZLOCKS_ALL);
4710 
4711 	return (B_FALSE);
4712 }
4713