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