#!/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:
#
# 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"

###################
#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
             fi
          fi
          # if we did not already check for availability of lic pkg,
          # do so now
          if [[ $LICPKG_CHECKED != 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}}}'`
ALT_PREFIX=`echo "$*" | 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 any options did not match (bad options) print help and exit
if echo "$*" | awk -v a="$PLATFORM" -v b="$ALT_PREFIX" '{ \
   ct=0; if(length(a)) ct=ct+1; if(length(b)) ct=ct+1; \
   if(ct!=NF) exit 0; exit 1}'
then echo " "
     echo "Usage:" 
     echo "install_server [prefix], where prefix is optional and it denotes the file system where product is to be installed. The default install location is /opt."
     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
RPM_DIR=`echo "$PLATFORM" | awk '{ \
        if($1=="ppc64")  print $1; \
        if($1=="s390x")  print $1; \
        if($1 ~ /i.86/)  print "i686"; \
        if($1=="x86_64") print "x86_64" ; \
        }'`

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

if test -z "$RPM_DIR"
then echo " "
     echo "Not a recognized platform, $PLATFORM."
     echo "Use install_server [platform] [prefix], where platform is ppc64, s390x, or i686. Prefix is optional and it denotes the file system where product is to be installed."
     exit 1
fi

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

#call the LAP tool to force agreement to license
licensedir=$INST_PATH/license
lapapp=/tmp/license/LAPApp.jar
jre=/tmp/license/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/license 2>/dev/null
     mkdir /tmp/license 2>/dev/null
     cp $licensedir/* /tmp/license 2>/dev/null >/dev/null

     #copy the proper jre in and check for copy failure
     cp -r $licensedir/$JRE_DIR/jre /tmp/license

     ret=$?
     if test $ret -ne 0
     then echo "Error copying $licensedir 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/license -s /tmp/license -text_only 

     ret=$?
     if test $ret -eq 3 -o $ret -eq 130
     then echo "License terms not agreed to."
          rm -rf /tmp/license 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
# if we're on pSeries, we have to distinguish between pkgs for SLES9/RHEL3, and
# packages for SLES8
if [[ $RPM_DIR != ppc64 ]]
then
   RPM_FILE_LIST=`ls $INST_PATH/$RPM_DIR/*.rpm $INST_PATH/noarch/*.rpm`
else
   glibc=`rpm -qa | grep ^glibc-2. | cut -c1-9` 
   glibc=`echo $glibc | awk -F" " '{ print $1 }'`
   RPM_FILE_LIST=`ls $INST_PATH/$RPM_DIR/$glibc/*.rpm $INST_PATH/noarch/*.rpm`
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/license; 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

