#!/bin/bash
#set -x

# --------------------------------------------------------------
# (C) Copyright 2001,2007
# International Business Machines Corporation,
#
# All Rights Reserved.
# --------------------------------------------------------------


#  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
rpmsArray=()
installedRpmsArray=()
missingDefaultRpmsArray=()
cellInstallRpmsArray=()

# cell-specific locations, logs, etc.
cellTop="/opt/cell"
mountPoint="${cellTop}/yum-repos"
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 Performance Tools'"

# command line arguments
auto=0       # auto install?
allFlag=0
runtime=0    # install only the runtime packages?
task=""      # one of install, update, uninstall, verify, mount, unmount, updateDetail
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;

    # if we're root, we'll write all messages to the log
    (($UID == 0)) && { 
        echo "`date +'%b %d %H:%M:%S'` $level-$number: $mesg" >> $messages || exit 1;
    }

    # warning and error messages are always logged, others are based on verbosity flags
    [ "$level" == "INFO"   ] && [ $DEBUG -le 0 ] && return 0;
    [ "$level" == "TRACE1" ] && [ $DEBUG -le 1 ] && return 0;
    [ "$level" == "TRACE2" ] && [ $DEBUG -le 2 ] && return 0;
    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 is not installed" 
        ((errors++))
    else 
        log TRACE2 4000 "The cell-install rpm is installed"
    fi

    # is the yum rpm installed?
    rpm --quiet -q yum 
    if [ $? -ne 0 ]; then
        log ERROR 0001 "The yum rpm is not installed" 
        ((errors++))
    else 
        log TRACE2 4001 "The yum rpm is installed"
    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"

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


# 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()
{
    local licenseType=$1
    local setting=$2

    if [ $setting -eq 0 ]; then
        log TRACE1 3007 "Disabling $licenseType repository in /etc/yum.repos.d/cellsdk-${distro}.repo"
    else 
        log TRACE1 3009 "Enabling $licenseType repository in /etc/yum.repos.d/cellsdk-${distro}.repo"
    fi

    filename="/etc/yum.repos.d/cellsdk-${distro}.repo"
    [ ! -e $filename ] && {
        log ERROR 0030 "Cannot enable SDK repositories because $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.1 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, 
  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.1 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.

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 "To find out 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 [ $rc -ne 9 -a $rc -ne 5 ] || [ ! -e ${cellTop}/license/license ]; then
        return $rc
    else
        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
    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

        # If we get to the extras license without finding one of the
        # SDK licenses, we probably have a repository problem
        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 "${myName} is unable to find any SDK files in the yum repositories."
                log INFO 2033 "Be sure the --iso flag was used and that network connections are working."
                exit 1
            fi
        fi

        # Only update the product license if this is an update, because
        # by definition, fixes are only made to supported product code.
        if [ "$task" = "update" ] && [ "$licenseType" != "product" ]; then 
            continue;
        fi
           
        # Only try to install the product license if this is not a RHEL system
        if [ "$licenseType" == "product" ] && [ "$distro" != "RHEL" ]; 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 
                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, updateDetail
        OPTIONS are:
          [ -r | --runtime ]       only install runtime, not development, files
          [ -o | --all]            install all optional SDK rpms
          [ -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="$yumCmd -d 3 -e 3"
            ;;
        -vv | --very-verbose)
            DEBUG=3; shift;
            yumCmd="$yumCmd -d 10 -e 10"
            ;;
        -V | --version)
            rpm --quiet -q cell-install
            if [ $? -ne 0 ]; then
                echo "The cell-install rpm is not installed.  It is needed to determine the version."
            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"
            yumCmd="$yumCmd -y"
            auto=1; shift;
            ;;
        -o | --all)
            log TRACE2 4012 "parseOptions:  setting all=1"
            allFlag=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 "Please provide a directory name after the --iso flag" 
                ((parseErrors++)) 
                isoDir=""
            fi
            ;;
        verify)
            readyCheck        
            getEnabledRepos
            installedRpmsArray=()       # zero out array
            missingDefaultRpmsArray=()  # zero out array
            verifyInstallation
            printMissing
            exit 
            ;;
        mount)
            # are we running as root?  If not, we can't do any mounts
            (($UID != 0)) && { 
                echo "INFO 2000 Root access is needed to run this script"
                exit
            }
            unmountIsos
            mountIsos
            exit
            ;;
        umount | unmount)
            # are we running as root?  If not, we can't do any umounts
            (($UID != 0)) && { 
                echo "INFO 2000 Root access is needed to run this script"
                exit
            }
            unmountIsos
            exit
            ;;
        install | update | uninstall |  updateDetail )
            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, all=$allFlag, runtime=$runtime, isoDir=$isoDir, task=$task"

    # do a little checking
    [ "$task" = "" ] && 
        log ERROR 0014 "Please specify one of install, update, uninstall, verify, mount, unmount or updateDetail" && ((parseErrors++))
 
    return $parseErrors
}


# take apart an rpm name
function parseRpm()
{
    local inValue=$1

    local rpmLongName=${inValue%.*}             # rm .rpm from end
    local rpmArch=${rpmLongName##*.}            # rm up to arch from front

    local rpmRelease=${rpmLongName%.*}          # rm .arch from the end
    rpmRelease=${rpmRelease##*-}                # rm up to dash

    local rpmVersion=${inValue%-*}              # rm last dash to EOF (ver+arch+.rpm)
    rpmVersion=${rpmVersion##*-}                # rm up to dash (rpm name)

    local rpmShortName=${inValue%-*}            # rm last dash to EOF (ver+arch+.rpm)
    rpmShortName=${rpmShortName%-*}             # rm last dash to EOF (rel)

    # return these values to calling routine by echo'ing them.
    echo "$rpmLongName $rpmShortName $rpmVersion $rpmRelease $rpmArch"
}


# insert an rpm element into the rpmArray, where the rpm element is a
# string containing the following items:
# 1=repo,2=instType,3=instGroup,4=rpmName,5=ver,6=rel,7=arch,8=status
function arrayInsert()
{
    let found=0
    local elem="$@"

    # split the element into it's various pieces.  First substitute
    # the pipe characters for spaces, then then 'set' the values into $@
    IFS='|'; set -- $elem; IFS=' '
    local repo=$1
    local name=$4
    local ver=$5
    local rel=$6
    local arch=$7

    # See if the rpm is already in the array.  Match on the rpm short 
    # name and the architecture
    let k=0
    let arraySize=${#rpmsArray[@]}
    for ((k=0; k<arraySize; k++)); do

        # split the array entry into it's various pieces
        IFS='|'; set -- ${rpmsArray[$k]}; IFS=' '

        # see if $name is already in the array
        if [ "$4" == "$name" -a "$7" == "$arch" ]; then
            # found the rpm.  
            # If this is a newer ver or rel, then replace the entry
            # Updates always trump whatever is there
            if [[ "${repo}" == *"Update"* ]]; then
                rpmsArray[$k]="$elem"
            elif [[ "$ver" > "$5" ]]; then
                rpmsArray[$k]="$elem"
            elif [[ "$rel" > "$6" ]]; then
                rpmsArray[$k]="$elem"
            fi
            found=1
            break

        # if the rpmName is greater than the current array element,
        # then the it's not in the array, and we should insert it here
        # caution:  the second element (y) in array:x:y is a count, not an index
        elif [[ "$4" > "$name" ]] ; then
            let prevElem=($k)
            IFS=' '; rpmsArray=(${rpmsArray[@]:0:$prevElem} ${elem} ${rpmsArray[@]:$prevElem:$arraySize});
            found=1
            break
        fi
    done
 
    # if still not in the array, then insert at end
    (($found == 0)) && {
        rpmsArray[$arraySize]="$elem"
    }

}


# 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=${#rpmsArray[@]}        # current count

    local fn="${cellTop}/yum-repos/$prod/$arch/rpmList.txt"
    [ ! -e $fn ] && return

    while read line; do
        IFS='|'; set -- $line; IFS=' '
        rpmLongName=$1; rpmShortName=$2; rpmVersion=$3; rpmRelease=$4; rpmArch=$5; category=$6; group=$7; instType=$8

        category=${category// /}    # remove any spaces
        group=${group// /}      

        # If the runtime flag is present, only process runtime rpms
        ((runtime != 0)) && [ "$group" != "CellRuntimeEnvironment" ] && continue;
    
        # See if the rpm is installed
        rpmStatus="ok"

        # on RHEL (rpm-4.4.2-48.el5.ppc), when the ppc64 version of an 
        # rpm is installed but the ppc version is not, rpm -q <ppc rpm> 
        # returns a rc of 0 instead of 1, even if the rpm is not installed.  
        # So we have to check that we get back a name in order to be sure 
        # it's already installed.
        installedRpm=`rpm -q $rpmShortName-$rpmVersion-$rpmRelease.$rpmArch`
        if [ $? -ne 0 ] || [ "$installedRpm" == "" ]; then
            rpmStatus="missing"
        fi

        # insert into rpm array, avoiding duplicate entries
        element="$prod-$arch|$instType|$group|$rpmShortName|$rpmVersion|$rpmRelease|$rpmArch|$rpmStatus"
        arrayInsert "$element"
    done < $fn

}


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

    mntList=()		# what to mount
    let cnt=0
    local version

    # Look for iso images in the --iso directory specified by the user
    # Only mount isos for product-sets that are enabled in the yum 
    # repository file
    for isoFile in `ls ${isoDir}/CellSDK-*-${distro}*.iso 2>/dev/null`; do
        tmp=`basename $isoFile`
        prod=${tmp/_*/}
        version=${tmp/*_/}
        version=${version/.iso/}

        # do we already have it?
        let found=0
        for ((i=0; i<cnt; i++)); do
            set -- ${mntList[$i]}	# split into $1=prod, $2=version, $3=filename
            if [ "$1" == "$prod" ]; then
                found=1
                [[ "$2" == "$version" ]] && break;
                [[ "$2"  > "$version" ]] && break;
                [[ "$2"  < "$version" ]] && {
                    mntList[$i]="$prod $version $isoFile"
                    break;
                }
            fi
        done
        if [ $found -eq 0 ]; then
            mntList[$cnt]="$prod $version $isoFile"
            ((cnt++))
        fi
    done

    # Look for already-mounted cdroms or isos
    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 to determine if it's an SDK image.
        for mFile in `find ${where} -name CellSDK-*-${distro}*.marker -print`; do
            tmp=`basename $mFile`
            prod=${tmp/_*/}
            prod=${prod%-*}
            version=${tmp/*_/}
            version=${version/.marker/}

            # do we already have it?
            let found=0
            for ((i=0; i<cnt; i++)); do
                set -- ${mntList[$i]}	# split into $1=prod, $2=version, $3=filename
                if [ "$1" == "$prod" ]; then
                    found=1
                    [[ "$2" == "$version" ]] && break;
                    [[ "$2" > "$version" ]] && break;
                    [[ "$2" < "$version" ]] && {
                        mntList[$i]="$prod $version $what"
                        break;
                    }
                fi
            done
            if [ $found -eq 0 ]; then
                mntList[$cnt]="$prod $version $what"
                ((cnt++))
            fi
        done
    done < $tmpFile
    rm $tmpFile

    for ((i=0; i<$cnt; i++)); do
        set -- ${mntList[$i]}	# split into $1=prod, $2=version, $3=filename
        mntName=${1}

        # if it's already mounted on ${mountPoint}, skip it
        if [ `mount | grep -c ${mountPoint}/${mntName}` -gt 0 ]; then
            log TRACE2 4019 "$3 is already mounted on $mountPoint/$mntName"
            continue
        fi

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

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

    # Do not permit both the product and trial versions to be mounted at the 
    # same time
    [ `grep -c ${mountPoint}/CellSDK-Product-${distro} /etc/mtab` -gt 0 ] &&
    [ `grep -c ${mountPoint}/CellSDK-Devel-${distro} /etc/mtab` -gt 0 ] &&
        umount ${mountPoint}/CellSDK-Devel-${distro} 2>/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
    # also unmount any SDK 3.1 isos
    grep "/tmp/sdk/CellSDK" /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 "Unable to unmount $what from $where"
        fi
    done < $tmpFile
    rm $tmpFile

}


# 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 $isoDir 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`
        newName=`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/${newVersion}/${newName} ]; then
            mkdir -p ${cellTop}/updates/${newVersion}
            cp ${r} ${cellTop}/updates/${newVersion}
        fi
        log TRACE2 4042 "comparing $savedVersion and $newVersion ($r)"
        [[ "$savedVersion" == "$newVersion" ]] && continue 
        [[ "$savedVersion" > "$newVersion" ]] && continue
        savedRpm=$r
        savedVersion=$newVersion
        savedName=`basename $r`
    done

    if [ "$savedRpm" != "" ]; then
        unmountIsos
        log TRACE1 3019 "rpm -Uvh ${cellTop}/updates/${savedVersion}/${savedName}"
        rpm -Uvh ${cellTop}/updates/${savedVersion}/${savedName}
        rc=$?
        mountIsos
        [ $rc -ne 0 ] && {
            log ERROR 0021 "Failed:  rpm -Uvh $savedRpm"
            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
}


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

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

    # display the results.  Write them to a file so we can sort them.
    tmpFile1="/tmp/${0##*/}1.$$"
    touch $tmpFile1
    for ((k=0; k<${#rpmsArray[@]}; k++)); do

        # split the array entry into it's various pieces
        # 1=repo,2=instType,3=instGroup,4=rpmName,5=ver,6=rel,7=arch,8=status
        IFS='|'; set -- ${rpmsArray[$k]}; IFS=' '
        repo=$1
        type=$2
        group=$3
        name="$4-$5-$6.$7"
        status=$8

        # If the runtime flag is present, only process runtime rpms
        ((runtime != 0)) && [ "$group" != "CellRuntimeEnvironment" ] && continue;
    
        printf "%-26s %-9s %-26s %-50s\n" $repo $type $group "$name $status" >> $tmpFile1
    done

    # keep the 3.0 printing format and array names ??
    oldRepo="";

    installedRpmsArray=()
    missingDefaultRpmsArray=()
    let i1=0;
    let i2=0;

    tmpFile2="/tmp/${0##*/}2.$$"
    sort $tmpFile1 > $tmpFile2

    while read repo type group rpm status; do
        if [ "$repo" != "$oldRepo" ]; then
            printf "\nrepository=%-s\n" $repo
            oldRepo="$repo"
        fi
        [ "$status" = "ok" ] && {
            printStatus=""
            installedRpmsArray[$i1]="$type,$group,$rpm"
            ((i1++))
        }
        [ "$status" = "missing" ] && {
            printStatus="not installed"
            [ "$type" = "mandatory" -o "$type" = "default" ] && {
                missingDefaultRpmsArray[$i2]="$type,$group,$rpm"
                ((i2++))
            }
        }
        printf "   %-9s %-25s %-50s\n" $type $group "$rpm $printStatus"
    done < $tmpFile2
    rm $tmpFile1 $tmpFile2

    echo ""
}



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

    # uninstall any rpms left on the system
    verifyInstallation &>/dev/null

    uninstallList=""
    let installedCount=${#installedRpmsArray[@]}    # current count
    ((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"
            uninstallList="${uninstallList} $rpm"
        done
        echo -n "Call yum to uninstall them [y/n]?"
        read answer
        if [ "$answer" = 'y' ]; then 
            runYum "erase ${uninstallList}"
            if [ $? -ne 0 ]; then 
                log ERROR 0023 "Failed:  $yumCmd erase ${uninstallList}"
            fi
        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 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

    # remove any cellsdk yum repository files
    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*"
    }

    # remove the /tmp/cellsdk/openSrc directory
    log TRACE2 4081 "rm -rf /tmp/cellsdk/openSrc"
    rm -rf /tmp/cellsdk/openSrc
    [ $? -ne 0 ] && {
        log ERROR 0047 "Failed:  rm -rf /tmp/cellsdk/openSrc"
    }

    # remove the ${cellTop}/license directory
    log TRACE2 4078 "rm -rf ${cellTop}/license"
    rm -rf ${cellTop}/license
    [ $? -ne 0 ] && {
        log ERROR 0032 "Failed:  rm -rf ${cellTop}/license"
    }

    # remove the ${cellTop}/updates directory
    log TRACE2 4079 "rm -rf ${cellTop}/updates"
    rm -rf ${cellTop}/updates
    [ $? -ne 0 ] && {
        log ERROR 0042 "Failed:  rm -rf ${cellTop}/updates"
    }

    # remove the ${cellTop}/itlm directory
    log TRACE2 4080 "rm -rf ${cellTop}/itlm"
    rm -rf ${cellTop}/itlm
    [ $? -ne 0 ] && {
        log ERROR 0044 "Failed:  rm -rf ${cellTop}/itlm"
    }

    # remove the ${cellTop}/yum-repos directory
    log TRACE2 4082 "rm -rf ${cellTop}/yum-repos"
    rm -rf ${cellTop}/yum-repos
    [ $? -ne 0 ] && {
        log ERROR 0048 "Failed:  rm -rf ${cellTop}/yum-repos"
    }

    # 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 /opt/cell directory
    echo " "
    echo "There may be user-created files in $cellTop."
    echo -n "Completely remove the $cellTop directory [y/n]? "
    read answer
    if [ "$answer" = "y" ]; then
        log TRACE2 4045 "rm -rf $cellTop"
        rm -rf $cellTop
        [[ $? -ne 0 ]] && {
            log ERROR 0022 "Failed:  rm -rf $cellTop"
        }
    else
        log INFO 2008 "Skipping removal of $cellTop"
    fi

    # 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
    # 8)  the /spu directory and the entry we make in /etc/fstab for the spufs


}



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

    [ "$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)"
    W8="Fedora release 8 (Werewolf)"
    F9="Fedora release 9 (Sulphur)"
    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 foundW8=0
    for file in `ls /etc/*-release 2>/dev/null`; do
        ((foundW8 += `grep -ic "${W8}" $file`))
    done

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

    let foundR5=0
    # here, we have to verify that the release is at least 5.2
    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.1" ]] && ((foundR5 += 1))
    done

    [ $foundF9 -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 "$F9 or"
        log WARNING 1000 "$R5 5.2 or greater"
    }
}


# 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
    local let totalCount=0

    if [ ! -e ${fileList} ]; then
        log TRACE2 4054 "copyFiles list ${fileList} does not exist"
        return 1
    else
        totalCount=`wc -l ${fileList} | awk {'print $1'}`
        for f in `cat ${fileList}`; do
            [ -e "${outDir}/$f" ] && ((copyCount++))
        done
    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}"
                    wgetFlags="--tries=9 --read-timeout=40 --continue "
                    # wget is verbose by default
                    [ $DEBUG -eq 0 ] && wgetFlags="--no-verbose $wgetFlags"  # quiet
                    [ $DEBUG -eq 3 ] && wgetFlags="--debug $wgetFlags"       # very verbose
                    log TRACE2 4030 "wget $wgetFlags -O ${dest} ${src}"
                    wget $wgetFlags -O ${dest} ${src}
                    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

    if (($copyCount != $totalCount)); then
        let missing=$(($totalCount - $copyCount))
        log ERROR 0006 "Unable to copy $missing of $totalCount rpms into ${outDir}:"
        for f in `cat ${fileList}`; do
            [ ! -e "${outDir}/$f" ] && echo "    $f"
        done
        ((copyErrors++))
    else
        log INFO 2016 "Copied ${copyCount} of ${totalCount} rpms into ${outDir}"
    fi

    return $copyErrors
}


function copyRpmList()
{
    # copy the rpmList.txt file into the save directory
    for repo in `echo ${enabledReposArray[@]}`; do
        # On an update, don't recopy the product rpm lists
        [ "$task" = "update" ] && [[ "${repo}" != *"Update"* ]] && continue
        # On an install, don't copy the product rpms lists into an update directory
        [ "$task" != "update" ] && [ -e "${cellTop}/updates/${version}/PreUpdateRpms" ] && continue

        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
    done
}


# install the SDK versions of open source rpms
function installOpenSrc()
{
    # Look for the cellsdk versions of the open-source rpms
    local rpmDir="/tmp/cellsdk/openSrc"
    local rpmList="${cellTop}/openSrcRpmsList.txt"
    [ -e ${rpmList} ] && rm -f ${rpmList}
    [ ! -e "${rpmDir}" ] && mkdir -p ${rpmDir}

    let i=0
    for repo in `echo ${enabledReposArray[@]}`; do

        # 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"
        # exclude the -cross packages
        for item in blas lapack oprofile libspe2 elfspe2; do
            if (($runtime == 0)); then
                grep $item ${cellTop}/yum-repos/$prod/$arch/rpmList.txt | grep -v manpage | grep -v examples \
                    | grep -v cross | awk -F'|' '{print $1}' >> ${rpmList}
            else
                grep $item ${cellTop}/yum-repos/$prod/$arch/rpmList.txt | grep -v manpage | grep -v examples \
                    | grep -i runtime | awk -F'|' '{print $1}' >> ${rpmList}
            fi
        done
        baseurl=${baseurlArray[$i]}
        ((i++))
        copyFiles $repo "$baseurl" ${rpmList} ${rpmDir}
    done
    rm -f ${rpmList}

    # If there are no files in the ${rpmDir}, we're done
    [ `ls ${rpmDir} | wc -l` -eq 0 ] && return 0;

    # Check on any rpms in the ${rpmDir} directory
    log INFO 2039 "Looking for ${distro} versions of the rpms in ${rpmDir}"
    removeList=()
    addList=()
    for openSrcRpm in `ls ${rpmDir}/*.rpm`; do
        openSrcRpm=`basename ${openSrcRpm}` # get just the rpm name
        set -- `parseRpm $openSrcRpm`
        rpmLongName=$1; rpmShortName=$2; rpmVersion=$3; rpmRelease=$4; rpmArch=$5
        
        # See if the cellsdk version is already installed
        rpm -q $rpmLongName &>/dev/null   
        [ $? -ne 0 ] && {
            # Nope.  See if a distro version is installed
            rpmInstalled=`rpm -q $rpmShortName.$rpmArch`
            # if it was already installed, replace it w/sdk version
            [ $? -eq 0 ] && {
                addList=( ${addList[@]} "$rpmLongName.rpm" )
                removeList=( ${removeList[@]} $rpmShortName )
            }
            # only install default rpms; skip optional ones
            if [ `grep $rpmLongName ${cellTop}/yum-repos/CellSDK-*-${distro}/$platform/rpmList.txt | \
                  grep -c optional` -eq 0 ]; then
                addList=( ${addList[@]} "$rpmLongName.rpm" )
            fi
        }
    done

    # If there are no SDK-version rpms that need installing, we're also done
    let addSize=${#addList[@]}
    let delSize=${#removeList[@]}
    [ $addSize -eq 0 ] && return 0;

    # Ask, the user if we should install them
    if [ $auto -eq 0 -a $delSize -gt 0 ]; then
        echo ""
        echo "There are distro versions of the following rpms installed:"
        echo ${removeList[@]} | fmt -w1 | sort | uniq | xargs
        echo "Answer y to remove them so their SDK versions can be installed."
        echo "Call yum to remove the listed rpms? [y/n]"
        
        read answer
        echo ""
        [ "$answer" != 'y' ] && return -1;
    fi

    # try to remove it. 
    [ ${#removeList[@]} -gt 0 ] && {
        log INFO 2048 "Calling yum to remove the distro versions of rpms in /tmp/cellsdk/openSrc"
        runYum "remove ${removeList[@]}"
        [ $? -ne 0 ] && return -1
    }

    # Now that we have the distro versions removed, install the SDK rpms
    [ ${#addList[@]} -gt 0 ] && {
        log INFO 2027 "Installing the ${myName} rpms in /tmp/cellsdk/openSrc"
        cd /tmp/cellsdk/openSrc;
        runYum "localinstall ${addList[@]}"
        [ $? -ne 0 ] && return -1
    }

    return 0
}


# print any missing rpms
function printMissing()
{
    echo "" >&2
    missing=${#missingDefaultRpmsArray[@]}
    if [ $missing -gt 0 ]; then
        echo "INFO 2020 There are $missing default or mandatory rpms that are not installed" >&2
        for ((i=0; i<$missing; i++)); do
	    rpmName=${missingDefaultRpmsArray[$i]}.rpm
            rpmName=${rpmName##*,}
            set -- `parseRpm $rpmName`
            rpmLongName=$1; rpmShortName=$2; rpmVersion=$3; rpmRelease=$4; rpmArch=$5
            actual=`rpm -q $rpmShortName.$rpmArch`
            if [ $? -eq 1 ]; then 
                actual=""
            else 
                actual="(installed = $actual)"
            fi
            echo "    ${rpmLongName} $actual" >&2
        done
        echo "INFO 2021 Try mounting the isos (cellsdk --iso <isoDir> mount) and" >&2
        echo "INFO 2021 then using yum or rpm to install the correct rpms." >&2
 
    else
        log INFO 2025 "All default rpms are installed"
    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

    # copy the rpmList.txt file into the updates directory
    copyRpmList

    # 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.
    log TRACE1 3008 "Verifying that all expected rpms are installed"
    installedRpmsArray=()   # zero out array
    missingDefaultRpmsArray=()  # zero out array
    verifyInstallation &>/dev/null
    printMissing

    unmountIsos

    log INFO 2045 "The ${myName} install is complete"
}


# 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 "The ${cellTop}/updates/updateVersionsList file is 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

    log INFO 2017 "The ${myName} update is complete"

}


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
}


# run a specified yum command
function runYum()
{
    local runcmd="$@"
    let rc=0		# return code

    log INFO 2043 "Calling $yumCmd $runcmd"
    eval $yumCmd $runcmd || {
        rc=$?
        log ERROR 0053 "Failed:  $yumCmd $runcmd (rc=$rc)" 
    }
    return $rc
}


# Provide fixpack backout information
function backout() 
{
    if [ ! -e "${cellTop}/updates/updateVersionsList" ]; then
        log ERROR 0033 "Unable to print updateDetail information because the" 
        log ERROR 0033 "${cellTop}/updates/updateVersionsList file is missing"
        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
        [[ "$version" > "$currVersion" ]] && continue
        prevVersion=${version}
        break;
    done
    read gaVersion < ${cellTop}/updates/updateVersionsList
    log TRACE1 3001 "initialVersion=$gaVersion, previousVersion=$prevVersion, currentVersion=$currVersion"

    [ "$currVersion" = "$gaVersion" ] && {
        log INFO 2029 "There are no updates available to remove."
        log INFO 2030 "Please use 'cellsdk uninstall' to remove the code"
        exit
    }

    updateDir="${cellTop}/updates/$currVersion"
    if [ ! -e ${updateDir}/CellSDK-Updates-RHEL-$platform ] &&
       [ ! -e ${updateDir}/CellSDK-Open-Updates-RHEL-$platform ]; then
        log WARNING 1001 "${currVersion} is not a fixpack"
        return 0
    fi

    # get the list of all the rpms in the update.
    let index=-1
    log INFO 2018 "Getting a list of the rpms in the $currVersion update"
    for list in ${cellTop}/updates/${currVersion}/*Update*/rpmList.txt; do
        # make a list of all installed update rpms 
        for rpmName in `cat $list`; do
            # see if this rpm is installed
            ((index++))
            rpm -q ${rpmName/.rpm/} > /dev/null
            if [ $? -eq 0 ]; then 
                updateRpmsState[$index]="yes"
            else
                updateRpmsState[$index]="no"
            fi
           
            updateRpms[$index]=${rpmName/.rpm/}
        done
    done

    # Now find the replacement rpm
    # Since updates are cumulative, an older rpm will only be in either the
    # previous update or in the original release
    log INFO 2019 "Identifying the replacement rpms"
    for ((j=0; j<${#updateRpms[@]}; j++)); do
        rpm=${updateRpms[$j]}
        shortName=${rpm%-*}           # rm release from the end
        shortName=${shortName%-*}     # rm version from the end
        arch=${rpm##*.}               # rm up to arch

        for v in $prevVersion $gaVersion; do
            for dirName in `ls ${cellTop}/updates/${v}`; do
                # have we already found it?
                [ "${replRpms[$j]}" != "" ] && continue

                # no?  then get the rpm name from the list
                rpmName=`grep ${shortName} ${cellTop}/updates/$v/$dirName/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
                       
                    replRpms[$j]="${r/.rpm/}"
                done
            done
        done
    
        if [ "${replRpms[$j]}" = "" ]; then
            replRpms[$j]="NONE"
        fi
        if [ "${updateRpms[$j]}" = "${replRpms[$j]}" ]; then
            replRpms[$j]="SAME"
        fi
    done

    for ((j=0; j<${#updateRpms[@]}; j++)); do
        if [ "${updateRpmsState[$j]}" == "yes" ]; then
            rmString="$rmString ${updateRpms[$j]}"
        fi
    done

    for ((j=0; j<${#updateRpms[@]}; j++)); do
        # is the rpm installed?  Is there a replacement for it?
        if [ "${updateRpmsState[$j]}" == "yes" ] &&
           [ "${replRpms[$j]}" != "NONE" ] ; then
            replString="$replString ${replRpms[$j]}"
        fi
    done

    cat << EOF1

To remove all or part of an update, see the documentation that
came with this release.  

EOF1

    printf "%-47s %-10s %s\n" "Post-Update Rpms" "Installed" "Pre-Update Rpms"
    for ((j=0; j<${#updateRpms[@]}; j++)); do
        printf "%-47s %-10s %s\n" ${updateRpms[$j]} ${updateRpmsState[$j]} "${replRpms[$j]}"
    done
}


# 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=""
    case $task in 
        updateDetail)
            backout
            return 0
            ;;
        install) 
            if [ $? -ne 0 ]; then 
                exit -1;
            fi
            if [ "$distro" = "RHEL" ]; then
                checkRhelPrerequisites
                if [ $? -ne 0 ]; then 
                    exit -1;
                fi
            fi

            unmountIsos		# unmount anything old (like left-behind SDK 3.1 iso's)
            mountIsos

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

            # 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

            # find and install the SDK versions of open source rpms
            installOpenSrc

            # in case the user is updating to a new release, update any 
            # optional rpms
            groupCmd="--disablerepo=*"
            for repo in `echo ${enabledReposArray[@]}`; do
                groupCmd="$groupCmd --enablerepo=${repo}"
            done
            groupCmd="$groupCmd update"
            runYum "$groupCmd"
            [ $? -ne 0 ] && return -1

            # install the SDK.  Exclude the openSrc rpms for which
            # there is a cellsdk version.  These are installed by installOpenSrc() above.
            installList=""
            local rpmDir="/tmp/cellsdk/openSrc"
            for repo in `echo ${enabledReposArray[@]}`; do
                prod=${repo%-*}         # remove the platform on end of repo name
                arch=${repo##*-}        # remove the product from front of repo name
                local fn="${cellTop}/yum-repos/$prod/$arch/rpmList.txt"
                [ ! -e $fn ] && return

                # license installation is handled in installAllLicenses
                cmd="grep -v license $fn"
                # skip optional installs unless the user selected --all
                ((allFlag == 0)) && cmd="$cmd | grep -v optional"
                # limit to runtime if the user selected --runtime
                ((runtime != 0)) && cmd="$cmd | grep -i runtime"

                tmpFile="/tmp/${0##*/}.$$"
                eval $cmd > $tmpFile
                while read line; do
                    IFS='|'; set -- $line; IFS=' '
                    rpmLongName=$1; rpmShortName=$2; rpmVersion=$3; rpmRelease=$4; rpmArch=$5; category=$6; group=$7; instType=$8
                     
                    # openSrc rpms need special processing.  The assumption here is that
                    # any openSrc rpms, default or optional, were removed in the installOpenSrc
                    # function called above.  If it's a mandatory/default rpm, it was also
                    # installed there.  Optional rpms, however, have to be installed here.
                    # We'll provide the release & version to be sure we get the right rpm.
                    if [ -e ${rpmDir}/$rpmLongName ]; then
                        # not optional
                        if [ `grep $rpmLongName ${cellTop}/yum-repos/CellSDK-*-${distro}/$platform/rpmList.txt | \
                              grep -c optional` -eq 0 ]; then
                            continue
                        fi
                        installList="${installList} $rpmShortName-$rpmVersion-$rpmRelease.$rpmArch"
                        continue
                    fi
                    installedRpm=`rpm -q $rpmShortName-$rpmVersion-$rpmRelease.$rpmArch`
                    if [ $? -ne 0 ] || [ "$installedRpm" == "" ]; then
                        installList="${installList} $rpmShortName.$rpmArch"
                    fi
                done < $tmpFile
                rm $tmpFile
            done

            if [ "${installList}" != "" ]; then
                runYum "-c ${cellTop}/yumcell.conf install ${installList}"
                [ $? -ne 0 ] && return -1
            else 
                log INFO 2046 "No rpms need to be installed"
            fi
            ;;
        update)
            log INFO 2040 "Updating rpms using CellSDK-*Updates-${distro}-${platform} yum repository"
            mountIsos

            # 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/product -name status.dat -print 2>/dev/null | wc -l` 
            if ((count == 0)); then
                log ERROR 0040 "The ${myName} product 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

            # keep a list of their current cellsdk rpms
            currVersion=`rpm -q --qf "%{version}-%{release}" cell-install`
            dirName=${cellTop}/updates/$currVersion
            fileName=PreUpdateRpms
            mkdir -p ${dirName}
            if [ ! -e "${dirName}/${fileName}" ]; then
                log INFO 2011 "Saving a list of pre-update rpms in ${dirName}/${fileName}"
                installedRpmsArray=()
                missingDefaultRpmsArray=()
                verifyInstallation &>${dirName}/${fileName}
            fi

            # 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"
            runYum "$groupCmd"
            [ $? -ne 0 ] && return -1

            # in case there are new rpms in the fixpak, call install also
            groupCmd="--disablerepo=* --enablerepo=CellSDK-*Updates-${distro}-${platform} groupinstall"
            if ((runtime > 0)); then 
                groupCmd="$groupCmd $runtimeGroups"
            else
                groupCmd="$groupCmd $runtimeGroups $develGroups"
            fi
            runYum "$groupCmd"
            [ $? -ne 0 ] && return -1

            # also store a list of the cellsdk rpms after the update
            dirName=${cellTop}/updates/$currVersion
            fileName=PostUpdateRpms
            mkdir -p ${dirName}
            if [ ! -e "${dirName}/${fileName}" ]; then
                log INFO 2012 "Saving a list of post-update rpms in ${dirName}/${fileName}"
                installedRpmsArray=()
                missingDefaultRpmsArray=()
                verifyInstallation &>${dirName}/${fileName}
            fi

            ;;
        uninstall)
            # uninstall the SDK.  
            uninstallList=""
            for repo in `echo ${enabledReposArray[@]}`; do
                prod=${repo%-*}         # remove the platform on end of repo name
                arch=${repo##*-}        # remove the product from front of repo name
                local fn="${cellTop}/yum-repos/$prod/$arch/rpmList.txt"
                [ ! -e $fn ] && return
                while read line; do
                    IFS='|'; set -- $line; IFS=' '
                    rpmLongName=$1; rpmShortName=$2; rpmVersion=$3; rpmRelease=$4; rpmArch=$5; category=$6; group=$7; instType=$8
                    rpm -q $rpmShortName-$rpmVersion-$rpmRelease.$rpmArch &>/dev/null
                    if [ $? -eq 0 ]; then
                        uninstallList="${uninstallList} $rpmShortName-$rpmVersion-$rpmRelease.$rpmArch"
                    fi
                done < $fn
            done

            if [ "${uninstallList}" != "" ]; then
                runYum "erase ${uninstallList}"
                [ $? -ne 0 ] && return -1
            else 
                log INFO 2047 "No rpms need to be uninstalled"
            fi
            ;;
        *)
        log ERROR 0035 "Unrecognized install command $task"
            return -1
    esac

    # 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() 
{
    # do the command line options parse correctly?
    parseOptions $args 
    rc=$?
    if (($rc > 0)); then {
        help
    }
    else {
        log INFO 2050 "STARTING cellsdk $args"
        log TRACE2 4005 "options parsed OK"
    }
    fi

    # are we running as root?  If not, we can't do any rpm/yum commands
    (($UID != 0)) && { 
        echo "INFO 2000 Root access is needed to run this script"
        exit
    }

    # 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

    # Pre-checks (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

    doTask

    log INFO 2051 "ENDING cellsdk $args"

    exit $?

# 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
