#!/bin/ksh
#
# ident "@(#)iu_lib.ksh	1.15 02/08/23 SMI"
#
# Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
#

#
# iu_lib.ksh
#
# install/upgrade library (for master tasks and modules)
#

#
# SunOSRelease()
#
# Description:
#     Checks the OS version passed against the one installed
#     on the system.
#
# Parameters:
#     $1 is the OS Release that you are comparing against.
#
# Globals used:
#

SunOSRelease() {
  case "$(uname -r)" in
    $1) return 0
        ;;
    *)  return 1
        ;;
  esac
}


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

YesOrNo() {

   typeset DEFPMPT=""
   typeset DEFVAL=""
   typeset ANS=""

   if [ ${#} -ne 2 ]; then
      return 1;
   fi

   if [ "${2}" = "Y" ]; then
      DEFPMPT="([Y]/N): \c "
      DEFVAL="Y"
   else
      DEFPMPT="(Y/[N]):\c "
      DEFVAL="N"
   fi


   while true
   do
      print "${1} ${DEFPMPT}";
      if [[ $G_QUICK_INSTALL = "no" ]]; then
         read ANS
      fi
      : ${ANS:="${DEFVAL}"}
      if [ "${ANS}" = "Y" -o "${ANS}" = "y" ]; then
         echo Yes >> $G_LOGFILE
         return 0;
      elif [ "${ANS}" = "N" -o "${ANS}" = "n" ]; then
         echo No >> $G_LOGFILE
         return 1;
      fi
   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
            echo .'\c'
            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:
#    (none)

ProductInstalled() {
  typeset pkg=""

  for pkg in $*; do
    pkginfo -q $pkg || return 1
  done

  return 0
}

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

AnyPackageInstalled() {
  pkginfo -q $*
  return $?
}

#
# ProductPartiallyInstalled()
#
# Description:
#    to check if a package has not been completely installed
#
# Parameters:
#    $* : list of packages names
#
# Globals used:
#    (none)

ProductPartiallyInstalled() {
  typeset pkg=""
  typeset -r all_partials="$(pkginfo -p 2>&-) "

  [[ $(echo "$all_partials" | sed 's/ //g') == "" ]] && return 1

  for pkg in $*; do
    echo "$all_partials" | grep "$pkg " 2>&1 >/dev/null && return 0
  done

  return 1
}

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

RemoveProduct() {
  typeset -r admin_file="$1"
  shift
  typeset -r all_pkgs="$*"
  typeset -r pkg_list=$(echo "$all_pkgs" | sed -e 's; ;/\|/var/sadm/pkg/;g')
  typeset pkg=""
  typeset deplist=""
  typeset errlist=""
  typeset errdep=""
  typeset deppkg=""
  typeset status=0
  typeset vflag=""

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

  for pkg in $all_pkgs; do
    pkginfo -q $pkg || continue
    if [[ "$pkg" != "SUNWfns" ]]; then
      deplist=$(grep "${pkg}[ 	]" /var/sadm/pkg/*/install/depend | 
        egrep -v '/var/sadm/pkg/'${pkg_list}'/' | grep '/install/depend:P' |
        awk -F/ '{print $5}')
    fi
    if [[ -z "$deplist" ]]; then
      pkginfo -q $pkg && pkgrm $vflag -n -a $admin_file $pkg
      pkginfo -q $pkg && {
        status=1
        errlist="${errlist}${pkg} "
      }
    else
      status=1
      for deppkg in $deplist; do
        errdep="${errdep}${deppkg} depends on ${pkg}	"
      done
    fi
  done

  if [[ "$status" != "0" ]]; then
    if [[ -n "$errlist" ]]; then
      print "\nThe following packages were not successfully removed:"
      print "${errlist}\n"
    fi
    if [[ -n "$errdep" ]]; then
      print "\nThe following packages were not removed due to dependencies:"
      echo "${errdep}" | tr '	' '\n'
      print -n "\nPlease manually remove packages listed in the first "
      print "column above.\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 $?
}

