#!/bin/bash
#install_server - controls the installation of the TSM Server on Linux
# 5765-303 (C) Copyright IBM Corporation 1990, 2003
#
# Creation: Fraser McCartney, IBM - 12/10/2003
#
# Change history:
#
# 31 Oct 2007 fraserm 36707
# Updated LAPApp temporary run location.
#
# 18 June 2007 ipouerie IC52385
# Add option to use different path for JRE
# 
# 12 June 2007 ipoueerie 33645
# added flag to acknowledge whether TIVsm-license pkg is needed on install media 
#
# 23 Apr 2007 fraserm 32883
# Added support for ia64sremoving code that required every platform
# be listed for the rpm and jre subdirs. This makes the code a little harder
# to read but means platforms can be added witout updating this script.
#
# 23 Oct 2006 jolay 30627
# fixed problem caused by 29041 that does not account for glibc2.2.5
#
# 3 Aug 2006 fraserm 29041
# ppc SLES10 uses glibc2.4 which is compatable with glibc2.3 but code here
# was not finding the special glibc2.3 version server packages. Detection
# code may be obsolete if we do not support older ppc OSs that used glibc2.2
#
# 21 Aug 2005 ipouerie 22214
# Redesign for x86_64 support - see HLD for LI 1418
#
# 12 June 2005 ipouerie linux_x86_64
# add support for x86_64
#
# 10 Mar 2005 fraserm
# adding support for installing i686 RPMs on RHEL4/AMD64
# new JRE name needed and cleanup of code
#
# 8 Dec 2004 ipouerie 20642
# use awk to account for more than one instance of glibc
#
# 2 Dec 2004 ipouerie IC42812
# use the prefix given at cmd line during an upgrade
#
# 1 Dec 2004 ipouerie gaLinuxPkg
# remove support for s390, add support for new pkg
# structure on pSeries
#
# 9 Sept 2004 fraserm 17260
# removed webadmin and webhelp from basic install - no longer packages in 53
#
# 9 Aug 2004 fraserm 15300
# removed code checking for running server, workitem 1361 addressed elsewhere
#
# 5 May 2004 fraserm 14583
# forced unconditional exit if user is not root
#
#

BASIC_INST_PACKAGES="TIVsm-server TIVsm-license"
LICPKG_CHECKED=0
licPkgNeeded=0

###################
#function section #
###################

function ask()
{
  ASK_TEXT="$1"; ASK_CHOICES="$2"

   while echo "$ASK_TEXT"
   do
    read ASK_ANS
    echo "$ASK_ANS" | awk -v chs=$ASK_CHOICES '{ if(length($0)>1) exit 0; \
        ua="ABCDEFGHIJKLMNOPQRSTUVWXYZ"; la="abcdefghijklmnopqrstuvwxyz"; \
        i=index(la,$1); if(i) $1=substr(ua,i,1); \
        i=index(chs,$1); exit i;}'; ret=$?

    if test $ret -ne 0; then return $ret; fi
  done
}


function kill_dir_apps()
{
  CMDDIR="$1"

  #return now if bug allows call without command name (dangerous)
  if test -z "$CMDDIR" ; then return 1; fi

  #get the PID column number, no guessing allowed, error if not found
  PIDCOL=`ps -f | awk '{ if(NR>2) exit 1; for(i=1;i<=NF;i++) \
           if($(i)=="PID"){ print i; exit 0;}}'`
  CMDCOL=`ps -f | awk '{ if(NR>2) exit 1; for(i=1;i<=NF;i++) \
           if($(i)=="CMD" || $(i)=="COMMAND"){ print i; exit 0;}}'`
  if test -z "$PIDCOL" -o -z "$CMDCOL"; then return 2; fi

  KLIST=`ps -ef | \
         awk -v pc="$PIDCOL" -v cc="$CMDCOL" -v cmdd="$CMDDIR" '{ \
           if(substr($(cc),1,length(cmdd))==cmdd) printf "%i\n",$(pc)}'`

  #for each pid in the kill list, issue kill-9s
  for K in $KLIST
  do kill -9 $K 2>/dev/null >/dev/null
  done
  #if any were killed, give kill some time to clean up
  if test -n "$KLIST"; then sleep 3; fi
}


function inst_rpm()
{
  INST_RPM_FILE=$1
  INST_RPM_NAME=`rpm -qp $INST_RPM_FILE --queryformat %{NAME}`
  INST_RPM_VER=`rpm -pq $INST_RPM_FILE`

  #INST_RPM_OLD_VER will be "" if RPM package is not installed
  INST_RPM_OLD_VER=""
  #echo "DEBUG: checking if old version is installed..."
  rpm -q $INST_RPM_NAME >/dev/null 2>/dev/null
  if [[ $? == 0 ]]
  then
     INST_RPM_OLD_VER=`rpm -q $INST_RPM_NAME`
  fi

  #if the same package is already installed, return
  if test "$INST_RPM_OLD_VER" = "$INST_RPM_VER"
  then
    echo ""
    #echo "DEBUG: installed pkg is same as new pkg"
    if [[ $PLATFORM == "x86_64" ]]
    then
       #echo "DEBUG: calling is32BitPkg with $INST_RPM_NAME"
       is32BitPkg $INST_RPM_NAME
       is32Bit=$?
       #echo "DEBUG: is32Bit is: $is32Bit"
       if [[ $is32Bit == 1 ]]
       then
          echo "A 32bit version of the package $INST_RPM_NAME was found on the system."
          echo "This installation will perform a migrate install to the 64bit package."
          echo "It will remove the existing 32bit pkg and install the 64bit one."
          echo "If you wish to go back to a 32bit TSM environment after the migration is"
          echo "completed, uninstall the 64bit packages manually and re-install the"
          echo "32bit packages."
          echo ""
          ask "Should I continue with the migration? (Y/N)" "YN"
          migrate=$?
          #echo "DEBUG: MIGRATE: $migrate"
          if [[ $migrate == 1 ]]
          then
             echo "Removing the 32bit pkg..."
             # remove the existing 32-bit pkg
             rpm -e $INST_RPM_NAME /dev/null 2>/dev/null
             # remove the old license pkg
             #echo "DEBUG: removing license..."
             rpm -e TIVsm-license >/dev/null 2>/dev/null
          else
             echo "Package $INST_RPM_FILE not installed."
             return 1
          fi
       elif [[ $is32Bit == -2 ]]
       then
          echo ""
          #echo "DEBUG: bitness doesn't matter for this spkg...$INST_RPM_FILE"
          # no need to check whether lang pkgs, etc are 32 or 64bit
       else
          echo ""
          #echo "DEBUG: found a 64bit Server installed..."
          echo "$INST_RPM_VER already installed."
          return 1
       fi
     fi
  fi

  #if there is another version installed update it
  if test -n "$INST_RPM_OLD_VER"
  then
     echo ""
     #echo "DEBUG: Found an old version installed..."
     echo "Updating the currently installed $INST_RPM_OLD_VER."
     #if we're doing a 64bit migrate install, it means we have removed the 32bit pkg already
     if [[ $migrate == 1 ]]
     then
        #echo "DEBUG: Migrating the currently installed $INST_RPM_OLD_VER to 64-bit..."
        rpmCmd="rpm -ivh "
    else
       rpmCmd="rpm -Uvh "
    fi
    if test -n "$ALT_PREFIX"
    then
      $rpmCmd $INST_RPM_FILE --prefix $ALT_PREFIX; ret=$?
    else
      $rpmCmd $INST_RPM_FILE; ret=$?
    fi
    if test $ret -ne 0
    then
       echo " "
       echo "\"rpm -Uvh $INST_RPM_FILE\" was not successful ."
       echo "The RPM issues must be resolved to continue the installation."
       echo "Please contact customer support for assistance."

    fi
    return $ret
  fi

  #if this is a fresh install, ask for alternate dir and install
  if test -z "$INST_RPM_OLD_VER"
  then
       echo "Installing $INST_RPM_VER."

       if test -n "$ALT_PREFIX"
       then
          INST_RPM_RUN="rpm -ivh $INST_RPM_FILE --prefix $ALT_PREFIX"
       else
          INST_RPM_RUN="rpm -ivh $INST_RPM_FILE"
       fi
       $INST_RPM_RUN; ret=$?
       if test $ret -ne 0
       then
            echo " "
            echo "\"$INST_RPM_RUN\" was not successful."
                       echo "The RPM issues must be resolved to continue the installation."
            return 1
       fi
       #echo "DEBUG: checking for lic pkg.."
       #if not license package, issue info msg
       if [[ $PLATFORM == "x86_64" ]]
       then
          rpm -q TIVsm-license >/dev/null 2>/dev/null
          # if the lic pkg is installed, check if it's the 64 or the 32 bit version
          if [[ $? == 0 ]]
          then
             licPrefix=`rpm -q TIVsm-license --queryformat %{INSTALLPREFIX}`
             lic64bitInstalled=`file $licPrefix/tivoli/tsm/server/bin/dsmreg.sl | awk '{ print $3 }'`
             if [[ $lic64bitInstalled == "32-bit" ]]
             then
                rpm -e TIVsm-license >/dev/null 2>/dev/null
                licPkgNeeded=1
             fi
          fi
          # if we did not already check for availability of lic pkg,
          # do so now
          if [[ $LICPKG_CHECKED != 1 ]] && [[ licPkgNeeded == 1 ]]
          then
             isLicPkgAvail $PLATFORM
             if [[ $? != 1 ]]
             then
               echo "The license package for TSM Server was not found on the installation media."
               echo "The TSM Server was installed in try/buy mode."
               echo ""
               echo "To obtain the license module for $PLATFORM, obtain a CD or elecectronic iso"
               echo "image from your regular software order system.  This could be"
               echo "Passport Advantage if you obtain your IBM software electronically."
               echo "You must have an authorized userid and password to obtain your software"
               echo "from Passport Advantage."
               echo "If you placed and order and were shipped CDs via the Advanced Administrative"
               echo "System (AAS), you may request an MES update (miscellaneous equipement update)."
               echo "For AAS, see your SE if you have questions."
            fi
            LICPKG_CHECKED=1
          fi
       fi
    fi
    return 0
}

#****************************************************************************
# is32BitPkg()
#
# function:      determines whether a pkg is 32bit or 64bit
# Input:         pkg name (TIVsm-server, TIVsm-tsmscsi, TIVsm-stagent)
#                install prefix(/opt, /usr, etc)
#
# returns:
#                1 - pkg is 32bit,
#                0 - pkg is 64bit
#               -1 - unable to determine
#               -2 - no need to determine
#
# Side effects: None
#
#****************************************************************************
function is32BitPkg()
{
  pkgName=$1

  echo "pkgName: $pkgName"
  #echo "\$1: $1"

  #if no prefix or pkgName given, return unsucessfull
  if [[ -z $pkgName ]]
  then
     echo "is32BitPkg: Unable to determine whether 32bit or 64bit pkg is installed due to"
     echo "missing parameter. Please contact customer support for assistance."
     return -1
  fi

  # all is fine... proceed with determining
  # the pkg install file system
  # get the install prefix first
  prefix=`rpm -q $pkgName --queryformat %{INSTALLPREFIX}`
  echo "the prefix for $pkgName is $prefix..."

  if [[ $pkgName == "TIVsm-server" ]]
  then
     FileToCompare=$prefix/tivoli/tsm/server/bin/dsmserv
  elif [[ $pkgName == "TIVsm-stagent" ]]
  then
     FileToCompare=$prefix/tivoli/tsm/StorageAgent/bin/dsmsta
  elif [[ $pkgName == "TIVsm-tsmscsi" ]]
  then
     FileToCompare=$prefix/tivoli/tsm/devices/bin/lbtest
  else
      FileTocompare=""
      return -2
  fi
  # determine the file type if need to
  # issue error msg if file not found
  if [[ $pkgName != "TIVsm-license" ]] && [[ -n $FileToCompare ]]
  then
     if [[ ! -e $FileToCompare ]]
     then
        echo "is32BitPkg: Unable to determine whether 32bit or 64bit pkg is"
        echo "installed due to unavailabe file $FileToCompare."
        echo "...Please contact customer support for assistance"
        return -1
     fi
  fi

  # find the bitness
  if [[ -n $FileToCompare ]]
  then
     bitness=`file $FileToCompare | awk '{ print $3 }'`
     if [[ $bitness == "32-bit" ]]
     then
        return 1
     elif [[ $bitness == "64-bit" ]]
     then
        #echo "64-bit TSM Environment detected..."
        return 0
     else
        echo "is32BitPkg: Unable to determine whether 32bit or 64bit pkg is"
        echo "installed due to unsupported return value \"$bitness\" from the file function"
        echo "Please contact customer support for assistance."
        return -1
     fi
  else
     return -2
  fi
}

#****************************************************************************
# isLicPkgAvail()
#
# function:     determines whether lic pkg is avail for a particular platform
# Input:        platform (i686, ppc64, x86_64, s390, s390x)
#
#
# returns:      1 if pkg is available,
#               0 if pkg is not available
#              -1 unable to determing
#
# Side effects: None
#
#****************************************************************************
function isLicPkgAvail()
{
  platform=$1

  # if no platform arg given, return with error
  if [[ -z $platform ]]
  then
     echo "isLicPkgAvail: Error determining whether license pkg is available due to"
     echo "missing platform argument. Please contact customer support for assistance."
     return -1
  fi

  # all is fine, see if file exists
  isLicFilePresent=`ls $PWD/$platform/TIVsm-license*.x86_64.rpm`
  #echo "DEBUG: isLicfilePresent: $isLicFilePresent"
  if [[ $isLicFilePresent == "" ]]
  then
     return 0
  else
     return 1
  fi
}

#############################
#command-line parse section #
#############################

#get optional parms from the command line
PLATFORM=`echo "$*" | awk '{plat="ppc64 i686 s390x"; \
              for(i=1;i<=NF;i++){ s=" "$(i)" "; if(index(plat,s)){ \
              print $(i); exit 0}}}'`

while getopts ":j:p:a:" OPT
do
   case $OPT in
      j ) JRE_LOC=$OPTARG ;; 
      p ) prefix=$OPTARG ;; 
      a ) platform=$OPTARG ;; 
      \? ) echo "Invalid option specified"; badopt=1 ;;
   esac
done
shift $(($OPTIND - 1 ))

ALT_PREFIX=`echo "$prefix" | awk '{for(i=1;i<=NF;i++) \
                           if(substr($(i),1,1)=="/"){ print $(i); exit 0}}'`

# LICPKG_CHECKED indicates that we already checked whether the lic pkg is available
LICPKG_CHECKED=0

if [[ $badopt == 1 ]]
then echo " "
     echo "Usage:"
     echo "install_server [-p prefix] [-a architecture] [ -j jrelocation]"
     echo "prefix is optional and it denotes the file system where product is to be installed. The default install location is /opt."
     echo "platform is optional and it denotes the architecture where product is to be installed(ppc64, i686, s390x, x86_64)"
     echo "jrelocation is optional and should be used only if the bunndled jre fails to display license agreement."
     exit 1
fi


####################
#pre-check section #
####################

#check to see if the user is root and ask to quit if not
if test "$UID" != ""
then if test $UID != "0"
     then echo " "
          echo "Your user ID is \"$UID\" and not \"0\" for root. RPM package"
          echo "installation is limited to the user root."
          exit 0
     fi
fi


######################
#environment section #
######################

#aquire a usable install path without trailing "/" (relative ok)
INST_PATH=`echo "$0" | awk '{ s=$0; \
        if(substr(s,1,1) != "/" && substr(s,1,2) != "./") s="./"s; \
        while(substr(s,length(s)) != "/") s=substr(s,1,length(s)-1); \
        print substr(s,1,length(s)-1);}'`

#determine the platform to install (could be from command line)
if test -z "$PLATFORM"
then PLATFORM=`uname -m 2>/dev/null`
fi

#determine the RPM directory for this platform, normaly the platform name
RPM_DIR=`echo "$PLATFORM" | awk '{ dir=$1; \
        if(dir ~ /i.86/)  dir="i686";   \
        } END { print dir }'`


#determine the JRE directory for this platform (most JREs are 32bit)
JRE_DIR=`echo "$PLATFORM" | awk '{ dir=$1; \
        if(dir ~ /i.86/)  dir="i386"; \
        if(dir=="s390x")  dir="s390"; \
        } END { print dir }'`

if test -z "$RPM_DIR"
then echo " "
     echo "Not a recognized platform, $PLATFORM."
     echo "install_server [-p prefix] [-a architecture] [ -j jrelocation]"
     echo "prefix is optional and it denotes the file system where product is to be installed. The default install location is /opt."
     echo "platform is optional and it denotes the architecture where product is to be installed(ppc64, i686, s390x, x86_64)"
     echo "jrelocation is optional and should be used only if the bunndled jre fails to display license agreement."
     exit 1
fi

###################
#lap tool section #
###################

#call the LAP tool to force agreement to license
licensedir=$INST_PATH/license
lapapp=/tmp/TSMS_elic/LAPApp.jar

if [[ -n $JRE_LOC ]]
then
   jre=$JRE_LOC
else
   jre=/tmp/TSMS_elic/jre
fi

echo "jreloc: $jre"

# if the LAP tool is not available, do not try to run it
if test -d $licensedir
then echo "Preparing License Agreement"

     #kill any rogue java exes from prior aborted installation attempts
     kill_dir_apps $jre

     #linux is special. It has more than one JRE on the CD.
     #only copy the license files and not the JRE yet
     rm -rf   /tmp/TSMS_elic 2>/dev/null
     mkdir -p /tmp/TSMS_elic 2>/dev/null
     cp $licensedir/* /tmp/TSMS_elic 2>/dev/null >/dev/null

     #copy the proper jre in and check for copy failure
     if [[ -n $JRE_LOC ]]
     then
        echo "Using $JRE_LOC to display lic agreement..."
     else
        cp -r $licensedir/$JRE_DIR/jre /tmp/TSMS_elic
     fi

     ret=$?
     if test $ret -ne 0
     then echo "Error copying JRE to /tmp."
          echo "Check that /tmp has more than 120MBs free and allows full access."
          exit 1
     fi

     $jre/bin/java -classpath $lapapp:$jre/lib/rt.jar:$jre/lib/i18n.jar com.ibm.lex.lapapp.LAP -l /tmp/TSMS_elic -s /tmp/TSMS_elic -text_only

     ret=$?
     if test $ret -eq 3 -o $ret -eq 130
     then echo "License terms not agreed to."
          rm -rf /tmp/TSMS_elic 2>/dev/null; exit 1
     fi
     if test $ret -ge 10
     then echo "Java error code $ret."
          exit 1
     fi
     if test $ret -ne 9
     then echo "JRE error attempting to evoke the license acceptance tool."
          echo "Error code $ret."
          exit 1
     fi
     echo "License Agreement Accepted"
fi


######################
#menu / main section #
######################

#declare the detected platform and the given alt prefix (dir) just for diag
echo "Ready to install RPM packages for $RPM_DIR."
if test -n "$ALT_PREFIX"
then
   echo "Using alternate directory prefix $ALT_PREFIX."
fi

#compile a list of RPMs for installation
# pSeries glibc 2.3+ requres a different server package. Change path depending
# on glibc ver. SLES9 and RHEL3 use glibc 2.3. SLES10 uses glibc 2.4
if [[ $RPM_DIR != ppc64 ]]
then
   RPM_FILE_LIST=`ls $INST_PATH/$RPM_DIR/*.rpm $INST_PATH/noarch/*.rpm 2>/dev/null`
else
   # get the version of glibc
   glibcVer=`rpm --queryformat '%{VERSION}' -q glibc | \
         awk -F. '{if(!$2) $2=0; printf "%i.%i",$1,$2;}'`


   # if glibc > 2.3 then use glibc 2.3 packages (2.4 used on SLES10)
   if echo "$glibcVer" | awk '{if ($1 > "2.3") exit 0; exit 1;}'
   then
     glibcVer="2.3"
   fi
   RPM_FILE_LIST=`ls $INST_PATH/$RPM_DIR/glibc-$glibcVer/*.rpm $INST_PATH/noarch/*.rpm 2>/dev/null`
fi

RPM_NAME_LIST=`for name in $RPM_FILE_LIST; do rpm -pq $name 2>/dev/null; done`

if test -z "$RPM_NAME_LIST"
then echo "Unable to query RPM for package names. RPM must be installed and functioning for package installations."
     rm -rf /tmp/TSMS_elic; exit 1
fi

#create the menu of packages for later display
RPM_MENU=`echo $RPM_NAME_LIST | awk '{ \
    for(i=1;i<=NF;i++){ sp=" "; if(i<10) sp=sp" "; if(i<100) sp=sp" "; \
    printf "\t%i%s%s\n",i,sp,$(i);} \
    printf "\tB   BASIC INSTALL\n"; \
    printf "\tQ   QUIT\n"}'`


#the RPM package install menu (loops until q/Q or package install failure)
while echo " "
do  LIST_COUNT=`echo $RPM_NAME_LIST | awk '{for(i=0;i<NF;i=i)i++}END{print i}'`

    #display list of packages
    echo " "
    echo "Please select a package to install or \"Q\" to quit."

    #use "more" to display the menu because it can tell the disp length
    echo "$RPM_MENU" | more

    #ask user for package or q/Q to quit
    read ans
    echo "$ans" | awk -v ct=$LIST_COUNT '{if(NF>1) exit 1; \
        if($1=="q"|| $1=="Q") exit 1; \
        if($1=="b"|| $1=="B") exit 2; \
        if($1<0 || $1>ct) exit 3;}'; ret=$?

    #if package selected, install
    if test $ret -eq 0
    then RPM_FILE=`echo $RPM_FILE_LIST | awk -v num=$ans '{print $(num)}'`

         #attempt to install the package (return of 1 is failure)
         inst_rpm "$RPM_FILE"; ret=$?

         #if the installation failed exit the script
         if test $ret -ne 0
         then exit 1
         fi

         #success, wait a moment before showing the menu again
         sleep 3
    fi


    #check for quit exit if it is given
    if test $ret -eq 1
    then exit 0
    fi


    #if the default set of packages was requested, install them
    if test $ret -eq 2
    then echo "The basic install includes the following packages:"

         #compile a list of the packages' base names for comparison
         BASE_NAME_LIST=`for name in $RPM_FILE_LIST; \
             do rpm -qp $name --queryformat %{NAME}; echo ""; done`

         #get a list of numbers that index basic packages in RPM_FILE/NAME_LIST
         BASIC_NUM_LIST=`for name in $BASIC_INST_PACKAGES; \
            do echo $BASE_NAME_LIST | awk -v n=$name '{ \
            for(i=1;i<=NF;i++) if(n==$(i)){ print i; exit 0}}'; \
            done`

         #get the basic install RPM packages names and display them
         for num in $BASIC_NUM_LIST
         do echo $RPM_NAME_LIST | awk -v n=$num '{ print $(n)}'
         done

         #ask if the user wants to continue and install them
         echo " "
         ask "Should I continue with the basic install? (Y/N)" "YN"; ret=$?

         #if Y then compile a file list and install each
         if test $ret -eq 1
         then  BASIC_INST_FILE_LIST=`for num in $BASIC_NUM_LIST; \
                   do echo $RPM_FILE_LIST | awk -v n=$num '{ print $(n)}'; done`

               #attempt to install each file, exit if error on any
               for name in $BASIC_INST_FILE_LIST
               do inst_rpm "$name"; ret=$?
                  if test $ret -ne 0
                  then
                     exit 1
                  fi
                  #give RPM time to clear
                  sleep 2
               done
         fi
    fi

done

