#!/usr/local/bin/perl
# 
# $Header: netAdmin.pl 06-jun-2008.14:29:14 nachen Exp $
#
# netAdmin.pl
# 
# Copyright (c) 2002, 2008, Oracle. All rights reserved.  
#
#    NAME
#      netAdmin.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)
#    nachen      06/19/08 - XbranchMerge nachen_bug-7144603 from st_emdbsa_11.1
#    nachen      06/06/08 - fix internal references security issue
#    mkiran      07/31/06 - 4774824: restore shared lib path.
#    vivsharm    02/15/06 - NT porting 
#    vivsharm    05/23/05 - for filesExist method fix 
#    jpegu       05/04/05 - Added subroutine to get details of servcies 
#                           command 
#    jpegu       04/18/05 - For making parseShowForLogOrTrace generic 
#    vivsharm    03/15/05 - for 4231285 
#    rasundar    11/05/03 - add changePermission function 
#    dkapoor     10/31/03 - fix bug3221435 
#    rasundar    10/14/03 - append slash based on the platform 
#    rasundar    09/12/03 - use own temp files on NT 
#    hasriniv    05/21/03 - Checking for existence of listener.ora 
#    dkapoor     12/11/02 - fix empty result
#    dkapoor     12/03/02 - fix no result
#    dkapoor     11/18/02 - not to use create_temp
#    dkapoor     11/05/02 - add exit to the command
#    dkapoor     10/28/02 - add testConnection
#    dkapoor     10/16/02 - replace prompt
#    dkapoor     10/07/02 - return full output
#    dkapoor     07/31/02 - dkapoor_fix_lsnr_targetadmin
#    dkapoor     07/31/02 - remove hard strings
#    dkapoor     07/26/02 - Creation
# 
require 5.8.2;
require "$ENV{EMDROOT}/sysman/admin/scripts/semd_common.pl";
require "$ENV{EMDROOT}/sysman/admin/scripts/db/db_common.pl";

use strict;
use File::Temp qw/ tempfile /;

sub changePermissions
{
  my ($fileName, $permission) = @_;
  my $status = 'NOK';

  chmod($permission, $fileName);
  EMD_PERL_DEBUG("Permisson changed successfully");

  $status = 'OK';

  return $status;
}

sub lsnStatusChange
{
    my ($oracleHome,$tnsAdmin,$lsnrName,$promptArrowReplace,@commands) = @_;
    #Check for the existence of the listener.ora file
    my $lsnrFile;
    my $OSNAME = get_osType();
    my $IsWin32 = ($OSNAME eq 'WIN');
    if($IsWin32)
    {
      $lsnrFile = $tnsAdmin."\\listener.ora";
    } 
    else
    {
      $lsnrFile = $tnsAdmin."/listener.ora";
    } 
    EMD_PERL_DEBUG("The listener file is $lsnrFile");
    if ( -e $lsnrFile )
      {
	return getRunCommandOutput($oracleHome,$tnsAdmin,"$oracleHome/bin/lsnrctl",$promptArrowReplace,@commands);
      }
    else
      {
	EMD_PERL_DEBUG($lsnrFile." not found");
	die "NET_ADMIN_ERROR,LSNRORA_NOT_FOUND,$tnsAdmin,$lsnrName";
  }
  
}

sub getRunCommandOutput
{
    my ($oracleHome,$tnsAdmin,$executable,$promptArrowReplace,@commands) = @_;
    $ENV{ORACLE_HOME}=$oracleHome;
    $ENV{TNS_ADMIN}=$tnsAdmin;

    my $bkup_path = get_complete_lib_path();
    set_lib_path($oracleHome);

    my $filename;
    my $fh;
    my $OSNAME = get_osType();
    my $IsWin32 = ($OSNAME eq 'WIN');
    if($IsWin32)
    {
      my $TEMP = "C:\\TEMP";
      #A temp solution
      &mkDir($TEMP);
      $filename = "$TEMP\\"."net.$$";
    }
    else
    {
      ($fh, $filename) = tempfile(UNLINK => 1); 
    }   
    my $output_string;     
    if(open(EXEC_WRITER, "|$executable > $filename"))
    {
      EMD_PERL_DEBUG("$executable opened");
      my $cmd;
      foreach $cmd (@commands)
      {
        EMD_PERL_DEBUG("priting command=[$cmd]");
        print  EXEC_WRITER "$cmd\n";
      }
      EMD_PERL_DEBUG("Exit done ..");
      EMD_PERL_DEBUG("Closing exec writer ..");
      close EXEC_WRITER;
      EMD_PERL_DEBUG("EXEC_WRITER closed ..");
      if(open (OUT_PUT, "$filename"))
      {
        my @output_content = <OUT_PUT>;
        $output_string = "@output_content";
        EMD_PERL_DEBUG("File output: \n$output_string");
        close OUT_PUT;
        $output_string =~ s/\>/$promptArrowReplace/g; 
        EMD_PERL_DEBUG("File output after replace: \n$output_string");
      }
      else
      {
        die "NET_ADMIN_ERROR,REMOTE_OP_ERROR,$!";
      }
    }
    else
    {
	die  "NET_ADMIN_ERROR,CANNOT_EXEC,$executable,$!";
    }
    #close($fh);
    if($IsWin32)
    {
      &removeFile($filename);
    }

    set_complete_lib_path($bkup_path);

    return $output_string;
}

sub parseShowForLogOrTrace
{
    my ($lsnrctlOutput,$listenerName,$command) = @_;
    if($lsnrctlOutput =~ /(TNS[-:])/)
    {
        return " ";
    }
    my @lines = split(/\n/,$lsnrctlOutput);

    my $RESLT = " ";
	my $line;
	my $mWord;
    foreach $line (@lines)
    {
      #if($line  =~ /^\s*$listenerName(.*)\"$command\"\s+\w+\s+\w+\s+(.*)/i)
      #{
      #   return $2;
      #}

	  # The output of the command like "lsnrctl show trc_level" will be a line which will look like:
	  #		LISTENER parameter "trc_level" set to off
	  if($line  =~ /^\s*$listenerName.*$command(.*)/i)
      {
		  # $1 will be = "set to off"
		  my @outputWords = split(/\s/,$1);

		  foreach $mWord (@outputWords) 
		  {
			# we actually need the last token which is the status = "off"
			# we keep overwriting $RESLT with the tokens in the loop (last token is what we need)
			$RESLT = $mWord;
		  }
	  }
    }
	# final value for $RESLT will be euther "on" or "off" when we return here.
    return $RESLT ;
}

sub testConnection
{
    my ($oracleHome,$tnsAdmin,$connectString,$user,$password) = @_;
    EMD_PERL_DEBUG("in testConnection OracleHome==>$oracleHome");
    my $output =getTestOutput ($oracleHome,$tnsAdmin,$connectString,$user,$password,":") ;
    #return parseOutput($output);
    $output =  parseOutput($output);
    EMD_PERL_DEBUG("in testConnection final output==>$output");
    return $output;
}


sub parseOutput
{
    my ($sqlplusOutput) = @_;
    if($sqlplusOutput !~ /(TNS[-:])|(ORA[:-])/i)
    {
	return " ";
    }
    my @lines = split(/\n/,$sqlplusOutput);
    my $line;
    foreach $line (@lines)
    {
    	if($line =~ /(TNS[-:])|(ORA[:-])/i)
	{
	    print "$line\n";
	}
    }
    return  " ";
}

sub getTestOutput
{
    my ($oracleHome,$tnsAdmin,$connectString,$user,$password,$promptArrowReplace) = @_;
    my @commands;
    EMD_PERL_DEBUG("in getTestOutput OracleHome==>$oracleHome");
    push(@commands,"connect $user/$password@\"$connectString\"\n");	
    push(@commands,"exit\n");	
    return getRunCommandOutput($oracleHome,$tnsAdmin,"$oracleHome/bin/sqlplus /nolog",$promptArrowReplace,@commands);
}




# Given the output from the lsnrctl "services" command in raw mode
# this subroutine returns an array for service names found and its correponding details
#
# For lsnrctl services output in raw mode like:
# LSNRCTL> services 
# Connecting to (ADDRESS=(PROTOCOL=TCP)(HOST=stadq11.example.com)(PORT=1521))
# Services Summary...
# (SERVICE=(SERVICE_NAME=orclServiceName)(INSTANCE=(INSTANCE_NAME=orcloid)(NUM=1)(IN
# STANCE_STATUS=UNKNOWN)(HANDLER=(HANDLER_DISPLAY=DEDICATED SERVER)(HANDLER_INFO=L
# OCAL SERVER)(HANDLER_MAXLOAD=0)(HANDLER_LOAD=0)(ESTABLISHED=0)(REFUSED=0)(HANDLE
# R_ID=B94B489DEB84-11D6-B6FD-0002A517EED1)(PRE=any)(HANDLER_NAME=DEDICATED)(SESSI
# ON=NS)(ADDRESS=(PROTOCOL=beq)(PROGRAM=extproc)(ENVS='ORACLE_HOME=d:\oracle92\test
# ,ORACLE_SID=orcloid')(ARGV0=extprocPLSExtProc)(ARGS='(LOCAL=NO)')))(NUMREL=

# The following will be returned
# (orclServiceName1, orclServiceName2)
#
#Assuptions:
# 0. The entry for INSTANCE_NAME = *extproc* (ignoring case) is not returned.
# 1. If no ORACLE_SID or ORACLE_HOME found , the entry is not returned
#


sub getServicesCmdDetails
{

	my ($results) = @_;
	#my %servCmdDetails; (planned to return a hash table)
	my @serviceArray;

	my @resultArray = split (/\n/, $results);

	my $serviceName; my $oracleHome; my $oracleSid; my $instanceName;

	foreach my $line (@resultArray) 
	{
		#Get Host & Port
		#if ($line =~ /^.*HOST=(\S+)\)\(PORT=(\S+)\)\)\)/i ) {
		#	$lsnrHost = $1 ;
		#	$port = $2;
		#	next;
		#}

		#Skip if No SERVICE is present
		if($line !~ /^\s*\(SERVICE/i)
		{
			next;
		}

		#Skip if No ORACLE_HOME is present
		if($line !~ /(ORACLE_HOME)|(ORACLE_SID)/i)
		{
			next;
		}

		#Get Service Name, Oracle SID and Oracle Home
		if( $line =~ /^.*SERVICE_NAME=(\S+)\)\(INSTANCE=.*ORACLE_HOME=(\S+)\,ORACLE_SID=(\S+)\'\)\(ARGV0=.*/ )
		{
			$serviceName = $1;
			$oracleHome = $2;
			$oracleSid = $3;
		}

		if ($oracleSid =~ /extproc/i)
		{
			#filter out sids containing with extproc
			next;
		}

		if( defined $oracleSid && $oracleSid ne ""  && defined $oracleHome && $oracleHome ne "")
		{
			#my %sidDetails = ('ORACLE_HOME' , $oracleHome, 'SERVICE_NAME' , $serviceName, 'PORT' , $port, 'HOST' , $lsnrHost) ;
			#my $refDetails = \%sidDetails;
			#$servCmdDetails{$oracleSid} = $refDetails;
			push(@serviceArray,$serviceName);
		}
	}
	#return \%servCmdDetails;
	return @serviceArray;

}
sub filesExistStrict
{
	my ($fileNameArray) = @_;
	my $DELIMITER = ":::";
	my @fileNames = split /$DELIMITER/, $fileNameArray;
	my $existStatus = "";
	my $fileName;
	foreach $fileName (@fileNames)
	{
		if(! -e "$fileName")
		{
			EMD_PERL_DEBUG("db_common.filesExists(): File $fileName does not exist");
			$existStatus .= "NOK:";
		}
		else #PATH is correct, but is it a file or DIR
		{
			if(! -d "$fileName") # must be a file
			{
				EMD_PERL_DEBUG("db_common.filesExists(): File $fileName exists");
				$existStatus .= "OK:";
			}
			else
			{
				EMD_PERL_DEBUG("db_common.filesExists(): $fileName is a Directory not a file.");
				$existStatus .= "NOK:";
			}
		}
	}
	return $existStatus;
} 
