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