#!/usr/local/bin/perl
# 
# $Header: emdb/sysman/webapps/em/WEB-INF/perl/config/netconfig.pl /st_emdbsa_11.2/3 2009/05/19 11:15:07 hasriniv Exp $
#
# netconfig.pl
# 
# Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      netconfig.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)
#    hasriniv    01/29/09 - Code Sync
#    hasriniv    08/12/08 - 
#    rimmidi     05/06/08 - Code slap from 11gc to 10.2.0.5
#    rimmidi     05/06/08 - Creation
# 
require "emd_common.pl";
# require "$ENV{EMDROOT}/sysman/admin/scripts/config/config_common.pl";


use strict;
use File::Basename;
use File::Copy;
use File::Temp qw/ tempfile tempdir /;
use File::stat;
use vars qw/$hostUserID $OS $NT $S $TEMP $CP $MV $PS $DF $DELIMITER $Registry/;

$ENV{EMAGENT_PERL_TRACE_LEVEL} = 0;  #DEBUG level.

# Global variables
$hostUserID = "";


# Backup listener.ora:
#   check exist or not
#   check file length
#      if not exist, create an empty one with a comment at the top
#      if exist and length > 0, copy it to make a backup
#      if exist but length 0, copy it to make a backup then add a comment at the top of original one
# backupListenerFile(listener, listenerBk, sqlnet)
sub backupListenerFile
{
  my ($listener, $listenerBk, $sqlnet) = @_;

  if(! -e "$listener") #not exist
  {
    my $tempfile = createZeroSizeFile(getDirname($listener));
    EMD_PERL_DEBUG("netconfig.backupNetConfigFiles(): tempfile: $tempfile");
    open(TEMPFILE, ">>$tempfile") || die "Cannot open $tempfile";
    print TEMPFILE "#LISTENER.ORA Network Configuration File\n";
    print TEMPFILE "#Created by Oracle Enterprise Manager Config tool\n";
    close TEMPFILE || die "Cannot close $tempfile";
    copyFile($tempfile, $listener);
    removeFile($tempfile);
  }
  else #exists
  {
    copyFile($listener, $listenerBk);
    if(-z "$listener") #exists and zero size
    {
      open(CONFIGFILE, ">>$listener") || die "Cannot open $listener";
      print CONFIGFILE "#LISTENER.ORA Network Configuration File\n";
      print CONFIGFILE "#Modified by Oracle Enterprise Manager Config tool\n";
      close CONFIGFILE || die "Cannot close $listener";
    }
  }
  if(! -e "$sqlnet") #not exist
  {
    my $tempfile = createZeroSizeFile(getDirname($sqlnet));
    open(TEMPFILE, ">>$tempfile") || die "Cannot open $tempfile";
    print TEMPFILE "#SQLNET.ORA Network Configuration File\n";
    print TEMPFILE "#Created by Oracle Enterprise Manager Config tool\n";
    if($NT)
    {
      print TEMPFILE "sqlnet.authentication_services=(NTS)\n";
    }
    close TEMPFILE || die "Cannot close $tempfile";
    copyFile($tempfile, $sqlnet);
    removeFile($tempfile);
  }
  else #exists
  {
    if(-z "$sqlnet") #exists and zero size
    {
      #only backup if zero size since we do not modify it if non-zero size
      #this is to workaround transferring zero size file.
      copyFile($sqlnet, $sqlnet.".orig"); 
      open(CONFIGFILE, ">>$sqlnet") || die "Cannot open $sqlnet";
      print CONFIGFILE "#SQLNET.ORA Network Configuration File\n";
      print CONFIGFILE "#Modified by Oracle Enterprise Manager Config tool\n";
      if($NT)
      {
        print CONFIGFILE "sqlnet.authentication_services=(NTS)\n";
      }
      close CONFIGFILE || die "Cannot close $sqlnet";
    }
  }
}
# Backup two network config files:
#   check exist or not
#   check file length
#      if not exist, create an empty one with a comment at the top
#      if exist and length > 0, copy it to make a backup
#      if exist but length 0, copy it to make a backup then add a comment at the top of original one
# backupNetConfigFiles(listener, listenerBk, tnsnames, tnsnamesBk, sqlnet)
sub backupNetConfigFiles
{
  my ($listener, $listenerBk, $tnsnames, $tnsnamesBk, $sqlnet) = @_;

  if(! -e "$listener") #not exist
  {
    my $tempfile = createZeroSizeFile(getDirname($listener));
    EMD_PERL_DEBUG("netconfig.backupNetConfigFiles(): tempfile: $tempfile");
    open(TEMPFILE, ">>$tempfile") || die "Cannot open $tempfile";
    print TEMPFILE "#LISTENER.ORA Network Configuration File\n";
    print TEMPFILE "#Created by Oracle Enterprise Manager Config tool\n";
    close TEMPFILE || die "Cannot close $tempfile";
    copyFile($tempfile, $listener);
    removeFile($tempfile);
  }
  else #exists
  {
    copyFile($listener, $listenerBk);
    if(-z "$listener") #exists and zero size
    {
      open(CONFIGFILE, ">>$listener") || die "Cannot open $listener";
      print CONFIGFILE "#LISTENER.ORA Network Configuration File\n";
      print CONFIGFILE "#Modified by Oracle Enterprise Manager Config tool\n";
      close CONFIGFILE || die "Cannot close $listener";
    }
  }
  
  if(! -e "$tnsnames") #not exist
  {
    my $tempfile = createZeroSizeFile(getDirname($tnsnames));
    open(TEMPFILE, ">>$tempfile") || die "Cannot open $tempfile";
    print TEMPFILE "#TNSNAMES.ORA Network Configuration File\n";
    print TEMPFILE "#Created by Oracle Enterprise Manager Config tool\n";
    close TEMPFILE || die "Cannot close $tempfile";
    copyFile($tempfile, $tnsnames);
    removeFile($tempfile);
  }
  else #exists
  {
    copyFile($tnsnames, $tnsnamesBk);
    if(-z "$tnsnames") #exists and zero size
    {
      open(CONFIGFILE, ">>$tnsnames") || die "Cannot open $tnsnames";
      print CONFIGFILE "#TNSNAMES.ORA Network Configuration File\n";
      print CONFIGFILE "#Modified by Oracle Enterprise Manager Config tool\n";
      close CONFIGFILE || die "Cannot close $tnsnames";
    }
  }

  if(! -e "$sqlnet") #not exist
  {
    my $tempfile = createZeroSizeFile(getDirname($sqlnet));
    open(TEMPFILE, ">>$tempfile") || die "Cannot open $tempfile";
    print TEMPFILE "#SQLNET.ORA Network Configuration File\n";
    print TEMPFILE "#Created by Oracle Enterprise Manager Config tool\n";
    if($NT)
    {
      print TEMPFILE "sqlnet.authentication_services=(NTS)\n";
    }
    close TEMPFILE || die "Cannot close $tempfile";
    copyFile($tempfile, $sqlnet);
    removeFile($tempfile);
  }
  else #exists
  {
    if(-z "$sqlnet") #exists and zero size
    {
      #only backup if zero size since we do not modify it if non-zero size
      #this is to workaround transferring zero size file.
      copyFile($sqlnet, $sqlnet.".orig"); 
      open(CONFIGFILE, ">>$sqlnet") || die "Cannot open $sqlnet";
      print CONFIGFILE "#SQLNET.ORA Network Configuration File\n";
      print CONFIGFILE "#Modified by Oracle Enterprise Manager Config tool\n";
      if($NT)
      {
        print CONFIGFILE "sqlnet.authentication_services=(NTS)\n";
      }
      close CONFIGFILE || die "Cannot close $sqlnet";
    }
  }
}

##########################################################
## Check if a listener is running
##########################################################
sub isListenerRunning
{
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): *** START ***");
  
    my($lname, $tns) = @_;
    my($lfile) = "${tns}${S}listener.ora";
    my($lsnrexec) = "$ENV{ORACLE_HOME}${S}bin${S}lsnrctl";
    my($retVal) = "NO";
    $ENV{TNS_ADMIN} = "$tns";
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): TNS_ADMIN = $ENV{TNS_ADMIN}");
  
    #remember the original OH
    my $original_oracle_home = $ENV{ORACLE_HOME};
    my $reset_env = "FALSE";
  
    my $lsnrctl = &getLsnrctl($tns);
    if($lsnrctl ne "")
    {
      $lsnrexec = $lsnrctl;
      $reset_env = "TRUE";
    }

    #A temp solution for hanging: redirect output to a temp file
    (my $fh, my $filename) = &create_temp_file();
    if($NT)
    {
      $filename = "$TEMP\\"."config.$$";
    }
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): Temp pfile: $filename");

    ## If status is bad, means it's not running
    my($cmd) = "$lsnrexec status $lname";
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): Command: $cmd");
    my(@res) = `$cmd >$filename 2>&1`;
  
    #my $mesg = getOutputFromFile($filename);
    #print STDOUT $mesg;
  
    if(!$?)
    {
      EMD_PERL_DEBUG("netconfig.isListenerRunning(): listener $lname currently running");
      $retVal = "YES";
    }

    close $fh;
    if($NT)
    {
	&removeFile($filename);
    }
    
    #set env back since getLsnrctl set it to a new home
    if($reset_env eq "TRUE")
    {
      &set_env($original_oracle_home, $ENV{ORACLE_SID});
    }
    
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): listener $lname isRunning: $retVal ");
    EMD_PERL_DEBUG("netconfig.isListenerRunning(): *** END ***");
    return $retVal;
}

##########################################################
## Start a listener
##########################################################
sub startListener
{
  EMD_PERL_DEBUG("netconfig.startListener(): *** START ***");
  
	my($lname, $tns) = @_;
        my($lfile) = "${tns}${S}listener.ora";
	my($lsnrexec) = "$ENV{ORACLE_HOME}${S}bin${S}lsnrctl";

	$ENV{TNS_ADMIN} = "$tns";
  EMD_PERL_DEBUG("netconfig.startListener(): TNS_ADMIN = $ENV{TNS_ADMIN}");
  
  #remember the original OH
  my $original_oracle_home = $ENV{ORACLE_HOME};
  my $reset_env = "FALSE";
  
  my $lsnrctl = &getLsnrctl($tns);
  if($lsnrctl ne "")
  {
    $lsnrexec = $lsnrctl;
    $reset_env = "TRUE";
  }

  #A temp solution for hanging: redirect output to a temp file
  (my $fh, my $filename) = &create_temp_file();
  if($NT)
  {
    $filename = "$TEMP\\"."config.$$";
  }
  EMD_PERL_DEBUG("netconfig.startListener(): Temp pfile: $filename");

	## If status is bad, means it's not running
	my($cmd) = "$lsnrexec status $lname";
        EMD_PERL_DEBUG("netconfig.startListener(): Command: $cmd");
	my(@res) = `$cmd >$filename 2>&1`;
  
  my $mesg = getOutputFromFile($filename);
  print STDOUT $mesg;
  
	if(!$?)
{
    EMD_PERL_DEBUG("netconfig.startListener(): listener $lname currently running");
    $cmd = "$lsnrexec reload $lname";
    EMD_PERL_DEBUG("netconfig.startListener(): Command: $cmd");
    @res = `$cmd >$filename 2>&1`;

    $mesg = getOutputFromFile($filename);
    print STDOUT $mesg;
    
		#if(system($cmd)){
    if($?){
      EMD_PERL_DEBUG("netconfig.startListener(): lsnrctl reload failed");
      exit(1);
		}

    close $fh;
    if($NT)
    {
	&removeFile($filename);
    }
    
    #set env back since getLsnrctl set it to a new home
    if($reset_env eq "TRUE")
    {
      &set_env($original_oracle_home, $ENV{ORACLE_SID});
    }
    
    EMD_PERL_DEBUG("netconfig.startListener(): listener $lname reloaded");
    EMD_PERL_DEBUG("netconfig.startListener(): *** END ***");
    return;
	}

	## Can't try the start too soon on NT
	if($NT){
		sleep 5;
	}

	$cmd = "$lsnrexec start $lname";
        EMD_PERL_DEBUG("netconfig.startListener(): Command: $cmd");
  @res = `$cmd >$filename 2>&1`;

  $mesg = getOutputFromFile($filename);
  print STDOUT $mesg;
  
	#system($cmd);
	if($?){
    EMD_PERL_DEBUG("netconfig.startListener(): ${cmd} failed: $!");
		exit(1);
	}

  if($NT)
  {
    my $lsnrService = getLsnrService($mesg, $lname);
    if($lsnrService ne "")
    {
      $cmd = $ENV{ComSpec}." /c";
      $cmd = "$cmd sc config ".${lsnrService}." start= auto";
      EMD_PERL_DEBUG("netconfig.startListener(): config service: $cmd");
      @res = `$cmd >$filename 2>&1`;
      EMD_PERL_DEBUG("netconfig.startListener(): config service output: @res");
      $mesg = getOutputFromFile($filename);
      print STDOUT $mesg;
    }
  }

  close $fh;
  if($NT)
  {
     &removeFile($filename);
  }
  
  #set env back since getLsnrctl set it to a new home
  if($reset_env eq "TRUE")
  {
    &set_env($original_oracle_home, $ENV{ORACLE_SID});
  }
  
  EMD_PERL_DEBUG("netconfig.startListener(): listener $lname started");
  EMD_PERL_DEBUG("netconfig.startListener(): *** END ***");
}
# Return "/abc/../bin/lsnrctl" if the given file path is "/abc/../network/admin/listener.ora"
# getLsnrctl(tns)
sub getLsnrctl
{
  my ($tns) = @_;
  
  my $lsnrctl = "";
  my $exe = "";
  my $levelOneDirName = "";
  my $levelTwoDirName = "";
  my $levelOneDirPath = "";
  my $levelTwoDirPath = "";
  
  $levelOneDirName = &getBasename($tns);
  $levelOneDirPath = &getDirname($tns);
  if((uc $levelOneDirName) ne (uc "admin"))
  {
    EMD_PERL_DEBUG("netconfig.getLsnrctl(): $levelOneDirName is not 'admin'");
    return $lsnrctl;
  }
  
  $levelTwoDirName = &getBasename($levelOneDirPath);
  $levelTwoDirPath = &getDirname($levelOneDirPath);
  if((uc $levelTwoDirName) ne (uc "network"))
  {
    EMD_PERL_DEBUG("netconfig.getLsnrctl(): $levelTwoDirName is not 'network'");
    return $lsnrctl;
  }
  
  if($NT)
  {
    $exe = ".exe";
  }
  
  $lsnrctl = "${levelTwoDirPath}${S}bin${S}lsnrctl${exe}";
  
  if(! -e "$lsnrctl")
  {
    EMD_PERL_DEBUG("netconfig.getLsnrctl(): $lsnrctl does not exist!");
    return "";
  }

  &set_env($levelTwoDirPath, $ENV{ORACLE_SID});
  
  EMD_PERL_DEBUG("netconfig.getLsnrctl(): lsrnctl is: $lsnrctl");
  return $lsnrctl;
}

# Get listener service name by parsing the "lsnrctl start" output
# getLsnrService(mesg, lname)
sub getLsnrService
{
  my $mesg = $_[0];
  my $lname = $_[1];

  EMD_PERL_DEBUG("netconfig.getLsnrService(): lsnrctl start output: $mesg");
  EMD_PERL_DEBUG("netconfig.getLsnrService(): listener name: $lname");

  if(uc($lname) eq "LISTENER")
  {
    $lname = "";
  }

  my $firstPart = "<Oracle";
  my $secondPart = "TNSListener".${lname}.">";
  my $startPos = index($mesg, $firstPart);
  my $endPos = index($mesg, $secondPart);
  if(($startPos < 0) || ($endPos < 0))
  {
    EMD_PERL_DEBUG("netconfig.getLsnrService(): startPos: $startPos");
    EMD_PERL_DEBUG("netconfig.getLsnrService(): endPos: $endPos");
    return "";
  }

  $firstPart = substr($mesg, $startPos + 1, ($endPos - $startPos - 1));
  $secondPart = substr($secondPart, 0, (length($secondPart) -1));
  my $lsnrService = ${firstPart}.${secondPart};
  EMD_PERL_DEBUG("netconfig.getLsnrService(): listener service name: $lsnrService");

  return $lsnrService;
}

1;
