#!/bin/sh
# @(*) $Id: install,v 1.19 2008/01/09 15:11:51 dsd Exp $
# ============================================================================
# Header
# ============================================================================
# Name: install
# Version: 1.4.0
# Author: Lisa Steinmetz <steinmet@sgi.com>, Steve Hein <ssh@sgi.com>
# Vendor: sgi
# Description: The installation script for the SGI SNx System Controller
#              Software.  This generic script is used for install of
#              System Controller software on L3 Controller (i386),
#              SGIConsole (i386) and SGI Itanium-based server systems.

# MAIN BODY BEGINS AFTER FUNCTIONS.....

# ********************************************************************
# ********************************************************************
#                       Utility Functions
# ********************************************************************
# ********************************************************************

GetPackageList() {

    pkglist=
    for lpkg in $*; do
        # get a list of all matching packages
        flist=`ls -1 $lpkg-*.$ARCH.rpm 2>/dev/null | sort -r`
        # remove the version and .$ARCH.rpm from the named packages
        plist=`echo "$flist" | sed -e "s/-[^-]*-[^-]*.$ARCH.rpm//" | sort -u`
        # now we have a list of the package names, get the latest version
        # of each specified package
        for llpkg in $plist; do
            # grab the latest version number
            fname=`ls -1 $llpkg-*.$ARCH.rpm 2>/dev/null | sort -r | head -1`
            if [ -n "$fname" ]; then
                if [ -n "$pkglist" ]; then
                    pkglist=`echo "$pkglist";echo $fname`
                else
                    pkglist=$fname
                fi
            fi
        done
    done

    # eliminate the filename extension (.$ARCH.rpm) from the names
    echo "$pkglist" | sed -e "s/.$ARCH.rpm//"
}

GetDependencies() {

    pkgdeplist=
    for dpkg in $*; do
        #echo -e "$dpkg\n----------------------------"
        # get list of all dependencies
        deplist=`rpm -q -p $dpkg.$ARCH.rpm --requires`
        # for our pkgs, all of the package dependencies are listed before
        #   the shell dependency /bin/sh
        pkgdeps=`echo "$deplist" | awk '/^\/bin\/sh/   { exit }   { gsub(" = ","-", $0); print $0 }'`
        pkgdeplist=`echo "$pkgdeplist"; echo "$pkgdeps"`
    done

    echo "$pkgdeplist" | sort -u
}

CheckDependencies() {

    pkglist=

    # get the dependencies for the specified packages
    pkgdeplist=`GetDependencies $*`

    # make sure all of these dependencies are satisfied by this install
    for pkgdep in $pkgdeplist; do
        # check for file dependencies (absolute path)
        if [ "`echo $pkgdep | cut -c1`" = '/' ]; then
            # if the file is present/readable, then the dependency is satisfied
            if [ -r $pkgdep ]; then
                continue;
            fi
            # otherwise map the file to an RPM (if it is known)
            case $pkgdep in
                /bin/ksh)     filemap="pdksh OR ksh" ;;
                *)            filemap="" ;;    # default
            esac
            # create the enhanced dependency fail message
            pkgfails=`echo "$pkgfails"; echo "$filemap (for required file $pkgdep)"`

        # otherwise assume that these are RPMs
        elif ! /bin/rpm -q $pkgdep >/dev/null 2>/dev/null; then
            # add to failed pkg list if this package is not in the list of
            # packages that will be installed
            echo "$*" | grep "$pkgdep-" >/dev/null 2>/dev/null \
                             || pkgfails=`echo "$pkgfails";echo "$pkgdep"`
        fi
    done

    echo "$pkgfails"
}

InstallPackages() {

    for ipkg in $*; do
       echo "****** Installing $ipkg:"

       # clear out options that may be set in future steps
       RPMOPTS_INSTALL=
       RPMOPTS_ERASE=
       OLDRPM=

       # determine if we need to install this pkg
       if /bin/rpm -q $ipkg >/dev/null 2>/dev/null; then
          if [ "$FORCE_INSTALL" != y ]; then
              echo "$ipkg.$ARCH.rpm already installed..."
              continue    # skip this package
          fi
       fi

       # grab the name of the RPM and the currently install version of
       # this RPM, (needed for several steps below)
       RPMNAME=`echo $ipkg | sed -e 's/-[^-]*-[^-]$//'`
       if /bin/rpm -q $RPMNAME >/dev/null 2>/dev/null; then
          OLDRPM=`rpm -q $RPMNAME`
       else
          # if this RPM name contains 'snx', look for a corresponding RPM
          # containing 'sn1' instead (the RPMs used to be named 'sn1').
          if echo $RPMNAME | grep -q 'snx' >/dev/null 2>/dev/null; then
             ORPMNAME=`echo $RPMNAME | sed 's/snx/sn1/'`
             if /bin/rpm -q $ORPMNAME >/dev/null 2>/dev/null; then
                OLDRPM=`rpm -q $ORPMNAME`
             fi
          # for install downgrade compatibility,
          # if this RPM name contains 'sn1', look for a corresponding RPM
          # containing 'snx' instead (the RPMs used to be named 'sn1').
          elif echo $RPMNAME | grep -q 'sn1' >/dev/null 2>/dev/null; then
             ORPMNAME=`echo $RPMNAME | sed 's/sn1/snx/'`
             if /bin/rpm -q $ORPMNAME >/dev/null 2>/dev/null; then
                OLDRPM=`rpm -q $ORPMNAME`
             fi
          fi
       fi

       # there's a bug in the 'sgidiag' specfile that causes the entire
       # /usr/people/sgidiag directory to be removed on an update of
       # the sgidiag package (actually anytime the sgidiag pkg is erased).
       # if we're upgrading the sgidiag package, delete the user account now,
       # but don't blast the home dir.
       if [ "$RPMNAME" = "sgidiag"  -a  -n "$OLDRPM" ]; then
          # do this before the faulty post-uninstall script in the sgidiag RPM
          # can do this, as it calls "userdel -r sgidiag", which is a bad thing!
          /usr/sbin/userdel sgidiag

          # also, don't run the pre- or post-uninstall scripts for sgidiag
          # (since we've already done the work above...)
          RPMOPTS_ERASE="--noscripts"
       fi

       # there's a bug in the 'kernel_sgisnx_usb*' specfile that causes
       # the new sgil1 driver module not to be loaded when upgrading;
       # instead, the old module is still loaded even though the files
       # have been removed and the new module is not loaded until the box
       # is rebooted.  To work around this, remove the sgil1.o driver
       # module if it is loaded and we're uninstalling a kernel USB module
       if echo "$RPMNAME" | grep -q 'kernel_sgisn[1x]_usb'  &&  [ -n "$OLDRPM" ]; then
          # unload the sgil1 module here
          /sbin/modprobe -r sgil1
       fi

       # if we get here, we're installing
       # first erase the old version if necessary
       if [ -n "$OLDRPM" ]; then
          rpm -e --allmatches $RPMOPTS_ERASE --nodeps $OLDRPM
          rpm -i $RPMOPTS_INSTALL $ipkg.$ARCH.rpm
          echo "Updated $ipkg.$ARCH.rpm..."
       else
          rpm -i $RPMOPTS_INSTALL $ipkg.$ARCH.rpm
          echo "Installed $ipkg.$ARCH.rpm..."
       fi

    done	

}


# ********************************************************************
# ********************************************************************
#                            Main
# ********************************************************************
# ********************************************************************


SCRIPTDIR=`cd \`dirname $0\`; pwd`

echo "SGI System Controller Software Package Installer"

# check command-line options
while [ -n "$1" ]; do
    case $1 in
        -f|-force)
            FORCE_INSTALL=y
            echo; echo "FORCE installation requested!"; echo
            ;;
        -nk|-nokern|-nokernel)
            SKIP_KERNEL=y
            echo; echo "Skipping kernel and kernel module installation."; echo
            ;;
        -uninstall|-remove)
            UNINSTALL=y
            ;;
        -verbose|-v)
            VERBOSE=y
            ;;
    esac
    shift
done

# get architecture (allow command-line override, to install i386 RPMs on IA64)
ARCH_NATIVE=`/bin/uname -m 2>/dev/null`
[ -z "$ARCH" ] && ARCH=$ARCH_NATIVE
case $ARCH in
    i386|i486|i586|i686|i786|athlon)
        # force architecture to i386, as that is how the RPMs are built
        ARCH=i386
        ;;
    ia64)
        # always disable kernel RPM install when running on IA64
        SKIP_KERNEL=y

        # If there are IA64 RPMs present in the install directory,
        # then use those RPMs, otherwise default to using i386.
        if ! ls *.ia64.rpm >/dev/null 2>&1; then
            # Force architecture to i386.   These IA32 binaries will run
            # on IA64 using the standard IA32 emulation.
            ARCH=i386

            # running IA64 packages on IA32 requires the 'ia32el' RPM
            # to be installed, so make sure that it is
            if ! rpm -q --quiet ia32el; then
                echo "ERROR: ia32el RPM must be installed in order to install and run IA32 (i386) RPMs"
                exit 1;
            fi

            # But...there is some bug occurring when RPM tries to install
            # the i386 RPMs on IA64.   For some reason, it tries to run
            # the IA32 emulated tools at /emul/ia32-Linux (uppercase 'L')
            # instead of /emul/ia32-linux (lowercase 'L').   If we set up
            # a symlink from ia32-linux to ia32-Linux, then the install
            # works properly.
            if [ -r /emul/ia32-linux -a \( ! -r /emul/ia32-Linux \) ]; then
                #echo "WARNING: Creating symlink /emul/ia32-linux -> /emul/ia32-Linux to fix RPM install issue..."
                ln -s /emul/ia32-linux /emul/ia32-Linux
            fi
        fi
        # else, leave the ARCH as ia64 to install the native RPMs
        ;;

    x86_64)
        # binaries are i386, but packages are x86_64
        ARCH=x86_64
        SKIP_KERNEL=y
        ;;

    *) echo "Sorry, Linux architecture ($ARCH) not supported"; exit 1;;
esac

# determine if this is an SGIConsole or L3 install
if rpm -q --quiet SGIconsole; then
    echo "SGIconsole install detected.  Only SGIconsole components will be installed"
    SGICONSOLE=y
fi

# ************* uninstall package if requested ******************

if [ "$UNINSTALL" = y ]; then

   echo
   echo "REMOVING the System Controller Software Package"
   echo

   # list of possible packages to uninstall
   PKGLIST="kernel_sgisnx kernel_sgisnx_usb snxsc_firmware snxsc_l3 sgidiag snxscan sysco_tools sscope"

   # get list of packages that are installed
   ALLPKGS=`rpm -qa`
   for pkg in $PKGLIST; do
      PKGINST=`echo "$ALLPKGS" | grep $pkg`
      if [ -n "$PKGINST" ] && rpm --quiet -q $PKGINST; then
          RPMOPTS_ERASE=

          echo "Removing $PKGINST..."
          # there's a bug in the 'sgidiag' specfile that causes the entire
          # /usr/people/sgidiag directory to be removed on an update of
          # the sgidiag package (actually anytime the sgidiag pkg is erased).
          # if we're upgrading the sgidiag package, delete the user account now,
          # but don't blast the home dir.
          if [ "$pkg" = "sgidiag" ]; then
             # do this before the faulty post-uninstall script in the sgidiag
             # RPM can do this, as it calls "userdel -r sgidiag", which is a
             # bad thing!
             /usr/sbin/userdel sgidiag

             # also, don't run the pre- or post-uninstall scripts for sgidiag
             # (since we've already done the work above...)
             RPMOPTS_ERASE="--noscripts"
          fi
          # there's a bug in the 'kernel_sgisnx_usb*' specfile that causes
          # the new sgil1 driver module not to be loaded when upgrading;
          # instead, the old module is still loaded even though the files
          # have been removed and the new module is not loaded until the box
          # is rebooted.  To work around this, remove the sgil1.o driver
          # module if it is loaded and we're uninstalling a kernel USB module
          if echo "$RPMNAME" | grep -q 'kernel_sgisn[1x]_usb'  &&  [ -n "$OLDRPM" ]; then
             # unload the sgil1 module here
             /sbin/modprobe -r sgil1
          fi


          rpm -e --nodeps $RPMOPTS_ERASE $PKGINST
       fi
   done
   exit 0
fi

# ********** determine which kernel package(s) to install *******

# There are two types of kernel RPMs:  RPMs that provide loadable
# modules for various kernel flavors, and a full kernel RPM
# that has the L1 USB support compiled in.
#
# First, determine if any of the loadable module packages can be
# installed.  If so, install them; otherwise install the full
# kernel RPM to provide L1 USB support.

# first check for any kernel packages, skip if none are present
PKGLIST=`GetPackageList kernel_sgisnx_usb kernel_sgisnx`
if [ "$SKIP_KERNEL" != "y"  -a  -z "$SGICONSOLE"  -a  -n "$PKGLIST" ]; then

    echo
    echo "Selecting the appropriate kernel package(s)..."
    echo

    # get the list of packages that are present
    PKGLIST=`GetPackageList kernel_sgisnx_usb`

    # now, determine which of these we can install
    if [ -n "$PKGLIST" ]; then
        for pkg in $PKGLIST; do
            faildep=`CheckDependencies $pkg`
            # make a list of all kernels that we can install
            if [ -z "$faildep" ]; then
                if [ -z "$KERNELPKG" ]; then
                    KERNELPKG=$pkg
                else
                    KERNELPKG=`echo "$KERNELPKG"; echo $pkg`
                fi
            fi
        done
    fi

    # if we can't install any of the loadable module packages,
    # then see if we have a full kernel available
    if [ -z "$KERNELPKG" ]; then
        FULLKERN=`GetPackageList kernel_sgisnx`

        # if we are currently running a 2.4 or later kernel, don't try
        # installing the full 2.2.x kernel
        KMAJOR=`uname -r | cut -f1 -d'.'`
        KMINOR=`uname -r | cut -f2 -d'.'`
        if [ $KMAJOR -gt 2 -o \( $KMAJOR -eq 2 -a $KMINOR -ge 4 \) ]; then
            echo "\
NOTICE: You are currently running the Linux kernel `uname -r`.
This package does not contain an RPM that provides SGI L1 Controller USB
connection support for this kernel.  The driver will be built as part
of this installation."

        # if we can't find a full kernel pkg, then warn the user
        elif [ -z "$FULLKERN" ]; then
            wlevel="ERROR"
            [ "$FORCE_INSTALL" = y ] && wlevel="WARNING"
            echo "
$wlevel:  Could not find a kernel package that will install
properly (meets dependency requirements) on this system!

The choices available in this package are:
$PKGLIST"
            [ "$FORCE_INSTALL" != y ] && exit -1
        else
            KERNELPKG=$FULLKERN
        fi
    fi

    if [ -n "$KERNELPKG" ]; then
        echo "The following kernel packages will be installed:"
        echo "$KERNELPKG"
    else
        #echo "WARNING: No appropriate kernel packages found. Skipping kernel install."
        :   # do nothing
    fi

    #
    # check for installed kernel versions that *would* support the
    # SGIL1 driver, but for which no RPM is available
    #
    
    KERNDIRS=`ls -1d /lib/modules/[0-9]*/kernel/drivers/usb 2>/dev/null | cut -f1-4 -d/`
    KERN_MAKE_DRIVER=n
    for kdir in $KERNDIRS; do
        #echo "**************************************************************"
        kern=`echo $kdir | cut -f4 -d/`
        #echo "Trying kernel $kern:"

        # get the name of the kernel w/o the "smp" or "enterprise" suffix
        # (the smp/enterprise suffix both map back to the same kernel
        #  source/header RPMs as the "normal" (no suffix) kernel; same applies
        #  for the sgisnx USB driver RPMs)
        krel=`echo $kern | sed 's|smp\|enterprise||g'`

        # check for USB driver RPM already installed
        # (using kernel release w/ smp or enterprise stripped off)
        if rpm -q kernel_sgisnx_usb-$krel >/dev/null 2>/dev/null; then
            # L1 USB driver RPM already installed
            continue
        fi

        # check for USB driver RPM in list of kernel drivers to install
        # (using kernel release w/ smp or enterprise stripped off)
        if echo "$KERNELPKG" | grep kernel_sgisnx_usb-$krel >/dev/null 2>/dev/null; then
            # L1 USB driver RPM is being installed
            continue
        fi

        # special case: skip any kernel with the "BOOT" or "debug" suffix, as
        # these types of kernels are not used for normal operation
        if echo "$kern" | grep -q -e "BOOT$" -e "debug$"; then
            [ "$VERBOSE" = y ]  &&  (echo; echo "Skipping kernel $kern (kernel type not used in normal operation)")
            continue
        fi

        # if we get here, print the message telling them how to build/install
        # the driver, or why they can't build/install the driver
        echo
        echo "NOTICE:  No package found for $kern kernel; building and installing the driver now..."

        MKDRIVOUT=`$SCRIPTDIR/sgil1_make_driver $kern`
        if [ $? -ne 0  -o  "$VERBOSE" = y ]; then
            echo "ERROR building kernel driver:"
            echo "$MKDRIVOUT"
            echo
        fi

    done

fi

echo

# create the kernel package name (filename less the version and .$ARCH.rpm)
KERNELPKG=`echo "$KERNELPKG" | sed -e 's/-[^-]*-[^-]*$//'`

# ********** obtain a list of files to install *********
if [ -n "$SGICONSOLE" ]; then
    PKGORDER="snxsc_firmware snxsc_l3 vacm-l2"
else
    PKGORDER="$KERNELPKG snxsc_firmware snxsc_l3 sgidiag snxscan sysco_tools sscope"
fi
PKGLIST=`GetPackageList $PKGORDER`

echo
echo "The following packages will be installed:"
echo "$PKGLIST"
echo



# ********** check the dependencies for these packages *************

PKGFAILS=`CheckDependencies $PKGLIST`

if [ -n "$PKGFAILS" ]; then
    # print a different message for FORCE install than normal install
    if [ "$FORCE_INSTALL" != y ]; then
        echo "
ERROR:   Cannot install because the following
required packages (RPMs) are missing:
$PKGFAILS

Please install the above RPMs and retry this install."
        exit 1

    else

        echo "
WARNING!!   The following required packages (RPMs) are missing:
$PKGFAILS

Continuing install (-force option specified)....."
        echo; echo
    fi
fi

# ********** verify if package exists and either upgrade or install **********

InstallPackages $PKGLIST

