#
# NAME - util.sh
#
# DESCRIPTION
#	Utility routines for installation
#

# get_fs_info
#
# Get file system info for a path.  Determines file system, where
# mounted, and avail space.  Uses df to find this info.  Handles
# various forms of df output.
#
# INPUT/OUTPUT
#	IN: $1 - path to check
#	OUT: FS - name of file system
#	OUT: MNT - mount point of file system
#	OUT: AVAIL - avail space on file system in kbytes

get_fs_info()
{
    set `$df $1 | $sed '1d'`
    case $ARCH in
    SunOS)
        FS=$1
        MNT=$6
        AVAIL=$4
        ;;
    AIX)
        FS=$1
        MNT=$7
        AVAIL=$3
        ;;
    HP-UX)
        FS=$1
        MNT=$6
        AVAIL=$4
        ;;
    *)
        FS=$1
        MNT=$6
        AVAIL=$4
        ;;
    esac
}

# path_existing_part
#
# Given a path, return the portion of it which actually exists
#
# INPUT/OUTPUT
#	IN: $1 - path to be processed
#	OUT: RETURN - set to the existing portion

path_existing_part()
{
    pep_path=$1
    while test ! -d $pep_path ; do
	pep_path=`$expr match $pep_path '\(.*\)/'`
	if test "$pep_path" = "" ; then pep_path="/" ; fi
    done
    RETURN=$pep_path
}

# NAME - nfs_path_p
#
# DESCRIPTION
#	Given a path (which may or may not exist), determine
#	if it resides (or would reside) on an NFS file system.
#
# INPUT/OUTPUT
#	IN: $1 - path to be checked
#	OUT: RETURN - 0 if this is not an nfs filesystem; 1 if it is
#	OUT: FSHOST - set to machine which exports this nfs filesystem 

nfs_path_p()
{
    path_existing_part $1
    npp_path=$RETURN
    get_fs_info $npp_path
    FSHOST=`$expr match $FS '\(.*\):'`
#
#   CHANGED FOR HPUX-10.x
#
    FSHOST=""
    if test "$FSHOST" != "" ; then RETURN=1 ; else RETURN=0 ; fi
}

# create_path
#
# Attempts to create an entire path.  If necessary, intermediate
# directories are created.  Handles both local and remote case.
#
# INPUT/OUTPUT
#	IN: $1 - path to create
#	OUT: RETURN - 0 if successful, 1 if not

create_path()
{
    cp_path=$1
    nfs_path_p $cp_path
    while test ! -d $cp_path
    do
	cp_parent=$cp_path
	while test ! -d $cp_parent
	do
	    cp_child=`echo $cp_parent | $sed 's:.*/::'`
	    cp_parent=`echo $cp_parent | $sed 's:[^/]*$::'`
	    if test $cp_parent != "/" ; then
		cp_parent=`echo $cp_parent | $sed 's:/$::'`
	    fi
	done
	if test "$FSHOST" = "" ; then
#	    echo "$mkdir $cp_parent/$cp_child"
	    $mkdir $cp_parent/$cp_child > /dev/null 2>&1
	else
#	    echo "$rsh $FSHOST $mkdir $cp_parent/$cp_child"
	    $rsh $FSHOST "$mkdir $cp_parent/$cp_child" > /dev/null 2>&1
	fi
	if test ! -d $cp_parent/$cp_child ; then
	    RETURN=1
	    return
	fi
    done
    RETURN=0
}

# standard_steps
#
# This routine performs a standard set of steps to install a
# piece of software.  On entry, the following should have been
# set up by the caller:
#
#	PRODUCT		string which describes software
#	DEFINSTALLDIR	default install directory
#	DISKSPACE	size of software in MB
#	VERFILE		the software version file; used both to check
#			if software is already installed and version
#	VERSION		version of software being installed
#	TARFILE		the tarfile containing the software

standard_steps()
{
STEP=1
WRITEPERMS=do_we_have_write_permission.$$
while test $STEP != 99
do
    case $STEP in

	# Invoke the software prologue
	1)
	    software_prologue
	    STEP=2
	;;

	# See if software is installed in DEFINSTALLDIR prior
	# to asking user if it is installed somewhere else
	2)
	    if test -f $DEFINSTALLDIR/$VERFILE ; then
		INSTALLDIR=$DEFINSTALLDIR
		cat << EOM

$PRODUCT is currently installed
in $INSTALLDIR if you proceed, it will 
be overwritten.
EOM
	    QUESTION="Do you want to proceed"
	    DEFAULT=y
	    get_response ynq
	    echo
	    if test $RETURN = n ; then STEP=13 ; else STEP=4 ; fi
#		STEP=17
	    else
                STEP=4
#		STEP=3
	    fi
	;;

	# Ask user if software is installed somewhere
	3)
	    cat << EOM

The default location of $PRODUCT is

	$DEFINSTALLDIR

The software is not installed in this location.

If the software is currently installed somewhere else, you should
install this release of the software in the same place.
EOM
	    QUESTION="Has $PRODUCT been previously installed"
	    DEFAULT=n
	    get_response ynq
	    if test $RETURN = n ; then STEP=4 ; else STEP=23 ; fi
	;;

	# Ask user where they want to install software
	4)
	    QUESTION="Where should I install this software"
	    DEFAULT=$DEFINSTALLDIR
	    get_response
	    INSTALLDIR=$RETURN
            STEP=6
#	    STEP=5
	;;

	# See if software is installed in INSTALLDIR prior to
	# putting it there
	5)
	    if test -f $INSTALLDIR/$VERFILE
	    then
		cat << EOM

$PRODUCT is already installed
in $INSTALLDIR
EOM
		STEP=17
	    else
		STEP=6
	    fi
	;;

	# Check if INSTALLDIR file system has enough room.
	# Handle case where INSTALLDIR does not actually exist.
	6)
	    path_existing_part $INSTALLDIR
	    get_fs_info $RETURN
	    kbyte_check $INSTALLDIR $FS $AVAIL ${DISKSPACE}000
	    if test $RETURN -eq 1 ; then STEP=7 ; else STEP=12 ; fi
	;;

	# INSTALLDIR file system has enough room.  Does
	# INSTALLDIR exist?
	7)
	    if test -d $INSTALLDIR ; then STEP=8 ; else STEP=15 ; fi
	;;

	# INSTALLDIR exists and there is sufficient space to install.
	# Check if access is via NFS
	8)
	    nfs_path_p $INSTALLDIR
	    if test $RETURN -eq 1 ; then
		REMOTE=y ; STEP=8.1
		
	    else
		REMOTE=n ; STEP=9
	    fi
	;;

	# Access to INSTALLDIR via NFS.  Use of rsh necessary.  Inform
	# user and verify that we have permission.
	8.1)
	    cat << EOM

$INSTALLDIR is an NFS directory.
Since the installation is being run from $HOSTNAME as root,
a remote operation must be performed.  Verifying that a
remote operation will succeed...

EOM
	    check_remote_op $FSHOST
	    if test $RETURN -eq 0 ; then STEP=8.2 ; else STEP=8.3 ; fi
	;;

	# Necessary remote operations can be performed.  Inform user.
	8.2)
	    cat << EOM
Remote operations are permitted.
EOM
	    STEP=9
	;;

	# Inform user of no permission to perform remote operation
	8.3)
	    cat << EOM
Remote operations are not permitted.  Installation in
$INSTALLDIR can NOT be done from this host.
EOM
	    QUESTION=""
	    get_response
	    STEP=13
	;;

	# Verify write permission in INSTALLDIR
	9)
	    if test $REMOTE = n ; then
		$touch $INSTALLDIR/$WRITEPERMS > /dev/null 2>&1
		if test -f $INSTALLDIR/$WRITEPERMS ; then
		    $rm $INSTALLDIR/$WRITEPERMS
		    STEP=10
		else
		    STEP=9.1
		fi
	    else
		$rsh $FSHOST "$touch $INSTALLDIR/$WRITEPERMS" > /dev/null 2>&1
		if test -f $INSTALLDIR/$WRITEPERMS ; then
		    $rsh $FSHOST "$rm $INSTALLDIR/$WRITEPERMS"
		    STEP=10
		else
		    STEP=9.1
		fi
	    fi
	;;

	# No write permission in INSTALLDIR
	9.1)
	    cat << EOM

I can NOT create files in $INSTALLDIR.  You will
have to change the permissions for this directory or
choose a different location.
EOM
	    STEP=13
	;;

	# Confirm that extraction should proceed
	10)
	    cat << EOM

$PRODUCT files will now be extracted
into $INSTALLDIR
EOM
	    QUESTION="Do you want to proceed"
	    DEFAULT=y
	    get_response ynq
	    echo
	    if test $RETURN = n ; then STEP=13 ; else STEP=10.1 ; fi
	;;

	# Extract files into INSTALLDIR.  Use remote operation
	# if necessary.
	10.1)
	    cat << EOM
Extracting files ...
		
EOM

	    if test $REMOTE = n ; then
		TFLOC=`$pwd`
		( cd $INSTALLDIR ; $tar $TFLOC/$TARFILE )
	    else
		cat $TARFILE | $rsh $FSHOST "cd $INSTALLDIR ; $tar -"
	    fi
	    STEP=10.2
	;;

	# Files have been extracted.  Notify user
	10.2)
	    cat << EOM

The extraction is complete.
EOM
	    QUESTION=""
	    get_response ynq
	    STEP=11
	;;

	# Do software specific post-install steps
	11)
	    software_epilogue
	    STEP=99
	;;

	# INSTALLDIR hasn't enough room, inform user of required room
	12)
	    cat << EOM

$PRODUCT requires $DISKSPACE MB of disk space.
EOM
	    STEP=13
	;;

	# Determine if user wants to terminate installation
	13)
	    QUESTION="Do you want to terminate installation"
	    DEFAULT=n
	    get_response ynq
	    if test $RETURN = n
	    then
		STEP=4
	    else
		STEP=14
	    fi
	;;

	# User has terminated installation
	14)
	    cat << EOM

Installation has been CANCELLED.

$PRODUCT was NOT installed.

EOM
	    exit
	;;

	# INSTALLDIR does not exist.  Inform user and ask if
	# it should be created.
	15)
	    cat << EOM

$INSTALLDIR does not exist.
EOM
	    QUESTION="Should I create this directory"
	    DEFAULT=y
	    get_response ynq
	    if test $RETURN = n ; then STEP=13 ; else STEP=15.1 ; fi
	;;

	# User wants to create INSTALLDIR.
	15.1)
	    cat << EOM

OK, I will try to create $INSTALLDIR.
One moment please...

EOM
	    create_path $INSTALLDIR
	    if test $RETURN -eq 1 ; then STEP=15.5 ; else STEP=15.2 ; fi
	;;

	# INSTALLDIR was created.  Inform user.
	15.2)
	    cat << EOM
$INSTALLDIR has been created.
EOM
	    STEP=8
	;;

	# INSTALLDIR could not be created.  Inform user.
	15.5)
	    cat << EOM
The attempt to create $INSTALLDIR FAILED.
EOM
	    STEP=13
	;;

	# VERFILE exists, meaning that a version of PRODUCT
	# is already installed.  Get the version number out
	# of VERFILE and compare to version being installed
	17)
	    INSTVER=`cat $INSTALLDIR/$VERFILE`
	    cat << EOM

The installed version is $INSTVER
The version you are installing is $VERSION
EOM
	    if test $VERSION -gt $INSTVER ; then
		STEP=17.1
	    else
		STEP=17.2
	    fi
	;;

	# Installed version is older.  Inform user and
	# determine if user wants to upgrade.
	17.1)
	    cat << EOM

The currently installed software is OLDER than the
software you are installing.

I can upgrade the software, but this will ERASE the
currently installed software.

Before performing an upgrade, it is STRONGLY recommended
that you make a BACKUP copy of the currently installed software.
EOM
	    QUESTION="Do you want to upgrade now"
	    DEFAULT=n
	    get_response ynq
	    if test $RETURN = y ; then STEP=7 ; else STEP=13 ; fi
	;;

	# Installed version is newer.  Inform user and
	# skip remaining steps.
	17.2)
	    cat << EOM

The currently installed software is as new or newer
than the software you are installing.  No further
action is required.
EOM
	    QUESTION=
	    get_response
	    VERSION=$INSTVER
	    STEP=99
	;;

	# User has indicated that software is already installed.
	# Find out where.
	23)
	    echo
	    echo $n "Where is $PRODUCT" $c
	    QUESTION="installed"
	    DEFAULT=$DEFINSTALLDIR
	    get_response
	    INSTALLDIR=$RETURN
	    if test -f $INSTALLDIR/$VERFILE ; then
		STEP=17
	    else
		STEP=23.1
	    fi
	;;

	# User has indicated that software is already installed,
	# but it doesn't appear to be where they said it is.
	23.1)
	    cat << EOM

$PRODUCT does not
appear to be installed in $INSTALLDIR
Please check for typing errors.
EOM
	    STEP=3
	;;

    esac
done
}

# find out architecture type

. ./set_arch.sh

# find out proper way to print an echo that does not have an END-OF-LINE

${rm} -f /tmp/.echotmp
(echo "hi there\c" ; echo " ") > /tmp/.echotmp
if ${grep} c /tmp/.echotmp > /dev/null 2>&1 ; then
	n='-n'
	c=''
else
	n=''
	c='\c'
fi
${rm} -f /tmp/.echotmp


# get_response
# print a prompt message and show the user the default value.
# return the value enter, or a yes/no answer.
#
get_response()
{
  ynq=$1
  while [ 1 ] ; do
    RETURN=""
    if [ "$QUESTION" = "" ] ; then
        echo ""
        echo $n "Press <Enter> to Continue $c"
        read response
        return
    else
        echo ""
        echo $n "$QUESTION [${DEFAULT}]? ${c}"
        read response
	if [ $? -ne 0 ] ;  then
	     terminate
	fi
	if [ "${ynq}" = "ynq" ] ; then
            case "${response}" in
            [Yy]*) RETURN="y"
                   return
                   ;;
            [Nn]*) RETURN="n"
                   return
                   ;;
            [Qq]*) terminate
                   ;;
               \?) help_text
                   ;;
               "") RETURN="${DEFAULT}"
                   return
                   ;;
            esac
	else
            case "${response}" in
            \?) help_text
               ;;
            "") RETURN="${DEFAULT}"
                return
                ;;
            .*) echo ""
		echo "Please enter an absolute pathname."
                ;;
            ~*) echo ""
		echo "Please enter an absolute pathname."
                ;;
            *) RETURN="$response"
               return
               ;;
            esac
	fi
    fi
  done
}

# NAME - kbyte_check
#
# DESCRIPTION
#	Determine if there exists enough space on the specified filesystem
#	such that the request being made can fit.
#
# IN/OUT
#	IN: $1 - pathname
#	IN: $2 - filesystem which <pathname> resides
#	IN: $3 - amount of space on <filesystem> in kilobytes
#	IN: $4 - amount which is required in kilobytes
#	OUT: RETURN - 1 if enough space, 0 if not enough space
#
kbyte_check()
{
    cat << EOM

The pathname you have provided has the following characteristics:

    pathname = $1
    filesystem = $2
    available space (kbytes) = $3

EOM

    if [ $3 -ge $4 ] ; then
        echo "Space on '$2' is SUFFICIENT to"
	echo "install ${PRODUCT}."
        RETURN=1
    else
        echo "Space on '$2' is INSUFFICIENT to"
	echo "install ${PRODUCT}."
        RETURN=0
    fi
}

# check_remote_op
# returns 0 if remote oper is possible, returns 1 if "Permission denied"
# ie /.rhosts file is not setup right on the remote machine, returns 2
# if something else is wrong like remote m/c can't be reached
#
check_remote_op()
{
    ${rsh} $1 echo hello > /tmp/bar.$$ 2>&1
    output=`${sed} -n '/^hello$/p' /tmp/bar.$$`
    if [ "$output" = "hello" ] ; then
        RETURN=0
    else
        ${grep} "Permission denied" /tmp/bar.$$ 1>/dev/null 2>&1
        if [ "$?" = 0 ] ; then
            RETURN=1
        else
            RETURN=2
        fi
    fi
    ${rm} -f /tmp/bar.$$
}

# terminate
#
terminate()
{
    echo
    echo "Installation terminating."
    echo
    exit 0
}
