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