#!/bin/ksh -p
#
# ident "@(#)iu_lib.ksh	1.47 08/08/08 SMI"
#
# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

function YesOrNo {
   # Description:
   #    prompt user for yes or no answer
   #    usage:  YesOrNo <prompt> <default value>
   #    Returns 0 if the user specified "Y" or "Yes" (case insensitive),
   #	nonzero otherwise.
   #
   # Parameters:
   #    $1 - PROMPT prefix
   #    $2 - default value "Y" or "N"
   #
   # Globals used:
   #    G_QUICK_INSTALL

   typeset PROMPT=""
   typeset DEFAULT=""
   typeset RESPONSE=""

   if [[ $# != 2 ]]; then
      return 1
   fi

   if [[ "$2" == "Y" ]]; then
      PROMPT="$1 ([Y]/N): "
      DEFAULT="Y"
   else
      PROMPT="$1 (Y/[N]): "
      DEFAULT="N"
   fi

   while true; do
      print -n "$PROMPT"

      case "$G_QUICK_INSTALL" in
        yes) RESPONSE="";;    # as if user only pressed Enter
        *)   read RESPONSE;;  # actually get user input
      esac
      print "$RESPONSE" >>$G_LOGFILE

      if [[ -z "$RESPONSE" ]]; then
        RESPONSE="$DEFAULT"  # empty response results in use of default
      fi

      case "$RESPONSE" in
	[Yy] | [Yy][Ee][Ss]) return 0;;
	[Nn] | [Nn][Oo])     return 1;;
      esac
   done
}

#
## Check if this is a trusted Solaris host.
##
## Returns 0     if this is a trusted Solaris host
##         non-0 otherwise
#
function isTrustedSolaris {
 typeset isTrustedSolaris=1
 if [[ "$G_OS" = "SunOS" && -x /bin/plabel ]] ; then
  /bin/plabel > /dev/null 2>&1
  if [ $? -eq 0 ] ; then
   isTrustedSolaris=0
  fi
 fi
 return $isTrustedSolaris
}

#
# function StartActivityMeter
#
# Description:
#    Start a subprocesses which prints out a "." (dot) each 2 seconds. This
#    is to show that the installer is not hanging.
#
# Parameters:
#    (none)
#
# Globals used:
#    G_ACTIVITYM_PID

function StartActivityMeter {

   if [[ -z "$G_ACTIVITYM_PID" ]]; then
      (
         while true; do
            print -n '.'
            sleep 2
         done
      ) &
      G_ACTIVITYM_PID=$!
   fi
}

#
# function StopActivityMeter
#
# Description:
#    Stop a subprocesses which prints out a "." (dot)
#
# Parameters:
#    (none)
#
# Globals used:
#    G_ACTIVITYM_PID

function StopActivityMeter {

   if [[ -n "$G_ACTIVITYM_PID" ]]; then
      kill -9 $G_ACTIVITYM_PID
      echo
      G_ACTIVITYM_PID=""
   fi
}

#
# function InstallMsg
#
# Description:
#    to print a message before installing a product
#
# Parameters:
#    $1 : product name
#    $2 : product version
#
# Globals used:
#    (none)

function InstallMsg {
  print "\nInstalling $1 version $2 ..."
  return 0
}

#
# function RemoveMsg
#
# Description:
#    to print a message before removing a product
#
# Parameters:
#    $1 : product name
#    $2 : product version
#
# Globals used:
#    (none)

function RemoveMsg {
  print "\nRemoving $1 version $2 ..."
  return 0
}

#
# function InstallPatches
#
# Description:
#    to install patches
#
# Parameters:
#    $1 : patches directory
#
# Globals used:
#    G_PROGRAM_ID
#    G_PID
#    G_TMP_DIR

function InstallPatches {
  typeset dir="$1"
  typeset all_patches=""
  typeset patch=""
  typeset patchid=""
  typeset exist=""
  typeset pkgs=""
  typeset file="${G_TMP_DIR}/${G_PROGRAM_ID}.${G_PID}.patchadd"

  if [[ -r "${dir}/.order" ]]; then
    all_patches=$(awk '/^[^#]/ { print $1 }' ${dir}/.order 2>&- |
        grep "^[0-9][0-9][0-9][0-9][0-9][0-9]")
  elif [[ -d "${dir}" ]]; then
    all_patches=$(\ls -1 ${dir} 2>&- | awk -F- '{ print $1 }' |
        grep "^[0-9][0-9][0-9][0-9][0-9][0-9]" | sort -u)
  fi

  [[ -n "$all_patches" ]] || return 0

  case "$G_OS" in
  SunOS)
    typeset showrev_p="${G_TMP_DIR}/${G_PROGRAM_ID}.${G_PID}.showrev_p"
    /bin/rm -f ${showrev_p}
    print "\nGenerating patch list..."
    showrev -p 2>&- |
    sed -n 's/Patch: \([0-9][0-9]*-[0-9][0-9]\).*/\1/p' |
    sort -rn >${showrev_p}

    for patchid in $all_patches; do
      print -n "... checking patch ${patchid} ... "
      exist=$(grep "${patchid}-[0-9][0-9]" ${showrev_p} | head -1)
      patch=$(\ls -1 "$dir" 2>&- | grep "^${patchid}" | tail -1)
      pkgs=$(cd "${dir}/${patch}" 2>&-; \ls -1 */pkginfo 2>&- | 
        sed -e 's:/pkginfo::g')

      [[ -n "$pkgs" ]] || continue
      pkginfo -q $pkgs || continue
      if [[ "$patch" > "$exist" ]]; then
        print "installing patch $patch ..."

        StartActivityMeter
        patchadd -M "$dir" "$patch" > "$file" || Note "\npatch $patch did not" \
          "install correctly, log follows, continuing ..."
        StopActivityMeter
        cat "$file"
      else
        print "patch ${exist} already installed."
      fi
    done
    /bin/rm ${showrev_p}
    ;;

  Linux)
    cd $dir
    for patchid in $all_patches; do
      patch=$(ls -d $patchid-*)
      print "installing patch $patch ..."
      (
	cd $patchid-*
        rpm --nodeps -F --noscripts *.rpm
      )
    done
    ;;
  esac

  return 0
}

function ProductInstalled {
  #
  # Description:
  #    to check if a product has been installed succesfully
  #
  # Parameters:
  #    $* : list of packages names
  #
  # Globals used:
  #    G_MEDIA_DIR

  typeset PKG=""
  typeset STATUS=0

  for PKG in $*; do
    if ! $G_MEDIA_DIR/utprodinfo -t installed $PKG; then
      STATUS=1
      break
    fi
  done

  return $STATUS
}

#
# function AnyPackageInstalled
#
# Description:
#    to check if one of the listed packages is installed correctly
#
# Parameters:
#    $* : list of packages names
#
# Globals used:
#    (none)

function AnyPackageInstalled {
  typeset pkg=""

  for pkg in $*; do
    if $G_MEDIA_DIR/utprodinfo -t installed $pkg; then
      return 0
    fi
  done

  return 1
}

function ProductPartiallyInstalled {
  #
  # Description:
  #    to check if a package has not been completely installed
  #
  # Parameters:
  #    $* : list of packages names
  #
  # Globals used:
  #    G_MEDIA_DIR

  typeset PKG=""

  for PKG in $*; do
    if $G_MEDIA_DIR/utprodinfo -t partial $PKG; then
      return 0
    fi
  done

  return 1
}

function InstallProduct {
  #
  # Description:
  #    to install a specific product
  #
  # Parameters:
  #    $1            : admin file (used for pkgadd)
  #    $2	           : device where the packages are located
  #    $* (after $2) : list of packages names
  #
  # Globals used:
  #    G_OS

  typeset VOPT=""

  typeset ADMINFILE="$1"
  typeset DIR="$2"
  shift 2
  typeset PKGS="$*"
  typeset PKG

  typeset STATUS=0

  if [[ G_DEBUG = "yes" ]]; then
     VOPT="-v"
  fi

  for PKG in $PKGS; do
    case "$PKG" in
      *.rpm) eval PKG="\$(basename \$(ls $DIR/$PKG))";;
    esac

    print "\n+++ $PKG"

    DOPT="--nodeps"
    case "$PKG" in
      SUNWuta-*.rpm) ;;
      SUNWuto-*.rpm) ;;
      SUNWutgsm-*.rpm) ;;
      gdm-*.rpm)     ;;
      SUNWutps-*.rpm)     ;;
      SUNWutref-*.rpm)     ;;
      *)             DOPT="";;
    esac

    case "$G_OS" in
      SunOS) pkgadd $VOPT -a $ADMINFILE -d $DIR $PKG;;
      Linux) rpm -i $VOPT $DOPT $DIR/$PKG;;
    esac

    if (( $? != 0 )); then
      STATUS=1
    fi
  done

  return $STATUS
}

function RemoveProduct {
  #
  # Description:
  #    to remove a specific product
  #
  # Parameters:
  #    $1            : admin file (used for pkgrm)
  #    $* (after $1) : list of packages names
  #
  # Globals used:
  #    G_DEBUG
  #    G_OS

  typeset ADMINFILE="$1"
  shift
  set -A PKG $*
  set ${PKG[*]}

  typeset I=$(($# - 1))
  typeset ERRLIST=""
  typeset STATUS=0
  typeset VOPT=""

  if [[ G_DEBUG = "yes" ]]; then
     VOPT="-v"
  fi

  while (( $I >= 0 )); do
    if $G_MEDIA_DIR/utprodinfo -t installed ${PKG[$I]}; then
      print "\n+++ ${PKG[$I]}"
      case "$G_OS" in
        SunOS) pkgrm $VOPT -n -a $ADMINFILE ${PKG[$I]};;
        Linux) rpm --nodeps -e --allmatches $VOPT ${PKG[$I]};;
      esac
    fi

    if $G_MEDIA_DIR/utprodinfo -t installed ${PKG[$I]}; then
      STATUS=1
      ERRLIST="$ERRLIST ${PKG[$I]}"
    fi

    I=$(($I - 1))
  done

  if (( $STATUS != 0 )); then
    if [[ -n "$ERRLIST" ]]; then
      print "\nThe following packages were not successfully removed:"
      print " $ERRLIST\n"
    fi
  fi

  return $STATUS
}

#
# function RemovePatch
#
# Description:
#    to remove a specific patch
#
# Parameters:
#    $* : list of patches
#
# Globals used:
#    (none)

function RemovePatch {
  typeset patches="$*"
  typeset installed=""
  typeset patchrev=""
  typeset patch=""
  typeset status=0

  [[ -n "$patches" ]] || return 0

  typeset showrev_p="${G_TMP_DIR}/${G_PROGRAM_ID}.${G_PID}.showrev_p"
  /bin/rm -f ${showrev_p}
  showrev -p 2>&- | \
      sed -n 's/Patch: \([0-9][0-9]*-[0-9][0-9]\).*/\1/p' | sort -rn \
      > ${showrev_p}

  for patch in $patches; do
    installed=$(grep "${patch}" ${showrev_p})
    [[ -n "$installed" ]] || continue
    for patchrev in $installed; do
      patchrm "$patchrev" || status=1
    done
  done

  /bin/rm ${showrev_p}
  return $status
}

#
# function ProductMsg
#
# Description:
#    to print the product name/version in a standard format
#
# Parameters:
#    $1 : product name
#    $2 : product version
#
# Globals used:
#    (none)

function ProductMsg {
  typeset -L40 S

  case "$1" in
    -n) S="$2"; print -n "$S ";;
    -l) print "$2";;
  esac

  return $?
}

function GetPackagePath {
  #
  # Description:
  #     Return the directory path for the packages based on the
  #     system architecture and kernel.  Nothing will be printed if
  #     either the G_INSTALL_ARCH or the G_INSTALL_OS is invalid.
  #
  # Parameters:
  #     $1 : product name
  #
  # Globals used:
  #     G_INSTALL_OS
  #     G_INSTALL_ARCH

  ProductName="$1"

  case "$G_INSTALL_OS,$G_INSTALL_ARCH" in
  SunOS,sparc)
    print "${G_PRODUCT_DIR}/${ProductName}/Solaris_10+/sparc/Packages"
    ;;

  SunOS,i386)
    print "${G_PRODUCT_DIR}/${ProductName}/Solaris_10+/i386/Packages"
    ;;

  Linux,i[3-6]86 | Linux,x86_64 | Linux,athlon)
    print "${G_PRODUCT_DIR}/${ProductName}/Linux/Packages"
    ;;

  Linux,*)
    if [[ -n "${SUN_SUNRAY_SERVER_ARCH:-}" ]]; then
    	G_INSTALL_ARCH=${SUN_SUNRAY_SERVER_ARCH}
    	print "${G_PRODUCT_DIR}/${ProductName}/Linux/Packages"
    else
    	Error "unsupported platform '$G_INSTALL_OS,$G_INSTALL_ARCH'"
    fi
    ;;

  *)
    Error "unsupported platform '$G_INSTALL_OS,$G_INSTALL_ARCH'"
    ;;
  esac

  return 0
}
