#!/bin/bash
############################################################
#                                                          #
# This code is written for Lunar Linux, see                #
# http://lunar-linux.org                                   #
#                                                          #
############################################################
#                                                          #
# lrm is for removing installed packages                   #
#                                                          #
# 20020610                                                 #
#                                                          #
############################################################
#                                                          #
# Copyrighted Kagan Kongar 2002 under GPLv2                #
#                                                          #
# Copyrighted Auke Kok 2004 under GPLv2                    #
#                                                          #
############################################################

help() {
  cat <<END
usage: lrm [options] [module ...]
   -d | --debug         Enables debug messages
   -D | --downgrade [module] [version] downgrades a module
   -h | --help          Displays this help text
   -k | --keepconfig    remove module(s) but keep dependencies and config
   -n | --nosustain     removes module(s) even if they are sustained
   -u | --upgrade       remove the module but do not run scripts etc.
   -v | --verbose       Increases the level of message output
   -p | --purge         Delete all modules that depend on the module(s)
                          being removed as well

lrm is a script for removing installed modules.
   If invoked without options, lrm will remove all installed files
belonging to the module(s) and remove the module(s) from the list
of installed modules.
   Downgrading a module means removing the current installed version
of the module and installing a specific version; given that the
specific version is already in $INSTALL_CACHE/.
   Some modules (such as bash and gcc)  are marked "non-removable" by the
system. In order to remove "sustained" modules, use the nosustain option.
END
  exit 1
}

lrm_module() {
  debug_msg "lrm_module ($@)"

  export TMP_DIRS=$(temp_create "$1.directories")

  run_details $1 &>/dev/null

  VERSION=$(installed_version $MODULE)
  INST_LOG=$INSTALL_LOGS/$MODULE-$VERSION
  MD5_LOG=$MD5SUM_LOGS/$MODULE-$VERSION

  # time-out 1: PRE_REMOVE
  if [ "$UPGRADE" != "on" ]; then
    plugin_call BUILD_PRE_REMOVE $MODULE
    run_module_file $MODULE PRE_REMOVE
  fi

  if [ "$MODULE" != "moonbase" ]; then
    update_plugin $MODULE remove
  fi

  # init.d scripts stop before rm phase, but only if ! upgrading
  if [ "$KEEPCONFIG" != "on" -a "$UPGRADE" != "on" ]; then
    # pre-read these variables!
    SERVICES=$(get_module_config "SERVICES")
    XINETD=$(get_other_module_config "xinetd" "INITDSCRIPTS")
    for INITDSCRIPT in $(get_module_config "INITDSCRIPTS"); do
      verbose_msg "Stopping service $INITDSCRIPT"
      (cd / && /etc/init.d/$INITDSCRIPT stop)
    done
  fi

  # grep -v the install logs over the protected stuff, this
  # yields the files that may be removed
  if [ "$REAP" == "on" -a "$UPGRADE" != "on" ]; then
    cat "$INST_LOG" | grep -v -f "$PROTECTED" | while read TARGET; do
      if [ -e "$TARGET" ] || [ -L "$TARGET" ]; then
        if [ -d "$TARGET" ]; then
          echo "$TARGET" >>$TMP_DIRS
        else
          handle_config_files "$TARGET" && remove_something "$TARGET"
        fi
      fi
    done
    process_directories $TMP_DIRS
  else
    verbose_msg "Skipping removal of files completely (REAP=$REAP, UPGRADE=$UPGRADE)"
  fi

  # administration duty time:
  remove_module $MODULE

  # time-out 2: POST_REMOVE
  if [ "$UPGRADE" != "on" ]; then
    plugin_call BUILD_POST_REMOVE $MODULE
    run_module_file $MODULE POST_REMOVE
  fi
  if [ "$KEEPCONFIG" == "on" -o "$UPGRADE" == "on" ]; then
    debug_msg "skipping removal of dependency listing and configs"
  else
    verbose_msg "removing module from dependency listing and configs"
    remove_depends $MODULE
    # remove alias if required
    if [ $MODULE != moonbase ]; then
      for ALIAS in $(cut -d: -f1 "$MOONBASE/aliases"); do
        if [ "$(get_local_config $(echo LUNAR_ALIAS_${ALIAS:1}))" == "$MODULE" ]; then
          verbose_msg "removing alias mapping from \"$ALIAS\" to \"$MODULE\""
          unset_local_config $(echo LUNAR_ALIAS_${ALIAS:1})
        fi
      done
    fi
    # restart xinetd after xinetd.confs have been removed by lrm...
    if [ -n "$SERVICES" -a -n "$XINETD" ]; then
      verbose_msg "restarting xinetd"
      /etc/init.d/xinetd restart
    fi
  fi

  message "${LRM_COLOR}Removed${EXTEMP} module:" \
    "${MODULE_COLOR}${MODULE}${DEFAULT_COLOR}"

  if [[ ("$MOONBASE_ACT_LOG" == "on" && "$MODULE" == "moonbase") || "$MODULE" != "moonbase" ]]; then
    activity_log  "lrm"  "$MODULE" "$VERSION"  "success"
  fi

  temp_destroy $TMP_DIRS
}

check_status() {
  if ! module_installed $MODULE; then
    message "${MODULE_COLOR}${MODULE}" \
      "${PROBLEM_COLOR}is not installed." \
      "${DEFAULT_COLOR}"
    return 1
  fi

  if [ "$NOSUSTAIN" != "on" -a "$UPGRADE" != "on" ]; then
    debug_msg "checking if \"$1\" is sustained"
    if grep -q "^$MODULE$" "$SUSTAINED"; then
      message "${MODULE_COLOR}${MODULE}" \
        "${PROBLEM_COLOR}is sustained." \
        "${DEFAULT_COLOR}"
      return 1
    fi
  fi
}

downgrade() {
  local CACHE_XZ

  # a local function for listing the contents of install cache
  list_available_cache() {
    ls -1 $INSTALL_CACHE/$MODULE-* | while read LINE; do
      echo "$LINE"
    done
    exit 1
  }

  root_check

  verbose_msg "running \"$MODULE\" DETAILS file"
  run_details $MODULE &>/dev/null || return 1

  if [ -z "$1" ]; then
    message "No version is entered. The below is the list of available files."
    list_available_cache
  fi

  CACHE_XZ=$(xzbz_file "$INSTALL_CACHE/$MODULE-$1-$BUILD.tar")

  if [ ! -s $CACHE_XZ ]; then
    message "Desired version is not available. Here is the available files"
    list_available_cache
  fi

  verbose_msg "checking if \"$MODULE\" is installed"

  if [ -n "$(installed_version $MODULE)" ]; then
    verbose_msg "\"$(installed_version $MODULE)\" of \"$MODULE\" is installed at the moment"

    if [ "$1" == "$I_VERSION" ]; then
      message "The downgrade version is the same as the installed version"
      message "Here is the available files."
      list_available_cache
    fi

    verbose_msg "removing \"$MODULE-$(installed_version $MODULE)\""
    lrm -ts $MODULE || lrm -s $MODULE

  else
    verbose_msg "\"$MODULE\" is NOT installed at the moment"
  fi

  verbose_msg "installing \"$MODULE-$1\""
  verbose_msg "extracting cached install file..."

  xzbz -dc $CACHE_XZ | tar -kt $TAR_P -C / >/dev/null
  verbose_msg "adding module to installed list"

  xzbz -dc $CACHE_XZ | tar -kx $TAR_P -C / 2>/dev/null >/dev/null
  verbose_msg "adding module to installed list"
  add_module $MODULE installed $1
  activity_log "lrm downgrade" "$MODULE" "$1" "success"

  message "${RESURRECT_COLOR}Downgraded module:" \
    "${MODULE_COLOR}${MODULE}" \
    "${DEFAULT_COLOR}" \
    "version" \
    "${VERSION_COLOR}${1}" \
    "${DEFAULT_COLOR}"

  exit
}

. /etc/lunar/config
. $BOOTSTRAP

GETOPT_ARGS=$(getopt -q -n lrm -o "dD:hknuvp" -l "debug,downgrade:,help,keepconfig,nosustain,upgrade,verbose,purge" -- "$@")

if [ -z "$?" ]; then
  help | view_file
  exit
else
  eval set -- $GETOPT_ARGS

  root_check
  enviro_check
  set_priority

  while true; do
    case "$1" in
      -d | --debug)
        ((LUNAR_DEBUG++))
        export LUNAR_DEBUG
        shift
        ;;
      -D | --downgrade)
        export DOWNGRADE="on"
        export MODULE="$2"
        shift 3
        downgrade "${@#-}"
        exit
        break
        ;;
      -h | --help) help ;;
      -k | --keepconfig)
        export KEEPCONFIG="on"
        shift
        ;;
      -n | --nosustain)
        export NOSUSTAIN="on"
        shift
        ;;
      -v | --verbose)
        export VERBOSE="on"
        shift
        ;;
      -u | --upgrade)
        export UPGRADE="on"
        shift
        ;;
      -p | --purge)
        export PURGE="on"
        shift
        ;;
      --)
        shift
        break
        ;;
      *)
        help
        break
        ;;
    esac
  done

  for MODULE in "${@#-}"; do
    if check_status "$MODULE"; then
      # assemble purge list if requested
      if [ "$PURGE" == "on" ]; then
        DEPS=$(list_installed_depending "$MODULE" | sort | uniq)
        for DEP in $DEPS; do
          # skip held modules
          if ! module_held $DEP; then
            # no duplicates
            if ! $(echo $LIST | grep -qw $DEP); then
              message "${MESSAGE_COLOR}Inserting ${MODULE_COLOR}$DEP${DEFAULT_COLOR}${MESSAGE_COLOR} into the removal queue${DEFAULT_COLOR}"
              LIST="$LIST $DEP"
            fi
          fi
        done
        # last append the module itself
        LIST="$LIST $MODULE"
      else
        # no fancy checks, just add to the list
        LIST="$LIST $MODULE"
      fi
    fi
  done
  for MODULE in $LIST; do
    lrm_module $MODULE
  done
fi
