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