#!/bin/sh
#set -x
#
# patch the configuration files
# takes one argument - the PATCHDIR, typically underinstall/patch/<patchnum>
#
basedir=<msg.RootPath>
UNAME=`/bin/uname`
#
# usage
#
usage()
{
  echo
  echo  "Usage: $0 <patchdir>\n"
  echo
  echo  "  <patchdir>: The patch directory area created during patchaadd."
  echo  "    e.g. $basedir/install/patch/116568-05"
  echo
  exit 1
}

#
# check to make sure config is accessible
#
check_configaccess() {
  if [ ! -w $basedir/config/imta_tailor ]; then
    log_msg "-- Could not access the config area $basedir/config"
    log_msg "-- This utility requires access to the config area"
    exit 2
  fi
}

#
# Special code for files that have moved locations
# - return_header.opt
#   - moved config location: from config/locale/C/ to config template
#
save_movedfiles() {
  log_only "-- save_movedfiles being run"
  if [ ! -f $basedir/config/return_header.opt -a -f $basedir/config/locale/C/return_header.opt ]; then
    log_only "/bin/cp -p $basedir/config/locale/C/return_header.opt $basedir/config/return_header.opt"
    /bin/cp -p $basedir/config/locale/C/return_header.opt $basedir/config/return_header.opt
  fi
}

#
# routine to add a final new line to a file if it does not have one
#
# diff3 will core dump if the file does not end in a newline
# so add a new line if it is missing
#
# - uses the $file variable, and fixes it in-place
#
add_newline() {
  log_only "lines=\`/usr/bin/tail -1 $file | /usr/bin/wc -l\`"
  lines=`/usr/bin/tail -1 $file | /usr/bin/wc -l`
  log_only "lines=$lines"
  if [ $lines -eq 0 ]; then
   log_only "-- Adding extra line to $file"
   /bin/echo "" >> $file
  fi
}

#
# patch config files
# - attempt to patch the user files, but do not actually overwrite
# - These are config files that do not have substitutions in them.
#   so they are "easier" to patch
patch_config() {
  log_only "-- patch_config being run"
  /bin/rm -f $PATCHDIR/newconfig.list
  /bin/touch -f $PATCHDIR/newconfig.list
  #
  set `/bin/cat $PATCHDIR/config.list`
  while [ $# -ne 0 ]
  do
    # the "template" file, a path relative to $basedir
    tfile=$1
    shift
    # the "config" file, a path relative to $basedir
    cfile=$1
    shift
    # need to do different things depending on:
    # - if the file is a .gif, .jpg or .ico file
    # - if the file is a text config file
    case $tfile in
      *.gif|*.jpg|*.ico) patch_binfile;;
      *) patch_configfile;;
    esac
  done
}

#
# patch a single binary config file
#
patch_binfile() {
  log_only "-- Running patch_binfile"
  # if (old $tfile != new $tfile && new $tfile != $cfile) do something
  /usr/bin/cmp -s $BACKOUTDIR/$tfile $basedir/$tfile
  cmp_tfiles=$?
  /usr/bin/cmp -s $basedir/$tfile $basedir/$cfile
  cmp_cfile=$?
  log_only "-- cmp_tfile = $cmp_tfiles cmp_cfile = $cmp_cfile"
  # cmp status is 0 if files are identical
  if [ $cmp_tfiles -ne 0 -a $cmp_cfile -ne 0 ]; then
    # backup the $cfile, do not overwrite an existing backup
    dir=`dirname $SAVEDIR/$cfile`
    if [ ! -d $dir ]; then
      log_only "/bin/mkdir -p $dir"
      /bin/mkdir -p $dir >> $LOGFILE 2>&1
    fi
    if [ ! -f $SAVEDIR/$cfile ]; then
      log_only "/bin/cp -p $basedir/$cfile $SAVEDIR/$cfile"
      /bin/cp -p $basedir/$cfile $SAVEDIR/$cfile >> $LOGFILE 2>&1
    fi
    /bin/cp -p $basedir/$tfile $SAVEDIR/$cfile.new
    NEWCONFIGS=`expr $NEWCONFIGS + 1`
    NEWBINS=`expr $NEWBINS + 1`
    log_msg "-- New: $basedir/$cfile"
    /bin/echo "$cfile" >> $PATCHDIR/newconfig.list
  else
    /bin/rm -f $SAVEDIR/$cfile.new
    log_only "-- No patch required for $basedir/$cfile"
  fi
}

#
# patch a single text config file
# using 3 way diff
#
# diff3 will core dump if the file does not end in a newline
# so add a new line if it is missing. Do not have to do it for 3rd
# file because we will make sure from now on we will not have files like 
# this.
#
patch_configfile() {
  log_only "-- Running patch_configfile"
  # The 3 files for diff3
  file1=$SAVEDIR/$cfile.new
  file2=$BACKOUTDIR/$tfile
  file3=$basedir/$tfile
  # backup the $cfile, do not overwrite an existing backup
  dir=`dirname $SAVEDIR/$cfile`
  if [ ! -d $dir ]; then
    log_only "/bin/mkdir -p $dir"
    /bin/mkdir -p $dir >> $LOGFILE 2>&1
  fi
  # create file1: $SAVEDIR/$cfile.new
  if [ -f $basedir/$cfile ]; then
    if [ ! -f $SAVEDIR/$cfile ]; then
      log_only "/bin/cp -p $basedir/$cfile $SAVEDIR/$cfile"
      /bin/cp -p $basedir/$cfile $SAVEDIR/$cfile >> $LOGFILE 2>&1
    fi
    log_only "/bin/cp -p $basedir/$cfile $SAVEDIR/$cfile.new"
    /bin/cp -p $basedir/$cfile $SAVEDIR/$cfile.new >> $LOGFILE 2>&1
    file=$file1
    add_newline
  else
    /bin/rm -f $SAVEDIR/$cfile.new >> $LOGFILE 2>&1
    /bin/touch $SAVEDIR/$cfile.new >> $LOGFILE 2>&1
  fi
  # file2
  #   if this is a new file
  if [ ! -f $file2 ]; then
    /bin/rm -f $PATCHDIR/empty_file
    /bin/touch $PATCHDIR/empty_file
    file2=$PATCHDIR/empty_file
  else
    file=$file2
    add_newline
  fi
  #
  log_only "/usr/bin/diff3 -E $file1 $file2 $file3 > $SAVEDIR/$cfile.script"
  /usr/bin/diff3 -E $file1 $file2 $file3 > $SAVEDIR/$cfile.script 2>> $LOGFILE
  stat=$?
  log_only "stat=$stat"

  # set diff3flag - nonzero mean diff3 failure. diff3 return status is
  # different on different platforms
  diff3flag=0;
  if [ $UNAME = "SunOS" ]; then
    # nonzero means failure
    diff3flag=$stat;
  elif [ $UNAME = "Linux" ]; then
    # failure only when return status is 2
    if [ $stat -eq 2 ]; then
      diff3flag=2;
    fi
  else
    diff3flag=$stat;
  fi

  if [ $diff3flag -ne 0 ]; then
    log_msg "--"
    log_msg "-- diff3 failed with status=$stat for"
    log_msg "--   $basedir/$cfile"
    log_msg "-- Please merge changes by hand from the new file"
    log_msg "--   $basedir/$tfile"
  else
    # "echo wq" on Solaris is redundant, but is required on Linux
    log_only "(/bin/cat $SAVEDIR/$cfile.script; /bin/echo 'wq') | /bin/ed -s $SAVEDIR/$cfile.new"
    (/bin/cat $SAVEDIR/$cfile.script; /bin/echo 'wq') | /bin/ed -s $SAVEDIR/$cfile.new >> $LOGFILE 2>&1
    log_only "/usr/bin/cmp -s $basedir/$cfile $SAVEDIR/$cfile.new"
    /usr/bin/cmp -s $basedir/$cfile $SAVEDIR/$cfile.new >> $LOGFILE 2>&1
    stat=$?
    if [ $stat -ne 0 ]; then
      log_only "/bin/grep -s '^=======$' $SAVEDIR/$cfile.script"
      /bin/grep -s '^=======$' $SAVEDIR/$cfile.script >> $LOGFILE 2>&1
      stat=$?
      NEWCONFIGS=`expr $NEWCONFIGS + 1`
      if [ $stat -eq 0 ]; then
        log_msg "-- New with Conflicts: $basedir/$cfile"
        CONFLICTS=`expr $CONFLICTS + 1`
      else
        log_msg "-- New: $basedir/$cfile"
      fi
      /bin/echo "$cfile" >> $PATCHDIR/newconfig.list
    else
      /bin/rm -f $SAVEDIR/$cfile.new
      log_only "-- No patch required for $basedir/$cfile"
      /bin/rm -f $SAVEDIR/$cfile.script
    fi
  fi
}

#
# main program
#
# NEWCONFIG - number of new files
# CONFLICTS - number of new files that have conflicts
# NEWBINS   - number of new files that are binary files
NEWCONFIGS=0
NEWBINS=0
CONFLICTS=0
# utility routines
. ${basedir}/lib/util.sh

# get args
# whether to install the new config files or not
while getopts h c
do
    case $c in
    h)
        usage;;
    \?)
        usage;;
    esac
done
shift `expr $OPTIND - 1 `

if [ $# -ne 1 ]; then
  usage
fi
PATCHDIR=$*
#
# must be root
#
set `/usr/bin/id`
if [ $1 != "uid=0(root)" ]; then
  echo
  echo "Utility to generate new config files for the Messaging server\n"
  echo "To use this utility you need to be the system's root user. \n"
  echo 
  exit 1
fi
# initialize logging
LOGFILE=$PATCHDIR/patch-config_`date +%Y%m%d%H%M%S`.log
log_init

if [ ! -d $PATCHDIR/save ]; then
  echo "Invalid PATCHDIR, $PATCHDIR/save is not a directory"
  usage
fi
SAVEDIR=$PATCHDIR/save
if [ ! -d $PATCHDIR/backout ]; then
  echo "Invalid PATCHDIR, $PATCHDIR/backout is not a directory"
  usage
fi
BACKOUTDIR=$PATCHDIR/backout

# check to make sure config is accessible
check_configaccess
save_movedfiles
patch_config

log_msg "--"
log_msg "-- Number of new config files: $NEWCONFIGS"
log_msg "-- Number of config files with conflicts: $CONFLICTS"
log_msg "-- Number of config files that are images (gif or jpg): $NEWBINS"
log_msg "-- The list of new config files are in $PATCHDIR/newconfig.list"
log_msg "--"
log_msg "-- Please review the changes in the new config files before installing them."
log_msg "-- Note that you may have to run imsimta cnbuild and imsimta chbuild."
log_msg "-- You also need to apply the ldif files under $basedir/lib/patch."
