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