#!/bin/bash
#set -x

#  This script is a bootstrap installer for the
#  Cell Broadband Engine Software Development Kit
#  for Multicore Acceleration 

# global values
DEBUG=1
let errors=0
progname=`basename $0`
myName="cellsdk"
version=""	   # cell-install rpm version
args=""
distro=""          # distro
platform=""        # what platform we're executing on


disabledReposArray=() # repository names are the product, a dash, and the arch
enabledReposArray=()  # only enabled repositories
baseurlArray=()	      # baseurl setting from repository file for Update repository
installedRpmsArray=()
missingDefaultRpmsArray=()
cellInstallRpmsArray=()

# cell-specific locations, logs, etc.
mountPoint="/tmp/sdk"
cellTop="/opt/cell"
cellLog="/var/log/cellsdk.log"    

yumCmd="yum"

# function return values
fullName=""        # full rpm name (w/ver,rel,arch) of rpm found on BSC or isos
what=""		   # what is mounted (an iso, usually)
where=""	   # and where it is mounted


runtimeGroups=" 'Cell Runtime Environment' "
develGroups=" 'Cell Development Tools' 'Cell Development Libraries' 'Cell Programming Examples' 'Cell Simulator' 'Cell Performance Tools'"

# command line arguments
auto=0       # auto install?
gui=0        # use gui to install?
runtime=0    # install only the runtime packages?
task=""      # one of install, update, uninstall, verify, mount, unmount, removeUpdate
isoDir=""    # dir where iso's are downloaded 


# log to stdout/stderr and log file
function log()
{
    [ $# -lt 3 ] && { echo "$FUNCNAME: ERROR invalid argument(s):  $@"; return -1; }
    
    local level=$1;
    local number=$2;
    local mesg=$3;
    
    local messages=$cellLog

    #validate the log dir exists
    local dirname=${cellLog%/*};
    [ -d $dirname ] || mkdir -p $dirname || messages=/dev/null;

    # warning and error messages are always logged
    [ "$level" = "INFO"   ] && [ $DEBUG -le 0 ] && return 0;
    [ "$level" = "TRACE1" ] && [ $DEBUG -le 1 ] && return 0;
    [ "$level" = "TRACE2" ] && [ $DEBUG -le 2 ] && return 0;

    echo "`date +'%b %d %H:%M:%S'` $level-$number: $mesg" >> $messages || exit 1;
    echo "$progname $level-$number: $mesg" || exit 1;
    return 0;
}


# Be sure we're ready to install.  Do all the checks before bailing out.
function readyCheck() 
{
    let errors=0

    log TRACE2 4004 "Starting readyCheck"

    # is the cell-install rpm installed?
    rpm --quiet -q cell-install
    if [[ $? -ne 0 ]]; then
        log ERROR 0034 "the cell-install rpm must be installed" 
        ((errors++))
    else 
        log TRACE2 4000 "found cell-install rpm OK"
    fi

    # is the yum rpm installed?
    rpm --quiet -q yum 
    if [[ $? -ne 0 ]]; then
        log ERROR 0001 "the yum rpm must be installed" 
        ((errors++))
    else 
        log TRACE2 4001 "found yum rpm OK"
    fi

    # Some machines have BOTH /etc/redhat-release and /etc/fedora-release.
    # The file contents seem to correctly indicate what's installed,
    # regardless of the filename.
    let redhat=0
    for file in `ls /etc/*-release 2>/dev/null`; do
        ((redhat += `grep -ic "red hat" $file`))
    done
    if ((redhat > 0)); then 
        distro="RHEL"
    else 
        distro="Fedora"
    fi
    log TRACE2 4058 "distro=$distro"

    # are we running on a known architecture?
    platform=`uname -m`        # i686, x86_64, ppc64
    case $platform in
        i386 | i586 | i686)
            platform='x86'
            ;;
        x86_64)
            ;;
        ppc64)
            `grep Cell /proc/cpuinfo >/dev/null` && 
            (`grep "Cell Broadband Engine" /proc/cpuinfo >/dev/null` || 
             `grep PS3PF /proc/cpuinfo >/dev/null`) && 
            platform='cbea'
            ;;
        *)
            log ERROR 0002 "${myName} is not supported on the $platform processor" 
            ((errors++))
            ;;
    esac
    log TRACE2 4003 "platform=$platform"

    # is /opt writeable?
    if [ ! -w /opt ]; then 
        log ERROR 0003 "This install script needs write access to /opt"
        ((errors++))
    else 
        log TRACE2 4006 "/opt is writeable"
    fi

    if ((errors > 0)); then {
        log ERROR 0004 "exiting with $errors errors"
        help
    }
    fi
}


# if user selected --gui, be sure we have either pirut or pup installed
function guiCheck()
{
    log TRACE1 3001 "checking that gui program is present"

    rpm2install=""
    # the pup command is installed as part of the pirut rpm
    if [ "$task" = "install" ] || [ "$task" = "update" ]; then 
        # is the pirut rpm already installed?
        rpm --quiet -q pirut
        [[ $? -eq 0 ]] && return 0
        rpm2install="pirut"
    fi

    echo "Using --gui requires uninstalled rpm $rpm2install."
    echo -n "Would you like to install it [y/n]?"
    read answer
    if [ "$answer" = 'y' ]; then 
        log INFO 2001 "$yumCmd install $rpm2install"
        $yumCmd install $rpm2install
        [[ $? -eq 0 ]] && return 0
        log ERROR 0005 "Yum install of $rpm2install failed with rc=$?" 
    fi
    echo -n "Would you like to continue in command line mode [y/n]?"
    read answer
    [ "$answer" != 'y' ] && exit 
    gui=0
}
    

# Read through the repository file, determining which
# repositories are enabled.
function getEnabledRepos()
{
    log TRACE1 3027 "finding enabled yum repositories"
    enabledReposArray=()      # zero out the array

    rm -f /etc/yum.repos.d/cellsdk*.orig

    let i=0
    let j=0
    for file in `ls /etc/yum.repos.d/cellsdk* 2>/dev/null`; do
        while read line; do
            [ "${line:0:1}" = "[" ] && {
                repo=${line#\[}        # remove [ from front
                repo=${repo%\]}        # remove ] from end
                prod=${repo%-*}        # remove arch from the end
                arch=${repo##*-}       # remove repo from the front
                continue
            }
    
            keyword=`echo $line | awk -F= '{print $1}'`
            value=`echo $line | awk -F= '{print $2}'`

            if [ "$keyword" = "baseurl" ]; then
                baseurl="$value"
            fi

            if [ "$keyword" = "enabled" ]; then
                # Skip any repositories that aren't for this distro
                [ `echo $repo | grep -c ${distro}` -eq 0 ] && continue
                # Skip any repositories that aren't for this platform
                [ "$arch" != "$platform" ] && continue

                if [ "$value" = "1" ]; then
                    # don't make the same entry twice
                    let found=0
                    let arraySize=${#enabledReposArray[@]}
                    for ((k=0; k<$arraySize; k++)); do
                        if [ "${enabledReposArray[$k]}" = "$repo" ]; then
                            found=1;
                        fi
                    done
                    if [ $found -eq 0 ]; then
                        enabledReposArray[$i]=$repo
                        baseurlArray[$i]=$baseurl
                        let i++
                    fi
                else
                    let found=0
                    let arraySize=${#disabledReposArray[@]}
                    for ((k=0; k<$arraySize; k++)); do
                        if [ "${disabledReposArray[$k]}" = "$repo" ]; then
                            found=1;
                        fi
                    done
                    if [ $found -eq 0 ]; then
                        disabledReposArray[$j]=$repo
                        let j++
                    fi
                fi
            fi

        done < $file
    done

}


function setRepoEnabledValue()
{
    licenseType=$1
    setting=$2

    log TRACE1 3009 "setting enabled=$setting for $licenseType license in cellsdk-${distro}.repo"

    filename="/etc/yum.repos.d/cellsdk-${distro}.repo"
    [ ! -e $filename ] && {
        log ERROR 0030 "$filename does not exist"
        return -1
    }

    mv -f $filename "$filename.orig"

    let count=0
    while read line; do
        [ "${line:0:1}" = "[" ] && {
            # this is the repository name
            repo=${line#\[}        # remove [ from front
            repo=${repo%\]}        # remove ] from end
            prod=${repo%-*}        # remove arch from the end
            arch=${repo##*-}       # remove repo from the front

            # change the setting for this platform only
            if [ "$arch" = "$platform" ]; then
                count=`echo $prod | grep -ic ${licenseType}`
            else 
                count=0
            fi
            echo $line >> $filename
            continue
        }

        keyword=`echo $line | awk -F= '{print $1}'`
        value=`echo $line | awk -F= '{print $2}'`

        if [ "$keyword" = "enabled" ] && (($count > 0)); then
            echo "enabled=${setting}" >> $filename
        else 
            echo $line >> $filename
        fi 
    done < $filename.orig
}


# get user license agreement
function printLicenseAgreement()
{
    log TRACE1 3004 "starting license agreement processing"

if [ "$distro" != "RHEL" ]; then
    cat << EOF 

The IBM SDK 3.0 for Multicore Acceleration contains components governed by 
the following Open Source licenses: 

GNU Public License (GPL) - see http://www.gnu.org/licenses/gpl.html.
  GPL licensed components include GCC Toolchain, Linux Kernel, netpbm, 
  numactl, oprofile, crash-spu-command, spu_tools, and SYSROOT image.  

Lesser GNU Public License (LGPL) - see http://www.gnu.org/copyleft/lesser.html.
  LGPL licensed components include ELFSPE, LibSPE, LibSPE2 and SYSROOT image.

Installation and use of this software requires you to certify you have read the 
licenses above, and accept their terms.  To accept these terms, type 'yes' at 
the prompt below.  If you do not wish to accept, type 'no' or press 'ctrl-C' to 
abort this program without installing. After typing 'yes', you will be 
presented with licenses for IBM owned code, Follow the instructions on the 
screen to accept the IBM Licenses and proceed with installation of the SDK.

EOF
else
    cat << EOF1

The IBM SDK 3.0 for Multicore Acceleration contains components governed by 
the following Open Source licenses: 

GNU Public License (GPL) - see http://www.gnu.org/licenses/gpl.html.
  GPL licensed components include GCC Toolchain and numactl.

Installation and use of this software requires you to certify you have read the 
license above, and accept its terms.  To accept these terms, type 'yes' at 
the prompt below.  If you do not wish to accept, type 'no' or press 'ctrl-C' to 
abort this program without installing. After typing 'yes', you will be 
presented with licenses for IBM owned code, Follow the instructions on the 
screen to accept the IBM Licenses and proceed with installation of the SDK.

EOF1
fi

    echo -n "I have read and accept the licenses above [no/yes]: "
    read answer
    case $answer in
        y | yes | Y | YES | Yes)
            log INFO 2028 "GPL/LGPL license accepted"
            statFile="${cellTop}/license/gpl/${version}/status.dat"
            mkdir -p ${cellTop}/license/gpl/${version}
            echo "#"`date` > ${statFile}
            echo "Status=9" >> ${statFile}
            return 0
            ;;
        *)
            log INFO 2002 "GPL/LGPL license rejected"
            log INFO 2003 "If you wish to know more about the Cell Broadband Engine please visit:"
            log INFO 2004 "  http://www-128.ibm.com/developerworks/power/cell/"
            return -1
            ;;
        esac
}



# install the license files
function installLicense()
{
    local licenseRpm=$1
    local licenseType=$2

    log TRACE1 3029 "installing licenses"

    # Even if the license rpm is installed, there might be an
    # updated version, so we'll just ask yum to try to install it
    log INFO 2023 "Trying to install or update $licenseRpm"
    # enable all repos so we locate all the license rpms
    log TRACE2 4053 "yum -y --enablerepo=CellSDK-*-${distro}-${platform} install $licenseRpm"
    yum -y --enablerepo=CellSDK-*-${distro}-${platform} install $licenseRpm &>/dev/null
    rpm -q $licenseRpm > /dev/null
    if [ $? -ne 0 ]; then
        log TRACE2 4062 "Unable to install $licenseRpm"
        return -1
    else 
        log INFO 2024 "$licenseRpm is installed"
    fi

    # now run lap to display the licenses if the rpm is installed 
    # but the acceptance file doesn't yet exist or has invalid content
    statFile="${cellTop}/license/$licenseType/${version}/status.dat"
    [ -e ${statFile} ] && [ `grep -c "Status=9" ${statFile}` -gt 0 ] && return 0

    if [ "$platform" = "x86" -o "$platform" = "x86_64" ]; then
        lapc=${cellTop}/license/lap/lapc/lapc.x86
    else 
        lapc=${cellTop}/license/lap/lapc/lapc.ppc32
    fi


    if [ ! -e "${lapc}" ]; then
        log ERROR 0007 "${lapc} does not exist"
        return -1
    fi

    rc=0
    if [ $auto -gt 0 ]; then
         ${lapc} -t 5 -l ${cellTop}/license/lap/$licenseType -s ${cellTop}/license/
    else 
         ${lapc} -l ${cellTop}/license/lap/$licenseType -s ${cellTop}/license/
    fi
    rc=$?
    [ $rc -eq 3 ] && {
        log INFO 2013 "$licenseType license declined.  Exiting"
        exit 0
    }
    [ $rc -eq 9 ] && {
        log INFO 2014 "$licenseType license accepted."
        verifyDistro
    }
    [ $rc -eq 5 ]  && log TRACE2 4064 "lapc rc=05 ${myName} license bypassed"
    [ $rc -eq 11 ] && log TRACE2 4066 "lapc rc=11 LA input error"
    [ $rc -eq 13 ] && log TRACE2 4067 "lapc rc=13 LI input error"
    [ $rc -eq 15 ] && log TRACE2 4068 "lapc rc=15 error while writing files"
    [ $rc -eq 17 ] && log TRACE2 4069 "lapc rc=17 missing arguments"
    [ $rc -eq 18 ] && log TRACE2 4070 "lapc rc=18 invalid arguments"
    [ $rc -eq 19 ] && log TRACE2 4071 "lapc rc=19 path to LA files invalid"
    [ $rc -eq 20 ] && log TRACE2 4072 "lapc rc=20 path to read status file invalid"
    [ $rc -eq 21 ] && log TRACE2 4073 "lapc rc=21 path to write status file invalid"
    [ $rc -eq 22 ] && log TRACE2 4074 "lapc rc=22 master path invalid"
    [ $rc -eq 23 ] && log TRACE2 4075 "lapc rc=23 out of memory"
    if [ -e ${cellTop}/license/license ]; then
        mkdir -p ${cellTop}/license/$licenseType/${version}
        mv ${cellTop}/license/license/status.dat ${cellTop}/license/$licenseType/${version}/status.dat
        mv ${cellTop}/license/license/* ${cellTop}/license/$licenseType
        rmdir ${cellTop}/license/license
        return 0
    else
        return $rc
    fi
}


# install the license files
function installAllLicenses()
{
    # now install the license files and get user acceptance
    mkdir -p ${cellTop}/license/gpl/${version}
    statFile="${cellTop}/license/gpl/${version}/status.dat"
    [ ! -e "$statFile" ] && {
        echo "${myName} logs to ${cellLog}"
        verifyDistro
        if [ $auto -eq 0 ]; then
            printLicenseAgreement
            [ $? -ne 0 ] && exit 1
        # in auto mode, we assume the user is accepting the license
        else
            statFile="${cellTop}/license/gpl/${version}/status.dat"
            mkdir -p ${cellTop}/license/gpl/${version}
            echo "#"`date` > ${statFile}
            echo "Status=9" >> ${statFile}
        fi
    }
    setRepoEnabledValue open 1 

    for licenseType in product devel extras-${distro}; do
        licenseRpm="cell-${licenseType}-license"

        # don't install the devel license if the product license is already installed
        if [ "$licenseType" = "devel" ]; then
            rpm -q cell-product-license > /dev/null
            prodInstalled=$?
            [ $prodInstalled -eq 0 ] && {
                setRepoEnabledValue devel 0 
                continue
            }
        fi

        # don't permit installing extras if the product is not installed
        if [ `echo $licenseType | grep -c extras` -gt 0 ]; then
            rpm -q cell-product-license > /dev/null
            prodInstalled=$?
            rpm -q cell-devel-license > /dev/null
            develInstalled=$?
            if [ $prodInstalled -eq 1 -a $develInstalled -eq 1 ]; then
                log INFO 2033 "cellsdk is unable to find the SDK files in the yum repositories."
                log INFO 2033 "Please be sure you used the --iso flag or that you can connect to the network."
                exit 1
            fi
        fi

        # Only update the product license if this is an update
        if [ "$task" = "update" ] && [ "$licenseType" != "product" ]; then 
            continue;
        fi
           
        # if the license isn't already installed, do so
        rpm -q cell-$licenseType-license > /dev/null
        if [ $? -ne 0 ] || [ ! -e "${cellTop}/license/$licenseType/$version/status.dat" ]; then
            installLicense $licenseRpm $licenseType
            if [ $? -ne 0 ]; then 
                log TRACE1 3007 "Disabling ${licenseType} repositories"
                setRepoEnabledValue ${licenseType} 0 
            else 
                setRepoEnabledValue ${licenseType} 1 
            fi
        fi
    done

    # lastly, refresh our list of enabled repositories
    getEnabledRepos

    return 0
}



# usage statement
function help() 
{
cat <<-EOM

'$progname' is a script used for installing the IBM cell sdk
Usage: $progname [OPTIONS] [--iso ISO_DIR] TASK
        ISO_DIR is the directory where ${myName} iso's have been downloaded.
          If not specified, network or cdrom install is assumed.
        TASK is one of install, update, uninstall, verify, mount, unmount, removeUpdate
        OPTIONS are:
          Note:  if you specify gui, you cannot specify runtime or auto
          [ -g | --gui]            use pirut or pup
          [ -r | --runtime ]       only install runtime, not development, files
          [ -a | --auto ]          auto-install (silent, no prompts)
          [ -? | -h | --help ]     display this help
          [ -V | --version ]       display $progname version
          [ -q | --quiet ]         quiet
          [ -v | --verbose ]       verbose
          [ -vv | --very-verbose ] very verbose

EOM
    exit 0
}


# parse the command line options
function parseOptions() 
{
    log TRACE1 3010 "parsing command line options"
    log TRACE2 4009 "parseOptions:  args=$@"

    let parseErrors=0

    [ $# -le 0 ] && {
        log TRACE2 4010 "parseOptions:  no args" && help
    }
    while [ $# -gt 0 ]; do
        case $1 in
        -\? | -h | --help)
            help --help; return $?;
            ;;
        -q | --quiet)
            DEBUG=0; shift;
            ;;
        -v | --verbose)
            DEBUG=2; shift;
            yumCmd="yum -d 3 -e 3"
            ;;
        -vv | --very-verbose)
            DEBUG=3; shift;
            yumCmd="yum -d 10 -e 10"
            ;;
        -V | --version)
            rpm --quiet -q cell-install
            if [[ $? -ne 0 ]]; then
                echo "Cannot get version because the cell-install rpm is not installed"
            else 
                version=`rpm -q --qf '%{version}-%{release}' cell-install`
                echo "IBM Cell Broadband Engine SDK $version"
            fi
            exit
            ;;
        -a | --auto)
            log TRACE2 4011 "parseOptions:  setting auto=1"
            auto=1; shift;
            ;;
        -g | --gui)
            log TRACE2 4012 "parseOptions:  setting gui=1"
            gui=1; shift;
            ;;
        -r | --runtime)
            log TRACE2 4013 "parseOptions:  setting runtime=1"
            runtime=1; shift;
            ;;
        -i | --iso)
            log TRACE2 4014 "parseOptions:  setting isoDir=$2"
            isoDir=$2; shift; shift;
            if [ ! -d "$isoDir" ]; then 
                log ERROR 0009 "parseOptions:  $isoDir is not a directory" 
                log ERROR 0010 "you must provide a directory name after the --iso flag" 
                ((parseErrors++)) 
                isoDir=""
            fi
            ;;
        install | update | uninstall | verify | mount | unmount | removeUpdate )
            log TRACE2 4015 "parseOptions:  setting task=$1"
            task=$1; shift;
            ;;
        *)
            log ERROR 0011 "unrecognized flag $1" && ((parseErrors++))
            shift;
            ;;
        esac
    done

    log TRACE2 4016 "variables set to auto=$auto, gui=$gui, runtime=$runtime, isoDir=$isoDir, task=$task"

    # do a little checking
    (( ($gui + $auto) > 1 )) && 
        log ERROR 0012 "--auto and --gui cannot both be set" && ((parseErrors++))
    (( ($gui + $runtime) > 1 )) && 
        log ERROR 0013 "--runtime and --gui cannot both be set" && ((parseErrors++))
    [ "$task" = "" ] && 
        log ERROR 0014 "you must specify install, update, uninstall, verify, mount, unmount or removeUpdate" && ((parseErrors++))
 
    return $parseErrors
}




# Get the package list of the specified repository (prod/arch)
# by reading the yum comps.xml metadata file stored in
# ${cellTop}/yum-repos
function getRpmsFromRepo()
{
    local prod=$1
    local arch=$2
    log TRACE2 4061 "getting list of rpms in $prod/$arch product set"

    let i1=${#installedRpmsArray[@]}        # current count
    let i2=${#missingDefaultRpmsArray[@]}   # current count

    tmpFile="/tmp/${0##*/}.$$"
    local fn="${cellTop}/yum-repos/$prod/$arch/repodata/comps.xml"
    [ ! -e $fn ] && return
    while read line; do
        line=${line/^*</<}    # strip leading blanks
        line=${line/>*$/>}    # strip trailing blanks
    
        # Store the yum group 
        if [ "$line" = "<group>" ]; then
            read line;
            group=${line#*>}    # remove metaflag from front
            group=${group%<*}   # removing closing metaflag
        fi
    
        # Get a list of the packages in the group
        let count=`echo $line | grep -c "<packagereq"`
        if ((count > 0)); then
            type=${line#*=\"}
            type=${type%\"*};
            rpm=${line#*>}  # remove metaflag from front
            rpm=${rpm%<*}   # removing closing metaflag
    
            # Get the full rpm name, including the arch
            rpmName=`rpm -q $rpm --qf '%{name}-%{version}-%{release}.%{arch} '`
            if [[ $? -ne 0 ]]; then 
                rpmName="$rpm not installed"
                printf "    %-9s %-25s %-30s\n" $type $group "$rpmName" >> $tmpFile
                if [ "$type" = "default" ]; then
                    missingDefaultRpmsArray[$i2]="$type,$group,$rpmName"
                    ((i2++))
                fi 
            else 
                # we have both ppc and ppc64 versions of some rpms, so we could
                # have gotten two rpms back from our rpm query
                for r in $rpmName; do
                    installedRpmsArray[$i1]="$type,$group,$r"
                    printf "    %-9s %-25s %-30s\n" $type $group "$r" >> $tmpFile
                    ((i1++))
                done
            fi
        fi
    done < $fn
    
    # display the results written in the tmpFile
    sort $tmpFile | uniq
    rm $tmpFile
}



# mount the latest version of each product iso available,
# for this distro only, on $mountPoint
function mountIsos()
{
    log TRACE1 3011 "mounting ${myName} iso's"

    # Look for iso's in the --iso directory specified by the user
    # Only mount isos for product-sets that are enabled in the yum repository file
    for repo in `echo ${enabledReposArray[@]} ${disabledReposArray[@]}`; do
        log TRACE2 4017 "mountIsos: enabled repository = $repo"
        isoFile=""
        prodSet=${repo%-*}      # remove the platform on end of repo name
        plat=${repo##*-}        # remove the product from front of repo name

        # There could be multiple versions of an iso in the directory.
        # If there is more than one iso for the prodSet, we'll take
        # the newest (sorted by iso name), so we call sort with -r
        # to sort in reverse order so the most recent version is on top
        list=`ls ${isoDir}/${prodSet}*.iso 2>/dev/null`
        list=`echo $list | fmt -w1 | sort -r`
        for isoFile in `echo $list`; do
            break
        done
        [ "$isoFile" = "" ] && continue
        log TRACE2 4018 "found $isoFile for mounting"

        # don't try to mount something that's already mounted
        baseName=`basename $isoFile`
        baseName=${baseName%.iso}   # remove .iso from end of filename
        what=""                     # what is mounted
        where=""                    # and where is it mounted
        tmpFile="/tmp/${0##*/}.$$"
        grep $baseName /etc/mtab > $tmpFile
        while read line; do
            # mtab format:  what where rest-of-line
            what=${line%% *}        # strip from space to EOL
            where=${line#* }        # strip up to & including space
            where=${where%% *}      # strip from space to EOL
        done < $tmpFile
        rm $tmpFile

        if [ "$where" != "" ]; then
            log TRACE2 4019 "$what is already mounted on $where"
            continue
        fi

        log TRACE2 4020 "mkdir -p ${mountPoint}/${baseName}"
        mkdir -p ${mountPoint}/${baseName}
        [[ $? -ne 0 ]] && {
            log ERROR 0015 "Failed:  mkdir -p {$mountPoint}/${baseName}"
            exit -1
        }

        log TRACE2 4021 "mount -o loop ${isoFile} ${mountPoint}/${baseName}"
        mount -o loop ${isoFile} ${mountPoint}/${baseName}
        [[ $? -ne 0 ]] && {
            log ERROR 0016 "Failed:  mount -o loop ${isoFile} ${mountPoint}/${baseName}"
            exit -1
        }

    done

    # Do not permit both the product and trial versions to be mounted at the 
    # same time
    local release=`rpm -q cell-install --qf '%{version}.%{release}'`
    [ -e "${mountPoint}/CellSDK-Product-${distro}_${release}" ] &&
    [ -e "${mountPoint}/CellSDK-Devel-${distro}_${release}" ] &&
        umount ${mountPoint}/CellSDK-Devel-${distro}_${release} 2>/dev/null

}


# Look for mounted iso's
function makeRepositoryLinks()
{
    log TRACE1 3012 "Making links to iso repository directories"

    tmpFile="/tmp/${0##*/}.$$"
    grep iso9660 /etc/mtab > $tmpFile
    while read line; do
        # mtab format:  what where rest-of-line
        what=${line%% *}        # what is mounted (strip from space to EOL)
        where=${line#* }        # where is it mounted (strip up to & including space)
        where=${where%% *}      # strip from space to EOL

        # look for the marker file (<repo>_*.marker, for
        # example: CellSDK-Product-RHEL-x86_64_3.0.0.0.0.marker) in the
        # mounted iso's.  If we find one, make a link to the appropriate
        # ${mountPoint} directory.
        for mFile in `find ${where} -name CellSDK*.marker`; do
            mFile=`basename ${mFile}` # get the filename
            repo=${mFile%_*}          # remove release on, leaving yum repo name
            prodSet=${repo%-*}        # remove the platform from the end of repo name
            plat=${repo##*-}          # remove the product from the front of repo name

            # Only mount the repositories for this platform
            #[ "${plat}" != "${platform}" ] && continue

            mkdir -p ${mountPoint}/${prodSet}
            [[ $? -ne 0 ]] && {
                log ERROR 0017 "Failed:  mkdir -p {$mountPoint}/${prodSet}"
                exit -1
            }

            # test to see if we've already made the link
            [ -L "${mountPoint}/${prodSet}/${plat}" ] && {
                # Only the move if we've found a newer file
                oldmFile=`basename ${mountPoint}/${prodSet}/${plat}/*.marker`

                [[ "$mFile" = "$oldmFile" ]] && continue
                [[ "$mFile" < "$oldmFile" ]] && continue
                log TRACE2 4022 "removing existing link ${mountPoint}/${prodSet}/${plat}"
                rm -f ${mountPoint}/${prodSet}/${plat}
                [[ $? -ne 0 ]] && {
                    log ERROR 0018 "Error:  rm ${mountPoint}/${prodSet}/${plat}"
                }
            }

            log TRACE2 4023 "ln -s $where/${plat} $mountPoint/${prodSet}/${plat}"
            ln -s ${where}/${plat} ${mountPoint}/${prodSet}/${plat} &>/dev/null
            [[ $? -ne 0 ]] && {
                log ERROR 0019 "Error:  ln -s ${where}/${plat} ${mountPoint}/${prodSet}/${plat}"
                exit -1
            }
        done
    done < $tmpFile
    rm $tmpFile

}


# Remove any links we made
function removeRepositoryLinks()
{
    log TRACE2 4050 "deleting files in ${mountPoint}"

    for repo in `echo ${enabledReposArray[@]}`; do
        prodSet=${repo%-*}      # remove the platform on end of repo name
        for arch in x86 x86_64 ppc64 cbea; do
            [ -e "${mountPoint}/${prodSet}/${arch}" ] && { 
                log TRACE2 4052 "deleting ${mountPoint}/${prodSet}/${arch}"
                rm -f ${mountPoint}/${prodSet}/${arch}
                [[ $? -ne 0 ]] && {
                    log ERROR 0027 "Failed:  rm -f ${mountPoint}/${prodSet}/${arch}"
                }
            }
        done
        # try to remove the directory.  If it's not empty, this will fail.
        rmdir ${mountPoint}/${prodSet} &>/dev/null
    done
    rmdir ${mountPoint} &>/dev/null
}


# unmount any mounted isos.  We only unmount ${mountPoint} mounts.
function unmountIsos()
{
    log TRACE1 3013 "unmounting iso's"

    tmpFile="/tmp/${0##*/}.$$"
    log TRACE2 4024 "grep ${mountPoint} /etc/mtab > $tmpFile"
    grep "${mountPoint}" /etc/mtab > $tmpFile
    while read line; do
        # mtab format:  what where rest-of-line
        what=${line%% *}        # what is mounted (strip from space to EOL)
        where=${line#* }        # where is it mounted (strip up to & including space)
        where=${where%% *}      # strip from space to EOL
        log TRACE2 4025 "Unmounting $what from $where"
        umount $where
        if [[ $? -ne 0 ]]; then
            log ERROR 0020 "Error:  Unable to unmount $what from $where"
        else
            rmdir $where
        fi
    done < $tmpFile
    rm $tmpFile

    # remove any links we made
    for arch in x86 x86_64 ppc64 cbea; do
        find $mountPoint -name $arch -type l -print -exec rm {} \;
    done
}


# See if there is a more recent cell-install rpm.
# Since the cell-install rpm itself is not part of any yum repository, it is 
# not possible to use "yum update" to find a newer version.  We are going 
# to look first on mounted isos, and then in /tmp/sdk only.  It is expected 
# that the customer will have an update iso.
function findLatestCellsdk()
{
    log TRACE1 3016 "Trying to find cell-install rpm"

    cellInstallRpmsArray=()
    let i=0

    # Look on the mounted isos.  
    log TRACE2 4033 "looking for cell-install rpm in the iso's"
    tmpFile="/tmp/${0##*/}.$$"
    grep iso9660 /etc/mtab > $tmpFile
    while read line; do
        # mtab format:  what where rest-of-line
        what=${line%% *}        # strip from space to EOL
        where=${line#* }        # strip up to & including space
        where=${where%% *}      # strip from space to EOL
        fullName=`ls ${where}/cell-install* 2>/dev/null`
        if [ "${fullName}" = "" ]; then
            log TRACE2 4034 "cell-install not found in ${where}"
        else
            log TRACE2 4008 "found ${fullName} in ${where}"
            cellInstallRpmsArray[$i]=${fullName}
            ((i++))
        fi
    done < $tmpFile
    rm $tmpFile

    # Also look in ${mountPoint} and ${isoDir}
    fullName=`ls ${mountPoint}/cell-install* 2>/dev/null`
    [ "${fullName}" != "" ] && {
        log TRACE2 4041 "found ${fullName} in ${mountPoint}"
        cellInstallRpmsArray[$i]=${fullName}
        ((i++))
    }
    [ ! -z "$isoDir" ] && {
        fullName=`ls ${isoDir}/cell-install* 2>/dev/null`
        [ "${fullName}" != "" ] && {
            log TRACE2 4051 "found ${fullName} in ${isoDir}"
            cellInstallRpmsArray[$i]=${fullName}
            ((i++))
        }
    }
}


function installLatestCellsdk()
{
    findLatestCellsdk

    let arrayLength=${#cellInstallRpmsArray[@]}
    [ $arrayLength -eq 0 ] && {
        log TRACE1 3017 "Unable to find newer version of cell-install"
        log TRACE1 3018 "Continuing with existing version of cell-install"
        return -1
    }

    # out of all the cell-install rpms we found, determine the newest version
    savedRpm=""
    savedVersion=${version}
    for r in `echo ${cellInstallRpmsArray[@]}`; do
        newVersion=`rpm --qf '%{version}-%{release}' -qp $r`
        log TRACE2 4042 "comparing $savedVersion and $newVersion ($r)"
        [[ "$savedVersion" = "$newVersion" ]] && continue 
        [[ "$savedVersion" > "$newVersion" ]] && continue
        savedRpm=$r
        savedVersion=$newVersion
        savedName=`basename $r`
        # if we haven't already saved a copy of this cell-install rpm, do it now
        # while we've got it
        if [ ! -e ${cellTop}/updates/${savedVersion}/${savedName} ]; then
            mkdir -p ${cellTop}/updates/${savedVersion}
            cp ${savedRpm} ${cellTop}/updates/${savedVersion}
        fi
    done

    if [ "$savedRpm" != "" ]; then
        log TRACE1 3019 "rpm --quiet --upgrade $savedRpm"
        rpm -Uvh $savedRpm 
        [ $? -ne 0 ] && {
            log ERROR 0021 "install of $savedRpm failed"
            log INFO 2005  "continuing with existing version of cell-install"
            return 0
        }

        # spawn a new ${progname}.  When we get back to here, just exit
        log INFO 2006 "spawning a new ${progname} using the newer cell-install version"
        log TRACE2 4043 "/bin/bash $cellTop/${progname} $args"
        /bin/bash $cellTop/${progname} $args
        exit $?
    fi
}


function removeDirectory() 
{
    local dirName=$1
    log TRACE2 4044 "removeDirectory $dirName"

    echo " "
    echo "If you have files in the $dirName you want to keep, answer no."
    echo -n "Completely remove $dirName [y/n]? "
    read answer
    if [ "$answer" = "y" ]; then
        log TRACE2 4045 "rm -rf $dirName"
        rm -rf $dirName
        [[ $? -ne 0 ]] && {
            log ERROR 0022 "Failed:  rm -rf $dirName"
        }
    else 
        log INFO 2008 "Skipping removal of $dirName"
    fi
}



# List the rpms that are available in every enabled repository
function verifyInstallation()
{
    log TRACE1 3028 "verifying that all expected rpms are installed"
    installedRpmsArray=()    # zero out the array

    for repo in `echo ${enabledReposArray[@]}`; do
        prod=${repo%-*}        # remove arch from the end
        arch=${repo##*-}       # remove repo from the front
        echo ""
        echo repository=$repo
        getRpmsFromRepo $prod $arch
    done
}



function completeRemoval()
{
    log INFO 2009 "looking for still-installed ${myName} rpms"

    # uninstall any rpms left on the system
    installedRpmsArray=()    # zero out the array
    verifyInstallation &>/dev/null

    let installedCount=${#installedRpmsArray[@]}    # current count
    echo "installedCount=$installedCount"
    ((installedCount > 0)) &&  {
        echo "There are $installedCount ${myName} rpms still installed:"
        for ((i=0; i<$installedCount; i++)); do
            line=${installedRpmsArray[$i]}
            type=${line%%,*}                # remove from first comma to EOL
            group=${line%,*}                # remove from last comma to EOL
            group=${group#*,}               # remove to first comma
            rpm=${line##*,}                 # remove to last comma
            printf "    %-9s %-25s %-30s\n" $type $group "$rpm"
        done
        echo -n "Uninstall them [y/n]?"
        read answer
        if [ "$answer" = 'y' ]; then 
            eval $yumCmd -y $groupCmd $runtimeGroups $develGroups || {
                log ERROR 0023 "$yumCmd $groupCmd $runtimeGroups $develGroups failed"
                exit -1
            }
        else 
            return
        fi
    }

    echo " "
    echo -n "Completely remove ${myName} from the system [y/n]? "
    read answer
    if [ "$answer" != "y" ] ; then
        log INFO 2010 "User cancel of ${myName} complete removal"
        return
    fi

    # remove the cell-install rpm
    log TRACE2 4046 "uninstalling cell-install rpm"
    rpm -e cell-install
    [[ $? -ne 0 ]] && {
        log ERROR 0024 "Failed:  rpm -e cell-install"
    }

    # remove the gpg key
    # The IBM cellsdk key
    key=`rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' | grep -i cellsdk`
    if [ "$key" != "" ]; then
        key=${key/ */}
        log TRACE2 4047 "rpm -e $key --allmatches"
        rpm -e $key --allmatches
        [[ $? -ne 0 ]] && {
            log ERROR 0025 "Failed:  rpm -e $key --allmatches"
        }
    fi
    # The BSC cellsdk key
    key=`rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' | grep -i cell_support`
    if [ "$key" != "" ]; then
        key=${key/ */}
        log TRACE2 4056 "rpm -e $key --allmatches"
        rpm -e $key --allmatches
        [[ $? -ne 0 ]] && {
            log ERROR 0045 "Failed:  rpm -e $key --allmatches"
        }
    fi

    # unmount anything still mounted
    if [ "`cat /etc/mtab | grep cell-sdk-sysroot`" != "" ] ; then
        log TRACE2 4048 "Unmounting sysroot from /mnt/cell-sdk-sysroot"
        umount /mnt/cell-sdk-sysroot
    fi
    unmountIsos
    removeRepositoryLinks

    # ------------------
    # directory cleanups
    # ------------------
    log TRACE2 4049 "rm -rf /etc/yum.repos.d/cellsdk*"
    rm -rf /etc/yum.repos.d/cellsdk*
    [[ $? -ne 0 ]] && {
        log ERROR 0026 "Failed:  rm -rf /etc/yum.repos.d/cellsdk*"
    }

    removeDirectory ${cellTop}
    removeDirectory /opt/ibm/systemsim-cell
    [ -e /opt/ibm/systemsim-cellsecure ] && 
        removeDirectory /opt/ibm/systemsim-cellsecure
    removeDirectory /tmp/cellsdk/rpms
    removeDirectory /tmp/cellsdk/openSrc

    log TRACE2 4007 "rm -rf /tmp/sdk/CellSDK*"
    rm -rf /tmp/sdk/CellSDK*
    [[ $? -ne 0 ]] && {
        log ERROR 0008 "Failed:  rm -rf /tmp/sdk/CellSDK*"
    }


    # Things we didn't remove:
    # 1)  the log file ${cellLog}
    # 2)  the kernel on cell machine
    # 3)  oprofile on a cell machine
    # 4)  any isos the user downloaded
    # 5)  any sandbox directories the user created
    # 6)  the compilers installed into /opt/ibmcmp
    # 7)  the /var/cache/yum/CellSDK* directories


}



function addSpufs()
{
    [ ! -e "$cellTop/sysroot" ] && mkdir -p $cellTop/sysroot

# FIXME - still need to put spufs into /etc/fstab?
    [ "$platform" = "cbea" ] && {
    log TRACE1 3023 "Adding spufs to /etc/fstab"
        grep -i spufs /etc/fstab > /dev/null
        [[ $? -ne 0 ]] && {
            echo "spufs             /spu    spufs   defaults        00" >> /etc/fstab
            mkdir -p /spu
        }
    }
    return
}



# verify that the distro is known
function verifyDistro() {
    M7="Fedora release 7 (Moonshine)"
    R5="Red Hat Enterprise Linux"

    log TRACE2 4060 "Verifying that the distro is known"

    let foundM7=0
    for file in `ls /etc/*-release 2>/dev/null`; do
        ((foundM7 += `grep -ic "${M7}" $file`))
    done

    let foundR5=0
    # here, we have to verify that the release is at least 5.1
    for file in `ls /etc/*-release 2>/dev/null`; do
        if [ `grep -ic "${R5}" $file` -gt 0 ]; then 
            set -- `cat $file`
            while [ $# -gt 0 ]; do
                if [ "$1" = "release" ]; then shift; release=$1
                else shift
                fi
            done
        fi
        [[ "${release}" > "5.0" ]] && ((foundR5 += 1))
    done
    [ $foundM7 -eq 0 -a $foundR5 -eq 0 ] && {
        log WARNING 1000 "The SDK has not been tested with this linux release."
        log WARNING 1000 "The tested GNU/Linux version is "
        log WARNING 1000 "$M7 or"
        log WARNING 1000 "$R5 5.1 or greater"
        log WARNING 1000 "Proceeding may result in a partial or failed SDK install."
    }
}


# This function looks through the cellsdk repositories, trying
# to find the files in the list.  The list must have one rpm per
# line.

function copyFiles()
{
    local repo=$1
    local baseurl=$2
    local fileList=$3
    local outDir=$4

    local let copyErrors=0
    local let copyCount=0

    if [ ! -e ${fileList} ]; then
        log TRACE2 4054 "copyFiles list ${fileList} does not exist"
        return 1
    fi

    [ ! -e ${outDir} ]  && mkdir -p ${outDir}

    for dir in $baseurl; do
        log TRACE2 4037 "looking in $dir for files to copy"

        # If this is a file url, then we can just copy the files
        let count=`echo $dir | grep -c "file://" `
        if [ $count -gt 0 ]; then
            dir=${dir#file://}

            # if the directory is an iso mount point, it might not exist
            [ ! -e $dir ] && continue;

            for rpm in `cat ${fileList}`; do
                src=${dir}/${rpm}
                dest=${outDir}/${rpm}
                if [ -e ${dest} ]; then 
                    log TRACE1 3005 "    ${rpm} already copied"
                    continue
                fi
                [ ! -e ${src} ] && continue	# isn't in the directory
                log TRACE2 4028 "cp ${src} ${dest}"
                cp ${src} ${dest}
                if [ $? -ne 0 ]; then 
	            log TRACE2 4031 "Cannot cp ${src} to ${dest}"
                    log INFO 2036 "    ${rpm} copy failed"
                    ((copyErrors++))
                else
                    log INFO 2026 "    saving ${rpm}"
                    ((copyCount++))
                fi
            done

        # must be a URL of some sort
        else
            for rpm in `cat ${fileList}`; do
                dest=${outDir}/${rpm}
                if [ -e ${dest} ]; then 
                    log TRACE1 3006 "    ${rpm} already copied"
                    continue
                fi

                # for performance, see if yum has it cached already
                src="/var/cache/yum/$repo/packages/$rpm"
                if [ -e ${src} ]; then
                    log TRACE2 4029 "cp ${src} ${dest}"
                    cp ${src} ${dest}
                    if [ $? -ne 0 ]; then 
	                log TRACE2 4032 "Cannot cp ${src} to ${dest}"
                        log INFO 2037 "    ${rpm} copy failed"
                        ((copyErrors++))
                    else
                        log INFO 2034 "    saving ${rpm}"
                        ((copyCount++))
                    fi
                else 
                    src=${dir}/${rpm}
                    log TRACE1 3003 "    ${rpm}"
                    log TRACE2 4030 "wget ${src} ${dest}"
                    wget --no-verbose --continue -O ${dest} ${src} #&>/dev/null
                    if [ $? -ne 0 ]; then 
	                log TRACE2 4035 "Cannot wget ${src}"
                        log INFO 2038 "    ${rpm} wget failed"
                        ((copyErrors++))
                        rm -rf ${dest}
                    else
                        log INFO 2035 "    saving ${rpm}"
                        ((copyCount++))
                    fi
                fi
            done
        fi
    done

    log TRACE2 4059 "Copied ${copyCount} rpms into ${outDir}"
    
    return $copyErrors
}


# Copy files in the update repository to the hard drive
function saveFiles()
{
    local version=$1
    local repo=$2
    local baseurl=$3
    log TRACE2 4026 "Saving update files for $version, $repo, baseurl=$baseurl"

    # create the save directory
    updateDir="${cellTop}/updates/${version}/${repo}"
    mkdir -p ${updateDir}

    if [ ! -e ${updateDir}/rpmList.txt ]; then
        log TRACE1 3014 "Cannot find rpm list ${updateDir}/rpmList.txt"
        log TRACE1 3015 "Skipping copy of $repo files into ${updateDir}"
        return -1
    fi

    let updateErrors=0

    # Store the cell-install rpm for future use.  We'll just save any
    # cell-install rpm we find, while we've got it
    findLatestCellsdk
    for rpmPath in `echo ${cellInstallRpmsArray[@]}`; do
        rpmName=`basename $rpmPath`
        rpmVersion=${rpmName/cell-install-/}
        rpmVersion=${rpmVersion/.noarch.rpm}
        if [ ! -e ${cellTop}/updates/${rpmVersion}/${rpmName} ]; then
            mkdir -p ${cellTop}/updates/${rpmVersion}
        fi
        cp ${rpmPath} ${cellTop}/updates/${rpmVersion}
    done

    log INFO 2025 "Copying files to ${updateDir}"
    copyFiles $repo "$baseurl" ${updateDir}/rpmList.txt ${updateDir}
    ((updateErrors += $?))

    return $updateErrors
}



# This function uses files saved on the user's hard drive to
# remove a service update
function backoutUpdate() 
{
    if [ ! -e "${cellTop}/updates/updateVersionsList" ]; then
        log ERROR 0043 "${cellTop}/updates/updateVersionsList file missing"
        log ERROR 0033 "Unable to do backout."
        return
    fi

    # Get the current version, the previous version and the ga version
    currVersion=`rpm --qf '%{version}-%{release}' -q cell-install`
    for version in `cat ${cellTop}/updates/updateVersionsList | sort -r`; do
        [ "$version" = "$currVersion" ] && continue
        prevVersion=${version}
        break;
    done
    read gaVersion < ${cellTop}/updates/updateVersionsList
    
    [ "$currVersion" = "$gaVersion" ] && {
        log INFO 2029 "No updates available to remove."
        log INFO 2030 "Please use 'cellsdk uninstall' to remove the code"
        exit
    }

    log INFO 2031 "Starting backout of $currVersion"
    
    prevRpm="${cellTop}/updates/${prevVersion}/cell-install-${prevVersion}.noarch.rpm" 
    if [ ! -e "${prevRpm}" ]; then
        log ERROR 0031 "Cannot find ${prevRpm} for backout"
        exit
    fi
    
    # try to mount isos and make links to the repositories
    mountIsos
    makeRepositoryLinks
    
    rpmRemove=()	# list of rpms in this update
    rpmInstall=()	# replacement rpms
    let missing=0
    let index=-1
    
    # get the list of all the rpms in the update.  
    for list in ${cellTop}/updates/${currVersion}/*Update*/rpmList.txt; do
        repoName=${list/\/rpmList.txt/}     # rm '/rpmList.txt' from end
        repoArch=${repoName##*-}	    # rm up to last dash, leaving arch
        repoName=${repoName%-*}		    # strip arch off end
        repoName=`basename $repoName`	
        
        for rpm in `cat $list`; do
            longName=${rpm%.*}              # rm .rpm from end
            arch=${longName##*.}            # rm up to arch
            shortName=${longName%.*}        # rm arch from the end
            shortName=${shortName%-*}       # rm release from the end
            shortName=${shortName%-*}       # rm version from the end
            # see if this rpm is installed
            rpm -q ${longName} > /dev/null
            if [ $? -eq 0 ]; then
                ((index++))
                rpmRemove[$index]=$longName
            else
                continue
            fi
    
            # since updates are cumulative, an older rpm will only be in either the
            # previous update or in the release
            for v in $prevVersion $gaVeresion; do
                for repo in `echo ${enabledReposArray[@]}`; do
                    prodSet=${repo%-*}      # remove the platform on end of repo name
                    plat=${repo##*-}	    # remove the product from front of repo name

                    # have we already found it?
                    [ "${rpmInstall[$index]}" != "" ] && continue

                    # no?  then get the rpm name from the list
                    rpmName=`grep ${shortName} ${cellTop}/updates/${v}/$repo/rpmList.txt 2>/dev/null`

                    # might get multiple matches if there's a -devel pkg or some such
                    for r in $rpmName; do
                        s=${r%-*}    # rm release from the end
                        s=${s%-*}    # rm version from the end
                        [ "${s}" != "${shortName}" ] && continue
                        a=${r%.*}    # rm .rpm from end
                        a=${a##*.}   # rm up to arch
                        [ "${a}" != "${arch}" ] && continue
                       
                        if [ -e "${cellTop}/updates/$v/$repo/$r" ]; then
                            rpmInstall[$index]="${cellTop}/updates/$v/$repo/$r"
                        fi
                        if [ -e "${mountPoint}/${prodSet}/${plat}/${r}" ]; then
                            rpmInstall[$index]="${mountPoint}/${prodSet}/${plat}/${r}"
                        fi
                    done
                done
            done
    
            if [ "${rpmInstall[$index]}" = "" ]; then
                rpmInstall[$index]="MISSING"
		((missing++))
            fi
        done
    done
    
    # dump array for debugging
    let arrayLength=${#rpmRemove[@]}
    for ((i=0; i<arrayLength; i++)); do
        string=`printf "    replacing %-35s with %s" ${rpmRemove[$i]} ${rpmInstall[$i]}`
        log TRACE2 4063 "$string"
    done
    
    # If we have any missing rpms, ask the user if we should continue.
    # If the auto flag was given, just do the removal without any prompting.
    if ((missing > 0)); then
        log INFO 2032 "Unable to locate $missing replacements for rpms in the update:"
        for ((i=0; i<arrayLength; i++)); do
            if [ "${rpmInstall[$i]}" = "MISSING" ]; then
                log INFO 2011 "    ${rpmRemove[$i]}"
            fi
        done
        log WARNING 1002 "Any missing rpms listed above will be uninstalled and not replaced if you continue."
    fi

    if [ $auto -eq 0 ]; then
        (($missing == 0)) && log INFO 2042 "All needed replacement rpms have been located."
        echo -n "Shall I remove the update? [y/n] "
        read answer    
        if [ "$answer" != 'y' ]; then
            exit
        fi
    fi

    # Remove the rpms
    for ((i=0; i<arrayLength; i++)); do
        # Updates are cumulative.  If we found the same rpm in a previous
        # update, there is no need to uninstall/install it.
        if [ ! -z "${rpmRemove[$i]}" -a ! -z "${rpmInstall[$i]}" ]; then  
            remove=${rpmRemove[$i]}
            instal=`basename ${rpmInstall[$i]}`
            instal=${instal%.*}              # rm .rpm from end
            [ "$remove" = "$instal" ] && continue
        fi

        log TRACE2 4036 "replacing $remove with $instal"
        log TRACE2 4038 "rpm -ev --nodeps ${rpmRemove[$i]}"
        [ ! -z "${rpmRemove[$i]}" ] && {
            rpm -ev --nodeps ${rpmRemove[$i]}
            [ $? -ne 0 ] && {
                log ERROR 0028 "Removal of ${rpmRemove[$i]} failed"
            }
        }
        if [ "${rpmInstall[$i]}" != "MISSING" ]; then
            log TRACE2 4002 "rpm -ivh --nodeps --force ${rpmInstall[$i]}"
            # reinstalling a ppc version fails if the ppc64 version
            # still exists at the old higher version, so we're using --force
            rpm -ivh --nodeps --force ${rpmInstall[$i]}
            [ $? -ne 0 ] && {
                log ERROR 0029 "Reinstall of ${rpmInstall[$i]} failed"
            }
        fi
    done

    # Remove the update from the bottom of the list 
    updateList=${cellTop}/updates/updateVersionsList
    cp ${updateList} ${updateList}.orig
    sed -e '$d' < ${updateList}.orig > ${updateList}
    rm ${updateList}.orig    

    # Remove the update directory
    log TRACE2 4039 "removing ${cellTop}/updates/${currVersion}"
    rm -rf "${cellTop}/updates/${currVersion}"

    # Remove the update license acceptances
    log TRACE2 4077 "removing update license acceptances"
    for file in `find ${cellTop}/license -name status.dat | grep ${currVersion}`; do
        rm -rf $file
        rmdir `dirname $file` 2>/dev/null
    done

    # Replace the cell-install rpm
    log TRACE2 4040 "replacing cell-install with ${prevRpm}"
    rpm -e --nodeps cell-install
    rpm -Uvh --nodeps ${prevRpm}

    log INFO 2012 "Backout complete"

}


function copyRpmList()
{
    # copy the rpmList.txt file into the save directory
    for repo in `echo ${enabledReposArray[@]}`; do
        prod=${repo%-*}        # remove arch from the end
        arch=${repo##*-}       # remove repo from the front
        mkdir -p ${cellTop}/updates/${version}/$repo
        cp ${cellTop}/yum-repos/$prod/$arch/rpmList.txt ${cellTop}/updates/${version}/$repo/rpmList.txt

        # While we're at it, let's copy any files we can find in the yum cache
        # This should be pretty fast
        for rpm in `cat ${cellTop}/yum-repos/$prod/$arch/rpmList.txt`; do
            src="/var/cache/yum/$repo/packages/$rpm"
            dest="${cellTop}/updates/${version}/$repo/$rpm"
            if [ -e ${src} -a ! -e ${dest} ]; then
                log TRACE2 4027 "cp ${src} ${dest}"
                cp ${src} ${dest}
            fi
        done
    done

}


# make isolation/cellsecure links
function linkSecure()
{
    simulator="/opt/ibm/systemsim-cell/images/cell"
    secureSim="/opt/ibm/systemsim-cellsecure/images/cell"
    if [ -e "${secureSim}" ]; then
        # -L flag tests if file exists and is a symbolic link
        if [ -e "${simulator}/sysroot_disk" -a ! -L ${secureSim}/sysroot_disk ]; then
            ln -s ${simulator}/sysroot_disk ${secureSim}/sysroot_disk
        fi
        if [ -e "${simulator}/vmlinux" -a ! -L ${secureSim}/vmlinux ]; then
            ln -s ${simulator}/vmlinux ${secureSim}/vmlinux
        fi
    fi
}


# post-install actions
function postInstall()
{
    # save the version number that just got installed
    mkdir -p ${cellTop}/updates
    if [ ! -e ${cellTop}/updates/updateVersionsList ]; then
        echo ${version} > ${cellTop}/updates/updateVersionsList
    elif [ `grep -c ${version} ${cellTop}/updates/updateVersionsList` -eq 0 ]; then
        echo ${version} >> ${cellTop}/updates/updateVersionsList
    fi

    # make a copy of the original cell-install rpm
    read gaVersion < ${cellTop}/updates/updateVersionsList
    mkdir -p ${cellTop}/updates/$gaVersion
    gaRpm="cell-install-$gaVersion.noarch.rpm"
    if [ ! -e "${cellTop}/updates/$gaVersion/$gaRpm" ]; then
        findLatestCellsdk
        for rpmPath in `echo ${cellInstallRpmsArray[@]}`; do
            rpmName=`basename $rpmPath`
            rpmVersion=${rpmName/cell-install-/}
            rpmVersion=${rpmVersion/.noarch.rpm}
            if [ ! -e "${cellTop}/updates/${rpmVersion}/${rpmName}" ]; then
                mkdir -p ${cellTop}/updates/${rpmVersion}
                cp ${rpmPath} ${cellTop}/updates/${rpmVersion}
            fi
        done
    fi

    copyRpmList

    # Look in the cbea repositories for the files that
    # need to be installed into the simulator sysroot
    rpm -q systemsim-cell &>/dev/null
    [ $? -eq 0 ] && {
        let i=0
        if [ -e "${cellTop}/sysrootList.txt" -a ! -e "/tmp/cellsdk/rpms" ]; then
            log INFO 2022 "Copying rpms to install in the simulator sysroot"
            for repo in `echo ${enabledReposArray[@]}`; do
                baseurl=${baseurlArray[$i]}
                ((i++))
    
                cbeaRepo=`echo $repo | sed -e s/$platform/cbea/g`
                cbeaBaseurl=`echo $baseurl | sed -e s/$platform/cbea/g`
                copyFiles $cbeaRepo "$cbeaBaseurl" ${cellTop}/sysrootList.txt /tmp/cellsdk/rpms
            done
        fi
    }

  
    # Look for the cellsdk versions of the open-source rpms
    local rpmDir="/tmp/cellsdk/openSrc"
    local rpmList="${cellTop}/openSrcRpmsList.txt"
    let i=0
    if [ ! -e "${rpmDir}" ]; then
        mkdir -p ${rpmDir}

        for repo in `echo ${enabledReposArray[@]}`; do
            rm -f ${rpmList}

            # make the list of rpms that we should be installing
            prod=${repo%-*}        # remove arch from the end
            arch=${repo##*-}       # remove repo from the front
            log INFO 2041 "Copying SDK versions of open source rpms to /tmp/cellsdk/openSrc"
            for item in blas numactl oprofile; do
                grep $item ${cellTop}/yum-repos/$prod/$arch/rpmList.txt \
                   | grep -v cross >> ${rpmList}
            done
            baseurl=${baseurlArray[$i]}
            ((i++))
            copyFiles $repo "$baseurl" ${rpmList} ${rpmDir}
        done
        rm -f ${rpmList}
    fi

  
    # Verify that all default rpms are installed and inform
    # user if they are not.  This is an informational message only.
    # The user could have choosen not to install something.
    if ((runtime == 0)); then 
        installedRpmsArray=()
        missingDefaultRpmsArray=()
        # if we didn't get a yum failure, then check that everything expected really got installed
        if [ $rc -eq 0 ]; then
            log TRACE1 3008 "verifying that all expected rpms are installed"
            verifyInstallation &>/dev/null
            missing=${#missingDefaultRpmsArray[@]}
            if [ $missing -gt 0 ]; then
                log INFO 2020 "Not all default rpms are installed"
                for ((i=0; i<$missing; i++)); do
                    line=${missingDefaultRpmsArray[$i]}
                    # the install type (default,optional,mandatory) is in quotes
                    type=${line%%,*}       # remove from first comma to EOL
                    group=${line%,*}       # remove from last comma to EOL
                    group=${group#*,}      # remove to first comma
                    rpm=${line##*,}        # remove to last comma
                    printf "    %-9s %-25s %-30s\n" $type $group "$rpm"
                done
                log INFO 2021 "If you wish to install the missing rpms, please rerun $progname install again"
            fi
        fi
    fi

    # Install the sdk version of the open source rpms (blas, numactl, oprofile)
    # Do this only if
    # 1)  we haven't already (the done file doesn't exist)
    # 2)  the directory contains files
    # 3)  the user has installed some arbitrary number of packages (5, arbitrarily)
    let count=${#installedRpmsArray[@]}        # current count of installed rpms

    if [ ! -e ${rpmDir}/done ] && 
       [ `ls ${rpmDir} | wc -l` -ne 0 ] && 
       ((count > 5)); then
        log INFO 2039 "Removing the ${distro} versions of the rpms in /tmp/cellsdk/openSrc"
        for rpmName in `ls ${rpmDir}`; do
            shortName=${rpmName%-*}          # rm last dash to EOF (ver+arch+.rpm)
            shortName=${shortName%-*}        # rm last dash to EOF (rel)

            # try to remove it
            if [ "$shortName" = "oprofile" ]; then
                log TRACE2 4057 "yum -y remove $shortName"
                yum -y remove oprofile
            else 
                log TRACE2 4055 "rpm -e --nodeps $shortName --allmatches"
                rpm -e --nodeps $shortName --allmatches &>/dev/null
            fi
        done
        log INFO 2027 "Installing the cellsdk rpms in /tmp/cellsdk/openSrc"
        yum -y localinstall `find ${rpmDir} -type f -print`
        touch ${rpmDir}/done
    fi

    # make system-cellsecure links, if necessary
    linkSecure

    rpm -q systemsim-cell &>/dev/null
    [ $? -eq 0 ] && {
        log INFO 2007 "Please run '/opt/cell/cellsdk_sync_simulator install'"
        log INFO 2007 "to install IBM-licensed rpms into the simulator."
    }
}


# post update actions
function postUpdate()
{
    # record the version number that just got installed
    mkdir -p ${cellTop}/updates
    if [ ! -e ${cellTop}/updates/updateVersionsList ]; then
        log ERROR 0046 "${cellTop}/updates/updateVersionsList file missing"
        log ERROR 0046 "Perhaps cellsdk install has not been run?"
    elif [ `grep -c ${version} ${cellTop}/updates/updateVersionsList` -eq 0 ]; then
        echo ${version} >> ${cellTop}/updates/updateVersionsList
    fi

    copyRpmList

    # save the update rpms
    let index=0
    for repo in `echo ${enabledReposArray[@]}`; do
        baseurl=${baseurlArray[$index]}
        ((index++))
        # we will only save RHEL Open and Product files 
        [[ "${repo}" != *"RHEL"* ]] && continue
        [[ "${repo}" != *"Update"* ]] && continue
        saveFiles $version $repo "$baseurl"
    done

    # if we haven't saved the original rpms yet, ask the user if we should
    read gaVersion < ${cellTop}/updates/updateVersionsList
    if [ ! -e "${cellTop}/updates/${gaVersion}/saved" ]; then
        if [ $auto -eq 0 ]; then
            echo ""
            echo "Would you like to save the initial rpms in case "
            echo -n "you want to remove this update later? [y/n] "
            read answer
            echo ""
        else
            answer=y
        fi
    
        if [ "$answer" = 'y' ]; then 
            let index=0
            for repo in `echo ${enabledReposArray[@]}`; do
                # we will only save RHEL Open and Product files 
                [[ "${repo}" != *"RHEL"* ]] && continue
                [[ "${repo}" != *"Open"* ]] && [[ "${repo}" != *"Product"* ]] && {
                    continue
                }
                baseurl=${baseurlArray[$index]}
                ((index++))
                saveFiles $gaVersion $repo "$baseurl"
            done
        fi
    fi

    # make system-cellsecure links, if necessary
    linkSecure

}


function checkRhelPrerequisites()
{
    machine=`uname -m`        # i686, x86_64, ppc64

    # libspe2 is required on ppc machines, including cbea machines
    if [[ "$machine" = "ppc"* ]]; then
        rpm -q libspe2.ppc libspe2.ppc64 > /dev/null
        rc=$?
        if [ $rc -ne 0 ]; then
            log ERROR 0050 "The libspe2.ppc and libspe2.ppc64 packages are required."
            log ERROR 0050 "Please install them from the Red Hat Supplemental CDROM."
            exit -1
        fi
    fi

    # check for the ppu-sysroot rpms 
    if [[ "$platform" = "x86"* ]] && (($runtime == 0)); then
        rpm -q ppu-sysroot ppu-sysroot64 > /dev/null
        rc=$?
        if [ $rc -ne 0 ]; then
            log ERROR 0052 "The ppu-sysroot and ppu-sysroot64 packages are required.  See the "
            log ERROR 0052 "install documentation for instructions on creating and installing them."
            exit -1
        fi
    fi

    return $missing
}



# install, update, uninstall, etc.
function doTask() 
{
    log TRACE1 3024 "starting $task"

    # This case statement sets up the yum command, which is
    # executed below the case statement
    groupCmd=""
    yumgui=""
    case $task in 
        verify)
            installedRpmsArray=()	# zero out array
            missingDefaultRpmsArray=()  # zero out array
            verifyInstallation
            return 0
            ;;
        mount)
            [ ! -z "$isoDir" ] && mountIsos
            makeRepositoryLinks
            return 0
            ;;
        unmount)
            unmountIsos
            removeRepositoryLinks
            return 0
            ;;
        removeUpdate)
            backoutUpdate
            return 0
            ;;
        install) 
            [ ! -z "$isoDir" ] && mountIsos
            makeRepositoryLinks

            # install the gpg key first, since the license rpm is signed
            log TRACE1 3025 "Installing the gpg keys"
            # The IBM cellsdk key
            key=`rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' | grep -i cellsdk`
            if [ "$key" == "" ]; then
                rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-cellsdk
            fi
            # The BSC cellsdk key
            key=`rpm -q gpg-pubkey --qf '%{name}-%{version}-%{release} --> %{summary}\n' | grep -i cell_support`
            if [ "$key" == "" ]; then
                rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-cellsdk-open
            fi

            installAllLicenses

            addSpufs

            if [ "$distro" = "RHEL" ]; then
                checkRhelPrerequisites
            fi

            groupCmd="groupinstall"
            yumgui="pirut"
            ;;
        update)
            log INFO 2040 "Update rpms using CellSDK-Updates-${distro}-${platform} yum repository"
            [ ! -z "$isoDir" ] && mountIsos
            makeRepositoryLinks

            # if any version of licenses have been installed before, then
            # we assume that they have already done an install once, and
            # we'll just try to get this version installed/accepted.
            let count=`find ${cellTop}/license -name status.dat -print 2>/dev/null | wc -l` 
            if ((count == 0)); then
                log ERROR 0040 "The ${myName} license is not yet installed"
                log ERROR 0040 "Please run install instead of update"
                exit -1
            else
	        installAllLicenses
                if [ $? -ne 0 ]; then 
	            log ERROR 0041 "License acceptance not complete.  Exiting." 
                    exit -1
                fi
            fi

            # Be sure we're running the latest cell-install version.  
            installLatestCellsdk

            # You can't replace the sysroot if it is mounted,
            # so unmount it before an update
            line=`grep $cellTop/sysroot /etc/mtab`
            if [ "$line" != "" ] ; then
                # mtab format:  what where rest-of-line
                where=${line#* }        # strip up to & including space
                where=${where%% *}      # strip from space to EOL
                log TRACE1 3026 "Unmounting sysroot from $where"
                umount $where
            fi

            # cellsdk update only uses the CellSDK-Updates* repository
            groupCmd="--disablerepo=* --enablerepo=CellSDK-Updates-${distro}-${platform} update"
            yumgui="pup"
            ;;
        uninstall)
            # enable all repos so we locate all the license rpms
            groupCmd="--enablerepo=CellSDK-*-${distro}-${platform} groupremove"
            yumgui="pirut"
            ;;
        *)
        log ERROR 0035 "doTask:  Unrecognized install command $task"
            return -1
    esac

    # Execute the command we set up above
    let rc=0		# return code
    if ((gui > 0)); then 
        log INFO 2015 "Calling $yumgui"
        eval $yumgui
    # update any installed SDK rpms for which a newer version is available
    elif [ "$task" = "update" ]; then
        if ((auto > 0)); then 
            log INFO 2043 "Calling yum -y $groupCmd"
            yum -y $groupCmd
        else
            log INFO 2044 "Calling yum $groupCmd"
            yum $groupCmd
        fi
    elif ((runtime > 0)); then 
        if ((auto > 0)); then 
            log INFO 2016 "Calling yum -y $groupCmd $runtimeGroups"
            eval $yumCmd -y $groupCmd $runtimeGroups || {
                rc=$?
                log ERROR 0036 "yum -y $groupCmd $runtimeGroups failed with rc=$rc" 
            }
        else 
            log INFO 2017 "Calling yum $groupCmd $runtimeGroups"
            eval $yumCmd $groupCmd $runtimeGroups || {
                rc=$?
                log ERROR 0037 "yum $groupCmd $runtimeGroups failed with rc=$rc" 
            }
        fi
    elif ((auto > 0)); then 
        log INFO 2018 "$yumCmd -y $groupCmd $runtimeGroups $develGroups"
        eval $yumCmd -y $groupCmd $runtimeGroups $develGroups || {
            rc=$?
            log ERROR 0038 "yum -y $groupCmd $runtimeGroups $develGroups failed with rc=$rc" 
        }
    else  
        log INFO 2019 "$yumCmd $groupCmd $runtimeGroups $develGroups"
        eval $yumCmd $groupCmd $runtimeGroups $develGroups || {
            rc=$?
            log ERROR 0039 "yum $groupCmd $runtimeGroups $develGroups failed with rc=$rc" 
            return -1
        }
    fi

    # Now do a few things after yum/pirut/pup runs

    # Set up the IBM-Tivoli License Manager file
    if ((runtime > 0)) && [ ! -e "${cellTop}/itlm/CC0049620300.SYS2" ]; then
        cp ${cellTop}/itlm/runtime.itlm  ${cellTop}/itlm/CC0049620300.SYS2
    elif [ ! -e "${cellTop}/itlm/CC0049610300.SYS2" ]; then 
        cp ${cellTop}/itlm/devel.itlm  ${cellTop}/itlm/CC0049610300.SYS2
    fi


    [ "$task" = "install" ] && {
        postInstall
    }

    [ "$task" = "update" ] && {
        postUpdate
    }

    # completeRemoval is interactive, so don't run it if they've
    # selected auto
    if [ "$task" = "uninstall" ]; then
        if [ $auto -eq 0 ]; then
            # See if they want this product complete removed
            completeRemoval
        fi
        # if the license rpm is removed, then also remove the acceptance file
        for licenseType in product devel extras-${distro}; do
            rpm -q cell-${licenseType}-license > /dev/null
            [ $? -eq 1 ] && [ -e ${cellTop}/license/${licenseType}/${version}/status.dat ] && { 
                rm -f ${cellTop}/license/${licenseType}/${version}/status.dat 
            }
        done
        # if the cell-install rpm is removed, then also remove the gpl acceptance file
        rpm -q cell-install > /dev/null
        [ $? -eq 1 ] && [ -e ${cellTop}/license/gpl/${version}/status.dat ] && { 
            rm -f ${cellTop}/license/gpl/${version}/status.dat 
        }
    fi

}



# main
function main() 
{
    # are we running as root?  If not, we can't do anything, including logging
    (($UID != 0)) && { 
        echo "INFO 2000 you must have root access to run this script"
        exit
    }

    # do the command line options parse correctly?
    parseOptions $args 
    rc=$?
    if (($rc > 0)); then {
        help
    }
    else {
        log TRACE2 4005 "options parsed OK"
    }
    fi

    # Pre-checks (are we root, is yum installed, etc)
    # If there are errors, readyCheck calls help and exits
    readyCheck        

    # see if the product repository is enabled
    getEnabledRepos

    # if the default mount point doesn't exist, create it
    [ ! -e ${mountPoint} ] && mkdir -p ${mountPoint}

    version=`rpm --qf '%{version}-%{release}' -q cell-install`
    [ $? -ne 0 ] && {
        log TRACE2 4076 "Cannot determine version for cell-install rpm"
        return -1
    }

# FIXME:  set user's gpgcheck=0 in /etc/yum.conf until we have signed rpms
#    [ ! -e "/etc/yum.conf.orig" ] && cp /etc/yum.conf /etc/yum.conf.orig
#    sed -e "s/gpgcheck=1/gpgcheck=0/g" /etc/yum.conf.orig > /etc/yum.conf

    if [ $gui -gt 0 ] && [ "$task" = "install" -o "$task" = "update" ]; then 
        guiCheck
    fi

    doTask

# FIXME:  set user's gpgcheck=1 back to original /etc/yum.conf
#    [ -e "/etc/yum.conf.orig" ] && {
#        cp /etc/yum.conf.orig /etc/yum.conf
#        rm /etc/yum.conf.orig
#    }
}


# shell entry point: call main() function, exit with main()'s retval
#export LC_ALL=C;
#main "$@";
args="$@"
main
