xref: /illumos-gate/usr/src/cmd/svr4pkg/pkgadd/main.c (revision d7c57852794a9ac50d4b6a9c4161cb10919658aa)
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 			echoDebug(DBG_CANNOT_GET_PKGLIST);
1112 
1113 			progerr(ERR_NOPKGS, pkgdev.dirname);
1114 			quit(1);
1115 			/* NOTREACHED */
1116 		}
1117 
1118 		/*
1119 		 * count the number of packages to install
1120 		 * NOTE: npkgs is a global variable that is referenced by quit.c
1121 		 * when error messages are generated - it is referenced directly
1122 		 * by the other functions called below...
1123 		 */
1124 
1125 		for (npkgs = 0; pkglist[npkgs] != (char *)NULL; /* void */) {
1126 			echoDebug(DBG_PKG_SELECTED, npkgs, pkglist[npkgs]);
1127 			npkgs++;
1128 		}
1129 
1130 		/* output number of packages to be added */
1131 
1132 		echoDebug(DBG_NUM_PKGS_TO_ADD, npkgs);
1133 
1134 		/*
1135 		 * if pkgask and response container is a file (not a directory),
1136 		 * and there is more than one package to install, then it is an
1137 		 * error - too many packages to install when response container
1138 		 * is a file.
1139 		 */
1140 
1141 		if ((askflag != 0) && (respdir == (char *)NULL) &&
1142 		    (npkgs > 1)) {
1143 			progerr(ERR_TOO_MANY_PKGS);
1144 			quit(1);
1145 			/* NOTREACHED */
1146 		}
1147 
1148 		/*
1149 		 * package list generated - add packages
1150 		 */
1151 
1152 		b = add_packages(pkglist, ids_name, repeat,
1153 		    altBinDir, device, noZones);
1154 
1155 		/*
1156 		 * close open input data stream (source package) if left open.
1157 		 */
1158 
1159 		if (ids_name) {
1160 			echoDebug(DBG_CLOSING_STREAM, ids_name,
1161 			    PSTR(pkgdev.dirname));
1162 			(void) ds_close(1);
1163 			rrmdir(pkgdev.dirname);
1164 			ids_name = NULL;
1165 			quitSetIdsName(ids_name);
1166 		}
1167 
1168 		/*
1169 		 * continue with next sequence of packages if continue set
1170 		 */
1171 
1172 		if (b == B_TRUE) {
1173 			continue;
1174 		}
1175 
1176 		/*
1177 		 * not continuing - quit with 0 exit code
1178 		 */
1179 
1180 		quit(0);
1181 		/* NOTREACHED */
1182 	}
1183 
1184 	/* NOTREACHED */
1185 }
1186 
1187 /*
1188  * *****************************************************************************
1189  * static internal (private) functions
1190  * *****************************************************************************
1191  */
1192 
1193 /*
1194  * Name:	pkgZoneCheckInstall
1195  * Description:	Invoke pkginstall in a specified zone to perform a preinstall
1196  *		check of the a single package in the specified zone
1197  * Arguments:	a_zoneName - pointer to string representing the name of the
1198  *			zone to check install the package in.
1199  *		a_zoneState - current state of the zone; must be mounted or
1200  *			running.
1201  *		a_idsName - pointer to string representing the data stream
1202  *			device (input data stream) containing the package to
1203  *			be check installed.
1204  *		a_altBinDir - pointer to string representing an alternative
1205  *			binary location directory to pass to pkginstall.
1206  *			If this is == NULL no alternative binary location is
1207  *			passed to pkginstall.
1208  *		a_adminFile - pointer to string representing the admin
1209  *			file to pass to pkginstall when installing the package.
1210  *			If this is == NULL no admin file is given to pkginstall.
1211  *		a_stdoutPath - pointer to string representing the local path
1212  *			into which all output written by pkginstall to stdout
1213  *			is stored.
1214  *			If this is == NULL stdout is redirected to /dev/null
1215  *		a_tmpzn - B_TRUE when this zone is booted by the package
1216  *			command or B_FALSE if it was running before.
1217  * Returns:	int	(see ckreturn() function for details)
1218  *		0 - success
1219  *		1 - package operation failed (fatal error)
1220  *		2 - non-fatal error (warning)
1221  *		3 - user selected quit (operation interrupted)
1222  *		4 - admin settings prevented operation
1223  *		5 - interaction required and -n (non-interactive) specified
1224  *		"10" will be added to indicate "immediate reboot required"
1225  *		"20" will be added to indicate "reboot after install required"
1226  */
1227 
1228 static int
1229 pkgZoneCheckInstall(char *a_zoneName, zone_state_t a_zoneState,
1230     char *a_idsName, char *a_altBinDir, char *a_adminFile,
1231     char *a_stdoutPath, boolean_t a_tmpzn)
1232 {
1233 	char	*arg[MAXARGS];
1234 	char	*p;
1235 	char	adminfd_path[PATH_MAX];
1236 	char	path[PATH_MAX];
1237 	char	pkgstreamfd_path[PATH_MAX];
1238 	int	fds[MAX_FDS];
1239 	int	maxfds;
1240 	int	n;
1241 	int	nargs;
1242 
1243 	/* entry assertions */
1244 
1245 	assert(a_zoneName != (char *)NULL);
1246 	assert(*a_zoneName != '\0');
1247 
1248 	/* entry debugging info */
1249 
1250 	echoDebug(DBG_PKGZONECHECKINSTALL_ENTRY);
1251 	echoDebug(DBG_PKGZONECHECKINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1252 	    PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1253 	    a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "/",
1254 	    PSTR(a_idsName), PSTR(a_adminFile), PSTR(a_stdoutPath));
1255 
1256 	/* generate full path to 'phatinstall' to run in zone */
1257 
1258 	(void) snprintf(path, sizeof (path), "%s/pkginstall",
1259 	    "/usr/sadm/install/bin");
1260 
1261 	/* start at first file descriptor */
1262 
1263 	maxfds = 0;
1264 
1265 	/*
1266 	 * generate argument list for call to pkginstall
1267 	 */
1268 
1269 	/* start at argument 0 */
1270 
1271 	nargs = 0;
1272 
1273 	/* first argument is always: full path to executable */
1274 
1275 	arg[nargs++] = path;
1276 
1277 	/*
1278 	 * second argument is always: pass -O debug to pkginstall: debug mode
1279 	 */
1280 	if (debugFlag == B_TRUE) {
1281 		arg[nargs++] = "-O";
1282 		arg[nargs++] = "debug";
1283 	}
1284 
1285 	/* pkgadd -G: pass -G to pkginstall */
1286 
1287 	if (globalZoneOnly == B_TRUE) {
1288 		arg[nargs++] = "-G";
1289 	}
1290 
1291 	/* pkgadd -b dir: pass -b to pkginstall */
1292 
1293 	if (a_altBinDir != (char *)NULL) {
1294 		arg[nargs++] = "-b";
1295 		arg[nargs++] = a_altBinDir;
1296 	}
1297 
1298 	/* pkgadd -C: pass -C to pkginstall: disable checksum */
1299 
1300 	if (disableChecksum) {
1301 		arg[nargs++] = "-C";
1302 	}
1303 
1304 	/* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1305 
1306 	if (disableAttributes) {
1307 		arg[nargs++] = "-A";
1308 	}
1309 
1310 	/*
1311 	 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1312 	 * pkg requiring operator interaction during a procedure script
1313 	 * (common before on1093)
1314 	 */
1315 
1316 	if (old_pkg) {
1317 		arg[nargs++] = "-o";
1318 	}
1319 
1320 	/*
1321 	 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1322 	 * symlinks consistent with old behavior
1323 	 */
1324 
1325 	if (old_symlinks) {
1326 		arg[nargs++] = "-y";
1327 	}
1328 
1329 	/*
1330 	 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1331 	 * package name length to be restricted
1332 	 */
1333 
1334 	if (ABI_namelength) {
1335 		arg[nargs++] = "-e";
1336 	}
1337 
1338 	/* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1339 
1340 	arg[nargs++] = "-S";
1341 
1342 	/* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1343 
1344 	arg[nargs++] = "-M";
1345 
1346 	/* pkgadd -v: pass -v to pkginstall: never trace scripts */
1347 
1348 	/* if running pkgask, pass -i to pkginstall: running pkgask */
1349 
1350 	if (askflag) {
1351 		return (0);
1352 	}
1353 
1354 	/* pass "-O enable-hollow-package-support" */
1355 
1356 	if (is_depend_pkginfo_DB()) {
1357 		arg[nargs++] = "-O";
1358 		arg[nargs++] = "enable-hollow-package-support";
1359 	}
1360 
1361 	/* check is always in non-interactive mode */
1362 
1363 	arg[nargs++] = "-n";
1364 
1365 	/* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1366 
1367 	if (a_adminFile) {
1368 		int fd;
1369 		fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1370 		if (fd < 0) {
1371 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1372 			    errno, strerror(errno));
1373 			return (1);
1374 		}
1375 		(void) snprintf(adminfd_path, sizeof (adminfd_path),
1376 		    "/proc/self/fd/%d", fd);
1377 		fds[maxfds++] = fd;
1378 		arg[nargs++] = "-a";
1379 		arg[nargs++] = adminfd_path;
1380 	}
1381 
1382 	/* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1383 
1384 	if (a_zoneState == ZONE_STATE_MOUNTED) {
1385 		arg[nargs++] = "-R";
1386 		arg[nargs++] = "/a";
1387 	}
1388 
1389 	/* pass -N to pkginstall: program name to report */
1390 
1391 	arg[nargs++] = "-N";
1392 	arg[nargs++] = get_prog_name();
1393 
1394 	/* pass "-O preinstallcheck" */
1395 
1396 	arg[nargs++] = "-O";
1397 	arg[nargs++] = "preinstallcheck";
1398 
1399 	/* add "-O addzonename" */
1400 
1401 	arg[nargs++] = "-O";
1402 	arg[nargs++] = "addzonename";
1403 
1404 	/*
1405 	 * add parent zone info/type
1406 	 */
1407 
1408 	p = z_get_zonename();
1409 	if ((p != NULL) && (*p != '\0')) {
1410 			char	zn[MAXPATHLEN];
1411 			(void) snprintf(zn, sizeof (zn),
1412 			    "parent-zone-name=%s", p);
1413 			arg[nargs++] = "-O";
1414 			arg[nargs++] = strdup(zn);
1415 	}
1416 
1417 	/* current zone type */
1418 
1419 	arg[nargs++] = "-O";
1420 	if (z_running_in_global_zone() == B_TRUE) {
1421 			char	zn[MAXPATHLEN];
1422 			(void) snprintf(zn, sizeof (zn),
1423 			    "parent-zone-type=%s",
1424 			    TAG_VALUE_GLOBAL_ZONE);
1425 			arg[nargs++] = strdup(zn);
1426 	} else {
1427 			char	zn[MAXPATHLEN];
1428 			(void) snprintf(zn, sizeof (zn),
1429 			    "parent-zone-type=%s",
1430 			    TAG_VALUE_NONGLOBAL_ZONE);
1431 			arg[nargs++] = strdup(zn);
1432 	}
1433 
1434 	/* Add the pkgserv options */
1435 	arg[nargs++] = "-O";
1436 	arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode());
1437 
1438 	/* add in the package stream file */
1439 
1440 	if (a_idsName != NULL) {
1441 		int fd;
1442 		fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1443 		if (fd < 0) {
1444 			progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1445 			    pkginst, strerror(errno));
1446 			quit(1);
1447 		}
1448 		(void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1449 		    "/proc/self/fd/%d", fd);
1450 		fds[maxfds++] = fd;
1451 		arg[nargs++] = pkgstreamfd_path;
1452 	} else {
1453 		progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1454 		quit(1);
1455 	}
1456 
1457 	/* add package instance name */
1458 
1459 	arg[nargs++] = pkginst;
1460 
1461 	/* terminate the argument list */
1462 
1463 	arg[nargs++] = NULL;
1464 
1465 	/*
1466 	 * run the appropriate pkginstall command in the specified zone
1467 	 */
1468 
1469 	if (debugFlag == B_TRUE) {
1470 		echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
1471 		for (n = 0; arg[n]; n++) {
1472 			echoDebug(DBG_ARG, n, arg[n]);
1473 		}
1474 	}
1475 
1476 	/* terminate file descriptor list */
1477 
1478 	fds[maxfds] = -1;
1479 
1480 	/* exec command in zone */
1481 
1482 	n = z_zone_exec(a_zoneName, path, arg, a_stdoutPath, (char *)NULL, fds);
1483 
1484 	echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n,
1485 	    PSTR(a_stdoutPath));
1486 
1487 	/*
1488 	 * close any files that were opened for use by the
1489 	 * /proc/self/fd interface so they could be passed to programs
1490 	 * via the z_zone_exec() interface
1491 	 */
1492 
1493 	for (; maxfds > 0; maxfds--) {
1494 		(void) close(fds[maxfds-1]);
1495 	}
1496 
1497 	/* return results of pkginstall in zone execution */
1498 
1499 	return (n);
1500 }
1501 
1502 /*
1503  * Name:	pkgZoneInstall
1504  * Description:	Invoke pkginstall in a specified zone to perform an install
1505  *		of a single package in the specified zone
1506  * Arguments:	a_zoneName - pointer to string representing the name of the
1507  *			zone to install the package in.
1508  *		a_zoneState - current state of the zone; must be mounted or
1509  *			running.
1510  *		a_idsName - pointer to string representing the data stream
1511  *			device (input data stream) containing the package to
1512  *			be installed.
1513  *		a_altBinDir - pointer to string representing an alternative
1514  *			binary location directory to pass to pkginstall.
1515  *			If this is == NULL no alternative binary location is
1516  *			passed to pkginstall.
1517  *		a_adminFile - pointer to string representing the admin
1518  *			file to pass to pkginstall when installing the package.
1519  *			If this is == NULL no admin file is given to pkginstall.
1520  *		a_stdoutPath - pointer to string representing the local path
1521  *			into which all output written by pkginstall to stdout
1522  *			is stored.
1523  *			If this is == NULL stdout is redirected to /dev/null
1524  *		a_tmpzn - B_TRUE when this zone is booted by the package
1525  *			command or B_FALSE if it was running before.
1526  * Returns:	int	(see ckreturn() function for details)
1527  *		0 - success
1528  *		1 - package operation failed (fatal error)
1529  *		2 - non-fatal error (warning)
1530  *		3 - user selected quit (operation interrupted)
1531  *		4 - admin settings prevented operation
1532  *		5 - interaction required and -n (non-interactive) specified
1533  *		"10" will be added to indicate "immediate reboot required"
1534  *		"20" will be added to indicate "reboot after install required"
1535  */
1536 
1537 static int
1538 pkgZoneInstall(char *a_zoneName, zone_state_t a_zoneState, char *a_idsName,
1539     char *a_altBinDir, char *a_adminFile, boolean_t a_tmpzn)
1540 {
1541 	char	*arg[MAXARGS];
1542 	char	*p;
1543 	char	adminfd_path[PATH_MAX];
1544 	char	path[PATH_MAX];
1545 	char	pkgstreamfd_path[PATH_MAX];
1546 	char	respfilefd_path[PATH_MAX];
1547 	int	fds[MAX_FDS];
1548 	int	maxfds;
1549 	int	n;
1550 	int	nargs;
1551 
1552 	/* entry assertions */
1553 
1554 	assert(a_zoneName != (char *)NULL);
1555 	assert(*a_zoneName != '\0');
1556 
1557 	/* entry debugging info */
1558 
1559 	echoDebug(DBG_PKGZONEINSTALL_ENTRY);
1560 	echoDebug(DBG_PKGZONEINSTALL_ARGS, a_zoneName, PSTR(pkginst),
1561 	    PSTR(pkgdev.dirname), PSTR(pkgdev.mount), PSTR(pkgdev.bdevice),
1562 	    a_zoneState == ZONE_STATE_MOUNTED ? "/a" : "", PSTR(a_idsName),
1563 	    a_adminFile);
1564 
1565 	/* generate path to pkginstall */
1566 
1567 	(void) snprintf(path, sizeof (path), "%s/pkginstall", PKGBIN);
1568 
1569 	/* start at first file descriptor */
1570 
1571 	maxfds = 0;
1572 
1573 	/*
1574 	 * generate argument list for call to pkginstall
1575 	 */
1576 
1577 	/* start at argument 0 */
1578 
1579 	nargs = 0;
1580 
1581 	/* first argument is path to executable */
1582 
1583 	arg[nargs++] = path;
1584 
1585 	/*
1586 	 * second argument is always: pass -O debug to pkginstall: debug mode
1587 	 */
1588 	if (debugFlag == B_TRUE) {
1589 		arg[nargs++] = "-O";
1590 		arg[nargs++] = "debug";
1591 	}
1592 
1593 	/* pkgadd -G: pass -G to pkginstall */
1594 
1595 	if (globalZoneOnly == B_TRUE) {
1596 		arg[nargs++] = "-G";
1597 	}
1598 
1599 	/* pkgadd -b dir: pass -b to pkginstall in zone */
1600 
1601 	if (a_altBinDir != (char *)NULL) {
1602 		arg[nargs++] = "-b";
1603 		arg[nargs++] = a_altBinDir;
1604 	}
1605 
1606 	/* pkgadd -B blocksize: pass -B to pkginstall in zone */
1607 
1608 	if (rw_block_size != NULL) {
1609 		arg[nargs++] = "-B";
1610 		arg[nargs++] = rw_block_size;
1611 	}
1612 
1613 	/* pkgadd -C: pass -C to pkgadd in zone: disable checksum */
1614 
1615 	if (disableChecksum) {
1616 		arg[nargs++] = "-C";
1617 	}
1618 
1619 	/* pkgadd -A: pass -A to pkgadd in zone: disable attribute checking */
1620 
1621 	if (disableAttributes) {
1622 		arg[nargs++] = "-A";
1623 	}
1624 
1625 	/* pkgadd -S: pass -S to pkgadd in zone: suppress copyright notices */
1626 
1627 	arg[nargs++] = "-S";
1628 
1629 	/* pkgadd -I: pass -I to pkgadd in zone: initial install */
1630 
1631 	if (init_install) {
1632 		arg[nargs++] = "-I";
1633 	}
1634 
1635 	/* pkgadd -M: pass -M to pkgadd in zone: dont mount client file sys */
1636 
1637 	arg[nargs++] = "-M";
1638 
1639 	/* pkgadd -v: pass -v to pkgadd in zone: trace scripts */
1640 
1641 	if (pkgverbose) {
1642 		arg[nargs++] = "-v";
1643 	}
1644 
1645 	/* pkgadd -z: pass -z to pkgadd in zone fresh inst from pkg save area */
1646 
1647 	if (saveSpoolInstall) {
1648 		arg[nargs++] = "-z";
1649 	}
1650 
1651 	/* pass "-O enable-hollow-package-support" */
1652 
1653 	if (is_depend_pkginfo_DB()) {
1654 		arg[nargs++] = "-O";
1655 		arg[nargs++] = "enable-hollow-package-support";
1656 	}
1657 
1658 	/* pkgadd -t pass -t to pkgadd in zone disable save spool area create */
1659 
1660 	if (disableSaveSpool) {
1661 		arg[nargs++] = "-t";
1662 	}
1663 
1664 	/* if running pkgask, pass -i to pkgadd in zone: running pkgask */
1665 
1666 	if (askflag) {
1667 		echo(MSG_BYPASSING_ZONE, a_zoneName);
1668 		return (0);
1669 	}
1670 
1671 	/*
1672 	 * pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode
1673 	 */
1674 	if (nointeract && !askflag) {
1675 		arg[nargs++] = "-n";
1676 	}
1677 
1678 	/* pkgadd -a admin: pass -a admin to pkginstall in zone: admin file */
1679 
1680 	if (a_adminFile) {
1681 		int fd;
1682 		fd = openLocal(a_adminFile, O_RDONLY, tmpdir);
1683 		if (fd < 0) {
1684 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1685 			    errno, strerror(errno));
1686 			return (1);
1687 		}
1688 		(void) snprintf(adminfd_path, sizeof (adminfd_path),
1689 		    "/proc/self/fd/%d", fd);
1690 		fds[maxfds++] = fd;
1691 		arg[nargs++] = "-a";
1692 		arg[nargs++] = adminfd_path;
1693 	}
1694 
1695 	/* pkgadd -R root: pass -R /a to pkginstall when zone is mounted */
1696 	if (a_zoneState == ZONE_STATE_MOUNTED) {
1697 		arg[nargs++] = "-R";
1698 		arg[nargs++] = "/a";
1699 	}
1700 
1701 	/*
1702 	 * pkgadd -D arg: pass -D dryrun to pkginstall in zone: dryrun
1703 	 * mode/file
1704 	 */
1705 	if (pkgdrtarg) {
1706 		arg[nargs++] = "-D";
1707 		arg[nargs++] = pkgdrtarg;
1708 	}
1709 
1710 	/*
1711 	 * pkgadd -c cont: pass -c cont to pkginstall in zone: continuation
1712 	 * file
1713 	 */
1714 	if (pkgcontsrc) {
1715 		arg[nargs++] = "-c";
1716 		arg[nargs++] = pkgcontsrc;
1717 	}
1718 
1719 	/* pkgadd -r resp: pass -r resp to pkginstall in zone: response file */
1720 
1721 	if (respfile) {
1722 		int fd;
1723 		fd = openLocal(respfile, O_RDONLY, tmpdir);
1724 		if (fd < 0) {
1725 			progerr(ERR_CANNOT_COPY_LOCAL, a_adminFile,
1726 			    errno, strerror(errno));
1727 			return (1);
1728 		}
1729 		(void) snprintf(respfilefd_path,
1730 		    sizeof (respfilefd_path),
1731 		    "/proc/self/fd/%d", fd);
1732 		fds[maxfds++] = fd;
1733 		arg[nargs++] = "-r";
1734 		arg[nargs++] = respfilefd_path;
1735 	}
1736 
1737 	/* add "-O addzonename" */
1738 
1739 	arg[nargs++] = "-O";
1740 	arg[nargs++] = "addzonename";
1741 
1742 	/*
1743 	 * add parent zone info/type
1744 	 */
1745 
1746 	p = z_get_zonename();
1747 	if ((p != NULL) && (*p != '\0')) {
1748 			char	zn[MAXPATHLEN];
1749 			(void) snprintf(zn, sizeof (zn),
1750 			    "parent-zone-name=%s", p);
1751 			arg[nargs++] = "-O";
1752 			arg[nargs++] = strdup(zn);
1753 	}
1754 
1755 	/* current zone type */
1756 
1757 	arg[nargs++] = "-O";
1758 	if (z_running_in_global_zone() == B_TRUE) {
1759 			char	zn[MAXPATHLEN];
1760 			(void) snprintf(zn, sizeof (zn),
1761 			    "parent-zone-type=%s",
1762 			    TAG_VALUE_GLOBAL_ZONE);
1763 			arg[nargs++] = strdup(zn);
1764 	} else {
1765 			char	zn[MAXPATHLEN];
1766 			(void) snprintf(zn, sizeof (zn),
1767 			    "parent-zone-type=%s",
1768 			    TAG_VALUE_NONGLOBAL_ZONE);
1769 			arg[nargs++] = strdup(zn);
1770 	}
1771 
1772 	/* Add the pkgserv options */
1773 	arg[nargs++] = "-O";
1774 	arg[nargs++] = pkgmodeargument(a_tmpzn ? RUN_ONCE : pkgservergetmode());
1775 
1776 	/* add in the package stream file */
1777 
1778 	if (a_idsName != NULL) {
1779 		int fd;
1780 		fd = openLocal(a_idsName, O_RDONLY, tmpdir);
1781 		if (fd < 0) {
1782 			progerr(ERR_STREAM_UNAVAILABLE, a_idsName,
1783 			    pkginst, strerror(errno));
1784 			quit(1);
1785 		}
1786 		(void) snprintf(pkgstreamfd_path, sizeof (pkgstreamfd_path),
1787 		    "/proc/self/fd/%d", fd);
1788 		fds[maxfds++] = fd;
1789 		arg[nargs++] = pkgstreamfd_path;
1790 	} else {
1791 		progerr(ERR_PKGZONEINSTALL_NO_STREAM);
1792 		quit(1);
1793 	}
1794 
1795 	/* add package instance name */
1796 
1797 	arg[nargs++] = pkginst;
1798 
1799 	/* terminate the argument list */
1800 
1801 	arg[nargs++] = NULL;
1802 
1803 	/*
1804 	 * run the appropriate pkginstall command in the specified zone
1805 	 */
1806 
1807 	if (debugFlag == B_TRUE) {
1808 		echoDebug(DBG_ZONE_EXEC_ENTER, a_zoneName, arg[0]);
1809 		for (n = 0; arg[n]; n++) {
1810 			echoDebug(DBG_ARG, n, arg[n]);
1811 		}
1812 	}
1813 
1814 	/* terminate file descriptor list */
1815 
1816 	fds[maxfds] = -1;
1817 
1818 	/* exec command in zone */
1819 
1820 	n = z_zone_exec(a_zoneName, path, arg, (char *)NULL, (char *)NULL, fds);
1821 
1822 	echoDebug(DBG_ZONE_EXEC_EXIT, a_zoneName, arg[0], n, "");
1823 
1824 	/*
1825 	 * close any files that were opened for use by the
1826 	 * /proc/self/fd interface so they could be passed to programs
1827 	 * via the z_zone_exec() interface
1828 	 */
1829 
1830 	for (; maxfds > 0; maxfds--) {
1831 		(void) close(fds[maxfds-1]);
1832 	}
1833 
1834 	/* return results of pkginstall in zone execution */
1835 
1836 	return (n);
1837 }
1838 
1839 /*
1840  * Name:	pkgInstall
1841  * Description:	Invoke pkginstall in the current zone to perform an install
1842  *		of a single package to the current zone or standalone system
1843  * Arguments:	a_altRoot - pointer to string representing the alternative
1844  *			root to use for the install
1845  *		a_idsName - pointer to string representing the data stream
1846  *			device (input data stream) containing the package to
1847  *			be installed.
1848  *		a_pkgDir - pointer to string representing the path to the
1849  *			directory containing the package
1850  *		a_altBinDir - pointer to string representing location of the
1851  *			pkginstall executable to run. If not NULL, then pass
1852  *			the path specified to the -b option to pkginstall.
1853  * Returns:	int	(see ckreturn() function for details)
1854  *		0 - success
1855  *		1 - package operation failed (fatal error)
1856  *		2 - non-fatal error (warning)
1857  *		3 - user selected quit (operation interrupted)
1858  *		4 - admin settings prevented operation
1859  *		5 - interaction required and -n (non-interactive) specified
1860  *		"10" will be added to indicate "immediate reboot required"
1861  *		"20" will be added to indicate "reboot after install required"
1862  * NOTE:	Both a_idsName and a_pkgDir are used to determine where the
1863  *		package to be installed is located. If a_idsName is != NULL
1864  *		then it must be the path to a device containing a package
1865  *		stream that contains the package to be installed. If a_idsName
1866  *		is == NULL then a_pkgDir must contain a full path to a directory
1867  *		that contains the package to be installed.
1868  */
1869 
1870 static int
1871 pkgInstall(char *a_altRoot, char *a_idsName, char *a_pkgDir, char *a_altBinDir)
1872 {
1873 	char	*arg[MAXARGS];
1874 	char	*p;
1875 	char	path[PATH_MAX];
1876 	char	buffer[256];
1877 	int	n, nargs;
1878 
1879 	/* entry debugging info */
1880 
1881 	echoDebug(DBG_PKGINSTALL_ENTRY);
1882 	echoDebug(DBG_PKGINSTALL_ARGS, PSTR(pkginst), PSTR(pkgdev.dirname),
1883 	    PSTR(pkgdev.mount), PSTR(pkgdev.bdevice), PSTR(a_altRoot),
1884 	    PSTR(a_idsName), PSTR(a_pkgDir));
1885 
1886 	/* generate full path to 'pkginstall' to run in zone */
1887 
1888 	(void) snprintf(path, sizeof (path), "%s/pkginstall",
1889 	    a_altBinDir == (char *)NULL ? PKGBIN : a_altBinDir);
1890 	/*
1891 	 * generate argument list for call to pkginstall
1892 	 */
1893 
1894 	/* start at argument 0 */
1895 
1896 	nargs = 0;
1897 
1898 	/* first argument is path to executable */
1899 
1900 	arg[nargs++] = path;
1901 
1902 	/*
1903 	 * second argument is always: pass -O debug to pkginstall: debug mode
1904 	 */
1905 	if (debugFlag == B_TRUE) {
1906 		arg[nargs++] = "-O";
1907 		arg[nargs++] = "debug";
1908 	}
1909 
1910 	arg[nargs++] = "-O";
1911 	arg[nargs++] = pkgmodeargument(pkgservergetmode());
1912 
1913 	/*
1914 	 * pkgadd -G: pass -G to pkginstall if:
1915 	 *  - the -G option is specified on the pkgadd command line
1916 	 *  - this package is marked 'this zone only':
1917 	 *  -- package has SUNW_PKG_THISZONE=true, or
1918 	 *  -- package has a request script
1919 	 * Setting -G for pkginstall causes pkginstall to install the package
1920 	 * in the target zone. If running in the global zone, will install the
1921 	 * package and mark the package as installed "in the global zone only".
1922 	 * If running in a non-global zone, will just install the package.
1923 	 */
1924 
1925 	if (globalZoneOnly == B_TRUE) {
1926 		arg[nargs++] = "-G";
1927 	} else if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
1928 		arg[nargs++] = "-G";
1929 	}
1930 
1931 	/* pkgadd -b dir: pass -b to pkginstall */
1932 
1933 	if (a_altBinDir != (char *)NULL) {
1934 		arg[nargs++] = "-b";
1935 		arg[nargs++] = a_altBinDir;
1936 	}
1937 
1938 	/* pkgadd -B blocksize: pass -B to pkginstall */
1939 
1940 	if (rw_block_size != NULL) {
1941 		arg[nargs++] = "-B";
1942 		arg[nargs++] = rw_block_size;
1943 	}
1944 
1945 	/* pkgadd -C: pass -C to pkginstall: disable checksum */
1946 
1947 	if (disableChecksum) {
1948 		arg[nargs++] = "-C";
1949 	}
1950 
1951 	/* pkgadd -A: pass -A to pkginstall: disable attribute checking */
1952 
1953 	if (disableAttributes) {
1954 		arg[nargs++] = "-A";
1955 	}
1956 
1957 	/*
1958 	 * NONABI_SCRIPTS defined: pass -o to pkginstall; refers to a
1959 	 * pkg requiring operator interaction during a procedure script
1960 	 * (common before on1093)
1961 	 */
1962 
1963 	if (old_pkg) {
1964 		arg[nargs++] = "-o";
1965 	}
1966 
1967 	/*
1968 	 * PKG_NONABI_SYMLINKS defined: pass -y to pkginstall; process
1969 	 * symlinks consistent with old behavior
1970 	 */
1971 
1972 	if (old_symlinks) {
1973 		arg[nargs++] = "-y";
1974 	}
1975 
1976 	/*
1977 	 * PKG_ABI_NAMELENGTH defined: pass -e to pkginstall; causes
1978 	 * package name length to be restricted
1979 	 */
1980 
1981 	if (ABI_namelength) {
1982 		arg[nargs++] = "-e";
1983 	}
1984 
1985 	/* pkgadd -S: pass -S to pkginstall: suppress copyright notices */
1986 
1987 	if (suppressCopyright) {
1988 		arg[nargs++] = "-S";
1989 	}
1990 
1991 	/* pkgadd -I: pass -I to pkginstall: initial install being performed */
1992 
1993 	if (init_install) {
1994 		arg[nargs++] = "-I";
1995 	}
1996 
1997 	/* pkgadd -M: pass -M to pkginstall: dont mount client file systems */
1998 
1999 	if (no_map_client) {
2000 		arg[nargs++] = "-M";
2001 	}
2002 
2003 	/* pkgadd -v: pass -v to pkginstall: trace scripts */
2004 
2005 	if (pkgverbose) {
2006 		arg[nargs++] = "-v";
2007 	}
2008 
2009 	/* pkgadd -z: pass -z to pkginstall: fresh install from pkg save area */
2010 
2011 	if (saveSpoolInstall) {
2012 		arg[nargs++] = "-z";
2013 	}
2014 
2015 	/*
2016 	 * if running in a non-global zone and the 'hollow' attribute is
2017 	 * passed in, then pass -h to pkginstall so that it knows how to
2018 	 * handle hollow packages for this local zone.
2019 	 */
2020 
2021 	if (!z_running_in_global_zone() && is_depend_pkginfo_DB()) {
2022 		arg[nargs++] = "-h";
2023 	}
2024 
2025 	/* pkgadd -t: pass -t to pkginstall: disable save spool area creation */
2026 
2027 	if (disableSaveSpool) {
2028 		arg[nargs++] = "-t";
2029 	}
2030 
2031 	/* if running pkgask, pass -i to pkginstall: running pkgask */
2032 
2033 	if (askflag) {
2034 		arg[nargs++] = "-i";
2035 	}
2036 
2037 	/* pkgadd -n (not pkgask): pass -n to pkginstall: noninteractive mode */
2038 
2039 	if (nointeract && !askflag) {
2040 		arg[nargs++] = "-n";
2041 	}
2042 
2043 	/* pkgadd -a admin: pass -a admin to pkginstall: admin file */
2044 
2045 	if (admnfile) {
2046 		arg[nargs++] = "-a";
2047 		arg[nargs++] = admnfile;
2048 	}
2049 
2050 	/* pkgadd -D dryrun: pass -D dryrun to pkginstall: dryrun mode/file */
2051 
2052 	if (pkgdrtarg) {
2053 		arg[nargs++] = "-D";
2054 		arg[nargs++] = pkgdrtarg;
2055 	}
2056 
2057 	/* pkgadd -c cont: pass -c cont to pkginstall: continuation file */
2058 
2059 	if (pkgcontsrc) {
2060 		arg[nargs++] = "-c";
2061 		arg[nargs++] = pkgcontsrc;
2062 	}
2063 
2064 	/* pkgadd -V vfstab: pass -V vfstab to pkginstall: alternate vfstab */
2065 
2066 	if (vfstab_file) {
2067 		arg[nargs++] = "-V";
2068 		arg[nargs++] = vfstab_file;
2069 	}
2070 
2071 	/* pkgadd -r resp: pass -r resp to pkginstall: response file */
2072 
2073 	if (respfile) {
2074 		arg[nargs++] = "-r";
2075 		arg[nargs++] = respfile;
2076 	}
2077 
2078 	/* pkgadd -R root: pass -R root to pkginstall: alternative root */
2079 
2080 	if (a_altRoot && *a_altRoot) {
2081 		arg[nargs++] = "-R";
2082 		arg[nargs++] = a_altRoot;
2083 	}
2084 
2085 	/*
2086 	 * If input data stream is available,
2087 	 * - add: -d ids_name -p number_of_parts
2088 	 * else,
2089 	 * - add: -d device -m mount [-f type]
2090 	 */
2091 
2092 	if (a_idsName != NULL) {
2093 		arg[nargs++] = "-d";
2094 		arg[nargs++] = a_idsName;
2095 		arg[nargs++] = "-p";
2096 		ds_close(1);
2097 		ds_putinfo(buffer, sizeof (buffer));
2098 		arg[nargs++] = buffer;
2099 	} else if (pkgdev.mount != NULL) {
2100 		arg[nargs++] = "-d";
2101 		arg[nargs++] = pkgdev.bdevice;
2102 		arg[nargs++] = "-m";
2103 		arg[nargs++] = pkgdev.mount;
2104 		if (pkgdev.fstyp != NULL) {
2105 			arg[nargs++] = "-f";
2106 			arg[nargs++] = pkgdev.fstyp;
2107 		}
2108 	}
2109 
2110 	/*
2111 	 * add parent zone info/type
2112 	 */
2113 
2114 	p = z_get_zonename();
2115 	if ((p != NULL) && (*p != '\0')) {
2116 			char	zn[MAXPATHLEN];
2117 			(void) snprintf(zn, sizeof (zn),
2118 			    "parent-zone-name=%s", p);
2119 			arg[nargs++] = "-O";
2120 			arg[nargs++] = strdup(zn);
2121 	}
2122 
2123 	/* current zone type */
2124 
2125 	arg[nargs++] = "-O";
2126 	if (z_running_in_global_zone() == B_TRUE) {
2127 			char	zn[MAXPATHLEN];
2128 			(void) snprintf(zn, sizeof (zn),
2129 			    "parent-zone-type=%s",
2130 			    TAG_VALUE_GLOBAL_ZONE);
2131 			arg[nargs++] = strdup(zn);
2132 	} else {
2133 			char	zn[MAXPATHLEN];
2134 			(void) snprintf(zn, sizeof (zn),
2135 			    "parent-zone-type=%s",
2136 			    TAG_VALUE_NONGLOBAL_ZONE);
2137 			arg[nargs++] = strdup(zn);
2138 	}
2139 
2140 	/* pass -N to pkginstall: program name to report */
2141 
2142 	arg[nargs++] = "-N";
2143 	arg[nargs++] = get_prog_name();
2144 
2145 	/* add package directory name */
2146 
2147 	arg[nargs++] = a_pkgDir;
2148 
2149 	/* add package instance name */
2150 
2151 	arg[nargs++] = pkginst;
2152 
2153 	/* terminate the argument list */
2154 
2155 	arg[nargs++] = NULL;
2156 
2157 	/*
2158 	 * run the appropriate pkginstall command in the specified zone
2159 	 */
2160 
2161 	if (debugFlag == B_TRUE) {
2162 		echoDebug(DBG_ZONE_EXEC_ENTER, "global", arg[0]);
2163 		for (n = 0; arg[n]; n++) {
2164 			echoDebug(DBG_ARG, n, arg[n]);
2165 		}
2166 	}
2167 
2168 	/* execute pkginstall command */
2169 
2170 	n = pkgexecv(NULL, NULL, NULL, NULL, arg);
2171 
2172 	/* return results of pkginstall execution */
2173 
2174 	return (n);
2175 }
2176 
2177 /*
2178  *  function to clear out any exisiting error return conditions that may have
2179  *  been set by previous calls to ckreturn()
2180  */
2181 static void
2182 resetreturn()
2183 {
2184 	admnflag = 0;	/* != 0 if any pkg op admin setting failure (4) */
2185 	doreboot = 0;	/* != 0 if reboot required after installation (>= 10) */
2186 	failflag = 0;	/* != 0 if fatal error has occurred (1) */
2187 	intrflag = 0;	/* != 0 if user selected quit (3) */
2188 	ireboot = 0;	/* != 0 if immediate reboot required (>= 20) */
2189 	nullflag = 0;	/* != 0 if admin interaction required (5) */
2190 	warnflag = 0;	/* != 0 if non-fatal error has occurred (2) */
2191 	interrupted = 0;	/* last pkg op was quit (1,2,3,4,5) */
2192 	needconsult = 0;	/* essential ask admin now (1,2,3,5) */
2193 }
2194 
2195 /*
2196  *  function which checks the indicated return value
2197  *  and indicates disposition of installation
2198  */
2199 static void
2200 ckreturn(int retcode)
2201 {
2202 	/*
2203 	 * entry debugging info
2204 	 */
2205 
2206 	echoDebug(DBG_PKGADD_CKRETURN, retcode, PSTR(pkginst));
2207 
2208 	/* reset needconsult so it only reflects this call to ckreturn */
2209 	needconsult = 0;
2210 
2211 	switch (retcode) {
2212 	case  0:	/* successful */
2213 	case 10:
2214 	case 20:
2215 		break; /* empty case */
2216 
2217 	case  1:	/* package operation failed (fatal error) */
2218 	case 11:
2219 	case 21:
2220 		failflag++;
2221 		interrupted++;
2222 		needconsult++;
2223 		break;
2224 
2225 	case  2:	/* non-fatal error (warning) */
2226 	case 12:
2227 	case 22:
2228 		warnflag++;
2229 		interrupted++;
2230 		needconsult++;
2231 		break;
2232 
2233 	case  3:	/* user selected quit; operation interrupted */
2234 	case 13:
2235 	case 23:
2236 		intrflag++;
2237 		interrupted++;
2238 		needconsult++;
2239 		break;
2240 
2241 	case  4:	/* admin settings prevented operation */
2242 	case 14:
2243 	case 24:
2244 		admnflag++;
2245 		interrupted++;
2246 		break;
2247 
2248 	case  5:	/* administration: interaction req (no -n) */
2249 	case 15:
2250 	case 25:
2251 		nullflag++;
2252 		interrupted++;
2253 		needconsult++;
2254 		break;
2255 
2256 	default:
2257 		failflag++;
2258 		interrupted++;
2259 		needconsult++;
2260 		return;
2261 	}
2262 
2263 	if (retcode >= 20) {
2264 		ireboot++;
2265 	} else if (retcode >= 10) {
2266 		doreboot++;
2267 	}
2268 }
2269 
2270 static void
2271 usage(void)
2272 {
2273 	char *prog = get_prog_name();
2274 
2275 	if (askflag) {
2276 		(void) fprintf(stderr, ERR_USAGE_PKGASK, prog);
2277 	} else if (z_running_in_global_zone() == B_FALSE) {
2278 		(void) fprintf(stderr, ERR_USAGE_PKGADD_NONGLOBALZONE,
2279 		    prog, prog);
2280 	} else {
2281 		(void) fprintf(stderr, ERR_USAGE_PKGADD_GLOBALZONE,
2282 		    prog, prog);
2283 	}
2284 }
2285 
2286 /*
2287  * Name:	check_applicability
2288  * Description:	determine if a package is installable in this zone; that is,
2289  *		does the scope of install conflict with existing installation
2290  *		or can the package be installed
2291  * Arguments:	a_packageDir - [RO, *RO] - (char *)
2292  *			Pointer to string representing the directory where the
2293  *			package is located
2294  *		a_pkgInst - [RO, *RO] - (char *)
2295  *			Pointer to string representing the name of the package
2296  *			to check
2297  *		a_rootPath - [RO, *RO] - (char *)
2298  *			Pointer to string representing path to the root of the
2299  *			file system where the package is to be installed - this
2300  *			is usually the same as the "-R" argument to pkgadd
2301  *		a_flags - [RO, *RO] - (CAF_T)
2302  *			Flags set by the caller to indicate the conditions
2303  *			under which the package is to be installed:
2304  *				CAF_IN_GLOBAL_ZONE - in global zone
2305  *				CAF_SCOPE_GLOBAL - -G specified
2306  *				CAF_SCOPE_NONGLOBAL - -Z specified
2307  * Returns:	boolean_t
2308  *			B_TRUE - the package can be installed
2309  *			B_FALSE - the package can not be installed
2310  */
2311 
2312 static boolean_t
2313 check_applicability(char *a_packageDir, char *a_pkgInst, char *a_rootPath,
2314     CAF_T a_flags)
2315 {
2316 	FILE		*pkginfoFP;
2317 	FILE		*pkgmapFP;
2318 	boolean_t	all_zones;	/* pkg is "all zones" only */
2319 	boolean_t	in_gz_only;	/* pkg installed in global zone only */
2320 	boolean_t	is_hollow;	/* pkg is "hollow" */
2321 	boolean_t	pkg_installed;	/* pkg is installed */
2322 	boolean_t	this_zone;	/* pkg is "this zone" only */
2323 	boolean_t	reqfile_found = B_FALSE;
2324 	char		instPkg[PKGSIZ+1];	/* installed pkg instance nam */
2325 	char		instPkgPath[PATH_MAX];	/* installed pkg toplevel dir */
2326 	char		pkginfoPath[PATH_MAX];	/* pkg 2 install pkginfo file */
2327 	char		pkgmapPath[PATH_MAX];	/* pkg 2 install pkgmap file */
2328 	char		pkgpath[PATH_MAX];	/* pkg 2 install toplevel dir */
2329 	int		len;
2330 	char		line[LINE_MAX];
2331 
2332 	/* entry assertions */
2333 
2334 	assert(a_packageDir != (char *)NULL);
2335 	assert(*a_packageDir != '\0');
2336 	assert(a_pkgInst != (char *)NULL);
2337 	assert(*a_pkgInst != '\0');
2338 
2339 	/* normalize root path */
2340 
2341 	if (a_rootPath == (char *)NULL) {
2342 		a_rootPath = "";
2343 	}
2344 
2345 	/* entry debugging info */
2346 
2347 	echoDebug(DBG_CHECKAPP_ENTRY);
2348 	echoDebug(DBG_CHECKAPP_ARGS, a_pkgInst, a_packageDir, a_rootPath);
2349 
2350 	/*
2351 	 * calculate paths to various objects
2352 	 */
2353 
2354 	/* path to package to be installed top level (main) directory */
2355 
2356 	len = snprintf(pkgpath, sizeof (pkgpath), "%s/%s", a_packageDir,
2357 	    a_pkgInst);
2358 	if (len > sizeof (pkgpath)) {
2359 		progerr(ERR_CREATE_PATH_2, a_packageDir, a_pkgInst);
2360 		return (B_FALSE);
2361 	}
2362 
2363 	/* error if package top level directory does not exist */
2364 
2365 	if (isdir(pkgpath) != 0) {
2366 		progerr(ERR_NO_PKGDIR, pkgpath, a_pkgInst, strerror(errno));
2367 		return (B_FALSE);
2368 	}
2369 
2370 	/* path to pkginfo file within the package to be installed */
2371 
2372 	len = snprintf(pkginfoPath, sizeof (pkginfoPath), "%s/pkginfo",
2373 	    pkgpath);
2374 	if (len > sizeof (pkginfoPath)) {
2375 		progerr(ERR_CREATE_PATH_2, pkgpath, "pkginfo");
2376 		return (B_FALSE);
2377 	}
2378 
2379 	/* path to highest instance of package currently installed */
2380 
2381 	pkgLocateHighestInst(instPkgPath, sizeof (instPkgPath),
2382 	    instPkg, sizeof (instPkg), a_rootPath, a_pkgInst);
2383 
2384 	/*
2385 	 * gather information from this package's pkginfo file
2386 	 */
2387 
2388 	pkginfoFP = fopen(pkginfoPath, "r");
2389 
2390 	if (pkginfoFP == (FILE *)NULL) {
2391 		progerr(ERR_NO_PKG_INFOFILE, a_pkgInst, pkginfoPath,
2392 		    strerror(errno));
2393 		return (B_FALSE);
2394 	}
2395 
2396 	/* determine "HOLLOW" setting for this package */
2397 
2398 	is_hollow = pkginfoParamTruth(pkginfoFP, PKG_HOLLOW_VARIABLE,
2399 	    "true", B_FALSE);
2400 
2401 	/* determine "ALLZONES" setting for this package */
2402 
2403 	all_zones = pkginfoParamTruth(pkginfoFP, PKG_ALLZONES_VARIABLE,
2404 	    "true", B_FALSE);
2405 
2406 	/* determine "THISZONE" setting for this package */
2407 
2408 	this_zone = pkginfoParamTruth(pkginfoFP, PKG_THISZONE_VARIABLE,
2409 	    "true", B_FALSE);
2410 
2411 	/* close pkginfo file */
2412 
2413 	(void) fclose(pkginfoFP);
2414 
2415 	/*
2416 	 * If request file is not found, it may be in the datastream which
2417 	 * is not yet unpacked. Check in the pkgmap file.
2418 	 */
2419 	if (isfile(pkgpath, REQUEST_FILE) != 0) {
2420 
2421 		/* path to pkgmap file within the package to be installed */
2422 		(void) snprintf(pkgmapPath, sizeof (pkgmapPath), "%s/pkgmap",
2423 		    pkgpath);
2424 
2425 		pkgmapFP = fopen(pkgmapPath, "r");
2426 
2427 		if (pkgmapFP == NULL) {
2428 			progerr(ERR_NO_PKG_MAPFILE, a_pkgInst,
2429 			    pkgmapPath, strerror(errno));
2430 			return (B_FALSE);
2431 		}
2432 
2433 		while (fgets(line, LINE_MAX, pkgmapFP) != NULL) {
2434 			if (strstr(line, " i request") != NULL) {
2435 				reqfile_found = B_TRUE;
2436 				break;
2437 			}
2438 		}
2439 		(void) fclose(pkgmapFP);
2440 	} else {
2441 		reqfile_found = B_TRUE;
2442 	}
2443 
2444 	/*
2445 	 * If this package is not marked for installation in this zone only,
2446 	 * check to see if this package has a request script. If this package
2447 	 * does have a request script, then mark the package for installation
2448 	 * in this zone only. Any package with a request script cannot be
2449 	 * installed outside of the zone the pkgadd command is being run in,
2450 	 * nor can such a package be installed as part of a new zone install.
2451 	 * A new zone install must be non-interactive, which is required
2452 	 * by all packages integrated into the Solaris WOS.
2453 	 */
2454 
2455 	if ((!this_zone) && (reqfile_found)) {
2456 		if (a_flags & CAF_IN_GLOBAL_ZONE) {
2457 			echoDebug(DBG_CHECKAPP_THISZONE_REQUEST, a_pkgInst);
2458 		}
2459 		this_zone = B_TRUE;
2460 	}
2461 
2462 	/*
2463 	 * If this package is already installed, see if the current installation
2464 	 * of the package has a request file - if it does, then act as though
2465 	 * the current package to be added has a request file - install the
2466 	 * package in the current zone only.
2467 	 */
2468 
2469 	if ((!this_zone) && (instPkgPath[0] != '\0') &&
2470 	    (isfile(instPkgPath, REQUEST_FILE) == 0)) {
2471 		if (a_flags & CAF_IN_GLOBAL_ZONE) {
2472 			echoDebug(DBG_CHECKAPP_THISZONE_INSTREQ,
2473 			    a_pkgInst, instPkg);
2474 		}
2475 		this_zone = B_TRUE;
2476 	}
2477 
2478 	/* gather information from the global zone only file */
2479 
2480 	in_gz_only = B_FALSE;
2481 	if (a_flags & CAF_IN_GLOBAL_ZONE) {
2482 		in_gz_only = pkgIsPkgInGzOnly(a_rootPath, a_pkgInst);
2483 	}
2484 
2485 	/* determine if this package is currently installed */
2486 
2487 	pkg_installed = pkginfoIsPkgInstalled((struct pkginfo **)NULL,
2488 	    a_pkgInst);
2489 
2490 	/*
2491 	 * verify package applicability based on information gathered,
2492 	 * and validate the three SUNW_PKG_ options:
2493 	 *
2494 	 * -----------|--------------|-------------|-------------|-----------
2495 	 * - - - - - -| GLOBAL ZONE -| GLOBAL ZONE | LOCAL ZONE	 | LOCAL ZONE
2496 	 * - - - - - -|	- - pkgadd - | pkgadd -G   | pkgadd	 | pkgadd -G
2497 	 * ----1------|--------------|-------------|-------------|------------
2498 	 * ALLZONES f | add to gz    | add to gz   | add to ls	 | add to ls
2499 	 * HOLLOW   f | current lz   | not to curr | only - - - -| only - - -
2500 	 * THISZONE f | futr lz - - -| or futr lz  | - - - - - - | - - - - - -
2501 	 * ----2------|--------------|-------------|-------------|------------
2502 	 * ALLZONES T | add to gz    | operation   | operation	 | operation
2503 	 * HOLLOW   f | current lz   | not allowed | not allowed | not allowed
2504 	 * THISZONE f | future lz    | - - - - - - | - - - - - - | - - - - - -
2505 	 * ----3------|--------------|-------------|-------------|------------
2506 	 * ALLZONES T | add to gz    | operation   | operation	 | operation
2507 	 * HOLLOW   T | pkg db only  | not allowed | not allowed | not allowed
2508 	 * THISZONE f | curr/futr lz | - - - - - - | - - - - - - | - - - - - -
2509 	 * ----4------|--------------|-------------|-------------|------------
2510 	 * ALLZONES T | bad option   | bad option  | bad option	 | bad option
2511 	 * HOLLOW   * | combo - - - -| combo - - - | combo - - - | combo - -
2512 	 * THISZONE T |	- - - - - - -|- - - - - - -|- - - - - - -|- - - - - -
2513 	 * ----5------|--------------|-------------|-------------|------------
2514 	 * ALLZONES f | bad option   | bad option  | bad option	 | bad option
2515 	 * HOLLOW   T | combo - - - -| combo - - - | combo - - - | combo - - -
2516 	 * THISZONE * | - - - - - - -| - - - - - - | - - - - - - | - - - - - -
2517 	 * ----6------|--------------|-------------|-------------|------------
2518 	 * ALLZONES f | add to gz    | add to gz   | add to lz	 | add to lz
2519 	 * HOLLOW   f | not current  | not current | only - - -	 | only - - -
2520 	 * THISZONE T | or future lz | or futr lz  | - - - - - - | - - - - - -
2521 	 * -----------|--------------|-------------|-------------|-----------
2522 	 */
2523 
2524 	/* pkg "all zones" && "this zone" (#4) */
2525 
2526 	if (all_zones && this_zone) {
2527 		progerr(ERR_ALLZONES_AND_THISZONE, a_pkgInst,
2528 		    PKG_ALLZONES_VARIABLE, PKG_THISZONE_VARIABLE);
2529 		return (B_FALSE);
2530 	}
2531 
2532 	/* pkg "!all zones" && "hollow" (#5) */
2533 
2534 	if ((!all_zones) && is_hollow) {
2535 		progerr(ERR_NOW_ALLZONES_AND_HOLLOW, a_pkgInst,
2536 		    PKG_ALLZONES_VARIABLE, PKG_HOLLOW_VARIABLE);
2537 		return (B_FALSE);
2538 	}
2539 
2540 	/* pkg ALLZONES=true && -Z specified */
2541 
2542 	if (all_zones && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2543 		progerr(ERR_ALLZONES_AND_Z_USED, a_pkgInst);
2544 		return (B_FALSE);
2545 	}
2546 
2547 	/* pkg ALLZONES=true & not running in global zone (#2/#3) */
2548 
2549 	if (all_zones && (!(a_flags & CAF_IN_GLOBAL_ZONE))) {
2550 		progerr(ERR_ALLZONES_AND_IN_LZ, a_pkgInst);
2551 		return (B_FALSE);
2552 	}
2553 
2554 	/* pkg "in gz only" & pkg "NOT installed" */
2555 
2556 	if (in_gz_only && (!pkg_installed)) {
2557 		/* MAKE A WARNING */
2558 		echo(ERR_IN_GZ_AND_NOT_INSTALLED, a_pkgInst,
2559 		    pkgGetGzOnlyPath());
2560 	}
2561 
2562 	/* pkg ALLZONES=true & pkg "in gz only" & pkg "is installed" */
2563 
2564 	if (all_zones && in_gz_only && pkg_installed) {
2565 		progerr(ERR_IN_GZ_AND_ALLZONES_AND_INSTALLED, a_pkgInst);
2566 		return (B_FALSE);
2567 	}
2568 
2569 	/* pkg ALLZONES=true && -G specified (#2/#3) */
2570 
2571 	if (all_zones && (a_flags & CAF_SCOPE_GLOBAL)) {
2572 		progerr(ERR_ALLZONES_AND_G_USED, a_pkgInst);
2573 		return (B_FALSE);
2574 	}
2575 
2576 	/* pkg "!this zone" && "in gz only" & -G not specified */
2577 
2578 	if ((!this_zone) && in_gz_only && (!(a_flags & CAF_SCOPE_GLOBAL))) {
2579 		progerr(ERR_IN_GZ_AND_NO_G_USED, a_pkgInst);
2580 		return (B_FALSE);
2581 	}
2582 
2583 	/* pkg "NOT in gz only" & -Z specified */
2584 
2585 	if ((!in_gz_only) && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2586 		progerr(ERR_NOT_IN_GZ_AND_Z_USED, a_pkgInst);
2587 		return (B_FALSE);
2588 	}
2589 
2590 	/* pkg "this zone" && -Z specified */
2591 
2592 	if (this_zone && (a_flags & CAF_SCOPE_NONGLOBAL)) {
2593 		progerr(ERR_THISZONE_AND_Z_USED, PKG_THISZONE_VARIABLE,
2594 		    a_pkgInst);
2595 		return (B_FALSE);
2596 	}
2597 
2598 	/*
2599 	 * If this package is marked 'this zone only', then mark the package
2600 	 * as "add to this zone only". This is referenced by the various
2601 	 * add_package_... functions to determine if the package should be
2602 	 * added to the current zone, or to all zones, depending on the
2603 	 * zone in which the command is being run.
2604 	 */
2605 
2606 	if (this_zone) {
2607 		pkgAddThisZonePackage(a_pkgInst);
2608 	}
2609 
2610 	return (B_TRUE);
2611 }
2612 
2613 /*
2614  * Name:	create_zone_adminfile
2615  * Description: Given a zone temporary directory and optionally an existing
2616  *		administration file, generate an administration file that
2617  *		can be used to perform "non-interactive" operations in a
2618  *		non-global zone.
2619  * Arguments:	r_zoneAdminFile - pointer to handle that will contain a
2620  *			string representing the path to the temporary
2621  *			administration file created - this must be NULL
2622  *			before the first call to this function - on
2623  *			subsequent calls if the pointer is NOT null then
2624  *			the existing string will NOT be overwritten.
2625  *		a_zoneTempDir - pointer to string representing the path
2626  *			to the zone temporary directory to create the
2627  *			temporary administration file in
2628  *		a_admnfile - pointer to string representing the path to
2629  *			an existing "user" administration file - the
2630  *			administration file created will contain the
2631  *			settings contained in this file, modified as
2632  *			appropriate to supress any interaction;
2633  *			If this is == NULL then the administration file
2634  *			created will not contain any extra settings
2635  * Returns:	void
2636  * NOTE:	Any string returned is placed in new storage for the
2637  *		calling method. The caller must use 'free' to dispose
2638  *		of the storage once the string is no longer needed.
2639  * NOTE:	On any error this function will call 'quit(1)'
2640  */
2641 
2642 static void
2643 create_zone_adminfile(char **r_zoneAdminFile, char *a_zoneTempDir,
2644     char *a_admnfile)
2645 {
2646 	boolean_t	b;
2647 
2648 	/* entry assertions */
2649 
2650 	assert(r_zoneAdminFile != (char **)NULL);
2651 	assert(a_zoneTempDir != (char *)NULL);
2652 	assert(*a_zoneTempDir != '\0');
2653 
2654 	/* entry debugging info */
2655 
2656 	echoDebug(DBG_CREATE_ZONE_ADMINFILE, a_zoneTempDir, PSTR(a_admnfile));
2657 
2658 	/* if temporary name already exists, do not overwrite */
2659 
2660 	if (*r_zoneAdminFile != (char *)NULL) {
2661 		return;
2662 	}
2663 
2664 	/* create temporary name */
2665 
2666 	*r_zoneAdminFile = tempnam(a_zoneTempDir, "zadmn");
2667 	b = z_create_zone_admin_file(*r_zoneAdminFile, a_admnfile);
2668 	if (b == B_FALSE) {
2669 		progerr(ERR_CREATE_TMPADMIN, *r_zoneAdminFile,
2670 		    strerror(errno));
2671 		quit(1);
2672 		/* NOTREACHED */
2673 	}
2674 
2675 	echoDebug(DBG_CREATED_ZONE_ADMINFILE, *r_zoneAdminFile);
2676 }
2677 
2678 /*
2679  * Name:	create_zone_tempdir
2680  * Description: Given a system temporary directory, create a "zone" specific
2681  *		temporary directory and return the path to the directory
2682  *		created.
2683  * Arguments:	r_zoneTempDir - pointer to handle that will contain a
2684  *			string representing the path to the temporary
2685  *			directory created - this must be NULL before the
2686  *			first call to this function - on subsequent calls
2687  *			if the pointer is NOT null then the existing string
2688  *			will NOT be overwritten.
2689  *		a_zoneTempDir - pointer to string representing the path
2690  *			to the system temporary directory to create the
2691  *			temporary zone directory in
2692  * Returns:	void
2693  * NOTE:	Any string returned is placed in new storage for the
2694  *		calling method. The caller must use 'free' to dispose
2695  *		of the storage once the string is no longer needed.
2696  * NOTE:	On any error this function will call 'quit(1)'
2697  * NOTE:	This function calls "quitSetZoneTmpdir" on success to
2698  *		register the directory created with quit() so that the
2699  *		directory will be automatically deleted on exit.
2700  */
2701 
2702 static void
2703 create_zone_tempdir(char **r_zoneTempDir, char *a_tmpdir)
2704 {
2705 	boolean_t	b;
2706 
2707 	/* entry assertions */
2708 
2709 	assert(r_zoneTempDir != (char **)NULL);
2710 	assert(a_tmpdir != (char *)NULL);
2711 	assert(*a_tmpdir != '\0');
2712 
2713 	/* entry debugging info */
2714 
2715 	echoDebug(DBG_CREATE_ZONE_TEMPDIR, a_tmpdir);
2716 
2717 	/* if temporary directory already exists, do not overwrite */
2718 
2719 	if (*r_zoneTempDir != (char *)NULL) {
2720 		return;
2721 	}
2722 
2723 	/* create temporary directory */
2724 
2725 	b = setup_temporary_directory(r_zoneTempDir, a_tmpdir, "ztemp");
2726 	if (b == B_FALSE) {
2727 		progerr(ERR_ZONETEMPDIR, a_tmpdir, strerror(errno));
2728 		quit(1);
2729 		/* NOTREACHED */
2730 	}
2731 
2732 	/* register with quit() so directory is removed on exit */
2733 
2734 	quitSetZoneTmpdir(*r_zoneTempDir);
2735 
2736 	/* exit debugging info */
2737 
2738 	echoDebug(DBG_CREATED_ZONE_TEMPDIR, *r_zoneTempDir);
2739 }
2740 
2741 /*
2742  * Name:	continue_installation
2743  * Description: Called from within a loop that is installing packages,
2744  *		this function examines various global variables and decides
2745  *		whether or not to ask an appropriate question, and wait for
2746  *		and appropriate reply.
2747  * Arguments:	<<global variables>>
2748  * Returns:	B_TRUE - continue processing with next package
2749  *		B_FALSE - do not continue processing with next package
2750  */
2751 
2752 static boolean_t
2753 continue_installation(void)
2754 {
2755 	char	ans[MAX_INPUT];
2756 	int	n;
2757 
2758 	/* return TRUE if not interrupted */
2759 
2760 	if (!interrupted) {
2761 		return (B_TRUE);
2762 	}
2763 
2764 	/*
2765 	 * process interrupted - determine whether or not to continue
2766 	 */
2767 
2768 	/* output appropriate interrupted message */
2769 
2770 	if (askflag) {
2771 		echo(npkgs == 1 ? MSG_1MORE_PROC : MSG_MORE_PROC, npkgs);
2772 	} else {
2773 		echo(npkgs == 1 ? MSG_1MORE_INST : MSG_MORE_INST, npkgs);
2774 	}
2775 
2776 	/* if running with no interaction (-n) do not ask question */
2777 
2778 	if (nointeract) {
2779 		/* if admin required return 'dont continue' */
2780 		if (needconsult) {
2781 			return (B_FALSE);
2782 		}
2783 		ckquit = 1;
2784 		return (B_TRUE);
2785 	}
2786 
2787 	/* interaction possible: ask question */
2788 
2789 	ckquit = 0;
2790 	n = ckyorn(ans, NULL, NULL, NULL, ASK_CONTINUE_ADD);
2791 	if (n != 0) {
2792 		quit(n);
2793 		/* NOTREACHED */
2794 	}
2795 	ckquit = 1;
2796 	if (strchr("yY", *ans) == NULL) {
2797 		return (B_FALSE);
2798 	}
2799 	return (B_TRUE);
2800 }
2801 
2802 /*
2803  * package can be in a number of formats:
2804  * - file containing package stream (pkgadd -d file [pkgs])
2805  * - directory containing packages (pkgadd -d /dir [pkgs])
2806  * - device containing packages (pkgadd -d diskette1 [pkgs])
2807  * non-global zones can be passed open files and strings as arguments
2808  * - for file containing package stream
2809  * -- the stream can be passed directly to the non-global zone
2810  * - for directory
2811  * -- convert packages to datastream to pass to the non-global zone
2812  * - for device
2813  * -- ?
2814  */
2815 
2816 static boolean_t
2817 unpack_and_check_packages(char **a_pkgList, char *a_idsName, char *a_packageDir)
2818 {
2819 	int	savenpkgs = npkgs;
2820 	int	i;
2821 	CAF_T	flags = 0;
2822 
2823 	/* entry assertions */
2824 
2825 	assert(a_pkgList != (char **)NULL);
2826 
2827 	/* entry debugging info */
2828 
2829 	echoDebug(DBG_UNPACKCHECK_ENTRY);
2830 	echoDebug(DBG_UNPACKCHECK_ARGS, PSTR(a_idsName), PSTR(a_packageDir));
2831 
2832 	/*
2833 	 * set flags for applicability check
2834 	 */
2835 
2836 	/* determine if running in the global zone */
2837 
2838 	if (z_running_in_global_zone() == B_TRUE) {
2839 		flags |= CAF_IN_GLOBAL_ZONE;
2840 	}
2841 
2842 	/* set -G flag */
2843 
2844 	if (globalZoneOnly == B_TRUE) {
2845 		flags |= CAF_SCOPE_GLOBAL;
2846 	}
2847 
2848 	/*
2849 	 * for each package to install:
2850 	 * - if packages from datastream, unpack package into package dir
2851 	 * - check applicability of installing package on this system/zone
2852 	 */
2853 
2854 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
2855 		if (a_idsName != (char *)NULL) {
2856 			/* create stream out of package if not already one */
2857 			if (unpack_package_from_stream(a_idsName, pkginst,
2858 			    a_packageDir) == B_FALSE) {
2859 				progerr(ERR_CANNOT_UNPACK_PKGSTRM,
2860 				    PSTR(pkginst), PSTR(a_idsName),
2861 				    PSTR(a_packageDir));
2862 
2863 				npkgs = savenpkgs;
2864 				return (B_FALSE);
2865 			}
2866 		} else {
2867 			echoDebug(DBG_PKG_IN_DIR, pkginst, a_packageDir);
2868 		}
2869 
2870 		/* check package applicability */
2871 		if (check_applicability(a_packageDir,
2872 		    pkginst, get_inst_root(), flags) == B_FALSE) {
2873 			progerr(ERR_PKG_NOT_INSTALLABLE, pkginst);
2874 			npkgs = savenpkgs;
2875 			return (B_FALSE);
2876 		}
2877 		npkgs--;
2878 	}
2879 
2880 	npkgs = savenpkgs;
2881 	return (B_TRUE);
2882 }
2883 
2884 /*
2885  * returns:
2886  *	B_TRUE - package list generated
2887  *	B_FALSE - failed to generate package list
2888  *	Will call quit(n) on fatal error.
2889  */
2890 
2891 static boolean_t
2892 get_package_list(char ***r_pkgList, char **a_argv, char *a_categories,
2893     char **a_categoryList, char *a_idsName, int *r_repeat)
2894 {
2895 	int		n;
2896 
2897 	/* entry assertions */
2898 
2899 	assert(r_repeat != (int *)NULL);
2900 
2901 	/* entry debugging info */
2902 
2903 	echoDebug(DBG_GETPKGLIST_ENTRY);
2904 	echoDebug(DBG_GETPKGLIST_ARGS, PSTR(a_idsName), PSTR(pkgdev.dirname),
2905 	    *r_repeat);
2906 
2907 	/*
2908 	 * get the list of the packages to add
2909 	 */
2910 
2911 	n = pkgGetPackageList(r_pkgList, a_argv, optind, a_categories,
2912 	    a_categoryList, &pkgdev);
2913 
2914 	switch (n) {
2915 		case -1:	/* no packages found */
2916 			echoDebug(DBG_PKGLIST_NONFOUND, PSTR(a_idsName),
2917 			    pkgdev.dirname);
2918 			return (B_FALSE);
2919 
2920 		case 0:		/* packages found */
2921 			break;
2922 
2923 		default:	/* "quit" error */
2924 			echoDebug(DBG_PKGLIST_ERROR, PSTR(a_idsName),
2925 			    pkgdev.dirname, n);
2926 			quit(n);
2927 			/* NOTREACHED */
2928 	}
2929 
2930 	/* order package list if input data stream specified */
2931 
2932 	if (a_idsName) {
2933 		ds_order(*r_pkgList);
2934 	}
2935 
2936 	return (B_TRUE);
2937 }
2938 
2939 /*
2940  * Name:	install_in_one_zone
2941  * Description:	Install a single package in a single zone
2942  * Arguments:	a_zoneName - pointer to string representing the name of the
2943  *			zone to install the package into.
2944  *		a_idsName - pointer to string representing the data stream
2945  *			device (input data stream) containing the package to
2946  *			be installed.
2947  *			If this is == NULL the package is assumed to be
2948  *			spooled in the zone temporary directory.
2949  *		a_zoneAdminFile - pointer to string representing the admin
2950  *			file to pass to pkginstall when installing the package.
2951  *			If this is == NULL no admin file is given to pkginstall.
2952  *		a_zoneTempDir - pointer to string representing the temporary
2953  *			directory in which spooled packages can be found if
2954  *			a_idsName is == NULL.
2955  *		a_altBinDir - pointer to string representing an alternative
2956  *			binary location directory to pass to pkginstall.
2957  *			If this is == NULL no alternative binary location is
2958  *			passed to pkginstall.
2959  *		a_scratchName - pointer to string representing the name of the
2960  *			scratch zone to use for installation.
2961  *		a_zoneState - state of the zone; must be mounted or running.
2962  *		a_tmpzn - B_TRUE when this zone is booted by the package
2963  *			command or B_FALSE if it was running before.
2964  * Returns:	void
2965  * NOTE:	As a side effect, "ckreturn" is called on the result returned
2966  *		from running 'pkginstall' in the zone; this sets several global
2967  *		variables which allows the caller to determine the result of
2968  *		the installation operation.
2969  */
2970 
2971 static void
2972 install_in_one_zone(char *a_zoneName, char *a_idsName,
2973     char *a_zoneAdminFile, char *a_zoneTempDir,
2974     char *a_altBinDir, zone_state_t a_zoneState, boolean_t a_tmpzn)
2975 {
2976 	char	zoneStreamName[PATH_MAX] = {'\0'};
2977 	int	n;
2978 
2979 	/* entry assertions */
2980 
2981 	assert(a_zoneName != (char *)NULL);
2982 	assert(*a_zoneName != '\0');
2983 
2984 	/* entry debugging info */
2985 
2986 	echoDebug(DBG_INSTINONEZONE_ENTRY);
2987 	echoDebug(DBG_INSTINONEZONE_ARGS, a_zoneName, PSTR(a_idsName),
2988 	    PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir),
2989 	    PSTR(a_altBinDir));
2990 
2991 	/* echo operation to perform to stdout */
2992 
2993 	echo(MSG_INSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
2994 
2995 	/* determine path to the package stream */
2996 
2997 	if (a_idsName == (char *)NULL) {
2998 		/* locate temp stream created earlier */
2999 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3000 		    "%s/%s.dstream", a_zoneTempDir, pkginst);
3001 	} else {
3002 		/* use stream passed in on command line */
3003 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3004 		    "%s", a_idsName);
3005 	}
3006 
3007 	echoDebug(DBG_INSTALL_IN_ZONE, pkginst, a_zoneName, zoneStreamName);
3008 
3009 	n = pkgZoneInstall(a_zoneName, a_zoneState, zoneStreamName,
3010 	    a_altBinDir, a_zoneAdminFile, a_tmpzn);
3011 
3012 	/* set success/fail condition variables */
3013 
3014 	ckreturn(n);
3015 
3016 	/* exit debugging info */
3017 
3018 	echoDebug(DBG_INSTALL_FLAG_VALUES, "after install", admnflag, doreboot,
3019 	    failflag, interrupted, intrflag, ireboot, needconsult,
3020 	    nullflag, warnflag);
3021 }
3022 
3023 /*
3024  * Name:	install_in_zones
3025  * Description:	Install a single package in the zones that are running from
3026  *		a list of zones
3027  * Arguments:	a_zlst - list of zones to install the package into
3028  *		a_idsName - pointer to string representing the data stream
3029  *			device (input data stream) containing the package to
3030  *			be installed.
3031  *			If this is == NULL the package is assumed to be
3032  *			spooled in the zone temporary directory.
3033  *		a_altBinDir - pointer to string representing an alternative
3034  *			binary location directory to pass to pkginstall.
3035  *			If this is == NULL no alternative binary location is
3036  *			passed to pkginstall.
3037  *		a_zoneAdminFile - pointer to string representing the admin
3038  *			file to pass to pkginstall when installing the package.
3039  *			If this is == NULL no admin file is given to pkginstall.
3040  *		a_zoneTempDir - pointer to string representing the temporary
3041  *			directory in which spooled packages can be found if
3042  *			a_idsName is == NULL.
3043  */
3044 
3045 static int
3046 install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3047     char *a_zoneAdminFile, char *a_zoneTempDir)
3048 {
3049 	char		*zoneName;
3050 	int		zoneIndex;
3051 	int		zonesSkipped = 0;
3052 	zone_state_t	zst;
3053 
3054 	/* entry assertions */
3055 
3056 	assert(a_zlst != (zoneList_t)NULL);
3057 
3058 	/* entry debugging info */
3059 
3060 	echoDebug(DBG_INSTALLINZONES_ENTRY);
3061 	echoDebug(DBG_INSTALLINZONES_ARGS, PSTR(a_idsName),
3062 	    PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3063 
3064 	/* process each zone in the list */
3065 
3066 	for (zoneIndex = 0;
3067 	    (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3068 	    zoneIndex++) {
3069 
3070 		/* skip the zone if it is NOT running */
3071 
3072 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3073 		if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3074 			zonesSkipped++;
3075 			echoDebug(DBG_SKIPPING_ZONE, zoneName);
3076 			continue;
3077 		}
3078 
3079 		/* install the package in this zone */
3080 
3081 		install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3082 		    a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3083 		    zst, B_FALSE);
3084 	}
3085 
3086 	return (zonesSkipped);
3087 }
3088 
3089 /*
3090  * Name:	boot_and_install_in_zones
3091  * Description:	Install a single package in the zones that are NOT running from
3092  *		a list of zones - each zone is booted, the package installed,
3093  *		and the zone is halted
3094  * Arguments:	a_zlst - list of zones to install the package into
3095  *		a_idsName - pointer to string representing the data stream
3096  *			device (input data stream) containing the package to
3097  *			be installed.
3098  *			If this is == NULL the package is assumed to be
3099  *			spooled in the zone temporary directory.
3100  *		a_altBinDir - pointer to string representing an alternative
3101  *			binary location directory to pass to pkginstall.
3102  *			If this is == NULL no alternative binary location is
3103  *			passed to pkginstall.
3104  *		a_zoneAdminFile - pointer to string representing the admin
3105  *			file to pass to pkginstall when installing the package.
3106  *			If this is == NULL no admin file is given to pkginstall.
3107  *		a_zoneTempDir - pointer to string representing the temporary
3108  *			directory in which spooled packages can be found if
3109  *			a_idsName is == NULL.
3110  */
3111 
3112 static int
3113 boot_and_install_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3114     char *a_zoneAdminFile, char *a_zoneTempDir)
3115 {
3116 	boolean_t	b;
3117 	char		*zoneName;
3118 	int		zoneIndex;
3119 	int		zonesSkipped = 0;
3120 	zone_state_t	zst;
3121 
3122 	/* entry assertions */
3123 
3124 	assert(a_zlst != (zoneList_t)NULL);
3125 
3126 	/* entry debugging info */
3127 
3128 	echoDebug(DBG_BOOTINSTALLINZONES_ENTRY);
3129 	echoDebug(DBG_BOOTINSTALLINZONES_ARGS, PSTR(a_idsName),
3130 	    PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3131 
3132 	/* process each zone in the list */
3133 
3134 	for (zoneIndex = 0;
3135 	    (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3136 	    zoneIndex++) {
3137 
3138 		/* skip the zone if it IS running */
3139 
3140 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3141 		if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3142 			echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3143 			continue;
3144 		}
3145 
3146 		/* skip the zone if it is NOT bootable */
3147 
3148 		if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3149 			echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3150 			echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3151 			continue;
3152 		}
3153 
3154 		/* mount up the zone */
3155 
3156 		echo(MSG_BOOTING_ZONE, zoneName);
3157 		echoDebug(DBG_BOOTING_ZONE, zoneName);
3158 
3159 		b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3160 		    ZONE_STATE_MOUNTED);
3161 		if (b == B_FALSE) {
3162 			progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3163 			/* set fatal error return condition */
3164 			ckreturn(1);
3165 			zonesSkipped++;
3166 			continue;
3167 		}
3168 
3169 		/* install the package in this zone */
3170 
3171 		install_in_one_zone(z_zlist_get_scratch(a_zlst, zoneIndex),
3172 		    a_idsName, a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3173 		    ZONE_STATE_MOUNTED, B_TRUE);
3174 
3175 		/* restore original state of zone */
3176 
3177 		echo(MSG_RESTORE_ZONE_STATE, zoneName);
3178 		echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3179 
3180 		b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3181 	}
3182 
3183 	return (zonesSkipped);
3184 }
3185 
3186 /*
3187  * Name:	pkginstall_check_in_one_zone
3188  * Description:	Do a pre install check of a single package in a single zone
3189  * Arguments:	a_zoneName - pointer to string representing the name of the
3190  *			zone to check install the package in.
3191  *		a_idsName - pointer to string representing the data stream
3192  *			device (input data stream) containing the package to
3193  *			be check installed.
3194  *			If this is == NULL the package is assumed to be
3195  *			spooled in the zone temporary directory.
3196  *		a_zoneAdminFile - pointer to string representing the admin
3197  *			file to pass to pkginstall when installing the package.
3198  *			If this is == NULL no admin file is given to pkginstall.
3199  *		a_zoneTempDir - pointer to string representing the temporary
3200  *			directory in which spooled packages can be found if
3201  *			a_idsName is == NULL.
3202  *		a_altBinDir - pointer to string representing an alternative
3203  *			binary location directory to pass to pkginstall.
3204  *			If this is == NULL no alternative binary location is
3205  *			passed to pkginstall.
3206  *		a_scratchName - pointer to string representing the name of the
3207  *			scratch zone to use for installation.
3208  *		a_zoneState - state of the zone; must be mounted or running.
3209  *		a_tmpzn - B_TRUE when this zone is booted by the package
3210  *			command or B_FALSE if it was running before.
3211  * Returns:	void
3212  * NOTE:	As a side effect, "ckreturn" is called on the result returned
3213  *		from running 'pkginstall' in the zone; this sets several global
3214  *		variables which allows the caller to determine the result of
3215  *		the pre installation check operation.
3216  */
3217 
3218 static void
3219 pkginstall_check_in_one_zone(char *a_zoneName,
3220     char *a_idsName, char *a_zoneAdminFile, char *a_zoneTempDir,
3221     char *a_altBinDir, char *a_scratchName, zone_state_t a_zoneState,
3222     boolean_t a_tmpzn)
3223 {
3224 	char	preinstallcheckPath[PATH_MAX+1];
3225 	char	zoneStreamName[PATH_MAX] = {'\0'};
3226 	int	n;
3227 
3228 	echo(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3229 	echoDebug(MSG_CHECKINSTALL_PKG_IN_ZONE, pkginst, a_zoneName);
3230 
3231 	(void) snprintf(preinstallcheckPath, sizeof (preinstallcheckPath),
3232 	    "%s/%s.%s.preinstallcheck.txt", a_zoneTempDir, pkginst,
3233 	    a_zoneName);
3234 
3235 	if (a_idsName == (char *)NULL) {
3236 		/* locate temporary stream created earlier */
3237 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3238 		    "%s/%s.dstream", a_zoneTempDir, pkginst);
3239 	} else {
3240 		(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3241 		    "%s", a_idsName);
3242 	}
3243 
3244 	echoDebug(DBG_CHECKINSTALL_IN_ZONE, pkginst, a_zoneName,
3245 	    zoneStreamName);
3246 
3247 	n = pkgZoneCheckInstall(a_scratchName, a_zoneState, zoneStreamName,
3248 	    a_altBinDir, a_zoneAdminFile, preinstallcheckPath, a_tmpzn);
3249 
3250 	/* set success/fail condition variables */
3251 
3252 	ckreturn(n);
3253 
3254 	echoDebug(DBG_INSTALL_FLAG_VALUES, "after preinstall check",
3255 	    admnflag, doreboot, failflag, interrupted, intrflag,
3256 	    ireboot, needconsult, nullflag, warnflag);
3257 }
3258 
3259 /*
3260  * Name:	pkginstall_check_in_zones
3261  * Description:	Check installation of a single package in the zones that
3262  *		are running from a list of zones
3263  * Arguments:	a_zlst - list of zones to check install the package
3264  *		a_idsName - pointer to string representing the data stream
3265  *			device (input data stream) containing the package to
3266  *			be check installed.
3267  *			If this is == NULL the package is assumed to be
3268  *			spooled in the zone temporary directory.
3269  *		a_altBinDir - pointer to string representing an alternative
3270  *			binary location directory to pass to pkginstall.
3271  *			If this is == NULL no alternative binary location is
3272  *			passed to pkginstall.
3273  *		a_zoneAdminFile - pointer to string representing the admin
3274  *			file to pass to pkginstall when checking the installing
3275  *			of the package.
3276  *			If this is == NULL no admin file is given to pkginstall.
3277  *		a_zoneTempDir - pointer to string representing the temporary
3278  *			directory in which spooled packages can be found if
3279  *			a_idsName is == NULL.
3280  */
3281 
3282 static int
3283 pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName, char *a_altBinDir,
3284     char *a_zoneAdminFile, char *a_zoneTempDir)
3285 {
3286 	char		*zoneName;
3287 	int		zoneIndex;
3288 	int		zonesSkipped = 0;
3289 	zone_state_t	zst;
3290 
3291 	for (zoneIndex = 0;
3292 	    (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3293 	    zoneIndex++) {
3294 
3295 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3296 		if (zst != ZONE_STATE_RUNNING && zst != ZONE_STATE_MOUNTED) {
3297 			zonesSkipped++;
3298 			echoDebug(DBG_SKIPPING_ZONE, zoneName);
3299 			continue;
3300 		}
3301 
3302 		pkginstall_check_in_one_zone(zoneName, a_idsName,
3303 		    a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3304 		    z_zlist_get_scratch(a_zlst, zoneIndex), zst, B_FALSE);
3305 	}
3306 
3307 	return (zonesSkipped);
3308 }
3309 
3310 /*
3311  * Name:	boot_and_pkginstall_check_in_zones
3312  * Description:	Check installation of a single package in the zones that
3313  *		are NOT running from a list of zones - each zone is booted,
3314  *		the package installation is checked, and the zone is halted.
3315  * Arguments:	a_zlst - list of zones to install the package into
3316  *		a_idsName - pointer to string representing the data stream
3317  *			device (input data stream) containing the package to
3318  *			be check installed.
3319  *			If this is == NULL the package is assumed to be
3320  *			spooled in the zone temporary directory.
3321  *		a_altBinDir - pointer to string representing an alternative
3322  *			binary location directory to pass to pkginstall.
3323  *			If this is == NULL no alternative binary location is
3324  *			passed to pkginstall.
3325  *		a_zoneAdminFile - pointer to string representing the admin
3326  *			file to pass to pkginstall when check installing the
3327  *			package.
3328  *			If this is == NULL no admin file is given to pkginstall.
3329  *		a_zoneTempDir - pointer to string representing the temporary
3330  *			directory in which spooled packages can be found if
3331  *			a_idsName is == NULL.
3332  */
3333 
3334 static int
3335 boot_and_pkginstall_check_in_zones(zoneList_t a_zlst, char *a_idsName,
3336     char *a_altBinDir, char *a_zoneAdminFile, char *a_zoneTempDir)
3337 {
3338 	int		zoneIndex;
3339 	int		zonesSkipped = 0;
3340 	char		*zoneName;
3341 	boolean_t	b;
3342 	zone_state_t	zst;
3343 
3344 	/* entry assertions */
3345 
3346 	assert(a_zlst != (zoneList_t)NULL);
3347 
3348 	/* entry debugging info */
3349 
3350 	echoDebug(DBG_BOOTCHECKINSTALLINZONES_ENTRY);
3351 	echoDebug(DBG_BOOTCHECKINSTALLINZONES_ARGS, PSTR(a_idsName),
3352 	    PSTR(a_zoneAdminFile), PSTR(a_zoneTempDir));
3353 
3354 	/* process each zone in the list */
3355 
3356 	for (zoneIndex = 0;
3357 	    (zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) != NULL;
3358 	    zoneIndex++) {
3359 
3360 		/* skip the zone if it IS running */
3361 
3362 		zst = z_zlist_get_current_state(a_zlst, zoneIndex);
3363 		if (zst == ZONE_STATE_RUNNING || zst == ZONE_STATE_MOUNTED) {
3364 			echoDebug(DBG_SKIPPING_ZONE_BOOT, zoneName);
3365 			continue;
3366 		}
3367 
3368 		/* skip the zone if it is NOT bootable */
3369 
3370 		if (z_zlist_is_zone_runnable(a_zlst, zoneIndex) == B_FALSE) {
3371 			echo(MSG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3372 			echoDebug(DBG_SKIPPING_ZONE_NOT_RUNNABLE, zoneName);
3373 			continue;
3374 		}
3375 
3376 		/* mount up the zone */
3377 
3378 		echo(MSG_BOOTING_ZONE, zoneName);
3379 		echoDebug(DBG_BOOTING_ZONE, zoneName);
3380 
3381 		b = z_zlist_change_zone_state(a_zlst, zoneIndex,
3382 		    ZONE_STATE_MOUNTED);
3383 		if (b == B_FALSE) {
3384 			progerr(ERR_CANNOT_BOOT_ZONE, zoneName);
3385 			/* set fatal error return condition */
3386 			ckreturn(1);
3387 			zonesSkipped++;
3388 			continue;
3389 		}
3390 
3391 		/* pre-installation check of the package in this zone */
3392 
3393 		pkginstall_check_in_one_zone(zoneName, a_idsName,
3394 		    a_zoneAdminFile, a_zoneTempDir, a_altBinDir,
3395 		    z_zlist_get_scratch(a_zlst, zoneIndex),
3396 		    ZONE_STATE_MOUNTED, B_TRUE);
3397 
3398 		/* restore original state of zone */
3399 
3400 		echo(MSG_RESTORE_ZONE_STATE, zoneName);
3401 		echoDebug(DBG_RESTORE_ZONE_STATE, zoneName);
3402 
3403 		b = z_zlist_restore_zone_state(a_zlst, zoneIndex);
3404 	}
3405 
3406 	return (zonesSkipped);
3407 }
3408 
3409 /*
3410  * Function:	add_packages_in_global_with_zones
3411  * Description: call this function to add a list of packages in the global zone
3412  *		when one or more non-global zones exist
3413  * returns:
3414  *	B_TRUE to process next data stream
3415  *	B_FALSE to exit
3416  */
3417 
3418 static boolean_t
3419 add_packages_in_global_with_zones(char **a_pkgList,
3420     char *a_idsName, int a_repeat, char *a_altBinDir,
3421     char *a_device, zoneList_t a_zlst)
3422 {
3423 static	char		*zoneTempDir = (char *)NULL;
3424 static	char		*zoneAdminFile = (char *)NULL;
3425 
3426 	boolean_t	b;
3427 	char		*packageDir;
3428 	char		instdir[PATH_MAX];
3429 	char		respfile_path[PATH_MAX];
3430 	char		zoneStreamName[PATH_MAX] = {'\0'};
3431 	int		i;
3432 	int		n;
3433 	int		savenpkgs = npkgs;
3434 	int		zonesSkipped;
3435 	boolean_t	globalPresent;
3436 
3437 	/* entry assertions */
3438 
3439 	assert(a_pkgList != (char **)NULL);
3440 	assert(a_zlst != (zoneList_t)NULL);
3441 
3442 	echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ENTRY);
3443 	echoDebug(DBG_ADDPACKAGES_GZ_W_LZ_ARGS, npkgs,
3444 	    PSTR(a_idsName), a_repeat, PSTR(a_device));
3445 
3446 	/* create temporary directory for use by zone operations */
3447 
3448 	create_zone_tempdir(&zoneTempDir, tmpdir);
3449 
3450 	/* create hands off settings admin file for use in a non-global zone */
3451 
3452 	create_zone_adminfile(&zoneAdminFile, zoneTempDir, admnfile);
3453 
3454 	/* determine directory where packages can be found */
3455 
3456 	if (a_idsName == (char *)NULL) {
3457 		/* no stream - directory containing packages provided */
3458 		packageDir = pkgdev.dirname;
3459 	} else {
3460 		packageDir = zoneTempDir;
3461 	}
3462 
3463 	/* unpack and check all packages */
3464 
3465 	b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3466 	if (b != B_TRUE) {
3467 		quit(1);
3468 	}
3469 
3470 	/*
3471 	 * if the packages are contained in a directory, convert the
3472 	 * packages into individual streams because pkgZoneInstall is only able
3473 	 * to pass a stream to the non-global zone's pkginstall command.
3474 	 * After this code is executed:
3475 	 * if the original input was a datastream:
3476 	 * -> that datastream has been unpacked into "instdir"
3477 	 * if the original input was a directory with packages in it:
3478 	 * -> those packages have been placed into a single datastream
3479 	 */
3480 
3481 	if (a_idsName == (char *)NULL) {
3482 		for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3483 			char	*pkgs[2];
3484 
3485 			/* package is not a stream - create one */
3486 
3487 			(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3488 			    "%s/%s.dstream", zoneTempDir, pkginst);
3489 
3490 			echoDebug(DBG_CONVERTING_PKG, packageDir, pkginst,
3491 			    zoneStreamName);
3492 
3493 			/* set up list of packages to be this package only */
3494 
3495 			pkgs[0] = pkginst;
3496 			pkgs[1] = (char *)NULL;
3497 
3498 			n = pkgtrans(packageDir, zoneStreamName, pkgs,
3499 			    PT_SILENT|PT_ODTSTREAM);
3500 			if (n != 0) {
3501 				progerr(ERR_CANNOT_CONVERT_PKGSTRM,
3502 				    pkginst, packageDir, zoneStreamName);
3503 				quit(1);
3504 			}
3505 			npkgs--;
3506 		}
3507 		npkgs = savenpkgs;
3508 	}
3509 
3510 	/*
3511 	 * Phase I - run collect dependency information for all packages for all
3512 	 * zones - this involves running pkginstall with the "preinstallcheck"
3513 	 * option which causes all dependency checks to be performed without
3514 	 * actually doing the installation of the packages. This information is
3515 	 * gathered in the zone temporary directory and is used later to present
3516 	 * the dependency check results to the system administrator depending
3517 	 * on the administration settings.
3518 	 */
3519 
3520 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3521 
3522 		/* reset interrupted flag before calling pkginstall */
3523 
3524 		interrupted = 0;	/* last action was NOT quit */
3525 
3526 		/*
3527 		 * if this package is marked "install in this zone only", then
3528 		 * do not check dependencies in any other zone
3529 		 */
3530 
3531 		if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3532 			echoDebug(DBG_VERIFY_SKIP_THISZONE, pkginst);
3533 			npkgs--;
3534 			continue;
3535 		}
3536 
3537 		/*
3538 		 * if operation failed in global zone do not propagate
3539 		 * to any non-global zones
3540 		 */
3541 
3542 		if (interrupted != 0) {
3543 			echo(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3544 			echoDebug(MSG_CHECKINSTALL_INTERRUPT_B4_Z, pkginst);
3545 			break;
3546 		}
3547 
3548 		echoDebug(DBG_INSTALL_FLAG_VALUES, "after pkginstall",
3549 		    admnflag, doreboot, failflag, interrupted, intrflag,
3550 		    ireboot, needconsult, nullflag, warnflag);
3551 
3552 		/*
3553 		 * call pkginstall to verify this package for all non-global
3554 		 * zones that are currently booted
3555 		 */
3556 
3557 		zonesSkipped = pkginstall_check_in_zones(a_zlst, a_idsName,
3558 		    a_altBinDir, admnfile, zoneTempDir);
3559 
3560 		/*
3561 		 * if any zones were skipped (becuase they are not currently
3562 		 * booted), boot each zone one at a time and call pkginstall
3563 		 * to verify this package for each such non-global zone
3564 		 */
3565 
3566 		if (zonesSkipped > 0) {
3567 			echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3568 
3569 			zonesSkipped =
3570 			    boot_and_pkginstall_check_in_zones(a_zlst,
3571 			    a_idsName, a_altBinDir, admnfile,
3572 			    zoneTempDir);
3573 
3574 			if (zonesSkipped > 0) {
3575 				progerr(ERR_INSTALL_ZONES_SKIPPED,
3576 				    zonesSkipped);
3577 			}
3578 		}
3579 
3580 		npkgs--;
3581 	}
3582 
3583 	/*
3584 	 * At this point, all of the dependency information has been gathered
3585 	 * and is ready to be analyzed. This function processes all of that
3586 	 * dependency information and presents the results to the system
3587 	 * administrator, depending on the current administration settings.
3588 	 */
3589 
3590 	i = preinstall_verify(a_pkgList, a_zlst, zoneTempDir);
3591 	if (i != 0) {
3592 		/* dependency checks failed - exit */
3593 		quit(i);
3594 	}
3595 
3596 	npkgs = savenpkgs;
3597 
3598 	/*
3599 	 * reset all error return condition variables that may have been
3600 	 * set during package installation dependency checking so that they
3601 	 * do not reflect on the success/failure of the actual package
3602 	 * installation operations
3603 	 */
3604 
3605 	resetreturn();
3606 
3607 	/*
3608 	 * At this point, all of the dependency checking is completed, and
3609 	 * the installation of the packages can proceed. Install each package
3610 	 * one at a time, starting with the global zone, and the for each
3611 	 * non-global zone that is booted, and then for each non-global zone
3612 	 * that is not currently booted.
3613 	 */
3614 
3615 	globalPresent = z_on_zone_spec(GLOBAL_ZONENAME);
3616 
3617 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3618 		/*
3619 		 * if immediate reboot required from last package and this is
3620 		 * not 'pkgask' then suspend installation of remaining packages
3621 		 */
3622 
3623 		if ((ireboot != 0) && (askflag == 0)) {
3624 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3625 				continue;
3626 		}
3627 
3628 		/*
3629 		 * handle interrupt if the previous pkginstall was interrupted
3630 		 */
3631 
3632 		if (continue_installation() == B_FALSE) {
3633 			return (B_FALSE);
3634 		}
3635 
3636 		/*
3637 		 * if pkgask, handle response file creation:
3638 		 * - if the response file is a directory, then create a path to
3639 		 * -- a package instance within the response file directory.
3640 		 * - If the response file is NOT a directory, if more than one
3641 		 * -- package is to be installed.
3642 		 */
3643 
3644 		if ((askflag != 0) && (respdir != (char *)NULL)) {
3645 			(void) snprintf(respfile_path, sizeof (respfile_path),
3646 			    "%s/%s", respdir, pkginst);
3647 			respfile = respfile_path;
3648 		}
3649 
3650 		echo(MSG_PROC_INST, pkginst, a_device);
3651 
3652 		/*
3653 		 * If we're installing another package in the same
3654 		 * session, the second through nth pkginstall, must
3655 		 * continue from where the prior one left off. For this
3656 		 * reason, the continuation feature (implied by the
3657 		 * nature of the command) is used for the remaining
3658 		 * packages.
3659 		 */
3660 
3661 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3662 			pkgcontsrc = pkgdrtarg;
3663 		}
3664 
3665 		if (globalPresent) {
3666 			/*
3667 			 * call pkginstall for this package for the global zone
3668 			 */
3669 
3670 			echo(MSG_INSTALLING_PKG_IN_GZ, pkginst);
3671 
3672 			/* reset interrupted flag before calling pkginstall */
3673 
3674 			interrupted = 0;	/* last action was NOT quit */
3675 
3676 			n = pkgInstall(get_inst_root(), NULL, packageDir,
3677 			    a_altBinDir);
3678 
3679 			/* set success/fail condition variables */
3680 
3681 			ckreturn(n);
3682 
3683 			/*
3684 			 * if operation failed in global zone do not propagate
3685 			 * to any non-global zones
3686 			 */
3687 
3688 			if (interrupted != 0) {
3689 				echo(MSG_INSTALL_INTERRUPT_B4_ZONES, pkginst);
3690 				echoDebug(MSG_INSTALL_INTERRUPT_B4_ZONES,
3691 				    pkginst);
3692 				break;
3693 			}
3694 		}
3695 
3696 		/*
3697 		 * if this package is marked "install in this zone only",
3698 		 * then only need to install the package in the global zone;
3699 		 * skip installation in any non-global zones.
3700 		 */
3701 
3702 		if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
3703 			echoDebug(DBG_INSTALL_SKIP_THISZONE, pkginst);
3704 			npkgs--;
3705 			continue;
3706 		}
3707 
3708 		echoDebug(DBG_INSTALL_FLAG_VALUES, "install in running zones",
3709 		    admnflag, doreboot, failflag, interrupted, intrflag,
3710 		    ireboot, needconsult, nullflag, warnflag);
3711 
3712 		/* install package in currently booted zones */
3713 
3714 		zonesSkipped = install_in_zones(a_zlst, a_idsName, a_altBinDir,
3715 		    zoneAdminFile, zoneTempDir);
3716 
3717 		/* install package in zones that are not currently booted */
3718 
3719 		if (zonesSkipped > 0) {
3720 			echoDebug(DBG_ZONES_SKIPPED, zonesSkipped);
3721 
3722 			zonesSkipped = boot_and_install_in_zones(a_zlst,
3723 			    a_idsName, a_altBinDir, zoneAdminFile,
3724 			    zoneTempDir);
3725 
3726 			if (zonesSkipped > 0) {
3727 				progerr(ERR_INSTALL_ZONES_SKIPPED,
3728 				    zonesSkipped);
3729 			}
3730 		}
3731 
3732 		/*
3733 		 * package completely installed - remove any temporary stream
3734 		 * of the package that might have been created
3735 		 */
3736 
3737 		if (a_idsName == (char *)NULL) {
3738 			/* locate temporary stream created earlier */
3739 			(void) snprintf(zoneStreamName, sizeof (zoneStreamName),
3740 			    "%s/%s.dstream", zoneTempDir, pkginst);
3741 			/* remove stream - no longer needed */
3742 			echoDebug(DBG_REMOVING_DSTREAM_PKGDIR, zoneStreamName,
3743 			    pkginst);
3744 			(void) remove(zoneStreamName);
3745 		} else {
3746 			/* remove package - no longer needed */
3747 			if (snprintf(instdir, sizeof (instdir), "%s/%s",
3748 			    zoneTempDir, pkginst) >= PATH_MAX) {
3749 				progerr(ERR_CANNOT_CREATE_PKGPATH, tmpdir);
3750 				quit(1);
3751 			}
3752 			echoDebug(DBG_REMOVING_PKG_TMPDIR, instdir, pkginst);
3753 			(void) remove(instdir);
3754 		}
3755 
3756 		/* decrement number of packages left to install */
3757 
3758 		npkgs--;
3759 
3760 		/*
3761 		 * if no packages left to install, unmount package source
3762 		 * device if appropriate
3763 		 */
3764 
3765 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3766 			(void) chdir("/");
3767 			if (!a_idsName) {
3768 				echoDebug(DBG_UNMOUNTING_DEV,
3769 				    PSTR(pkgdev.mount));
3770 				(void) pkgumount(&pkgdev);
3771 			}
3772 		}
3773 	}
3774 
3775 	/*
3776 	 * all packages in the package list have been installed.
3777 	 * Continue with installation if:
3778 	 * -- immediate reboot is NOT required
3779 	 * -- there are more packages to install
3780 	 * -- the package source is a path to a file
3781 	 * else return do NOT continue.
3782 	 */
3783 
3784 	if ((ireboot == 0) && (a_repeat != 0) &&
3785 	    (pkgdev.pathname == (char *)NULL)) {
3786 		return (B_TRUE);
3787 	}
3788 
3789 	/* return 'dont continue' */
3790 
3791 	return (B_FALSE);
3792 }
3793 
3794 /*
3795  * Function:	add_packages_in_nonglobal_zone
3796  * Description: call this function to add a list of packages in a non-global
3797  *		zone
3798  * returns:
3799  *	B_TRUE to process next data stream
3800  *	B_FALSE to exit
3801  */
3802 
3803 static boolean_t
3804 add_packages_in_nonglobal_zone(char **a_pkgList,
3805     char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3806 {
3807 static	char		*zoneTempDir = (char *)NULL;
3808 
3809 	char		*packageDir;
3810 	char		respfile_path[PATH_MAX];
3811 	int		i;
3812 	int		n;
3813 	boolean_t	b;
3814 	int		savenpkgs = npkgs;
3815 
3816 	/* entry assertions */
3817 
3818 	assert(a_pkgList != (char **)NULL);
3819 
3820 	/* entry debugging info */
3821 
3822 	echoDebug(DBG_ADDPACKAGES_LZ_ENTRY);
3823 	echoDebug(DBG_ADDPACKAGES_LZ_ARGS, npkgs, PSTR(a_idsName),
3824 	    a_repeat, PSTR(a_device));
3825 
3826 	/* create temporary directory for use by zone operations */
3827 
3828 	create_zone_tempdir(&zoneTempDir, tmpdir);
3829 
3830 	/*
3831 	 * package can be in a number of formats:
3832 	 * - file containing package stream (pkgadd -d file [pkgs])
3833 	 * - directory containing packages (pkgadd -d /dir [pkgs])
3834 	 * - device containing packages (pkgadd -d diskette1 [pkgs])
3835 	 * non-global zones can be passed open file drescriptors and
3836 	 * strings as arguments
3837 	 * - for file containing package stream
3838 	 * -- the stream can be passed directly to the non-global zone
3839 	 * - for directory
3840 	 * -- convert packages to datastream to pass to the non-global zone
3841 	 * - for device
3842 	 */
3843 
3844 	/* determine directory where packages can be found */
3845 
3846 	if (a_idsName == (char *)NULL) {
3847 		/* no stream - directory containing packages provided */
3848 		packageDir = pkgdev.dirname;
3849 	} else {
3850 		packageDir = zoneTempDir;
3851 	}
3852 
3853 	b = unpack_and_check_packages(a_pkgList, a_idsName, packageDir);
3854 	if (b != B_TRUE) {
3855 		quit(1);
3856 	}
3857 
3858 	/*
3859 	 * this is the main loop where all of the packages (as listed in the
3860 	 * package list) are added one at a time.
3861 	 */
3862 
3863 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3864 		npkgs--;
3865 	}
3866 
3867 	npkgs = savenpkgs;
3868 
3869 	/*
3870 	 * this is the main loop where all of the packages (as listed in the
3871 	 * package list) are added one at a time.
3872 	 */
3873 
3874 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
3875 		/*
3876 		 * if immediate reboot required from last package and this is
3877 		 * not 'pkgask' then suspend installation of remaining packages
3878 		 */
3879 
3880 		if ((ireboot != 0) && (askflag == 0)) {
3881 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
3882 				continue;
3883 		}
3884 
3885 		/*
3886 		 * handle interrupt if the previous pkginstall was interrupted
3887 		 */
3888 
3889 		if (continue_installation() == B_FALSE) {
3890 			return (B_FALSE);
3891 		}
3892 
3893 		/*
3894 		 * if pkgask, handle response file creation:
3895 		 * - if the response file is a directory, then create a path to
3896 		 * -- a package instance within the response file directory.
3897 		 * - If the response file is NOT a directory, if more than one
3898 		 * -- package is to be installed.
3899 		 */
3900 
3901 		if ((askflag != 0) && (respdir != (char *)NULL)) {
3902 			(void) snprintf(respfile_path, sizeof (respfile_path),
3903 			    "%s/%s", respdir, pkginst);
3904 			respfile = respfile_path;
3905 		}
3906 
3907 		echo(MSG_PROC_INST, pkginst, a_device);
3908 
3909 		/*
3910 		 * If we're installing another package in the same
3911 		 * session, the second through nth pkginstall, must
3912 		 * continue from where the prior one left off. For this
3913 		 * reason, the continuation feature (implied by the
3914 		 * nature of the command) is used for the remaining
3915 		 * packages.
3916 		 */
3917 
3918 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
3919 			pkgcontsrc = pkgdrtarg;
3920 		}
3921 
3922 		/* reset interrupted flag before calling pkginstall */
3923 
3924 		interrupted = 0;	/* last action was NOT quit */
3925 
3926 		/* call pkginstall for this package */
3927 
3928 		n = pkgInstall(get_inst_root(), NULL,
3929 		    packageDir, a_altBinDir);
3930 
3931 		/* set success/fail condition variables */
3932 
3933 		ckreturn(n);
3934 
3935 		/* decrement number of packages left to install */
3936 
3937 		npkgs--;
3938 
3939 		/*
3940 		 * if no packages left to install, unmount package source
3941 		 * device if appropriate
3942 		 */
3943 
3944 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
3945 			(void) chdir("/");
3946 			if (!a_idsName) {
3947 				(void) pkgumount(&pkgdev);
3948 			}
3949 		}
3950 	}
3951 
3952 	/*
3953 	 * all packages in the package list have been installed.
3954 	 * Continue with installation if:
3955 	 * -- immediate reboot is NOT required
3956 	 * -- there are more packages to install
3957 	 * -- the package source is a path to a file
3958 	 * else return do NOT continue.
3959 	 */
3960 
3961 	if ((ireboot == 0) && (a_repeat != 0) &&
3962 	    (pkgdev.pathname == (char *)NULL)) {
3963 		return (B_TRUE);
3964 	}
3965 
3966 	/* return 'dont continue' */
3967 
3968 	return (B_FALSE);
3969 }
3970 
3971 /*
3972  * Function:	add_packages_in_global_no_zones
3973  * Description: call this function to add a list of packages in the global zone
3974  *		when no non-global zones exist
3975  * returns:
3976  *	B_TRUE to process next data stream
3977  *	B_FALSE to exit
3978  */
3979 
3980 static boolean_t
3981 add_packages_in_global_no_zones(char **a_pkgList,
3982     char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device)
3983 {
3984 	int		n;
3985 	int		i;
3986 	char		respfile_path[PATH_MAX];
3987 	CAF_T		flags = 0;
3988 
3989 	/* entry assertions */
3990 
3991 	assert(a_pkgList != (char **)NULL);
3992 
3993 	echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ENTRY);
3994 	echoDebug(DBG_ADDPACKAGES_GZ_NO_LZ_ARGS, npkgs,
3995 	    PSTR(a_idsName), a_repeat, PSTR(a_device));
3996 
3997 	/*
3998 	 * set flags for applicability check
3999 	 */
4000 
4001 	/* in the global zone */
4002 
4003 	flags |= CAF_IN_GLOBAL_ZONE;
4004 
4005 	/* set -G flag */
4006 
4007 	if (globalZoneOnly == B_TRUE) {
4008 		flags |= CAF_SCOPE_GLOBAL;
4009 	}
4010 
4011 	/*
4012 	 * this is the main loop where all of the packages (as listed in the
4013 	 * package list) are added one at a time.
4014 	 */
4015 
4016 	for (i = 0; (pkginst = a_pkgList[i]) != NULL; i++) {
4017 		/*
4018 		 * if immediate reboot required from last package and this is
4019 		 * not 'pkgask' then suspend installation of remaining packages
4020 		 */
4021 
4022 		if ((ireboot != 0) && (askflag == 0)) {
4023 			ptext(stderr, MSG_SUSPEND_ADD, pkginst);
4024 				continue;
4025 		}
4026 
4027 		/*
4028 		 * handle interrupt if the previous pkginstall was interrupted
4029 		 */
4030 
4031 		if (continue_installation() == B_FALSE) {
4032 			return (B_FALSE);
4033 		}
4034 
4035 		/*
4036 		 * check package applicability to install in this context
4037 		 */
4038 
4039 		if (check_applicability(pkgdev.dirname,
4040 		    pkginst, get_inst_root(), flags) == B_FALSE) {
4041 			progerr(ERR_PKG_NOT_APPLICABLE, pkginst);
4042 			quit(1);
4043 		}
4044 
4045 		/*
4046 		 * if pkgask, handle response file creation:
4047 		 * - if the response file is a directory, then create a path to
4048 		 * -- a package instance within the response file directory.
4049 		 * - If the response file is NOT a directory, if more than one
4050 		 * -- package is to be installed.
4051 		 */
4052 
4053 		if ((askflag != 0) && (respdir != (char *)NULL)) {
4054 			(void) snprintf(respfile_path, sizeof (respfile_path),
4055 			    "%s/%s", respdir, pkginst);
4056 			respfile = respfile_path;
4057 		}
4058 
4059 		echo(MSG_PROC_INST, pkginst, a_device);
4060 
4061 		/*
4062 		 * If we're installing another package in the same
4063 		 * session, the second through nth pkginstall, must
4064 		 * continue from where the prior one left off. For this
4065 		 * reason, the continuation feature (implied by the
4066 		 * nature of the command) is used for the remaining
4067 		 * packages.
4068 		 */
4069 
4070 		if ((i == 1) && (pkgdrtarg != (char *)NULL)) {
4071 			pkgcontsrc = pkgdrtarg;
4072 		}
4073 
4074 		/* reset interrupted flag before calling pkginstall */
4075 
4076 		interrupted = 0;	/* last action was NOT quit */
4077 
4078 		/* call pkginstall for this package */
4079 
4080 		n = pkgInstall(get_inst_root(), a_idsName,
4081 		    pkgdev.dirname, a_altBinDir);
4082 
4083 		/* set success/fail condition variables */
4084 
4085 		ckreturn(n);
4086 
4087 		/* decrement number of packages left to install */
4088 
4089 		npkgs--;
4090 
4091 		/*
4092 		 * if no packages left to install, unmount package source
4093 		 * device if appropriate
4094 		 */
4095 
4096 		if ((npkgs <= 0) && (pkgdev.mount || a_idsName)) {
4097 			(void) chdir("/");
4098 			if (!a_idsName) {
4099 				(void) pkgumount(&pkgdev);
4100 			}
4101 		}
4102 	}
4103 
4104 	/*
4105 	 * all packages in the package list have been installed.
4106 	 * Continue with installation if:
4107 	 * -- immediate reboot is NOT required
4108 	 * -- there are more packages to install
4109 	 * -- the package source is a path to a file
4110 	 * else return do NOT continue.
4111 	 */
4112 
4113 	if ((ireboot == 0) && (a_repeat != 0) &&
4114 	    (pkgdev.pathname == (char *)NULL)) {
4115 		return (B_TRUE);
4116 	}
4117 
4118 	/* return 'dont continue' */
4119 
4120 	return (B_FALSE);
4121 }
4122 
4123 /*
4124  * returns:
4125  *	B_TRUE to process next data stream
4126  *	B_FALSE to exit
4127  */
4128 
4129 static boolean_t
4130 add_packages(char **a_pkgList,
4131     char *a_idsName, int a_repeat, char *a_altBinDir, char *a_device,
4132     boolean_t a_noZones)
4133 {
4134 	zoneList_t	zlst;
4135 	boolean_t	b;
4136 
4137 	/* entry assertions */
4138 
4139 	assert(a_pkgList != (char **)NULL);
4140 
4141 	echoDebug(DBG_ADDPACKAGES_ENTRY);
4142 	echoDebug(DBG_ADDPACKAGES_ARGS, npkgs, PSTR(a_idsName),
4143 	    a_repeat, PSTR(a_altBinDir), PSTR(a_device));
4144 
4145 	/*
4146 	 * if running in the global zone AND one or more non-global
4147 	 * zones exist, add packages in a 'zones aware' manner, else
4148 	 * add packages in the standard 'non-zones aware' manner.
4149 	 */
4150 
4151 	if ((a_noZones == B_FALSE) && (z_running_in_global_zone() == B_FALSE)) {
4152 		/* in non-global zone */
4153 
4154 		echoDebug(DBG_IN_LZ);
4155 
4156 		b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4157 		if (b != B_TRUE) {
4158 			progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4159 			/* set fatal error return condition */
4160 			ckreturn(1);
4161 			return (B_FALSE);
4162 		}
4163 
4164 		b = add_packages_in_nonglobal_zone(a_pkgList, a_idsName,
4165 		    a_repeat, a_altBinDir, a_device);
4166 
4167 		(void) z_unlock_this_zone(ZLOCKS_ALL);
4168 
4169 		return (B_FALSE);
4170 	}
4171 
4172 	/* running in the global zone */
4173 
4174 	b = z_non_global_zones_exist();
4175 	if ((a_noZones == B_FALSE) && (b == B_TRUE) &&
4176 	    (globalZoneOnly == B_FALSE)) {
4177 
4178 		echoDebug(DBG_IN_GZ_WITH_LZ);
4179 
4180 		/* error if -V specified - what to use in non-global zone? */
4181 
4182 		if (vfstab_file) {
4183 			progerr(ERR_V_USED_WITH_GZS);
4184 			quit(1);
4185 		}
4186 
4187 		/* get a list of all non-global zones */
4188 		zlst = z_get_nonglobal_zone_list();
4189 		if (zlst == (zoneList_t)NULL) {
4190 			progerr(ERR_CANNOT_GET_ZONE_LIST);
4191 			quit(1);
4192 		}
4193 
4194 		/* need to lock all of the zones */
4195 
4196 		quitSetZonelist(zlst);
4197 		b = z_lock_zones(zlst, ZLOCKS_PKG_ADMIN);
4198 		if (b == B_FALSE) {
4199 			z_free_zone_list(zlst);
4200 			progerr(ERR_CANNOT_LOCK_ZONES);
4201 			/* set fatal error return condition */
4202 			ckreturn(1);
4203 			return (B_FALSE);
4204 		}
4205 
4206 		/* add packages to all zones */
4207 
4208 		b = add_packages_in_global_with_zones(a_pkgList,
4209 		    a_idsName, a_repeat, a_altBinDir, a_device, zlst);
4210 
4211 		/* unlock all zones */
4212 
4213 		(void) z_unlock_zones(zlst, ZLOCKS_ALL);
4214 		quitSetZonelist((zoneList_t)NULL);
4215 
4216 		/* free list of all non-global zones */
4217 
4218 		z_free_zone_list(zlst);
4219 
4220 		return (B_FALSE);
4221 	}
4222 
4223 	/* in global zone no non-global zones */
4224 
4225 	echoDebug(DBG_IN_GZ_NO_LZ);
4226 
4227 	b = z_lock_this_zone(ZLOCKS_PKG_ADMIN);
4228 	if (b != B_TRUE) {
4229 		progerr(ERR_CANNOT_LOCK_THIS_ZONE);
4230 		/* set fatal error return condition */
4231 		ckreturn(1);
4232 		return (B_FALSE);
4233 	}
4234 
4235 	b = add_packages_in_global_no_zones(a_pkgList, a_idsName,
4236 	    a_repeat, a_altBinDir, a_device);
4237 
4238 	(void) z_unlock_this_zone(ZLOCKS_ALL);
4239 
4240 	return (B_FALSE);
4241 }
4242