#---------------------------------------------------------------------
##
## @Synopsis Functions for automatic init-script installation.
##
## Installation steps performed by this script:
## <pre>
## pre install:
##    <li>Determine if the script is a facility provider, if it is then
##    ask the user whether it should be the default provider.
##
## install:
##  <ul>
##   <li>Determine which runlevel the script should be placed in.
##   <li>Make a backup if there already is a different version of the script in
##    the target location.
##   <li>Install the script with permissions 754.
##   <li>Determine if the script sources any config file from /etc/sysconfig.
##   <li>For each config file:
##    <ul>
##      <li>Install the config file if there is no existing copy installed.
##      </li>Otherwise merge new options into existing copy.
##   </ul></ul>
##
## post install:
##
##  <li> When the spell has been installed successfully then change the
##    /etc/sysconfig/facilities-file if the user wanted the script to be a
##    default provider.
## </pre>
## @Copyright Copyright (C) 2003 The Source Mage Team <http://www.sourcemage.org>
##
##
## @Contributors Robert Helgesson <rycee@home.se>
##
#---------------------------------------------------------------------


#---------------------------------------------------------------------
## @param new file
## @param old file
## Makes a backup of "old file" if it differs from "new file"
##
#---------------------------------------------------------------------
function _init_make_backup()
{

  # Don't bother if the old file doesn't exist
  [ -f $2 ] || return

  # Do the files differ? Return if they don't.
  cmp -s $2 $1 && return

  local savetime=$( date +'%Y%m%d%H%M' )
  bck_file=$2.$savetime.backup

  message "Making a backup of $2 due to differing content..."
  mv $2 $bck_file
  chmod 644 $bck_file

}


#---------------------------------------------------------------------
## @param init script
## @Stdout filelist
## Extracts the files in /etc/sysconfig which are sourced by the script and
## prints them to stdout separated by newlines.
##
#---------------------------------------------------------------------
function _init_get_conf_files()
{

  sed -n -f - $1 <<EOF
s!^\.\s\s*/etc/sysconfig/\([^[:space:]]*\).*!\1!p
s!^source\s\s*/etc/sysconfig/\([^[:space:]]*\).*!\1!p
EOF

}


#---------------------------------------------------------------------
## @param new config file
## @param old config file
## Inserts new options from the new file into the old, existing, file
##
#---------------------------------------------------------------------
function _init_merge_config_file()
{

  # Get newly added options
  local new_opts=$( sed -n -e 's/[[:space:]]*\([[:alnum:]_]*\)=.*/\1/p' $1 $2 |
                          sort | uniq -u )

  # for now the file is always modified...
  if [ -z "$new_opts" ] ; then
    message "  No new options to merge into $2..."
    track_manual $2 # but we still need to track it.
    return 0
  fi

  local savetime=$( date +'%Y%m%d%H%M' )
  cp $2 $2.$savetime.backup

  for opt in $new_opts ; do
    message "  Merging option $opt into $2..."
    sed -n -f - $1 <<EOF >> $2
# If we encounter an empty line then clear hold space since another
# variable is coming up...
/^$/ { x ; d ; h ; }

# The variable we're looking for has come, add it to the hold space and
# then print everything, quit when done...
/^[[:space:]]*$opt=/ { H ; x ; p; q; }

# Default action, append line to hold space
H
EOF
  done

}


#---------------------------------------------------------------------
## @param configuration file...
##
## Installs or merges a list of init-script configuration-files.
##
#---------------------------------------------------------------------
function _init_install_conf_files()
{

  mkdir -p $INSTALL_ROOT/etc/sysconfig
  for file in "$@" ; do
    local target_file=${INSTALL_ROOT}/etc/sysconfig/$file
    local file=$SCRIPT_DIRECTORY/init.d/$file.conf

    if [ ! -f "$file" ] ; then
      [ ! -f "$target_file" ] && 
        message "${PROBLEM_COLOR}Unable to find file $file...${DEFAULT_COLOR}"
      continue
    fi

    if [ -f "$target_file" ] ; then
      check_if_modified "$target_file" && mark_file_modified "$target_file"
      _init_merge_config_file $file $target_file
    else
      install -m 644 $file $target_file
      touch $target_file
    fi
  done

}


#---------------------------------------------------------------------
## @param init script
## @param previous cast instance's answers, if any
## @param init script
## Prepares installation of an init-script.
## Creates the variable $INITPROVIDES which contains facility provided by the
##   script (if any)
##
#---------------------------------------------------------------------
function init_prepare_install()
{

  local service="$1"
  local old_provides="$2"
  local result_list="$3"
  local script_path="$SCRIPT_DIRECTORY/init.d/$service"
  local script_provides=$( grep '^[:space:]*PROVIDES' $script_path )
  script_provides=$( eval "( ${script_provides:=:} ; echo \$PROVIDES ; )" )

  [ -z "$script_provides" ] && return

  local default=n
  if test -f $INSTALL_ROOT/etc/sysconfig/facilities &&
     grep -q "$script_provides=$service" \
              $INSTALL_ROOT/etc/sysconfig/facilities ||
     list_find "$service:$script_provides" $old_provides; then
    default=y
  fi
  local question="Set $service to be the default provider of $script_provides?"
  if query "$question" $default; then
    list_add "$result_list" "$service:$script_provides"
  fi
}


#---------------------------------------------------------------------
## @param init script
## * Makes a backup of an existing script.
## * Installs the new script into the correct runlevel.
## * Installs any config file used by the script.
##
#---------------------------------------------------------------------
function init_install()
{

  local enable_script="$1"
  local script_name="$2"
  local script_path="$SCRIPT_DIRECTORY/init.d/$script_name"
  local script_runlevel=$( grep '^[:space:]*RUNLEVEL' $script_path )
  script_runlevel=$( eval "( $script_runlevel ; echo \$RUNLEVEL )" )

  [ "$script_runlevel" = "s" ] && script_runlevel="S"

  if [ -z "$script_runlevel" ] ; then
    message "Init script $script_name doesn't contain good RUNLEVEL variable..."
    return
  fi

  message "Installing $script_name to runlevel $script_runlevel..."

  (
    . ${INSTALL_ROOT}/etc/sysconfig/init

    # /etc/sysconfig/init might not exist yet so we define this in case
    RUNLEVELS_DIR="${RUNLEVELS_DIR:-$INSTALL_ROOT/etc/init.d/runlevels}"
    
    local runlevel_dir="$RUNLEVELS_DIR/%$script_runlevel"

    if [ ! -d "$runlevel_dir" ] ; then
      message -n "${PROBLEM_COLOR}"
      message -n "Unable to install $script_name to runlevel $script_runlevel. "
      message "Runlevel do not exist or is not implemented as a directory."
      message -n ${DEFAULT_COLOR}
      exit 1
    else
      _init_make_backup $script_path $runlevel_dir/$script_name
      if [ "$enable_script" == "enabled" ] ; then
        install -m 754 $script_path $runlevel_dir
        message "  script $script_name installed and ${MESSAGE_COLOR}enabled${DEFAULT_COLOR}. Disable with 'telinit disable $script_name'."
        message "${MESSAGE_COLOR}If you want to [re]start the service now${DEFAULT_COLOR}, issue 'telinit run $script_name [re]start'."
      else
        install -m 644 $script_path $runlevel_dir
        message "  script $script_name installed and ${MESSAGE_COLOR}disabled${DEFAULT_COLOR}. Enable with 'telinit enable $script_name'."
      fi
      _init_install_conf_files $( _init_get_conf_files $script_path )
    fi
  )

}


#---------------------------------------------------------------------
##
## Does cleanup if necessary. Must be run _after_ installwatch has stopped.
##
#---------------------------------------------------------------------
function init_post_install()
{
  (
    IFS="$WHITESPACE_IFS"
    for sp in $INIT_PROVIDES ; do
      mkdir -p $INSTALL_ROOT/etc/sysconfig
      mark_file_modified "$INSTALL_ROOT/etc/sysconfig/facilities"
      IFS=":"
      set $sp   # $1 - script name, $2 - facility
      if ! sedit "s/^\([:space:]*$2\)=.*/\1=$1/" \
            $INSTALL_ROOT/etc/sysconfig/facilities ; then
        message -n "${PROBLEM_COLOR}Unable to modify facilities file to make "
        message "$1 provider of $2.${DEFAULT_COLOR}"
      else
        message "Made $1 provider of $2"
      fi
    done
  )
}

#---------------------------------------------------------------------
##
## This software is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation; either version 2 of the License, or
## (at your option) any later version.
##
## This software is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this software; if not, write to the Free Software
## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
##
#---------------------------------------------------------------------
