#!/bin/ksh -p
#
# ident "@(#)iu_lib.ksh	1.38 05/06/23 SMI"
#
# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#

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
}

#
# 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

StartActivityMeter() {

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

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

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)

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)

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

InstallPatches() {
  typeset -r dir="$1"
  typeset all_patches=""
  typeset patch=""
  typeset patchid=""
  typeset exist=""
  typeset pkgs=""
  typeset -r 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

  typeset -r 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}
  return 0
}

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
}

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

AnyPackageInstalled() {
  typeset pkg=""

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

  return 1
}

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
}

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 -r ADMINFILE="$1"
  typeset -r DIR="$2"
  shift 2
  typeset -r 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)     ;;
      *)             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
}

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 -r 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 $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)

RemovePatch() {
  typeset -r patches="$*"
  typeset installed=""
  typeset patchrev=""
  typeset patch=""
  typeset status=0

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

  typeset -r 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
}

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

ProductMsg() {
  typeset -L40 S

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

  return $?
}

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

  typeset -r ProductName="$1"

  case "$G_INSTALL_OS,$G_INSTALL_ARCH" in
  SunOS,sparc)
    print "${G_PRODUCT_DIR}/${ProductName}/Solaris_8+/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
}
