#!/sbin/sh -
# $Id: vxadm_lib.sh,v 1.27.65.24.2.3 2003/03/24 02:28:10 pgondi Exp $
#ident "$Source: /project/unixvm-cvs/src/sol/cmd/vxvm/voladm/vxadm_lib.sh,v $"

#
# $Copyrights: Copyright (c) 1990 - 2004 VERITAS Software Corporation.
# All rights reserved.
# VERITAS, the VERITAS Logo and all other VERITAS product names and
# slogans are trademarks or registered trademarks of VERITAS Software
# Corporation. VERITAS and the VERITAS Logo Reg. U.S. Pat. & Tm. Off.
# Other product names and/or slogans mentioned herein may be trademarks or
# registered trademarks of their respective companies.
#
# UNPUBLISHED - RIGHTS RESERVED UNDER THE COPYRIGHT LAWS OF THE UNITED
# STATES.  USE OF A COPYRIGHT NOTICE IS PRECAUTIONARY ONLY AND DOES NOT
# IMPLY PUBLICATION OR DISCLOSURE.
#
# THIS SOFTWARE CONTAINS CONFIDENTIAL INFORMATION AND TRADE SECRETS OF
# VERITAS SOFTWARE.  USE, DISCLOSURE OR REPRODUCTION IS PROHIBITED WITHOUT
# THE PRIOR EXPRESS WRITTEN PERMISSION OF VERITAS SOFTWARE.
#
# The Licensed Software and Documentation are deemed to be "commercial
# computer software" and "commercial computer software documentation" as
# defined in FAR Sections 12.212 and DFARS Section 227.7202.  $
#


: ${VOLROOT_DIR:=$__VXVM_ROOT_DIR}
: ${VOL_SCRIPTS_DIR:=$VOLROOT_DIR/usr/lib/vxvm/bin}
: ${VOL_SCRIPTS_LIB:=$VOLROOT_DIR/usr/lib/vxvm/lib}
: ${VOLADM_ROOT:=$VOLROOT_DIR/usr/lib/vxvm/voladm.d}
: ${VOLADM_BIN=$VOLADM_ROOT/bin}
: ${VOLADM_LIB=$VOLADM_ROOT/lib}
: ${VOLADM_HELP=$VOLADM_ROOT/help}
: ${VOL_CONFIG_DIR:=$VOLROOT_DIR/etc/vx}
: ${VOL_LOCK_DIR:=$VROOT_DIR/var/spool/locks}
: ${VOL_TYPE_DIR:=$VROOT_DIR/usr/lib/vxvm/type}

SYSROOT=$__VXVM_SYSTEM_ROOT_DIR

export VOL_SCRIPTS_DIR
export VOLADM_ROOT
export VOLADM_BIN
export VOLADM_LIB
export VOLADM_HELP
export VOL_CONFIG_DIR

CNTRL_EXCLUDE_FILE=${VOL_CONFIG_DIR}/cntrls.exclude
DISK_EXCLUDE_FILE=${VOL_CONFIG_DIR}/disks.exclude
ENCLR_EXCLUDE_FILE=${VOL_CONFIG_DIR}/enclr.exclude

SYSDIRS=
[ -n "$VOLROOT_DIR" ] && {
	SYSDIRS=$VOLROOT_DIR/usr/sbin:$VOLROOT_DIR/sbin:
}
SYSDIRS=$SYSDIRS/usr/sbin:/sbin:/usr/bin:/usr/ucb
: ${__VXADM_NEED_PATH:=$VOL_SCRIPTS_DIR:$VOLADM_BIN:$SYSDIRS}
case $PATH in
$__VXADM_NEED_PATH|$__VXADM_NEED_PATH:*) :;;
*)	PATH=$__VXADM_NEED_PATH:$PATH;;
esac
export PATH

voladm_menu_stack=
cleanup_list=cleanup_tempfiles
newline='
'

v_opt=
verbose=
if [ "X$1" = X-v ]
then
	verbose=yes
	v_opt=-v
	shift
fi

tmpfile1=${TMPDIR:-/tmp}/vx1.$$
tmpfile2=${TMPDIR:-/tmp}/vx2.$$
tmpfile3=${TMPDIR:-/tmp}/vx3.$$
tmpfile4=${TMPDIR:-/tmp}/vx4.$$
_vd_tmpfile=${TMPDIR:-/tmp}/vx5.$$
_cef_tmpfile=${TMPDIR:-/tmp}/vx6.$$
_vdskd_rawmatch=${TMPDIR:-/tmp}/vx7.$$
_vdskd_cntrlmatch=${TMPDIR:-/tmp}/vx8.$$
_vdskd_diskmatch=${TMPDIR:-/tmp}/vx9.$$
_vdskd_enclrmatch=${TMPDIR:-/tmp}/vx10.$$

cleanup_tempfiles()
{
	rm -f $tmpfile1 $tmpfile2 $tmpfile3 $tmpfile4 \
	$_vd_tmpfile $_cef_tmpfile \
	$_vdskd_rawmatch $_vdskd_cntrlmatch $_vdskd_diskmatch \
	$_vdskd_enclrmatch
}

quit()
{
	trap "" INT HUP QUIT TERM
	for f in $cleanup_list
	do
		"$f"
	done
	exit $1
}

trap "quit 100" INT HUP QUIT TERM

exec 4<&0 5>&2

# doit - execute a command, printing the command in verbose mode
doit()
{
	[ "$verbose" ] && echo ! "$@" >&5
	"$@"
}

writemsg()
{
	echo "";
	for _wm_line in "$@"
	do
		echo "  $_wm_line"
	done
}

#
# usage: ewritemsg \
#	 [-a] [-M catalog_id] [-f file] \
#	 default_message [shell_parms]
#
# -a: append the list to 'file' instead of overwriting. This
#     flag only has affect when -f is also used.
# -M catalog_id: specify catalog id
# -f file: write the list to 'file' and display the 'file' 
# 
# NOTE: egettxt allows the output without an extra newline
# 
ewritemsg()
{
	_ewm_append=no
	_ewm_cat=
	_ewm_file=

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "aM:f:" c
	do
		case $c in
		a) _ewm_append=yes;;
		M) _ewm_cat=$OPTARG;;
		f) _ewm_file="$OPTARG";;
		\?) egettxt "ewritemsg: bad argument list" vxvmshm:1440
		    return;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ -n "$_ewm_cat" ]
	then
		_ewm_msg="$1"
		shift 1
		_ewm_msg="`egettxt \"$_ewm_msg\" \"$_ewm_cat\" \"$@\"`"
	else
		_ewm_msg="$*"
	fi

	if [ -z "$_ewm_file" ]
	then
		writemsg "$_ewm_msg"
	else
		if [ "$_ewm_append" = "no" ]
		then
			> $_ewm_file
		fi

		# Save stdout and redirect stdout to $_ewm_file.
		exec 9>&0 >> $_ewm_file
		writemsg "$_ewm_msg"
		# Restore stdout and close $_ewm_file.
		exec >&9 9>&-
	fi
}

read_input()
{
	echo ""
	_once=
	if [ "X$1" = X-m ]
	then
		_once=yes
		shift
	fi
	_prompt="$1 "
	[ -z "$2" ] || _prompt="${_prompt}[$2,q,?] "
	[ -z "$3" ] || _prompt="${_prompt}(default: $3) "
	case $_prompt in
????????????????????????????????????????????????????????????????????*)
		if [ ! -z "$2" ] || [ ! -z "$3" ]
		then
			_prompt="$1$newline"
			[ -z "$2" ] || _prompt="${_prompt}[$2,q,?] "
			[ -z "$3" ] || _prompt="${_prompt}(default: $3) "
		fi
		;;
	esac
	while true
	do
		echo "$_prompt\c"
		read input <&4
		case $input in
		"")	input=$3; return 0;;
		"!")	${SHELL:-sh} <&4
			echo !
			[ ! -z "$_once" ] && return 1;;
		"!"*)	${SHELL:-sh} -c "`expr "$input" : '!\(.*\)'`" <&4
			echo !
			[ ! -z "$_once" ] && return 1;;
		'?')	voladm_help; [ ! -z "$_once" ] && return 1;;
		'??')	voladm_help_help; [ ! -z "$_once" ] && return 1;;
		q|quit)	quit 101;;
		x)	quit 100;;
		*)	return 0;;
		esac
	done
}

pop_list()
{
	_list=$1
	eval "set -- \$$_list"
	shift
	eval "$_list=\$*"
}

first_item()
{
	echo $1
}

last_item()
{
	_list=$1
	eval "set -- \$$_list"
	eval "echo \${$#}"
}

list_item()
{
	_item=$1
	shift
	eval "echo \${$_item}"
}


list_count()
{
	echo $#
}

push_list()
{
	_list=$1
	shift
	eval "set -- \$* \$$_list"
	eval "$_list=\$*"
}

append_list()
{
	_list=$1
	shift
	eval "set -- \$$_list \$*"
	eval "$_list=\$*"
}

list_member()
{
	_want=$1
	shift
	for i in $@
	do
		[ "X$_want" = "X$i" ] && return 0
	done
	return 1
}

#
# Set 'out_list' to be the 'elem_num' element of every 'num_elem_in_group'
# elements in the list 'in_list'.
#
# NOTE: The numbering for 'elem_num' starts from 1.
#
# usage: get_list_group num_elem_in_group elem_num in_list out_list
#
get_list_group()
{
	if [ $# -lt 4 ]
	then
		egettxt "get_list_group: bad argument list" vxvmshm:1442
		return
	fi

	_glg_num_elem_in_group=$1
	_glg_elem_num=$2
	_glg_in_list=$3
	_glg_out_list=$4

	if [ $_glg_num_elem_in_group -lt $_glg_elem_num ]
	then
		egettxt "get_list_group: num_elem_in_group not > than elem_num" vxvmshm:1443
		return
	fi

	if [ $_glg_num_elem_in_group -eq 0 -o $_glg_elem_num -eq 0 ]
	then
		egettxt "get_list_group: num_elem_in_group or elem_num are 0" vxvmshm:1444
		return
	fi

	eval $_glg_out_list=

	set -- `eval echo "\\$$_glg_in_list"`
	while [ $# -gt 0 ]
	do
		eval $_glg_out_list=\`eval \
		\"echo \${$_glg_out_list} \${$_glg_elem_num}\"\`
		shift $_glg_num_elem_in_group
	done
}

#
# Remove every 'elem_num' element from every 'num_elem_in_group' in 'list'.
#
# NOTE: The numbering for 'elem_num' starts from 1.
#
# usage: change_list_group num_elem_in_group elem_num list
#
remove_list_group()
{
	if [ $# -lt 3 ]
	then
		egettxt "remove_list_group: bad argument list" vxvmshm:1446
		return
	fi

	_rlg_num_elem_in_group=$1
	_rlg_elem_num=$2
	_rlg_list=$3

	if [ $_rlg_num_elem_in_group -lt $_rlg_elem_num ]
	then
		egettxt "remove_list_group: num_elem_in_group not > than elem_num" vxvmshm:1447
		return
	fi

	if [ $_rlg_num_elem_in_group -eq 0 -o $_rlg_elem_num -eq 0 ]
	then
		egettxt "remove_list_group: num_elem_in_group or elem_num are 0" vxvmshm:1448
		return
	fi

	set -- `eval echo "\\$$_rlg_list"`
	eval $_rlg_list=
	while [ $# -gt 0 ]
	do
		i=1
		while [ $i -le $_rlg_num_elem_in_group ]
		do
			if [ $i -ne $_rlg_elem_num ]
			then
				eval $_rlg_list=\"\$$_rlg_list $1\"
			fi
			inc i
			shift 1
		done
	done
}


#
# list_explode [-t fieldsep] listname var1 var2 ...
#
# Explode a list and store elements into the named variables.  If
# some variables could not be filled (because the named list didn't
# have enough members) return a non-zero status.
#
list_explode()
{
	_le_save=$IFS
	_le_ifs=$IFS
	[ "X$1" = X-t ] && {
		_le_ifs=$2
		shift 2
	}
	_le_list=$1
	shift
	_le_vars="$*"
	IFS="$_le_ifs"
	eval "set \$$_le_list"
	IFS="$_le_save"
	for _le_var in $_le_vars
	do
		[ $# -eq 0 ] && {
			return 1
		}
		eval "$_le_var=\$1"
		shift
	done
	return 0
}

not()
{
	"$@"
	[ $? -eq 0 ] && return 1
	return 0
}

add_cleanup()
{
	push_list cleanup_list $*
}

voladm_menu_push()
{
        if [ "$1" = "-M" ]
        then
                _mnu_cat="$2"
                _mnu_def="$3"
                shift 3
                _mnu_cur="`egettxt \"$_mnu_def\" \"$_mnu_cat\" \"$@\"`"
        else
                _mnu_cur="$*"
        fi

	if [ -z "$VOLADM_CURRENT_MENU" ]
	then
		VOLADM_CURRENT_MENU=$_mnu_cur
	elif [ ! -z "$_mnu_cur" ] 
	then
		VOLADM_CURRENT_MENU=$VOLADM_CURRENT_MENU/$_mnu_cur
	fi
	export VOLADM_CURRENT_MENU
	push_list voladm_menu_stack $VOLADM_CURRENT_MENU
}

voladm_menu_pop()
{
	nitems=`list_count $voladm_menu_stack`
	[ "$nitems" -gt 1 ] && pop_list voladm_menu_stack
	VOLADM_CURRENT_MENU=`first_item $voladm_menu_stack`
	export VOLADM_CURRENT_MENU
}

voladm_menu_set()
{
        if [ "$1" = "-M" ]
        then
                _mnu_cat="$2"
                _mnu_def="$3"
                shift 3
                _mnu_cur="`egettxt \"$_mnu_def\" \"$_mnu_cat\" \"$@\"`"
        else
                _mnu_cur="$*"
        fi

	voladm_menu_pop
	voladm_menu_push $_mnu_cur
}

voladm_help_push()
{
	VOLADM_CURRENT_HELP=$1
	export VOLADM_CURRENT_HELP
	voladm_help_stack="$VOLADM_CURRENT_HELP $voladm_help_stack"
}

voladm_help_pop()
{
	VOLADM_CURRENT_HELP=`first_item $voladm_help_stack`
	export VOLADM_CURRENT_HELP
	pop_list voladm_help_stack
}

voladm_help_set()
{
	voladm_help_pop
	voladm_help_push $1
}

voladm_help_help()
{
	voladm_help vxadm.info
}

tput_valid()
{
	[ -x /usr/bin/tput ] && [ ! -z "$TERM" ]
}

voladm_help()
{
	help=${1:-$VOLADM_CURRENT_HELP}
	_vx_menu="`egettxt 'Menu:' vxvmshm:883`"

	# When running in L10N environment, setup
	# the appropiate language directory
	HELP_LANG_DIR=
	LC_MESSAGES=`locale | grep LC_MESSAGES | sed s/LC_MESSAGES=\"// | sed s/\"//`
        if [ -f $VOLADM_HELP/$LC_MESSAGES/$help ]
        then
                HELP_LANG_DIR=$LC_MESSAGES
        fi

	tput_valid && tput clear
	( echo "$title\n$_vx_menu $VOLADM_CURRENT_MENU\n"
	  grep -v "^#" $VOLADM_HELP/$HELP_LANG_DIR/$help; echo "" ) | voladm_display
}

#
# display a file, using a pager, if needed
#
# usage: voladm_display [-acn] [-f out_file] [in_file]
#
# -a: append the list to 'out_file' instead of overwriting. This
#     flag is only meaningful when -f is used.
# -c: call voladm_continue called after the display is finished if the
#     pager was not used
# -f out_file: write the list to 'out_file' and display 'out_file' 
# -n: add new line after file
#
# If 'in_file' is not specified, read from standard input.
#
voladm_display()
{
	_vd_out_file=
	_vd_append=no
	_vd_pause=no
	_vd_nflag=no

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "acnf:" c
	do
		case $c in
		a) _vd_append=yes;;
		c) _vd_pause=yes;;
		n) _vd_nflag=yes;;
		f) _vd_out_file="$OPTARG";;
		\?) egettxt "voladm_display: bad argument list" vxvmshm:1452
		    return;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ -z "$_vd_out_file" ]
	then
		_vd_out_file=$_vd_tmpfile
		cat "$@" > $_vd_out_file
		if [ $_vd_nflag = "yes" ]
		then
			echo >> $_vd_out_file
		fi
	else
		if [ "$_vd_append" = "no" ]
		then
			cat "$@" > $_vd_out_file
		else
			cat "$@" >> $_vd_out_file
		fi
		if [ $_vd_nflag = "yes" ]
		then
			echo >> $_vd_out_file
		fi
	fi

	tput_valid && _vd_lines=`tput lines`
	[ -z "$_vd_lines" ] && _vd_lines=24
	if [ "`wc -l < $_vd_out_file`" -ge $_vd_lines ]
	then
		${PAGER:-more} $_vd_out_file <&4
	else
		cat $_vd_out_file
		if [ "$_vd_pause" = "yes" ]
		then
			voladm_continue
		fi
	fi
}

#
# Send a list to the fmt command and then display the output with a
# pager, if needed. If the number of elements in a group is greater
# than one, then by default (unless '-e elem_num' is used) all elements
# in the list surrounded by brackets will be displayed.
#
# usage: voladm_list_display \
#	[-abcn] [-f file] \
#	[-g num_elem_in_group] [-d elem_num] \
#	list...
# -a: append the list to 'file' instead of overwriting. This
#     flag only has affect when -f is also used.
# -b: put brackets around elements in the list. if there is more than
#     one element to be displayed separate the elements with forward
#     slashes '/'
# -c: call voladm_continue called after the display is finished if the
#     pager was not used
# -f file: write the list to 'file' and display the 'file' 
# -g num_elem_in_group: specify the number of elements in a group (default: 1)
# -d elem_num: specify the group element to display (default: 1)
# -n: add new line after list
#
voladm_list_display()
{
	_vld_append=no
	_vld_pause=no
	_vld_file=
	_vld_num_elem_in_group=1
	_vld_elem_num=1
	_vld_dflag=no
	_vld_use_bracket=no 
	_vld_nflag=no

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "abcf:g:d:n" c
	do
		case $c in
		a) _vld_append=yes;;
		b) _vld_use_bracket=yes;;
		c) _vld_pause=yes ;;
		f) _vld_file="$OPTARG";;
		g) _vld_num_elem_in_group="$OPTARG";;
		d) _vld_dflag=yes; _vld_elem_num="$OPTARG";;
		n) _vld_nflag=yes;;
		\?) egettxt "voladm_list_display: bad argument list" vxvmshm:1455
		    return;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ $_vld_num_elem_in_group -eq 0 ]
	then
		egettxt "voladm_list_display: num_elem_in_group is 0" vxvmshm:1457
		return
	fi

	if [ $_vld_dflag = "yes" -a $_vld_elem_num != "all" -a \
	     $_vld_elem_num -eq 0 ]
	then
		egettxt "voladm_list_display: num_elem is 0" vxvmshm:1456
		return
	fi

	# If all is specified, then use the default handling.
	if [ $_vld_dflag = "yes" -a $_vld_elem_num = "all" ]
	then
		_vld_dflag=no
	fi

	if [ -z "$_vld_file" ]
	then
		_vld_file=$_vd_tmpfile
		> $_vld_file
	else
		if [ "$_vld_append" = "no" ]
		then
			> $_vld_file
		fi
	fi

	echo >> $_vld_file
	while [ $# -gt 0 ]
	do
		# If '-d elem_num' was specified then display only the
		# element that was selected.
		if [ $_vld_dflag = "yes" ]
		then
			if [ $_vld_use_bracket = "yes" ]
			then
				eval "echo \"  [\${$_vld_elem_num}]\""
			else
				eval "echo \"  \${$_vld_elem_num}\""
			fi
			shift $_vld_num_elem_in_group
		else
			if [ $_vld_use_bracket = "yes" ]
			then
				echo "  [\c"
			fi
			i=$_vld_num_elem_in_group
			_vld_first=yes
			while [ $i -gt 0 ]
			do
				if [ $_vld_use_bracket = "yes" ]
				then
					if [ $_vld_first = "yes" ]
					then
						echo "$1\c"
						_vld_first=no
					else
						echo ",$1\c"
					fi
				else
					echo "  $1"
				fi
				dec i
				shift 1
			done
			if [ $_vld_use_bracket = "yes" ]
			then
				echo "]"
			fi
		fi
	done | fmt >> $_vld_file
	if [ $_vld_nflag = "yes" ]
	then
		echo >> $_vld_file
	fi
	tput_valid && _vld_lines=`tput lines`
	[ -z "$_vld_lines" ] && _vld_lines=24
	if [ "`wc -l < $_vld_file`" -ge $_vld_lines ]
	then
		${PAGER:-more} $_vld_file <&4
	else
		cat $_vld_file
		if [ "$_vld_pause" = "yes" ]
		then
			voladm_continue
		fi
	fi
}

voladm_call()
{
	_util=$1
	shift

	doit "$_util" $v_opt "$@" <&4
	status=$?
	if [ $status -eq 100 ] || [ $status -eq 101 ]
	then
		quit $status
	fi
	return $status
}

voladm_menu_call()
{
	_util=$1
	shift

	doit "$_util" $v_opt "$@" <&4
	status=$?
	if [ $status -eq 100 ]
	then
		quit 100
	fi
	return $status
}

voladm_begin_screen()
{
	if [ "$1" = "-M" ]
	then
		_vbs_cat="$2"
		_vbs_def="$3"
		shift 3
		_vbs_msg="`egettxt \"$_vbs_def\" \"$_vbs_cat\" \"$@\"`"
	else
		_vbs_msg="$1"
	fi
	tput_valid && tput clear
	_vx_menu="`egettxt 'Menu:' vxvmshm:883`"
	echo "\n$_vbs_msg\n$_vx_menu $VOLADM_CURRENT_MENU"
}

voladm_menu()
{
	_menu_h1="`egettxt \"Display help about menu\" vxvmshm:159`"
	_menu_h2="`egettxt \"Display help about the menuing system\" \
			vxvmshm:160`"
	_menu_h3="`egettxt \"Exit from menus\"  vxvmshm:190`"
	_menu_h4="`egettxt \"Select an operation to perform\"  vxvmshm:297`"
	_menu_h5="`egettxt \"default\"  vxvmshm:540`"

	read _menu_title
	_menu_default=
	_vx_menu="`egettxt 'Menu:' vxvmshm:883`"
	_menu="$_menu_title\n$_vx_menu $VOLADM_CURRENT_MENU\n"
	_menu2=
	_menu_select='case $input in'
	cur_linenum=6
	tput_valid && lines_per_page=`tput lines`
	[ -z "$lines_per_page" ] && lines_per_page=24
	while read _menu_key _menu_item _menu_cat _menu_text
	do
		if [ -z "$_menu_key" ]
		then
			_menu="$_menu\n"
			_menu2="$_menu2\n"
		elif [ "X$_menu_item" = Xdefault ]
		then
			_menu_default=$_menu_key
		else
			_menu_select="$_menu_select '$_menu_key')VOLADM_MENU_SELECT=$_menu_item;break 2;;"
			if [ ! -z "$_menu_cat" ]
			then
				cur_linenum=`expr $cur_linenum + 1`
				_menu_ctext="`egettxt \"$_menu_text\" \"$_menu_cat\"`"
				if [ $cur_linenum -lt $lines_per_page ]; then
					_menu="$_menu\n $_menu_key\t$_menu_ctext"
				else
					_menu2="$_menu2\n $_menu_key\t$_menu_ctext"
				fi
			fi
		fi
	done
	_menu_select="$_menu_select *) :;; esac"
	cur_linenum=`expr $cur_linenum + 1`
	if [ $cur_linenum -lt $lines_per_page ]; then
		_menu="$_menu\n ?\t$_menu_h1"
	else
		_menu2="$_menu2\n ?\t$_menu_h1"
	fi
	cur_linenum=`expr $cur_linenum + 1`
	if [ $cur_linenum -lt $lines_per_page ]; then
		_menu="$_menu\n ??\t$_menu_h2"
	else
		_menu2="$_menu2\n ??\t$_menu_h2"
	fi
	cur_linenum=`expr $cur_linenum + 1`
	if [ $cur_linenum -lt $lines_per_page ]; then
		_menu="\n$_menu\n q\t$_menu_h3"
	else
		_menu2="\n$_menu2\n q\t$_menu_h3"
	fi

	_menu_prompt="${1:-$_menu_h4:}"
	if [ ! -z "$_menu_default" ]
	then
		_menu_prompt="$_menu_prompt [$_menu_h5: $_menu_default]"
	fi

	while true
	do
		tput_valid && tput clear
		echo "$_menu"
		if [ $cur_linenum -ge $lines_per_page ]; then
			voladm_continue
			tput_valid && tput clear
			echo "$_menu2"
		fi
		while true
		do
			read_input -m "$_menu_prompt" "" $_menu_default
			if [ $? -ne 0 ]
			then
				voladm_continue
				continue 2
			fi
			eval "$_menu_select"

			case $input in
			x)	quit 100;;
			q|quit)	quit 101;;
			'?')	voladm_help; continue 2;;
			h)	voladm_help; continue 2;;
			help)	voladm_help; continue 2;;
			'??')	voladm_help_help; continue 2;;
			esac
			ewritemsg -M vxvmshm:302 "Selection not recognized, enter ?? for help"
		done
	done

	echo ""
}

# voladm_yorn question default
voladm_yorn()
{
	if [ "$1" = "-M" ]
	then
		_vadm_cat="$2"
		_vadm_def="$3"
		_vadm_yon="$4"
		shift 4
		_vadm_msg="`egettxt \"$_vadm_def\" \"$_vadm_cat\" \"$@\"`"
	else
		_vadm_msg="$1"
		_vadm_yon="$2"
	fi
	while true
	do
		read_input "$_vadm_msg" "y,n" $_vadm_yon
		case $input in
		y|yes)	return 0;;
		n|no)	return 1;;
		*)	ewritemsg -M vxvmshm:788 \
			"Please respond with \\\"y\\\" or \\\"n\\\""
			continue;;
		esac
	done
}

#
# Ask "yes" or "no" for an entire list. Each element of the list may be
# reviewed separately or the same answer may be given for the entire list.
# Separate prompts and defaults are specified for the list and for elements
# of the list.
#
#
# usage: voladm_yorn_batch \
#	[-bh] [-f file] [-M list_catalog_id] [-m elem_catalog_id] \
#	[-g num_elem_in_group] [-p elem_num] [-d elem_num] \
#	list_prompt list_yon \
#	elem_prompt elem_yon \
#	list yes_list no_list [shell_parms]
#
# -b: add brackets around list items
# -h: push and pop voladm_help menus
# -f file: append the question output to 'file' and display 'file'
# -M list_catalog_id: specify list catalog id
# -m elem_catalog_id: specify element catalog id
# -g num_elem_in_group: specify the number of elements in a group (default: 1)
# -p elem_num: specify the group element to prompt (default: 1)
# -d elem_num: specify the group element to display.
# list_prompt: specify list prompt string
# list_yon: specify default list answer
# elem_prompt: specify element prompt string
# list_yon: specify default element answer
# list: list of elements to ask questions about (input)
# yes_list: elements with yes answers (output)
# no_list: elements with no answers (output)
#
# If -d 'elem_num' is not used or if "all" is specified, then all elements
# will displayed.
#
voladm_yorn_batch()
{
	_vadm_use_bracket=no
	_vadm_help=no
	_vadm_file=
	_vadm_list_cat=
	_vadm_elem_cat=
	_vadm_num_elem_in_group=1
	_vadm_prompt_num=1
	_vadm_dflag=no
	_vadm_disp_num=1

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "bhf:M:m:g:p:d:" c
	do
		case $c in
		b) _vadm_use_bracket=yes;;
		h) _vadm_help=yes;;
		f) _vadm_file="$OPTARG";;
		M) _vadm_list_cat="$OPTARG";;
		m) _vadm_elem_cat="$OPTARG";;
		g) _vadm_num_elem_in_group="$OPTARG";;
		p) _vadm_prompt_num="$OPTARG";;
		d) _vadm_dflag=yes; _vadm_disp_num="$OPTARG";;
		\?) egettxt "voladm_yorn_batch: bad argument list" vxvmshm:1460
		    return ;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ $# -lt 7 ]
	then
		egettxt "voladm_yorn_batch: bad argument list" vxvmshm:1460
		return
	fi

	_vadm_list_msg="$1"
	_vadm_list_yon="$2"
	_vadm_elem_msg="$3"
	_vadm_elem_yon="$4"
	_vadm_select_list="$5"
	_vadm_yes_list="$6"
	_vadm_no_list="$7"
	shift 7

	if [ $_vadm_num_elem_in_group -eq 0 -o $_vadm_prompt_num -eq 0 ]
	then
		egettxt "voladm_yorn_batch: -g or -p arguments can not be 0" vxvmshm:1459
		return
	fi

	if [ $_vadm_dflag = "yes" -a $_vadm_disp_num != "all" -a \
	     $_vadm_disp_num -eq 0 ]
	then
		egettxt "voladm_yorn_batch: -d argument can not be zero." vxvmshm:1458
		return
	fi

	eval $_vadm_yes_list=
	eval $_vadm_no_list=

	# If a catalog entry was specified for the list message, get it.
	if [ -n "$_vadm_list_cat" ]
	then
		_vadm_list_msg="`\
			egettxt \"$_vadm_list_msg\" \"$_vadm_list_cat\" \"$@\"`"
	fi

	# If a catalog entry was specified for the element message, get it.
	if [ -n "$_vadm_elem_cat" ]
	then
		_vadm_elem_msg="`\
			egettxt \"$_vadm_elem_msg\" \"$_vadm_elem_cat\" \"$@\"`"
	fi

	_vadm_vld_darg=
	if [ $_vadm_dflag = "yes" ]
	then
		_vadm_vld_darg="-d $_vadm_disp_num"
	fi

	_vadm_vld_barg=
	if [ $_vadm_use_bracket = "yes" ]
	then
		_vadm_vld_barg="-b"
	fi

	if [ -z "$_vadm_file" ]
	then
		voladm_list_display \
		-g $_vadm_num_elem_in_group $_vadm_vld_darg \
		$_vadm_vld_barg `eval "echo \\$$_vadm_select_list"`
	else
		voladm_list_display -a -f $_vadm_file $_vadm_vld_barg \
		-g $_vadm_num_elem_in_group $_vadm_vld_darg \
		`eval "echo \\$$_vadm_select_list"`
	fi

	# If there is only one element on the list, call voladm_batch_single.
	set -- `eval "echo \\$$_vadm_select_list"`
	if [ $# -eq $_vadm_num_elem_in_group ]
	then
		voladm_batch_single
		return
	fi

	[ "$_vadm_help" = "yes" ] && voladm_help_push yorn_batch_list.help

	while true
	do
		read_input "$_vadm_list_msg" "Y,N,S(elect)" $_vadm_list_yon
		case $input in
		Y|Yes)
			eval $_vadm_yes_list=\"\$$_vadm_select_list\"
			break;;
		N|No)
			eval $_vadm_no_list=\"\$$_vadm_select_list\";
			break;;
		S|Select|s|select)
			voladm_batch_select
			break;;
		r|redisplay)
			voladm_list_display \
			-g $_vadm_num_elem_in_group $_vadm_vld_darg \
			$_vadm_vld_barg `eval "echo \\$$_vadm_select_list"`
			continue;;
		*)
			ewritemsg -M vxvmshm:787 \
		   	"Please respond with \\\"Y\\\", \\\"N\\\", or \\\"S\\\""
			continue;;
		esac
	done

	[ "$_vadm_help" = "yes" ] && voladm_help_pop
}

# function called by voladm_yorn_batch
voladm_batch_single()
{
	[ "$_vadm_help" = "yes" ] && voladm_help_push yorn_batch_single.help
	while true
	do
		read_input "$_vadm_elem_msg" "y,n" $_vadm_elem_yon
		case $input in
		y|yes)
			eval $_vadm_yes_list=\"\$$_vadm_select_list\"
			break;;
		n|no)
			eval $_vadm_no_list=\"\$$_vadm_select_list\";
			break;;
		r|redisplay)
			voladm_list_display \
			-g $_vadm_num_elem_in_group $_vadm_vld_darg \
			$_vadm_vld_barg `eval "echo \\$$_vadm_select_list"`
			continue;;
		*)
			ewritemsg -M vxvmshm:788 \
			"Please respond with \\\"y\\\" or \\\"n\\\""
			continue;;
		esac
	done
	[ "$_vadm_help" = "yes" ] && voladm_help_pop
}

# function called by voladm_yorn_batch
voladm_batch_select()
{
	[ "$_vadm_help" = "yes" ] && voladm_help_push yorn_batch_elem.help
	set -- `eval echo "\\$$_vadm_select_list"`
	while [ $# -gt 0 ]
	do
		if [ $_vadm_use_bracket = "yes" ]
		then
			ewritemsg `eval echo "[\\${$_vadm_prompt_num}]\"`
		else
			ewritemsg `eval echo "\\${$_vadm_prompt_num}\"`
		fi
		while true
		do
			read_input "$_vadm_elem_msg" "y,n,Y,N" $_vadm_elem_yon
			case $input in
			y|yes)
				i=$_vadm_num_elem_in_group
				while [ $i -gt 0 ]
				do
					eval \
					$_vadm_yes_list=\"\$$_vadm_yes_list $1\"
					dec i
					shift 1
				done
				break;;
			n|no)
				i=$_vadm_num_elem_in_group
				while [ $i -gt 0 ]
				do
					eval \
					$_vadm_no_list=\"\$$_vadm_no_list $1\"
					dec i
					shift 1
				done
				break;;
			Y|Yes)
				eval $_vadm_yes_list=\"\$$_vadm_yes_list $*\"
				break 2;;
			N|No)
				eval $_vadm_no_list=\"\$$_vadm_no_list $*\"
				break 2;;
			r|redisplay)
				if [ $_vadm_use_bracket = "yes" ]
				then
					ewritemsg \
					`eval echo "[\\${$_vadm_prompt_num}]\"`
				else
					ewritemsg \
					`eval echo "\\${$_vadm_prompt_num}\"`
				fi
				continue;;
			*)
				ewritemsg -M vxvmshm:789 \
"Please respond with \\\"y\\\", \\\"n\\\", \\\"Y\\\", or \\\"N\\\""
				continue;;
			esac
		done
	done
	[ "$_vadm_help" = "yes" ] && voladm_help_pop
}

#
# usage: voladm_continue [-n] [prompt_string]
# -n: precede prompt with a newline
#
voladm_continue()
{
	_return_msg=`egettxt "Hit RETURN to continue." vxvmshm:1272`
	if [ $# -ge 1 -a "$1" = "-n" ]
	then
		echo "\n${2:-$_return_msg}\c"
	else
		echo "${1:-$_return_msg}\c"
	fi
	read _continue <&4
	case $_continue in
	q|quit)	quit 101;;
	x)	quit 100;;
	*)	return 0;;
	esac
}

# Like voladm_continue, but no quit option.
voladm_do_continue()
{
	_return_msg=`egettxt "Hit RETURN to continue." vxvmshm:1272`
	echo "${1:-$_return_msg}\c"
	read _continue <&4
	return 0
}

#
# check_exclude_files
#
# Check the disks.exclude and cntrls.exclude files for consistency.
# This function should be called before either of these files is
# used.
#
# If 1 is returned, the program should tell the user to fix the
# problems and then it should exit. If 0 is returned, the files
# were found to be non-existent or correct so processing can continue.
#
check_exclude_files()
{
	bad_disk_list=
	bad_cntrl_list=

	if [ -f $DISK_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxbaddxcld ]
	then
		bad_disk_list=`$VOL_SCRIPTS_DIR/vxbaddxcld $DISK_EXCLUDE_FILE`
	elif [ -f $DISK_EXCLUDE_FILE ]
	then
		for disk in `cat $DISK_EXCLUDE_FILE`
		do
			if not dogi_name_is_device $disk
			then
				append_list bad_disk_list $disk
			fi
		done
	fi

	if [ -f $CNTRL_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxbadcxcld ]
	then
		bad_cntrl_list=`$VOL_SCRIPTS_DIR/vxbadcxcld $CNTRL_EXCLUDE_FILE`
	elif [ -f $CNTRL_EXCLUDE_FILE ]
	then
		for cntrl in `cat $CNTRL_EXCLUDE_FILE`
		do
			if not dogi_name_is_cntrlr $cntrl
			then
				append_list bad_cntrl_list $cntrl
			fi
		done
	fi

	if [ -z "$bad_disk_list" -a -z "$bad_cntrl_list" ]
	then
		return 0	# No errors found.
	else 
		if [ -n "$bad_cntrl_list" ]
		then
			if [ `list_count $bad_cntrl_list` -eq 1 ]
			then
				export CNTRL_EXCLUDE_FILE bad_cntrl_list; \
				ewritemsg -M vxvmshm:343 \
"The following controller address in the controller exclude file
  ${CNTRL_EXCLUDE_FILE} is invalid: $bad_cntrl_list"
			else
				export CNTRL_EXCLUDE_FILE; \
				ewritemsg -f $_cef_tmpfile -M vxvmshm:344 \
"The following controller addresses in the controller exclude file
  ${CNTRL_EXCLUDE_FILE} are invalid:"
				voladm_list_display -acn \
				-f $_cef_tmpfile $bad_cntrl_list
			fi
		fi

		if [ -n "$bad_disk_list" ]
		then
			if [ `list_count $bad_disk_list` -eq 1 ]
			then
				export CNTRL_EXCLUDE_FILE bad_disk_list; \
				ewritemsg -M vxvmshm:351 \
"The following disk address in the disk exclude file
  ${DISK_EXCLUDE_FILE} is invalid: $bad_disk_list"
			else
				export CNTRL_EXCLUDE_FILE; \
				ewritemsg -f $_cef_tmpfile -M vxvmshm:352 \
"The following disk addresses in the disk exclude file
  ${DISK_EXCLUDE_FILE} are invalid:"
				voladm_list_display -acn \
				-f $_cef_tmpfile $bad_disk_list
			fi
		fi
		return 1	# Errors found.
	fi
}

#
# Read a single disk address from the standard input and set its
# address in 'device'. Honor the disks.exclude and cntrls.exclude
# files.
# 
# usage: voladm_disk_device \
#	 [-M catalog_id]
#	 prompt-string [default-result [select-list]]
#
# -M catalog_id: specify catalog id
#
voladm_disk_device()
{
	if [ "$1" = "-M" ]
	then
		_vdskd_msg="`egettxt \"$3\" \"$2\"`"
		shift 2 # Leave message as $1.
	else
		_vdskd_msg="$1"
	fi

	_vdskd_def=
	_vdskd_sel=

	if [ $# -ge 2 ]
	then
		_vdskd_def="$2"
		if [ $# -ge 3 ]
		then
			_vdskd_sel="$3"
		fi
	fi

	while true
	do
		#
		# If the exclude files exist they should have already been
		# verified with the check_exclude_files() function.
		#
		# Create egrep patterns from the files that ensure that only
		# the disk or controller specified is excluded.
		#
		# Build the exclude egrep patterns inside the input while
		# loop in case the files are edited after an exclusion is
		# reported.
		# 
		cntrl_egrep=
		disk_egrep=
		enclr_egrep=

		if [ -f $CNTRL_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxcxcld ]
		then
			cntrl_egrep=`$VOL_SCRIPTS_DIR/vxcxcld $CNTRL_EXCLUDE_FILE`
		elif [ -f $CNTRL_EXCLUDE_FILE ]
		then
			for cntrl in `cat $CNTRL_EXCLUDE_FILE`
			do
				add_cntrlr_expression $cntrl cntrl_egrep
			done
		fi

		if [ -f $DISK_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxdxcld ]
		then
			disk_egrep=`$VOL_SCRIPTS_DIR/vxdxcld $DISK_EXCLUDE_FILE`
		elif [ -f $DISK_EXCLUDE_FILE ]
		then
			for disk in `cat $DISK_EXCLUDE_FILE`
			do
				add_device_expression $disk disk_egrep
			done
		fi

		if [ -f $ENCLR_EXCLUDE_FILE ]
		then
			for enclr in `cat $ENCLR_EXCLUDE_FILE`
			do
				add_enclr_expression $enclr enclr_egrep
			done
		fi


		# To filter out only the listed disk devices in the list 
		# disk_egrep, it's necessary to append "$" to the 
		# enclosure-based names and "s2$" to the mctd and ctd names.
		if [ -n "$disk_egrep" ]
		then
		
			disk_egrep=`echo $disk_egrep | \
			nawk -F"|" '{
				re1=".+_.+"
				re2="(mc|c)[0-9]+t[0-9]+d[0-9]+"
		        	for ( x = 1; x <= NF; ++x )
		        	{
		               		if ( match( $x, re1 ) )
		                       		printf ("%s$", $x)
		               		else if ( match( $x, re2) )
		                       		printf "%ss2$", $x
		               		if ( x < NF )
		                       		printf "|"
		        	}
			}'`
		
		fi


		read_input "$_vdskd_msg" "${_vdskd_sel:-<address>,list}" \
			$_vdskd_def
		
		device=$input
		#
		# If the default value that was specified to read_input
		# was returned, then return now after having set 'device'.
		#
		if [ -n "$_vdskd_def" -a "$device" = "$_vdskd_def" ]
		then
			return 0
		fi

		if [ "X$device" = "X" ] ; then 
			ewritemsg -M vxvmshm:206 \
			"Input not recognized, enter ?? for help"
			continue
		fi

		vxdisk list $device 1>/dev/null 2>&1
		ret=$?
		if vxcheckda $device > /dev/null 2> /dev/null || [ $ret -eq 0 ]
		then
			if dogi_name_is_slice $device
			then
				daname=$device
			else
				dogi_name_daname $device daname
			fi
			
			if [ -n "$cntrl_egrep" ]
			then
				echo $daname | egrep -s -e "$cntrl_egrep"
				if [ $? -eq 0 ]
				then
					export CNTRL_EXCLUDE_FILE device; \
					ewritemsg -M vxvmshm:429 \
"This disk that you specified has been excluded by the
  $CNTRL_EXCLUDE_FILE file: $device"
					device=
					daname=
					continue
				fi
			fi

			if [ -n "$disk_egrep" ]
			then
				echo $daname | egrep -s -e "$disk_egrep"
				if [ $? -eq 0 ]
				then
					export DISK_EXCLUDE_FILE device; \
					ewritemsg -M vxvmshm:430 \
"This disk that you specified has been excluded by the
  $DISK_EXCLUDE_FILE file: $device"
					device=
					daname=
					continue
				fi
			fi

			if [ -n "$enclr_egrep" ]
			then
				echo $daname | egrep -s -e "$enclr_egrep"
				if [ $? -eq 0 ]
				then
					export ENCLR_EXCLUDE_FILE device; \
					ewritemsg -M vxvmshm:1368 \
"This disk that you specified has been excluded by the
  $ENCLR_EXCLUDE_FILE file: $device"
					device=
					daname=
					continue
				fi
			fi

			return 0

		else
			case $device in
			list|l)	(echo ""; vxdevlist ) | voladm_display
				continue;;
			*) ewritemsg -M vxvmshm:206 \
			   "Input not recognized, enter ?? for help";;
	
			esac
		fi
	done
}

#
# Read or take as an argument a disk address pattern list and
# return a list of matching disks in 'device_list'. Honor the
# disks.exclude and cntrls.exclude files.
#
# The following disk address specifications are acceptable:
#
# all:          all disks
# c3 c4t2:      all disks on both controller 3 and controller 4, target 2
# c3t4d2:       a single disk
#
# usage: voladm_disk_device_list \
#	 [-M catalog_id] [-i input-string] \
#	 prompt-string [default-result [select-list]]
#
# -M catalog_id: specify catalog id
# -i input-string: don't call read_input, use input-string as input.
#
voladm_disk_device_list()
{
	_vdskd_iflag=no
	_vdskd_input=
	_vdskd_cat=

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "i:M:" c
	do
		case $c in
		M) _vdskd_cat=$OPTARG;;
		i) _vdskd_iflag=yes; _vdskd_input="$OPTARG";;
		\?) egettxt "voladm_disk_device_list: bad argument list" vxvmshm:1802
		    return 1;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ -n "$_vdskd_cat" ]
	then
		_vdskd_msg="`egettxt \"$1\" \"$_vdskd_cat\"`"
	else
		_vdskd_msg="$1"
	fi

	_vdskd_def=
	_vdskd_sel=

	if [ $# -ge 2 ]
	then
		_vdskd_def="$2"
		if [ $# -ge 3 ]
		then
			_vdskd_sel="$3"
		fi
	fi

	while true
	do
		#
		# If the exclude files exist they should have already been
		# verified with the check_exclude_files() function.
		#
		# Create egrep patterns from the files that ensure that only
		# the disk or controller specified is excluded.
		#
		# Build the exclude egrep patterns inside the input while
		# loop in case the files are edited after an exclusion is
		# reported.
		# 
		cntrl_egrep=
		disk_egrep=
		enclr_egrep=
		if [ -f $CNTRL_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxcxcld ]
		then
			cntrl_egrep=`$VOL_SCRIPTS_DIR/vxcxcld $CNTRL_EXCLUDE_FILE`
		elif [ -f $CNTRL_EXCLUDE_FILE ]
		then
			for cntrl in `cat $CNTRL_EXCLUDE_FILE`
			do
				add_cntrlr_expression $cntrl cntrl_egrep
			done
		fi

		if [ -f $DISK_EXCLUDE_FILE -a -x $VOL_SCRIPTS_DIR/vxdxcld ]
		then
			disk_egrep=`$VOL_SCRIPTS_DIR/vxdxcld $DISK_EXCLUDE_FILE`
		elif [ -f $DISK_EXCLUDE_FILE ]
		then
			for disk in `cat $DISK_EXCLUDE_FILE`
			do
				add_device_expression $disk disk_egrep
			done
		fi

		if [ -f $ENCLR_EXCLUDE_FILE ]
		then
			for enclr in `cat $ENCLR_EXCLUDE_FILE`
			do
				add_enclr_expression $enclr enclr_egrep
			done
		fi

		if [ "$_vdskd_iflag" = "yes" ]
		then
			if [ -n "$_vdskd_input" ]
			then
				input="$_vdskd_input"
				_vdskd_input=
			else
				# Return after one iteration.
				return 0
			fi
		else
			read_input "$_vdskd_msg" \
			"${_vdskd_sel:-<pattern-list>,all,list}" $_vdskd_def

			#
			# If the default value that was specified to
			# read_input was returned, then set device_list
			# and return.
			#
			if [ -n "$_vdskd_def" -a "$input" = "$_vdskd_def" ]
			then
				device_list="$_vdskd_def"
				return 0
			fi

			if [ -z "$input" ]
			then
				ewritemsg -M vxvmshm:206 \
				"Input not recognized, enter ?? for help"
				continue
			fi
		fi

		list=
		first_pass=yes

		cntrl_exclude_list=
		disk_exclude_list=
		enclr_exclude_list=

		# Process each disk address or pattern entered.
		set -- $input
		while [ $# -gt 0 ]
		do
			spec=$1
			pattern=

			if [ "$spec" = "all" ]
			then
				if [ "$first_pass" = "no" -o $# -gt 1 ]
				then
					ewritemsg -M vxvmshm:63 \
"'all' should appear alone, enter ?? for help"
					continue 2
				fi
			fi

			if [ "$spec" = "list"  -o "$spec" = "l" ]
			then
				if [ "$first_pass" = "no" -o $# -gt 1 ]
				then
					ewritemsg -M vxvmshm:64 \
"'list' should appear alone, enter ?? for help"
				else
					(echo ""; vxdevlist) | voladm_display
				fi
				continue 2;
			fi
			
			expand_device_wildcard list \
			 "$disk_egrep" "$cntrl_egrep" "$enclr_egrep"\
			 disk_exclude_list cntrl_exclude_list \
			 enclr_exclude_list $spec

			if [ $? -ne 0 ]
			then
				if [ "$_vdskd_iflag" = "yes" ]
				then
					export spec;ewritemsg -M vxvmshm:766 \
"Input not recognized: \"$spec\""
					return 1
				fi
				continue 2
			fi
			
			first_pass=no
			shift
		done

		#
		# Shouldn't reach here unless ready to return. Sort the
		# list and remove any duplicates, then return.
		#
		device_list=`for d in $list; do echo $d; done | sort | uniq`

		if [ -n "$cntrl_exclude_list" -o -n "$disk_exclude_list" \
			-o -n "$enclr_exclude_list" ]
		then
			cntrl_exclude_list=`
			for c in $cntrl_exclude_list; do echo $c; done |
			sed "s%/dev/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"   |
			sed "s%/dev/ap/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"` 

			disk_exclude_list=`
			for d in $disk_exclude_list; do echo $d; done |
			sed "s%/dev/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"  |
			sed "s%/dev/ap/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"`

			enclr_exclude_list=`
			for d in $enclr_exclude_list; do echo $d; done |
			sed "s%/dev/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"  |
			sed "s%/dev/ap/rdsk/\(.*\)$VOL_FULL_SLICE$%\1%"`

			disp_file=$_vdskd_rawmatch

			if [ -n "$cntrl_exclude_list" ]
			then
				if [ `list_count $cntrl_exclude_list` -eq 1 ]
				then
					export \
					cntrl_exclude_list CNTRL_EXCLUDE_FILE; \
					ewritemsg -M vxvmshm:428 \
"This disk that you specified has been excluded by the
  $CNTRL_EXCLUDE_FILE file: $cntrl_exclude_list"
					voladm_continue -n
				else
					export CNTRL_EXCLUDE_FILE; \
					ewritemsg -f $disp_file -M vxvmshm:415 \
"These disks that you specified have been excluded by the
  $CNTRL_EXCLUDE_FILE file:"
				voladm_list_display -anc \
				-f $disp_file $cntrl_exclude_list
				fi
			fi

			if [ -n "$disk_exclude_list" ]
			then
				if [ `list_count $disk_exclude_list` -eq 1 ]
				then
					export \
					disk_exclude_list DISK_EXCLUDE_FILE; \
					ewritemsg -M vxvmshm:431 \
"This disk that you specified has been excluded by the
  $DISK_EXCLUDE_FILE file: $disk_exclude_list"
					voladm_continue -n
				else
					export DISK_EXCLUDE_FILE; \
					ewritemsg -f $disp_file -M vxvmshm:416 \
"These disks that you specified have been excluded by the
  $DISK_EXCLUDE_FILE file:"
					voladm_list_display -anc \
					-f $disp_file $disk_exclude_list
				fi
			fi

			if [ -n "$enclr_exclude_list" ]
			then
				if [ `list_count $enclr_exclude_list` -eq 1 ]
				then
					export \
					enclr_exclude_list ENCLR_EXCLUDE_FILE; \
					ewritemsg -M vxvmshm:1369 \
"This disk that you specified has been excluded by the
  $ENCLR_EXCLUDE_FILE file: $enclr_exclude_list"
					voladm_continue -n
				else
					export ENCLR_EXCLUDE_FILE; \
					ewritemsg -f $disp_file -M vxvmshm:1367 \
"These disks that you specified have been excluded by the
  $ENCLR_EXCLUDE_FILE file:"
					voladm_list_display -anc \
					-f $disp_file $enclr_exclude_list
				fi
			fi

			if [ -z "$device_list" ]
			then
				continue
			fi
		fi
		return 0
	done
}

# voladm_disk_group purpose default
voladm_disk_group()
{
	_new_group_okay=
	if [ X$1 = X-n ]
	then
		_new_group_okay=yes
		shift
	fi
	_opt="<group>,list"
	[ $# -eq 3 ] && _opt="<group>,none,list"
	_default=$2
	_prompt=$1
	while true
	do
		_riput=`egettxt "Which disk group" vxvmshm:509`
		read_input "$_riput" "$_opt" $_default
		dgname=$input
		case $dgname in
		"")	ewritemsg -M vxvmshm:70 "A disk group name is required."
			continue;;
		list|l)	(echo ""; vxdg list ) | voladm_display
			continue;;
		*" "* | *"	"*)
			export dgname; ewritemsg -M vxvmshm:156 "Disk group name $dgname is not valid."
			continue;;
		none)	[ $# -eq 3 ] && return 0;;
		esac
		_voldg_output=`vxdg -q list | grep "^\$dgname[ 	]"`
		if [ `list_count $_voldg_output` -ne 3 ]
		then
			export dgname; ewritemsg -M vxvmshm:399 "There is no active disk group named $dgname."

			if [ -n "$_new_group_okay" ] &&
			   voladm_yorn -M vxvmshm:119 "Create a new group named $dgname?" y
			then
				return 10
			fi
			continue
		fi
		if [ "X`list_item 2 $_voldg_output`" != Xenabled ]
		then
			export dgname; ewritemsg -M vxvmshm:154 \
		 "Disk group $dgname is not currently usable due to errors."
			continue
		fi
		return 0
	done
}

voladm_new_disk_dmname()
{
	_default_dmname=`vxnewdmname "$1"`

	if [ "$2" ] ; then
		disk="$2"; export disk; \
		_riput=`egettxt "Enter disk name for $disk" vxvmshm:184`
	else
		_riput=`egettxt "Enter disk name" vxvmshm:183`
	fi

	# gather all known names currently in use in the disk group
	while true ; do
		read_input "$_riput" "<name>" $_default_dmname
		if [ "X$input" != "X$_default_dmname" ] &&
		   not vxnewdmname -c "$input" "$1"
		then
			export input;  ewritemsg -M vxvmshm:546 \
		      "dmname $input already in use. Please enter a new one."
			_riput=`egettxt "Enter disk name" vxvmshm:183`
			continue
		else
                        input_len=`strlen $input`
                        if [ `expr $input_len \> 31` = 1 ] ; then
                                ewritemsg -M vxvmshm:334\
                "The disk name is too long. Please re-enter."
				_riput=`egettxt "Enter disk name" vxvmshm:183`
                                continue
                        fi
		fi
		break
	done

	dmname=$input
	return 0
}

voladm_new_disk_privlen()
{
	_default_privlen=2048
	_max_privlen=524288
	_min_privlen=1
	
	disk=$1
	export disk
	_riput=`egettxt "Enter private region length for $disk" vxvmshm:1344`
	while true ; do 
		read_input "$_riput" "<privlen>" $_default_privlen
		if [ $input -lt $_min_privlen ] ||
			[ $input -gt $_max_privlen ] 
		then
			export input;  ewritemsg -M vxvmshm:1353 \
		      	"Private region length $input out of range. Please enter a length between 1 and 524288."
			export disk
			_riput=`egettxt "Enter private region length for $disk" vxvmshm:1344`
			continue
		fi
		break
	done
	
	dmprivlen=$input;export dmprivlen

	return 0
}

#
# usage: voladm_get_disk_dmname \
#	 [-r] [-g disk-group] [-h on|off] \
#	 prompt default
# -r: restrict search to removed disks
# -n: restrict search to disks with enough free space
# -h on|off: restrict to disks with the hot-spare flag on or off
# -g disk-group: restrict search to disks in disk-group
#
voladm_get_disk_dmname()
{
	_dm_want_removed=
	_dm_want_spec_dg=
	_dm_want_hotspare=
	_dm_want_nohotuse=
	_dm_want_newdm=

	OPTIND=1 # sh does not re-initialize OPTIND
	while getopts "rg:h:n:e:" c
	do
		case $c in
		r) _dm_want_removed=yes;;
		g) _dm_want_spec_dg="$OPTARG";;
		h) _dm_want_hotspare="$OPTARG";; 
		e) _dm_want_nohotuse="$OPTARG";; 
		n) _dm_want_newdm=yes 
		   orig_len=$OPTARG;;
		\?) egettxt "voladm_get_disk_dmname: bad argument list" vxvmshm:1454
		    return 1;;
		esac
	done
	shift `expr $OPTIND - 1`

	if [ -n "$_dm_want_hotspare" -a \
	    "$_dm_want_hotspare" != "on" -a "$_dm_want_hotspare" != "off" ]
	then
		egettxt "voladm_get_disk_dmname: -h takes only 'on' or 'off'" vxvmshm:1453
		return
	fi

	_dm_prompt=$1
	[ X"$_dm_prompt" != "X" ] || \
		_dm_prompt=`egettxt "Enter disk name" vxvmshm:183`
	_default=$2

	while true
	do
		read_input "$_dm_prompt" "<disk>,list" $_default
		dmname=$input
		case $input in
		"")	ewritemsg -M vxvmshm:252 \
	 "Please enter a disk name, or type \\\"list\\\" to list all disks."
			continue;;
		$_default)
			return 0;;
		list|l)	if [ "$_dm_want_removed" ]
			then
				(echo ""
				 if [ -z "$_dm_want_spec_dg" ]
				 then
				 	vxprint -Atd
				 else
				 	vxprint -td -g "$_dm_want_spec_dg"
				 fi |
					awk '$1!="dm" || $3=="-" {print $0;}'
				 echo "") | voladm_display
			elif [ "$_dm_want_newdm" ]
			then
				dmlist=`vxprint -qd -g "$_dm_want_spec_dg" -F %name`
				for i in $dmlist
				do
					voladm_freespace_len $i $orig_len
					if [ $? -eq 0 ]
					then
						(echo ""
						vxdisk -qg $_dm_want_spec_dg list |\
						grep $i) | voladm_display
					fi
				done
			elif [ "$_dm_want_hotspare" ]
			then
				(echo ""
				 if [ -z "$_dm_want_spec_dg" ]
				 then
				 	LANG= vxdisk list
				 else
				 	LANG= vxdisk -g "$_dm_want_spec_dg"
				 fi | awk '{
					found="off"
					foundnhu="off"
					for (i=6; i<=NF; i++)
						if ($i == "spare") {
							found="on"
						} else if ($i == "nohotuse") {
							foundnhu="on"
						}
					if ( $1 == "DEVICE" || (found == "'$_dm_want_hotspare'" && \
											foundnhu == "off" && $3 != "-" ))
						print $0
					}'
				) | voladm_display
			elif [ "$_dm_want_nohotuse" ]
			then
				(echo ""
				 if [ -z "$_dm_want_spec_dg" ]
				 then
				 	LANG= vxdisk list
				 else
				 	LANG= vxdisk -g "$_dm_want_spec_dg"
				 fi | awk '{
					found="off"
					foundspare="off"
					for (i=6; i<=NF; i++)
						if ($i == "nohotuse") {
							found="on"
						} else if ($i == "spare") {
							foundspare="on"
						}
					if ( $1 == "DEVICE" || (found == "'$_dm_want_nohotuse'" && \
											foundspare == "off" && $3 != "-" ))
						print $0
					}'
				) | voladm_display
			else
				(echo ""; vxprint -Atd ) | voladm_display
			fi
			continue
			;;
		esac
		# XXX - The disks below should be filtered if _dm_want_removed
		# or _dm_want_hotspare have been specified.
		shift $# 
		if [ -z "$_dm_want_spec_dg" ]
		then
			set -- `vxprint -dAQF "%dgname" "\$dmname" 2> /dev/null`
		else
			set -- `vxprint -g "$_dm_want_spec_dg" \
					-dF "%dgname" "\$dmname" 2> /dev/null`
		fi
		if [ $# -eq 0 ] && [ -z "$_dm_want_spec_dg" ]
		then
			export dmname; ewritemsg -M vxvmshm:400 \
"There is no disk named $dmname in any disk group configuration.
  To get a list of disks enter \\\"list\\\"."
			continue
		elif [ $# -eq 0 ]
		then
			export dmname _dm_want_spec_dg; \
			ewritemsg -M vxvmshm:401 \
"There is no disk named $dmname in disk group $_dm_want_spec_dg.
  To get a list of disks enter \\\"list\\\"."
			continue
		fi
		break
	done
	if [ $# -eq 1 ]
	then
		dgname=$1
		return 0
	fi
	export dmname; ewritemsg -M vxvmshm:397 \
"There is a disk named $dmname in each of the following disk groups:
  	$*" "$@"
	while true
	do
		_riput=`egettxt "Enter the disk group to use" vxvmshm:187`
		read_input "$_riput" "group" $1
		for dgname in $*
		do
			if [ "X$dgname" = "X$input" ]
			then
				return 0
			fi
		done
		ewritemsg -M vxvmshm:248 \
			"Please choose a disk group from the list:\n\n\t$*" "$@"
	done
}

#
# usage: voladm_get_origin_dmname\
#	 [-r] [-g disk-group] [-h on|off] \
#	 prompt default
# -r: restrict search to removed disks
# -u: restrict search to disks which failed and the subdisks on it were
#     hot-relocated
# -h on|off: restrict to disks with the hot-spare flag on or off
# -g disk-group: restrict search to disks in disk-group
#
voladm_get_origin_dmname()
{
	_dm_prompt=`egettxt "Enter the original disk name" vxvmshm:1431`
	_default=$2

	while true
	do
		read_input "$_dm_prompt" "<disk>,list" $_default
		dmname=$input
		case $input in
		"") 
			ewritemsg -M vxvmshm:939 \
"Please enter a disk name, or type \\\"list\\\" to list all hot-relocated disks."
			continue;;
		$_default)
			return 0;;
		list|l)	
			(echo ""
			 vxprint -QAs -e 'sd_orig_dmname!=""' \
				  -F %orig_dmname | sort | uniq) | voladm_display
			continue
			;;
		esac

		shift $# 

		vxprint -AQs -e'sd_orig_dmname == "'$dmname'"' \
			-F %dgname | sort | uniq > $tmpfile1
		set -- `cat $tmpfile1 2> /dev/null`

		if [ $# -eq 0 ]
		then
			export dmname; ewritemsg -M vxvmshm:935 \
"No subdisks appear to be hot-relocated from $dmname.
  To get a list of hot-relocated disks enter \\\"list\\\"."
			continue
			
		fi
		break
	done

	if [ $# -eq 1 ]
	then
		dgname=`cat $tmpfile1`
		return 0
	fi
	export dmname; ewritemsg -M vxvmshm:946 \
"There are subdisks which were relocated from $dmname in the following disk groups:
  	$*" "$@"
	while true
	do
		_riput=`egettxt "Enter the disk group to use" vxvmshm:187`
		read_input "$_riput" "group" $1
		for dgname in $*
		do
			if [ "X$dgname" = "X$input" ]
			then
				return 0
			fi
		done
		ewritemsg -M vxvmshm:248 \
			"Please choose a disk group from the list:\n\n\t$*" "$@"
	done
}

# get free space length on a specified disk
voladm_freespace_len()
{
	total=0
	diskname=$1
	total=`vxdg -qa -g $dgname free $diskname | \
		awk '{sum += $5}; END {printf("%ld\n", sum)}'`

	if [ $total -ge $2 ]
	then
		return 0
	else 
		return 1
	fi
}

# re-online all online disks
voladm_reonline_all()
{
	vxdisk -a online > /dev/null 2>&1
}

# get the system hostid from the volboot file in system_hostid
voladm_system_hostid()
{
	system_hostid=
	system_hostid=`LANG= vxdctl list | grep '^hostid:' |
			{ read key hostid; echo "$hostid"; }`
	if [ -z "$system_hostid" ]
	then
		ewritemsg -M vxvmshm:442 \
	 "Unexpected internal error -- Cannot get the system's hostid."
		return 1
	fi
	return 0
}

strlen()
{
	echo "$1" | awk '{ printf("%d",length($0)) }'
}

#
# table look-up increment for small positive integers
#
inc()
{
	if [ $# -ne 1 ]
	then
		echo "usage: inc var-name"
		return
	fi

	_i_var=$1
	eval "_i_val=\$$_i_var"

	case $_i_val in
	0) _i_new_val=1;;
	1) _i_new_val=2;;
	2) _i_new_val=3;;
	3) _i_new_val=4;;
	4) _i_new_val=5;;
	5) _i_new_val=6;;
	6) _i_new_val=7;;
	7) _i_new_val=8;;
	8) _i_new_val=9;;
	9) _i_new_val=10;;
	10) _i_new_val=11;;
	11) _i_new_val=12;;
	12) _i_new_val=13;;
	13) _i_new_val=14;;
	14) _i_new_val=15;;
	15) _i_new_val=16;;
	16) _i_new_val=17;;
	17) _i_new_val=18;;
	18) _i_new_val=19;;
	19) _i_new_val=20;;
	20) _i_new_val=21;;
	21) _i_new_val=22;;
	22) _i_new_val=23;;
	23) _i_new_val=24;;
	24) _i_new_val=25;;
	25) _i_new_val=26;;
	26) _i_new_val=27;;
	27) _i_new_val=28;;
	28) _i_new_val=29;;
	29) _i_new_val=30;;
	30) _i_new_val=31;;
	31) _i_new_val=32;;
	32) _i_new_val=33;;
	33) _i_new_val=34;;
	34) _i_new_val=35;;
	35) _i_new_val=36;;
	36) _i_new_val=37;;
	37) _i_new_val=38;;
	38) _i_new_val=39;;
	39) _i_new_val=40;;
	40) _i_new_val=41;;
	41) _i_new_val=42;;
	42) _i_new_val=43;;
	43) _i_new_val=44;;
	44) _i_new_val=45;;
	45) _i_new_val=46;;
	46) _i_new_val=47;;
	47) _i_new_val=48;;
	48) _i_new_val=49;;
	49) _i_new_val=50;;
	50) _i_new_val=51;;
	51) _i_new_val=52;;
	52) _i_new_val=53;;
	53) _i_new_val=54;;
	54) _i_new_val=55;;
	55) _i_new_val=56;;
	56) _i_new_val=57;;
	57) _i_new_val=58;;
	58) _i_new_val=59;;
	59) _i_new_val=60;;
	60) _i_new_val=61;;
	61) _i_new_val=62;;
	62) _i_new_val=63;;
	63) _i_new_val=64;;
	64) _i_new_val=65;;
	65) _i_new_val=66;;
	66) _i_new_val=67;;
	67) _i_new_val=68;;
	68) _i_new_val=69;;
	69) _i_new_val=70;;
	70) _i_new_val=71;;
	71) _i_new_val=72;;
	72) _i_new_val=73;;
	73) _i_new_val=74;;
	74) _i_new_val=75;;
	75) _i_new_val=76;;
	76) _i_new_val=77;;
	77) _i_new_val=78;;
	78) _i_new_val=79;;
	79) _i_new_val=80;;
	80) _i_new_val=81;;
	81) _i_new_val=82;;
	82) _i_new_val=83;;
	83) _i_new_val=84;;
	84) _i_new_val=85;;
	85) _i_new_val=86;;
	86) _i_new_val=87;;
	87) _i_new_val=88;;
	88) _i_new_val=89;;
	89) _i_new_val=90;;
	90) _i_new_val=91;;
	91) _i_new_val=92;;
	92) _i_new_val=93;;
	93) _i_new_val=94;;
	94) _i_new_val=95;;
	95) _i_new_val=96;;
	96) _i_new_val=97;;
	97) _i_new_val=98;;
	98) _i_new_val=99;;
	99) _i_new_val=100;;
	*) _i_new_val=`expr $_i_val + 1`
	esac

	eval $_i_var=$_i_new_val
}

#
# table look-up decrement for small positive integers
#
dec()
{
	if [ $# -ne 1 ]
	then
		echo "usage: dev var-name"
		return
	fi

	_d_var=$1
	eval "_d_val=\$$_d_var"

	case $_d_val in
	0) _d_new_val=-1;;
	1) _d_new_val=0;;
	2) _d_new_val=1;;
	3) _d_new_val=2;;
	4) _d_new_val=3;;
	5) _d_new_val=4;;
	6) _d_new_val=5;;
	7) _d_new_val=6;;
	8) _d_new_val=7;;
	9) _d_new_val=8;;
	10) _d_new_val=9;;
	11) _d_new_val=10;;
	12) _d_new_val=11;;
	13) _d_new_val=12;;
	14) _d_new_val=13;;
	15) _d_new_val=14;;
	16) _d_new_val=15;;
	17) _d_new_val=16;;
	18) _d_new_val=17;;
	19) _d_new_val=18;;
	20) _d_new_val=19;;
	21) _d_new_val=20;;
	22) _d_new_val=21;;
	23) _d_new_val=22;;
	24) _d_new_val=23;;
	25) _d_new_val=24;;
	26) _d_new_val=25;;
	27) _d_new_val=26;;
	28) _d_new_val=27;;
	29) _d_new_val=28;;
	30) _d_new_val=29;;
	31) _d_new_val=30;;
	32) _d_new_val=31;;
	33) _d_new_val=32;;
	34) _d_new_val=33;;
	35) _d_new_val=34;;
	36) _d_new_val=35;;
	37) _d_new_val=36;;
	38) _d_new_val=37;;
	39) _d_new_val=38;;
	40) _d_new_val=39;;
	41) _d_new_val=40;;
	42) _d_new_val=41;;
	43) _d_new_val=42;;
	44) _d_new_val=43;;
	45) _d_new_val=44;;
	46) _d_new_val=45;;
	47) _d_new_val=46;;
	48) _d_new_val=47;;
	49) _d_new_val=48;;
	50) _d_new_val=49;;
	51) _d_new_val=50;;
	52) _d_new_val=51;;
	53) _d_new_val=52;;
	54) _d_new_val=53;;
	55) _d_new_val=54;;
	56) _d_new_val=55;;
	57) _d_new_val=56;;
	58) _d_new_val=57;;
	59) _d_new_val=58;;
	60) _d_new_val=59;;
	61) _d_new_val=60;;
	62) _d_new_val=61;;
	63) _d_new_val=62;;
	64) _d_new_val=63;;
	65) _d_new_val=64;;
	66) _d_new_val=65;;
	67) _d_new_val=66;;
	68) _d_new_val=67;;
	69) _d_new_val=68;;
	70) _d_new_val=69;;
	71) _d_new_val=70;;
	72) _d_new_val=71;;
	73) _d_new_val=72;;
	74) _d_new_val=73;;
	75) _d_new_val=74;;
	76) _d_new_val=75;;
	77) _d_new_val=76;;
	78) _d_new_val=77;;
	79) _d_new_val=78;;
	80) _d_new_val=79;;
	81) _d_new_val=80;;
	82) _d_new_val=81;;
	83) _d_new_val=82;;
	84) _d_new_val=83;;
	85) _d_new_val=84;;
	86) _d_new_val=85;;
	87) _d_new_val=86;;
	88) _d_new_val=87;;
	89) _d_new_val=88;;
	90) _d_new_val=89;;
	91) _d_new_val=90;;
	92) _d_new_val=91;;
	93) _d_new_val=92;;
	94) _d_new_val=93;;
	95) _d_new_val=94;;
	96) _d_new_val=95;;
	97) _d_new_val=96;;
	98) _d_new_val=97;;
	99) _d_new_val=98;;
	*) _d_new_val=`expr $_d_val - 1`
	esac

	eval $_d_var=$_d_new_val
}

# contents of default vxvm.exclude and vxdmp.exclude files
default_exclude_file()
{
	echo "exclude_all 0"
	echo "paths"
	echo "#"
	echo "controllers"
	echo "#"
	echo "product"
	echo "#"
	echo "pathgroups"
	echo "#"
}

# create the default exclude files if they are not present
create_exclude_files()
{
	if [ ! -f $VOL_CONFIG_DIR/vxvm.exclude ]
	then
		default_exclude_file > $VOL_CONFIG_DIR/vxvm.exclude
	fi

	if [ ! -f $VOL_CONFIG_DIR/vxdmp.exclude ]
	then
		default_exclude_file > $VOL_CONFIG_DIR/vxdmp.exclude
	fi
}

# returns true if given path is of the form cXtX or cXtXdX
match_path()
{
	input_len=`strlen $1`

	match_len1=`expr $1 : 'c[0-9][0-9]*t.*'`
	match_len2=`expr $1 : 'c[0-9][0-9]*t.*d[0-9][0-9]*'`
	[ "$input_len" -eq "$match_len1" -o "$input_len" -eq "$match_len2" ]
}

# returns true if given path is of the form cXtX
match_target_path()
{
	input_len=`strlen $1`

	match_len1=`expr $1 : 'c[0-9][0-9]*t.*'`
	[ "$input_len" -eq "$match_len1" ]
}

# returns true if given path is of the form cXtXdX
match_lun_path()
{
	input_len=`strlen $1`

	match_len1=`expr $1 : 'c[0-9][0-9]*t.*d[0-9][0-9]*'`
	[ "$input_len" -eq "$match_len1" ]
}

# returns true if given path is of the form cXtXdXsX
match_slice_path()
{
	input_len=`strlen $1`

	match_len1=`expr $1 : 'c[0-9][0-9]*t*d[0-9][0-9]*s[0-7]'`
	match_len2=`expr $1 : 'vpath[0-9][0-9]*c'`
	[ "$input_len" -eq "$match_len1" -o "$input_len" -eq "$match_len2" ]
}


match_vpath_path()
{
	input_len=`strlen $1`
	match_len1=`expr $1 : 'vpath[0-9][0-9]*'`
	[ "$input_len" -eq "$match_len1" ]
}

# prints the input on a single line
print_line()
{
        count=0

        echo
        printf "\n   "
        set -- $@
        while [ $# -gt 0 ]
        do
                IN_ARG=`basename $1`
                IN_ARGLEN=`echo $IN_ARG|wc -m`
		for i in 15 20 30 40
                do if [ "$IN_ARGLEN" -lt "$i" ]
                   then
                        IN_ARGLEN=$i
                        break
                   fi
                done
                count=`expr $count + $IN_ARGLEN`
                [ $count -gt 65 ] && { count=$IN_ARGLEN; printf "\n   "; }
                printf "%-${IN_ARGLEN}s " $IN_ARG
                shift 1
        done
        echo;echo
}

# returns a list of device names given a list of slice names. uses the function
# dogi_slice_to_device
slice_to_device()
{
	set -- $@

	while [ $# -gt 0 ]
	do
		name=`basename $1`
		dogi_slice_to_device $name devicename
		ret=$?
		if [ $ret != 0 ]
		then
			# this is to handle c#tWWNd#s# pathnames
			devicename=`expr $name : \
				'\(c[0-9][0-9]*t.*d[0-9][0-9]*\)s[0-9][0-9]*'`
			[ -z "$devicename" ] && { shift 1; continue; }
		fi
		echo $devicename
		shift 1
	done
}

# checks if any path under the given controller is the last enabled path to a
# disk containing a volume
check_ctlr_for_volumes()
{
	ctlr=$1
	pathsonctlr=`vxdmpadm getsubpaths ctlr=$ctlr | tail +3 | \
							awk '{ print $1; }'`
	volume_list=
	lastpath=0
	for path in $pathsonctlr
	do
		dmpnode=`vxdmpadm getdmpnode nodename=$path | tail +3 | \
							awk '{ print $1; }'`
		npaths_enabled=`vxdisk list $dmpnode | grep "state=enabled" | \
							wc -l`
		path_state=`vxdisk list $dmpnode | grep "^$path" | \
							awk '{ print $2; }'`
		if [ "$npaths_enabled" -eq 1 ] && \
					[ "$path_state" = "state=enabled" ]
		then
			dmname=`vxdisk list | grep $dmpnode | \
					awk '{ print $3; }' | egrep -v "^-$"`
			dgname=`vxdisk list | grep $dmpnode | \
					awk '{ print $4; }' | egrep -v "^-$"`
			[ -z "$dmname" ] && continue
			/etc/vx/bin/vxckdiskrm -g $dgname $dmname \
							> $tmpfile1 2>/dev/null
			if [ -s $tmpfile1 ]
			then
				lastpath=1
				vol=`cat $tmpfile1 | awk '{print $1}'`
				volume_list="$volume_list $vol"
			fi
		fi
	done

	if [ $# -gt 1 ]
	then
		eval "${2}=\"$volume_list\""
	fi

	rm -f $tmpfile1

	[ "$lastpath" -eq 0 ]
}

check_ctlr_for_enclosures()
{
	ctlr=$1
	enclr_list=
	enclrs_on_ctlr=`vxdmpadm listctlr ctlr=$ctlr | tail +3 | \
						awk '{ print $4; }'`
	lastctlr=0
	for enclr in $enclrs_on_ctlr
	do
		nctlrs_enabled=`vxdmpadm listctlr enclosure=$enclr | \
					tail +3 | grep "ENABLED" | wc -l`
		ctlr_state=`vxdmpadm listctlr ctlr=$ctlr enclosure=$enclr | \
					tail +3 | awk '{ print $3; }'`
		if [ "$nctlrs_enabled" -eq 1 ] && \
					[ "$ctlr_state" = "ENABLED" ]
		then
			lastctlr=1
			enclr_list="$enclr_list $enclr"	
		fi
	done

	if [ $# -gt 1 ]
	then
		eval "${2}=\"$enclr_list\""
	fi

	[ "$lastctlr" -eq 0 ]
}

# checks if the given path is the last enabled path to a disk containing
# volume(s)
check_path_for_volumes()
{
	path=$1
	lastpath=0
	dmpnode=`vxdmpadm getdmpnode nodename=$path 2>/dev/null| tail +3 | \
							awk '{ print $1; }'`
	npaths_enabled=`vxdisk list $dmpnode | grep "state=enabled" | wc -l`
	path_state=`vxdisk list $dmpnode | grep "^$path" | awk '{ print $2; }'`

	if [ "$npaths_enabled" -eq 1 ] && [ "$path_state" = "state=enabled" ]
	then
		dmname=`vxdisk list | grep $dmpnode | awk '{ print $3; }'\
					| egrep -v "^-$"`
		dgname=`vxdisk list | grep $dmpnode | awk '{ print $4; }'\
					| egrep -v "^-$"`
		[ -z "$dmname" ] && continue
		/etc/vx/bin/vxckdiskrm -g $dgname $dmname >$tmpfile1 2>/dev/null
		if [ -s $tmpfile1 ]
		then
			lastpath=1
			if [ $# -gt 1 ]
			then
			     eval "${2}=\"`cat $tmpfile1 | awk '{print $1}'`\""
			fi
		fi
	fi

	rm -f $tmpfile1

	[ "$lastpath" -eq 0 ]
}

# checks if the given disk is part of any volume
check_dmpnode_for_volumes()
{
	path=$1
	lastpath=0
	dmpnode=`vxdmpadm getdmpnode nodename=$path | tail +3 | \
							awk '{ print $1; }'`
	dmname=`vxdisk list | grep $dmpnode | awk '{ print $3; }'\
							| egrep -v "^-$"`
	dgname=`vxdisk list | grep $dmpnode | awk '{ print $4; }'\
							| egrep -v "^-$"`
	if [ ! -z "$dmname" ]
	then
		/etc/vx/bin/vxckdiskrm -g $dgname $dmname >$tmpfile1 2>/dev/null
		if [ -s $tmpfile1 ]
		then
			lastpath=1
			if [ $# -gt 1 ]
			then
			      eval "${2}=\"`cat $tmpfile1 | awk '{print $1}'`\""
			fi
		fi
	fi

	rm -f $tmpfile1
	[ "$lastpath" -eq 0 ]
}

# this is the message given after any include/exclude operation that needs
# a reboot to take effect
reboot_message()
{
	ewritemsg -M vxvmshm:1241 \
"This operation will take effect only after a reboot."
	voladm_continue -n	
}

# this function lists all the paths seen by DMP. It uses the vxdmpadm
# command to gather the list of all paths.
listpaths()
{
	allpaths=
	newline="\n"
	for enclr in `vxdmpadm listenclosure all | tail +3 |\
			grep -v "DISCONNECTED" | awk '{print $1 "\n";}'`
	do
		for dmpnode in `vxdmpadm getdmpnode enclosure=$enclr |\
			grep -v "NONAME" | tail +3 | awk '{ print $1 "\n"; }'`
		do
			paths=`vxdmpadm getsubpaths dmpnodename=$dmpnode |\
			grep -v "NONAME" | tail +3 | awk '{ print $1 "\n"; }'`
			allpaths="$allpaths $paths"
			allpaths="$allpaths $newline"
		done
	done
	echo $allpaths
}

# this function lists all the paths seen by DMP. It uses the vxdmpadm
# command to gather the list of all paths. the output of this function
# will be in the form <c#WWWN#d#s#  dmpnodename#>
list_dmpnode_paths()
{
	allpaths=
	for enclr in `vxdmpadm listenclosure all | tail +3 |\
			grep -v "DISCONNECTED" | awk '{print $1;}'`
	do
		for dmpnode in `vxdmpadm getdmpnode enclosure=$enclr |\
				grep -v "NONAME" | tail +3 | \
				awk '{ print $1; }'`
		do
			dmpnodedev=`slice_to_device $dmpnode`
			for path in \
				`vxdmpadm getsubpaths dmpnodename=$dmpnode | \
				grep -v "NONAME" | tail +3 | awk '{print $1}'`
			do
				path=`slice_to_device $path`
				allpaths="$allpaths $path $dmpnodedev"
			done
		done
	done

	set -- $allpaths
	printf "%-10s %s\n" "PATH" "(DMPNODE)"
	printf "%-10s %s\n" "----" "---------"

	while [ $# -gt 1 ]
	do
		printf "%-10s %s\n" $1 $2
		shift 2
	done
}

# this function checks if the given VID:PID combination matches the VID:PID
# of the rootdisk. Returns true if it does, false otherwise.
check_rootdisk_vidpid()
{
	set_rootdisk
	dogi_whole_slice $rootdisk rootdev
	rootvid=`/etc/vx/diag.d/vxdmpinq $DISK_RAWPATH/$rootdev |\
			grep "Vendor" | awk '{ print $4 }'`
	# Product id may contain spaces.
	rootpid=`/etc/vx/diag.d/vxdmpinq $DISK_RAWPATH/$rootdev |\
			grep "Product" | sed -e 's/Product id//g' \
			-e 's/^[ 	][ 	]*//g' -e 's/^:[ 	]//g'`
	root_vid_pid1="$rootvid:$rootpid"
	root_vid_pid2="*:$rootpid"
	root_vid_pid3="$rootvid:*"

	[ "$1" = "$root_vid_pid1" ] || [ "$1" = "$root_vid_pid2" ] ||\
		[ "$1" = "$root_vid_pid3" ]
}

get_volumes_on_ctlr()
{
	ctlr=$1
	volumes_on_ctlr=
	volumes_present=no
	disks_on_ctlr=`vxdmpadm getsubpaths ctlr=$1 | tail +3 | \
						awk '{ print $4; }'`
	for disk in $disks_on_ctlr
	do
		dmname=`vxdisk list | grep $disk | awk '{ print $3; }' | \
							egrep -v "^-$"`
		dgname=`vxdisk list | grep $disk | awk '{ print $4; }' | \
							egrep -v "^-$"`
		if [ ! -z "$dmname" ]
		then
			/etc/vx/bin/vxckdiskrm -g $dgname $dmname \
						>$tmpfile1 2>/dev/null
			if [ -s $tmpfile1 ]
			then
				volumes_present=yes
				vol=`cat $tmpfile1 | awk '{print $1}'`
				volumes_on_ctlr="$volumes_on_ctlr $vol"
			fi
		fi
	done

	rm -f $tmpfile1

	if [ $# -gt 1 ]
	then
		eval "${2}=\"$volumes_on_ctlr\""
	fi

	[ "$volumes_present" = "no" ]
}

check_path_for_disk()
{
	path=$1
	last_path=0
	diskname=`vxdmpadm getdmpnode nodename=$path 2>/dev/null | tail +3 | \
					awk '{ print $1; }'`
	npaths_enabled=`vxdmpadm getdmpnode nodename=$path 2>/dev/null| tail +3 | \
					awk '{ print $5; }'`
	path_state=`vxdmpadm getsubpaths dmpnodename=$diskname 2>/dev/null| tail +3 | \
			grep "^$path" | awk '{ print $2; }'`

	if [ "$npaths_enabled" -eq 1 ] && [ "$path_state" = "ENABLED" ]
	then
		last_path=1
	fi

	if [ $# -gt 1 ]
	then
		eval "${2}=\"$diskname\""
	fi

	[ "$last_path" -eq 0 ]
}

# this function will determine if a dmnode is multipathed and return: 
#   If not mutlipathed:
#      dmpnodename
#   If multipathed:
#      the primary node name if enabled  
#      the secondary node name if the primary node is disabled 
#      the dmpnodename if both paths are disabled...

get_primary_path()
{

	path=$1

	ctlr=`expr $path  : \
		     "\(m\{0,1\}c[0-9][0-9]*\)t\{0,1\}[0-9]*d[0-9][0-9]*"`

	if  dogi_name_is_cntrlr $ctlr 	     
	    then 
	    dmpname=`vxdmpadm getdmpnode nodename=$path 2> /dev/null | tail +3 | \
					awk '{ print $1; }'`
	    eval "${2}=${dmpname}"
	else 
	    dmpname=$1
	fi 
	 
	primary_path=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | tail +3 | \
			grep  "PRIMARY" | head -1 | awk '{ print $1 ; }'`

	if   [ -n "$primary_path" ] 2> /dev/null
	    then
	    enabled=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | tail +3 | \
			grep  "PRIMARY" | head -1 | awk '{ print $2 ; }'`
	    if [ "$enabled" = "ENABLED" ]
		then 
	        active_path=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | \
				tail +3 | grep  "PRIMARY" | head -1 | \
				awk '{ print $1 ; }'`
		eval "${2}=${active_path}"
	    else 
		enabled=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | tail +3 | \
			grep  "SECONDARY" | head -1 | awk '{ print $2 ; }'`
		if [ "$enabled" = "ENABLED" ]
		    then 
		    active_path=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | \
					tail +3 | grep  "SECONDARY" | \
					head -1 | awk '{ print $1 ; }'`
		    eval "${2}=${active_path}"
		fi    
	    fi
	    
	else  
            primary_path=`vxdmpadm getsubpaths dmpnodename=$dmpname 2> /dev/null | \
				tail +3 | grep  "ENABLED" | head -1 | \
				awk '{ print $1 ; }'`		
	    if [ -n "${primary_path}" ]
	    then
		eval "${2}=${primary_path}"		
	    fi
   	fi
}


#  This function checks to see if a disk has at least one extra cylinder of
#	of reserved space.
is_extra_cylinder()
{

	if [ -z "$2" ]
	then 
	    SDG=rootdg
	else
	    SDG=$2
	fi

	SDANAME=`vxprint -g $SDG -F%daname $1`
	SDISK=`vxdmpadm getsubpaths dmpnodename=$SDANAME|grep ENABLED|head -1|awk '{print $1}'`
	SCYL_LEN=`vxparms -s /dev/rdsk/$SDISK|grep STAT_SECPERCYL|awk -F"=" '{print $2}'`
	SDISK_LEN=`vxparms -s /dev/rdsk/$SDISK|grep STAT_DISKNUMSEC|awk -F"=" '{print $2}'`
	SDA_TYPE=`vxprint -g $SDG -F "%da_type" $1` 
	if [ "$SDA_TYPE" != "sliced" ]
	then 
            return 1
        fi
        PUB_LEN=`vxprint -g $SDG -F "%publen" $1` 
        PRIV_LEN=`vxprint -g $SDG -F "%privlen" $1`
        VM_LEN=`expr $PUB_LEN + $PRIV_LEN`
        SLEN_DIFF=`expr $SDISK_LEN - $VM_LEN`
        if [ $SLEN_DIFF -lt $SCYL_LEN ] 
        then
            return 0 
        else
            return 1 
        fi

}

#   This function gets the privlen information from a source disk and
#   	re-initialize a target disk with the same privlen as the source
#	disk and without any reserved cylinder space.  
disk_reinit_no_cyl()
{
	TDANAME=`vxprint -g $3 -F%daname $1`
	TSD_NUM=`vxprint  -g $3 -F%sd_num $1`
	if [ $TSD_NUM -eq 0 ]
	then 
	#  We cannot do a vxdisksetup with the slice information.
	    TDISK=$TDANAME
	    dogi_slice_to_device $TDISK ITDISK
	    #  Get the privlen of the source disk 
	    SPRIV_LEN=`vxprint -g $3 -F%privlen $2`
	    # store the flags like spare,nohotuse,reserve.. if any on target disk
	    TFLAGS=`vxprint -g $3 -Qqd -F '%spare %nohotuse %reserve' $1`
	    TSFLAG=`echo $TFLAGS | awk '{print $1}'`
	    TNOHOTFLAG=`echo $TFLAGS | awk '{print $2}'`
	    TRESFLAG=`echo $TFLAGS | awk '{print $3}'`
	    vxdg -g $3 rmdisk $1
	    #  The target disk should has the same length as the source disk
	    vxdisksetup -if $ITDISK privlen=$SPRIV_LEN old_layout
	    vxdisk -f init $TDISK
	    vxdg -g $3 adddisk $1=$TDISK
            # restore all the flags saved before removal of the disk
	    vxedit -g $3 set spare=$TSFLAG nohotuse=$TNOHOTFLAG reserve=$TRESFLAG $1  2> /dev/null
	    return 0
	else
	    return 1
	fi
}

#
# List any Volume Manager disks in the enclosure found in a valid 
# disk group. If Volume Manager is already installed, retain the 
# in the configuration by removing them from the disk enclosure    
# list. Otherwise, prompt the user whether or not to retain these disks. 
# Disk not retained, will be eligible for re-initialization. 
# 
#  voladm_list_dg  enlr  disks_in_enclr 
# 
#  where: 
# 
#     enclr           = enclosure neame
#     disks_in_enclr = file containing list of disks in the enclosure
# 
voladm_list_dg()
{
 _enclr=$1
 _disks_in_enclr=$2

tempf1=/tmp/voladm_dgs.$$
tempf2=/tmp/voladm_dg.$$
tempf3=/tmp/voladm_dg_list.$$
tempf4=/tmp/voladm_dg_disks.$$
tempf5=/tmp/voladm_disks.$$

#  Create a list of disk_group/disk entries found in all enclosures 
vxdisk -q -o alldgs list | \
 awk '{ if ( $1 != "-" && $4 != "-" && $5 != "error" ) print $4 "  " $1}' |  \
 sed 's/)//' | 
 sed 's/(//'|
 sed 's/s2$//' > ${tempf1}

#  Create a list of disk_group/disk entries found in this enclosure 
if [ -s ${tempf1} ] ; then
	while read disk 
	do
    	   	grep " ${disk}\$" ${tempf1} >> ${tempf2}
	done <${_disks_in_enclr}
fi 

#  Create list of disk groups found in this enclosure
if [ -s ${tempf2} ] ; then
	cat ${tempf2} | awk '{ print $1 }' | sort | uniq > ${tempf3}
fi

#  Issue warning and list disks in valid disk groups.  If VxVM is not  
#  installed, allow user to retain the disk groups in the installation 
#  configuration.
#  
if [ -s ${tempf2} -a -s ${tempf3} ] ; then
	echo 
        export _enclr; egettxt  \
"WARNING: Disk array ${_enclr} contains valid disk groups and disks 
from a previous Volume Manager configuration:" vxvmshm:1797

	while read dg 
	do
        	voladm_list_display ${dg}":"
        	voladm_list_display `grep "^${dg} " ${tempf2} |
		  awk '{ print $2 }'` 
	done <${tempf3}

	cat ${tempf2} | awk '{ print $2 }' > ${tempf4} 

        retain="yes"
	if [ -f ${mkdbfile} ]
	then
		if not voladm_yorn -M vxvmshm:1798 \
"Would you like to retain these disks in the Volume Manager configuration?  
(If not, these disks will be available for re-initialization.)" n;
		then
			retain="no"
        	fi
	fi
	if [ "${retain}" = "yes" ]  
	then
		rdg=`grep "^rootdg" ${tempf3} | uniq -u`
		[ -n "$rdg" ] && retain_oldcfg="yes"
		echo
		while read disk 
		do
			grep -v "^${disk}\$" ${_disks_in_enclr} > ${tempf5}
			mv ${tempf5} ${_disks_in_enclr} 
			export disk; egettxt "<excluding disk ${disk}>" \
                                        vxvmshm:1795 >&2
			continue
		done <${tempf4}
		echo
	        egettxt  \
"These disks have been excluded and are not available for re-initialization" vxvmshm:1796
		voladm_continue
        fi
fi

if [ -f ${tempf1} ] ; then
        rm -f ${tempf1}
fi
if [ -f ${tempf2} ] ; then
        rm -f ${tempf2}
        rm -f ${tempf3}
        rm -f ${tempf4}
fi

}

. ${VOLADM_LIB:-/usr/lib/vxvm/voladm.d/lib}/vxadm_syslib.sh
