#!/bin/sh
#------------------------------------------------------------------------------
# Apple Open Systems Software Installer
#
#	@(#)Revision is $Id: mae_installer,v 3.51 1997/04/09 01:33:03 mfc Exp $
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Copyright 1993-96 Apple Computer, Inc.
# All Rights Reserved.
#
# THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF APPLE COMPUTER, INC.
# The copyright notice above does not evidence any actual or
# intended publication of such source code.
#------------------------------------------------------------------------------

#------------------------------------------------------------------------------
# Save argc and arg1 as globals
#------------------------------------------------------------------------------
argc=$#                                 # Number of command line args
argv=${@:-''}                           # Arg list - NULL if not set

#------------------------------------------------------------------------------
# Make sure we can read and write the message passing file
#------------------------------------------------------------------------------
msg_file="/tmp/$$.MSG"                        # File used for message passing
/bin/cp /dev/null "$msg_file" 2> /dev/null
if [ ! -w "$msg_file" -o ! -r "$msg_file" ]; then
    echo "
    Cannot access message passing file [ $msg_file ]" >&2
    CleanUpExit 1
fi
/bin/rm -f "$msg_file"

#--------------------------------------------------------------------------
# Load terminal specific escape sequences into variables
#--------------------------------------------------------------------------
bld=`tput bold 2> /dev/null`            # Turn BOLD atribute ON 
rev=`tput rev 2> /dev/null`             # Turn REVERSE atribute ON 
off=`tput sgr0 2> /dev/null`            # Turn ALL atributes OFF 
clr_scrn=`tput clear 2>/dev/null`       # Clear screen 

#------------------------------------------------------------------------------
# Set umask and PATH (include cwd), and save the default IFS
# Make sure we have some idea of a HOME directory
#------------------------------------------------------------------------------
umask 0022
## DEBUG ## Make sure this path is still valid for all platforms ## DEBUG ##
PATH=/bin:/usr/bin:/usr/ucb:/etc:/usr/etc:/usr/5bin:.
S_IFS="$IFS"                            # Save a copy of a "good" IFS

if [ x"$HOME" != x ]; then              # HOME is set
    if [ ! -d "$HOME" ]; then           # However, it does not exist
        HOME=/tmp; export HOME
    fi
else                                    # HOME is not set
    HOME=/tmp; export HOME
fi

#------------------------------------------------------------------------------
# Save Location and Name information
#------------------------------------------------------------------------------
start_dir="`/bin/pwd`"                  # Directory where user was at launch
launch_dir="`dirname \"$0\"`"           # Directory where installer lives
if [ "$launch_dir" = '.' ]; then        # Make sure that it is an absolute path
    launch_dir="$start_dir"     
elif [ "`expr \"$launch_dir\"// : '\/.*'`" -eq 0 ]; then
    if [ "$start_dir" = '/' ]; then
        launch_dir="${start_dir}$launch_dir"  
    else
        launch_dir="${start_dir}/$launch_dir"  
    fi
fi
installer="`basename \"$0\"`"           # Name of install script 

#------------------------------------------------------------------------------
# Find the correct strings file 
#------------------------------------------------------------------------------
d_catalog_dir="C"                       ## DEFAULT ##
catalog_dir="${LC_ALL:-${LC_MESSAGES:-${LANG:-$d_catalog_dir}}}"

#------------------------------------------------------------------------------
## Add new supported locales here #LOCALIZE# ## DEBUG ##
#------------------------------------------------------------------------------
case $catalog_dir in
    C)       catalog_dir="C" ;;
    euc)     catalog_dir="EUC" ;;
    sjis)    catalog_dir="SJIS" ;;
esac

#------------------------------------------------------------------------------
## Locate Installer message strings
#------------------------------------------------------------------------------

if [ -r "${launch_dir}/LOCALE/${catalog_dir}/INSTALL.STR" ]; then
    installer_cat_dir="${launch_dir}/LOCALE/${catalog_dir}"
    . "${installer_cat_dir}/INSTALL.STR"          # Load strings
elif [ -r "${start_dir}/LOCALE/${catalog_dir}/INSTALL.STR" ]; then
    installer_cat_dir="${start_dir}/LOCALE/${catalog_dir}"
    . "${installer_cat_dir}/INSTALL.STR"          # Load strings
else
    echo "
    WARNING:
    Cannot locate message file for '$catalog_dir' locale." >&2

    ##
    ## If we were looking for the DEFAULT catalog then just bail here
    ##
    if [ "$catalog_dir" = "C" ]; then
        echo "
    WARNING:
    Cannot locate default message file.

    The Installation cannot continue until a valid message file is
    available in '${launch_dir}/LOCALE'.

    Try setting your locale using the LC_ALL, LC_MESSAGES, or LANG
    environment variables." >&2
    
        exit 5
    fi

    ##
    ## Otherwise look for default locale
    ##
    catalog_dir="$d_catalog_dir"            # Try default
    echo "
    Looking for default message file using '${catalog_dir}' locale." >&2

    if [ -r "${launch_dir}/LOCALE/${catalog_dir}/INSTALL.STR" ]; then
        installer_cat_dir="${launch_dir}/LOCALE/${catalog_dir}"
        . "${installer_cat_dir}/INSTALL.STR"      # Load strings
    elif [ -r "${start_dir}/LOCALE/${catalog_dir}/INSTALL.STR" ]; then
        installer_cat_dir="${start_dir}/LOCALE/${catalog_dir}"
        . "${installer_cat_dir}/INSTALL.STR"      # Load strings
    else
        echo "
    WARNING:
    Cannot locate default message file.

    The Installation cannot continue until a valid message file is
    available in '${launch_dir}/LOCALE'.

    Try setting your locale using the LC_ALL, LC_MESSAGES, or LANG
    environment variables." >&2

        exit 5
    fi
fi

unset LANG
unset LC_ALL
unset LC_MESSAGES


#------------------------------------------------------------------------------
# Save tty state 
#------------------------------------------------------------------------------
save_stty="`/bin/stty -g`"                        # Save stty settings
/bin/stty intr "^C"                               # Ensure that we know what sends SIGINT

#------------------------------------------------------------------------------
# Traps 
#------------------------------------------------------------------------------
trap 'CleanUpExit 3' 1 2 3 15                     # Clean up on signal

#------------------------------------------------------------------------------
# Clear Functions - we don't use absolute path names for these so...
#------------------------------------------------------------------------------
unset -f cd echo exit kill


###############################################################################
## Function definitions begin here                                           ##
###############################################################################

#------------------------------------------------------------------------------
#   Alert - display localized ERROR: message 
#------------------------------------------------------------------------------
Alert()
{
    if [ $# -ne 1 ]; then
        AssertErr "No args passed to Alert function."
    fi
    _alert_msg="$1"

    TopScreen "$hit_ret_banner_msg"
    echo 
    echo 
    echo "${bld}    ${error_msg}${off}$_alert_msg" 
    echo $off                                     # Just in case bold is left on
    Report "${error_msg} $_alert_msg"             # Save a copy in the report file
    WaitToContinue;
}

#------------------------------------------------------------------------------
#   Report - save message in report file
#------------------------------------------------------------------------------
Report()
{
    if [ "$report_file" = "/dev/null" ]; then
        return                                    # Report NOT!
    fi
    if [ $# -ne 1 ]; then
        AssertErr "No args passed to Report function."
    fi
    _report_msg="$1"

    echo '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -' >> "$report_file"
    echo "$_report_msg"                                                          >> "$report_file"
}

#------------------------------------------------------------------------------
# AskDir - Prompt for a directory name.  Validate before returning.
#------------------------------------------------------------------------------
AskDir()
{
    if [ $# -ne 4 ]; then
        AssertErr "Incorrect number of args passed to AskDir()."
    fi

    _ask_dir_prompt="$1"
    _ask_dir_help="$2"
    _ask_dir_pkg_name="$3"
    _ask_dir_write_req="$4"                       # Either 'W' or NULL
    eval _ask_dir_def_loc="\$d_${_ask_dir_pkg_name}_dir"
	
    while :; do
        TopScreen;                                # Clear screen and display banner
        echo "$_ask_dir_prompt" 
        if [ -z "$_ask_dir_def_loc" ]; then
            Prompt "    [$bld$no_default_msg$off] >>> "
        else
            Prompt "    [$default_equals_msg$bld$_ask_dir_def_loc$off] >>> "
        fi
        read _ask_dir_location
    
        ToLower _ask_dir_location                 # Convert to Lowercase
        case "$_ask_dir_location_lwr" in
            '')                  if [ -z "$_ask_dir_def_loc" ]; then
                                     Alert "$alert_no_default_msg"
                                     continue     # No default, ask again
                                 else 
                                     _ask_dir_location="$_ask_dir_def_loc" # Use default
                                 fi
                                 ;;
            "$help_msg"|\
            "$help_short_msg")   DoHelp "$_ask_dir_help"
                                 continue
                                 ;;
            "$quit_msg"|\
            "$quit_short_msg")   AskQuit "$yes_msg"
                                 continue
                                 ;;
            "$q_bang_msg")       CleanUpExit 0
                                 ;;
        esac

        # Run validation script
        "${source_dir}/${_ask_dir_pkg_name}.VAL" "$_ask_dir_location" "$msg_file" destination 2> /dev/null
        _ask_dir_pkg_result=$?
        if [ $_ask_dir_pkg_result -ne 0 ]; then   # Error
            if [ -r "$msg_file" -a -s "$msg_file" ]; then
                ShowErrMsg
            else
                Alert "$an_error_msg    (destination)"  # Generic msg
            fi
            return 1
        fi                            
        if BadDir "$_ask_dir_location" "$_ask_dir_pkg_name" "$_ask_dir_write_req"; then
            if [ "$_ask_dir_location" = "$_ask_dir_def_loc" ]; then
                _ask_dir_def_loc=                 # Default didn't work; reset
                eval ${_ask_dir_pkg_name}_dir=
                eval d_${_ask_dir_pkg_name}_dir=
            fi
            return 1                              # Bad dir, return ERROR
        fi
# mfc 970404 kludge
#	sigh. This should really be done in E1_MAE.VAL, but there are too many
#	dependencies, and that is called all over the place. I'm putting a
#	hard-coded kludge here to warn users that they are installing over
#	an existing MAE installation.
#
#	By the time you get here, everything seems OK. Check that the
#	specified dir is not a current mae install dir (for E1_MAE only)
#	and for installing only...
	if [ x"$_ask_dir_pkg_name" = x"E1_MAE" ]; then # do only for E1_MAE package
	    case "$state" in
		AskInstPkgs|\
		WherePutAll|\
		WherePutCmdLinePkgs)
		    # These are the 3 "we are installing something" modes
		    if [ -f "$_ask_dir_location/sys/Finder" -o \
			 -f "$_ask_dir_location/sys/System" -o \
			 -f "$_ask_dir_location/bin/mae" ]
		     then
		        # Warn user that s/he's installing over existing appledir
		        echo "$mae_existing"  > "$msg_file"
		        echo "\t($_ask_dir_location)"  >> "$msg_file"
			ShowErrMsg
		    fi
		;;
	    esac
	fi

        return 0                                  # Dir ok, return SUCCESS
    done
}

#------------------------------------------------------------------------------
# AskInstMode - Sets inst_mode
#------------------------------------------------------------------------------
AskInstMode()
{
    if [ -z "$d_inst_mode" ]; then
        AssertErr "No default installation mode in AskInstmode"
    fi
	
    while :; do
        TopScreen;
        case "$d_inst_mode" in
            EASY)   if [ "$e_pkg_cnt" -ge 1 ]; then
                        _inst_mode_prompt="$easy_msg" 
                    else
                        _inst_mode_prompt="$custom_msg"
                        d_inst_mode=CUSTOM
                    fi
                    ;;
            CUSTOM) _inst_mode_prompt="$custom_msg"
                    ;;
            REMOVE) if [ "$r_pkg_cnt" -ge 1 ]; then
                        _inst_mode_prompt="$remove_msg"
                    else
                        _inst_mode_prompt="$custom_msg"
                        d_inst_mode=CUSTOM
                    fi
                    ;;
            *)      AssertErr "Invalid d_inst_mode in AskInstMode." ;;
        esac

        echo "$instmode_prompt_msg" 
        echo
        Prompt "    [default=$bld$_inst_mode_prompt$off] >>> "
        read _inst_mode_selection
        ToLower _inst_mode_selection;
        case "$_inst_mode_selection_lwr" in
            '')                    inst_mode="$d_inst_mode"
                                   return
                                   ;;
            "$easy_short_msg"|\
            "$easy_msg")           if [ "$e_pkg_cnt" -eq 0 ]; then
                                       Alert "$no_easy_packages_msg"
                                       continue
                                   fi
                                   inst_mode="EASY"
                                   d_inst_mode="EASY"
                                   return
                                   ;;
            "$custom_short_msg"|\
            "$custom_msg")         inst_mode="CUSTOM"
                                   d_inst_mode="CUSTOM"
                                   return
                                   ;;
            "$remove_short_msg"|\
            "$remove_msg")         if [ "$r_pkg_cnt" -eq 0 ]; then
                                       Alert "$no_rem_packages_msg"
                                       continue
                                   fi
                                   inst_mode="REMOVE"
                                   d_inst_mode="REMOVE"
                                   return
                                   ;;
            "$quit_msg"|\
            "$quit_short_msg")     AskQuit "$yes_msg"
                                   continue
                                   ;;
            "$q_bang_msg")         CleanUpExit 0
                                   ;;
            "$help_msg"|\
            "$help_short_msg")     DoHelp "$instmode_help_msg"
                                   continue
                                   ;;
            *)                     Alert "$alert_not_valid_msg"
                                   continue 
                                   ;; 
        esac
    done
}

#------------------------------------------------------------------------------
#   AskQuit - either quit or continue with the install based on input
#------------------------------------------------------------------------------
AskQuit()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in AskQuit()."
    fi
    quit_default="$1"

    if Interactive; then
        in_quit=TRUE;                   # Prevent recursive calls to AskQuit
        AskYesNo "$ask_quit_msg" "$quit_help_msg" "$quit_default"
        in_quit=FALSE                   # Reset flag
        case "$reply" in
            "$yes_msg") CleanUpExit 0 ;; # Clean up and exit
            "$no_msg")  return 0 ;;     # Continue with installation
            *) AssertErr "Invalid return from AskYesNo() in AskQuit()" ;;
        esac
    else
         CleanUpExit 0                  # Just exit if NON-interactive
    fi
}   

#------------------------------------------------------------------------------
# FindSourceDir - Sets source_dir
#------------------------------------------------------------------------------
FindSourceDir()
{
    # Do a Pre-check to try to find the source dir
    if [ ${INSTALL_SRC:-NULL} != NULL ]; then     # Check environment variable 
        if [ -f "${INSTALL_SRC}/${o_s}.TOP" ]; then
            d_source_dir="$INSTALL_SRC"
            return 0                              # Happy, Happy, Joy, Joy
        elif [ -f "$INSTALL_SRC/${o_s}/${o_s}.TOP" ]; then
            d_source_dir="${INSTALL_SRC}/$o_s"
            return 0
        fi
    else                                          # Environment variable not set
        if [ -z "$d_source_dir" ]; then           # Should be set in InitVars
            d_source_dir="/cdrom"
        fi
        for check_point in "$launch_dir" "$d_source_dir" "$start_dir"; do
            if [ -f "${check_point}/${o_s}.TOP" ]; then
                d_source_dir="$check_point"
                return 0
            elif [ -f "${check_point}/${o_s}/${o_s}.TOP" ]; then
                d_source_dir="${check_point}/$o_s"
                return 0
            fi
        done
    fi

    Alert "$not_supported_os_msg"
    CleanUpExit 2
}

#------------------------------------------------------------------------------
# FindPackages - Locate and verify the packages to be installed
#------------------------------------------------------------------------------
FindPackages()
{
    source_dir="$d_source_dir"      # Use default (reserved for future use)
    pkg_cnt=0                       # Initialize global array subscript
    e_pkg_cnt=0                     # Initialize global array subscript
    r_pkg_cnt=0                     # Initialize global array subscript

    if [ -x "$source_dir" ]; then     # Exit if cd will fail
        cd "$source_dir"
    else
        Alert "$cannot_chdir_to_msg    [ $source_dir ].  $quitting_msg"
        CleanUpExit 2
    fi

    echo "$find_pkgs_msg"               # Let them know what we are doing
    #--------------------------------------------------------------------------
    # For each PKG file found, try to locate all of the other required files
    #--------------------------------------------------------------------------
    for _fnd_pkg_pkg in `/bin/ls *.PKG 2> /dev/null`; do
        if [ -z "$_fnd_pkg_pkg" ]; then
            Alert "$is_not_correct_dir_msg"
            CleanUpExit 2                         # No PKG files
        fi
        _fnd_pkg_pkg_name="`expr \"$_fnd_pkg_pkg\" : '\(.*\)\.PKG'`"    # Get package (file) name

        #----------------------------------------------------------------------
        # Look for the .STR (strings) file
        #----------------------------------------------------------------------
        if [ ! -r "LOCALE/$catalog_dir/${_fnd_pkg_pkg_name}.STR" ]; then
            continue                              # Get next package
        fi

        #----------------------------------------------------------------------
        # Look for the .VAL (validation) file
        #----------------------------------------------------------------------
        if [ ! -x "${_fnd_pkg_pkg_name}.VAL" ]; then
            continue                              # Get next package
        fi

        #----------------------------------------------------------------------
        # Run validation (preflight) script
        #----------------------------------------------------------------------
        "${source_dir}/${_fnd_pkg_pkg_name}.VAL" '' "$msg_file" preflight 2> /dev/null
        _fnd_pkg_result=$?
        if [ $_fnd_pkg_result -ne 0 ]; then       # Error
            if [ "$quiet" = TRUE -o $_fnd_pkg_result -eq 2 ]; then
                continue                          # Do not display message
            fi
            if [ -r "$msg_file" -a -s "$msg_file" ]; then
                ShowErrMsg
            else
                Alert "$an_error_msg    (preflight)"  # Generic msg
            fi
            echo "$find_pkgs_msg"                 # Let them know what we are doing
            continue                              # Get next package
        fi                            

        cd "$source_dir"                          # Just in case VAL script changed cwd

        #----------------------------------------------------------------------
        # Look for the .SIZ (size) file
        #----------------------------------------------------------------------
        if [ ! -r "${_fnd_pkg_pkg_name}.SIZ" ]; then
            continue                              # Get next package
        fi

        space_req="`/bin/cat ${_fnd_pkg_pkg_name}.SIZ`"       # Space requirements in KB

        #----------------------------------------------------------------------
        # Look for the .INS (installer) file
        #----------------------------------------------------------------------
        if [ ! -x "${_fnd_pkg_pkg_name}.INS" ]; then
            continue                              # Get next package
        fi

        #----------------------------------------------------------------------
        # Look for the .NAM (name) file
        #----------------------------------------------------------------------
        if [ ! -r "LOCALE/$catalog_dir/${_fnd_pkg_pkg_name}.NAM" ]; then
            continue                              # Get next package
        fi

        #----------------------------------------------------------------------
        # Make a note if package is part of 'Easy Install'
        #----------------------------------------------------------------------
        match_chars=`expr "$_fnd_pkg_pkg_name" : 'E.*'`  # Is an Easy Install package
        if [ "$match_chars" -ne 0 ]; then
            e_pkg_cnt=`expr $e_pkg_cnt + 1`   
            eval e_package_$e_pkg_cnt="$_fnd_pkg_pkg_name" 
        fi

        #----------------------------------------------------------------------
        # Make a note if package can be listed under 'Remove' option
        #----------------------------------------------------------------------
        "${source_dir}/${_fnd_pkg_pkg_name}.VAL" '' /dev/null ask_rem 2> /dev/null

        if [ $? -eq 0 ]; then
            r_pkg_cnt=`expr $r_pkg_cnt + 1`
            eval r_package_$r_pkg_cnt="$_fnd_pkg_pkg_name"
        fi

        #----------------------------------------------------------------------
        # Make a note if package install or remove requires system reboot
        #----------------------------------------------------------------------
        "${source_dir}/${_fnd_pkg_pkg_name}.VAL" '' /dev/null ask_reboot 2> /dev/null

        if [ $? -eq 0 ]; then
            eval reboot_${_fnd_pkg_pkg_name}="TRUE" # Requires reboot
        else
            eval reboot_${_fnd_pkg_pkg_name}="FALSE" # Does not require reboot
        fi

        #----------------------------------------------------------------------
        # Load all other package information into arrays
        #----------------------------------------------------------------------
        pkg_cnt=`expr $pkg_cnt + 1`               # Increment package count
        eval package_$pkg_cnt="$_fnd_pkg_pkg_name" # Name saved in array of names
        eval ${_fnd_pkg_pkg_name}_size=$space_req # Space requirements
        eval inst_$_fnd_pkg_pkg_name=''           # Initialize Only
    done

    #--------------------------------------------------------------------------
    # If no packages are found then we have to exit
    #--------------------------------------------------------------------------
    if [ $pkg_cnt -eq 0 ]; then        
        Alert "$is_not_correct_dir_msg"           # No packages found!
        CleanUpExit 2
    fi
    if [ "$e_pkg_cnt" -eq 0 -a "$inst_mode" = EASY ]; then
        Alert "$no_easy_packages_msg"
        CleanUpExit 0
    fi
    if [ "$r_pkg_cnt" -eq 0 -a "$inst_mode" = REMOVE ]; then
        Alert "$no_rem_packages_msg"
        CleanUpExit 0
    fi
}

#------------------------------------------------------------------------------
# AskInstPkgs - Ask user if they want to install each package in turn
#------------------------------------------------------------------------------
AskInstPkgs()
{
    _ask_inst_cnt=1
    while [ $_ask_inst_cnt -le $pkg_cnt ]; do
        default_destination=''                       
        eval _ask_inst_pkg_name="\$package_$_ask_inst_cnt"

        #----------------------------------------------------------------------
        # Default is YES for Easy packages and NO for other packages.
        #----------------------------------------------------------------------
        match_chars=`expr "$_ask_inst_pkg_name" : 'E.*'`  # Is an Easy Install package
        if [ "$match_chars" -ne 0 ]; then
            eval _ask_inst_default="\${inst_$_ask_inst_pkg_name:-$yes_msg}" # Easy
        else
            eval _ask_inst_default="\${inst_$_ask_inst_pkg_name:-$no_msg}"  # Custom
        fi

        . "$source_dir/LOCALE/$catalog_dir/${_ask_inst_pkg_name}.STR"
	default_destination="${d_dest_dir}/${relative_destination}"

        #----------------------------------------------------------------------
        # AskYesNo returns "yes" or "no" in $reply
        #----------------------------------------------------------------------
        AskYesNo "$install_prompt_msg" "$install_help_msg" "$_ask_inst_default"

        eval inst_$_ask_inst_pkg_name="$reply" 
        
        if [ "$reply" = "$yes_msg" ]; then
            "${source_dir}/${_ask_inst_pkg_name}.VAL" '' /dev/null ask_dest >/dev/null 2>&1
            ask_dest=$?
            if [ "$ask_dest" -ne 0 ]; then # Dont ask for destination
                #--------------------------------------------------------------
                # Validate destination
                #--------------------------------------------------------------
                if [ -z "$default_destination" ]; then
                    AssertErr "default_destination not set in AskInstPkgs"
                fi
                _dest_dir="`eval echo $default_destination`"
                eval d_${_ask_inst_pkg_name}_dir="$_dest_dir"

                "${source_dir}/${_ask_inst_pkg_name}.VAL" "`eval echo \\\$d_${_ask_inst_pkg_name}_dir`" "$msg_file" destination 2>> "$report_file"
                _ask_inst_result=$?
                if [ $_ask_inst_result -ne 0 ]; then    # Error
                    if [ -r "$msg_file" -a -s "$msg_file" ]; then
                        ShowErrMsg
                    else
                        Alert "$an_error_msg    (destination)"  # Generic msg
                    fi
                    continue
		fi
		if [ "$ask_dest" -ne 2 ] ; then 
		  if BadDir "`eval echo \\\$d_${_ask_inst_pkg_name}_dir`" "$_ask_inst_pkg_name" W; then
		    continue
		  fi
		fi
            else
                SetTopDir
                eval d_${_ask_inst_pkg_name}_dir=\${d_${_ask_inst_pkg_name}_dir:-\"$d_dest_dir\"}
                #--------------------------------------------------------------
                # The AskDir function will modify the value of <_ask_inst_pkg_name>_dir. 
                #--------------------------------------------------------------
                AskDir "$destination_prompt_msg" "$destination_help_msg" "$_ask_inst_pkg_name" W 
                if [ $? -ne 0 ]; then                 # Bad Dir - go back
                    continue                          # Ask if they want to install
                fi
                eval d_dest_dir=\$${_ask_inst_pkg_name}_dir   # For SetTopDir
		if [ "$_ask_inst_pkg_name" = "E1_MAE" ]; then
                	master_d_dest_dir="$d_dest_dir" # Set once and save
		fi
		d_dest_dir=${master_d_dest_dir}
            fi
        fi
        _ask_inst_cnt=`expr $_ask_inst_cnt + 1`
    done
        
    return
}

#------------------------------------------------------------------------------
# ListRemPkgs - List all of the packages that the installer knows how to remove
#------------------------------------------------------------------------------
ListRemPkgs()
{
    if [ "$r_pkg_cnt" -eq 0 ]; then
        AssertErr "No removable packages in ListRemPkgs"
    fi

    TopScreen "$hit_ret_banner_msg"               # Clear screen and display header
    echo "$can_remove_these_msg"
    _list_rem_cnt=1
    while [ $_list_rem_cnt -le $r_pkg_cnt ]; do
        eval _list_rem_pkg_name="\$r_package_$_list_rem_cnt"
        echo "        `/bin/cat \"$source_dir/LOCALE/$catalog_dir/${_list_rem_pkg_name}.NAM\"`"
        _list_rem_cnt=`expr $_list_rem_cnt + 1`
    done
    echo
    WaitToContinue
}
#------------------------------------------------------------------------------
# AskRemPkgs - Ask user if they want to remove each package in turn
#------------------------------------------------------------------------------
AskRemPkgs()
{
    if [ "$r_pkg_cnt" -eq 0 ]; then
        AssertErr "No removable packages in AskRemPkgs"
    fi

    ListRemPkgs     # List all of the packages that the installer knows how to remove

    _ask_rem_cnt=1
    while [ $_ask_rem_cnt -le $r_pkg_cnt ]; do
        eval _ask_rem_pkg_name="\$r_package_$_ask_rem_cnt"
        . "$source_dir/LOCALE/$catalog_dir/${_ask_rem_pkg_name}.STR"
	default_destination="${d_dest_dir}/${relative_destination}"
        eval _ask_rem_default="\${rem_$_ask_rem_pkg_name:-$no_msg}" 
        #------------------------------------------------------------------
        # AskYesNo returns "yes" or "no" in $reply
        #------------------------------------------------------------------
        AskYesNo "$remove_prompt_msg" "$remove_help_msg" "$_ask_rem_default"
        eval rem_$_ask_rem_pkg_name="$reply" 
      
        if [ "$reply" = "$yes_msg" ]; then
            "${source_dir}/${_ask_rem_pkg_name}.VAL" '' /dev/null ask_dest >/dev/null 2>&1
            ask_dest=$?
            if [ "$ask_dest" -eq 0 ]; then
                SetTopDir
                eval d_${_ask_rem_pkg_name}_dir=\${d_${_ask_rem_pkg_name}_dir:-\"$d_dest_dir\"}
                #----------------------------------------------------------
                # The AskDir function will modify the value of <_ask_rem_pkg_name>_dir. 
                #----------------------------------------------------------
                AskDir "$where_is_prompt_msg" "$where_is_help_msg" "$_ask_rem_pkg_name" ''
                if [ $? -ne 0 ]; then
                    continue                  # Ask (again) if they want to remove pkg
                fi
                eval d_dest_dir=\$${_ask_rem_pkg_name}_dir   # For SetTopDir
                master_d_dest_dir="${master_d_dest_dir:-$d_dest_dir}" # Set once and save
            fi
        fi
        _ask_rem_cnt=`expr $_ask_rem_cnt + 1`
    done
        
    return
}

#------------------------------------------------------------------------------
# RemCmdLinePkgs - 
#------------------------------------------------------------------------------
RemCmdLinePkgs()
{
    if [ "$r_pkg_cnt" -eq 0 ]; then
        AssertErr "No removable packages in RemCmdLinePkgs"
    fi
    _ask_rem_cnt=1
    while [ $_ask_rem_cnt -le $r_pkg_cnt ]; do
        eval _ask_rem_pkg_name="\$r_package_$_ask_rem_cnt"
        . "$source_dir/LOCALE/$catalog_dir/${_ask_rem_pkg_name}.STR"
	default_destination="${d_dest_dir}/${relative_destination}"
        eval remove_it="\$rem_$_ask_rem_pkg_name"
      
        if [ "$remove_it" = "$yes_msg" ]; then
            "${source_dir}/${_ask_rem_pkg_name}.VAL" '' /dev/null ask_dest >/dev/null 2>&1
            ask_dest=$?
            if [ "$ask_dest" -eq 0 ]; then
                SetTopDir
                eval d_${_ask_rem_pkg_name}_dir=\${d_${_ask_rem_pkg_name}_dir:-\"$d_dest_dir\"}
                #----------------------------------------------------------
                # The AskDir function will modify the value of <_ask_rem_pkg_name>_dir. 
                #----------------------------------------------------------
                AskDir "$where_is_prompt_msg" "$where_is_help_msg" "$_ask_rem_pkg_name" ''
                if [ $? -ne 0 ]; then
                    continue                  # Ask (again) if they want to remove pkg
                fi
                eval d_dest_dir=\$${_ask_rem_pkg_name}_dir   # For SetTopDir
                master_d_dest_dir="${master_d_dest_dir:-$d_dest_dir}" # Set once and save
            fi
        fi
        _ask_rem_cnt=`expr $_ask_rem_cnt + 1`
    done
    if [ "$quiet" = TRUE ]; then
	interactive=FALSE
    fi

    return
}

#------------------------------------------------------------------------------
#   AskYesNo - keep asking a yes/no question till user answers yes/no
#   $3 is default, assumes help will be provided by all calling routines
#------------------------------------------------------------------------------
AskYesNo()
{
    if [ $# -ne 3 ]; then
        AssertErr "Incorrect argument count in AskYesNo()."
    fi
    _ask_y_n_prompt="$1"                         # Local $prompt
    _ask_y_n_help="$2"                           # Local $help
    _ask_y_n_default="$3"                        # Local $default (yes/no)
    if [ "$_ask_y_n_default" != "$yes_msg" -a "$_ask_y_n_default" != "$no_msg" ]; then
        AssertErr "Problem with arguments passed to AskYesNo()."
    fi

    while :; do
        TopScreen;
        echo "$_ask_y_n_prompt"  
        Prompt "    [$default_equals_msg$bld$_ask_y_n_default$off] >>> "
        read _ask_y_n_answer
        ToLower _ask_y_n_answer                  # Convert to Lowercase
   
        case "$_ask_y_n_answer_lwr" in
        '')                  reply=$_ask_y_n_default    # Use default
                             return 0
                             ;;
        "$yes_msg"|\
        "$yes_short_msg")    reply="$yes_msg"
                             return
                             ;;
        "$no_msg"|\
        "$no_short_msg")     reply="$no_msg"
                             return
                             ;;
        "$help_msg"|\
        "$help_short_msg")   DoHelp "$_ask_y_n_help"
                             continue
                             ;;
        "$quit_msg"|\
        "$quit_short_msg")   if [ "$in_quit" = "TRUE" ]; then
                                 CleanUpExit 0    # Go to exit
                             fi
                              save_ask_y_n_prompt="$_ask_y_n_prompt"
                              save_ask_y_n_help="$_ask_y_n_help"
                              save_ask_y_n_default="$_ask_y_n_default"
                             AskQuit "$yes_msg"   # Quit (or return here)
                              _ask_y_n_prompt="$save_ask_y_n_prompt"
                              _ask_y_n_help="$save_ask_y_n_help"
                              _ask_y_n_default="$save_ask_y_n_default"
                             continue             # Ask again
                             ;;
         "$q_bang_msg")      CleanUpExit 0
                             ;;
        *)   Alert "$alert_not_valid_msg" ;;
       esac
    done
}

#------------------------------------------------------------------------------
# AssertErr - Display Alert and exit
#------------------------------------------------------------------------------
AssertErr()
{
    if [ $# -lt 1 ]; then
        _assert_err="No information available"
    else
        _assert_err="$1"
    fi

    Alert "$assert_msg

    [ $_assert_err ]"

    CleanUpExit 1                               
}

#------------------------------------------------------------------------------
# BadDir - Check directory accessability, (and writablity) ( return 0 if bad)
#------------------------------------------------------------------------------
BadDir()
{
    # Usage: BadDir <dir_name> <pkg_name>  W | ''

    if [ $# -ne 3 -o "$3" != W -a "$3" != '' ]; then
        AssertErr "Problem with argument list in BadDir()." 
    fi

    _bad_dir_dir="$1"
    _bad_dir_pkg_name="$2"
    if [ "$3" = W ]; then
        _need_write_access=TRUE
    else
        _need_write_access=FALSE
    fi
    
    echo "$checking_directory_msg"                # This takes a bit of time - warn them

    #--------------------------------------------------------------------------
    # Prevent user from getting the shell to do nasty things here.
    #--------------------------------------------------------------------------
    _bad_dir_dir="`echo "$_bad_dir_dir" | cut -d';' -f1`"           # Remove any junk after a ';'
    _bad_dir_dir="`echo "$_bad_dir_dir" | cut -d'|' -f1`"           # Remove any junk after a '|'

    #--------------------------------------------------------------------------
    # Use shell to expand path.  Allows for $HOME stuff
    #--------------------------------------------------------------------------
    _bad_dir_dir="`eval echo \"$_bad_dir_dir\"`"  # Expand path
    
    if [ $? -ne 0 -o "`expr \"$_bad_dir_dir\"// : '.*~.*'`" -ne 0 ]; then
        Alert "$badly_formed_path_msg" 
        return 0                                  # Path must contain bad chars
    fi

    if [ "`expr \"$_bad_dir_dir\"// : '\/.*'`" -eq 0 ]; then
        _bad_dir_dir="$start_dir/$_bad_dir_dir"   # Prepend path if not absolute
    fi

    if [ ! -d "$_bad_dir_dir" ]; then
        if [ "$_need_write_access" = TRUE ]; then # Write access required
            if MakeDir "$_bad_dir_dir"; then      # Try to create dir
                :                                 # Remember to remove this dir later
            else                                  
                Alert "$cannot_create_dir_msg    [$_bad_dir_dir]." 
                return 0                          # Return TRUE (is bad dir)
            fi
        else                                      # We should not create dir
            Alert "$dir_not_exist_msg    [$_bad_dir_dir]."    
            return 0                              # Return TRUE (is bad dir)
        fi
    fi                                            # Dir must exist

    chmod u+rwx "$_bad_dir_dir" 2> /dev/null      # Ensure full access to dir

    #------------------------------------------------------------------------
    # If destination directory is not accessable then display alert and return
    #------------------------------------------------------------------------
    if [ ! -x "$_bad_dir_dir" ]; then
        Alert "$cannot_chdir_to_msg    [$_bad_dir_dir]"       # Cannot chdir to directory
        return 0                                  # Return TRUE (is bad dir)
    else
        cd "$_bad_dir_dir" 2> /dev/null           
        _bad_dir_dir="`/bin/pwd`"                 # Get REAL path (resolves sym-links, etc.)
    fi
    if [ ! -r "$_bad_dir_dir" ]; then
        Alert "$cannot_read_from_msg    [$_bad_dir_dir]"      # Cannot read from directory
        return 0                                  # Return TRUE (is bad dir)
    fi

    #--------------------------------------------------------------------------
    # Must be fully expanded before calling SpaceCheck
    #--------------------------------------------------------------------------
    eval ${_bad_dir_pkg_name}_dir=\"$_bad_dir_dir\"                 
    eval d_${_bad_dir_pkg_name}_dir=\"$_bad_dir_dir\"  
    
    #------------------------------------------------------------------------
    # If two args then test for writability and free space
    #------------------------------------------------------------------------
    if [ "$_need_write_access" = TRUE ]; then     # Write test request
        if [ -w "$_bad_dir_dir" ]; then           # If we can write to the dir
            $mkdir_cmd "$mkdir_opt" "${_bad_dir_dir}/$$" 2> /dev/null  
            if [ -d "${_bad_dir_dir}/$$" ]; then  # Double Check!! (r/o NFS mounts)
                /bin/rmdir "${_bad_dir_dir}/$$" 2> /dev/null        # Clean up tmp dir
            else                                  # Don't be fooled by CD-ROMs
                Alert "$cannot_write_to_msg    [$_bad_dir_dir]"   # Cannot write to directory
                return 0                          # Return TRUE (is bad dir) 
            fi
        else
            Alert "$cannot_write_to_msg    [$_bad_dir_dir]"   # Cannot write to directory
            return 0                              # Return TRUE (is bad dir)
        fi
        #--------------------------------------------------------------------
        # Check for free space on volume
        #--------------------------------------------------------------------
        if SpaceCheck "$_bad_dir_dir" "$_bad_dir_pkg_name"; then
            if [ "${we_made_dir:-FALSE}" = TRUE ]; then    # Only if we made the dir
                cd "$start_dir"                   # In case we're in the dir to be removed
                /bin/rmdir "$_bad_dir_dir" 2> /dev/null
            fi
            return 1                              # Return FALSE (not bad dir)
        else
            if [ "${we_made_dir:-FALSE}" = TRUE ]; then    # Only if we made the dir
                cd "$start_dir"                   # In case we're in the dir to be removed
                /bin/rmdir "$_bad_dir_dir" 2> /dev/null
            fi
            return 0                              # Return TRUE (is bad dir)
        fi
    fi

    return 1                                      # Return FALSE (not bad dir)
}

#------------------------------------------------------------------------------
#   CleanUpExit -  Clean up and partially installed files then call exit
#   with the status in arg[1].
#------------------------------------------------------------------------------
CleanUpExit()
{
trap 'echo $done_msg; exit 0' 1 2 3 15            # Just exit if we get another signal
        #---------------------------------------------------#
        #   exit status 0 is normal                         #
        #   exit status 1 is ASSERTION ERROR                #
        #   exit status 2 is I/O ERROR, parameter ERROR     #
        #   exit status 3 is SIGNAL                         #
        #---------------------------------------------------#

    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in CleanUpExit()."
    fi
    _exit_status=$1

    echo "$off"                                   # Undo any screen effects
    /bin/stty "$save_stty"                        # Reset to original settings
    /bin/rm -f "$msg_file"                        # Remove temp file for this session

    if [ "$_exit_status" -eq 3 ]; then
        Report "Terminated by signal"
    fi

    #--------------------------------------------------------------------------
    # Tell them about the report file, if one exists
    #--------------------------------------------------------------------------
    if [ "$report_file" != "/dev/null" -a -s "$report_file" -a $_exit_status -ne 99 ]; then
        echo "$read_the_report_msg [ $report_file ]"
        echo; echo
    fi

    #--------------------------------------------------------------------------
    # No cleanup required if status 0 
    #--------------------------------------------------------------------------
    if [ $_exit_status -eq 0 ]; then
        exit 
    fi

    if [ $_exit_status -ne 99 ]; then 
        #----------------------------------------------------------------------
        # Set a signal handler to protect us and then kill everyone in our proc grp
        # (HP-UX 9.01 does not support killing negative PIDs; can you say BUG!))
        #----------------------------------------------------------------------
        trap 'CleanUpExit 99' 15                  # Run this func again on SIGTERM
        kill -15 0  > /dev/null 2>&1              # Send SIGTERM to init (sent to all in proc grp)
        # kill -15 -$$ > /dev/null 2>&1             # Kill the currently running install script
    fi

    #--------------------------------------------------------------------------
    # Otherwise clean up any installed files
    #--------------------------------------------------------------------------
    Prompt "$cleaning_up_msg"                   

    #--------------------------------------------------------------------------
    # Make sure those pesky kids are dead
    #--------------------------------------------------------------------------
    wait $! > /dev/null 2>&1

    if [ "$inst_mode" != REMOVE -a ${_do_inst_status:-0} -eq 99 ]; then
        "${source_dir}/${_do_inst_pkg_name}.INS" "$_do_inst_destination" "$msg_file" cleanup 2> /dev/null
        if [ $? -ne 0 ]; then
            if [ -r "$msg_file" -a -s "$msg_file" ]; then
                ShowErrMsg
            fi
        fi
    fi
    #--------------------------------------------------------------------------
    # Add any new cleanup code here.     
    #--------------------------------------------------------------------------

    echo "$done_msg"               
    exit $_exit_status
}

#------------------------------------------------------------------------------
# Confirm - Return TRUE (0) to continue; FALSE (1) to make changes
#------------------------------------------------------------------------------
Confirm()
{
    Interactive || return 0                      # Don't do this if non-interactive

    if [ "$inst_mode" != EASY -a "$inst_mode" != CUSTOM -a "$inst_mode" != REMOVE ]; then
         AssertErr "Invalid installation mode in Confirm()."
    fi

    #--------------------------------------------------------------------------
    # Check for No Packages Selected
    #--------------------------------------------------------------------------
    _confirm_cnt=1
    while [ $_confirm_cnt -le $pkg_cnt ]; do
        eval _confirm_pkg_name="\$package_$_confirm_cnt"
        if [ "$inst_mode" = REMOVE ]; then
            eval _confirm_install="\$rem_$_confirm_pkg_name"
        else
            eval _confirm_install="\$inst_$_confirm_pkg_name"
        fi
        if [ "$_confirm_install" = "$yes_msg" ]; then
            break                                 # There is at least one package to install
        fi
        _confirm_cnt="`expr $_confirm_cnt + 1`"
    done
    if [ $_confirm_cnt -gt $pkg_cnt ]; then  
        if [ "$inst_mode" = REMOVE ]; then
            Alert "$no_rem_packages_selected_msg"
        else
            Alert "$no_inst_packages_selected_msg"
        fi
        return 1
    fi
        
    if [ "$inst_mode" = REMOVE ]; then 
        _confirm_prompt="$confirm_remove_msg"
    else
        _confirm_prompt="$confirm_install_msg"
    fi

    _confirm_cnt=1
    _appletalk_package=0
    _volume_package=0
    _mae_package=0
    while [ $_confirm_cnt -le $pkg_cnt ]; do
        eval _confirm_pkg_name="\$package_$_confirm_cnt"
        if [ "$inst_mode" = REMOVE ]; then
            eval _confirm_install="\$rem_$_confirm_pkg_name"
        else
            eval _confirm_install="\$inst_$_confirm_pkg_name"
        fi
        if [ "$_confirm_install" = "$yes_msg" ]; then
	    if [ "$_confirm_pkg_name" = "E3_VOLD" ] ; then
                _volume_package=1
            fi
	    if [ "$_confirm_pkg_name" = "E2_ATALK" ]; then
		_appletalk_package=1
	    fi
	    if [ "$_confirm_pkg_name" = "E1_MAE" ]; then
		_mae_package=1
	    fi
            . "$source_dir/LOCALE/$catalog_dir/${_confirm_pkg_name}.STR"   # Load package strings
	    default_destination="${d_dest_dir}/${relative_destination}"
            _confirm_prompt="$_confirm_prompt
        $package_name_msg"
        fi
    _confirm_cnt="`expr $_confirm_cnt + 1`"
    done

    Report "$_confirm_prompt"                     # Keep a list in the report file
    if [ "$inst_mode" = REMOVE ]; then
        _confirm_prompt="$_confirm_prompt $do_you_want_to_cont_rem_msg"
        _confirm_help="$confirm_rem_help_msg"
    else
        _confirm_prompt="$_confirm_prompt $do_you_want_to_cont_inst_msg"
        _confirm_help="$confirm_inst_help_msg"
	if [ "$_appletalk_package" = 0 -a "$_mae_package" = 1 ]; then
            "${source_dir}/E2_ATALK.INS" "$launch_dir" "$msg_file" version
	    _tmp=$?
	    if [ $_tmp = 0 ]; then
		_confirm_prompt="$_confirm_prompt$appletalk_not_installed"
		Report "$appletalk_not_installed"
	    fi
	    if [ $_tmp = 2 ]; then
		_confirm_prompt="$_confirm_prompt$appletalk_version_mismatch"
		Report "$appletalk_version_mismatch"
	    fi
	fi
	if [ "$o_s" = 'SOLARIS' ] ; then
               volume_dir="/usr/lib"
            if [ "$_volume_package" = 0 -a "$_mae_package" = 1 ] ; then
               if [ -f "$volume_dir/rmmount/action_macfs.so.1" \
                    -a -f "$volume_dir/fs/macfs/ident_macfs.so.1" ] ; then
                       cd /tmp
                       cpio -idm .file_info < "${source_dir}/E3_VOLD.PKG" > /dev/null 2>&1
                       CheckA="`grep iden* .file_info`"
                       CheckB="`grep action* .file_info`"
                       rm -rf .file_info
                       cd /usr/lib
                       CheckC="`sum -r fs/macfs/ident_macfs.so.1`"
                       CheckD="`sum -r rmmount/action_macfs.so.1`"
                       if [ "$CheckA" = "$CheckC" -a "$CheckB" = "$CheckD" ] ; then
                            cd "${source_dir}"
                       else
			    cd "${source_dir}"
                            _confirm_prompt="$_confirm_prompt$volume_version_mismatch"
                            Report "$volume_version_mismatch"
                       fi
               else
                       _confirm_prompt="$_confirm_prompt$no_volume_manager_msg"
	               Report "$no_volume_manager_msg"	
               fi
            fi
        fi
    fi

    AskYesNo "$_confirm_prompt" "$_confirm_help" "$yes_msg"
    case "$reply" in
        "$yes_msg") return 0 ;;                   # Proceed
        "$no_msg")  return 1 ;;                   # Start over
    esac
}

#------------------------------------------------------------------------------
# DoClear - Clear screen (if supported)
#------------------------------------------------------------------------------
DoClear()
{
    if [ "$can_clear" = TRUE ]; then
        Prompt "$clr_scrn"                        # Clear screen
    else
        # Incrementing loops in sh are toooo slooooww.
        echo; echo; echo; echo; echo; echo; echo; echo; 
        echo; echo; echo; echo; echo; echo; echo; echo; 
        echo; echo; echo; echo; echo; echo; echo; echo; 
    fi
}

#------------------------------------------------------------------------------
#   DoHelp - display help message and wait for a RETURN to continue
#------------------------------------------------------------------------------
DoHelp()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in DoHelp()."
    fi
    _do_help_msg="$1"
	
    DoClear;
    echo "$rev$help_side_msg$help_title_msg$help_side_msg$off"
    echo "$_do_help_msg" 
    echo
    echo 
    echo "$help_trailer1_msg"
    echo "$help_trailer2_msg"
    echo

    WaitToContinue;
}

#------------------------------------------------------------------------------
# DoInstall - Installs requested packages 
#------------------------------------------------------------------------------
DoInstall()
{
    if [ "$pkg_cnt" -le 0 ]; then
        AssertErr "Bogus pkg_cnt in DoInstall."
    fi

    if Interactive; then
        TopScreen "$press_to_stop_msg"
    else
        echo; echo "$press_to_stop_msg"
        sleep 3                                   # Give them a moment to quit
    fi

    _error_occurred=FALSE                         # Initialize global
    appledir=''                                   # set to NULL
    _do_inst_cnt=1
    while [ $_do_inst_cnt -le $pkg_cnt ]; do
        eval _do_inst_pkg_name="\$package_$_do_inst_cnt"
        eval _do_inst_install="\$inst_$_do_inst_pkg_name"
        if [ "$_do_inst_install" = "$yes_msg" ]; then
            _do_inst_destination="`eval echo \\$\${_do_inst_pkg_name}_dir`"
            appledir="${appledir:-$_do_inst_destination}"     # Set to first directory used  
            . "$source_dir/LOCALE/$catalog_dir/${_do_inst_pkg_name}.STR" # Load package strings
	    default_destination="${d_dest_dir}/${relative_destination}"

            #------------------------------------------------------------------
            # Run the package install script
            #------------------------------------------------------------------
            _do_inst_status=99
            Report "Installing $package_name_msg in $_do_inst_destination."
            "${source_dir}/${_do_inst_pkg_name}.INS" "$_do_inst_destination" "$msg_file" install 2>> "$report_file"
            _do_inst_status=$?

            if [ $_do_inst_status -ne 0 ]; then   # Error
                _error_occurred=TRUE              # Global Flag
                if [ -r "$msg_file" -a -s "$msg_file" ]; then
                    ShowErrMsg
                else
                    Alert "$an_error_msg    (install)"  # A generic message
                    echo
                fi
                Report "Cleaning up $package_name_msg in $_do_inst_destination."
                "${source_dir}/${_do_inst_pkg_name}.INS" "$_do_inst_destination" "$msg_file" cleanup 2>> "$report_file"
                if [ $? -ne 0 ]; then
                    if [ -r "$msg_file" -a -s "$msg_file" ]; then
                        ShowErrMsg
                    else
                        Alert "$an_error_msg    (cleanup)"  # A generic message
                        echo
                    fi
                fi
                if [ $_do_inst_cnt -lt $pkg_cnt ]; then    # Still more packages
                    AskQuit "$yes_msg"            # Quit (or return here)
                fi
            else                                  # Package installed without error
                _do_inst_status=99
                Report "Verifying $package_name_msg in $_do_inst_destination."
                "${source_dir}/${_do_inst_pkg_name}.INS" "$_do_inst_destination" "$msg_file" verify 2>> "$report_file"
                _do_inst_status=$?
                if [ $_do_inst_status -ne 0 ]; then   # Verify failed
                    _error_occurred=TRUE              # Global Flag
                    if [ -r "$msg_file" -a -s "$msg_file" ]; then
                        ShowErrMsg
                    else
                        Alert "$an_error_msg    (verify)"  # A generic message
                        echo
                    fi
                    Report "Cleaning up $package_name_msg in $_do_inst_destination."
                    "${source_dir}/${_do_inst_pkg_name}.INS" "$_do_inst_destination" "$msg_file" cleanup 2>> "$report_file"
                    if [ $? -ne 0 ]; then         # Remove failed
                        if [ -r "$msg_file" -a -s "$msg_file" ]; then
                            ShowErrMsg
                        else
                            Alert "$an_error_msg    (cleanup)" # A generic message
                            echo
                        fi
                    fi
                else
# Disabled old alias mechanism. SS
                    #----------------------------------------------------------
                    # Put entry in AliasList file  # DEBUG: Ick! MAE Specific!
                    #----------------------------------------------------------
#                    if [ -d "${appledir}/lib" -a \
#                         -w "${appledir}/lib" -a \
#                         -d "${appledir}/sys/Fonts" ]; then
#                        "${source_dir}/${_do_inst_pkg_name}.VAL" '' /dev/null mk_alias >/dev/null 2>&1
#			case "$?" in
#			    0)  echo "nonpersistent|home|$_do_inst_destination" >> "${appledir}/lib/AliasList" 2> /dev/null
#				$sort_cmd -u -o "${appledir}/lib/AliasList" "${appledir}/lib/AliasList"
#				;;
#			    1)  ;;
#			    2)  echo "nonpersistent|extras|$_do_inst_destination" >> "${appledir}/lib/AliasList" 2> /dev/null
#				$sort_cmd -u -o "${appledir}/lib/AliasList" "${appledir}/lib/AliasList"
#				;;
#                        esac
#                    fi

		    # Put entries into AliasList file
		    if [ -f "${master_d_dest_dir}/lib/AliasList" -a -w "${master_d_dest_dir}/lib/AliasList" ]; then
			export _do_inst_destination
			"${source_dir}/${_do_inst_pkg_name}.VAL" "${master_d_dest_dir}" /dev/null mk_alias > /dev/null 2>&1
		    fi
                    #--------------------------------------
                    # Set global reboot flag if required
                    #--------------------------------------
                    eval _do_inst_reboot="\$reboot_$_do_inst_pkg_name"
                    if [ "$_do_inst_reboot" = TRUE ]; then
                        reboot_required=TRUE
                    fi
                fi  
            fi
        fi
        _do_inst_cnt=`expr $_do_inst_cnt + 1`
    done
        
    return
}

#------------------------------------------------------------------------------
# DoRemove - Removes requested packages 
#------------------------------------------------------------------------------
DoRemove()
{
    if [ "$r_pkg_cnt" -le 0 ]; then
        AssertErr "No removable packages in DoRemove"
    fi

    if Interactive; then
        TopScreen "$press_to_stop_rmv_msg"
    else
        echo; echo "$press_to_stop_rmv_msg"
        sleep 3                                   # Give them a moment to quit
    fi

    _error_occurred=FALSE                         # Initialize global
    _do_rem_cnt=1
    while [ $_do_rem_cnt -le $r_pkg_cnt ]; do
        eval _do_rem_pkg_name="\$r_package_$_do_rem_cnt"
        eval _do_rem_remove="\$rem_$_do_rem_pkg_name"
        if [ "$_do_rem_remove" = "$yes_msg" ]; then
            _do_rem_destination="`eval echo \\$\${_do_rem_pkg_name}_dir`"
            . "$source_dir/LOCALE/$catalog_dir/${_do_rem_pkg_name}.STR" # Load package strings
	    default_destination="${d_dest_dir}/${relative_destination}"
	    if [ -z "$_do_rem_destination" ]; then
		_do_rem_destination="$default_destination"
	    fi

            #------------------------------------------------------------------
            # Run the package remove script 
            #------------------------------------------------------------------
            Report "Removing $package_name_msg from $_do_rem_destination."
            "${source_dir}/${_do_rem_pkg_name}.INS" "$_do_rem_destination" "$msg_file" remove 2>> "$report_file"
            if [ $? -ne 0 ]; then
                if [ -r "$msg_file" -a -s "$msg_file" ]; then
                    ShowErrMsg
                else
                    Alert "$an_error_msg    (remove)"  # A generic message
                    echo
                fi
                _error_occurred=TRUE
            fi
            #--------------------------------------
            # Set global reboot flag if required
            #--------------------------------------
            eval _do_rem_reboot="\$reboot_$_do_rem_pkg_name"
            if [ "$_do_rem_reboot" = TRUE ]; then
                reboot_required=TRUE
            fi
        fi
        _do_rem_cnt=`expr $_do_rem_cnt + 1`
    done
        
    return
}

#------------------------------------------------------------------------------
# Epilogue - Any last requests?
#------------------------------------------------------------------------------
Epilogue()
{
    if [ "${_error_occurred:-FALSE}" = TRUE ]; then
        if [ "$inst_mode" = REMOVE ]; then
            echo "$removal_failed_msg"
            Report "$removal_failed_msg"
        else
            echo "$installation_failed_msg"
            Report "$installation_failed_msg"
        fi
        _exit_code=2
    else
	if [ -n "$_no_operation" ]; then
	    echo "$no_operation_msg"
	    Report "$no_operation_msg"
            _exit_code=1
	else
	    if [ "$inst_mode" = REMOVE ]; then
        	echo "$remove_complete_msg" 
                Report "$remove_complete_msg" 
            else
                echo "$install_complete_msg" 
                Report "$install_complete_msg" 
            fi
            _exit_code=0 
        fi
    fi
    WaitToContinue

    # We should check to see if they are logged in as root. 
    # For now we will assume that packages that require reboot
    # will also require root login. So it will be handled in
    # the .VAL script
    if [ "$reboot_forced" = TRUE ]; then
	DoClear;
        AskYesNo "$read_report_prompt_msg" "$read_report_help_msg" "$no_msg"
        if [ "$reply" = "$yes_msg" ] ; then
                more -c "$report_file"
	        WaitToContinue
        fi
        Reboot
    fi
    if [ "$reboot_required" = TRUE ]; then
        if [ "$interactive" = TRUE ]; then
	     AskYesNo "$read_report_prompt_msg" "$read_report_help_msg" "$no_msg"
            if [ "$reply" = "$yes_msg" ] ; then
                   more -c "$report_file"
		   WaitToContinue
            fi
            DoClear;
            AskYesNo "$reboot_prompt_msg" "$reboot_help_msg" "$no_msg"
            if [ "$reply" = "$yes_msg" ]; then
                Reboot
            fi
        else
            echo "$you_must_reboot_msg"
            Report "$you_must_reboot_msg"
        fi
    fi
    CleanUpExit $_exit_code
}

#------------------------------------------------------------------------------
# Reboot - Reboot system with default grace period
#------------------------------------------------------------------------------
Reboot()
{
    cd / 

    case "$o_s" in
        HPUX)    reboot
                 ;;
        HPUX9)	 reboot
		 ;;
        SOLARIS) reboot
                 ;;
        *)       AssertErr "Unsupported O/S in Reboot()"
                 ;;
    esac
}

#------------------------------------------------------------------------------
# GetOS - Determine system type and OS
#------------------------------------------------------------------------------
GetOS()
{
    case "`/bin/uname -s`" in
         A/UX*)  o_s='AUX'     ;;                 # Apple
          AIX*)  o_s='unknown' ;;                 # IBM
        SunOS*)  o_s='SUN'     ;;                 # Sun
        HP-UX*)  o_s='HPUX'    ;;                 # HP
             *)  o_s='unknown' ;;                 # unknown
    esac
    
    #--------------------------------------------------------------------------
    # Additional code to determine O_S version and release
    #--------------------------------------------------------------------------
    case $o_s in
        SUN) 	case "`/bin/uname -r`" in
                 4*) o_s='unknown' ;;             # SunOS 
                 5*) o_s='SOLARIS' ;;             # Solaris 2.x
                  *) o_s='unknown' ;;             # unknown
             	esac
             	;;
	HPUX)  	case "`/bin/uname -r | cut -c 3,4,5,6`" in
	         09.0) o_s='HPUX9'   ;;           # for 9 specific installation
		 10.0) o_s='unknown' ;;		  # don't support 10.01
		 10.*) o_s='HPUX' ;;
		 *)    o_s='unknown' ;;
	       	esac
	       	;;
    esac
    
    if [ "$o_s" = unknown ]; then
        Alert "[`/bin/uname -sr`]  $not_supported_os_msg." 
        CleanUpExit 2
    fi
}

#------------------------------------------------------------------------------
# GetOpts - Get command line options
#------------------------------------------------------------------------------
GetOpts()
{
    _cnt=1
    _cnt2=1
    _match_args=0
    _pkg_name=""
    _tmp_string=""
    _packages_selected=FALSE
    cmd_line_pkg_cnt=0 ; export cmd_line_pkg_cnt
    cmd_line_dest=""
    reboot_required=FALSE
    reboot_forced=FALSE

    if [ "$argc" -eq 0 ]; then
        return
    fi

    set -- $argv PED                           # Set positional parameters; end with PED
    while :; do
        case "$1" in
           PED)  break ## return
                 ;;
            -q)  quiet=TRUE
                 shift
                 ;;
            -e)  if [ -z "$inst_mode" ]; then
                     inst_mode=EASY
                     shift
                 else
                     echo; echo "$usage_msg"
                     CleanUpExit 0
                 fi
                 ;;
            -c)  if [ -z "$inst_mode" ]; then
                     inst_mode=CUSTOM
                     shift
                     while :; do
                         case "$1" in
                       PED)  break           # No more package names
                             ;;
                         -*) break           # No more package names
                             ;;
                         *)  cmd_line_pkg_cnt=`expr $cmd_line_pkg_cnt + 1`
                             eval cmd_line_pkg_${cmd_line_pkg_cnt}="$1"
			     eval export cmd_line_pkg_${cmd_line_pkg_cnt}
                             shift
                             ;;
                         esac
                     done

                 else
                     echo; echo "$usage_msg"
                     CleanUpExit 0
                 fi
                 ;;
            -r)  if [ -z "$inst_mode" ]; then
                     inst_mode=REMOVE
                     shift
                     while :; do
                         case "$1" in
                       PED)  break           # No more package names
                             ;;
                         -*) break           # No more package names
                             ;;
                         *)  cmd_line_pkg_cnt=`expr $cmd_line_pkg_cnt + 1`
                             eval cmd_line_pkg_${cmd_line_pkg_cnt}="$1"
                             shift
                             ;;
                         esac
                     done

                 else
                     echo; echo "$usage_msg"
                     CleanUpExit 0
                 fi
                 ;;
            -d)  ## Set destination
                 shift
                 if [ "$1" = PED ]; then
                     echo; echo "$usage_msg"
                     CleanUpExit 0
                 else
                     cmd_line_dest="$1"
                     d_dest_dir="$1"     ## Default destination
                     shift
                 fi
                 ;;
             -R) ## Force Reboot
                 shift
                 reboot_forced=TRUE
                 ;;
             *)  echo; echo "$usage_msg"
                 CleanUpExit 0
                 ;;
        esac
    done

    ##
    ## Sanity check to make sure args are used in valid combinations
    ##

    FindPackages               # Look for valid packages

    if [ "$inst_mode" = CUSTOM ]; then
        if [ "$cmd_line_pkg_cnt" -eq 0 ]; then
            continue  ## No packages specified
        fi
   
        ## Do the requested packages exist?
        _cnt=1; _bad_pkg_cnt=0;
        while [ "$_cnt" -le "$cmd_line_pkg_cnt" ]; do
            eval _tmp_string="\$cmd_line_pkg_$_cnt"
            _found_flag=0
            _cnt2=1
            while [ "$_cnt2" -le "$pkg_cnt" ]; do
                eval _pkg_name="\$package_$_cnt2"
                if [ "$_pkg_name" = "$_tmp_string" ]; then
                    eval inst_${_pkg_name}="$yes_msg"
                    _match_args=`expr $_match_args + 1`
                    _found_flag=1
                    break
                fi
                _cnt2=`expr $_cnt2 + 1`
            done

            ## Record which package is bad. SS
            if [ $_found_flag -eq 0 ]; then
                _bad_pkg_cnt=`expr $_bad_pkg_cnt + 1`
                eval _bad_pkg_${_bad_pkg_cnt}="$_tmp_string"
            fi
                              
            _cnt=`expr $_cnt + 1`
        done
        if [ "$_match_args" -ne "$cmd_line_pkg_cnt" ]; then
            echo "$invalid_pkg_msg"
            _cnt=1             # Re-initialize
            while [ "$_cnt" -le "$_bad_pkg_cnt" ]; do
                eval _bad_pkg_name="\$_bad_pkg_$_cnt"
                echo "        $_bad_pkg_name"
                _cnt=`expr $_cnt + 1`
            done
            echo ""
            echo "$choose_from_msg"
            _cnt=1             # Re-initialize
            while [ "$_cnt" -le "$pkg_cnt" ]; do
                eval _pkg_name="\$package_$_cnt"
                echo "        $_pkg_name"
                _cnt=`expr $_cnt + 1`
            done
            CleanUpExit 0
        else
            _packages_selected=TRUE
        fi
    fi

    if [ "$inst_mode" = REMOVE ]; then
        if [ "$cmd_line_pkg_cnt" -eq 0 ]; then
            continue       ## No packages specified
        fi
   
        ## Do the requested packages exist?
        ## And are they removable?
        _cnt=1; _cnt2=1;
        while [ "$_cnt" -le "$cmd_line_pkg_cnt" ]; do
            eval _tmp_string="\$cmd_line_pkg_$_cnt"
            while [ "$_cnt2" -le "$r_pkg_cnt" ]; do
                eval _pkg_name="\$r_package_$_cnt2"
                if [ "$_pkg_name" = "$_tmp_string" ]; then
                    eval rem_${_pkg_name}="$yes_msg"
                    _match_args=`expr $_match_args + 1`
                    break
                fi
                _cnt2=`expr $_cnt2 + 1`
            done
              
            _cnt=`expr $_cnt + 1`
        done
        if [ "$_match_args" -ne "$cmd_line_pkg_cnt" ]; then
            echo "$invalid_pkg_msg \"$_tmp_string\"."
            echo "$choose_from_msg"
            _cnt=1             # Re-initialize
            while [ "$_cnt" -le "$pkg_cnt" ]; do
                eval _pkg_name="\$r_package_$_cnt"
                echo "        $_pkg_name"
                _cnt=`expr $_cnt + 1`
            done
            CleanUpExit 0
        else
            _packages_selected=TRUE
        fi
    fi
}

#------------------------------------------------------------------------------
# InitVars - O/S specific commands loaded into variables
#------------------------------------------------------------------------------
InitVars()
{
    inst_mode=''
    quiet=FALSE
    interactive=TRUE

    d_inst_mode="EASY" 
    d_source_dir='/cdrom'
    d_dest_dir='/opt/apple'                    
    master_d_dest_dir=''

    df_cmd='/bin/df'                              
    format_cmd='/bin/fmt'                         
    mkdir_cmd='/bin/mkdir'                      
    mkdir_opt='-p'                      
    sort_cmd='/bin/sort'                      
    tput_cmd='/bin/tput'                      
    if `echo -n XXXX | /bin/grep n > /dev/null 2>&1`; then
        bsd_echo=FALSE
    else
        bsd_echo=TRUE
    fi

    case "$o_s" in
          AIX)    df_arg='-I'                       
                  ;;
        SUN_OS)   df_arg=''                       
                  d_dest_dir='/opt/apple'            
                  ;;
        SOLARIS)  df_arg='-k'                       
                  d_dest_dir='/opt/apple'            
                  ;;
         HPUX)    format_cmd='/bin/adjust'         
                  df_cmd='/usr/bin/bdf'             
                  df_arg=''                         
                  tput_cmd='/usr/bin/tput'          
                  ;;
         HPUX9)   format_cmd='/bin/adjust'         
                  df_cmd='/usr/bin/bdf'             
                  df_arg=''                         
                  tput_cmd='/usr/bin/tput'          
                  ;;
          AUX)    df_arg='-B'                       
                  tput_cmd='/usr/bin/tput'          
                  format_cmd='/usr/ucb/fmt'
                  mkdir_opt=''                      
                  ;;
           *)     AssertErr "Unknown O_S type in InitVars()."
                  ;;
    esac


    #--------------------------------------------------------------------------
    # Test to determine whether we are dumb terminal or smart.
    #--------------------------------------------------------------------------
    $tput_cmd clear > /tmp/tput.test$$ 2> /dev/null
    if [ -s /tmp/tput.test$$ ]; then
        can_clear=TRUE
    else
        can_clear=FALSE
    fi
    /bin/rm -f /tmp/tput.test$$
}

#------------------------------------------------------------------------------
# Interactive - Return TRUE (0) if interactive=TRUE
#------------------------------------------------------------------------------
Interactive()
{
    if [ "$interactive" = TRUE ]; then
         return 0                                 # We ARE interactive
    else
        return 1                                  # We are NOT interactive
    fi
}

#--------------------------------------------------------------------------
# ListPackages - Let the user know what packages are available
#--------------------------------------------------------------------------
ListPackages()
{
    TopScreen "$hit_ret_banner_msg"               # Clear screen and display header
    echo "$here_are_the_pkgs_msg"
    #----------------------
    # Easy Only Packages
    #----------------------
    if [ "$e_pkg_cnt" -ge 1 ]; then
        echo "$here_are_the_e_pkgs_msg"
         _list_pkgs_cnt=1
        while [ $_list_pkgs_cnt -le $e_pkg_cnt ]; do
            eval _list_pkgs_pkg_name="\$e_package_$_list_pkgs_cnt"
            eval _list_pkgs_size="\$${_list_pkgs_pkg_name}_size"
            # Convert size to number of megabytes or kilobytes
	    if [ "$_list_pkgs_size" -le 1000 ]; then
	        _list_pkgs_size="$_list_pkgs_size"KB
	    else
                _list_pkgs_size="`expr $_list_pkgs_size / 1024`"
                #------------------------------------------------------------------
                # Add 1 to inflate the number slightly (almost the same as rounding up)
                #------------------------------------------------------------------
                _list_pkgs_size="`expr $_list_pkgs_size + 1`"
  		_list_pkgs_size="$_list_pkgs_size"MB
	    fi

    
            echo "        ${_list_pkgs_size}	`/bin/cat \"$source_dir/LOCALE/$catalog_dir/${_list_pkgs_pkg_name}.NAM\"`"
    
        _list_pkgs_cnt="`expr $_list_pkgs_cnt + 1`"
        done
    fi
    #--------------------------------------------------------------------------
    # Other Packages
    #--------------------------------------------------------------------------
    if [ "$pkg_cnt" -ge 1 -a "$pkg_cnt" -gt "$e_pkg_cnt" ]; then
        if [ "$e_pkg_cnt" -ge 1 ]; then
            echo "$here_are_the_c_pkgs_msg1"
        else
            echo "$here_are_the_c_pkgs_msg2"
        fi
        _list_pkgs_cnt=1
        while [ $_list_pkgs_cnt -le $pkg_cnt ]; do
            eval _list_pkgs_pkg_name="\$package_$_list_pkgs_cnt"
            match_chars=`expr "$_list_pkgs_pkg_name" : 'E.*'`  # Is an Easy Install package
            if [ "$match_chars" -ne 0 ]; then
                _list_pkgs_cnt="`expr $_list_pkgs_cnt + 1`"
                continue                          # Has already been displayed
            fi
            eval _list_pkgs_size="\$${_list_pkgs_pkg_name}_size"
            #------------------------------------------------------------------
            # Use 1000 (instead of 1024) to inflate the number slightly
            #------------------------------------------------------------------
	    if [ "$_list_pkgs_size" -le 1000 ]; then
	        _list_pkgs_size="$_list_pkgs_size"KB
	    else
                _list_pkgs_size="`expr $_list_pkgs_size / 1000`"
  		_list_pkgs_size="$_list_pkgs_size"MB
	    fi

            . "$source_dir/LOCALE/$catalog_dir/${_list_pkgs_pkg_name}.STR"   # Load package strings
	    default_destination="${d_dest_dir}/${relative_destination}"
            echo "        ${_list_pkgs_size}	$package_name_msg"
    
        _list_pkgs_cnt="`expr $_list_pkgs_cnt + 1`"
        done
    else
        echo "$here_are_the_c_pkgs_msg0"
    fi
    echo
    WaitToContinue
}

#--------------------------------------------------------------------------
# LoadMountList - load (global) array with mount points and free space
#--------------------------------------------------------------------------
LoadMountList()
{
    IFS='
'
    _ld_mnt_cnt=1
    _skipped_header=''
    for _mnt_point in `$df_cmd $df_arg 2> /dev/null`; do
        if [ -z "$_skipped_header" ]; then
            _skipped_header="TRUE"
            continue                              # Skip the header
        fi
        set -- `echo X$_mnt_point | awk '{ print($4); print($6) }'`  # Prepend an X for df() bug
        if [ "${1:-NULL}" = NULL -o "${2:-NULL}" = NULL ]; then
            continue                              # Must be a bad mount - ignore
        fi
        eval free_space_$_ld_mnt_cnt="$1"
        if [ -d "$2" -a -x "$2" ]; then           # If dir exists and is searchable
            cd "$2"                               # We're pretty darn sure that the dir exists
            _tmp_dir="`/bin/pwd 2> /dev/null`"    # Get "real" path (resolve sym-links)
            if [ $? -ne 0 ]; then
                _tmp_dir="$2"                     # Use whatever df() gave us
            fi
        else
            _tmp_dir="$2"                         # Use whatever df() gave us
        fi
        eval mnt_point_$_ld_mnt_cnt="$_tmp_dir"

        _ld_mnt_cnt=`expr $_ld_mnt_cnt + 1`
    done

    MAX_MNTS=`expr $_ld_mnt_cnt - 1`              # Global
    IFS="$S_IFS"
}

#------------------------------------------------------------------------------
# MakeDir - Make directory(s) from supplied path - always absolute path
#------------------------------------------------------------------------------
MakeDir()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in MakeDir()."
    fi
    _mk_dir_target="$1"
    we_made_dir=FALSE                             # Global Flag

    if [ -d "$_mk_dir_target" ]; then             # Already exists
        return 0              
    fi

    if [ -f "$_mk_dir_target" ]; then             # File with same name exists
        Alert "$file_not_dir_msg"
        return 1                                  # Error
    fi

    $mkdir_cmd "$mkdir_opt" "$_mk_dir_target" > /dev/null 2>&1
    if [ ! -d "$_mk_dir_target" ]; then           # Could not make directory
        return 1                                  # Return Error
    fi

    we_made_dir=TRUE                              # Global Flag
    return 0                                      # Return Success
}

#------------------------------------------------------------------------------
# Prompt - Display prompt - suppress CR/LF 
#------------------------------------------------------------------------------
Prompt()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in Prompt()."
    fi

    if [ "$bsd_echo" = TRUE ]; then
        echo -n "$1"
    else
        echo "$1\c"
    fi
}

#------------------------------------------------------------------------------
# RemoveDir - Remove directory(s) from supplied path, if empty
#------------------------------------------------------------------------------
RemoveDir()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in RemoveDir()."
    fi

    _rem_dir_dir="$1"
    cd "$start_dir"                               # In case we're in the dir to be removed
    
    until [ -z "$_rem_dir_dir" ]; do
        /bin/rmdir "$_rem_dir_dir" 2> /dev/null   # Remove dir if possible
        if [ $? -ne 0 ]; then                     # Could not remove dir (not an error)
            return 0
        fi
        _rem_dir_dir="`expr \"$_rem_dir_dir\" : '\(.*\)\/.*'`"      # remove rightmost dirname
    done

    return 0                                      # Return TRUE
}

#------------------------------------------------------------------------------
# MountPoint - determine the mountpoint of a directory
#------------------------------------------------------------------------------
MountPoint()
{
    if [ $# -ne 1 ]; then
        AssertErr "Incorrect arg count in MountPoint()."
    fi

    _mnt_pnt_dir_name="$1"
    #--------------------------------------------------------------------------
    # Save the name of the dir; strip all spaces in path
    #--------------------------------------------------------------------------
    _mnt_pnt_save_name="`echo $_mnt_pnt_dir_name | tr -d  ' ./-'`"

    #--------------------------------------------------------------------------
    # Use cached data if it exists
    #--------------------------------------------------------------------------
    _mnt_pnt_mount_point="`eval echo \\$_mp_\${_mnt_pnt_save_name}_dir`" 

    until [ -n "$_mnt_pnt_mount_point" ]; do      # Loop until mountpoint is found
        IFS='
'
        for _mnt_pnt_tmp_line in `$df_cmd $df_arg 2> /dev/null`; do
            IFS="$S_IFS"
            set -- "`echo X$_mnt_pnt_tmp_line | awk '{ print($6) }'`"
            if [ "${1:-NULL}" = "$_mnt_pnt_dir_name" ]; then
                _mnt_pnt_mount_point="$_mnt_pnt_dir_name"
                continue 2                        # Continue in 'until' loop
            fi
        done

        if [ -z "$_mnt_pnt_mount_point" ]; then            # Haven't found it
            _mnt_pnt_dir_name="`expr \"$_mnt_pnt_dir_name\" : '\(.*\)\/.*'`"  # remove rightmost dir
            #------------------------------------------------------------------
            # The command above will turn '/foo' into '' so we put '/' back
            #------------------------------------------------------------------
            if [ -z "$_mnt_pnt_dir_name" ]; then
                _mnt_pnt_dir_name='/'                      # If doesn't match now, we're hosed!
            fi
        fi
    done

    eval _mp_${_mnt_pnt_save_name}_dir=$_mnt_pnt_mount_point 

    _mnt_pnt_cnt=1
    while [ $_mnt_pnt_cnt -le $MAX_MNTS ]; do
        eval _mnt_pnt_mount_point_tmp="\$mnt_point_$_mnt_pnt_cnt"
        if [ "$_mnt_pnt_mount_point" = "$_mnt_pnt_mount_point_tmp" ]; then
            return $_mnt_pnt_cnt                           # Return with the mount index
        else
            _mnt_pnt_cnt=`expr $_mnt_pnt_cnt + 1` 
        fi
    done

    Alert "$could_not_find_mnt_point_msg"         # Should have returned above
    return 99                                     # Error detected
}

#------------------------------------------------------------------------------
# SetTopDir - Sets d_dest_dir
#------------------------------------------------------------------------------
SetTopDir()
{
    if [ "${d_dest_dir:-NULL}" = NULL ]; then
        AssertErr "d_dest_dir not set in SetTopDir"
        exit 1
    fi

    # If not the default default (or first time) remove the last dir name
    if [ -z "${master_d_dest_dir}" -a -n "${_ask_inst_pkg_name}" -a "${_ask_inst_pkg_name}" != "E1_MAE" ]; then
	while [ -z "${master_d_dest_dir}" ]; do
	    if [ -w "${d_dest_dir}" ]; then
	        master_d_dest_dir="${d_dest_dir}"
	    else
		__tmp_cur_dir=`pwd`
		cd "$HOME"; __home_dir=`pwd`; cd "$__tmp_cur_dir"
		master_d_dest_dir="${__home_dir:-/tmp}/apple"
	    fi
	    echo "$where_is_mae_msg"
	    Prompt "    [default=${bld}${master_d_dest_dir}${off}] >>> "
	    read __where_is_mae
	    if [ -n "${__where_is_mae}" ]; then
		master_d_dest_dir=${__where_is_mae}
                if [ ! -r "${master_d_dest_dir}/sys/Finder" -o ! -r "${master_d_dest_dir}/sys/System" -o ! -r "${master_d_dest_dir}/bin/mae" ]; then 
		    echo "    Warning: MAE is not installed there."
		    master_d_dest_dir=''	
		fi
	    fi
	done
    fi
    if [ "$d_dest_dir" != "${master_d_dest_dir:-$d_dest_dir}" ]; then
	d_dest_dir="${master_d_dest_dir:-\"$d_dest_dir\"}"
    fi

    #--------------------------------------------------------------------------
    # Get the name of prefered dir
    #--------------------------------------------------------------------------
    if [ -n "$default_destination" ]; then        # Set in <package>.STR
	if [ "$default_destination" != '$d_dest_dir' -a -z "$master_d_dest_dir" ]; then
	    master_d_dest_dir="$d_dest_dir"
	fi
        d_dest_dir="${master_d_dest_dir}/${relative_destination}"
    fi

    #--------------------------------------------------------------------------
    # If target dir does not exist create it (remove it before leaving this function)
    #--------------------------------------------------------------------------
    if [ ! -d "$d_dest_dir" ]; then
        MakeDir "$d_dest_dir"                     # Try to create dir
    fi
 
    #--------------------------------------------------------------------------
    # If d_dest_dir is not accessable then default to HOME directory
    #--------------------------------------------------------------------------
    if [ ! -d "$d_dest_dir" -o ! -x "$d_dest_dir" -o ! -w "$d_dest_dir" ]; then
#        dir="`basename \"$d_dest_dir\"`"          # Get the name of prefered dir
#        if [ "$dir" != "apple" ]; then
#            dir="apple/$dir"                      # Add "apple" if not there
#        fi
	__tmp_cur_dir=`pwd`
	cd "$HOME"; __home_dir=`pwd`; cd "$__tmp_cur_dir"
        set_top_tmp="${__home_dir:-/tmp}/apple"               # Use HOME, or /tmp if not set
#        d_dest_dir="${set_top_tmp}/$dir"          # Make it a sub dir of HOME
        d_dest_dir="${set_top_tmp}/${relative_destination}"    # Make it a sub dir of HOME
    else
        if [ "${we_made_dir:-FALSE}" = TRUE ]; then
            cd "$start_dir"                       # In case we're in the dir to be removed
            /bin/rmdir "$d_dest_dir" 2> /dev/null # Remove dir if empty
        fi
    fi
}

#------------------------------------------------------------------------------
# SpaceCheck - calculate free space - needed space; return 1 if insufficient
#------------------------------------------------------------------------------
SpaceCheck()
{
    if [ $# -ne 2 ]; then
        AssertErr "Incorrect arg count in SpaceCheck()."
    fi
    
    _spc_chk_dir="$1"                             # Target dir

    echo "$checking_space_msg"                    # This takes some time - warn them

    LoadMountList                                 # Get current avail space
    MountPoint "$_spc_chk_dir"                    # Get mount point for arg
    mnt_num=$?                                    # Entry into mount_point[]
    if [ $mnt_num -eq 99 ]; then
        return 1                                  # Error in MountPoint function
    fi

    alloc_space=0
    _spc_chk_cnt=1
    while [ $_spc_chk_cnt -le $pkg_cnt ]; do      
        eval _spc_chk_pkg_name="\$package_$_spc_chk_cnt"
        eval _spc_chk_inst_var="\$inst_$_spc_chk_pkg_name"   
        if [ "$_spc_chk_inst_var" != "$yes_msg" ]; then
            _spc_chk_cnt=`expr $_spc_chk_cnt + 1`
            continue                              # Not to be installed
        fi
        var_dir="`eval echo \\$\${_spc_chk_pkg_name}_dir`"
	if [ -z "$var_dir" ]; then
	    var_dir="${d_dest_dir}"
	fi
        MountPoint "$var_dir"                     # Get mount point for arg dest
        var_mnt_num=$?                            # Entry into mount_point[]
        if [ $var_mnt_num -eq 99 ]; then
            return 1                              # Error in MountPoint function
        fi
        if [ $var_mnt_num -ne $mnt_num ]; then
            _spc_chk_cnt=`expr $_spc_chk_cnt + 1`
            continue                              # Not on same mount point
        fi
        _spc_chk_pkg_size="`eval echo \\$\${_spc_chk_pkg_name}_size`"
        alloc_space="`expr $alloc_space + $_spc_chk_pkg_size`"
        _spc_chk_cnt=`expr $_spc_chk_cnt + 1`
    done

    eval free_space="\$free_space_$mnt_num"
    if [ $free_space -lt $alloc_space ]; then
        Alert "$not_enough_free_space_msg    [ $_spc_chk_dir ]" 
        return 1
    else
        return 0
    fi
}

#------------------------------------------------------------------------------
# ToLower - Convert input string to lowercase
#------------------------------------------------------------------------------
ToLower()
{
    if [ $# -ne 1 ]; then AssertErr "ToLower"; fi

    mixed="`eval echo \\$\$1`"

    if [ -z "$mixed" ]; then 
        eval ${1}_lwr=\"\"
    else
        #----------------------------------------------------------------------
        # Convert alphabetic to lowercase and $ to _
        # Use explicit list to work correctly in certain locales
        #----------------------------------------------------------------------
        eval ${1}_lwr=\"`echo $mixed | tr "ABCDEFGHIJKLMNOPQRSTUVWXYZ$" "abcdefghijklmnopqrstuvwxyz_"`\" 
    fi
}

#------------------------------------------------------------------------------
# TopScreen - clear screen - home cursor - display help banner
#------------------------------------------------------------------------------
TopScreen()
{
    if Interactive ; then
        :
    else
        return                                    # Don't do anything in batch mode
    fi

    if [ $# -eq 0 ]; then
        banner="$banner_msg"                      # Set default banner
    else
        banner="$1"                               # Override default with arg1
    fi

    DoClear;                                      # Clear screen - Home cursor
    echo  "$rev$banner$off"                       # Display banner in rev_video
}

#------------------------------------------------------------------------------
# WaitToContinue - Wait for user to hit RETURN key
#------------------------------------------------------------------------------
WaitToContinue()
{
    if Interactive ; then
        :
    else
        return                                    # Don't do anything in batch mode
    fi

    while :; do
        Prompt "${hit_ret_side_msg}${bld}${hit_return_msg}${off}"
        while :; do
            /bin/stty -echo                       # Don't display input
            read  key
            /bin/stty echo                        # Reset to norm
            case "$key" in
            '')                   return 0        # Time to move on
                                  ;;
            "$help_msg"|\
            "$help_short_msg")   DoHelp "$no_help_msg"
                                 return 0
                                 ;;
            "$quit_msg"|\
            "$quit_short_msg")   if [ "$in_quit" = "TRUE" ]; then
                                     CleanUpExit 0
                                 fi
                                 AskQuit "$yes_msg" # Either exit or return here
                                 continue 2        # Display "Hit RETURN" msg again
                                 ;;
            "$q_bang_msg")       CleanUpExit 0
                                 ;;
            esac
        done
    done
}

#------------------------------------------------------------------------------
# Welcome - Display welcome message and wait to continue
#------------------------------------------------------------------------------
Welcome()
{
    DoClear
    echo "$welcome1_msg" 
    echo "$welcome2_msg" 
    echo "$welcome3_msg" 
    WaitToContinue
}

#------------------------------------------------------------------------------
# ShowErrMsg - Display error message, save in report file, and wait to continue
#------------------------------------------------------------------------------
ShowErrMsg()
{
    TopScreen "$hit_ret_banner_msg";
    echo
    /bin/cat "$msg_file"
    echo
    Report "`/bin/cat \"$msg_file\"`"    # Save message in report file
    WaitToContinue
}

#------------------------------------------------------------------------------
# WherePutAll - Ask user where they want to install everything
#------------------------------------------------------------------------------
WherePutAll()
{
    if [ "$e_pkg_cnt" -lt 1 ]; then               # No Easy packages!
        AssertErr "No Easy packages in WherePutAll"
    fi

    _whr_put_cnt=1
    _easy_size=0
    #--------------------------------------------------------------------------
    # Interested in Easy packages only
    #--------------------------------------------------------------------------
    while [ $_whr_put_cnt -le $e_pkg_cnt ]; do
        eval _whr_put_pkg_name="\$e_package_$_whr_put_cnt"
        eval inst_$_whr_put_pkg_name="$no_msg"   # Just pretending for a moment
        _easy_size="`eval expr $_easy_size + \\$\${_whr_put_pkg_name}_size`"
        _whr_put_cnt=`expr $_whr_put_cnt + 1`
    done

    #--------------------------------------------------------------------------
    # Generate default location based on first package (#1)
    #--------------------------------------------------------------------------
    eval _whr_put_pkg_name="\$e_package_1"        # Get name for package number 1
    eval ${_whr_put_pkg_name}_size=$_easy_size    # Total of all packages
    eval inst_${_whr_put_pkg_name}="$yes_msg"     # For BadDir call
    default_destination=''                        # Should be set in *.STR
    . "$source_dir/LOCALE/$catalog_dir/${_whr_put_pkg_name}.STR"     # Load localized strings file
    default_destination="${d_dest_dir}/${relative_destination}"
    Interactive && SetTopDir                      # Sets d_dest_dir (if interactive)
    eval d_${_whr_put_pkg_name}_dir=\${d_${_whr_put_pkg_name}_dir:-\"$d_dest_dir\"} # Used in AskDir

    while :; do
        if Interactive; then
            #------------------------------------------------------------------
            # The AskDir function will modify the value of ${_whr_put_pkg_name}_dir. 
            #------------------------------------------------------------------
            AskDir "$easy_install_prompt_msg" "$easy_install_help_msg" "$_whr_put_pkg_name" W
        else
            #--------------------------------------------------------------
            # Run validation script
            #--------------------------------------------------------------
            "${source_dir}/${_whr_put_pkg_name}.VAL" "`eval echo \\\$d_${_whr_put_pkg_name}_dir`" "$msg_file" destination 2>> "$report_file"
            if [ $? -ne 0 ]; then                 # Error
                if [ -r "$msg_file" -a -s "$msg_file" ]; then
                    ShowErrMsg
                else
                    Alert "$an_error_msg    (destination)"  # Generic msg
                fi
                CleanUpExit 0 
            fi
            if BadDir "`eval echo \\\$d_${_whr_put_pkg_name}_dir`" "$_whr_put_pkg_name" W; then
                CleanUpExit 0 
            fi
        fi
        if [ $? -ne 0 ]; then
            continue                              # Bad dir - Ask again
        else
            break                                 # Good dir - Go on
        fi
    done

    _whr_put_cnt=1
    d_dest_dir="`eval echo \\$\${_whr_put_pkg_name}_dir`"
    master_d_dest_dir="${d_dest_dir}" # Set once and save
    while [ $_whr_put_cnt -le $e_pkg_cnt ]; do
        eval _whr_put_pkg_name="\$e_package_$_whr_put_cnt"
        . "$source_dir/LOCALE/$catalog_dir/${_whr_put_pkg_name}.STR"    # Load strings 
	default_destination="${d_dest_dir}/${relative_destination}"
        if [ -n "$default_destination" ]; then    # Set in <package>.STR
            eval ${_whr_put_pkg_name}_dir=\"`echo $default_destination`\"
        else
            eval ${_whr_put_pkg_name}_dir="$d_dest_dir" 
        fi
        # DEBUG We really should do the full check for each package/destination
        # but that would take a long time
        eval inst_$_whr_put_pkg_name="$yes_msg"   # We really do want to install this package
        _whr_put_cnt=`expr $_whr_put_cnt + 1`     # Increment counter
    done

    return 0
}

#------------------------------------------------------------------------------
# WherePutCmdLinePkgs - Ask user where they want to install everything
#------------------------------------------------------------------------------
WherePutCmdLinePkgs()
{
    if [ "$cmd_line_pkg_cnt" -lt 1 ]; then        # No packages!
        AssertErr "No cmd_line packages in WherePutCmdLinePkgs"
    fi

    #--------------------------------------------------------------------------
    # Morph the command line packages into Easy packages
    #--------------------------------------------------------------------------
    _whr_put_cnt=1
    e_pkg_cnt=$cmd_line_pkg_cnt                   #Override

    while [ $_whr_put_cnt -le $e_pkg_cnt ]; do
        eval _cl_pkg_name=\$cmd_line_pkg_${_whr_put_cnt}
        eval e_package_${_whr_put_cnt}=$_cl_pkg_name
        _whr_put_cnt=`expr $_whr_put_cnt + 1`
    done

    #--------------------------------------------------------------------------
    # Check each package against the destination
    #--------------------------------------------------------------------------
    _whr_put_cnt=1
#    if [ -z "$cmd_line_dest" ]; then
#	if [ -w '/' ]; then
#	    cmd_line_dest="/opt/apple"
#	else
#	    cmd_line_dest="${HOME:-/tmp}/apple"
#	fi
#    fi
    if [ ! -d "$d_dest_dir" ]; then
        MakeDir "$d_dest_dir"                     # Try to create dir
    fi
    if [ ! -d "$d_dest_dir" -o ! -x "$d_dest_dir" -o ! -w "$d_dest_dir" ]; then
	__tmp_cur_dir=`pwd`
	cd "$HOME"; __home_dir=`pwd`; cd "$__tmp_cur_dir"
        d_dest_dir="${__home_dir:-/tmp}/apple"    # Use HOME, or /tmp if not set
    fi

    master_d_dest_dir="$d_dest_dir" # Try to set Appledir location

    while [ "$_whr_put_cnt" -le "$e_pkg_cnt" ]; do
        default_destination=''                        # Should be set in *.STR
#        d_dest_dir="$cmd_line_dest"
        eval _whr_put_pkg_name="\$e_package_${_whr_put_cnt}"

        . "$source_dir/LOCALE/$catalog_dir/${_whr_put_pkg_name}.STR"  # Set default_destination
	default_destination="${d_dest_dir}/${relative_destination}"
	eval ${_whr_put_pkg_name}_dir=\"`echo $default_destination`\"

#        if [ -n "$default_destination" ]; then    # Set in <package>.STR
#            eval ${_whr_put_pkg_name}_dir=\"`echo $default_destination`\"
#        else
#	    eval ${_whr_put_pkg_name}_dir="$d_dest_dir" 
#        fi

        _dest_dir="`eval echo $default_destination`"

	"${source_dir}/${_whr_put_pkg_name}.VAL" '' /dev/null ask_dest >/dev/null 2>&1
	ask_dest=$?

	if [ "$ask_dest" -eq 0 -a -z "$cmd_line_dest" ]; then
	    #-------------------------------------------------------------
	    # Somehow we don't have a destination (probably no -d on the 
	    # command line)
	    #-------------------------------------------------------------
	    while :; do
		eval d_${_whr_put_pkg_name}_dir=\"$_dest_dir\"
		#----------------------------------------------------------
		# Gets directory and validates
		#----------------------------------------------------------
		AskDir "$destination_prompt_msg" "$destination_help_msg" "$_whr_put_pkg_name" W
		if [ $? -ne 0 ]; then
		    continue
		else
		    break
		fi
	    done
	    if [ "${_whr_put_pkg_name}" = "E1_MAE" ]; then
		master_d_dest_dir="${_whr_put_pkg_name}"
	    elif [ -z "$master_d_dest_dir" ]; then
		# ask where is mae
		while [ -z "$master_d_dest_dir" ]; do
		    if [ -w "${d_dest_dir}" ]; then
			master_d_dest_dir="${d_dest_dir}"
		    else
			__tmp_cur_dir=`pwd`
			cd "$HOME"; __home_dir=`pwd`; cd "$__tmp_cur_dir"
			master_d_dest_dir="${__home_dir:-/tmp}/apple"
		    fi
		    echo "$where_is_mae_msg"
		    Prompt "    [default=${bld}${master_d_dest_dir}${off}] >>> "
		    read __where_is_mae
		    if [ -n "${__where_is_mae}" ]; then
			master_d_dest_dir=${__where_is_mae}
			if [ ! -r "${master_d_dest_dir}/sys/Finder" -o ! -r "${master_d_dest_dir}/sys/System" -o ! -r "${master_d_dest_dir}/bin/mae" ]; then 
			    echo "    Warning: MAE is not installed there."
			    master_d_dest_dir=''	
			fi
		    fi
		done
	    fi
	else
	    eval d_${_whr_put_pkg_name}_dir=\"$_dest_dir\"

	    #--------------------------------------------------------------
	    # Run validation script
	    #--------------------------------------------------------------
	    ## "${source_dir}/${_whr_put_pkg_name}.VAL" "`eval echo \\\$d_${_whr_put_pkg_name}_dir`" "$msg_file" destination 2>> "$report_file"

	    "${source_dir}/${_whr_put_pkg_name}.VAL" "$default_destination" "$msg_file" destination 2>> "$report_file"
	    if [ $? -ne 0 ]; then                 # Error
		if [ -r "$msg_file" -a -s "$msg_file" ]; then
		    ShowErrMsg
		else
		    Alert "$an_error_msg    (destination)"  # Generic msg
		fi
		CleanUpExit 0 
	    fi
	    #-------------------------------------------------------------------
	    # Now make sure the receiving directory is OK
	    #-------------------------------------------------------------------
	    if BadDir "`eval echo \\\$d_${_whr_put_pkg_name}_dir`" "$_whr_put_pkg_name" W; then
		CleanUpExit 0 
	    fi
	fi
        # let _whr_put_cnt=$_whr_put_cnt+1
        _whr_put_cnt=`expr $_whr_put_cnt + 1`
    done
    if [ "$quiet" = TRUE ]; then
	interactive=FALSE
    fi

    return 0
}

###############################################################################
## Main - Main program begins                                                ##
###############################################################################

#------------------------------------------------------------------------------
# Identify OS   - sets o_s (or exits)
#------------------------------------------------------------------------------
GetOS

#------------------------------------------------------------------------------
# Initialize platform specific vars - sets lots of things
#------------------------------------------------------------------------------
InitVars

#------------------------------------------------------------------------------
# Make sure we can write to the report file
#------------------------------------------------------------------------------
report_file="/tmp/installer_report$$" 
/bin/cp /dev/null "$report_file" 2> /dev/null
if [ ! -w "$report_file" ]; then
    TopScreen
    echo
    echo
    echo "${bld}    ${error_msg}${off}$no_report_msg [ $report_file ]"
    echo $off
    WaitToContinue;
    report_file="/dev/null"
fi

#------------------------------------------------------------------------------
# Locate source files (or exit) - sets source_dir
#------------------------------------------------------------------------------
FindSourceDir

#------------------------------------------------------------------------------
# Get command line options - sets interactive, inst_mode, d_dest_dir
#------------------------------------------------------------------------------
GetOpts

#------------------------------------------------------------------------------
# Start the report log file with the date, command args, and O/S version
#------------------------------------------------------------------------------
echo "`date`"               >  "$report_file"     # Create the file
echo "$0 $argv"             >> "$report_file"
echo "`/bin/uname -sr`"     >> "$report_file"
echo '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -' >> "$report_file"

#------------------------------------------------------------------------------
# Based on the current settings, jump into the main loop at the apropriate state
#------------------------------------------------------------------------------
case $inst_mode in
    '')        state=Welcome                      # Normal default
               ;;
    EASY)      state=WherePutAll                  # Quick Easy
               ;;
    CUSTOM)    if [ "$cmd_line_pkg_cnt" -gt 0 ]; then
                   state=WherePutCmdLinePkgs      # Command Line Choices
               else
                   state=AskInstPkgs              # Quick Custom
               fi
               ;;
    REMOVE)    if [ "$cmd_line_pkg_cnt" -gt 0 ]; then
                   state=RemCmdLinePkgs           # Command Line Choices
               else
                   state=AskRemPkgs               # Quick Remove
               fi
               ;;
    *)         AssertErr "Invalid state entering main loop"
               ;;
esac

#-------------------------------------------------------------------------------
# Main loop controls flow of execution
#-------------------------------------------------------------------------------
while :; do
    case "$state" in 
    Welcome)       Welcome                        # Display welcome message
                   state=FindPackages
                   ;;
    FindPackages)  FindPackages                   # Sets pkg_cnt/e_pkg_cnt/r_pkg_cnt (or exit)
                   state=ListPackages
                   ;;
    ListPackages)  ListPackages                   # Display package info 
                   state=AskInstMode
                   ;;
    AskInstMode)   AskInstMode                    # Modifies inst_mode
                   case $inst_mode in
                       EASY)    state=WherePutAll ;;
                       CUSTOM)  state=AskInstPkgs ;;
                       REMOVE)  state=AskRemPkgs ;;
                       *)       AssertErr "Invalid inst_mode in main loop." ;;
                   esac
                   ;;
    AskInstPkgs)   AskInstPkgs                    # Modifies inst_*
                   state=Confirm
                   ;;
    AskRemPkgs)    AskRemPkgs                     # Modifies rem_*
                   state=Confirm
                   ;;
    RemCmdLinePkgs)    RemCmdLinePkgs             # 
                   state=Confirm
                   ;;
    WherePutAll)   WherePutAll                    # 
                   state=Confirm
                   ;;
    WherePutCmdLinePkgs)   WherePutCmdLinePkgs    # 
                   state=Confirm
                   ;;
    Confirm)       if Confirm; then               
                       if [ $inst_mode = REMOVE ]; then
                           state=DoRemove         # Go Forward to Remove
                       else
                           state=DoInstall        # Go forward to Install
                       fi
                   else
                       if [ "$cmd_line_pkg_cnt" -gt 0 ]; then
                           _no_operation=TRUE
                           state=Epilogue
                       else
                           state=AskInstMode          # Go Back 
                       fi
                   fi
                   if [ "$cmd_line_pkg_cnt" -gt 0 ]; then
                       interactive=FALSE
                   fi
                   ;;
    DoInstall)     DoInstall                      # Does not return
                   state=Epilogue
                   ;;
    DoRemove)      DoRemove                       # Does not return
                   state=Epilogue
                   ;;
    Epilogue)      Epilogue
                   ;;
    *)             AssertErr "Invalid State! State = '$state'."
                   ;;
    esac
done

