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