#!/usr/local/bin/perl
# 
# $Header: emdb/sysman/admin/scripts/lsnrParams.pl /st_emdbsa_11.2/1 2011/01/12 21:33:34 mappusam Exp $
#
# lsnrParams.pl
# 
# Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      lsnrParams.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)
#    mappusam    01/10/11 - Backport mappusam_bug-9934831 from main
#    manosing    01/12/07 - XbranchMerge manosing_lastpols from main
#    manosing    12/28/06 - flood control for windows policy
#    manosing    10/09/06 - inbound_connect_timeout 
#    dsukhwal    07/22/05 - parse listener.ora too for hostname 
#    dsukhwal    06/30/05 - support flood control for all policies 
#    dkjain      06/27/05 - Adding check for oms ver 
#    dsukhwal    05/13/05 - limit number of rows pushed 
#    dsukhwal    05/01/05 - handle win32 cases 
#    dsukhwal    03/17/05 - address correct listener 
#    dsukhwal    02/15/05 - exceptional cases in file_perm usage 
#    dsukhwal    12/28/04 - Permissions of backups of listener.ora
#    dsukhwal    12/28/04 - Query running listener
#    dsukhwal    12/14/04 - Display permissions in rwx format(bug 4057002) 
#    dsukhwal    11/24/04 - change some extract_parameter_par to line 
#    dsukhwal    11/23/04 - fix lsnrAdmin empty value 
#    dkjain      10/13/04 - NA removed 
#    dkjain      10/08/04 - dkjain_esa_impl_init
#    dkjain      10/08/04 - Creation
# 

  use strict;
  require "$ENV{EMDROOT}/sysman/admin/scripts/db/esaUtils.pl";
  require "$ENV{EMDROOT}/sysman/admin/scripts/db/net/listenerUtil.pl";
  use vars qw($NT $S); #both come from db_common.pl
  require "$ENV{EMDROOT}/sysman/admin/scripts/db/db_common.pl";
  $S = qq($S);
  #$S = "\\";


  #$ENV{'SLASH'}=$S;
  my $name = $ENV{LSNR_NAME};
  my $listenerFile = $ENV{'LSNR_ORA_DIR'}.$S."listener.ora";
  my $executable= $ENV{LSNR_ORACLE_HOME}.$S."bin".$S."lsnrctl";
  my $machine = $ENV{LSNR_MACHINE};
  my $port = $ENV{LSNR_PORT};
  my $address="(ADDRESS=(PROTOCOL=TCP)(HOST=$machine)(PORT=$port))";
  my $tgtOracleHome = $ENV{'LSNR_ORACLE_HOME'};
  my $oms_ver=$ENV{OMS_VERSION};


  #print "em_result=DEBUG|$oms_ver|NA\n";
 if(!($oms_ver =~ "10.1")){ 
  lsnr_host_ip(); #queries running listener. 
  lsnr_trace_file();#queries running listener, uploads 2 properties trace_file_lsnr_own and trace_file_lsnr_perm
  lsnr_trace_directory();#queries running listener, uploads 2 properties trace_dir_lsnr_perm and trace_dir_lsnr_own
  lsnr_log_file();#queries running listener, uploads 2 properties log_file_lsnr_own and log_file_lsnr_perm
  lsnr_ora_perms();
  #if(!($oms_ver =~ "10.2.0.2") && !($oms_ver =~ "10.2.0.3")){
  #if(!($oms_ver =~ "10.2.0.2")){
      lsnr_inbound_connect_timeout();
  #} #uploads only for 10gR4 n onwards
          
 } #uploads only for 10gR2 n onwards
  lsnr_admin_status(); #parses the file

sub lsnr_host_ip
{
    my @command = ("set current_listener $address", "status");
    my $result;
    my $n;
    my @hosts;
    my $maxRows = $ENV{'HOSTNAMEMAX'};
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result, remove the line containing "Connecting to", or  "Current Listener is "
    #This is because these lines contain the IP address/hostname supplied by the targets.xml
    #and is not necessarily the address used by the listener.ora/tnsnames.ora etc.
    my @resultLines = split(/\n/,$result);
    for(my $n=0;$n<@resultLines;$n++){
        if($resultLines[$n] =~ /(\s+)LSNRCTL>(\s+)Connecting to (.*)/){
            $resultLines[$n] = "";
        }
        if($resultLines[$n] =~ /(\s+)LSNRCTL>(\s+)Current Listener is (.*)/){
            $resultLines[$n] = "";
        }
    }
    $result = join("",@resultLines);
    $result =~ s/\s+//g; #remove blank spaces
    @hosts = split(/host=/i,$result);
    shift(@hosts);
    foreach (@hosts) {
        s/(.*?)\)(.|\n)*/$1/;
    }
    @hosts = uniq_array(@hosts);
    @hosts = remove_dynamic(@hosts);
    if(defined($maxRows) && ($maxRows >= 0)){
        splice(@hosts, $maxRows);
    }
    foreach  (@hosts) {
        print "em_result=host_name|$_|NA\n";
    }
}

#this function gets the listener.ora file for the listener from the status of the running listener. 
#It then determines the directory by stripping the leading "listener.ora" from it. In this directory, 
#it searches all files having listener as a substring of their name(*listener* files) and 
#reports their permissions in octal format
sub lsnr_ora_perms{
    my @command = ("set current_listener $address", "status");
    my $result;
    my @lines;
    my $perm;
    my $lsnr_ora_dir;
    my $maxRows;
    
    if($^O eq "MSWin32"){
        $maxRows = $ENV{'NLOPERMMAX'};
    }else{
        $maxRows = $ENV{'LOPERMMAX'};
    }
    my $rowNum = 0;
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result
    @lines = split(/\n/,$result);    
    foreach (@lines) {
        if (m/Listener Parameter File(\s+)(.*)/i) {
            my $slashForSplit = s/\\/\\\\/g;
            my @file_parts = split(/$slashForSplit/, $2);
            my $lastPart = pop(@file_parts);
            if(lc($lastPart) eq "listener.ora"){
                $lsnr_ora_dir = join($S, @file_parts);
            }
            else{
                $lsnr_ora_dir = "";
            }
            last;
        }
    }
    if(!$lsnr_ora_dir){ # if lsnrctl status fails to provide the listener.ora directory, 
                        #we take the directory supplied in the targets.xml
        $lsnr_ora_dir = $ENV{'LSNR_ORA_DIR'};
    }
    eval{
        opendir(IMD, $lsnr_ora_dir) || die("Cannot open directory");
        my @thefiles= readdir(IMD);
        closedir(IMD);
        foreach (@thefiles)
        {
            if($_ =~ /listener/ )
            {
                if($^O eq "MSWin32"){#platform is win32
                    if(!compareNegInf($rowNum, $maxRows)){
                        return;
                    }
                    my $lsnrFile = $lsnr_ora_dir.$S.$_;
                    my $win_perm = check_512char(win32_file_perm($lsnrFile));
                    if($win_perm != -1) {
                        print "em_result=nt_lsnrora_permission|$lsnrFile|$win_perm\n";
                        $rowNum++;
                    }
                }
                elsif($^O eq "linux"){#platform is linux
                  if(!compareNegInf($rowNum, $maxRows)){
                    return;
                  }
                  $perm = file_perm($lsnr_ora_dir.$S.$_) & 0777;
                  printf("em_result=lsnrora_permission|$lsnr_ora_dir$S$_|%03o\n",$perm);
                  $rowNum++;
                }
                else{
                  #neither linux nor windows stuff
                }
            }
        }
    };
}

sub lsnr_trace_file
{
    #could have received this information from "lsnrctl show trc_file" also, but status shows the resultant trace file, 
    #made up of information from trace directory and trace file. Hence, better suited for our purposes is "lsnrctl status"
    my @command = ("status $address");
    my $result ;
    my @lines;
    my $trc_file;
    my $perm;
    my $permMax;
    my $ownMax = $ENV{'TFOWNMAX'};
    my $permRowNum = 0;
 
   if($^O eq "MSWin32"){
        $permMax = $ENV{'NTFPERMMAX'};
   }else{
        $permMax = $ENV{'TFPERMMAX'};
   } 
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result
    @lines = split(/\n/,$result);    
    foreach (@lines) {
        if (m/Listener Trace File(\s+)(.*)/i){
            $trc_file = $2;
            compareOwner("trace_file_lsnr_own", $ownMax, $trc_file, $tgtOracleHome);
            if($^O eq "linux"){
                $perm = file_perm($trc_file);
                if( ($perm >= 0) && compareNegInf($permRowNum, $permMax) ){
                    $perm = $perm & 0777;
                    printf ("em_result=trace_file_lsnr_perm|$trc_file|%03o\n",$perm);
                    $permRowNum++;
                }
                last;
            }
            elsif($^O eq "MSWin32"){
                if(!compareNegInf($permRowNum, $permMax)){
                    return;
                }       
                my $win_perm = check_512char(win32_file_perm($trc_file));
                if($win_perm != -1){
                    print "em_result=nt_trace_file_lsnr_perm|$trc_file|$win_perm\n";
                    $permRowNum++;
                }
            }
            else{
                #neither mswin32, nor linux stuff
            }
        }
    }
}

sub lsnr_trace_directory
{
    my @command = ("set current_listener $address", "show trc_directory");
    my $result ;
    my @lines;
    my $trc_dir;
    my $perm;
    my $permMax;
    my $ownMax = $ENV{'TDOWNMAX'};
    my $permRowNum = 0;
    
    if($^O eq "MSWin32"){
        $permMax = $ENV{'NTDPERMMAX'};
    }else{
        $permMax = $ENV{'TDPERMMAX'};
    }
    if(isExecutionPossible(\@command))
    { 
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result
    @lines = split(/\n/,$result);
    pop(@lines);
    pop(@lines);
    $trc_dir = pop(@lines);
    $trc_dir =~ s/(.*)parameter \"trc_directory\" set to (.*)/$2/i;
    compareOwner("trace_dir_lsnr_own", $ownMax, $trc_dir, $tgtOracleHome);
    if($^O eq "linux"){
        $perm = file_perm($trc_dir);
        if( ($perm >= 0) && compareNegInf($permRowNum, $permMax) ){
            $perm = $perm & 0777;
            printf ("em_result=trace_dir_lsnr_perm|$trc_dir|%03o\n",$perm);
            $permRowNum++;
        }
    }
    elsif($^O eq "MSWin32"){
        if(!compareNegInf($permRowNum, $permMax)){
            return;
        }       
        my $win_perm = check_512char(win32_file_perm($trc_dir));
        if($win_perm != -1){
            print "em_result=nt_trace_dir_lsnr_perm|$trc_dir|$win_perm\n";
            $permRowNum++;
        }
    }
    else{
        #neither mswin32, nor linux stuff
    }
   }
}

sub lsnr_log_file
{
    #could have received this information from "lsnrctl show log_file" also, but status shows the resultant log file, made 
    #up of information from log directory and log file. Hence, better suited for our purposes is "lsnrctl status"
    my @command = ("set current_listener $address", "status");
    my $result ;
    my @lines;
    my $log_file;
    my $perm;
    my $permMax;
    my $ownMax = $ENV{'LFOWNMAX'};
    my $permRowNum = 0;
    
    if($^O eq "MSWin32"){
        $permMax = $ENV{'NLFPERMMAX'};
    }else{
        $permMax = $ENV{'LFPERMMAX'};
    }
    
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result
    @lines = split(/\n/,$result);
    foreach (@lines) {
        if (m/Listener Log File(\s+)(.*)/i) {
            $log_file = $2;
            compareOwner("log_file_lsnr_own", $ownMax, $log_file, $tgtOracleHome);
            $perm = file_perm($log_file);
            if($^O eq "linux"){
                if( ($perm >= 0) && compareNegInf($permRowNum, $permMax) ){
                    $perm = $perm & 0777;
                    printf ("em_result=log_file_lsnr_perm|$log_file|%03o\n",$perm);
                    $permRowNum++;
                }
            }
            elsif($^O eq "MSWin32"){
                if(!compareNegInf($permRowNum, $permMax)){
                    return;
                }
                my $win_perm = check_512char(win32_file_perm($log_file));
                if($win_perm != -1) {
                    print "em_result=nt_log_file_lsnr_perm|$log_file|$win_perm\n";
                    $permRowNum++;
                }
            }
            else{
                #neither mswin32, nor linux stuff
            }
        }
    }
}



sub parseFile
{
    my ($configFile) = @_;
    my $CONFIG_FILE_READER;

    if(!-e $configFile)
    {
        print "em_error=File does not exist[$configFile]\n";
        return;
    }

    open($CONFIG_FILE_READER, $configFile);
    if(!(defined $CONFIG_FILE_READER))
    {
        print "em_error=File cound not be open for reading [$configFile]\n";
        return;
    }
    my @info;
    my $line;
    while($line = <$CONFIG_FILE_READER>)
    {
        chomp($line);    
        push(@info,$line);
    }

    close $CONFIG_FILE_READER;
    return @info;
}



sub lsnr_admin_status
{
    my $rowNum = 0;
    my $maxRows = $ENV{'ADMINMAX'};
    if(!compareNegInf($rowNum, $maxRows)){
        return;
    }
    my $paramValue;
    my $line;
    my @info = parseFile($listenerFile);
    if ($@ || $#info < 0) 
    {
        print "em_error=Failed to read listener.ora file\n";
        exit;
    }

    foreach $line (@info)
    {
        #check for the ADMIN_RESTRICTIONS parameter beginning on a
        #new line without any leading whitespace. lsnrctl doesnt
        #recognize the parameter setting otherwise.
        if ($line =~ /^ADMIN_RESTRICTIONS_(.*)/i) 
        {    
            my @nvpair = split('=', $1);
    
            #need to verify presence of '=' and a value after it
            if ($#nvpair == 1) 
            {
                if ($nvpair[0] =~ /^$name\s*$/i)
                {
                    #found ADMIN_RESTRICTIONS_<lsnr_name>
                    $paramValue = $nvpair[1];
                    #trim the leading and trailing spaces
                    $paramValue =~ s/^\s*(.*?)\s*$/$1/;
                    last;
                }
            }
        }
    }

    if(defined($paramValue)  &&  ($paramValue ne "")){
        print "em_result=listenerAdmin|$paramValue\n";
    }
    else{
        print "em_result=listenerAdmin|NONE\n";
    }
    
}

sub remove_dynamic{
    my $CONFIG_FILE_READER;
    my @hosts;
    my $host;
    my %hostHash;#if a host $host is found in listener.ora file, $hostHash{lc($host)} is 1
    open($CONFIG_FILE_READER, $listenerFile);
    if(!(defined $CONFIG_FILE_READER))
    {
        print "em_error=File cound not be open for reading [$listenerFile]\n";
        return @_;
    }
    my $line;
    while($line = <$CONFIG_FILE_READER>)
    {
        $line =~ s/(.*)#(.*)/$1/; #remove commented out characters
        $line =~ s/\s+//g;#remove white space
        if(!($line =~ /host=/i)){
            next;
        }
        $line =~ s/^(.*)\(host=(.*?)\)(.*)$/$2/i;
        $hostHash{lc($line)} = 1;
    }
    close $CONFIG_FILE_READER;
    foreach $host (@_){
        if(defined($hostHash{lc($host)})){
            push(@hosts,$host);
        }
    }
    return @hosts;
}
        
        
sub lsnr_inbound_connect_timeout
{
    my @command = ("set current_listener $address", "show inbound_connect_timeout");
    my $result;
    my $maxRows = $ENV{'INBOUNDMAX'};
    if(isExecutionPossible(\@command))
    {
    eval
    {
        $result = getResult($executable,\@command,$listenerFile,$name);
    };
    if($@)
    {
        print "em_error=Failed to run lsnrctl\n";
        exit;
    }
    ## parse result, extract the relevant line 
    my @resultLines = split(/\n/,$result);
    $result = "";
    for(my $n=0;$n<@resultLines;$n++){
        if($resultLines[$n] =~ /parameter \"inbound_connect_timeout\" set to/){
            $result = $resultLines[$n];
            $result =~ s/(.*)parameter \"inbound_connect_timeout\" set to(\s+)(.*)$/$3/i;
            last;
        }
    }
    if($result eq "")
    {
        return;
    }
    if($maxRows != 0){#if -1, upload all rows, if >0, upload the one row that is possible.
        print "em_result=lsnr_inbound_connect_timeout|$result|NA\n";
    }
    }
}




