#!/bin/sh
#
# ident	"@(#)hads_utilities.sh	1.8	01/03/27 SMI"
#
# Library of shell routines for High Availability scripts.
# This is included at the top of EACH cluster monitor script.
#

loglevel()
{
# XXX
#set +x
    # Usage: loglevel level msg ...
    # Logs a message.  The level is in the syslog sense, and is passed
    # to the logger command.  
    LOGGER=logger
    UTIL_ha_slogtag=${HA_SLOGTAG:=hadf}
    UTIL_facility=${HA_SLOGFACILITY:=local7}
    UTIL_LEVEL=$1
    UTIL_LEVELUP="`echo $UTIL_LEVEL | tr "[a-z]" "[A-Z]"`"
    if [ "$UTIL_LEVELUP" = "ERR" ]; then
	UTIL_LEVELUP="ERROR"
    fi
    shift
    UTIL_msg="`echo \"$*\" | sed s/%/%%/g | tr '\012' ' '`"
    UTIL_msg="${UTIL_LEVELUP}: `basename $0`: $UTIL_msg"
    # The logger(1) program is written with a buffer size of 120 for
    # the non-switch arguments.  We used to be friendly to it by
    # truncating our message, roughly:
    #    MAXLOGGERARGS=110
    #    UTIL_msg="`echo $UTIL_msg | fdl_headc $MAXLOGGERARGS`"
    # However, truncating loses too much information.  Instead,
    # we now use fold(1).  Strangely, logger(1) uses a larger buffer
    # of size 200 when taking input from a file, so we use 180
    # for the fold width.  We also use sed to add a continuation
    # indicator to lines other than the first.
    UTIL_foldwidth=180
    echo "$UTIL_msg" | fold -w $UTIL_foldwidth | sed -e '2,$ s/^/'${UTIL_LEVELUP}': CONT:  /' | \
	$LOGGER -p ${UTIL_facility}.${UTIL_LEVEL} -t $UTIL_ha_slogtag
    if [ $? -ne 0 ]; then
	echo "$UTIL_ha_slogtag: $UTIL_msg" >/dev/console
	if [ $? -ne 0 ]; then
	    return 1
	fi
    fi
# XXX
#set -x
    return 0
}

#
# log_err_file filename     Copies the entire contents of filename to
#			    syslog as an "err" using our facility and tag.
log_err_file()
{
    if [ -z "$1" ]; then
        logerr "SUNWcluster.ha.hads.utilities.4001" `gettext "Bus error: log_err_file called with wrong argument"`
	return 0
    fi
    if [ ! -s $1 ]; then
	return 0
    fi
    LOGGER=logger
    UTIL_ha_slogtag=${HA_SLOGTAG:=hadf}
    UTIL_facility=${HA_SLOGFACILITY:=local7}
    sed -e 's/^/ERROR: /' < $1 | \
	$LOGGER -p ${UTIL_facility}.err -t $UTIL_ha_slogtag
    if [ $? -ne 0 ]; then
	cat $1 > /dev/console
	if [ $? -ne 0 ]; then
	    return 1
	fi
    fi
    return 0
}

logalert()
{
    msg_prefix=$1
    shift
    log_warning $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

logerr()
{
    msg_prefix=$1
    shift
    log_error $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

logwarning()
{
    msg_prefix=$1
    shift
    log_warning $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

logwarn()
{
    msg_prefix=$1
    shift
    log_warning $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

lognotice()
{
    msg_prefix=$1
    shift
    log_info $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

logdeb()
{
    msg_prefix=$1
    shift
    log_debug $msg_prefix "`get_logical_host`:`get_inst_name`: $*"
}

runerr()
{
    # Usage: runerr cmd args ...
    # Runs cmd with args, redirecting stderr to its own file.
    # If cmd exits zero, just return 0.
    # If cmd exits non-zero, we log an error, including the contents of
    # stderr, and exit 1 from the surrounding script. 
    UTIL_RUNERR_TMPERR=/var/opt/SUNWcluster/run/fdl_runerr.$$
    $* 2>$UTIL_RUNERR_TMPERR
    RC=$?
    if [ $RC -eq 0 ]; then
	rm -f $UTIL_RUNERR_TMPERR
	return 0;
    fi
    logerr "SUNWcluster.ha.hads.utilities.4002" "$* exitted non-zero ${RC}, stderr was: `cat $UTIL_RUNERR_TMPERR`"
    rm -f $UTIL_RUNERR_TMPERR
    exit 1
}



#
# list_priv_siblings
#
# Output a list of the private-link network names of our sibling hosts.
#
list_priv_siblings()
{
	myname=`uname -n`
	allhosts=`haget -f all_physical_hosts`
	if [ $? -eq 0 ]; then
		for i in $allhosts; do
			if [ "$myname" = "$i" ]; then
				continue
			fi
			plinks=`haget -f private_links -h $i`
		done
		set $plinks
		priv=$1
	else
		# HA not running, ask for private link name.
		false
		until [ $? -eq 0 ]; do
			echo_n `gettext "Please enter a private link name for the sibling server: "`
			read priv
			check_reply $priv 
		done
	fi

	echo $priv
}


#
# is_member()
# Usage: is_member element "$SET"
# The second argument should be quoted, as shown.
# Returns 0 for true, 1 for false, ala Unix programs.
#
is_member() {
	for ISM_X in $2 ; do
		if [ "$1" = "$ISM_X" ]; then
			return 0
		fi
	done
	return 1
}


#
# is_subset()
# Usage: is_subset "$FOO" "$BAR"
# The arguments should be quoted, as shown.
# The arguments may be empty lists provided that they are quoted.
# Returns 0 for true, 1 for false, ala Unix programs.
#
is_subset() {
	for ISS_X in $1 ; do
		is_member $ISS_X "$2"
		if [ $? -ne 0 ]; then
			return 1
		fi
	done
	return 0
}


#
# sets_equal()
# Usage:  sets_equal "$FOO" "$BAR"
# The arguments should be quoted, e.g., as shown.
# The arguments may be empty lists provided that they are quoted.
# Returns 0 for true, 1 for false, ala Unix programs.
#
sets_equal() {
	is_subset "$1" "$2"
	if [ $? -ne 0 ]; then
		return 1
	fi
	is_subset "$2" "$1"
	if [ $? -ne 0 ]; then
		return 1
	fi
	return 0
}


#
# set_diff()
# Usage: set_diff "$FOO" "$BAR"
# Computes the set difference: result = FOO - BAR
# The arguments should be quoted, as shown on the Usage line.
#
set_diff() {
	SETDIFF_RESULT=""
	SETDIFF_FIRST=1
	for SETDIFF_X in $1 ; do
		is_member $SETDIFF_X "$2"
		if [ $? -ne 0 ]; then
			if [ $SETDIFF_FIRST -eq 1 ]; then
				SETDIFF_RESULT="$SETDIFF_X"
				SETDIFF_FIRST=0
			else				
				SETDIFF_RESULT="$SETDIFF_RESULT $SETDIFF_X"
			fi
		fi
	done
	echo "$SETDIFF_RESULT"
	return 0
}


#
# cleanstring() -	cleanstring string
#
#	Print the string after cleaning it up for use as a parameter name.
#
cleanstring() {
	echo $* | sed 's/[^a-zA-Z0-9_]/_/g'
}

#
# count_items() -	count_items [items]
#
#	Print the number of items, or arguments
#
count_items() {
	echo $#
}

#
# is_numeric() -	is_numeric string
#
#	Returns zero if the string consists only of numbers
#
is_numeric() {
	echo $1 | egrep -e '^[0-9]+$' >/dev/null 2>&1
	return $?
}

#
# is_positive() -	is_positive string
#
#	Returns zero if the string is positive (0 returns true)
#
is_positive()
{
	echo $1 | egrep -e '^[0-9]+$' >/dev/null 2>&1
	return $?
}

#
# is_negative() -	is_negative string
#
#	Returns zero if the string is negative (-0 returns true)
#
is_negative()
{
	echo $1 | egrep -e '^-[0-9]+$' >/dev/null 2>&1
	return $?
}

#
# select_item item-# word-list
#
# Select word item-# from word-list.  Numbering begins from 1.
# item-# beyond end of list returns blank.  item-# 0 returns "sh".
# Negative item-# returns undefined results.  Use ksh to handle
# >1-digit item-#'s.
#
select_item()
{
#set -xv
	item=$1
	shift
	ksh -c "set - $* ; eval echo \${$item}"
}

#
# echo_n string
#
# (Conveniently) echo the string without an ending newline.
#
echo_n ()
{
	eval "/usr/bin/echo '$* \c'"
}

#
# y_or_n word
#
# Indicate affirmative (return 0) or negative (return 1) answer.
# XXX - no i18n.
#
y_or_n()
{
	[ "$1" = "" -o `expr "$1" : [yY].*` -gt 0 ] && return 0

	return 1
}

#
# check_reply string
#
# Prompt the user to verify the previously-entered string.
#
check_reply ()
{
#set -x
	echo `gettext "You entered:"`
	echo $*
	echo_n `gettext "Is this correct (y/n) [y]? "`
	read ans
	y_or_n $ans

	return $?
}

#
# getpids() -		getpids command [command_arg]
#
#	Print all pids for "command", optionally qualified with a "command_arg".#
getpids() 
{
        UTIL_command=`basename $1`			  # Binary basename
        UTIL_cmdarg=${2:+"`echo $2 | sed 's-/-\\\/-g'`"}  # Pre-escape /'s

	# Find instances of binary name plain or preceded by a pathname,
	# optionally followed immediately by the command-arg word.
        /usr/proc/bin/pflags /proc/* 2>/dev/null | \
                nawk 'BEGIN { FS=":" } \
/^[0-9]*:	'${UTIL_command}${UTIL_cmdarg:+" $UTIL_cmdarg"}'( |$)/ \
        { print $1 ; next } \
/^[0-9]*:	.*( |\/)'${UTIL_command}${UTIL_cmdarg:+" $UTIL_cmdarg"}'( |$)/ \
        { print $1 }'
 
        return 0
}

#
# establish_cleanup_handler()
#   Establishes trap handlers for calling a cleanup() function.
#
establish_cleanup_handler()
{
    ECH_TRAPSIGNALS="1 2 3 15"
    trap "cleanup ; trap 0 ; exit 1" $ECH_TRAPSIGNALS
}


#
# prog_not_exist_err progname 
#
#   Tests whether progname exists in our path and if not issues
# an error message and returns 1.  Otherwise, returns 0.
#
prog_not_exist_err()
{
    PNE_PATH="`echo $PATH | tr ':' ' '`"
    for PNE_CAND in $PNE_PATH ; do
	if [ -x ${PNE_CAND}/$1 ]; then
	    return 0
	fi
    done
    # This handles case where argument is a full path name:
    if [ -x /$1 ]; then
	return 0
    fi
    logerr "SUNWcluster.ha.hads.utilities.4003" `gettext "Program $1 does not exist in PATH. Possibly a data service did not get installed properly"`
    return 1
}    

#
# source_env_file environment-file
#
# Import the given environment file info into a running script.
# Return 1 on failure.
#
source_env_file ()
{
	#set -x
	NUSVC_ENV=$1
        tmp_env=/var/opt/SUNWcluster/run/svc_env.$$
        pse_stat=/var/opt/SUNWcluster/run/pse.$$ 
	echo " " > $pse_stat

	if [ -f $NUSVC_ENV ]; then
			# Save parser status and verify that parser output file
            # fully written by comparing output length to file length.
            #ccount=`{ ./parse_svc_env $NUSVC_ENV; echo $? 1> $pse_stat; } \
            #         | tee $tmp_env | wc -c`
            #echo $? > $pse_stat
            #check=`cat $pse_stat`
            #"$ccount" -ne "`wc -c < $tmp_env`" ];

            #logerr "./parse_svc_env $NUSVC_ENV > $tmp_env"
            #logerr "where = `pwd`"
            parse_svc_env $NUSVC_ENV > $tmp_env
            status=$?
            if [ $status -ne 0 -o \
				 ! -f $tmp_env ];
			then
				logerr "SUNWcluster.ha.hads.utilities.4004" `gettext "Failed to parse $NUSVC_ENV."`
				rm -f $tmp_env $pse_stat
				return 1
			fi

		# Evaluate the environment file directives.
		. $tmp_env || 
		  { logerr  "SUNWcluster.ha.hads.utilities.4011" `gettext "Failed to source $tmp_env."`; 
		    rm -f $tmp_env $pse_stat; 
		    return 1; }

		rm -f $tmp_env $pse_stat
	else
		logerr "SUNWcluster.ha.hads.utilities.4005" `gettext "Data Service configuration file $NUSVC_ENV is missing."`
		logerr "SUNWcluster.ha.hads.utilities.4006" `gettext "You must run hadsconfig to configure this data service."`

		return 1
	fi
}


# get_config_param <instance_name> <keyword>
#
# The routine assumes that the config file was already parsed
# and the _INST_* variables were set (typically the do_service script
# will call source_env_file().)
#
# The routine prints to the standard output the value of the requested
# keyword.
#
# If _INST_LIST is empty or the keyword was not set in the config file,
# it will silently print an empty string.
#

get_config_param ()
{

	inst_name=$1
	inst_key=$2
	val=
	n=0

	for i in $_INST_LIST; do
		n=`expr $n + 1`
		if [ "$i" = "$inst_name" ]; then
			eval "val=\$_INST_${n}_${inst_key}"
			break
		fi
	done

	echo $val
}

#
# Output a list of logical hosts which can be served by the given physical
# host and the data service is registered.
#
get_service_reg_lhosts()
{
  service=$1
  LHOSTS=$2

  REG_LHOSTS="`$HA_BIN/hareg -q $service -H`"

  # return error if service is not registered
  [ $? -eq 0 ] || return 1

  lhosts=""
  # check if service is registered in the whole cluster
  if [ -z "$REG_LHOSTS" ] ; then
        echo "$LHOSTS"
  else
       for lhost in $LHOSTS ; do
                for lh in $REG_LHOSTS ; do
                                if [ "$lhost" = "$lh" ]  ; then
                                        lhosts="$lhosts $lhost"
                                fi
                done
        done
        echo "$lhosts"
  fi
  echo
}

#
# get_remote_hostname - retrieve the remote host name        
#                       set REMOTEHOST to the other potential master host of
#			the logical host for failover
# 			REMOTHOST is used by subsequent hactl command.
get_remote_hostname ()
{
        lhost=$1
        LOCALHOST=`uname -n`
	PHYS_HOSTS=
	if [ "$lhost" ]; then
                PHYS_HOSTS=`haget -f physical_hosts -h $lhost`
        fi
        REMOTEHOST=
        for ph in $PHYS_HOSTS; do
                if [ "$ph" != "$LOCALHOST" ]; then
			REMOTEHOST=$ph
                fi
        done

}


# evaluate_probing - check to see if the specific data service need to 
#			start/stop the probing in this node
#
evaluate_probing ()
{
	service=$1
	lhost=$2
	thisnode=`uname -n`

	hareg -f service_is_on -s $service >/dev/null 2>&1
	if [ $? = 0 ]; then
		return 0
	fi

	reg_lhosts=`hareg -q $service -H`
	if [ "$reg_lhosts" != "" ]; then
		is_member $lhost "$reg_lhosts" || return 0
	else
		return 0
	fi

	# Make sure that the logical host is actually mastered someplace. Or else
	# the probes (particularly the remote probes) would confuse the lack of
	# $lhost in the MASTERED list with $lhost being mastered on some other node
	# For example: 
	# Example 1) When a logical host is in maintainence mode
	# Example 2) When the cluster is starting up and there are more then 1 logical hosts
	#	configured and the FIRST one to be started by the framework is NOT the
	#   logical host for this instance

	CUR_MASTER=`haget -f master -h $lhost`
	if [ -z "$CUR_MASTER" ] ; then
		return 0
	fi


	phys_hosts=`haget -f physical_hosts -h $lhost`
	if [ "$phys_hosts" ]; then
		is_member $thisnode "$phys_hosts" || return 0 
	else
		return 0
	fi

	return 1
}
# generic_svc action mastered-hosts non-mastered-hosts timeout [ no_idemp ]
#
# Called directly by a top level method.
# action can be: 'start', 'stop', 'start_net', stop_net', 'fm_init',
# 'fm_start', 'fm_stop', 'fm_check_this_host_ok', corresponding to each
# data service method.
# The mastered-hosts, non-mastered-hosts, and timeout args are
# pass-through from the framework.
# no_idemp is an optional flag that when set to 0 means that idempotency
# check is required before calling bundle_do_svc, and 1 means don't do
# the idempotency check (leting bundle_do_svc deal with that).
# no_idemp defaults to 0.
#

generic_svc ()
{
	# First, make global lists of master and non-mastered hosts
	MASTERED_LOGICAL_HOSTS="$2"
	NOT_MASTERED_LOGICAL_HOSTS="$3"

	# Replace comma with space to form an sh word list
	MASTERED_LOGICAL_HOSTS="`echo $MASTERED_LOGICAL_HOSTS | tr ',' ' '`"
	NOT_MASTERED_LOGICAL_HOSTS="`echo $NOT_MASTERED_LOGICAL_HOSTS | tr ',' ' '`"

	# Save timeout
	METHOD_TIMEOUT="$4"

	# get the no_idemp flag. If not set, default to 0
	NO_IDEMP=$5
	[ -z "$NO_IDEMP" ] && NO_IDEMP=0

	# Check whether to start this service here
	n=0
	for i in $_INST_LIST; do
		n=`expr $n + 1`

		# Set variables used per-instance lower down
		_INST_NAME=$i
		for keyword in $_INSTANCE_KWDS; do

			varname=_INST_${n}_${keyword}
			#
			# this line of code sets a variable _INST_<KEYWORD> to the
			# content of _INST_<n>_<KEYWORD> only if _INST_<n>_<KEYWORD>
			# was set by the parser. This is done so unset keywords
			# in the config file will not get a corresponding variable,
			# so it will be possible in the config file to set
			# a keyword to null string
			#
			eval "[ \"\${$varname-UnsetVar}\" = \"UnsetVar\" ] || \
				_INST_${keyword}=\$$varname "

		done

		# Set the count of probes for this instance; default 0
		# (PROBECOUNT is not a keyword).
		eval '_INST_PROBECOUNT=${_INST_'$n'_PROBECOUNT:=0}'
		pcount=$_INST_PROBECOUNT
		while [ $pcount -ne 0 ] ; do
			#
			# for each PROBE block, set only the variables that
			# where defined in the config file (and created
			# by the parser)
			#
			for keyword in $_PROBE_KWDS; do
			
				varname=_INST_${n}_PROBE_${pcount}_${keyword}
				eval "[ \"\${$varname-UnsetVar}\" = \"UnsetVar\" ] || \
					_INST_PROBE_${keyword}_${pcount}=\$$varname "

			done

			pcount=`expr $pcount - 1`
		done
			
		# Build private variable defns
		eval priv_vars='"$_INST_'$n'_PRIVATE_VARS"'
		for j in $priv_vars; do
			eval _INST_PRIV_$j='"$_INST_'$n'_PRIV_'$j'"'
		done

		# This is needed for logging
		set_inst_name ${_INST_NAME}

		# Apply action to the bundle
		ha_svc_bundle $1
	done
}


#
# ha_svc_bundle action
# 
# For each service in the bundle, execute action as directed by $1.
#
ha_svc_bundle ()
{
	# XXX Future: For bundles with defined PARTs, iteration over the parts
	# goes here; make instance name from $_INST_INSTANCE and PART name.  
	# See Aug 1996 @Home prototype.

	# Check idempotence here, if required
	case "$1" in
	  start | start_net)

		# Pause here to check mastery before checking service
		is_member $_INST_LOGICAL_HOST "$MASTERED_LOGICAL_HOSTS" || return 0

		if [ $NO_IDEMP -eq 0 ]; then
			# If service is running, do nothing
			ha_svc_not_running $_INST_NAME || return 0
		fi

		;;

	  stop | stop_net | abort | abort_net)

		# Pause here to check mastery before checking service
		is_member $_INST_LOGICAL_HOST "$NOT_MASTERED_LOGICAL_HOSTS" || return 0

		if [ $NO_IDEMP -eq 0 ]; then
			# If service not running, do nothing
			ha_svc_not_running $_INST_NAME && return 0
		fi
		;;

	  fm_stop)
		;;

	  fm_check_this_host_ok)
		;;

	  fm_start | fm_init)

		# check registration of this data service           
		evaluate_probing $_SERVICE $_INST_LOGICAL_HOST  
        	if [ $? -ne 1 ]; then
                #
                # service is not on, do nothing, return
                #
	        	return 0
       		fi

		#
		# Check if probe is already running. 
		# If so, then don't need to start it again.
		#
		ha_svc_not_running "${_INST_NAME}.probe" || return 0
		
		;;

	esac

	# Execute bundle_do_svc in a subshell, so any variable name 
	# collisions do not corrupt our internal variables.
	( bundle_do_svc $1 )
}


#
# ha_svc_not_running instance_name
#   - return 0 if instance specified by $1 is not running,
#     otherwise return 1.
#	Inverted logic derived from UNIX command exit codes.
#
ha_svc_not_running ()
{

	if [ -z "$1" ]; then
		logerr "SUNWcluster.ha.hads.utilities.4007" `gettext "Internal error in ha_svc_not_running"`
		exit 1
	fi
	pmfadm -l $1 >/dev/null 2>&1
	if [ $? -eq 0 ]; then
		return 1
	else
		return 0
	fi
}
 

#
# ha_svc_report action command status
#
# Test the given status from the attempt to start/stop command.
# Report any errors.  
#
ha_svc_report ()
{
	action_status=0
	action=$1
	cmd=$2
	actstat=$3
	# get stderr output from commands and log if appropriate
	if [ $actstat -ne 0 ]; then
		logerr "SUNWcluster.ha.hads.utilities.4008" `gettext "Error: $cmd didn't $action successfully."`
		err=`cat $errfile`
		rm -f $errfile 2>/dev/null
		lognotice "SUNWcluster.ha.hads.utilities.2001" "$err"
		action_status=1
	fi

	return $action_status
}


#
# set_owner pathname
# 
# Set the variable "prog_owner" with the owner of pathname, otherwise leave
# unset.
#
set_owner()
{
	if [ -x "$1" ]; then
		prog_owner=`ls -l "$1" | awk '{ print \$3 }'`

		# Bogus command or numeric (unknown) owner id?  
		if [ -z "$prog_owner" ] || 
		   expr "$prog_owner" : '[0-9]*' > /dev/null 2>&1; then
			unset prog_owner
			return 1
		fi
		
		return 0
	fi
	return 1
}

# 
# `start_as cmdline`
#
# Output the command line that will execute $0 under its owner's uid.  
# Do this by noting the owner of the program and su-ing to that owner 
# to execute the command.  Leave effective command path in $abs_cmd.
#
# Note: call this routine only for single commands; |, &, and ;
# command lines may not have the desired effect.  Caller should 
# evaluate the output of this command within `` in the calling script.
#
start_as()
{
	case "$1" in
	  /*|*/*)
		abs_cmd="$1"
		set_owner "$abs_cmd"
		;;
	  *)
		for i in `echo $PATH | sed 's/:/ /g'`; do
			abs_cmd="$i/$1"
			set_owner "$abs_cmd" && break
		done
		;;
	esac

	shift
#	echo "$abs_cmd $*"
	echo "/bin/su - '$prog_owner' -c '$abs_cmd $*'"
	return 0
}

############################################################
#
# replicate_file() filename
#	copies filename to all the sibling hosts
#	takes care to do it only over the private network.
#	Tries all the available private links untill successful.
#	Uses haget to find its siblings and their private network
#	address then uses rcp to copy the file. Avoids copying
#	to the local host (rcp may corrupt the file if this is done)
#
############################################################

replicate_file()
{
	IFLIST=` netstat -i | awk ' { print $4} ' | egrep -v "localhost|Address" `
	haget=` pkginfo -l SUNWhagen | awk ' /BASEDIR:/ { print $2 } ' `
	if [ ! "${haget}" ]; then
		logerr "SUNWcluster.ha.hads.utilities.4009" `gettext "Error: Could not locate SUNWhagen package"`
		return 1
	fi
	haget=${haget}/opt/SUNWhadf/bin/haget
	hostlist=` ${haget} -f all_physical_hosts `
	for physhost in $hostlist
	do
		islocal=false
		for index in ${IFLIST}
		do
			if [ ${index} = ${physhost} ]; then
				islocal=true
				break
			fi
		done
		if [ ${islocal} = "true" ]; then
			continue
		fi
		privlist=` ${haget} -f private_links -h ${physhost} `
		didcopy=false
		for privlink in ${privlist}
		do
			rcp -p $1 ${privlink}:$1
			if [ $? -eq 0 ]; then
				didcopy=true
				break
			fi
		done
		if [ ${didcopy} = "false" ]; then
			logerr "SUNWcluster.ha.hads.utilities.4010" `gettext "Warning: Failed to replicate file to host ${physhost}."`
			return 1
		fi
	done

	return 0
}

##############################################################################
#
#  set_inst_name  <instance name>
#
#       This function sets instance name in global variable
#       use 'get_inst_name' to obtain the value of instance
#
##############################################################################
set_inst_name ()
{
    MY_INST_NAME=$1
    set_logical_host `get_config_param ${MY_INST_NAME} LOGICAL_HOST`
}

##############################################################################
#
#  set_logical_host  <logical host name>
#
#       This function sets value in global variable
#       use get_my_logical_host to obtain the value of logical host
#
##############################################################################
set_logical_host()
{
    MY_LOGICAL_HOST=$1
}
##############################################################################
#
#  get_inst_name
#
#       This function returns instance name from global variable
#
##############################################################################
get_inst_name()
{
    echo ${MY_INST_NAME}
}
##############################################################################
#
#  get_logical_host
#
#       This function returns logical host name from global variable
#
##############################################################################
get_logical_host()
{
    echo ${MY_LOGICAL_HOST}
}
