#!/usr/local/bin/perl
# 
# $Header: install/tools/deinstall/deinstall.pl /st_install_11.2.0/14 2011/06/09 18:24:27 huliliu Exp $
#
# deinstall.pl
# 
# Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      deinstall.pl - <one-line expansion of the name>
#
#    DESCRIPTION
#      <short description of component this file declares/defines>
#
#    NOTES
#      <other useful comments, qualifications, etc.>
#
#    MODIFIED   (MM/DD/YY)
#    huliliu     06/09/11 - XbranchMerge huliliu_cleanupobase from main
#    huliliu     06/02/11 - add -cleanupOBase option
#    huliliu     05/25/11 - XbranchMerge huliliu_bug-12552180 from main
#    huliliu     05/23/11 - special handle for -help options bug 12552180
#    vkoganol    05/10/11 - XbranchMerge vkoganol_bug-12433438 from main
#    vkoganol    05/08/11 - Correcting script name in error message
#    huliliu     05/03/11 - XbranchMerge huliliu_bug-12415406 from main
#    huliliu     05/01/11 - only remove OH and OB from env for Windows, not for
#                           all the platforms -bug 12415406
#    huliliu     04/27/11 - XbranchMerge huliliu_bug-12387663 from main
#    huliliu     04/27/11 - for windows system, do not do setLdLibraryPath()
#                           -bug 12387663
#    vkoganol    04/18/11 - XbranchMerge
#                           vkoganol_correct_ld_lib_path_for_linux64_in_deinstall_pl
#                           from st_install_11.2.0
#    bkghosh     04/08/11 - In 12g ldapjclnt11.jar has got renamed to
#                           ldapjclnt12.jar. Renaming ldapjclnt11.jar to
#                           ldapjclnt12.jar for the classpath
#    bkghosh     03/28/11 - Fix for bug#11876355 : Changing lib oui lib path   for hpunix and hp-pa 
#    bkghosh     03/09/11 - XbranchMerge bkghosh_bug-11811102 from main
#    bkghosh     03/08/11 - Fix for bug#11811102..Updating the classpath
#    vkoganol    03/02/11 - setting LD_LIBRARY_PATH to oui/lib/linux64 for
#                           linux64 inline with OUI changes
#    bkghosh     02/21/11 - XbranchMerge bkghosh_bug-9509840_2_main from main
#    bkghosh     02/13/11 - Adding orai18n-mapping to classpath
#    bkghosh     01/26/11 - XbranchMerge bkghosh_bug-11687496 from
#                           st_install_11.2.0
#    bkghosh     01/26/11 - Fix for bug-11687496
#    bkghosh     01/17/11 - Fix for bug#9871334
#    bkghosh     01/17/11 - Fix for bug # 10089962
#    vkoganol    12/10/10 - Adding support for command line opion to provide log
#                           directory
#    ssampath    07/14/10 - Fix for lrg 4771029
#    ssampath    06/04/10 - Fix for bug 9470771.
#    prsubram    12/09/09 - XbranchMerge prsubram_bug-9106829 from main
#    ssampath    03/01/10 - XbranchMerge ssampath_bug-9257960 from
#                           st_install_11.2.0.1.0
#    ssampath    01/18/10 - Decouple bootstrapping logic to bootstrap.pl
#    mwidjaja    01/14/10 - XbranchMerge mwidjaja_bug-9269768 from
#                           st_install_11.2.0.1.0
#    mwidjaja    01/14/10 - Fix help message for params
#    ssampath    01/11/10 - XbranchMerge ssampath_bug-9265533 from
#                           st_install_11.2.0.1.0
#    ssampath    01/10/10 - Add -DBOOTSTRAP_DIR to java command
#    prsubram    01/08/10 - Removing the hardcoded string in the usage() method
#    prsubram    01/07/10 - Correcting the help msg for windows
#    prsubram    12/08/09 - Removing setting of OH as an env var
#    prsubram    10/19/09 - XbranchMerge prsubram_bug-9002203 from
#                           st_install_11.2.0.1.0
#    prsubram    10/15/09 - Adding OCM deconfig jar to classpath
#    ssampath    08/24/09 - XbranchMerge ssampath_cleanup_deinstall_scripts
#                           from main
#    ssampath    08/20/09 - Comment debug statements
#    dchriste    03/12/09 - New deinstall perl script to generically replace 
#                           both deinstall script and deinstall.bat 
#    dchriste    03/12/09 - Creation 
# 
use Cwd;
use File::Basename;
use File::Path;
use File::Copy;
use File::Find;
use Getopt::Long;

$isWindows = ($^O =~ /.*MSWin.*/) ? 1 : 0;
$notRecommendedMessage = "It is not recommended to run the script directly.  Execute deinstall or deinstall.bat which executes this script with the right set of arguments\n";

$helpflag = shift;
$homeVersion = shift;

if($helpflag)
{
usage(0);
}

if($homeVersion eq "")
{
   print "Deinstall tool version is one of the required arguments for this perl script. $notRecommendedMessage";
   exit 1;
}

$tmp = shift;
if($tmp eq "")
{
   print "Temporary directory is one of the required arguments for this perl script. $notRecommendedMessage";
   exit 1;
}

$bootstrapDir = shift;
if($bootstrapDir eq "")
{
   print "The deinstall tool standalone or bootstrapped directory is one of the required arguments for this perl script. $notRecommendedMessage";
   print "$notRecommendedMessage";
   exit 1;
}

if(!$isWindows) {
   $archFlag = shift;
   if($archFlag ne "-d64")
   {
      $archFlag = "";
   }
}

if($homeVersion) {
   $ORACLE_HOME = shift @ARGV;
   if($ORACLE_HOME eq "")
   {
      print "The Oracle home directory is one of the required arguments for this perl script. $notRecommendedMessage";
      exit 1;
   }
}

$CHMOD = exists($ENV{CHMOD}) ? $ENV{CHMOD} : '/bin/chmod';
$ID = exists($ENV{ID}) ? $ENV{ID} : '/usr/bin/id';
$LSL = exists($ENV{LSL}) ? $ENV{LSL} : '/bin/ls -l';
if ($isWindows)  {
 	$dirSep = '\\';
 	$pathSep = ';';
	$ENV{PATH}=$bootstrapDir.$dirSep.'bin;'.'C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem';
} else {
 	$dirSep = '/';
 	$pathSep = ':';
}
# Check if this script is run as root on Linux.  If so, then error out.
# This is fix for bug 5024086.
if (! $isWindows) {
	my $id = `$ID`;
	$id =~ /.*?\((\w+)\).*/;
	$user = $1;
	#print "\n\$user = $user\n";
	if ($user eq 'root') {
		print "\nERROR: You must not be logged in as root to run the deinstall tool.\n";
		print "       Log in as Oracle user and rerun the deinstall tool.\n";
		exit 1;
	}
}

$cmdLineArgs = parseArgs();

#foreach $key (keys %$cmdLineArgs) {
	#print " $key";
	#if (defined $cmdLineArgs->{$key}) {
		#print " ", $cmdLineArgs->{$key};
	#}
#}

#Different error conditions

$EMPTY_JRE_LOC = 1; 
$INCORRECT_JRE_LOC = 2;
$INCORRECT_JRE_VER = 3;
$MISSING_JRE_ARG = 4;
$ROOT_USER = 5;
$MISSING_OH_LOC = 6;
$OH_LOC_EMPTY = 7;
$NOT_VALID_DIR_OH = 8;
$toolArgs = '';

# Default -help option to false
$userHelp = 0; # DJC appears not to be used

if ($homeVersion) {
	if (exists($cmdLineArgs->{home})) {
		print "\nERROR: -home must not be set for a deinstall running from within an ORACLE_HOME.\n";
		print "       Deinstall of the current home is assumed.\n";
		exit 1;
	} else {
		$cmdLineArgs->{home} = $ORACLE_HOME;
	}

	if (exists($cmdLineArgs->{help})) 
	{
	   usage(0);
        }
	$jreHome = $bootstrapDir.$dirSep."jdk".$dirSep."jre";
} else {
	if (! exists($cmdLineArgs->{home})) {
		print "\nTool is being run outside the Oracle Home, -home needs to be set.\n";
		usage($MISSING_OH_LOC);
	}
	$jreHome = $bootstrapDir.$dirSep.'jre';
	processArgs();
}

$perlHome = $bootstrapDir.$dirSep.'perl';

# Remove -tmpdir before setting up toolArgs which gets passed onto Java code
delete($cmdLineArgs->{tmpdir});

foreach $key (keys %$cmdLineArgs) {
    $toolArgs .= '-'. $key . ' ';
    if ($cmdLineArgs->{$key}) {
        $toolArgs .= $cmdLineArgs->{$key} . ' ';
    }
} 

#print "\n\$toolArgs = $toolArgs\n";
#print "\n\$bootstrapDir = $bootstrapDir\n";
$ouiDir = $bootstrapDir.$dirSep."oui".$dirSep."jlib";
$jlibDir = $bootstrapDir.$dirSep."jlib";
$libDir = $bootstrapDir.$dirSep."lib".$dirSep."linux";
$binDir = $bootstrapDir.$dirSep."bin";
$templateDir = $bootstrapDir.$dirSep."templates";
$deinstallDir = $bootstrapDir;
$deinstallJlib = $deinstallDir.$dirSep."jlib";

if ($isWindows) {
	unsetEnv();
}

# Check that user running this script is owner of Oracle Home.
$homeInventory = $ORACLE_HOME.$dirSep.'inventory';
if (! $isWindows) {
        my $id = `$ID`;
        $id =~ /.*?\((\w+)\).*/;
        $user = $1;
	#print "\n\$user = $user\n";
	if (-d $ORACLE_HOME) {
		if (-d $homeInventory) {
			my @lsCmdOutput = `$LSL $ORACLE_HOME`;
			my $inventoryOwner;
			foreach $lineOut (@lsCmdOutput) {
				chomp($lineOut);
				$lineOut =~ s/^\s+//;
				$lineOut =~ s/\s+$//;
				if ($lineOut =~ /.+?\s+[0-9]+\s+(.+?)\s+.*inventory/) {
					$inventoryOwner = $1;
					#print "owner = $inventoryOwner\n";
				}
			}
			if ($user ne $inventoryOwner) {
				print "You must be the owner of this Oracle Home to deinstall/deconfigure it.\n";
				exit 1;
			}
		} else {
			print "The home inventory does not exist on this Oracle Home: $ORACLE_HOME\n";
			print "Please create '$homeInventory' as original user and rerun this script.\n";
			exit 1;
		}
	} else {
		print "The Oracle Home '$ORACLE_HOME' does not exist.\n";
		print "Please re-create the Oracle Home as original user and rerun this script.\n";
		exit 1;
	}
}
$perlBin = $perlHome.$dirSep.'bin';
$perlLib = $perlHome.$dirSep.'lib';
#$ENV{ORACLE_HOME} = $ORACLE_HOME;
#print "\nORACLE_HOME environment variable set to $ORACLE_HOME\n";
$oracleBin = $ORACLE_HOME.$dirSep.'bin'.$dirSep.'oracle';
if (-f $oracleBin) {
	$noOracleBin = 'false';
} else {
	$noOracleBin = 'true';
}
#print "\n\$noOracleBin = $noOracleBin\n";

setClassPath();
if (! $isWindows){
   setLdLibraryPath();
}
# set SRVM tracing
$trace = exists($ENV{SRVM_TRACE}) ? '-DTRACING.ENABLED=true -DTRACING.LEVEL=2' : '';
$logdir='';
if (exists($cmdLineArgs->{'logdir'})) {
  if ($cmdLineArgs->{'logdir'}) {
    $logdir = $cmdLineArgs->{'logdir'};
  } 
}

# run the tool
#$toolCmd = $jreHome.$dirSep.'bin'.$dirSep.'java -DNOHOME='.$noOracleBin.' -Dpid='.$$.' -Doracle.installer.jre_loc='.$jreHome.' -DHOME_OPT='.$homeOpt.' -Doracle.installer.oui_loc='.$bootstrapDir.$dirSep.'oui '.$trace.' -classpath '.$classPath.' oracle.install.db.deinstall.wrapper.clusterDeconfig '.$toolArgs;
$toolCmd = $jreHome.$dirSep.'bin'.$dirSep.'java '.$archFlag.' -DNOHOME='.$noOracleBin.' -Dpid='.$$.' -Doracle.installer.jre_loc='.$jreHome.' -DLOGDIR='.$logdir.' -Djava.io.tmpdir='.$tmp.' -DBOOTSTRAP_DIR='.$bootstrapDir.' -DUSER='.$user.' -DHOME_OPT='.(($homeVersion) ? 0 : 1).' -Doracle.installer.oui_loc='.$bootstrapDir.$dirSep.'oui '.$trace.' -classpath '.$classPath.' oracle.install.db.deinstall.wrapper.clusterDeconfig '.$toolArgs;
#print "\n\$toolCmd = $toolCmd\n";

chdir($tmp);
system($toolCmd);

exit 0;

############################################################################################## End of main logic - Beginning subroutine section ##############################

sub usage {
	my $exitStatus = shift;
	if($exitStatus !~ /^-?\d/) {
	   $exitStatus = 0;
	}
	my $ext = sh;
	if ($isWindows)  {
	$ext = "bat";
        } 
	($cmdName, $dirs, $suffix)  = fileparse($0, qr/\.[^.]*/);
	if ($homeVersion) {
		print "\n$cmdName\n";
	} else {
		print "\n$cmdName -home <Complete path of Oracle home>\n";
	}
	print "               [ -silent ]\n";
	print "               [ -checkonly ]\n";
        print "               [ -cleanupOBase ]\n";
	print "               [ -local ]\n";
	print "               [ -paramfile <complete path of input parameter properties file> ]\n";
	print "               [ -params <name1=value[ name2=value name3=value ...]> ]\n";
	print "               [ -o <complete path of directory for saving files> ]\n";
	print "               [ -tmpdir <complete path of temporary directory to use> ]\n";
        print "               [ -logdir <complete path of log directory to use> ]\n";
	print "               [ -help : Type -help to get more information on each of the above options. ]\n";
	exit $exitStatus;
}

sub parseArgs() {
   my %toolOptions;
   my $param = "";
   GetOptions( \%toolOptions,
                'home=s',
                'silent',
                'checkonly',
                'cleanupOBase',
                'local',
                'giclean',
                'paramfile=s',
                'params=s{1,}' => \@paramsArr,
                'o=s',
                'tmpdir=s',
		'logdir=s',
                'help' => \&usage) || exit(1);

   if ( @paramsArr > 0 )
   {
      $toolOptions{params} = join(" ",@paramsArr);
   }

   return \%toolOptions;
}

sub processArgs() {
	if (exists($cmdLineArgs->{help})) {
	   usage(0);
	}

	#Validation for logdir path provided through command line
        if(exists($cmdLineArgs->{'logdir'})){
	  $logdir=$cmdLineArgs->{'logdir'};
          unless($logdir)
          {
	    print "\nInvalid log directory path\n";
	    exit 1;
	  }
	  if(!-e $logdir)
	  {
	    mkdir $logdir  or die "\nCan't create directory : ".$logdir."\n";
	  }
	  else
	  {
	    if(!-d $logdir)
	    {
	      print "\nPath provided for log directory is not a directory\n";
              exit 1; 
	    }
	    else
	    {
	      if(!-w $logdir)
	      {
	        print "\nLog directory is not writable\n";
		exit 1;
	      }
	    }
	  }
	}

	if (exists($cmdLineArgs->{home})) {
		if ($cmdLineArgs->{home}) {
			$ORACLE_HOME = $cmdLineArgs->{home};
		} else {
			print "\nSpecify the complete path of the Oracle home you want to remove.\n";
			usage($MISSING_OH_LOC);
		}
	}
	unless (-d $ORACLE_HOME) {
		if (-f $ORACLE_HOME || -l $ORACLE_HOME) {
			print "\nThe path specified for Oracle_Home $ORACLE_HOME is not a valid directory. Make sure to specify a valid Oracle home path.\n";
			usage($NOT_VALID_DIR_OH);
		} else {
			print "\nThe path specified for Oracle_Home $ORACLE_HOME does not exist. In order to proceed, create an empty Oracle home directory and rerun the tool.\n";
			usage($OH_LOC_EMPTY);
		}
	}
	#print "\n\$ORACLE_HOME = $ORACLE_HOME\n";
}

sub unsetEnv() {
	# In case of downloaded version, we unset ORACLE_HOME and ORACLE_BASE.
	if ($ENV{ORACLE_HOME}) {
		delete($ENV{ORACLE_HOME});
	}
	if ($ENV{ORACLE_BASE}) {
		delete($ENV{ORACLE_BASE});
	}
}

sub setLdLibraryPath() {
	#print "...before LD_LIBRARY_PATH = ", $ENV{LD_LIBRARY_PATH},"\n";
        $LD_LIBRARY_PATH = $libDir.$pathSep.$bootstrapDir.$dirSep.'lib'.$pathSep.$bootstrapDir.$dirSep.'oui'.$dirSep.'lib'.$dirSep;
        if ($^O =~ /.*SunOS.*/) {
                $LD_LIBRARY_PATH .= 'solaris';
        } elsif ($^O =~ /.*HPUX.*/i) {
		$hw = `/bin/uname -m`;
		$hw =~ s/^\s+//;
		$hw =~ s/\s+$//;
	       if ($hw eq 'ia64')
	       {
		$LD_LIBRARY_PATH .= 'hpia64';
               }
               else
	       {
		$LD_LIBRARY_PATH .= 'hpunix';
               }
        } elsif ($^O =~ /.*AIX.*/i) {
                $LD_LIBRARY_PATH .= 'aix';
        } else {
		$GETCONF = exists($ENV{GETCONF}) ? $ENV{GETCONF} : '/usr/bin/getconf';
                if (`$GETCONF LONG_BIT` =~ '64') {
                        $LD_LIBRARY_PATH .= 'linux64';
                }
                else {
                        $LD_LIBRARY_PATH .= 'linux';
                }
        }
	$LD_LIBRARY_PATH .= $pathSep.$bootstrapDir.$dirSep.'bin';

	$LD_LIBRARY_PATH .= $pathSep.$ENV{LD_LIBRARY_PATH} if (exists($ENV{LD_LIBRARY_PATH}));
	$ENV{LD_LIBRARY_PATH} = $LD_LIBRARY_PATH;
	#print "...after LD_LIBRARY_PATH = ", $ENV{LD_LIBRARY_PATH},"\n";

	# Apart from LD_LIBRARY_PATH, LIBPATH (on AIX) and SHLIB_PATH (On HP-UX)
	# need to be set
        if ($^O =~ /.*HPUX.*/i) {
           $SHLIB_PATH = $LD_LIBRARY_PATH;
           $SHLIB_PATH .= $pathSep.$ENV{SHLIB_PATH} if (exists($ENV{SHLIB_PATH}));
           $ENV{SHLIB_PATH} = $SHLIB_PATH;
	}

        if ($^O =~ /.*AIX.*/i) {
           $LIBPATH = $LD_LIBRARY_PATH;
           $LIBPATH .= $pathSep.$ENV{LIBPATH} if (exists($ENV{LIBPATH}));
           $ENV{LIBPATH} = $LIBPATH;
	}
}

sub setClassPath() {
	# component specific deconfig JARs
	$toolJar = 'deinstall_wrapper.jar';
	$installDeconfigJar = 'deinstall_core.jar';
	$xmlParserJar = 'xmlparserv2.jar';
	$crsDeconfigJar = $jlibDir.$dirSep.'crsdc.jar';
	$ouiDeconfigJar = $ouiDir.$dirSep.'OraInstaller.jar';
	$ouiCheckpointJar = $ouiDir.$dirSep.'OraCheckPoint.jar';
    	$ocmDeconfigJar = $jlibDir.$dirSep.'deconfigCCR.jar';

	# other JARs for components
	$ouiPrereqJar = $ouiDir.$dirSep.'OraPrereq.jar';
	$ouiPrereqChecksJar = $ouiDir.$dirSep.'OraPrereqChecks.jar';
	$shareJar = $ouiDir.$dirSep.'share.jar';
	$ewtJar = $jlibDir.$dirSep.'ewt3.jar';
	$helpJar = $jlibDir.$dirSep.'help4.jar';

	# Dependent JARs for components
	$srvmJar = $jlibDir.$dirSep.'srvm.jar';
	$srvmHasJar = $jlibDir.$dirSep.'srvmhas.jar';
	$srvmAsmJar = $jlibDir.$dirSep.'srvmasm.jar';
	$vipCaJar = $jlibDir.$dirSep.'vipca.jar';
	$cvuJar = $jlibDir.$dirSep.'cvu.jar';
	$netCaJar = $bootstrapDir.$dirSep.'assistants'.$dirSep.'netca'.$dirSep.'jlib'.$dirSep.'netca.jar';
	$netCamJar = $jlibDir.$dirSep.'netcam.jar';
	$netCfgJar = $jlibDir.$dirSep.'netcfg.jar';
	$ldapJar = $jlibDir.$dirSep.'ldapjclnt11.jar';
	$dbcaJar = $jlibDir.$dirSep.'dbca.jar';
	$dbuaJar = $jlibDir.$dirSep.'dbma.jar';
	$utilJar = $bootstrapDir.$dirSep.'assistants'.$dirSep.'jlib'.$dirSep.'assistantsCommon.jar';
	$emCoreJar = $jlibDir.$dirSep.'emCORE.jar';
	$emConfigJar = $jlibDir.$dirSep.'emConfigInstall.jar';
	$emCaJar = $jlibDir.$dirSep.'emca.jar';
	$httpClientJar = $ouiDir.$dirSep.'http_client.jar';
	$oraMappingJar = $ouiDir.$dirSep.'orai18n-mapping.jar';
	
	
	# set the classpaths
	$toolClassPath = $deinstallJlib.$dirSep.$toolJar;
	$installClassPath = $deinstallJlib.$dirSep.$installDeconfigJar;

	$xmlParserClassPath = $ouiDir.$dirSep.$xmlParserJar; # DJC - Not in the original windows .bat file
	$crsClassPath = $crsDeconfigJar.$pathSep.$vipCaJar.$pathSep.$cvuJar.$pathSep.$oraMappingJar;
	$commonDepClassPath = $srvmJar.$pathSep.$srvmHasJar;
	$ouiClassPath = $ouiDeconfigJar.$pathSep.$ouiCheckpointJar.$pathSep.$ouiPrereqJar.$pathSep.$shareJar.':'.$ewtJar.$pathSep.$helpJar.$pathSep.$xmlParserClassPath;
	$assistantsClassPath = $utilJar.$pathSep.$dbcaJar.$pathSep.$dbuaJar.$pathSep.$ouiPrereqChecksJar.$pathSep.$srvmAsmJar;
	$netCaClassPath = $netCaJar.$pathSep.$netCamJar.$pathSep.$netCfgJar.$pathSep.$ldapJar;
	$emCpClassPath = $srvmAsmJar.$pathSep.$xmlParserClassPath.$pathSep.$utilJar.$pathSep.$shareJar.$pathSep.$emConfigJar.$pathSep.$emCoreJar.$pathSep.$emCaJar.$pathSep.$httpClientJar;
    	$ocmClassPath = $ocmDeconfigJar;

	# main classpath
	$classPath = $toolClassPath.$pathSep.$crsClassPath.$pathSep.$commonDepClassPath.$pathSep.$installClassPath.$pathSep.$ouiClassPath.$pathSep.$assistantsClassPath.$pathSep.$netCaClassPath.$pathSep.$emCpClassPath.$pathSep.$ocmClassPath;
	#print "\n... classPath = $classPath\n";
}
