#!/bin/bash
############################################################
#                                                          #
# This code is written for Lunar Linux, see                #
# http://www.lunar-linux.org                               #
#                                                          #
############################################################
#                                                          #
# lrm is for removing installed packages                   # 
#                                                          #
# 20020610                                                 #
#                                                          #
############################################################
#                                                          #
# Copyrighted Kagan Kongar 2002 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
   -v | --verbose       Increases the level of message output
   
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
}


exit_proc() {
  debug_msg "exit_proc ($@)"
  temp_destroy $LRM_QUEUE
  temp_destroy $LRM_TEMP
  temp_destroy $TEMP_FILE
  temp_destroy $TEMP2_FILE
  exit
}


trap_proc() {
  verbose_msg "Trapped a signal! "
  exit_proc
}


handle_config_files() {
  debug_msg "handle_config_files ($@)"
  TARGET="$1"
  if dirname "$TARGET" | grep -q "^/etc" ; then
    verbose_msg "Examining config file \"$TARGET\""

    TARGET_MD5=$(md5sum "$TARGET" | cut -d " " -f 1-1)
    OLD_MD5=$(grep -w "$TARGET\$" $MD5_LOG | cut -d " " -f 1-1)

    if [ -z "$TARGET_MD5" ] ; then
      verbose_msg "Skipping removal of \"$TARGET\" due to problem with md5sum"
      continue
    fi

    if [ -z "$OLD_MD5" ] ; then
      verbose_msg "Skipping removal of \"$TARGET\" due to missing original md5sum"
      continue
    fi

    if [ "$TARGET_MD5" == "$OLD_MD5" ] ; then
      verbose_msg "Removing \"$TARGET\""
      rm -f $TARGET
      continue
    fi

    if [ "$TARGET_MD5" != "$OLD_MD5" ] ; then
      verbose_msg "Skipping removal of \"$TARGET\" due to md5sum mismatch"
      if [ "$PRESERVE" == "on" ] ; then
         verbose_msg "PRESERVE=on, keeping \"$TARGET\""
         continue
      else
         verbose_msg "PRESERVE=off, archiving \"$TARGET\""
         mv $TARGET $TARGET.`date +%Y%m%d%H%M`
         continue
      fi
    fi
  fi
}

remove_something() {
  debug_msg "remove_something ($@)"
   if [ -z "$1" ]; then
     debug_msg "remove_something: No args, exiting"
     return 1
   fi

   if ! [ -e "$1" ] && ! [ -L "$1" ] ; then
     debug_msg "remove_something: no such file $1, exiting"
     return 1
   fi

   TARGET="$1"

   if [ -d "$TARGET" ] ; then
     rmdir $TARGET 2> /dev/null
   else
     rm -f $TARGET 2>/dev/null
   fi

   if [ "$?" == "0" ] ; then
     debug_msg "remove_something: removed $TARGET succesfully"
   else
     debug_msg "remove_something: removed $TARGET not succesful"
   fi
}

process_directories() {
  debug_msg "process_directories ($@)"

  if [ -z "$1" ]; then
    debug_msg "process_directories: No args, exiting"
    return 1
  fi

  cat $1 | sort -r | while read LINE ; do
    remove_something "$LINE"
  done
}


process_lrm_queue() {
  debug_msg "process_lrm_queue ($@)"

  export TEMP_FILE=$(temp_create "lrm")
  export TEMP2_FILE=$(temp_create "lrm")

  while [ -s "$LRM_QUEUE" ]
  do   
    MODULE=$(remove_queue $LRM_QUEUE)
    verbose_msg "${TEMP}removing \"$MODULE\""

    run_details $MODULE &> /dev/null

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

    # time-out 1: PRE_REMOVE
    run_module_file $MODULE PRE_REMOVE 

    while read TARGET ; do
      if ! [ -e "$TARGET" ] ; then
        continue
      fi

      if grep -q -w "$TARGET\$" $PROTECTED $EXCLUDED ; then
        verbose_msg "\"$TARGET\" is protected or excluded!!"
        continue
      fi

      if [ -d "$TARGET" ] ; then
        echo "$TARGET" >> $TEMP_FILE
        continue
      fi

      handle_config_files $TARGET

      remove_something $TARGET

    done < $INST_LOG

    process_directories $TEMP_FILE $TEMP2_FILE

    # time-out 2: POST_REMOVE
    run_module_file $MODULE POST_REMOVE

    if [ "$KEEPCONFIG" == "on" ] ; then
      verbose_msg "skipping removal of dependency listing and configs"
    else
      verbose_msg "removing module from dependency listing and configs"
      remove_depends  $MODULE
    fi

    # administration duty time:
    verbose_msg "removing module from installed list.. "
    remove_module $MODULE

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

    activity_log  "lrm"  "$MODULE" "$VERSION"  "success"
  done
}


check_status() {
   module_installed $MODULE || {
      message  "${MODULE_COLOR}${MODULE}"  \
      "${PROBLEM_COLOR}is not installed."  \
      "${DEFAULT_COLOR}"
      [ "$EXILE"   == "on" ] || return 1
   } 

   [ "$NOSUSTAIN" == "on" ] && return 0 || {

      verbose_msg "checking if \"$1\" is sustained"
      grep -q -w "$MODULE" "$SUSTAINED" && {
             message  "${MODULE_COLOR}${MODULE}"         \
                      "${PROBLEM_COLOR}is sustained."  \
                      "${DEFAULT_COLOR}"
            return 1 
      } || return 0 
   }
   true
}


downgrade() {
  # 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 || exit 1

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

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

  if [ ! -s $INSTALL_CACHE/$MODULE-$1-$BUILD.tar.bz2 ] ; then 
    echo "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
      echo "The downgrade version is the same as the installed version"
      echo "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..."
  
  bzcat $INSTALL_CACHE/$FILENAME | tar -kt $TAR_P -C / >/dev/null
  verbose_msg "adding module to installed list"

  bzcat $INSTALL_CACHE/$FILENAME | 
  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
}

create_lrm_queue() {

  [ "$#" == "0" ] && help;

   if [ "$TEST" != "on" ]; then 
      root_check || exit 1
   fi

   [ -e "$EXCLUDED" ] || {
      message  "${PROBLEM_COLOR} $EXCLUDED can't be found!!."  \
               "\nTouching it to create, but this is just a "  \
               "workaround!! \nDo a lunar update ASAP\n"       \
               "${DEFAULT_COLOR}"
      touch $EXCLUDED 
    }

   [ -e "$PROTECTED" ] || {
      message  "${PROBLEM_COLOR} $PROTECTED can't be found!!." \
               "\nTouching it to create, but this is just a "  \
               "workaround!! \nDo a lunar update ASAP\n"       \
               "${DEFAULT_COLOR}"
      touch $PROTECTED 
    }

  export LRM_QUEUE=$(temp_create "lrm-queue")
  export LRM_TEMP=$(temp_create "lrm")
                       
   MODULE_LIST="$@"
   for MODULE in $MODULE_LIST
   do
      check_status $MODULE  || continue
      add_queue $LRM_QUEUE $MODULE
   done      
}

. /etc/lunar/config



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

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 ;;
     --) shift; break ;;
      *) help;  break ;;
   esac
  done

  verbose_msg "signals TERM, INT and QUIT are trapped"
  trap "trap_proc" INT QUIT TERM

  create_lrm_queue "${@#-}"
  process_lrm_queue
  exit_proc
fi

