zones.c revision 12734:76969fc28795
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) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26
27/*
28 * Module:	zones.c
29 * Group:	libinstzones
30 * Description:	Provide "zones" interface for install consolidation code
31 *
32 * Public Methods:
33 *  z_create_zone_admin_file - Given a location to create the file, and
34 *	optionally an existing administration file, generate an
35 *	administration file that can be used to perform "non-interactive"
36 *	operations in a non-global zone.
37 *  z_free_zone_list - free contents of zoneList_t object
38 *  z_get_nonglobal_zone_list - return zoneList_t object describing all
39 *	non-global native zones
40 *  z_get_nonglobal_zone_list_by_brand - return zoneList_t object describing
41 *      all non-global zones matching the list of zone brands passed in.
42 *  z_free_brand_list - free contents of a zoneBrandList_t object
43 *  z_make_brand_list - return a zoneBrandList_t object describing the list
44 *	of all zone brands passed in.
45 *  z_get_zonename - return the name of the current zone
46 *  z_global_only - Determine if the global zone is only zone on the spec list
47 *  z_lock_this_zone - lock this zone
48 *  z_lock_zones - lock specified zones
49 *  z_mount_in_lz - Mount global zone directory in specified zone's root file
50 *	system
51 *  z_non_global_zones_exist - Determine if any non-global native zones exist
52 *  z_on_zone_spec - Determine if named zone is on the zone_spec list
53 *  z_running_in_global_zone - Determine if running in the "global" zone
54 *  z_set_output_functions - Link program specific output functions
55 *  z_set_zone_root - Set root for zones library operations
56 *  z_set_zone_spec - Set list of zones on which actions will be performed
57 *  z_umount_lz_mount - Unmount directory mounted with z_mount_in_lz
58 *  z_unlock_this_zone - unlock this zone
59 *  z_unlock_zones - unlock specified zones
60 *  z_verify_zone_spec - Verify list of zones on which actions will be performed
61 *  z_zlist_change_zone_state - Change the current state of the specified zone
62 *  z_zlist_get_current_state - Determine the current kernel state of the
63 *	specified zone
64 *  z_zlist_get_original_state - Return the original kernal state of the
65 *	specified zone
66 *  z_zlist_get_scratch - Determine name of scratch zone
67 *  z_zlist_get_zonename - Determine name of specified zone
68 *  z_zlist_get_zonepath - Determine zonepath of specified zone
69 *  z_zlist_restore_zone_state - Return the zone to the state it was originally
70 *	in
71 *  z_zone_exec - Execute a Unix command in a specified zone and return results
72 *  z_zones_are_implemented - Determine if any zone operations can be performed
73 *  z_is_zone_branded - determine if zone has a non-native brand
74 *  z_is_zone_brand_in_list - determine if the zone's brand matches the
75 *      brand list passed in.
76 *  z_brands_are_implemented - determine if branded zones are implemented on
77 *			this system
78 */
79
80/*
81 * System includes
82 */
83
84#include <stdio.h>
85#include <stdlib.h>
86#include <unistd.h>
87#include <fcntl.h>
88#include <ctype.h>
89#include <sys/types.h>
90#include <sys/param.h>
91#include <sys/sysmacros.h>
92#include <string.h>
93#include <strings.h>
94#include <sys/stat.h>
95#include <stdarg.h>
96#include <limits.h>
97#include <errno.h>
98#include <time.h>
99#include <signal.h>
100#include <stropts.h>
101#include <wait.h>
102#include <zone.h>
103#include <sys/brand.h>
104#include <libintl.h>
105#include <locale.h>
106#include <libzonecfg.h>
107#include <libcontract.h>
108#include <sys/contract/process.h>
109#include <sys/ctfs.h>
110#include <assert.h>
111#include <dlfcn.h>
112#include <link.h>
113#include <time.h>
114
115/*
116 * local includes
117 */
118
119/*
120 * When _INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA is defined,
121 * instzones_lib.h will define the z_global_data structure.
122 * Otherwise an extern to the structure is inserted.
123 */
124
125#define	_INSTZONES_LIB_Z_DEFINE_GLOBAL_DATA
126#include "instzones_lib.h"
127#include "zones_strings.h"
128
129/*
130 * Private structures
131 */
132
133#define	CLUSTER_BRAND_NAME	"cluster"
134
135/* maximum number of arguments to exec() call */
136
137#define	UUID_FORMAT	"%02d%02d%02d%03d-%02d%02d%02d%d-%016llx"
138
139/*
140 * Library Function Prototypes
141 */
142
143#define	streq(a, b) (strcmp((a), (b)) == 0)
144
145/*
146 * Local Function Prototypes
147 */
148
149/*
150 * global internal (private) declarations
151 */
152
153/*
154 * *****************************************************************************
155 * global external (public) functions
156 * *****************************************************************************
157 */
158
159/*
160 * Name:	z_create_zone_admin_file
161 * Description:	Given a location to create the file, and optionally an existing
162 *		administration file, generate an administration file that
163 *		can be used to perform "non-interactive" operations in a
164 *		non-global zone.
165 * Arguments:	a_zoneAdminFilename - pointer to string representing the
166 *			full path of zone admin file to create
167 *		a_userAdminFilename - pointer to string representing the path
168 *			to an existing "user" administration file - the
169 *			administration file created will contain the
170 *			settings contained in this file, modified as
171 *			appropriate to supress any interaction;
172 *			If this is == NULL then the administration file
173 *			created will not contain any extra settings
174 * Returns:	boolean_t
175 *			== B_TRUE - admin file created
176 *			== B_FALSE - failed to create admin file
177 */
178
179boolean_t
180z_create_zone_admin_file(char *a_zoneAdminFilename, char *a_userAdminFilename)
181{
182	FILE	*zFp;
183	FILE	*uFp = (FILE *)NULL;
184
185	/* entry assertions */
186
187	assert(a_zoneAdminFilename != NULL);
188	assert(*a_zoneAdminFilename != '\0');
189
190	/* create temporary zone admin file */
191
192	zFp = fopen(a_zoneAdminFilename, "w");
193	if (zFp == (FILE *)NULL) {
194		return (B_FALSE);
195	}
196
197	/* open user admin file if specified */
198
199	if (a_userAdminFilename != (char *)NULL) {
200		uFp = fopen(a_userAdminFilename, "r");
201	}
202
203	/* create default admin file for zone pkg ops if no user admin file */
204
205	if (uFp == (FILE *)NULL) {
206		/* create default admin file */
207		(void) fprintf(zFp, "action=nocheck\nauthentication=nocheck\n"
208		    "basedir=default\nconflict=nocheck\nidepend=nocheck\n"
209		    "instance=unique\npartial=nocheck\nrdepend=nocheck\n"
210		    "runlevel=nocheck\nsetuid=nocheck\nspace=nocheck\n"
211		    "mail=\n");
212	} else for (;;) {
213		/* copy user admin file substitute/change appropriate entries */
214		char	buf[LINE_MAX+1];
215		char	*p;
216
217		/* read next line of user admin file */
218
219		p = fgets(buf, sizeof (buf), uFp);
220		if (p == (char *)NULL) {
221			(void) fclose(uFp);
222			break;
223		}
224
225		/* modify / replace / accept as appropriate */
226
227		if (strncmp(buf, "instance=quit", 13) == 0) {
228			(void) fprintf(zFp, "%s", "instance=unique\n");
229			/*LINTED*/
230		} else if (strncmp(buf, "keystore=", 9) == 0) {
231		} else if (strncmp(buf, "action=", 7) == 0) {
232			(void) fprintf(zFp, "action=nocheck\n");
233		} else if (strncmp(buf, "authentication=", 15) == 0) {
234			(void) fprintf(zFp, "authentication=nocheck\n");
235		} else if (strncmp(buf, "conflict=", 9) == 0) {
236			(void) fprintf(zFp, "conflict=nocheck\n");
237		} else if (strncmp(buf, "idepend=", 8) == 0) {
238			(void) fprintf(zFp, "idepend=nocheck\n");
239		} else if (strncmp(buf, "mail=", 5) == 0) {
240			(void) fprintf(zFp, "mail=\n");
241		} else if (strncmp(buf, "partial=", 8) == 0) {
242			(void) fprintf(zFp, "partial=nocheck\n");
243		} else if (strncmp(buf, "rdepend=", 8) == 0) {
244			(void) fprintf(zFp, "rdepend=nocheck\n");
245		} else if (strncmp(buf, "runlevel=", 9) == 0) {
246			(void) fprintf(zFp, "runlevel=nocheck\n");
247		} else if (strncmp(buf, "setuid=", 7) == 0) {
248			(void) fprintf(zFp, "setuid=nocheck\n");
249		} else if (strncmp(buf, "space=", 6) == 0) {
250			(void) fprintf(zFp, "space=nocheck\n");
251		} else {
252			(void) fprintf(zFp, "%s", buf);
253		}
254	}
255
256	/* close admin file and return success */
257
258	(void) fclose(zFp);
259	return (B_TRUE);
260}
261
262/*
263 * Name:	z_brands_are_implemented
264 * Description:	Determine if any branded zones may be present
265 * Arguments:	void
266 * Returns:	boolean_t
267 *			== B_TRUE - branded zones are supported
268 *			== B_FALSE - branded zones are not supported
269 */
270
271boolean_t
272z_brands_are_implemented(void)
273{
274static	boolean_t	_brandsImplementedDetermined = B_FALSE;
275static	boolean_t	_brandsAreImplemented = B_FALSE;
276
277	/* if availability has not been determined, cache it now */
278
279	if (!_brandsImplementedDetermined) {
280		_brandsImplementedDetermined = B_TRUE;
281		_brandsAreImplemented = _z_brands_are_implemented();
282		if (_brandsAreImplemented) {
283			_z_echoDebug(DBG_BRANDS_ARE_IMPLEMENTED);
284		} else {
285			_z_echoDebug(DBG_BRANDS_NOT_IMPLEMENTED);
286		}
287	}
288
289	/* return cached answer */
290
291	return (_brandsAreImplemented);
292}
293
294/*
295 * Name:	z_free_zone_list
296 * Description:	free contents of zoneList_t object
297 * Arguments:	a_zlst - handle to zoneList_t object to free
298 * Returns:	void
299 */
300
301void
302z_free_zone_list(zoneList_t a_zlst)
303{
304	int	numzones;
305
306	/* ignore empty list */
307
308	if (a_zlst == (zoneList_t)NULL) {
309		return;
310	}
311
312	/* free each entry in the zone list */
313
314	for (numzones = 0; a_zlst[numzones]._zlName != (char *)NULL;
315	    numzones++) {
316		zoneListElement_t *zelm = &a_zlst[numzones];
317
318		/* free zone name string */
319
320		free(zelm->_zlName);
321
322		/* free zonepath string */
323
324		if (zelm->_zlPath != (char *)NULL) {
325			free(zelm->_zlPath);
326		}
327
328	}
329
330	/* free handle to the list */
331
332	free(a_zlst);
333}
334
335/*
336 * Name:	z_get_nonglobal_zone_list
337 * Description: return zoneList_t object describing all non-global
338 *              native zones - branded zones are not included in list
339 * Arguments:	None.
340 * Returns:	zoneList_t
341 *			== NULL - error, list could not be generated
342 *			!= NULL - success, list returned
343 * NOTE:    	Any zoneList_t returned is placed in new storage for the
344 *		calling function. The caller must use 'z_free_zone_list' to
345 *		dispose of the storage once the list is no longer needed.
346 */
347
348zoneList_t
349z_get_nonglobal_zone_list(void)
350{
351	zoneList_t zones;
352	zoneBrandList_t *brands = NULL;
353
354	if ((brands = z_make_brand_list("native cluster", " ")) == NULL)
355		return (NULL);
356
357	zones = z_get_nonglobal_zone_list_by_brand(brands);
358
359	z_free_brand_list(brands);
360
361	return (zones);
362}
363
364/*
365 * Name:	z_free_brand_list
366 * Description: Free contents of zoneBrandList_t object
367 * Arguments:	brands - pointer to zoneBrandList_t object to free
368 * Returns: 	void
369 */
370void
371z_free_brand_list(zoneBrandList_t *brands)
372{
373	while (brands != NULL) {
374		zoneBrandList_t *temp = brands;
375		free(brands->string_ptr);
376		brands = brands->next;
377		free(temp);
378	}
379}
380
381/*
382 * Name:	z_make_brand_list
383 * Description:	Given a string with a list of brand name delimited by
384 *		the delimeter passed in, build a zoneBrandList_t structure
385 *		with the list of brand names and return it to the caller.
386 * Arguments:
387 *		brands - const char pointer to string list of brand names
388 *		delim - const char pointer to string representing the
389 *			delimeter for brands string.
390 * Returns:	zoneBrandList_t *
391 *			== NULL - error, list could not be generated
392 *			!= NULL - success, list returned
393 * NOTE:	Any zoneBrandList_t returned is placed in new storage for the
394 *		calling function.  The caller must use 'z_free_brand_list' to
395 *		dispose of the storage once the list is no longer needed.
396 */
397zoneBrandList_t *
398z_make_brand_list(const char *brands, const char *delim)
399{
400	zoneBrandList_t *brand = NULL, *head = NULL;
401	char		*blist = NULL;
402	char		*str = NULL;
403
404	if ((blist = strdup(brands)) == NULL)
405		return (NULL);
406
407	if ((str = strtok(blist, delim)) != NULL) {
408		if ((brand = (zoneBrandList_t *)
409		    malloc(sizeof (struct _zoneBrandList))) == NULL) {
410			return (NULL);
411		}
412
413		head = brand;
414		brand->string_ptr = strdup(str);
415		brand->next = NULL;
416
417		while ((str = strtok(NULL, delim)) != NULL) {
418			if ((brand->next = (zoneBrandList_t *)
419			    malloc(sizeof (struct _zoneBrandList))) == NULL) {
420				return (NULL);
421			}
422
423			brand = brand->next;
424			brand->string_ptr = strdup(str);
425			brand->next = NULL;
426		}
427	}
428
429	free(blist);
430	return (head);
431}
432
433/*
434 * Name:	z_get_nonglobal_zone_list_by_brand
435 * Description: return zoneList_t object describing all non-global
436 *              zones matching the list of brands passed in.
437 * Arguments:	brands - The list of zone brands to look for.
438 * Returns:	zoneList_t
439 *			== NULL - error, list could not be generated
440 *			!= NULL - success, list returned
441 * NOTE:    	Any zoneList_t returned is placed in new storage for the
442 *		calling function. The caller must use 'z_free_zone_list' to
443 *		dispose of the storage once the list is no longer needed.
444 */
445zoneList_t
446z_get_nonglobal_zone_list_by_brand(zoneBrandList_t *brands)
447{
448	FILE		*zoneIndexFP;
449	int		numzones = 0;
450	struct zoneent	*ze;
451	zoneList_t	zlst = NULL;
452	FILE		*mapFP;
453	char		zonename[ZONENAME_MAX];
454	zone_spec_t	*zent;
455
456	/* if zones are not implemented, return empty list */
457
458	if (!z_zones_are_implemented()) {
459		return ((zoneList_t)NULL);
460	}
461
462	/*
463	 * Open the zone index file.  Note that getzoneent_private() handles
464	 * NULL.
465	 */
466	zoneIndexFP = setzoneent();
467
468	mapFP = zonecfg_open_scratch("", B_FALSE);
469
470	/* index file open; scan all zones; see if any are at least installed */
471
472	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
473		zone_state_t	st;
474
475		/* skip the global zone */
476
477		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
478			free(ze);
479			continue;
480		}
481
482		/*
483		 * skip any zones with brands not on the brand list
484		 */
485		if (!z_is_zone_brand_in_list(ze->zone_name, brands)) {
486			free(ze);
487			continue;
488		}
489
490		/*
491		 * If the user specified an explicit zone list, then ignore any
492		 * zones that aren't on that list.
493		 */
494		if ((zent = _z_global_data._zone_spec) != NULL) {
495			while (zent != NULL) {
496				if (strcmp(zent->zl_name, ze->zone_name) == 0)
497					break;
498				zent = zent->zl_next;
499			}
500			if (zent == NULL) {
501				free(ze);
502				continue;
503			}
504		}
505
506		/* non-global zone: create entry for this zone */
507
508		if (numzones == 0) {
509			zlst = (zoneList_t)_z_calloc(
510			    sizeof (zoneListElement_t)*2);
511		} else {
512			zlst = (zoneList_t)_z_realloc(zlst,
513			    sizeof (zoneListElement_t)*(numzones+2));
514			(void) memset(&zlst[numzones], 0L,
515			    sizeof (zoneListElement_t)*2);
516		}
517
518		/*
519		 * remember the zone name, zonepath and the current
520		 * zone state of the zone.
521		 */
522		zlst[numzones]._zlName = _z_strdup(ze->zone_name);
523		zlst[numzones]._zlPath = _z_strdup(ze->zone_path);
524		zlst[numzones]._zlOrigInstallState = ze->zone_state;
525		zlst[numzones]._zlCurrInstallState = ze->zone_state;
526
527		/* get the zone kernel status */
528
529		if (zone_get_state(ze->zone_name, &st) != Z_OK) {
530			st = ZONE_STATE_INCOMPLETE;
531		}
532
533		_z_echoDebug(DBG_ZONES_NGZ_LIST_STATES,
534		    ze->zone_name, ze->zone_state, st);
535
536		/*
537		 * For a scratch zone, we need to know the kernel zone name.
538		 */
539		if (zonecfg_in_alt_root() && mapFP != NULL &&
540		    zonecfg_find_scratch(mapFP, ze->zone_name,
541		    zonecfg_get_root(), zonename, sizeof (zonename)) != -1) {
542			free(zlst[numzones]._zlScratchName);
543			zlst[numzones]._zlScratchName = _z_strdup(zonename);
544		}
545
546		/*
547		 * remember the current kernel status of the zone.
548		 */
549
550		zlst[numzones]._zlOrigKernelStatus = st;
551		zlst[numzones]._zlCurrKernelStatus = st;
552
553		numzones++;
554		free(ze);
555	}
556
557	/* close the index file */
558	endzoneent(zoneIndexFP);
559
560	if (mapFP != NULL)
561		zonecfg_close_scratch(mapFP);
562
563	/* return generated list */
564
565	return (zlst);
566}
567
568/*
569 * Name:	z_get_zonename
570 * Description:	return the name of the current zone
571 * Arguments:	void
572 * Returns:	char *
573 *			- pointer to string representing the name of the current
574 *			zone
575 * NOTE:    	Any string returned is placed in new storage for the
576 *		calling function. The caller must use 'Free' to dispose
577 *		of the storage once the string is no longer needed.
578 */
579
580char *
581z_get_zonename(void)
582{
583	ssize_t		zonenameLen;
584	char		zonename[ZONENAME_MAX];
585	zoneid_t	zoneid = (zoneid_t)-1;
586
587	/* if zones are not implemented, return "" */
588
589	if (!z_zones_are_implemented()) {
590		return (_z_strdup(""));
591	}
592
593	/* get the zone i.d. of the current zone */
594
595	zoneid = getzoneid();
596
597	/* get the name of the current zone */
598
599	zonenameLen = getzonenamebyid(zoneid, zonename, sizeof (zonename));
600
601	/* return "" if could not get zonename */
602
603	if (zonenameLen < 1) {
604		return (_z_strdup(""));
605	}
606
607	return (_z_strdup(zonename));
608}
609
610/*
611 * Name:	z_global_only
612 * Description:	Determine if the global zone is only zone on the spec list.
613 * Arguments:	None
614 * Returns:	B_TRUE if global zone is the only zone on the list,
615 *		B_FALSE otherwise.
616 */
617
618boolean_t
619z_global_only(void)
620{
621	/* return true if zones are not implemented - treate as global zone */
622
623	if (!z_zones_are_implemented()) {
624		return (B_TRUE);
625	}
626
627	/* return true if this is the global zone */
628
629	if (_z_global_data._zone_spec != NULL &&
630	    _z_global_data._zone_spec->zl_next == NULL &&
631	    strcmp(_z_global_data._zone_spec->zl_name, GLOBAL_ZONENAME) == 0) {
632		return (B_TRUE);
633	}
634
635	/* return false - not the global zone */
636
637	return (B_FALSE);
638}
639
640/*
641 * Name:	z_lock_this_zone
642 * Description:	lock this zone
643 * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
644 *			Flags indicating which locks to acquire
645 * Returns:	boolean_t
646 *			== B_TRUE - success specified locks acquired
647 *			== B_FALSE - failure specified locks not acquired
648 * NOTE: the lock objects for "this zone" are maintained internally.
649 */
650
651boolean_t
652z_lock_this_zone(ZLOCKS_T a_lflags)
653{
654	boolean_t	b;
655	char		*zoneName;
656	pid_t		pid = (pid_t)0;
657
658	/* entry assertions */
659
660	assert(a_lflags != ZLOCKS_NONE);
661
662	/* entry debugging info */
663
664	_z_echoDebug(DBG_ZONES_LCK_THIS, a_lflags);
665
666	zoneName = z_get_zonename();
667	pid = getpid();
668
669	/* lock zone administration */
670
671	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
672		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
673		    zoneName, LOBJ_ZONEADMIN, pid,
674		    MSG_ZONES_LCK_THIS_ZONEADM,
675		    ERR_ZONES_LCK_THIS_ZONEADM);
676		if (!b) {
677			(void) free(zoneName);
678			return (B_FALSE);
679		}
680	}
681
682	/* lock package administration always */
683
684	if (a_lflags & ZLOCKS_PKG_ADMIN) {
685		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
686		    zoneName, LOBJ_PKGADMIN, pid,
687		    MSG_ZONES_LCK_THIS_PKGADM,
688		    ERR_ZONES_LCK_THIS_PKGADM);
689		if (!b) {
690			(void) z_unlock_this_zone(a_lflags);
691			(void) free(zoneName);
692			return (B_FALSE);
693		}
694	}
695
696	/* lock patch administration always */
697
698	if (a_lflags & ZLOCKS_PATCH_ADMIN) {
699		b = _z_lock_zone_object(&_z_global_data._z_ObjectLocks,
700		    zoneName, LOBJ_PATCHADMIN, pid,
701		    MSG_ZONES_LCK_THIS_PATCHADM,
702		    ERR_ZONES_LCK_THIS_PATCHADM);
703		if (!b) {
704			(void) z_unlock_this_zone(a_lflags);
705			(void) free(zoneName);
706			return (B_FALSE);
707		}
708	}
709
710	(void) free(zoneName);
711
712	return (B_TRUE);
713}
714
715/*
716 * Name:	z_lock_zones
717 * Description:	lock specified zones
718 * Arguments:	a_zlst - zoneList_t object describing zones to lock
719 *		a_lflags - [RO, *RO] - (ZLOCKS_T)
720 *			Flags indicating which locks to acquire
721 * Returns:	boolean_t
722 *			== B_TRUE - success, zones locked
723 *			== B_FALSE - failure, zones not locked
724 */
725
726boolean_t
727z_lock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
728{
729	boolean_t	b;
730	int		i;
731
732	/* entry assertions */
733
734	assert(a_lflags != ZLOCKS_NONE);
735
736	/* entry debugging info */
737
738	_z_echoDebug(DBG_ZONES_LCK_ZONES, a_lflags);
739
740	/* if zones are not implemented, return TRUE */
741
742	if (z_zones_are_implemented() == B_FALSE) {
743		_z_echoDebug(DBG_ZONES_LCK_ZONES_UNIMP);
744		return (B_TRUE);
745	}
746
747	/* lock this zone first before locking other zones */
748
749	b = z_lock_this_zone(a_lflags);
750	if (b == B_FALSE) {
751		return (b);
752	}
753
754	/* ignore empty list */
755
756	if (a_zlst == (zoneList_t)NULL) {
757		_z_echoDebug(DBG_ZONES_LCK_ZONES_NOZONES);
758		return (B_FALSE);
759	}
760
761	/* zones exist */
762
763	_z_echoDebug(DBG_ZONES_LCK_ZONES_EXIST);
764
765	/*
766	 * lock each listed zone that is currently running
767	 */
768
769	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
770		/* ignore zone if already locked */
771		if (a_zlst[i]._zlStatus & ZST_LOCKED) {
772			continue;
773		}
774
775		/* ignore zone if not running */
776		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
777		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
778			continue;
779		}
780
781		/*
782		 * mark zone locked - if interrupted out during lock, an attempt
783		 * will be made to release the lock
784		 */
785		a_zlst[i]._zlStatus |= ZST_LOCKED;
786
787		/* lock this zone */
788		b = _z_lock_zone(&a_zlst[i], a_lflags);
789
790		/* on failure unlock all zones and return error */
791		if (b != B_TRUE) {
792			_z_program_error(ERR_ZONES_LCK_ZONES_FAILED,
793			    a_zlst[i]._zlName);
794			(void) z_unlock_zones(a_zlst, a_lflags);
795			return (B_FALSE);
796		}
797	}
798
799	/* success */
800
801	return (B_TRUE);
802}
803
804/*
805 * Name:	z_mount_in_lz
806 * Description:	Mount global zone directory in specified zone's root file system
807 * Arguments:	r_lzMountPoint - pointer to handle to string - on success, the
808 *			full path to the mount point relative to the global zone
809 *			root file system is returned here - this is needed to
810 *			unmount the directory when it is no longer needed
811 *		r_lzRootPath - pointer to handle to string - on success, the
812 *			full path to the mount point relative to the specified
813 *			zone's root file system is returned here - this is
814 *			passed to any command executing in the specified zone to
815 *			access the directory mounted
816 *		a_zoneName - pointer to string representing the name of the zone
817 *			to mount the specified global zone directory in
818 *		a_gzPath - pointer to string representing the full absolute path
819 *			of the global zone directory to LOFS mount inside of the
820 *			specified non-global zone
821 *		a_mountPointPrefix - pointer to string representing the prefix
822 *			to be used when creating the mount point name in the
823 *			specified zone's root directory
824 * Returns:	boolean_t
825 *			== B_TRUE - global zone directory mounted successfully
826 *			== B_FALSE - failed to mount directory in specified zone
827 * NOTE:    	Any strings returned is placed in new storage for the
828 *		calling function. The caller must use 'Free' to dispose
829 *		of the storage once the strings are no longer needed.
830 */
831
832boolean_t
833z_mount_in_lz(char **r_lzMountPoint, char **r_lzRootPath, char *a_zoneName,
834	char *a_gzPath, char *a_mountPointPrefix)
835{
836	char		lzRootPath[MAXPATHLEN] = {'\0'};
837	char		uuid[MAXPATHLEN] = {'\0'};
838	char		gzMountPoint[MAXPATHLEN] = {'\0'};
839	char		lzMountPoint[MAXPATHLEN] = {'\0'};
840	hrtime_t	hretime;
841	int		err;
842	int		slen;
843	struct tm	tstruct;
844	time_t		thetime;
845	zoneid_t	zid;
846
847	/* entry assertions */
848
849	assert(a_zoneName != (char *)NULL);
850	assert(*a_zoneName != '\0');
851	assert(a_gzPath != (char *)NULL);
852	assert(*a_gzPath != '\0');
853	assert(r_lzMountPoint != (char **)NULL);
854	assert(r_lzRootPath != (char **)NULL);
855
856	/* entry debugging info */
857
858	_z_echoDebug(DBG_ZONES_MOUNT_IN_LZ_ENTRY, a_zoneName, a_gzPath);
859
860	/* reset returned non-global zone mount point path handle */
861
862	*r_lzMountPoint = (char *)NULL;
863	*r_lzRootPath = (char *)NULL;
864
865	/* if zones are not implemented, return FALSE */
866
867	if (z_zones_are_implemented() == B_FALSE) {
868		return (B_FALSE);
869	}
870
871	/* error if global zone path is not absolute */
872
873	if (*a_gzPath != '/') {
874		_z_program_error(ERR_GZPATH_NOT_ABSOLUTE, a_gzPath);
875		return (B_FALSE);
876	}
877
878	/* error if global zone path does not exist */
879
880	if (_z_is_directory(a_gzPath) != 0) {
881		_z_program_error(ERR_GZPATH_NOT_DIR, a_gzPath, strerror(errno));
882		return (B_FALSE);
883	}
884
885	/* verify that specified non-global zone exists */
886
887	err = zone_get_id(a_zoneName, &zid);
888	if (err != Z_OK) {
889		_z_program_error(ERR_GET_ZONEID, a_zoneName,
890		    zonecfg_strerror(err));
891		return (B_FALSE);
892	}
893
894	/* obtain global zone path to non-global zones root file system */
895
896	err = zone_get_rootpath(a_zoneName, lzRootPath, sizeof (lzRootPath));
897	if (err != Z_OK) {
898		_z_program_error(ERR_NO_ZONE_ROOTPATH, a_zoneName,
899		    zonecfg_strerror(err));
900		return (B_FALSE);
901	}
902
903	if (lzRootPath[0] == '\0') {
904		_z_program_error(ERR_ROOTPATH_EMPTY, a_zoneName);
905		return (B_FALSE);
906	}
907
908	/*
909	 * lofs resolve the non-global zone's root path first in case
910	 * its in a path that's been lofs mounted read-only.
911	 * (e.g. This happens when we're tyring to patch a zone in an ABE
912	 * that lives on a filesystem that the ABE shares with the currently
913	 * running BE.)
914	 */
915	z_resolve_lofs(lzRootPath, sizeof (lzRootPath));
916
917	/* verify that the root path exists */
918
919	if (_z_is_directory(lzRootPath) != 0) {
920		_z_program_error(ERR_LZROOT_NOTDIR, lzRootPath,
921		    strerror(errno));
922		return (B_FALSE);
923	}
924
925	/*
926	 * generate a unique key - the key is the same length as unique uid
927	 * but contains different information that is as unique as can be made;
928	 * include current hires time (nanosecond real timer). Such a unique
929	 * i.d. will look like:
930	 *		0203104092-1145345-0004e94d6af481a0
931	 */
932
933	hretime = gethrtime();
934
935	thetime = time((time_t *)NULL);
936	(void) localtime_r(&thetime, &tstruct);
937
938	slen = snprintf(uuid, sizeof (uuid),
939	    UUID_FORMAT,
940	    tstruct.tm_mday, tstruct.tm_mon, tstruct.tm_year,
941	    tstruct.tm_yday, tstruct.tm_hour, tstruct.tm_min,
942	    tstruct.tm_sec,	tstruct.tm_wday, hretime);
943	if (slen > sizeof (uuid)) {
944		_z_program_error(ERR_GZMOUNT_SNPRINTFUUID_FAILED,
945		    UUID_FORMAT, sizeof (uuid));
946		return (B_FALSE);
947	}
948
949	/* create the global zone mount point */
950
951	slen = snprintf(gzMountPoint, sizeof (gzMountPoint), "%s/.SUNW_%s_%s",
952	    lzRootPath,
953	    a_mountPointPrefix ? a_mountPointPrefix : "zones", uuid);
954	if (slen > sizeof (gzMountPoint)) {
955		_z_program_error(ERR_GZMOUNT_SNPRINTFGMP_FAILED,
956		    "%s/.SUNW_%s_%s", lzRootPath,
957		    a_mountPointPrefix ? a_mountPointPrefix : "zones",
958		    uuid, sizeof (gzMountPoint));
959		return (B_FALSE);
960	}
961
962	slen = snprintf(lzMountPoint, sizeof (lzMountPoint), "%s",
963	    gzMountPoint+strlen(lzRootPath));
964	if (slen > sizeof (lzMountPoint)) {
965		_z_program_error(ERR_GZMOUNT_SNPRINTFLMP_FAILED,
966		    "%s", gzMountPoint+strlen(lzRootPath),
967		    sizeof (lzMountPoint));
968		return (B_FALSE);
969	}
970
971	_z_echoDebug(DBG_MNTPT_NAMES, a_gzPath, a_zoneName, gzMountPoint,
972	    lzMountPoint);
973
974	/* error if the mount point already exists */
975
976	if (_z_is_directory(gzMountPoint) == 0) {
977		_z_program_error(ERR_ZONEROOT_NOTDIR, gzMountPoint,
978		    a_zoneName, strerror(errno));
979		return (B_FALSE);
980	}
981
982	/* create the temporary mount point */
983
984	if (mkdir(gzMountPoint, 0600) != 0) {
985		_z_program_error(ERR_MNTPT_MKDIR, gzMountPoint, a_zoneName,
986		    strerror(errno));
987		return (B_FALSE);
988	}
989
990	/* mount the global zone path on the non-global zone root file system */
991
992	err = mount(a_gzPath, gzMountPoint, MS_RDONLY|MS_DATA, "lofs",
993	    (char *)NULL, 0, (char *)NULL, 0);
994	if (err != 0) {
995		_z_program_error(ERR_GZMOUNT_FAILED, a_gzPath,
996		    gzMountPoint, a_zoneName, strerror(errno));
997		return (B_FALSE);
998	}
999
1000	/* success - return both mountpoints to caller */
1001
1002	*r_lzMountPoint = _z_strdup(gzMountPoint);
1003
1004	*r_lzRootPath = _z_strdup(lzMountPoint);
1005
1006	/* return success */
1007
1008	return (B_TRUE);
1009}
1010
1011/*
1012 * Name:	z_non_global_zones_exist
1013 * Description:	Determine if any non-global native zones exist
1014 * Arguments:	None.
1015 * Returns:	boolean_t
1016 *	== B_TRUE - at least one non-global native zone exists
1017 *	== B_FALSE - no non-global native zone exists
1018 */
1019
1020boolean_t
1021z_non_global_zones_exist(void)
1022{
1023	FILE		*zoneIndexFP;
1024	boolean_t	anyExist = B_FALSE;
1025	struct zoneent	*ze;
1026	zone_spec_t	*zent;
1027
1028	/* if zones are not implemented, return FALSE */
1029
1030	if (z_zones_are_implemented() == B_FALSE) {
1031		return (B_FALSE);
1032	}
1033
1034	/* determine if any zones are configured */
1035	zoneIndexFP = setzoneent();
1036	if (zoneIndexFP == NULL) {
1037		return (B_FALSE);
1038	}
1039
1040	/* index file open; scan all zones; see if any are at least installed */
1041
1042	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1043		/*
1044		 * If the user specified an explicit zone list, then ignore any
1045		 * zones that aren't on that list.
1046		 */
1047		if ((zent = _z_global_data._zone_spec) != NULL) {
1048			while (zent != NULL) {
1049				if (strcmp(zent->zl_name, ze->zone_name) == 0)
1050					break;
1051				zent = zent->zl_next;
1052			}
1053			if (zent == NULL) {
1054				free(ze);
1055				continue;
1056			}
1057		}
1058
1059		/* skip the global zone */
1060		if (strcmp(ze->zone_name, GLOBAL_ZONENAME) == 0) {
1061			free(ze);
1062			continue;
1063		}
1064
1065		/* skip any branded zones */
1066		if (z_is_zone_branded(ze->zone_name)) {
1067			free(ze);
1068			continue;
1069		}
1070
1071		/* is this zone installed? */
1072		if (ze->zone_state >= ZONE_STATE_INSTALLED) {
1073			free(ze);
1074			anyExist = B_TRUE;
1075			break;
1076		}
1077		free(ze);
1078	}
1079
1080	/* close the index file */
1081
1082	endzoneent(zoneIndexFP);
1083
1084	/* return results */
1085
1086	return (anyExist);
1087}
1088
1089/*
1090 * Name:	z_on_zone_spec
1091 * Description:	Determine if named zone is on the zone_spec list.
1092 * Arguments:	Pointer to name to test.
1093 * Returns:	B_TRUE if named zone is on the list or if the user specified
1094 *		no list at all (all zones is the default), B_FALSE otherwise.
1095 */
1096
1097boolean_t
1098z_on_zone_spec(const char *zonename)
1099{
1100	zone_spec_t	*zent;
1101
1102	/* entry assertions */
1103
1104	assert(zonename != NULL);
1105	assert(*zonename != '\0');
1106
1107	/* return true if zones not implemented or no zone spec list defined */
1108
1109	if (!z_zones_are_implemented() || _z_global_data._zone_spec == NULL) {
1110		return (B_TRUE);
1111	}
1112
1113	/* return true if named zone is on the zone spec list */
1114
1115	for (zent = _z_global_data._zone_spec;
1116	    zent != NULL; zent = zent->zl_next) {
1117		if (strcmp(zent->zl_name, zonename) == 0)
1118			return (B_TRUE);
1119	}
1120
1121	/* named zone is not on the zone spec list */
1122
1123	return (B_FALSE);
1124}
1125
1126/*
1127 * Name:	z_running_in_global_zone
1128 * Description:	Determine if running in the "global" zone
1129 * Arguments:	void
1130 * Returns:	boolean_t
1131 *			== B_TRUE - running in global zone
1132 *			== B_FALSE - not running in global zone
1133 */
1134
1135boolean_t
1136z_running_in_global_zone(void)
1137{
1138	static	boolean_t	_zoneIdDetermined = B_FALSE;
1139	static	boolean_t	_zoneIsGlobal = B_FALSE;
1140
1141	/* if ID has not been determined, cache it now */
1142
1143	if (!_zoneIdDetermined) {
1144		_zoneIdDetermined = B_TRUE;
1145		_zoneIsGlobal = _z_running_in_global_zone();
1146	}
1147
1148	return (_zoneIsGlobal);
1149}
1150
1151/*
1152 * Name:	z_set_output_functions
1153 * Description:	Link program specific output functions to this library.
1154 * Arguments:	a_echo_fcn - (_z_printf_fcn_t)
1155 *			Function to call to cause "normal operation" messages
1156 *			to be output/displayed
1157 *		a_echo_debug_fcn - (_z_printf_fcn_t)
1158 *			Function to call to cause "debugging" messages
1159 *			to be output/displayed
1160 *		a_progerr_fcn - (_z_printf_fcn_t)
1161 *			Function to call to cause "program error" messages
1162 *			to be output/displayed
1163 * Returns:	void
1164 * NOTE:	If NULL is specified for any function, then the functionality
1165 *		associated with that function is disabled.
1166 * NOTE:	The function pointers provided must call a function that
1167 *		takes two arguments:
1168 *			function(char *format, char *message)
1169 *		Any registered function will be called like:
1170 *			function("%s", "message")
1171 */
1172
1173void
1174z_set_output_functions(_z_printf_fcn_t a_echo_fcn,
1175    _z_printf_fcn_t a_echo_debug_fcn,
1176    _z_printf_fcn_t a_progerr_fcn)
1177{
1178	_z_global_data._z_echo = a_echo_fcn;
1179	_z_global_data._z_echo_debug = a_echo_debug_fcn;
1180	_z_global_data._z_progerr = a_progerr_fcn;
1181}
1182
1183/*
1184 * Name:	z_set_zone_root
1185 * Description:	Set root for zones library operations
1186 * Arguments:	Path to root of boot environment containing zone; must be
1187 *		absolute.
1188 * Returns:	None.
1189 * NOTE:	Must be called before performing any zone-related operations.
1190 *		(Currently called directly by set_inst_root() during -R
1191 *		argument handling.)
1192 */
1193
1194void
1195z_set_zone_root(const char *zroot)
1196{
1197	char *rootdir;
1198
1199	/* if zones are not implemented, just return */
1200
1201	if (!z_zones_are_implemented())
1202		return;
1203
1204	/* entry assertions */
1205
1206	assert(zroot != NULL);
1207
1208	rootdir = _z_strdup((char *)zroot);
1209	z_canoninplace(rootdir);
1210
1211	if (strcmp(rootdir, "/") == 0) {
1212		rootdir[0] = '\0';
1213	}
1214
1215	/* free any existing cached root path */
1216	if (*_z_global_data._z_root_dir != '\0') {
1217		free(_z_global_data._z_root_dir);
1218		_z_global_data._z_root_dir = NULL;
1219	}
1220
1221	/* store duplicate of new zone root path */
1222
1223	if (*rootdir != '\0') {
1224		_z_global_data._z_root_dir = _z_strdup(rootdir);
1225	} else {
1226		_z_global_data._z_root_dir = "";
1227	}
1228
1229	/* set zone root path */
1230
1231	zonecfg_set_root(rootdir);
1232
1233	free(rootdir);
1234}
1235
1236/*
1237 * Name:	z_set_zone_spec
1238 * Description:	Set list of zones on which actions will be performed.
1239 * Arguments:	Whitespace-separated list of zone names.
1240 * Returns:	0 on success, -1 on error.
1241 * NOTES:	Will call _z_program_error if argument can't be parsed or
1242 *		memory not available.
1243 */
1244
1245int
1246z_set_zone_spec(const char *zlist)
1247{
1248	const char	*zend;
1249	ptrdiff_t	zlen;
1250	zone_spec_t	*zent;
1251	zone_spec_t	*zhead;
1252	zone_spec_t	**znextp = &zhead;
1253
1254	/* entry assertions */
1255
1256	assert(zlist != NULL);
1257
1258	/* parse list to zone_spec_t list, store in global data */
1259
1260	for (;;) {
1261		while (isspace(*zlist)) {
1262			zlist++;
1263		}
1264		if (*zlist == '\0') {
1265			break;
1266		}
1267		for (zend = zlist; *zend != '\0'; zend++) {
1268			if (isspace(*zend)) {
1269				break;
1270			}
1271		}
1272		zlen = ((ptrdiff_t)zend) - ((ptrdiff_t)zlist);
1273		if (zlen >= ZONENAME_MAX) {
1274			_z_program_error(ERR_ZONE_NAME_ILLEGAL, zlen, zlist);
1275			return (-1);
1276		}
1277		zent = _z_malloc(sizeof (*zent));
1278		(void) memcpy(zent->zl_name, zlist, zlen);
1279		zent->zl_name[zlen] = '\0';
1280		zent->zl_used = B_FALSE;
1281		*znextp = zent;
1282		znextp = &zent->zl_next;
1283		zlist = zend;
1284	}
1285	*znextp = NULL;
1286
1287	if (zhead == NULL) {
1288		_z_program_error(ERR_ZONE_LIST_EMPTY);
1289		return (-1);
1290	}
1291
1292	_z_global_data._zone_spec = zhead;
1293	return (0);
1294}
1295
1296/*
1297 * Name:	z_umount_lz_mount
1298 * Description:	Unmount directory mounted with z_mount_in_lz
1299 * Arguments:	a_lzMountPointer - pointer to string returned by z_mount_in_lz
1300 * Returns:	boolean_t
1301 *			== B_TRUE - successfully unmounted directory
1302 *			== B_FALSE - failed to unmount directory
1303 */
1304
1305boolean_t
1306z_umount_lz_mount(char *a_lzMountPoint)
1307{
1308	int	err;
1309
1310	/* entry assertions */
1311
1312	assert(a_lzMountPoint != (char *)NULL);
1313	assert(*a_lzMountPoint != '\0');
1314
1315	/* entry debugging info */
1316
1317	_z_echoDebug(DBG_ZONES_UNMOUNT_FROM_LZ_ENTRY, a_lzMountPoint);
1318
1319	/* if zones are not implemented, return TRUE */
1320
1321	if (z_zones_are_implemented() == B_FALSE) {
1322		return (B_FALSE);
1323	}
1324
1325	/* error if global zone path is not absolute */
1326
1327	if (*a_lzMountPoint != '/') {
1328		_z_program_error(ERR_LZMNTPT_NOT_ABSOLUTE, a_lzMountPoint);
1329		return (B_FALSE);
1330	}
1331
1332	/* verify mount point exists */
1333
1334	if (_z_is_directory(a_lzMountPoint) != 0) {
1335		_z_program_error(ERR_LZMNTPT_NOTDIR, a_lzMountPoint,
1336		    strerror(errno));
1337		return (B_FALSE);
1338	}
1339
1340	/* unmount */
1341
1342	err = umount2(a_lzMountPoint, 0);
1343	if (err != 0) {
1344		_z_program_error(ERR_GZUMOUNT_FAILED, a_lzMountPoint,
1345		    strerror(errno));
1346		return (B_FALSE);
1347	}
1348
1349	/* remove the mount point */
1350
1351	(void) remove(a_lzMountPoint);
1352
1353	/* return success */
1354
1355	return (B_TRUE);
1356}
1357
1358/*
1359 * Name:	z_unlock_this_zone
1360 * Description:	unlock this zone
1361 * Arguments:	a_lflags - [RO, *RO] - (ZLOCKS_T)
1362 *			Flags indicating which locks to release
1363 * Returns:	boolean_t
1364 *			== B_TRUE - success specified locks released
1365 *			== B_FALSE - failure specified locks may not be released
1366 * NOTE: the lock objects for "this zone" are maintained internally.
1367 */
1368
1369boolean_t
1370z_unlock_this_zone(ZLOCKS_T a_lflags)
1371{
1372	boolean_t	b;
1373	boolean_t	errors = B_FALSE;
1374	char		*zoneName;
1375
1376	/* entry assertions */
1377
1378	assert(a_lflags != ZLOCKS_NONE);
1379
1380	/* entry debugging info */
1381
1382	_z_echoDebug(DBG_ZONES_ULK_THIS, a_lflags);
1383
1384	/* return if no objects locked */
1385
1386	if ((_z_global_data._z_ObjectLocks == (char *)NULL) ||
1387	    (*_z_global_data._z_ObjectLocks == '\0')) {
1388		return (B_TRUE);
1389	}
1390
1391	zoneName = z_get_zonename();
1392
1393	/* unlock patch administration */
1394
1395	if (a_lflags & ZLOCKS_PATCH_ADMIN) {
1396		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1397		    zoneName, LOBJ_PATCHADMIN, ERR_ZONES_ULK_THIS_PATCH);
1398		if (!b) {
1399			errors = B_TRUE;
1400		}
1401	}
1402
1403	/* unlock package administration */
1404
1405	if (a_lflags & ZLOCKS_PKG_ADMIN) {
1406		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1407		    zoneName, LOBJ_PKGADMIN, ERR_ZONES_ULK_THIS_PACKAGE);
1408		if (!b) {
1409			errors = B_TRUE;
1410		}
1411	}
1412
1413	/* unlock zone administration */
1414
1415	if (a_lflags & ZLOCKS_ZONE_ADMIN) {
1416		b = _z_unlock_zone_object(&_z_global_data._z_ObjectLocks,
1417		    zoneName, LOBJ_ZONEADMIN, ERR_ZONES_ULK_THIS_ZONES);
1418		if (!b) {
1419			errors = B_TRUE;
1420		}
1421	}
1422
1423	(void) free(zoneName);
1424	return (!errors);
1425}
1426
1427/*
1428 * Name:	z_unlock_zones
1429 * Description:	unlock specified zones
1430 * Arguments:	a_zlst - zoneList_t object describing zones to unlock
1431 *		a_lflags - [RO, *RO] - (ZLOCKS_T)
1432 *			Flags indicating which locks to release
1433 * Returns:	boolean_t
1434 *			== B_TRUE - success, zones unlocked
1435 *			== B_FALSE - failure, zones not unlocked
1436 */
1437
1438boolean_t
1439z_unlock_zones(zoneList_t a_zlst, ZLOCKS_T a_lflags)
1440{
1441	boolean_t	b;
1442	boolean_t	errors = B_FALSE;
1443	int		i;
1444
1445	/* entry assertions */
1446
1447	assert(a_lflags != ZLOCKS_NONE);
1448
1449	/* entry debugging info */
1450
1451	_z_echoDebug(DBG_ZONES_ULK_ZONES, a_lflags);
1452
1453	/* if zones are not implemented, return TRUE */
1454
1455	if (z_zones_are_implemented() == B_FALSE) {
1456		_z_echoDebug(DBG_ZONES_ULK_ZONES_UNIMP);
1457		return (B_TRUE);
1458	}
1459
1460	/* ignore empty list */
1461
1462	if (a_zlst == (zoneList_t)NULL) {
1463		_z_echoDebug(DBG_ZONES_ULK_ZONES_NOZONES);
1464		/* unlock this zone before returning */
1465		return (z_unlock_this_zone(a_lflags));
1466	}
1467
1468	/* zones exist */
1469
1470	_z_echoDebug(DBG_ZONES_ULK_ZONES_EXIST);
1471
1472	/*
1473	 * unlock each listed zone that is currently running
1474	 */
1475
1476	for (i = 0; (a_zlst[i]._zlName != (char *)NULL); i++) {
1477		/* ignore zone if not locked */
1478		if (!(a_zlst[i]._zlStatus & ZST_LOCKED)) {
1479			continue;
1480		}
1481
1482		/* ignore zone if not running */
1483		if (a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_RUNNING &&
1484		    a_zlst[i]._zlCurrKernelStatus != ZONE_STATE_MOUNTED) {
1485			continue;
1486		}
1487
1488		/* unlock this zone */
1489		b = _z_unlock_zone(&a_zlst[i], a_lflags);
1490
1491		if (b != B_TRUE) {
1492			errors = B_TRUE;
1493		} else {
1494			/* mark zone as unlocked */
1495			a_zlst[i]._zlStatus &= ~ZST_LOCKED;
1496		}
1497	}
1498
1499	/* unlock this zone */
1500
1501	if (z_unlock_this_zone(a_lflags) != B_TRUE) {
1502		errors = B_TRUE;
1503	}
1504
1505	return (errors);
1506}
1507
1508/*
1509 * Name:	z_verify_zone_spec
1510 * Description:	Verify list of zones on which actions will be performed.
1511 * Arguments:	None.
1512 * Returns:	0 on success, -1 on error.
1513 * NOTES:	Will call _z_program_error if there are zones on the specified
1514 *		list that don't exist on the system. Requires that
1515 *		z_set_zone_root is called first (if it is called at all).
1516 */
1517
1518int
1519z_verify_zone_spec(void)
1520{
1521	FILE		*zoneIndexFP;
1522	boolean_t	errors;
1523	char		zoneIndexPath[MAXPATHLEN];
1524	struct zoneent	*ze;
1525	zone_spec_t	*zent;
1526
1527	if (!z_zones_are_implemented()) {
1528		_z_program_error(ERR_ZONES_NOT_IMPLEMENTED);
1529		return (-1);
1530	}
1531
1532	zoneIndexFP = setzoneent();
1533	if (zoneIndexFP == NULL) {
1534		_z_program_error(ERR_ZONEINDEX_OPEN, zoneIndexPath,
1535		    strerror(errno));
1536		return (-1);
1537	}
1538
1539	while ((ze = getzoneent_private(zoneIndexFP)) != NULL) {
1540		for (zent = _z_global_data._zone_spec;
1541		    zent != NULL; zent = zent->zl_next) {
1542			if (strcmp(zent->zl_name, ze->zone_name) == 0) {
1543				zent->zl_used = B_TRUE;
1544				break;
1545			}
1546		}
1547		free(ze);
1548	}
1549	endzoneent(zoneIndexFP);
1550
1551	errors = B_FALSE;
1552	for (zent = _z_global_data._zone_spec;
1553	    zent != NULL; zent = zent->zl_next) {
1554		if (!zent->zl_used) {
1555			_z_program_error(ERR_ZONE_NONEXISTENT, zent->zl_name);
1556			errors = B_TRUE;
1557		}
1558	}
1559	return (errors ? -1 : 0);
1560}
1561
1562/*
1563 * Name:	z_zlist_change_zone_state
1564 * Description:	Change the current state of the specified zone
1565 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1566 *		a_zoneIndex - index into a_zlst of the zone to return the
1567 *		a_newState - the state to put the specified zone in
1568 * Returns:	boolean_t
1569 *			== B_TRUE - the zone is in the new state
1570 *			== B_FALSE - unable to transition the zone to the
1571 *				specified state
1572 * NOTE:	This changes the "current kernel" state of the specified
1573 *		zone. For example, to boot the zone, change the state
1574 *		to "ZONE_STATE_RUNNING". To halt the zone, change the
1575 *		state to "ZONE_STATE_INSTALLED".
1576 */
1577
1578boolean_t
1579z_zlist_change_zone_state(zoneList_t a_zlst, int a_zoneIndex,
1580	zone_state_t a_newState)
1581{
1582	int	i;
1583
1584	/* entry debugging info */
1585
1586	_z_echoDebug(DBG_ZONES_CHG_Z_STATE_ENTRY, a_zoneIndex, a_newState);
1587
1588	/* ignore empty list */
1589
1590	if (a_zlst == (zoneList_t)NULL) {
1591		return (B_FALSE);
1592	}
1593
1594	/* find the specified zone in the list */
1595
1596	for (i = 0; (i != a_zoneIndex) &&
1597	    (a_zlst[i]._zlName != (char *)NULL); i++)
1598		;
1599
1600	/* return error if the specified zone does not exist */
1601
1602	if (a_zlst[i]._zlName == (char *)NULL) {
1603		return (B_FALSE);
1604	}
1605
1606	/* return success if the zone is already in this state */
1607
1608	if (a_zlst[i]._zlCurrKernelStatus == a_newState) {
1609		return (B_TRUE);
1610	}
1611
1612	/* take action on new state to set zone to */
1613
1614	_z_echoDebug(DBG_ZONES_CHG_Z_STATE, a_zlst[i]._zlName,
1615	    a_zlst[i]._zlCurrKernelStatus, a_newState);
1616
1617	switch (a_newState) {
1618	case ZONE_STATE_RUNNING:
1619	case ZONE_STATE_MOUNTED:
1620		/* these states mean "boot the zone" */
1621		return (_z_make_zone_running(&a_zlst[i]));
1622
1623	case ZONE_STATE_DOWN:
1624	case ZONE_STATE_INSTALLED:
1625		/* these states mean "halt the zone" */
1626		return (_z_make_zone_down(&a_zlst[i]));
1627
1628	case ZONE_STATE_READY:
1629		return (_z_make_zone_ready(&a_zlst[i]));
1630
1631	case ZONE_STATE_CONFIGURED:
1632	case ZONE_STATE_INCOMPLETE:
1633	case ZONE_STATE_SHUTTING_DOWN:
1634	default:
1635		/* do not know how to change zone to this state */
1636		return (B_FALSE);
1637	}
1638}
1639
1640/*
1641 * Name:	z_is_zone_branded
1642 * Description:	Determine whether zone has a non-native brand
1643 * Arguments:	a_zoneName - name of the zone to check for branding
1644 * Returns:	boolean_t
1645 *			== B_TRUE - zone has a non-native brand
1646 *			== B_FALSE - zone is native
1647 */
1648boolean_t
1649z_is_zone_branded(char *zoneName)
1650{
1651	char			brandname[MAXNAMELEN];
1652	int			err;
1653
1654	/* if zones are not implemented, return FALSE */
1655	if (!z_zones_are_implemented()) {
1656		return (B_FALSE);
1657	}
1658
1659	/* if brands are not implemented, return FALSE */
1660	if (!z_brands_are_implemented()) {
1661		return (B_FALSE);
1662	}
1663
1664	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1665	if (err != Z_OK) {
1666		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1667		return (B_FALSE);
1668	}
1669
1670	/*
1671	 * Both "native" and "cluster" are native brands
1672	 * that use the standard facilities in the areas
1673	 * of packaging/installation/patching/update.
1674	 */
1675	if (streq(brandname, NATIVE_BRAND_NAME) ||
1676	    streq(brandname, CLUSTER_BRAND_NAME)) {
1677		return (B_FALSE);
1678	} else {
1679		return (B_TRUE);
1680	}
1681}
1682
1683/*
1684 * Name:	z_is_zone_brand_in_list
1685 * Description:	Determine whether zone's brand has a match in the list
1686 *              brands passed in.
1687 * Arguments:	zoneName - name of the zone to check for branding
1688 *              list - list of brands to check the zone against
1689 * Returns:	boolean_t
1690 *			== B_TRUE - zone has a matching brand
1691 *			== B_FALSE - zone brand is not in list
1692 */
1693boolean_t
1694z_is_zone_brand_in_list(char *zoneName, zoneBrandList_t *list)
1695{
1696	char			brandname[MAXNAMELEN];
1697	int			err;
1698	zoneBrandList_t		*sp;
1699
1700	if (zoneName == NULL || list == NULL)
1701		return (B_FALSE);
1702
1703	/* if zones are not implemented, return FALSE */
1704	if (!z_zones_are_implemented()) {
1705		return (B_FALSE);
1706	}
1707
1708	/* if brands are not implemented, return FALSE */
1709	if (!z_brands_are_implemented()) {
1710		return (B_FALSE);
1711	}
1712
1713	err = zone_get_brand(zoneName, brandname, sizeof (brandname));
1714	if (err != Z_OK) {
1715		_z_program_error(ERR_BRAND_GETBRAND, zonecfg_strerror(err));
1716		return (B_FALSE);
1717	}
1718
1719	for (sp = list; sp != NULL; sp = sp->next) {
1720		if (sp->string_ptr != NULL &&
1721		    strcmp(sp->string_ptr, brandname) == 0) {
1722			return (B_TRUE);
1723		}
1724	}
1725
1726	return (B_FALSE);
1727}
1728
1729/*
1730 * Name:	z_zlist_get_current_state
1731 * Description:	Determine the current kernel state of the specified zone
1732 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1733 *		a_zoneIndex - index into a_zlst of the zone to return
1734 * Returns:	zone_state_t
1735 *			The current state of the specified zone is returned
1736 */
1737
1738zone_state_t
1739z_zlist_get_current_state(zoneList_t a_zlst, int a_zoneIndex)
1740{
1741	int	i;
1742
1743	/* ignore empty list */
1744
1745	if (a_zlst == (zoneList_t)NULL) {
1746		return (ZONE_STATE_INCOMPLETE);
1747	}
1748
1749	/* find the specified zone in the list */
1750
1751	for (i = 0; (i != a_zoneIndex) &&
1752	    (a_zlst[i]._zlName != (char *)NULL); i++)
1753		;
1754
1755	/* return error if the specified zone does not exist */
1756
1757	if (a_zlst[i]._zlName == (char *)NULL) {
1758		return (ZONE_STATE_INCOMPLETE);
1759	}
1760
1761	/* return selected zone's current kernel state */
1762
1763	_z_echoDebug(DBG_ZONES_GET_ZONE_STATE,
1764	    a_zlst[i]._zlName ? a_zlst[i]._zlName : "",
1765	    a_zlst[i]._zlCurrKernelStatus);
1766
1767	return (a_zlst[i]._zlCurrKernelStatus);
1768}
1769
1770/*
1771 * Name:	z_zlist_get_original_state
1772 * Description:	Return the original kernal state of the specified zone
1773 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1774 *		a_zoneIndex - index into a_zlst of the zone to return the
1775 * Returns:	zone_state_t
1776 *			The original state of the specified zone is returned.
1777 *			This is the state of the zone when the zoneList_t
1778 *			object was first generated.
1779 */
1780
1781zone_state_t
1782z_zlist_get_original_state(zoneList_t a_zlst, int a_zoneIndex)
1783{
1784	int	i;
1785
1786	/* ignore empty list */
1787
1788	if (a_zlst == (zoneList_t)NULL) {
1789		return (ZONE_STATE_INCOMPLETE);
1790	}
1791
1792	/* find the specified zone in the list */
1793
1794	for (i = 0; (i != a_zoneIndex) &&
1795	    (a_zlst[i]._zlName != (char *)NULL); i++)
1796		;
1797
1798	/* return error if the specified zone does not exist */
1799
1800	if (a_zlst[i]._zlName == (char *)NULL) {
1801		return (ZONE_STATE_INCOMPLETE);
1802	}
1803
1804	/* return selected zone's original kernel state */
1805
1806	return (a_zlst[i]._zlOrigKernelStatus);
1807}
1808
1809/*
1810 * Name:	z_zlist_get_scratch
1811 * Description:	Determine name of scratch zone
1812 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1813 *		a_zoneIndex - index into a_zlst of the zone to use
1814 * Return:	char *
1815 *			== NULL - zone name could not be determined
1816 *			!= NULL - pointer to string representing scratch zone
1817 * NOTE:    	Any name returned is placed in static storage that must
1818 *		NEVER be free()ed by the caller.
1819 */
1820
1821char *
1822z_zlist_get_scratch(zoneList_t a_zlst, int a_zoneIndex)
1823{
1824	int	i;
1825
1826	/* ignore empty list */
1827
1828	if (a_zlst == NULL)
1829		return (NULL);
1830
1831	/* find the specified zone in the list */
1832
1833	for (i = 0; i != a_zoneIndex; i++) {
1834		if (a_zlst[i]._zlName == NULL)
1835			return (NULL);
1836	}
1837
1838	/* return selected zone's scratch name */
1839
1840	return (a_zlst[i]._zlScratchName == NULL ? a_zlst[i]._zlName :
1841	    a_zlst[i]._zlScratchName);
1842}
1843
1844/*
1845 * Name:	z_zlist_get_zonename
1846 * Description:	Determine name of specified zone
1847 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1848 *		a_zoneIndex - index into a_zlst of the zone to return the
1849 * Return:	char *
1850 *			== NULL - zone name could not be determined
1851 *			!= NULL - pointer to string representing zone name
1852 * NOTE:    	Any zoneList_t returned is placed in static storage that must
1853 *		NEVER be free()ed by the caller.
1854 */
1855
1856char *
1857z_zlist_get_zonename(zoneList_t a_zlst, int a_zoneIndex)
1858{
1859	int	i;
1860
1861	/* ignore empty list */
1862
1863	if (a_zlst == (zoneList_t)NULL) {
1864		return ((char *)NULL);
1865	}
1866
1867	/* find the specified zone in the list */
1868
1869	for (i = 0; (i != a_zoneIndex) &&
1870	    (a_zlst[i]._zlName != (char *)NULL); i++)
1871		;
1872
1873	/* return error if the specified zone does not exist */
1874
1875	if (a_zlst[i]._zlName == (char *)NULL) {
1876		return (NULL);
1877	}
1878
1879	/* return selected zone's name */
1880
1881	return (a_zlst[i]._zlName);
1882}
1883
1884/*
1885 * Name:	z_zlist_get_zonepath
1886 * Description:	Determine zonepath of specified zone
1887 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1888 *		a_zoneIndex - index into a_zlst of the zone to return
1889 * Return:	char *
1890 *			== NULL - zonepath could not be determined
1891 *			!= NULL - pointer to string representing zonepath
1892 * NOTE:    	Any zoneList_t returned is placed in static storage that must
1893 *		NEVER be free()ed by the caller.
1894 */
1895
1896char *
1897z_zlist_get_zonepath(zoneList_t a_zlst, int a_zoneIndex)
1898{
1899	int	i;
1900
1901	/* ignore empty list */
1902
1903	if (a_zlst == (zoneList_t)NULL) {
1904		return ((char *)NULL);
1905	}
1906
1907	/* find the specified zone in the list */
1908
1909	for (i = 0; (i != a_zoneIndex) &&
1910	    (a_zlst[i]._zlName != (char *)NULL); i++)
1911		;
1912
1913	/* return error if the specified zone does not exist */
1914
1915	if (a_zlst[i]._zlName == (char *)NULL) {
1916		return (NULL);
1917	}
1918
1919	/* return selected zone's zonepath */
1920
1921	return (a_zlst[i]._zlPath);
1922}
1923
1924boolean_t
1925z_zlist_is_zone_runnable(zoneList_t a_zlst, int a_zoneIndex)
1926{
1927	int	i;
1928
1929	/* if zones are not implemented, return error */
1930
1931	if (z_zones_are_implemented() == B_FALSE) {
1932		return (B_FALSE);
1933	}
1934
1935	/* ignore empty list */
1936
1937	if (a_zlst == (zoneList_t)NULL) {
1938		return (B_FALSE);
1939	}
1940
1941	/* find the specified zone in the list */
1942
1943	for (i = 0; (i != a_zoneIndex) &&
1944	    (a_zlst[i]._zlName != (char *)NULL); i++)
1945		;
1946
1947	/* return error if the specified zone does not exist */
1948
1949	if (a_zlst[i]._zlName == (char *)NULL) {
1950		return (B_FALSE);
1951	}
1952
1953	/* choose based on current state */
1954
1955	switch (a_zlst[i]._zlCurrKernelStatus) {
1956	case ZONE_STATE_RUNNING:
1957	case ZONE_STATE_MOUNTED:
1958		/* already running */
1959		return (B_TRUE);
1960
1961	case ZONE_STATE_INSTALLED:
1962	case ZONE_STATE_DOWN:
1963	case ZONE_STATE_READY:
1964	case ZONE_STATE_SHUTTING_DOWN:
1965		/* return false if the zone cannot be booted */
1966
1967		if (a_zlst[i]._zlStatus & ZST_NOT_BOOTABLE) {
1968			return (B_FALSE);
1969		}
1970
1971		return (B_TRUE);
1972
1973	case ZONE_STATE_CONFIGURED:
1974	case ZONE_STATE_INCOMPLETE:
1975	default:
1976		/* cannot transition (boot) these states */
1977		return (B_FALSE);
1978	}
1979}
1980
1981/*
1982 * Name:	z_zlist_restore_zone_state
1983 * Description:	Return the zone to the state it was originally in
1984 * Arguments:	a_zlst - handle to zoneList_t object describing all zones
1985 *		a_zoneIndex - index into a_zlst of the zone to return the
1986 * Returns:	boolean_t
1987 *			== B_TRUE - the zone's state has been restored
1988 *			== B_FALSE - unable to transition the zone to its
1989 *				original state
1990 */
1991
1992boolean_t
1993z_zlist_restore_zone_state(zoneList_t a_zlst, int a_zoneIndex)
1994{
1995	int		i;
1996
1997	/* ignore empty list */
1998
1999	if (a_zlst == (zoneList_t)NULL) {
2000		return (B_FALSE);
2001	}
2002
2003	/* find the specified zone in the list */
2004
2005	for (i = 0; (i != a_zoneIndex) &&
2006	    (a_zlst[i]._zlName != (char *)NULL); i++)
2007		;
2008
2009	/* return error if the specified zone does not exist */
2010
2011	if (a_zlst[i]._zlName == (char *)NULL) {
2012		return (B_FALSE);
2013	}
2014
2015	/* transition the zone back to its original state */
2016
2017	return (z_zlist_change_zone_state(a_zlst,
2018	    a_zoneIndex, a_zlst[i]._zlOrigKernelStatus));
2019}
2020
2021/*
2022 * Name:	z_zone_exec
2023 * Description:	Execute a Unix command in a specified zone and return results
2024 * Arguments:	a_zoneName - pointer to string representing the name of the zone
2025 *			to execute the specified command in
2026 *		a_path - pointer to string representing the full path *in the
2027 *			non-global zone named by a_zoneName* of the Unix command
2028 *			to be executed
2029 *		a_argv[] - Pointer to array of character strings representing
2030 *			the arguments to be passed to the Unix command. The list
2031 *			must be termianted with an element that is (char *)NULL
2032 *		NOTE: a_argv[0] is the "command name" passed to the command
2033 *		a_stdoutPath - Pointer to string representing the path to a file
2034 *			into which all output to "stdout" from the Unix command
2035 *			is placed.
2036 *			== (char *)NULL - leave stdout open and pass through
2037 *			== "/dev/null" - discard stdout output
2038 *		a_strerrPath - Pointer to string representing the path to a file
2039 *			into which all output to "stderr" from the Unix command
2040 *			is placed.
2041 *			== (char *)NULL - leave stderr open and pass through
2042 *			== "/dev/null" - discard stderr output
2043 *		a_fds - Pointer to array of integers representing file
2044 *			descriptors to remain open during the call - all
2045 *			file descriptors above STDERR_FILENO not in this
2046 *			list will be closed.
2047 * Returns:	int
2048 *			The return (exit) code from the specified Unix command
2049 *			Special return codes:
2050 *			-1 : failure to exec process
2051 *			-2 : could not create contract for greenline
2052 *			-3 : fork() failed
2053 *			-4 : could not open stdout capture file
2054 *			-5 : error from 'waitpid' other than EINTR
2055 *			-6 : zones are not supported
2056 * NOTE:	All file descriptores other than 0, 1 and 2 are closed except
2057 *		for those file descriptors listed in the a_fds array.
2058 */
2059
2060int
2061z_zone_exec(const char *a_zoneName, const char *a_path, char *a_argv[],
2062	char *a_stdoutPath, char *a_stderrPath, int *a_fds)
2063{
2064	int			final_status;
2065	int			lerrno;
2066	int			status;
2067	int			tmpl_fd;
2068	pid_t			child_pid;
2069	pid_t			result_pid;
2070	struct sigaction	nact;
2071	struct sigaction	oact;
2072	void			(*funcSighup)();
2073	void			(*funcSigint)();
2074
2075	/* if zones are not implemented, return TRUE */
2076
2077	if (z_zones_are_implemented() == B_FALSE) {
2078		return (-6);	/* -6 : zones are not supported */
2079	}
2080
2081	if ((tmpl_fd = _zexec_init_template()) == -1) {
2082		_z_program_error(ERR_CANNOT_CREATE_CONTRACT, strerror(errno));
2083		return (-2);	/* -2 : could not create greenline contract */
2084	}
2085
2086	/*
2087	 * hold SIGINT/SIGHUP signals and reset signal received counter;
2088	 * after the fork1() the parent and child need to setup their respective
2089	 * interrupt handling and release the hold on the signals
2090	 */
2091
2092	(void) sighold(SIGINT);
2093	(void) sighold(SIGHUP);
2094
2095	_z_global_data._z_SigReceived = 0;	/* no signals received */
2096
2097	/*
2098	 * fork off a new process to execute command in;
2099	 * fork1() is used instead of vfork() so the child process can
2100	 * perform operations that would modify the parent process if
2101	 * vfork() were used
2102	 */
2103
2104	child_pid = fork1();
2105
2106	if (child_pid < 0) {
2107		/*
2108		 * *************************************************************
2109		 * fork failed!
2110		 * *************************************************************
2111		 */
2112
2113		(void) ct_tmpl_clear(tmpl_fd);
2114		(void) close(tmpl_fd);
2115		_z_program_error(ERR_FORK, strerror(errno));
2116
2117		/* release hold on signals */
2118
2119		(void) sigrelse(SIGHUP);
2120		(void) sigrelse(SIGINT);
2121
2122		return (-3);	/* -3 : fork() failed */
2123	}
2124
2125	if (child_pid == 0) {
2126		int	i;
2127
2128		/*
2129		 * *************************************************************
2130		 * This is the forked (child) process
2131		 * *************************************************************
2132		 */
2133
2134		(void) ct_tmpl_clear(tmpl_fd);
2135		(void) close(tmpl_fd);
2136
2137		/* reset any signals to default */
2138
2139		for (i = 0; i < NSIG; i++) {
2140			(void) sigset(i, SIG_DFL);
2141		}
2142
2143		/*
2144		 * close all file descriptors not in the a_fds list
2145		 */
2146
2147		(void) fdwalk(&_z_close_file_descriptors, (void *)a_fds);
2148
2149		/*
2150		 * if a file for stdout is present, open the file and use the
2151		 * file to capture stdout from the _zexec process
2152		 */
2153
2154		if (a_stdoutPath != (char *)NULL) {
2155			int	stdoutfd;
2156
2157			stdoutfd = open(a_stdoutPath,
2158			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2159			if (stdoutfd < 0) {
2160				_z_program_error(ERR_CAPTURE_FILE, a_stdoutPath,
2161				    strerror(errno));
2162				return (-4);
2163			}
2164
2165			(void) dup2(stdoutfd, STDOUT_FILENO);
2166			(void) close(stdoutfd);
2167		}
2168
2169		/*
2170		 * if a file for stderr is present, open the file and use the
2171		 * file to capture stderr from the _zexec process
2172		 */
2173
2174		if (a_stderrPath != (char *)NULL) {
2175			int	stderrfd;
2176
2177			stderrfd = open(a_stderrPath,
2178			    O_WRONLY|O_CREAT|O_TRUNC, 0600);
2179			if (stderrfd < 0) {
2180				_z_program_error(ERR_CAPTURE_FILE, a_stderrPath,
2181				    strerror(errno));
2182				return (-4);
2183			}
2184
2185			(void) dup2(stderrfd, STDERR_FILENO);
2186			(void) close(stderrfd);
2187		}
2188
2189		/* release all held signals */
2190
2191		(void) sigrelse(SIGHUP);
2192		(void) sigrelse(SIGINT);
2193
2194		/* execute command in the specified non-global zone */
2195
2196		_exit(_zexec(a_zoneName, a_path, a_argv));
2197	}
2198
2199	/*
2200	 * *********************************************************************
2201	 * This is the forking (parent) process
2202	 * *********************************************************************
2203	 */
2204
2205	/* register child process i.d. so signal handlers can pass signal on */
2206
2207	_z_global_data._z_ChildProcessId = child_pid;
2208
2209	/*
2210	 * setup signal handlers for SIGINT and SIGHUP and release hold
2211	 */
2212
2213	/* hook SIGINT to _z_sig_trap() */
2214
2215	nact.sa_handler = _z_sig_trap;
2216	nact.sa_flags = SA_RESTART;
2217	(void) sigemptyset(&nact.sa_mask);
2218
2219	if (sigaction(SIGINT, &nact, &oact) < 0) {
2220		funcSigint = SIG_DFL;
2221	} else {
2222		funcSigint = oact.sa_handler;
2223	}
2224
2225	/* hook SIGHUP to _z_sig_trap() */
2226
2227	nact.sa_handler = _z_sig_trap;
2228	nact.sa_flags = SA_RESTART;
2229	(void) sigemptyset(&nact.sa_mask);
2230
2231	if (sigaction(SIGHUP, &nact, &oact) < 0) {
2232		funcSighup = SIG_DFL;
2233	} else {
2234		funcSighup = oact.sa_handler;
2235	}
2236
2237	/* release hold on signals */
2238
2239	(void) sigrelse(SIGHUP);
2240	(void) sigrelse(SIGINT);
2241
2242	(void) ct_tmpl_clear(tmpl_fd);
2243	(void) close(tmpl_fd);
2244
2245	/*
2246	 * wait for the process to exit, reap child exit status
2247	 */
2248
2249	for (;;) {
2250		result_pid = waitpid(child_pid, &status, 0L);
2251		lerrno = (result_pid == -1 ? errno : 0);
2252
2253		/* break loop if child process status reaped */
2254
2255		if (result_pid != -1) {
2256			break;
2257		}
2258
2259		/* break loop if not interrupted out of waitpid */
2260
2261		if (errno != EINTR) {
2262			break;
2263		}
2264	}
2265
2266	/* reset child process i.d. so signal handlers do not pass signals on */
2267
2268	_z_global_data._z_ChildProcessId = -1;
2269
2270	/*
2271	 * If the child process terminated due to a call to exit(), then
2272	 * set results equal to the 8-bit exit status of the child process;
2273	 * otherwise, set the exit status to "-1" indicating that the child
2274	 * exited via a signal.
2275	 */
2276
2277	if (WIFEXITED(status)) {
2278		final_status = WEXITSTATUS(status);
2279		if ((_z_global_data._z_SigReceived != 0) &&
2280		    (final_status == 0)) {
2281			final_status = 1;
2282		}
2283	} else {
2284		final_status = -1;	/* -1 : failure to exec process */
2285	}
2286
2287	/* determine proper exit code */
2288
2289	if (result_pid == -1) {
2290		final_status = -5;	/* -5 : error from waitpid not EINTR */
2291	} else if (_z_global_data._z_SigReceived != 0) {
2292		final_status = -7;	/* -7 : interrupt received */
2293	}
2294
2295	/*
2296	 * reset signal handlers
2297	 */
2298
2299	/* reset SIGINT */
2300
2301	nact.sa_handler = funcSigint;
2302	nact.sa_flags = SA_RESTART;
2303	(void) sigemptyset(&nact.sa_mask);
2304
2305	(void) sigaction(SIGINT, &nact, (struct sigaction *)NULL);
2306
2307	/* reset SIGHUP */
2308
2309	nact.sa_handler = funcSighup;
2310	nact.sa_flags = SA_RESTART;
2311	(void) sigemptyset(&nact.sa_mask);
2312
2313	(void) sigaction(SIGHUP, &nact, (struct sigaction *)NULL);
2314
2315	/*
2316	 * if signal received during command execution, interrupt
2317	 * this process now.
2318	 */
2319
2320	if (_z_global_data._z_SigReceived != 0) {
2321		(void) kill(getpid(), SIGINT);
2322	}
2323
2324	/* set errno and return */
2325
2326	errno = lerrno;
2327
2328	return (final_status);
2329}
2330
2331/*
2332 * Name:	z_zones_are_implemented
2333 * Description:	Determine if any zone operations can be performed
2334 * Arguments:	void
2335 * Returns:	boolean_t
2336 *			== B_TRUE - zone operations are available
2337 *			== B_FALSE - no zone operations can be done
2338 */
2339
2340boolean_t
2341z_zones_are_implemented(void)
2342{
2343	static	boolean_t	_zonesImplementedDetermined = B_FALSE;
2344	static	boolean_t	_zonesAreImplemented = B_FALSE;
2345
2346	/* if availability has not been determined, cache it now */
2347
2348	if (!_zonesImplementedDetermined) {
2349		_zonesImplementedDetermined = B_TRUE;
2350		_zonesAreImplemented = _z_zones_are_implemented();
2351		if (!_zonesAreImplemented) {
2352			_z_echoDebug(DBG_ZONES_NOT_IMPLEMENTED);
2353		} else {
2354			_z_echoDebug(DBG_ZONES_ARE_IMPLEMENTED);
2355		}
2356	}
2357
2358	return (_zonesAreImplemented);
2359}
2360