#!/usr/bin/perl
# -*- Mode: CPerl -*-
#
# uninstall the configuration files installed by install-newconfig
# takes one argument - the PATCHDIR, typically under install/patch/<patchnum>

use Getopt::Long;               # for GetOptions
use File::Compare;              # for compare
use File::Basename;             # for dirname
use File::Path;                 # for mkpath
use File::Copy;                 # for move, copy

#
# usage
#
sub usage
{
print <<EOF;

Usage: $0 [--domain <domain>|ALL] [--force] <patchdir>

  --domain <domain>|ALL
    The hosted domain to operate on, or ALL for all hosted domains
    You can also use the short form of the switch -d instead of --domain

  --force
    Do not prompt for confirmation when overwriting live config files.
    You can also use the short form of the switch -f instead of --force

  <patchdir>: The patch directory area created during patchadd.
    e.g. $basedir/install/patch/118207-41

EOF
  die "  Exiting";
}

########################################
# given file list, uninstall the files
# - uses global variables
#   $SAVEDIR $basedir $CONFIGBACKOUTDIR
########################################
sub uninstall_filelist
{
  my($filelist) = @_;
  my ($copies, $cfile, $file, @tmp, $f, $stat, $ans, $dir);

  $copies = 0;
  open (CONFIG, "$filelist") or die ("Cannot open $filelist for reading -");
  while (<CONFIG>) {
    chomp;
    $cfile = $_;
    $file = "$SAVEDIR/$cfile";
    if ( ! -f "$file" ) {
      log_msg("-- $file does not exist, skipping it\n");
      next;
    }
    # special code for msg.conf, take the youngest msg.conf.<timestamp> if any
    if ( $cfile eq "config/msg.conf" ) {
      @tmp = glob("$SAVEDIR/config/msg.conf.[0-9]*");
      if (@tmp != null) {
        foreach $f (@tmp) {
          $file=$f;
        }
        chomp($file);
      }
    }

    # check if it is identical first
    $stat = compare( "$file", "$basedir/$cfile");
    # cmp status is 0 if files are identical
    if ( $stat != 0 ) {
      # save existing config file
      if ( -f "$basedir/$cfile" ) {
        $dir = dirname("$CONFIGBACKOUTDIR/$cfile");
	if ( ! -d "$dir" ) {
          log_only("mkpath $dir 0 0755\n");
          mkpath("$dir",0,0755);
        }
        log_only("copy $basedir/$cfile $CONFIGBACKOUTDIR/$cfile\n");
        copy("$basedir/$cfile", "$CONFIGBACKOUTDIR/$cfile");
      }
      # restore the old config file
      $dir = dirname("$basedir/$cfile");
      if ( ! -d "$dir" ) {
        log_only("mkpath $dir 0 0755\n");
        mkpath("$dir",0,0755);
      }

      if ( defined $opt_f ) {
        $ans = "y";
      } else {
        $ans = YesOrNo("Overwrite $basedir/$cfile ?", "no");
      }
      if ($ans eq "y" ) {
        log_msg("copy $file $basedir/$cfile\n");
        copy( "$file", "$basedir/$cfile" );
        $copies = $copies + 1;
      }
    } else {
      log_only("-- $file and $basedir/$cfile are identical, skipping it\n");
    }
  }
  close (CONFIG);
  return($copies);
}

########################################
# uninstall newconfig files
# - Restore files that were saved off the patch-config
#   i.e. files listed in newconfig.list
#   Note that although patch-config may have saved them off, it does not
#   necessarily mean that new versions were ever installed. It also does
#   not mean that all the config files at patch-config time are restored,
#   only those that patch-config generated new versions for.
########################################
sub uninstall_newconfig
{
  my ($NUMCOPIES,$copies);
  # uninstall the file
  $NUMCOPIES = 0;

  # default domain
  if ( ! defined $opt_d ) {
    log_msg("-- Checking default domain\n");
    $copies = uninstall_filelist("$PATCHDIR/newconfig.list");
    $NUMCOPIES = $NUMCOPIES + $copies;
  }
  # hosted domains 
  foreach $domain (@domains) {
    log_msg("-- Checking hosted domain $domain\n");
    $copies = uninstall_filelist("$PATCHDIR/${domain}_newconfig.list");
    $NUMCOPIES = $NUMCOPIES + $copies;
  }

  log_msg("-- Number of different files: $NUMCOPIES\n");
  log_msg("-- Original files are backed up under $CONFIGBACKOUTDIR\n");
}

########################################
# determine the full path to this script's location
# set the variable scriptDir
#
# make $currDir and $scriptDir globally available
########################################
sub get_my_dir {
  $currDir=`pwd`;
  chomp $currDir;
  $scriptDir = dirname("$0");
  chdir $scriptDir;
  $scriptDir =`pwd`;
  chomp $scriptDir;
  chdir $currDir;
}

########################################
# main program
########################################
$ENV{"PATH"} = "/bin:/usr/bin:/usr/sbin:/sbin:/usr/etc:" . $ENV{"PATH"};

get_my_dir();
# assume that this script is located in $basedir/sbin/
# so set basedir accordingly
$basedir = dirname ("$scriptDir");


# Start environment variable settings
#
# LD_LIBRARY_PATH used for Solaris 2.5+, SCO Unix, IRIX, Linux
$ENV{"LD_LIBRARY_PATH"} = "${basedir}/lib:" . $ENV{"LD_LIBRARY_PATH"};

# prepend to search path
unshift (@INC, "$basedir/lib");
require "util.pl";

# get args
# whether to install the new config files or not
if (! GetOptions("help" => \$help,
                 "force" => \$opt_f,
                 "domain=s" => \$opt_d) ) {
  print "ERROR parsing options: \n";
  usage;
}

if ( $help ) {
  print "Here is your Help: \n";
  usage;
}

if ( @ARGV != 1 ) {
  print "ERROR: Missing patch directory argument\n";
  usage;
}
$PATCHDIR = "$ARGV[0]";

#
# must be root
#
if ($< != 0) {
  print "Utility to uninstall the new config files installed by install-newconfig\n";
  print "To use this utility you need to be the system's root user. \n\n";
  exit(1);
}
# process -d switch
# @domains will be the list of hosted domains to operate on
@domains = get_hosted_domains();
if ( ! defined $opt_d ) {
  # default is to operate on all hosted domains, already set to do so
} elsif ( $opt_d eq "ALL") {
  # do nothing, already set to all domains
} else {
  # set to a specific domain
  # make sure it is a valid domain
  $exists = grep /^$opt_d$/, @domains;
  if ( $exists != 0 ) {
    @domains = ($opt_d);
  } else {
    print "ERROR: Invalid domain $opt_d\n";
    print "The list of valid domains are: @domains\n";
    die "  ";
  }
}

# initialize logging
$LOGFILE = getLogfile($PATCHDIR, '/', "uninstall-newconfig");
log_init($LOGFILE);
log_only("basedir = $basedir\n");

# save directory created by patchadd and patch-config
if ( ! -d "$PATCHDIR/save" ) {
  log_msg("Invalid PATCHDIR, $PATCHDIR/save is not a directory\n");
  usage;
}
$SAVEDIR = "$PATCHDIR/save";

# file containing list of new config files
if ( defined $opt_d ) {
  foreach $domain (@domains) {
    if ( ! -f "$PATCHDIR/${domain}_newconfig.list" ) {
      log_msg("$PATCHDIR/${domain}_newconfig.list not found, Please run patch-config first\n");
      usage;
    }
  }
} else {
  if ( ! -f "$PATCHDIR/newconfig.list" ) {
    log_msg("$PATCHDIR/newconfig.list not found, Please run patch-config first\n");
    usage;
  }
}

# where original config files will be backed up
$datestr = genTimestamp();
$CONFIGBACKOUTDIR = "${PATCHDIR}/config_${datestr}";
mkpath($CONFIGBACKOUTDIR, 0, 0755);

# check to make sure config is accessible
check_configaccess();
isHAconfigured();
if ( $isHAconfigured == 1 ) {
  log_msg("Warning an HA configuration is detected on your systems,\n");
  ContinueYesNo();
}

stop_servers();
uninstall_newconfig();
perform_checks();
log_msg("-- Note that ldif file\n");
log_msg("--   $basedir/lib/patch/ugdir_diff.ldif\n");
log_msg("-- that you may have applied to the user/group\n");
log_msg("-- Directory may also have to be undone.\n");
log_msg("-- There is no tool to do this currently.\n");
log_msg("-- Nor are there any backups of the previous ldap entries.\n");
