#!/bin/ksh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
#
#

# This script provides a simple GUI for managing labeled zones.
# It provides contextual menus which provide appropriate choices.
# It must be run in the global zone as root.

# These arguments are accepted, and will result in non-interactive
# (text-only) mode:
#
#	txzonemgr [-c | -d[f]]
#
#	-c	create default zones
#	-d	destroy all zones; prompts for confirmation unless
#		the -f flag is also specified
#	-f	force
#

# DISP - use GUI (otherwise use non-interactive mode)
DISP=1
# CREATEDEF - make default zones (non-interactive)
CREATEDEF=0
# DESTROYZONES - tear down all zones (non-interactive)
DESTROYZONES=0
# FORCE - force
FORCE=0

NSCD_PER_LABEL=0
NSCD_INDICATOR=/var/tsol/doors/nscd_per_label
if [ -f $NSCD_INDICATOR ] ; then
	NSCD_PER_LABEL=1
fi

myname=$(basename $0)

TXTMP=/tmp/txzonemgr
TNRHTP=/etc/security/tsol/tnrhtp
TNRHDB=/etc/security/tsol/tnrhdb
TNZONECFG=/etc/security/tsol/tnzonecfg
PUBZONE=public
INTZONE=internal

PATH=/usr/bin:/usr/sbin:/usr/lib export PATH
title="Labeled Zone Manager 2.1"

msg_defzones=$(gettext "Create default zones using default settings?")
msg_confirmkill=$(gettext "OK to destroy all zones?")
msg_continue=$(gettext "(exit to resume $(basename $0) when ready)")
msg_getlabel=$(gettext "Select a label for the")
msg_getremote=$(gettext "Select a remote host or network from the list below:")
msg_getnet=$(gettext "Select a network configuration for the")
msg_getzone=$(gettext "Select a zone from the list below:
(select global for zone creation and shared settings)")
msg_getcmd=$(gettext "Select a command from the list below:")
msg_inuse=$(gettext "That label is already assigned\nto the")
msg_getmin=$(gettext "Select the minimum network label for the")
msg_getmax=$(gettext "Select the maximum network label for the")
msg_badip=$(gettext " is not a valid IP address")


process_options()
{
	typeset opt optlist

	optlist='cdf'

	while getopts ":$optlist" opt
	do
		case $opt in
		c)	CREATEDEF=1
			DISP=0
			;;
		d)	DESTROYZONES=1
			DISP=0
			;;
		f)	FORCE=1
			;;
		*)	gettext "invalid option -$OPTARG\n"
			usage
			return 2
			;;
		esac
	done

	if [ $CREATEDEF -eq 1 -a $DESTROYZONES -eq 1 ] ; then
		gettext "cannot combine options -c and -d\n"
		usage
		return 2
	fi
	if [ $CREATEDEF -eq 1 -a $FORCE -eq 1 ] ; then
		gettext "option -f not allowed with -c\n"
		usage
		return 2
	fi
	if [ $FORCE -eq 1 -a $CREATEDEF -eq 0 -a $DESTROYZONES -eq 0 ] ; then
		gettext "option -f specified without any other options\n"
		usage
		return 2
	fi

	shift $((OPTIND - 1))
	if [ "x$1" != "x" ] ; then
		usage
		return 2
	fi

	return 0
}

usage() {
	gettext "usage: $myname [-c | -d[f]]\n"
}

consoleCheck() {
	if [ $zonename != global ] ; then
		zconsole=$(pgrep -f "zlogin -C $zonename")
		if [ $? != 0 ] ; then
			console="Zone Console...\n"
		fi
	fi
}

labelCheck() {
	hexlabel=$(grep "^$zonename:" $TNZONECFG|cut -d : -f2);
	if [[ $hexlabel ]] ; then
		label=
		if [ $zonename = global ] ; then
			template="admin_low"
			addcipsohost="Add Multilevel Access to Remote Host...\n"
			removecipsohost="Remove Multilevel Access to Remote Host...\n"
			setmlps="Configure Multilevel Ports...\n"
		else
			template=${zonename}_unlab
			addcipsohost=
			removecipsohost=
			setmlps=

			net=$(zonecfg -z $zonename info net)
			if [[ -n $net ]] ; then
				setmlps="Configure Multilevel Ports...\n"
			elif [ $zonestate = configured ] ; then
				addnet="Configure Network Interfaces...\n"
			fi
		fi
		addremotehost="Add Single-level Access to Remote Host...\n"
		remotes=$(grep -v "^#" $TNRHDB|grep $template)
		if [ $? = 0 ] ; then
			removeremotehost="Remove Single-level Access to Remote Host...\n"
		else
			removeremotehost=
		fi
	else
		label="Select Label...\n"
		addremotehost=
		removeremotehost=
		addcipsohost=
		removecipsohost=
		setmlps=
	fi
}

cloneCheck() {
	set -A zonelist
	integer clone_cnt=0
	for p in $(zoneadm list -ip) ; do
		z=$(echo "$p"|cut -d : -f2)
		s=$(echo "$p"|cut -d : -f3)
		if [ $z = $zonename ] ; then
			continue
		elif [ $s = "installed" ] ; then
			zonelist[clone_cnt]=$z
			clone_cnt+=1
		fi
	done
	if [ $clone_cnt -gt 0 ] ; then
		clone="Clone...\n"; \
	fi
}

relabelCheck() {
	macstate=$(zonecfg -z $zonename info|grep win_mac_write)
	if [[ -n $macstate ]] ; then
		permitrelabel="Deny Relabeling\n"
	else
		permitrelabel="Permit Relabeling\n"
	fi
}

autobootCheck() {
	bootmode=$(zonecfg -z $zonename info autoboot)
	if [[ $bootmode == 'autoboot: true' ]] ; then
		autoboot="Set Manual Booting\n"
	else
		autoboot="Set Automatic Booting\n"
	fi
}

newZone() { 
		if [[ ! -n $zonename ]] ; then
			zonename=$(zenity --entry \
			    --title="$title" \
			    --width=330 \
			    --entry-text="" \
			    --text="Enter Zone Name: ")

			if [[ ! -n $zonename ]] ; then
				zonename=global
				return
			fi
		fi
		zonecfg -z $zonename "create -t SUNWtsoldef;\
		     set zonepath=/zone/$zonename"
}

removeZoneBEs() {
	delopt=$*

	zfs list -H $ZDSET/$zonename 1>/dev/null 2>&1
	if [ $? = 0 ] ; then
		for zbe in $(zfs list -rHo name $ZDSET/$zonename|grep ROOT/zbe) ; do
			zfs destroy $delopt $zbe
		done
	fi
}

updateTemplate () {
	if [ $hostType = cipso ] ; then
		template=${zonename}_cipso
		deflabel=
	else
		template=${zonename}_unlab
		deflabel="def_label=${hexlabel};"
	fi

	tnzone=$(grep "^${template}:" $TNRHTP 2>/dev/null)
	if [ $? -eq 0 ] ; then
		sed -e "/^${template}/d" $TNRHTP > $TXTMP/tnrhtp.$$ 2>/dev/null
		mv $TXTMP/tnrhtp.$$ $TNRHTP
	fi
	print "${template}:host_type=${hostType};doi=1;min_sl=${minlabel};max_sl=${maxlabel};$deflabel" >> $TNRHTP
	tnctl -t $template
}
		
setTNdata () {
	tnzline="$zonename:${hexlabel}:0::"
	grep "^$tnzline" $TNZONECFG 1>/dev/null 2>&1
	if [ $? -eq 1 ] ; then
		print "$tnzline" >> $TNZONECFG
	fi

	#
	# Add matching entries in tnrhtp if necessary
	#
	minlabel=admin_low
	maxlabel=admin_high
	hostType=cipso
	updateTemplate

	hostType=unlabeled
	updateTemplate
}

selectLabel() {
	hexlabel=$(tgnome-selectlabel \
		--title="$title" \
		--text="$msg_getlabel $zonename zone:" \
		--min="${DEFAULTLABEL}"  \
		--default="${DEFAULTLABEL}"  \
		--max=$(chk_encodings -X) \
		--accredcheck=yes \
		--mode=sensitivity \
		--format=internal)
	if [ $? = 0 ] ; then
		x=$(grep -i :{$hexlabel}: $TNZONECFG)
		if [ $? = 0 ] ; then
			z=$(print $x|cut -d : -f1)
			x=$(zenity --error \
			    --title="$title" \
			    --text="$msg_inuse $z zone.")
		else
			setTNdata
		fi
	fi	
}

getLabelRange() {
	deflabel=$(hextoalabel $hexlabel)
	minlabel=$(tgnome-selectlabel \
		--title="$title" \
		--text="$msg_getmin $zonename zone:" \
		--min="${DEFAULTLABEL}"  \
		--max="$deflabel" \
		--default="$hexlabel" \
		--accredcheck=no \
		--mode=sensitivity \
		--format=internal)
	[ $? != 0 ] && return
	
	maxlabel=$(tgnome-selectlabel \
		--title="$title" \
		--text="$msg_getmax $zonename zone:" \
		--min="$deflabel"  \
		--max=$(chk_encodings -X) \
		--default="$hexlabel" \
		--accredcheck=no \
		--mode=sensitivity \
		--format=internal)
	[ $? != 0 ] && return

	hostType=cipso
	updateTemplate
}


encryptionValues() {
	echo $(zfs get 2>&1 | grep encryption | sed -e s/^.*YES// -e s/\|//g)
}

getPassphrase() {
	pass1=$(zenity --entry --title="$title" --text="Enter passphrase:" \
	    --width=330 --hide-text)
	pass2=$(zenity --entry --title="$title" --text="Re-enter passphrase:" \
	    --width=330 --hide-text)
	if [[ "$pass1" != "$pass2" ]]; then
		zenity --error --title="$title" \
			--text="Passphrases do not match"
		return ""
	fi
	file=$(mktemp)
	echo "$pass1" > $file
	echo "$file"
}

createZDSET() {
	options=$1
	pool=${2%%/*}

	# First check if ZFS encrytption support is available
	pversion=$(zpool list -H -o version $pool)
	cversion=$(zpool upgrade -v | grep Crypto | awk '{ print $1 }')
	if (( cversion == 0 || pversion < cversion )); then
		zfs create $options $ZDSET
		return
	fi

	encryption=$(zenity --list --title="$title" --height=320 \
		--text="Select cipher for encryption of all labels:" \
		--column="encryption" $(encryptionValues))

	if [[ $? != 0 || $encryption == "off" ]]; then
		zfs create $options $ZDSET
		return
	fi

	format=$(zenity --list --title="$title" \
		--text "Select encryption key source:" \
		--column="Key format and location" \
		"Passphrase" "Generate Key in file")
	[ $? != 0 ] && exit 

	if [[ $format == "Passphrase" ]]; then
		file=$(getPassphrase)
		if [[ $file == "" ]]; then
			exit
		fi
		keysource="passphrase,file://$file"
		removefile=1;
	elif [[ $format == "Generate Key in file" ]]; then
		file=$(zenity --file-selection \
			--title="$title: Location of key file" \
			--save --confirm-overwrite)
		[ $? != 0 ] && exit 
		if [[ $encryption == "on" ]]; then
			keylen=128
		else
			t=${encryption#aes-} && keylen=${t%%-*}
		fi
		pktool genkey keystore=file keytype=aes \
		    keylen=$keylen outkey=$file
		keysource="raw,file:///$file"
	fi

	options="$options -o encryption=$encryption -o keysource=$keysource"
	zfs create $options $ZDSET
	if (( removefile == 1 )); then
		zfs set keysource=passphrase,prompt $ZDSET
		rm $file
	fi
}


initialize() {
	zonepath=$(zoneadm -z $zonename list -p|cut -d : -f4)
	ZONE_ETC_DIR=$zonepath/root/etc
	SYSIDCFG=${ZONE_ETC_DIR}/sysidcfg

	if [ -f /var/ldap/ldap_client_file ] ; then
		ldapaddress=$(ldapclient list | \
		    grep "^NS_LDAP_SERVERS" | cut -d " " -f2)
		print "name_service=LDAP {" > ${SYSIDCFG}
		domain=$(domainname)
		print "domain_name=$domain" >> ${SYSIDCFG}
		profName=$(ldapclient list | \
		    grep "^NS_LDAP_PROFILE" | cut -d " " -f2)
		proxyPwd=$(ldapclient list | \
		    grep "^NS_LDAP_BINDPASSWD" | cut -d " " -f2)
		proxyDN=$(ldapclient list | \
		    grep "^NS_LDAP_BINDDN" | cut -d " " -f 2)
		if [ "$proxyDN" ] ; then
			print "proxy_dn=\"$proxyDN\"" >> ${SYSIDCFG}
			print "proxy_password=\"$proxyPwd\"" >> ${SYSIDCFG}
		fi
		print "profile=$profName" >> ${SYSIDCFG}
		print "profile_server=$ldapaddress }" >> ${SYSIDCFG}
		cp /etc/nsswitch.conf $ZONE_ETC_DIR/nsswitch.ldap
	else
		print "name_service=NONE" > ${SYSIDCFG}
		fi
	print "security_policy=NONE" >> ${SYSIDCFG}
	locale=$(locale|grep LANG | cut -d "=" -f2)
	if [[ -z $locale ]] ; then
		locale="C"
	fi
	print "system_locale=$locale" >> ${SYSIDCFG}
	timezone=$(grep "^TZ" /etc/TIMEZONE|cut -d "=" -f2)
	print "timezone=$timezone" >> ${SYSIDCFG}
	print "terminal=vt100" >> ${SYSIDCFG}
	rootpwd=$(grep "^root:" /etc/shadow|cut -d : -f2)
 
#	There are two problems with setting the root password:
#		The zone's shadow file may be read-only
#		The password contains unparsable characters
#	so the following line is commented out until this is resolved.

	#print "root_password=$rootpwd" >> ${SYSIDCFG}
	print "nfs4_domain=dynamic" >> ${SYSIDCFG}
	print "network_interface=PRIMARY {" >> ${SYSIDCFG}

	net=$(zonecfg -z $zonename info net)
	ipType=$(zonecfg -z $zonename info ip-type|cut -d" " -f2)
	if [ $ipType = exclusive ] ; then
		hostname=$(zenity --entry \
		    --title="$title" \
		    --width=330 \
		    --text="${zonename}0: Enter Hostname or dhcp: ")
		[ $? != 0 ] && return

		if [ $hostname = dhcp ] ; then
			print "dhcp" >> ${SYSIDCFG}
		else
			print "hostname=$hostname" >> ${SYSIDCFG}
			ipaddr=$(getent hosts $hostname|cut -f1)
			if [ $? != 0 ] ; then
				ipaddr=$(zenity --entry \
				    --title="$title" \
				    --text="$nic: Enter IP address: " \
				    --entry-text a.b.c.d)
				[ $? != 0 ] && return
				
				validateIPaddr
				if [[ -z $ipaddr ]] ; then
					return
				fi
			fi
			print "ip_address=$ipaddr" >> ${SYSIDCFG}
			getNetmask
			print "netmask=$nm" >> ${SYSIDCFG}
			print "default_route=none" >> ${SYSIDCFG}
			template=${zonename}_cipso
			cidr=32
			updateTnrhdb
		fi
	elif [[ -n $net ]] ; then
		hostname=$(hostname)
		hostname=$(zenity --entry \
		    --title="$title" \
		    --width=330 \
		    --text="Enter Hostname: " \
		    --entry-text $hostname)
		[ $? != 0 ] && return
		
		print "hostname=$hostname" >> ${SYSIDCFG}
		ipaddr=$(getent hosts $hostname|cut -f1)
		if [ $? = 0 ] ; then
			print "ip_address=$ipaddr" >> ${SYSIDCFG}
		fi
	else
		getAllZoneNICs
		for i in ${aznics[*]} ; do
			ipaddr=$(ifconfig $i|grep inet|cut -d " " -f2)
		done
		print "hostname=$(hostname)" >> ${SYSIDCFG}
		print "ip_address=$ipaddr" >> ${SYSIDCFG}
	fi
		
	print "protocol_ipv6=no }" >> ${SYSIDCFG}
	cp /etc/default/nfs ${ZONE_ETC_DIR}/default/nfs
	touch ${ZONE_ETC_DIR}/.NFS4inst_state.domain
}

clone() {
	image=$1
	if [[ -z $image ]] ; then
		msg_clone=$(gettext "Clone the $zonename zone using a
snapshot of one of the following halted zones:")
		image=$(zenity --list \
		    --title="$title" \
		    --text="$msg_clone" \
		    --height=300 \
		    --width=330 \
		    --column="Installed Zones" ${zonelist[*]})
	fi

	if [[ -n $image ]] ; then
		removeZoneBEs
		zoneadm -z $zonename clone $image

		if [ $NSCD_PER_LABEL = 0 ] ; then
			sharePasswd $zonename
		else
			unsharePasswd $zonename
		fi

		ipType=$(zonecfg -z $zonename info ip-type|cut -d" " -f2)
		if [ $ipType = exclusive ] ; then
			zoneadm -z $zonename ready
			zonepath=$(zoneadm -z $zonename list -p|cut -d : -f4)
			sys-unconfig -R $zonepath/root 2>/dev/null
			initialize
			zoneadm -z $zonename halt
		fi
	fi
}

install() {
	removeZoneBEs
	if [ $DISP -eq 0 ] ; then
		gettext "installing zone $zonename ...\n"
		zoneadm -z $zonename install
	else
		# sleep is needed here to avoid occasional timing
		# problem with gnome-terminal display...
		sleep 2
		gnome-terminal \
		    --title="$title: Installing $zonename zone" \
		    --command "zoneadm -z $zonename install" \
		    --disable-factory \
		    --hide-menubar
	fi

	zonestate=$(zoneadm -z $zonename list -p | cut -d : -f 3)
	if [ $zonestate != installed ] ; then
		gettext "error installing zone $zonename.\n"
		return 1
	fi

	if [ $NSCD_PER_LABEL = 0 ] ; then
		sharePasswd $zonename
	else
		unsharePasswd $zonename
	fi

	zoneadm -z $zonename ready
	zonestate=$(zoneadm -z $zonename list -p | cut -d : -f 3)
	if [ $zonestate != ready ] ; then
		gettext "error making zone $zonename ready.\n"
		return 1
	fi

	initialize
	zoneadm -z $zonename halt
}

delete() {
	delopt=$*

	# if there is an entry for this zone in tnzonecfg, remove it
	# before deleting the zone.

	tnzone=$(grep "^$zonename:" $TNZONECFG 2>/dev/null)
	if [ -n "${tnzone}" ] ; then
		sed -e "/^$zonename:/d" $TNZONECFG > \
		    $TXTMP/tnzonefg.$$ 2>/dev/null
		mv $TXTMP/tnzonefg.$$ $TNZONECFG
	fi

	for tnzone in $(grep ":${zonename}_unlab" $TNRHDB 2>/dev/null) ; do
		tnctl -dh "$tnzone"
		sed -e "/:${zonename}_unlab/d" $TNRHDB > \
		    $TXTMP/tnrhdb.$$ 2>/dev/null
		mv $TXTMP/tnrhdb.$$ $TNRHDB
	done

	for tnzone in $(grep "^${zonename}_unlab:" $TNRHTP 2>/dev/null) ; do
		tnctl -dt ${zonename}_unlab
		sed -e "/^${zonename}_unlab:/d" $TNRHTP > \
		    $TXTMP/tnrhtp.$$ 2>/dev/null
		mv $TXTMP/tnrhtp.$$ $TNRHTP
	done

	for tnzone in $(grep ":${zonename}_cipso" $TNRHDB 2>/dev/null) ; do
		tnctl -dh "$tnzone"
		sed -e "/:${zonename}_cipso/d" $TNRHDB > \
		    $TXTMP/tnrhdb.$$ 2>/dev/null
		mv $TXTMP/tnrhdb.$$ $TNRHDB
	done

	for tnzone in $(grep "^${zonename}_cipso:" $TNRHTP 2>/dev/null) ; do
		tnctl -dt ${zonename}_cipso
		sed -e "/^${zonename}_cipso:/d" $TNRHTP > \
		    $TXTMP/tnrhtp.$$ 2>/dev/null
		mv $TXTMP/tnrhtp.$$ $TNRHTP
	done

	zonecfg -z $zonename delete -F

	removeZoneBEs $delopt
	for snap in $(zfs list -Ho name -t snapshot|grep "\@${zonename}_snap") ; do
		zfs destroy -R $snap
	done
}

validateIPaddr () {
	OLDIFS=$IFS
	IFS=.
	integer octet_cnt=0
	integer dummy
	set -A octets $ipaddr
	IFS=$OLDIFS
	if [ ${#octets[*]} == 4 ] ; then
		while (( octet_cnt < ${#octets[*]} )); do
			dummy=${octets[octet_cnt]}
			if [ $dummy = ${octets[octet_cnt]} ] ; then
				if (( dummy >= 0 && \
				    dummy < 256 )) ; then
					octet_cnt+=1
					continue
				fi
			else
			x=$(zenity --error \
			    --title="$title" \
			    --text="$ipaddr $msg_badip")
			ipaddr=
			return
			fi
		done
	else
		x=$(zenity --error \
		    --title="$title" \
		    --text="$ipaddr $msg_badip")
		ipaddr=
	fi
}

getAllZoneNICs(){
	integer count=0
	for i in $(ifconfig -a4|grep  "^[a-z].*:")
	do
		print "$i" |grep "^[a-z].*:" >/dev/null 2>&1
		[ $? -eq 1 ] && continue
		
		i=${i%:} # Remove colon after interface name
		for j in $(ifconfig $i)
		do
			case $j in
				all-zones)
					aznics[count]=$i
					count+=1
					;;
			esac
		done
        done
}

getNetmask() {
	cidr=
	nm=$(zenity --entry \
	    --title="$title" \
	    --width=330 \
	    --text="$ipaddr: Enter netmask: " \
	    --entry-text 255.255.255.0)
	[ $? != 0 ] && return;

	cidr=$(perl -e 'use Socket; print unpack("%32b*",inet_aton($ARGV[0])), "\n";' $nm)
}

addNet() {
	getIPaddr
	if [[ -z $ipaddr ]] ; then
		return;
	fi
	getNetmask
	if [[ -z $cidr ]] ; then
		return;
	fi
	zonecfg -z $zonename "add net; \
	    set address=${ipaddr}/${cidr}; \
	    set physical=$nic; \
	    end"
	template=${zonename}_cipso
	cidr=32
	updateTnrhdb
}

getAttrs() {
	zone=global
	type=ignore
	for j in $(ifconfig $nic)
	do
		case $j in
			inet) type=$j;;
			zone) type=$j;;
			all-zones) zone=all-zones;;
			flags*) flags=$j;;
			*) case $type in
				inet) ipaddr=$j ;;
				zone) zone=$j ;;
				*) continue ;;
			   esac;
			   type=ignore;;
		esac
	done
	if [[ $flags == ~(E).UP, ]] ; then
		updown=Up
	else
		updown=Down
	fi
	if [[ $nic == ~(E).: ]] ; then
		linktype=logical
	else
		vnic=$(dladm show-vnic -po link $nic 2>/dev/null)
		if [[ -n $vnic ]] ; then
			linktype=virtual
		else
			linktype=physical
		fi
	fi
	if [ $ipaddr != 0.0.0.0 ] ; then
		x=$(grep "^${ipaddr}[^0-9]" $TNRHDB)
		if [ $? = 1 ] ; then
			template=cipso
			cidr=32
			updateTnrhdb
		else
			template=$(print "$x"|cut -d : -f2)
		fi
	else
		template="..."
		ipaddr="..."
	fi
}
deleteTnrhdbEntry() {
	remote=$(grep "^${ipaddr}[^0-9]" $TNRHDB)
	if [ $? = 0 ] ; then
		ip=$(print $remote|cut -d "/" -f1)
			if [[ $remote == ~(E)./ ]] ; then
				pr=$(print $remote|cut -d "/" -f2)
				remote="$ip\\/$pr"
			fi
		sed -e "/^${remote}/d" $TNRHDB > /tmp/tnrhdb.$$ 2>/dev/null
		mv /tmp/tnrhdb.$$ $TNRHDB
	fi
}

updateTnrhdb() {
	deleteTnrhdbEntry
	if [[ -n $cidr ]] ; then
		print "${ipaddr}/$cidr:$template" >> $TNRHDB
		tnctl -h ${ipaddr}/$cidr:$template
	else
		print "${ipaddr}:$template" >> $TNRHDB
		tnctl -h ${ipaddr}:$template
	fi
}

getIPaddr() {
        hostname=$(zenity --entry \
            --title="$title" \
	    --width=330 \
            --text="$nic: Enter Hostname: ")

        [ $? != 0 ] && return

	ipaddr=$(getent hosts $hostname|cut -f1)
        if [[ -z $ipaddr ]] ; then
		ipaddr=$(zenity --entry \
		    --title="$title" \
		    --text="$nic: Enter IP address: " \
		    --entry-text a.b.c.d)
		[ $? != 0 ] && return
		validateIPaddr
	fi

}

addHost() {
	# Update hosts
        if [[ -z $ipaddr ]] ; then
               return;
	fi
	grep "^${ipaddr}[^0-9]" /etc/inet/hosts >/dev/null
	if [ $? -eq 1 ] ; then
		print "$ipaddr\t$hostname" >> /etc/inet/hosts
	fi

	template=cipso
	cidr=32
	updateTnrhdb

	ifconfig $nic $ipaddr netmask + broadcast +
	#
	# TODO: better integration with nwam
	# TODO: get/set netmask for IP address
	#
	print $hostname > /etc/hostname.$nic
}

createInterface() {
	msg=$(ifconfig $nic addif 0.0.0.0)
	$(zenity --info \
	    --title="$title" \
	    --text="$msg" )
	nic=$(print "$msg"|cut -d" " -f5)

}
		    
createVNIC() {
	if [ $zonename != global ] ; then
		vnicname=${zonename}0
	else
		vnicname=$(zenity --entry \
		    --title="$title" \
		    --width=330 \
		    --entry-text="" \
		    --text="Enter VNIC Name: ")

		if [[ ! -n $vnicname ]] ; then
			return
		fi
	fi
	x=$(dladm show-vnic|grep "^$vnicname " )
	if [[ ! -n $x ]] ; then
		dladm create-vnic -l $nic $vnicname
	fi
	if [ $zonename = global ] ; then
		ifconfig $vnicname plumb
	else
		zonecfg -z $zonename "add net; \
		    set physical=$vnicname; \
		    end"
	fi
	nic=$vnicname
}

shareInterface() {
	#
	# TODO: better integration with nwam
	#
	ifconfig $nic all-zones;\
	if_file=/etc/hostname.$nic
	sed q | sed -e "s/$/ all-zones/" < $if_file >$TXTMP/txnetmgr.$$
	mv $TXTMP/txnetmgr.$$ $if_file
}

unshareInterface() {
	#
	# TODO: better integration with nwam
	#
	ifconfig $nic -zone;\
	if_file=/etc/hostname.$nic
	sed q | sed -e "s/all-zones/ /" < $if_file >$TXTMP/txnetmgr.$$
	mv $TXTMP/txnetmgr.$$ $if_file
}

addTnrhdb() {
	ipaddr=$(zenity --entry \
	    --title="$title" \
	    --width=330 \
	    --text="Zone:$zonename. Enter IP address of remote host or network: " \
	    --entry-text a.b.c.d)
	[ $? != 0 ] && return
	validateIPaddr
	if [[ -z $ipaddr ]] ; then
		return;
	fi
	if [ ${octets[3]} = 0 ] ; then
		nic="$ipaddr"
		getNetmask
		if [[ -z $cidr ]] ; then
			return;
		fi
	else
		cidr=32
	fi
	print "${ipaddr}/$cidr:$template" > $TXTMP/tnrhdb_new.$$
	x=$(tnchkdb -h $TXTMP/tnrhdb_new.$$ 2>$TXTMP/syntax_error.$$)
	if [ $? = 0 ] ; then
		updateTnrhdb
	else
		syntax=$(cat $TXTMP/syntax_error.$$)
		x=$(zenity --error \
		    --title="$title" \
		    --text="$syntax")
	fi
	rm $TXTMP/tnrhdb_new.$$
	rm $TXTMP/syntax_error.$$
}

removeTnrhdb() {
	while (( 1 )) do
		remotes=$(grep "^[^#][0-9.]" $TNRHDB|grep ":$template"|cut -d : -f1-2|tr : " ")
		if [ $template = cipso ] ; then
			templateHeading="from All Zones":
		else
			templateHeading="from this Zone":
		fi
		if [[ -n $remotes ]] ; then
			ipaddr=$(zenity --list \
			    --title="$title" \
			    --text="$msg_getremote" \
			    --height=250 \
			    --width=300 \
			    --column="Remove Access to:" \
			    --column="$templateHeading" \
			    $remotes)

			if [[ -n $ipaddr ]] ; then
				deleteTnrhdbEntry
				tnctl -dh ${ip}:$template
			else
				return
			fi
		else
			return
		fi
	done
}

setMLPs() {
	tnzone=$(grep "^$zonename:" $TNZONECFG 2>/dev/null)
	zoneMLPs=:$(print "$tnzone"|cut -d : -f4)
	sharedMLPs=:$(print "$tnzone"|cut -d : -f5)
	attrs="Private Interfaces$zoneMLPs\nShared Interfaces$sharedMLPs"
	ports=$(print "$attrs"|zenity --list \
	    --title="$title" \
	    --height=200 \
	    --width=450 \
	    --text="Zone: $zonename\nClick once to select, twice to edit.\nShift-click to select both rows." \
	    --column="Multilevel Ports (example: 80-81/tcp;111/udp;)" \
	    --editable \
	    --multiple
	    )

	if [[ -z $ports ]] ; then
		return
	fi

	# getopts needs another a blank and another dash
	ports=--$(print "$ports"|sed 's/ //g'|sed 's/|/ --/g'|sed 's/Interfaces:/ :/g')

	OPTIND=1
	while getopts "z:(Private)s:(Shared)" opt $ports ; do
		case $opt in
			z) zoneMLPs=$OPTARG ;;
			s) sharedMLPs=$OPTARG ;;
		esac
	done

	sed -e "/^$zonename:*/d" $TNZONECFG > $TXTMP/tnzonecfg.$$ 2>/dev/null
	tnzone=$(print "$tnzone"|cut -d : -f1-3)
	echo "${tnzone}${zoneMLPs}${sharedMLPs}" >> $TXTMP/tnzonecfg.$$

	x=$(tnchkdb -z $TXTMP/tnzonecfg.$$ 2>$TXTMP/syntax_error.$$)

	if [ $? = 0 ] ; then
		mv $TXTMP/tnzonecfg.$$ $TNZONECFG
		zenity --info \
		    --title="$title" \
		    --text="Multilevel ports for the $zonename zone\nwill be interpreted on next reboot."
		if [ $zonename != global ] ; then
			getLabelRange
		fi
	else
		syntax=$(cat $TXTMP/syntax_error.$$)
		x=$(zenity --error \
		    --title="$title" \
		    --text="$syntax")
		rm $TXTMP/tnzonecfg.$$
	fi
	rm $TXTMP/syntax_error.$$
}

enableAuthentication() {
	integer file_cnt=0

	zonepath=$(zoneadm -z $1 list -p|cut -d : -f4)
	ZONE_ETC_DIR=$zonepath/root/etc

	# If the zone's shadow file was previously read-only
	# there may be no root password entry for this zone.
	# If so, replace the root password entry with the global zone's.

	entry=$(grep ^root:: $ZONE_ETC_DIR/shadow)
	if [ $? -eq 0 ] ; then
		grep ^root: /etc/shadow > $TXTMP/shadow.$$
		sed -e "/^root::/d" $ZONE_ETC_DIR/shadow >> \
		    $TXTMP/shadow.$$ 2>/dev/null
		mv $TXTMP/shadow.$$ $ZONE_ETC_DIR/shadow
		chmod 400 $ZONE_ETC_DIR/shadow
	fi

	if [ $LOGNAME = "root" ]; then
		return
	fi

	file[0]="passwd"
	file[1]="shadow"
	file[2]="user_attr"
	#
	# Add the user who assumed the root role to each installed zone
	#
	while (( file_cnt < ${#file[*]} )); do
		exists=$(grep "^${LOGNAME}:" \
		    $ZONE_ETC_DIR/${file[file_cnt]} >/dev/null)
		if [ $? -ne 0 ] ; then
			entry=$(grep "^${LOGNAME}:" \
			    /etc/${file[file_cnt]})
			if [ $? -eq 0 ] ; then
				print "$entry" >> \
				    $ZONE_ETC_DIR/${file[file_cnt]}
			fi
		fi
		file_cnt+=1
	done
	chmod 400 $ZONE_ETC_DIR/shadow
}

unsharePasswd() {
	zonecfg -z $1 remove fs dir=/etc/passwd >/dev/null 2>&1 | grep -v such
	zonecfg -z $1 remove fs dir=/etc/shadow >/dev/null 2>&1 | grep -v such
	zoneadm -z $1 ready >/dev/null 2>&1
	if [ $? -eq 0 ] ; then
		enableAuthentication $1
		zoneadm -z $1 halt >/dev/null 2>&1
	else
		echo Skipping $1
	fi
}

sharePasswd() {
	passwd=$(zonecfg -z $1 info|grep /etc/passwd)
	if [ $? -eq 1 ] ; then
		zonecfg -z $1 "add fs; \
		    set special=/etc/passwd; \
		    set dir=/etc/passwd; \
		    set type=lofs; \
		    add options ro; \
		    end; \
		    add fs; \
		    set special=/etc/shadow; \
		    set dir=/etc/shadow; \
		    set type=lofs; \
		    add options ro; \
		    end"
	fi
	zoneadm -z $1 halt >/dev/null 2>&1
}

# This routine is a toggle -- if we find it configured for global nscd,
# change to nscd-per-label and vice-versa.
#
# The user was presented with only the choice to CHANGE the existing
# configuration.

manageNscd() {
	if [ $NSCD_PER_LABEL -eq 0 ] ; then
		# this MUST be a regular file for svc-nscd to detect
		touch $NSCD_INDICATOR
		NSCD_OPT="Unconfigure per-zone name service"
		NSCD_PER_LABEL=1
		for i in $(zoneadm list -i | grep -v global) ; do
			zoneadm -z $i halt >/dev/null 2>&1
			unsharePasswd $i
		done
	else
		rm -f $NSCD_INDICATOR
		NSCD_OPT="Configure per-zone name service"
		NSCD_PER_LABEL=0
		for i in $(zoneadm list -i | grep -v global) ; do
			zoneadm -z $i halt >/dev/null 2>&1
			sharePasswd $i
		done
	fi
}

manageZoneNets () {
	ncmds[0]="Only use all-zones interfaces"
	ncmds[1]="Add a logical interface"
	ncmds[2]="Add a virtual interface (VNIC)"

	stacks[0]="Shared Stack"
	stacks[1]="Exclusive Stack"

	getAllZoneNICs
	netOps[0]="1\n${ncmds[0]}\nShared Stack\n${aznics[*]}"

	integer nic_cnt=0
	integer netOp_cnt=2

	set -A nics $(dladm show-phys|grep -v LINK|cut -f1 -d " ")

	while (( nic_cnt < ${#nics[*]} )); do
		netOps[netOp_cnt - 1]="\n$netOp_cnt\n${ncmds[1]}\n${stacks[0]}\n${nics[nic_cnt]}"
		netOp_cnt+=1
		netOps[netOp_cnt - 1]="\n$netOp_cnt\n${ncmds[2]}\n${stacks[1]}\n${nics[nic_cnt]}"
		netOp_cnt+=1
		nic_cnt+=1
	done

	netOp=$(print "${netOps[*]}"|zenity --list \
	    --title="$title" \
	    --text="$msg_getnet $zonename zone:" \
	    --height=300 \
	    --width=500 \
	    --column="#" \
	    --column="Network Configuration " \
	    --column="IP Type" \
	    --column="Available Interfaces" \
	    --hide-column=1
	)
	
	# User picked cancel or no selection
	if [[ -z $netOp ]] ; then
		return
	fi

	# All-zones is the default, so just return
	if [ $netOp = 1 ] ; then
		return
	fi

	cmd=$(print "${netOps[$netOp - 1]}"|tr '\n' ';' |cut -d';' -f 3)
	nic=$(print "${netOps[$netOp - 1]}"|tr '\n' ';' |cut -d';' -f 5) 
	case $cmd in
	    ${ncmds[1]} )
		addNet;
		;;	
	    ${ncmds[2]} )
		zonecfg -z $zonename set ip-type=exclusive
		createVNIC
		;;
	esac
}

manageInterface () {
	while (( 1 )) do
		getAttrs

		# Clear list of commands

		share=
		setipaddr=
		newlogical=
		newvnic=
		unplumb=
		bringup=
		bringdown=

		if [ $updown = Down ] ; then
			bringup="Bring Up\n"
		else
			bringdown="Bring Down\n"
		fi

		case $linktype in
		physical )
			newlogical="Create Logical Interface...\n";
			newvnic="Create Virtual Interface (VNIC)...\n";
			;;
		logical )
			unplumb="Remove Logical Interface\n"
			;;
		virtual )
			newlogical="Create Logical Interface...\n";
			unplumb="Remove Virtual Interface\n" ;
			;;
		esac

		if [ $ipaddr = "..." ] ; then
			setipaddr="Set IP address...\n"
		elif [ $zone != all-zones ] ; then
			share="Share with Shared-IP Zones\n"
		else 
			share="Remove from Shared-IP Zones\n"
		fi

		command=$(print ""\
		    $share \
		    $setipaddr \
		    $newlogical \
		    $newvnic \
		    $unplumb \
		    $bringup \
		    $bringdown \
		    | zenity --list \
		    --title="$title" \
		    --text="Select a command from the list below:" \
		    --height=300 \
		    --column "Interface: $nic" )

		case $command in
		    " Create Logical Interface...")
			createInterface;;
		    " Create Virtual Interface (VNIC)...")
			createVNIC ;;	
		    " Set IP address...")
			getIPaddr
			addHost;;
		    " Share with Shared-IP Zones")
			shareInterface;;
		    " Remove from Shared-IP Zones")
			unshareInterface;;
		    " Remove Logical Interface")
			ifconfig $nic unplumb
			rm -f /etc/hostname.$nic
			return;;
		    " Remove Virtual Interface")
			ifconfig $nic unplumb
			dladm delete-vnic $nic
			rm -f /etc/hostname.$nic
			return;;
		    " Bring Up")
			ifconfig $nic up;;
		    " Bring Down")
			ifconfig $nic down;;
		    *) return;;
		esac
	done
}

sharePrimaryNic() {
	set -A ip $(getent hosts $(cat /etc/nodename))
	for i in $(ifconfig -au4|grep  "^[a-z].*:" |grep -v LOOPBACK)
	do
		print "$i" |grep "^[a-z].*:" >/dev/null 2>&1
		[ $? -eq 1 ] && continue
		
		nic=${i%:} # Remove colon after interface name
		getAttrs
		if [ ${ip[0]} = $ipaddr ]; then
			shareInterface
			break
		fi
	done
}

manageNets() {
	while (( 1 )) do
		attrs=
		for i in $(ifconfig -a4|grep  "^[a-z].*:" |grep -v LOOPBACK)
		do
			print "$i" |grep "^[a-z].*:" >/dev/null 2>&1
			[ $? -eq 1 ] && continue
			
			nic=${i%:} # Remove colon after interface name
			getAttrs
			attrs="$nic $linktype $zone $ipaddr $template $updown $attrs"
		done

		nic=$(zenity --list \
		    --title="$title" \
		    --text="Select an interface from the list below:" \
		    --height=300 \
		    --width=500 \
		    --column="Interface" \
		    --column="Type" \
		    --column="Zone Name" \
		    --column="IP Address" \
		    --column="Template" \
		    --column="State" \
		    $attrs)

		if [[ -z $nic ]] ; then
			return
		fi
		manageInterface
	done
}

createLDAPclient() {
	ldaptitle="$title: Create LDAP Client"
	ldapdomain=$(zenity --entry \
	    --width=400 \
	    --title="$ldaptitle" \
	    --text="Enter Domain Name: ")
	if [[ -n $ldapdomain ]] ; then
	ldapserver=$(zenity --entry \
	    --width=400 \
	    --title="$ldaptitle" \
	    --text="Enter Hostname of LDAP Server: ")
	else
		return
	fi
	if [[ -n $ldapserver ]] ; then
	ldapserveraddr=$(zenity --entry \
	    --width=400 \
	    --title="$ldaptitle" \
	    --text="Enter IP adddress of LDAP Server $ldapserver: ")
	else
		return
	fi
	ldappassword=""
	while [[ -z ${ldappassword} || "x$ldappassword" != "x$ldappasswordconfirm" ]] ; do
	    ldappassword=$(zenity --entry \
		--width=400 \
		--title="$ldaptitle" \
		--hide-text \
		--text="Enter LDAP Proxy Password:")
	    ldappasswordconfirm=$(zenity --entry \
		--width=400 \
		--title="$ldaptitle" \
		--hide-text \
		--text="Confirm LDAP Proxy Password:")
	done
	ldapprofile=$(zenity --entry \
	    --width=400 \
	    --title="$ldaptitle" \
	    --text="Enter LDAP Profile Name: ")
	whatnext=$(zenity --list \
	    --width=400 \
	    --height=250 \
	    --title="$ldaptitle" \
	    --text="Proceed to create LDAP Client?" \
	    --column=Parameter --column=Value \
	    "Domain Name" "$ldapdomain" \
	    "Hostname" "$ldapserver" \
	    "IP Address" "$ldapserveraddr" \
	    "Password" "$(print "$ldappassword" | sed 's/./*/g')" \
	    "Profile" "$ldapprofile")
	[ $? != 0 ] && return

	grep "^${ldapserveraddr}[^0-9]" /etc/hosts > /dev/null
	if [ $? -eq 1 ] ; then
		print "$ldapserveraddr $ldapserver" >> /etc/hosts
	fi

	grep "${ldapserver}:" $TNRHDB > /dev/null
	if [ $? -eq 1 ] ; then
		print "# ${ldapserver} - ldap server" \
		    >> $TNRHDB
		print "${ldapserveraddr}:cipso" \
		    >> $TNRHDB
		tnctl -h "${ldapserveraddr}:cipso"
	fi

	proxyDN=$(print $ldapdomain|awk -F"." \
	    "{ ORS = \"\" } { for (i = 1; i < NF; i++) print \"dc=\"\\\$i\",\" }{ print \"dc=\"\\\$NF }")

	zenity --info \
	    --title="$ldaptitle" \
	    --width=500 \
	    --text="global zone will be LDAP client of $ldapserver"

	ldapout=$TXTMP/ldapclient.$$

	ldapclient init -a profileName="$ldapprofile" \
	    -a domainName="$ldapdomain" \
	    -a proxyDN"=cn=proxyagent,ou=profile,$proxyDN" \
	    -a proxyPassword="$ldappassword" \
	    "$ldapserveraddr" >$ldapout 2>&1

	if [ $? -eq 0 ] ; then
	    ldapstatus=Success
	else
	    ldapstatus=Error
	fi

	zenity --text-info \
	    --width=700 \
	    --height=300 \
	    --title="$ldaptitle: $ldapstatus" \
	    --filename=$ldapout

	rm -f $ldapout


}

tearDownZones() {
	if [ $DISP -eq 0 ] ; then
		if [ $FORCE -eq 0 ] ; then
			gettext "OK to destroy all zones [y|N]? "
			read ans
			printf "%s\n" "$ans" \
			    | /usr/xpg4/bin/grep -Eq "$(locale yesexpr)"
			if [ $? -ne 0 ] ; then
				gettext "canceled.\n"
				return 1
			fi
		fi
		gettext "destroying all zones ...\n"
	else
		killall=$(zenity --question \
		    --title="$title" \
		    --width=330 \
		    --text="$msg_confirmkill")
		if [[ $? != 0 ]]; then
			return
		fi
	fi

	for p in $(zoneadm list -cp|grep -v global:) ; do
		zonename=$(echo "$p"|cut -d : -f2)
		if [ $DISP -eq 0 ] ; then
			gettext "destroying zone $zonename ...\n"
		fi
		zoneadm -z $zonename halt 1>/dev/null 2>&1
		zoneadm -z $zonename uninstall -F 1>/dev/null 2>&1
		delete -rRf
	done
	zonename=global
}

createDefaultZones() {
	# If GUI display is not used, skip the dialog
	if [ $DISP -eq 0 ] ; then
		createDefaultPublic
		if [ $? -ne 0 ] ; then
			return 1
		fi
		createDefaultInternal
		return
	fi

	msg_choose1=$(gettext "Choose one:")
	defpub=$(gettext "$PUBZONE zone only")
	defboth=$(gettext "$PUBZONE and $INTZONE zones")
	defskip=$(gettext "Main Menu...")
	command=$(echo ""\
	    "$defpub\n" \
	    "$defboth\n" \
	    "$defskip\n" \
	    | zenity --list \
	    --title="$title" \
	    --text="$msg_defzones" \
	    --column="$msg_choose1" \
	    --height=400 \
	    --width=330 )

	case $command in
	    " $defpub")
		createDefaultPublic ;;

	    " $defboth")
		createDefaultPublic
		if [ $? -ne 0 ] ; then
			return 1
		fi
		createDefaultInternal ;;

	    *)
		return;;
	esac
}

createDefaultPublic() {
	zonename=$PUBZONE
	if [ $DISP -eq 0 ] ; then
		gettext "creating default $zonename zone ...\n"
	fi
	newZone	
	zone_cnt+=1 
	hexlabel=$DEFAULTLABEL
	setTNdata
	sharePrimaryNic

	install
	if [ $? -ne 0 ] ; then
		return 1
	fi

	if [ $DISP -eq 0 ] ; then
		gettext "booting zone $zonename ...\n"
		zoneadm -z $zonename boot
	else
		zoneadm -z $zonename boot &
		gnome-terminal \
		    --disable-factory \
		    --title="Zone Console: $zonename $msg_continue" \
		    --command "zlogin -C $zonename"
	fi
}

createDefaultInternal() {
	zoneadm -z $PUBZONE halt

	zonename=snapshot
	newZone	
	zone_cnt+=1 
	zonecfg -z $zonename set autoboot=false

	clone $PUBZONE
	zoneadm -z $PUBZONE boot &

	zonename=$INTZONE
	if [ $DISP -eq 0 ] ; then
		gettext "creating default $zonename zone ...\n"
	fi
	newZone	
	zone_cnt+=1 

	hexlabel=$INTLABEL
	x=$(grep -i :{$hexlabel}: $TNZONECFG)
	if [ $? = 0 ] ; then
		z=$(print $x|cut -d : -f1)
		echo "$msg_inuse $z zone."
	else
		setTNdata
	fi

	clone snapshot
	if [ $DISP -eq 0 ] ; then
		gettext "booting zone $zonename ...\n"
	else
		gnome-terminal \
		    --title="Zone Console: $zonename" \
		    --command "zlogin -C $zonename" &
	fi
	zoneadm -z $zonename boot &
}

selectZone() {
	set -A zonelist "global\nrunning\nADMIN_HIGH"
	integer zone_cnt=1

	for p in $(zoneadm list -cp|grep -v global:) ; do
		zone_cnt+=1
	done
	if [ $zone_cnt == 1 ] ; then
		createDefaultZones
	fi
	if [ $zone_cnt == 1 ] ; then
		zonename=global
		singleZone
		return
	fi

	zone_cnt=1
	for p in $(zoneadm list -cp|grep -v global:) ; do
		zonename=$(echo "$p"|cut -d : -f2)
		state=$(echo "$p"|cut -d : -f3)
		hexlabel=$(grep "^$zonename:" $TNZONECFG|cut -d : -f2)
		if [[ $hexlabel ]] ; then
			curlabel=$(hextoalabel $hexlabel)
		else
			curlabel=...
		fi
		zonelist[zone_cnt]="\n$zonename\n$state\n$curlabel"
		zone_cnt+=1
	done
	zonename=$(print "${zonelist[*]}"|zenity --list \
	    --title="$title" \
	    --text="$msg_getzone" \
	    --height=300 \
	    --width=500 \
	    --column="Zone Name" \
	    --column="Status" \
	    --column="Sensitivity Label" \
	)

	# if the menu choice was a zonename, pop up zone menu
	if [[ -n $zonename ]] ; then
		singleZone
	else
		exit
	fi
}

# Loop for single-zone menu
singleZone() {

	while (( 1 )) do
		# Clear list of commands

		console=
		label=
		start=
		reboot=
		stop=
		clone=
		install=
		ready=
		uninstall=
		autoboot=
		delete=
		deletenet=
		permitrelabel=

		if [ $zone_cnt -gt 1 ] ; then
			killZones="Destroy all zones...\n"
			xit="Select another zone..."
		else
			killZones=
			xit="Exit"
		fi
		if [ $zonename = global ] ; then
			ldapClient="Create LDAP Client...\n"
			nscdOpt="$NSCD_OPT\n"
			createZone="Create a new zone...\n"
			addnet="Configure Network Interfaces...\n"
		else
			ldapClient=
			nscdOpt=
			createZone=
			addnet=
			killZones=
		fi

		zonestate=$(zoneadm -z $zonename list -p | cut -d : -f 3)

		consoleCheck;
		labelCheck;
		delay=0

		if [ $zonename != global ] ; then
			case $zonestate in
				running)
					ready="Ready\n"
					reboot="Reboot\n"
					stop="Halt\n"
					;;
				ready)
					start="Boot\n"
					stop="Halt\n"
					;;
				installed)
					if [[ -z $label ]] ; then
						ready="Ready\n"
						start="Boot\n"
					fi
					uninstall="Uninstall\n"
					relabelCheck
					autobootCheck
					;;
				configured) 
					install="Install...\n"
					cloneCheck
					delete="Delete\n"
					console=
					;;
				incomplete)
					uninstall="Uninstall\n"
					;;
				*)
				;;
			esac
		fi

		command=$(echo ""\
		    $createZone \
		    $console \
		    $label \
		    $start \
		    $reboot \
		    $stop \
		    $clone \
		    $install \
		    $ready \
		    $uninstall \
		    $delete \
		    $addnet \
		    $deletenet \
		    $addremotehost \
		    $addcipsohost \
		    $removeremotehost \
		    $removecipsohost \
		    $setmlps \
		    $permitrelabel \
		    $autoboot \
		    $ldapClient \
		    $nscdOpt \
		    $killZones \
		    $xit \
		    | zenity --list \
		    --title="$title" \
		    --text="$msg_getcmd" \
		    --height=400 \
		    --width=330 \
		    --column "Zone: $zonename   Status: $zonestate" )

		case $command in
		    " Create a new zone...")
			zonename=
			newZone ;;

		    " Zone Console...")
			delay=2
			gnome-terminal \
			    --title="Zone Console: $zonename" \
			    --command "zlogin -C $zonename" & ;;

		    " Select Label...")
			selectLabel;;

		    " Ready")
			zoneadm -z $zonename ready ;;

		    " Boot")
			zoneadm -z $zonename boot ;;

		    " Halt")
			zoneadm -z $zonename halt ;;

		    " Reboot")
			zoneadm -z $zonename reboot ;;

		    " Install...")
			install;;

		    " Clone...")
			clone ;;

		    " Uninstall")
			zoneadm -z $zonename uninstall -F;;

		    " Delete")
			delete
			return ;;

		    " Configure Network Interfaces...")
			if [ $zonename = global ] ; then
				manageNets
			else
				manageZoneNets
			fi;;	

		    " Add Single-level Access to Remote Host...")
			addTnrhdb ;;

		    " Add Multilevel Access to Remote Host...")
			template=cipso
			addTnrhdb ;;

		    " Remove Single-level Access to Remote Host...")
			removeTnrhdb ;;

		    " Remove Multilevel Access to Remote Host...")
			template=cipso
			removeTnrhdb ;;

		    " Configure Multilevel Ports...")
			setMLPs;;

		    " Permit Relabeling")
			zonecfg -z $zonename set limitpriv=default,\
win_mac_read,win_mac_write,win_selection,win_dac_read,win_dac_write,\
file_downgrade_sl,file_upgrade_sl,sys_trans_label ;;

		    " Deny Relabeling")
			zonecfg -z $zonename set limitpriv=default ;;

		    " Set Automatic Booting")
			zonecfg -z $zonename set autoboot=true ;;

		    " Set Manual Booting")
			zonecfg -z $zonename set autoboot=false ;;

		    " Create LDAP Client...")
			createLDAPclient ;;

		    " Configure per-zone name service")
			manageNscd ;;

		    " Unconfigure per-zone name service")
			manageNscd ;;

		    " Destroy all zones...")
			tearDownZones
			return ;;

		    *)
			if [ $zone_cnt == 1 ] ; then
				exit
			else
				return
			fi;;
		esac
		sleep $delay;
	done
}

# Main loop for top-level window
#

/usr/bin/plabel $$ 1>/dev/null 2>&1
if [ $? != 0 ] ; then
	gettext "$0 : Trusted Extensions must be enabled.\n"
	exit 1
fi

myzone=$(/sbin/zonename)
if [ $myzone != "global" ] ; then
	gettext "$0 : must be in global zone to run.\n"
	exit 1
fi


process_options "$@" || exit

mkdir $TXTMP 2>/dev/null
deflabel=$(chk_encodings -a|grep "Default User Sensitivity"|\
   sed 's/= /=/'|sed 's/"/'''/g|cut -d"=" -f2)
DEFAULTLABEL=$(atohexlabel ${deflabel})
intlabel=$(chk_encodings -a|grep "Default User Clearance"|\
   sed 's/= /=/'|sed 's/"/'''/g|cut -d"=" -f2)
INTLABEL=$(atohexlabel -c "${intlabel}")

# are there any zfs pools?
ZDSET=none
zpool iostat 1>/dev/null 2>&1
if [ $? = 0 ] ; then
	# is there a zfs pool named "zone"?
	zpool list -H zone 1>/dev/null 2>&1
	if [ $? = 0 ] ; then
		# yes
		ZDSET=zone
	else
		# no, but is there a root pool?
		rootfs=$(df -n / | awk '{print $3}')
		if [ $rootfs = "zfs" ] ; then
			# yes, use it
			ZDSET=$(zfs list -Ho name / | cut -d/ -f 1)/zones
			zfs list -H $ZDSET 1>/dev/null 2>&1
			if [ $? = 1 ] ; then
				createZDSET "-o mountpoint=/zone" $ZDSET
			fi
		fi
	fi
fi

if [ $DISP -eq 0 ] ; then
	gettext "non-interactive mode ...\n"

	if [ $DESTROYZONES -eq 1 ] ; then
		tearDownZones
	fi

	if [ $CREATEDEF -eq 1 ] ; then
		if [[ $(zoneadm list -c) == global ]] ; then
			createDefaultZones
		else
			gettext "cannot create default zones because there are existing zones.\n"
		fi
	fi

	exit
fi

if [ $NSCD_PER_LABEL -eq 0 ] ; then
	NSCD_OPT="Configure per-zone name service"
else
	NSCD_OPT="Unconfigure per-zone name service"
fi


while (( 1 )) do
	selectZone
done