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