# This must be called in a script before set -e because
# /etc/init.d/functions on RedHat is not errexit safe and will exit
# prematurely.

SUSE_RELEASE=/etc/SuSE-release
REDHAT_RELEASE=/etc/redhat-release
UBUNTU_RELEASE=/etc/debian_version

LIBDIR=/usr/lib/vmware-tools

error()
{
   echo "ERROR: $*"
   exit 1
}

[ $( id -u ) = 0 ] || error "Must run $0 as root"

[ $# -gt 0 ] || error "Must specify at least one argument to $0"

# todo: check to see if this bizarre thing is actually still needed here
#
# This comment is a hack to prevent RedHat distributions from outputing
# "Starting <basename of this script>" when running this startup script.
# We just need to write the word daemon followed by a space

# This defines echo_success() and echo_failure() on RedHat
if [ -r /etc/init.d/functions ]; then
   . /etc/init.d/functions
fi

# This defines $rc_done and $rc_failed on S.u.S.E.
if [ -f /etc/rc.config ]; then
   # Don't include the entire file: there could be conflicts
   rc_done=`(. /etc/rc.config; echo "$rc_done")`
   rc_failed=`(. /etc/rc.config; echo "$rc_failed")`
else
   # Make sure the ESC byte is literal: Ash does not support echo -e
   rc_done='[71G done'
   rc_failed='[71Gfailed'
fi

# Is a given module loaded?
isLoaded()
{
   local module="$1"

   /sbin/lsmod | awk 'BEGIN {n = "no";} {if ($1 == "'"$module"'") n = "yes";} END {print n;}'
}

#
# We exit on failure because these functions are called within the
# context of vmware_exec, which sets up a trap that causes exit to jump
# back to vmware_exec, like an exception handler. On success, we return
# because our caller may want to perform additional instructions.
#
vmware_load_module() {
   local module=$1
   shift

   if [ "`isLoaded $module`" = "yes" ]; then
      /sbin/rmmod $module
   fi

   local path=/lib/modules/`uname -r`/misc/$module.ko

   # Prefer kernel versioned modules if they exist.  Currently this is the
   # case for ubuntu as well as user rebuilt kmod source packages.
   if [ -e "$path" ]; then
      /sbin/insmod -s -f "$path" >/dev/null 2>&1 || error "Unable to load kernel module $module from $path"
      return 0
   fi

   local modulesPath=/usr/lib/vmware-tools/modules

   local rhel4="EL(|smp|hugemem)$"
   local rhel5="el5(|PAE)$"
   local sles9="(smp|default|bigsmp)$"
   local sles10="(smp|default|bigsmp|vmi|vmipae)$"
   local sles11="(default|pae|vmi)$"

   local dist=`get_dist_key` || error "Unable to detect distribution"
   eval "local regex=\$$dist"

   local release=`uname -r`
   local kmodType=`echo $release | awk '{ match($0, /'$regex'/, arr)
                                          print arr[1] }'`

   # There is only one kernel type for UP and SMP systems on RHEL5.
   if is_rhel && [ `get_major_version` = "5" ] && [ -z $kmodType ]; then
      kmodType=smp
   fi

   local distroRelease=`get_release_type``get_release` || \
      error "Unable to determine distribution release version."

   # For RHEL systems only: ABI is guaranteed, so fall back on a default
   # path if one doesn't exist for this minor version.
   if is_rhel && [ ! -e "$modulesPath/$distroRelease" ]; then
      distroRelease=default
   fi

   # If there is no extension then it means it's UP.
   if [ -z $kmodType ]; then
      if is_rhel; then
         kmodType=up
      else
         error "Unable to determine kernel type"
      fi
   fi

   path=$modulesPath/$distroRelease/$kmodType/$module.ko

   /sbin/insmod -s -f "$path" >/dev/null 2>&1 || error "Unable to load kernel module $module from $path"
   return 0
}

vmware_unload_module() {
   if [ "`isLoaded "$1"`" = 'yes' ]; then
      /sbin/rmmod "$1" >/dev/null 2>&1 || exit 1
   fi
   return 0
}

# Determine if SELinux is enabled
isSELinuxEnabled()
{
   if [ "`cat /selinux/enforce 2> /dev/null`" = "1" ]; then
      echo "yes"
   else
      echo "no"
   fi
}

vmware_failed()
{
  if [ "`type -t 'echo_failure' 2>/dev/null`" = 'function' ]; then
    echo_failure
  else
    echo -n "$rc_failed"
  fi
}

vmware_success()
{
  if [ "`type -t 'echo_success' 2>/dev/null`" = 'function' ]; then
    echo_success
  else
    echo -n "$rc_done"
  fi
}

# Execute a macro
vmware_exec()
{
  local msg="$1"  # IN
  local func="$2" # IN
  shift 2

  echo -n '   '"$msg"

  # On Caldera 2.2, SIGHUP is sent to all our children when this script exits
  # I wanted to use shopt -u huponexit instead but their bash version
  # 1.14.7(1) is too old
  #
  # Ksh does not recognize the SIG prefix in front of a signal name
  if [ "$VMWARE_DEBUG" = 'yes' ]; then
    (trap '' HUP; "$func" "$@")
  else
    (trap '' HUP; "$func" "$@") >/dev/null 2>&1
  fi
  if [ "$?" -gt 0 ]; then
    vmware_failed
    echo
    return 1
  fi

  vmware_success
  echo
  return 0
}

# Runs a command and retries under the provided SELinux context if it fails
vmware_exec_selinux()
{
   local command="$1"
   # XXX We should probably ask the user at install time what context to use
   # when we retry commands.  unconfined_t is the correct choice for Red Hat.
   local context="unconfined_t"
   local retval

   $command
   retval=$?
   if [ $retval -ne 0 -a "`isSELinuxEnabled`" = 'yes' ]; then
      runcon -t $context -- $command
      retval=$?
   fi

   return $retval
}

do_not_install_or_configure()
{
   local excludes_file="/etc/vmware-tools/excludes"
   [ -e $excludes_file ] && grep -q "$1" $excludes_file
}

# Outputs the first path found to stdout and exits with 0, otherwise
# exits with non-zero exit code.
find_first_exists()
{
   for path in "$@"; do
      if [[ -e "$path" ]]; then
         echo "$path"
         exit 0
      fi
   done

   exit 1
}

# Executes sed-type replacements on the given file in-place.  All
# other arguments are passed to sed.
replace()
{
   local temp="`mktemp /tmp/vmwareReplace.XXXXXX`"
   local file="${@:$#}"          # Last argument
   local sedArgs="${@:0:$#}"

   if sed "$sedArgs" < "$file" > "$temp"; then
      mv -f "$temp" "$file"
   fi

   rm -f "$temp"
}

# Strips all leading a trailing whitespace from stdin, writing to
# stdout.
strip()
{
   tr -d "[:space:]"
}

# Returns 0 if running RHEL, otherwise 1.
is_rhel()
{
   [ -e $REDHAT_RELEASE ]
}

# Returns 0 if running SLES, otherwise 1.
is_sles()
{
   [ -e $SUSE_RELEASE ]
}

# Returns 0 if running Ubuntu, otherwise 1.
is_ubuntu()
{
   [ -e $UBUNTU_RELEASE ]
}

# Get a given field from the SuSE release file.
get_sles_release_field()
{
   local field="$1"
   shift

   local val=`awk '{ match($0, /'$field' = ([0-9]+)$/, arr)
          print arr[1] }' < $SUSE_RELEASE`
   echo $val | strip
}

# Returns the SLES major version (8, 9, 10, etc.)
get_sles_major_version()
{
   get_sles_release_field VERSION
}

# Returns the RHEL major version (3, 4, 5, etc.)
get_rhel_major_version()
{
   local version=`lsb_release --release --short`

   echo "$version" | sed 's/^\([0-9]*\).*$/\1/'
}

# Returns the SP level on SLES
get_sles_release()
{
   local release=`get_sles_release_field PATCHLEVEL`

   # If we didn't find anything just assume GA.
   if [ -n "$release" -a "$release" != 0 ]; then
      echo $release
   fi
}

# Returns the update level on RHEL
get_rhel_release()
{
   local version=`lsb_release --release --short`
   local release="$(echo "$version" | sed 's/^[0-9][0-9]*\.\?//')"

   # if lsb_release includes minor version, use that
   if [ -n "$release" -a "$release" != 0 ]; then
      echo $release
      return 0
   fi

   # otherwise, fall back to /etc/redhat-release
   if [ `get_major_version` = "5" ]; then
      local regex="[0-9]+\.([0-9]+)"
   else
      # Only tested with RHEL4.
      local regex="Update ([0-9]+)\)$"
   fi

   release=`awk '{ match($0, /'"$regex"'/, arr)
                     print arr[1] }' < $REDHAT_RELEASE`

   # If we didn't find anything just assume GA.
   if [ -n $release ]; then
      echo $release
   fi
}

# Returns the full version of Ubuntu without the separating space
# (704, 710, 804, etc.)
get_ubuntu_major_version()
{
   lsb_release --release --short | tr --delete "."
}

get_major_version()
{
   get_`get_dist`_major_version
}

get_release()
{
   get_`get_dist`_release
}

# Return the prefix used for the release version number.
get_release_type()
{
   local release=`get_release`

   if [ -z $release ]; then
      echo ga
      exit
   fi

   if is_rhel; then
      echo u
   elif is_sles; then
      echo sp
   else
      echo
      exit 1
   fi
}

get_dist()
{
   if is_rhel; then
      echo rhel
   elif is_sles; then
      echo sles
   elif is_ubuntu; then
      echo ubuntu
   else
      echo unknown
      exit 1
   fi
}

# Get a unique key representing a combination of the distribution and
# its major version.
#
# Examples:
#    rhel4
#    sles9
#    ubuntu704
get_dist_key()
{
   local dist=`get_dist`
   echo $dist`get_${dist}_major_version`
}

