#!/usr/local/bin/perl
#
# $Header: emdb/sysman/admin/scripts/adrviewer.pl /st_emdbsa_11.2/10 2010/08/11 22:08:10 fagonzal Exp $
#
# adrviewer.pl
#
# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 
#
#    NAME
#      adrviewer.pl - adrviewer OS Fetchlet
#
#    DESCRIPTION
#      adrviewer is to access adr repository.
#      arguments are as follows
#      $0 : argument for uidriver
#
#    Error codes
#        DIU-59001: uidrvpath does not exist
#        DIU-59002: ccrtoolpath does not exist
#        DIU-59003: Can't open path
#        DIU-59004: Cannot chdir
#        DIU-59005: invalid command
#
#    MODIFIED   (MM/DD/YY)
#    fagonzal    08/09/10 - Changing emCCR.exe to emCCR.bat (bug 9967178)
#    fagonzal    07/29/10 - Changing OCM classpath
#    mappusam    02/24/10 - Backport mappusam_bug-6965447 from main
#    fagonzal    02/08/10 - Adding OH/bin to path before invoking uidrvci (bug 9204749)
#    fagonzal    10/15/09 - Fixing java invocation, classpath, for package
#                           upload command
#    balnaff     05/11/09 - bug 7272399
#    balnaff     01/29/09 - bug 8208062
#    balnaff     12/17/08 - bug 7651085
#    fagonzal    04/01/08 - Removing remote correlation key check before
#                           creating remote package
#    dchakumk    03/10/08 - XbranchMerge dchakumk_6752_xbmsrc from
#                           st_emdbsa_11.1
#    balnaff     01/25/08 - bug 6732588
#    fagonzal    12/19/07 - Fixing bug that prevented sweep command from
#                           executing
#    jsoule      08/29/07 - remove unnecessary EM_TARGET_ADR_BASE parameter
#    balnaff     07/01/07 - adding ml creds
#    balnaff     05/15/07 - 
#    loliu       05/21/07 - Disabled output TRACE for showXMLTrace and
#                           showTraceSection
#    jsoule      04/20/07 - enable package name, description
#    jsoule      04/12/07 - use backslash to find uidrvci.exe
#    keiwong     04/03/07 - fix bug 5898320
#    loliu       03/25/07 - Changed adrviewer.pl to use target ADR base and
#                           home from environment
#    jsoule      03/15/07 - copy temp file creation
#    jsoule      03/09/07 - add modified createPackageCorrelated
#    jsoule      03/03/07 - add remote packaging special cases
#    keiwong     01/09/07 - fix bug 5750178
#    keiwong     12/04/06 - fix bug 5678573
#    hopark      10/25/06 - add package state change
#    hopark      10/10/06 - add upload
#    hopark      10/05/06 - add quick packaging
#    hopark      09/19/06 - return manifest
#    hopark      07/30/06 - change adrbase
#    hopark      05/09/06 - Creation
# 

require "semd_common.pl";
require "emd_common.pl";
require "adr_common.pl";

use Time::Local;
use IPC::Open2;
use File::Spec;
#use Time::HiRes;

# default the max trace file size is 5MB
$MAX_TRACE_SIZE = 5 * 1024 * 1024;
if ($ENV{EMAGENT_PERL_TRACE_FILESIZE} ne "")
{
    $MAX_TRACE_SIZE = $ENV{EMAGENT_PERL_TRACE_FILESIZE} * 1024;
}

$NT = 0;
if ($^O =~ /MSWin32/i){
    $NT = 1;
}

# package state
#$pkgstat_package = 4;
$pkgstat_upload = 6;

# declare stdinArgs early.
my %stdinArgs;

sub parse_csv {
    my $text = shift;      # record containing comma-separated values
    my @new  = ();
    push(@new, $+) while $text =~ m{
        # the first part groups the phrase inside the quotes.
        # see explanation of this pattern in MRE
        "([^\"\\]*(?:\\.[^\"\\]*)*)",?
           |  ([^,]+),?
           | ,
    }gx;
    push(@new, undef) if substr($text, -1,1) eq ',';
    return @new;      # list of values that were comma-separated
}

sub trim {
    my $string = shift(@_);
    $string =~ s/\s//g;
    return $string;
}

################################
# -- BEGIN WORKAROUND --
# This routine works around bug 5924743 by stopping processing
# an input variable when __EndProp__ is seen (rather than just skipping it).
sub get_stdinvars_workaround
{
    my %r;
    while(<STDIN>)
    {
	if(/(.*)=(.*)/)
	{
	    if($2 eq "__BeginProp__")
	    {
		while(<STDIN>)
		{
		    if($_ ne "__EndProp__\n")
		    {
			$r{"$1"} .= "$_";
		    }
else { last; }
		}
	    }
	    else
	    {
		$r{"$1"} = "$2"; 
	    }
	}
    }
    return %r;
}
# -- END WORKAROUND --
################################

sub invokeCmd {
    @fields = parse_csv($args);
    $cmd = shift(@fields);
    TRACE("cmd = $cmd\n");

    if (!$use_arglist) {
        TRACE("args = $args\n");
    }

    if ($cmd eq "getDefaultADRHome") {
        TRACE("$target_adrhome\n");
        print "$target_adrhome\n";
        return;
    }

    $adrid = shift(@fields);
    
    if ($cmd eq "checkFileExist") {
        $path = shift(@fields);
        $result = 0;
        if (-e $path) {
            $result = 1;
        }
        print $result;
        return;
    }

    if ($cmd eq "readFile") {
        $path = shift(@fields);
        open F, "< $path" or die "ERROR,DIU-59003: Can't open $path : $!";
        my @f = <F>;
        close F;      
        print @f;
        return;
    }

    if ($cmd eq "quickPackage") {
        # quickPackage pkgId pkgMode path sr mlusername mlpwd mlcsi mlcc mlseed
        # This command is only used for DiagJob
        # The output of this command will not be parsed by ADRViewer.java
        # Print out as much as information.
        my $ccrIndex = 2;
        my @adrArgs = @fields[0 .. $ccrIndex];
        unshift(@adrArgs,"generatePhysicalPackage");
        unshift(@adrArgs,$adrbase);
        TRACE("adrArgs = @adrArgs\n");
        my $sr = $fields[3];
        my $mlun = $fields[4];
        my $mlpw = $fields[5];
        my $mlcsi = $fields[6];
        my $mlcc = $fields[7];
        my $mlseed = $fields[8];
        if (invokeADR(@adrArgs) == 0) {
            print("\nSuccessfully generated physical package\n");
            # Get package name
            my $pkgid = $adrArgs[2];
            my @getPkgArgs = ();

            # This logic has a tight dependency to ips_package_history relation.
            # If ips_package_history relation is changed, this should be changed
            # too.
            # Better way to handle this is to return the new package name from
            # generatePhysicalPackage api.
            # Currently IPS does not return new package name.
            # However, we can implement this logic in uidrvci.
            # ....
            push(@getPkgArgs, $adrbase); #adrbase
            push(@getPkgArgs, "query");
            push(@getPkgArgs, "ips_package_history");
            push(@getPkgArgs, "package_id=".$pkgid);
            push(@getPkgArgs, "ARCHIVE_TIME"); #sort_key
            push(@getPkgArgs, 0); #descending sort
            push(@getPkgArgs, -1); #id index
            push(@getPkgArgs, 1); #fetch
            invokeADR(@getPkgArgs);

            my $pkgName = "";
            my $seq = "";
            my $resultsize = @results;

            if ($resultsize > 0) {
                my $line = $results[0];
                TRACE("$line\n");
                my @cols = parse_csv($line);
                my $colsize = @cols;
                if ($colsize >= 7) {
                    $pkgName = $cols[7];
                    $seq = $cols[2];
                }
            }

            if ($pkgName eq "") {
                print("Failed to get the physical package name for package_id=$pkgid\n");
            } else {
                print("Upload package : $sr,$pkgName\n");
                my @ccrArgs = ();
                push(@ccrArgs,"upload");
                push(@ccrArgs,$pkgId);
                push(@ccrArgs,$sr);
                push(@ccrArgs,$pkgName);
                push(@ccrArgs,$seq);
                push(@ccrArgs,$mlun);
                push(@ccrArgs,$mlpw);
                push(@ccrArgs,$mlcsi);
                push(@ccrArgs,$mlcc);
                push(@ccrArgs,$mlseed);
                TRACE("ccrArgs = @ccrArgs\n");
                my $rc = invokeCCR(@ccrArgs);
                print "\n";
                for ($i = 0; $i < @results; $i++) {
                  my $line = @results[$i];
                  print $line;
                }
            }
        } else {
            print("Failed to generated physical package\n");
        }
        exit;
    }

    if ($cmd eq "uploadPhysicalPackage") {
        unshift(@fields, "upload");
        invokeCCR(@fields);
        exit;
    }

    unshift(@fields,$cmd);
    unshift(@fields,$adrbase);

    ################################
    # special case command processing for correlation key APIs
    #
    if ($cmd eq "getRemoteCorrKeysFromPackage") {
        # create temp file for ips to populate with correlated-key data
        my $corrKeysXMLFile = create_temp_file(".xml");
        push(@fields, $corrKeysXMLFile);
    } elsif ($cmd eq "createPackageCorrelated") {
        invokeCreatePackageCorrelated(@fields);
        return; # do not call invokeADR
    } elsif ($cmd eq "useRemoteCorrKeysFromPackage" ||
             $cmd eq "checkRemoteCorrKeysFromPackage") {
        invokeCmdRemoteCorrKeysFromPackage(@fields);
        return; # do not call invokeADR
    }
    #
    # end special case command processing
    ################################

    invokeADR(@fields);
}

sub invokeCCR() {
    my @fields = @_;
    my $cmd = shift(@fields);
    my $pkgId = shift(@fields);
    my $sr = shift(@fields);
    my $pkgs = shift(@fields);
    my $seqs = shift(@fields);
    my $mlun = shift(@fields);
    my $mlpw = shift(@fields);
    my $mlcsi = shift(@fields);
    my $mlcc = shift(@fields);
    my $mlseed = shift(@fields);

    TRACE("sr = $sr, mlun = $mlun, mlpw = $mlpw\n");
    TRACE("mlcsi = $mlcsi, mlcc= $mlcc, mlseed= $mlseed\n");
    TRACE("pkgs = $pkgs, seqs=$seqs\n");

    # Setting up classpath for invoking OCMAccess. OCMAccess is in emcoreAgent.jar. 
    # We also need emocmclnt.jar, http_client.jar and regexp.jar
    my $sysmanjlibdir = $myorahome.$separator."sysman".$separator."jlib".$separator;
    my $sysmanjlibocmdir = $sysmanjlibdir."ocm".$separator;
    my $classpath = $sysmanjlibdir."emocmclnt.jar".$classpath_separator.$sysmanjlibdir."emocmcommon.jar".$classpath_separator.$sysmanjlibocmdir."log4j-core.jar".$classpath_separator.$sysmanjlibocmdir."regexp.jar".$classpath_separator.$sysmanjlibocmdir."http_client.jar".$classpath_separator.$sysmanjlibdir."emcoreAgent.jar";
    TRACE("Classpath: $classpath\n");

    #constructing the java command, which takes two arguments: the agent home and the target home. It tries the agent home first to see
    # if the OCM there is configured. If it is not, it'll try the DB home.
    my $java_binary = $ENV{JAVA_HOME}.$separator."bin".$separator."java";
    my $java_command = "$java_binary -classpath $classpath oracle.sysman.eml.swb.framework.emagentAccess.OCMAccess $myorahome $orahome";
    TRACE("Command: $java_command\n");

    open(LOGFILE, ">>$tracefile");
    open(SAVEERR, ">&STDERR");
    open(STDERR, ">>&LOGFILE");
    open(SAVEOUT, ">&STDOUT");
    open(STDOUT, ">>&LOGFILE");

    #invoking the command. The output is the OCM config path, the error thrown, or both.
    open(BUFP, "$java_command |");
    @results = ();
    while (<BUFP>) {
        my $line = $_;
        TRACE("$line");
        push(@results, $line);
    }

    close(BUFP);
    my $exitcode = $?;
    #retriving the exit code from the java command. It should be in the second byte.
    my $ec = ($exitcode>>8) & 127;

    #the exit code is divided into two parts: agent exit code, and target exit code like this: tttaaa
    my $agent_ec = $ec & 7;
    my $target_ec = $ec >>3;
    TRACE("ec = $ec\n");
    TRACE("agent_ec = $agent_ec\n");
    TRACE("target ec = $target_ec\n");
    my $ccrpath = $orahome.$separator."ccr";
    my $resultcode = 1;

    #if we do have a successful invocation, the last line of the output is the config path
    if($agent_ec==0||$target_ec==0) {
        my $ressize = $results;
        $ccrpath = trim(@results[$ressize-1]);
    } else {
        #otherwise, we want to throw the correct error. Since the OMS expects certain exit codes, we have to convert the
        #exit code we got from OCMAccess to the correct OMS exit codes
        if($agent_ec==2) {
            #OCM not configured
            $resultcode = 100;
        } elsif($agent_ec==3) {
            #Invalid OCM state
            $resultcode = 101;
        } elsif($agent_ec==4) {
            #File not found
            $resultcode = 102;
        } elsif($agent_ec==5) {
            #Path exception
            $resultcode = 8;
        } elsif($agent_ec==6||$agent_ec==1) {
            #other exception or incorrect usage
            $resultcode = 56;
        }
        close(STDOUT);
        open(STDOUT, ">&SAVEOUT");
        close(STDERR);
        open(STDERR, ">&SAVEERR");
        print $resultcode;
        return $resultcode;
    }

    my $ccrdir = $ccrpath.$separator."state";
    TRACE("ccrdir = $ccrdir\n");

    chdir($ccrdir) || die "ERROR,DIU-59004: Cannot chdir $ccrdir: $!";

    my $first  = "diagnostic";
    my $second = "$sr";
    if(!(-d $first)) {
      mkdir($first, 0750) || die "Cannot mkdir $first: $!";
    }
    chdir($first) || die "Cannot chdir $first: $!";
    if(!(-d $second)) {
      mkdir($second, 0750) || die "Cannot mkdir $second: $!";
    }
    chdir($second) || die "Cannot chdir $second: $!";

    my $crd_dir = $ccrdir.$separator.$first.$separator.$second.$separator;
    my $crd_file = $crd_dir.$sr.".crd";
    TRACE("sr file: $crd_file\n");

    my $ccrhome = $agent_ec==0?$agent_ccrhome:$target_ccrhome;

    if (!-e $ccrhome) {
        print SAVEOUT "ERROR,DIU-59002: $ccrhome does not exist\n";
        exit;
    }

    chdir($ccrhome)  || die "ERROR,DIU-59004: Cannot chdir $ccrhome: $!";

    if ($cmd eq "upload") {
        my $ccrtoolpath = $ccrhome . "/emCCR";
        my $ccrtool = "./emCCR";

        if ($NT) {   
            $ccrtoolpath = $ccrhome . "\\emCCR.bat";
            $ccrtool = ".\\emCCR.bat";
        }

        if (!-e $ccrtool) {
            print SAVEOUT "ERROR,DIU-59002: $ccrtoolpath does not exist\n";
            exit;
        }

        @results = ();
        my @pkgfiles = parse_csv($pkgs);
        my @pkgseqs = parse_csv($seqs);
        $resultcode = 0;

        for ($i = 0; $i < @pkgfiles; $i++) {
            my $pkg = @pkgfiles[$i];
            my $seq = @pkgseqs[$i];

            open(CRD, ">$crd_file");
            print CRD "CRD_VERSION=1.0\n";
            print CRD "METALINK_USER=$mlun\n";
            print CRD "METALINK_PSWD=$mlpw\n";
            print CRD "CRYPT_SEED=$mlseed\n";
            print CRD "METALINK_CSI=$mlcsi\n";
            print CRD "METALINK_CC=$mlcc\n";
            close(CRD);

            my $cmdline = "$ccrtoolpath upload -nointeractive -diagnostic=SR=".$sr.",FILE=".$pkg; 
            TRACE("$cmdline\n");
            open(BUFP, "$cmdline |");

            while (<BUFP>) {
                my $line = $_;
                TRACE("$line");
                push(@results, $line);
            }

            close(BUFP);
            $ec = $?;
            $exitcode = $ec >> 8;
            my $sig = $ec & 127;
            my $has_coredump = $ec & 128;

            if ($exitcode == 0) {
                setPackageState($adrbase, $pkgId, $seq, $pkgstat_upload);        
            }

            if ($resultcode eq 0) {
                $resultcode = $exitcode;
            }
        }
        close(STDOUT);
        open(STDOUT, ">&SAVEOUT");
        TRACE("resultcode = $resultcode\n");
        print $resultcode;
    } else {
        close(STDOUT);
        open(STDOUT, ">&SAVEOUT");
        print("ERROR,DIU-59005: invalid command '$cmd'\n");
    }
    close(STDERR);
    open(STDERR, ">&SAVEERR");
    return $resultcode;
}

#
# getCorrKeys
#  Pull the correlation keys from stdin arguments, populate a temp file with
#  them.  Return the filename of the temp file.
#
sub getCorrKeys()
{
    # populate temp file with correlated-key data for ips
    $corrKeysXMLFile = create_temp_file(".xml");
    open(F, ">$corrKeysXMLFile")
        or die "ERROR,DIU-59003: Can't open temp file : $!";
    # use ARGLIST (i.e., these operations cannot be performed in batch)
    print {F} ($stdinArgs{"ARGLIST"});
    close(F);
    return $corrKeysXMLFile;
}

#
# invokeCreatePackageCorrelated
#  This routine intercepts a createPackageCorrelated invocation from the OMS
#  This processing is necessary to avoid making many OMS->Agent calls.
#
# $adrBase the adr base
# $createCmd should be createPackageCorrelated
# $name name of the main package
#
sub invokeCreatePackageCorrelated()
{
    my ($adrBase, $createCmd, $name) = @_;
    my $output = '';
    my $corrKeysXMLFile = getCorrKeys();

    # redirect printing to the trace file -- this suppresses invokeADR output.
    # if tracing is disabled, attempt to trace to /dev/null
    TRACE("Redirecting output to the log.\n");
    if (EMAGENT_isPerlDebugEnabled() || !open(LOG, ">/dev/null"))
    {
      open(LOG, ">>$tracefile");
    }
    select(LOG);

    # correlated keys apply; continue with the create
    invokeADR($adrBase,
              $createCmd
              ,$name
              ,"correlated_package on instance $ENV{ORACLE_SID}"
             );
    $output = $results[0];

    if (!($results[0] =~ /ERROR/))
    {
        # no error indicates success;
        # output has now been determined, unless errors below
        my ($relation, $corrPackageID, $corrADRHome) =
            parse_csv($results[0]);
        invokeADR($adrBase,
            "useRemoteCorrKeysFromPackage",
            $corrPackageID,
            $corrKeysXMLFile);

        if ($results[0] =~ /ERROR/)
        {
            # error in useRemoteCorrKeysFromPackage"; report it and clean up
            TRACE("error populating package; cleaning up...\n");
            $output = $results[0];
            invokeADR($adrBase, "deletePackage", $corrPackageID);
        }
    }

    # restore printing to STDOUT.
    select(STDOUT);

    # the result
    print $output;
}

#
# invokeCmdRemoteCorrKeysFromPackage
#  This routine intercepts a use/checkCorrKeysFromPackage invocation from the
#  client.
#  It adds a temporary correlation key file to the end of the args.
#
sub invokeCmdRemoteCorrKeysFromPackage()
{
    my @fields = @_;
    push (@fields, getCorrKeys());
    invokeADR(@fields);
}

sub setPackageState() {
    my $adrbase = shift(@_);
    my $pkgId = shift(@_);
    my $seq = shift(@_);
    my $pkgstate = shift(@_);
    
    my @fields = ();
    push(@fields, $adrbase);
    push(@fields, "updatePackageUploadStatus");
    push(@fields, $pkgId);
    push(@fields, $seq);
    push(@fields, $pkgstate);
    invokeADR(@fields);
    
    # format time in  2006-10-25 16:16:01 GMT-07:00
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
    my $offset  = sprintf "%.1f", (timegm(localtime) - time) / 3600;
    my $minutes = sprintf "%02d", abs( $offset - int($offset) ) * 60;
    $timestr =
        sprintf ("%4d-%02d-%02d %02d:%02d:%02d GMT%+03d:%02d",
            $year+1900,$mon+1,$mday,$hour,$min,$sec,int($offset), $minutes);
    @fields = ();
    push(@fields, $adrbase);
    push(@fields, "setPackageUploadTime");
    push(@fields, $pkgId);
    push(@fields, $seq);
    push(@fields, $timestr);
    invokeADR(@fields);
}

#
#  Function:    sweepADR
#  Description: check whether ADR should be swept and do so when necessary.
#  Arguments:   $_[0] = target's adrbase
#               $_[1] = target's adrhome
#               $_[2] = target's oracle_home
#               $_[3] = arg to adrci sweep directive
#
sub sweepADR
{
  my $adr_base    = shift(@_);
  my $adr_home    = shift(@_);
  my $oracle_home = shift(@_);
  my $sweep       = shift(@_);

  my $adr_homepath = "";
  if ($sweep && $adr_base)
  {
    $regexp = quotemeta("$adr_base$separator");
    if ($adr_home =~ /$regexp(.*)/)
    {
      $adr_homepath = $1;
      $adrciexe  = "$oracle_home$separator"."bin$separator".
                   ($NT ? "adrci.exe" : "adrci");
      $adrscript = "exec=\"set base $adr_base;".
                          "set homepath $adr_homepath;".
                          "sweep $sweep\"";
      TRACE("Sweeping ADR with [$adrciexe $adrscript]\n");
      if (system("$adrciexe $adrscript"))
      {
        # TODO: this should be error level
        TRACE("ADR sweep failed; error code: ".($?>>8).
              " signal: ".($?&255)." error: $!\n");
      }
    }
  }
}

sub invokeADR() {
    my @fields = @_;
    my $adrbase = shift(@fields);
    my $cmd = shift(@fields);
    my $arguments = "$cmd";

    foreach (@fields) {
        $arg = $_;

        if ($arguments) {
            $arguments .= ",";
        }

        if ($arg eq "_TEMP_") {
            $arg = $temp_folder;
        }

        if ($arg =~ m/(,)/) {
            $arguments .= "\"" . $arg . "\"";
        } else {
            $arguments .= $arg;
        }
    }

    # identify the XML file for getRemoteCorrKeysFromPackage
    my $corrKeysXMLFile = '';

    if ($cmd eq "getRemoteCorrKeysFromPackage") {
        $corrKeysXMLFile = $fields[$#fields];
    }

    my $uidrv = "$uidrvhome/uidrvci";

    if ($NT) {   
        $uidrv = "$uidrvhome\\uidrvci.exe";
    }

    if (!-e $uidrv) {
        print "ERROR,DIU-59001: $uidrv does not exist\n";
        exit;
    }
    
    TRACE("$uidrv -uidrv_adrbase=$uidrv_adrbase -target_adrhome=$target_adrhome\n");

    if ($use_arglist) {
        TRACE("command: $cmd\n");
    } else {
        TRACE("command: $arguments\n");
    }

    my $pid;

    eval
    {    
        $pid = open2(*BUFP, *INPUT, "$uidrv -uidrv_adrbase=$uidrv_adrbase -target_adrhome=$target_adrhome");
    };

    if ($@)
    {    
        print "adrviewer.pl: unexpected error $@";
        return $?;
    }

    print INPUT "$arguments\n";
    print INPUT "\n"; # need this for uidrvci to exit
    close(INPUT);

    @results = ();

    $isTraceCmd = 0;
    if (($cmd eq "showXMLTraceMap") || ($cmd eq "showTraceSection")) {
      $isTraceCmd = 1;
    }
    while( <BUFP> ) {
        my $line = $_;

        # bug 9258685. On Windows, a CR char is seen before the newline
        # Working around this by stripping each line of whitespace
        $line =~ s/^\s+//; # remove leading spaces
        $line =~ s/\s+$//; # remove trailing spaces (including newlines)
        $line .= "\n";     # add a newline

        if (!$isTraceCmd) {
          TRACE("$line");
	}

        ################################
        # special case output for getRemoteCorrKeysFromPackage
        # on success, XML file contents are returned
        #
        if ($cmd eq "getRemoteCorrKeysFromPackage" && # command
            $line == 1 &&                             # success
            $corrKeysXMLFile) {                       # unspooled file

            if (!open(F, "< $corrKeysXMLFile")) {
                print "ERROR,DIU-59003: Can't open temp correlation key file : $!";
            } else {
                while (<F>) { print; }
                close(F);
            }

            # we tried once; don't try again
            $corrKeysXMLFile = '';
        }
        #
        # end special case output
        ################################
        else {
            # standard operating procedure
            print $line;
        }

        push(@results, $line);
    }

    close(BUFP);
    # need to avoid running out of resource in NT
    waitpid($pid, 0);

    my $ec = $?;
    my $exitcode = $ec >> 8;
    my $sig = $ec & 127;
    my $has_coredump = $ec & 128;
    return $exitcode;
}

$orahome = trim($ENV{"EM_TARGET_ORACLE_HOME"});
$sid = trim($ENV{"EM_TARGET_ORACLE_SID"});
$args =  "";

foreach $argnum (0 .. $#ARGV) {
    if ($args ne "") {
        $args .= " ";
    }
    $args .= $ARGV[$argnum];
}

$myorahome = trim($ENV{'ORACLE_HOME'});
$separator = $NT ? "\\" : "\/";
$classpath_separator = $NT ? ";":":";

if ($ENV{EMAGENT_PERL_TRACE_DIR} ne "") {
    $tracefile = $ENV{EMAGENT_PERL_TRACE_DIR}.$separator."adrviewer.log";
    $backup_tracefile = $ENV{EMAGENT_PERL_TRACE_DIR}.$separator.".adrviewer.log";
}

my $state_root = "";

if ($ENV{EMSTATE} ne "") {
    $state_root = $ENV{EMSTATE};
} elsif ($ENV{EMDROOT} ne "") {
    $state_root = $ENV{EMDROOT};
} elsif ($ENV{EM_AGENT_STATE_DIR} ne "") {
    $state_root = $ENV{EM_AGENT_STATE_DIR};
}

if ($state_root ne "" && -d $state_root) {
    $temp_folder = $state_root.$separator."sysman".$separator."emd".$separator."state".$separator;

    if ($tracefile eq "") {    
        $tracefile = $state_root.$separator."sysman".$separator."log".$separator."adrviewer.log";
        $backup_tracefile = $state_root.$separator."sysman".$separator."log".$separator.".adrviewer.log";
    }
} else {
    chdir($myorahome) || die "Cannot chdir $myorahome: $!";
    my $firstdir = "sysman";
    my $seconddir = "log";

    if (!(-d $firstdir)) {
        mkdir($firstdir, 0750) || die "Cannot mkdir $firstdir: $!";
    }

    chdir($firstdir) || die "Cannot chdir $firstdir: $!";

    if (!(-d $seconddir)) {
        mkdir($seconddir, 0750) || die "Cannot mkdir $seconddir: $!";
    }

    $temp_folder = $myorahome.$separator.$firstdir.$separator.$seconddir.$separator;

    if ($tracefile eq "") {    
        $tracefile = $temp_folder."adrviewer.log";
        $backup_tracefile = $temp_folder."adrviewer.log";
    }
}

my $tracesize = -s $tracefile;
if ($tracesize > $MAX_TRACE_SIZE) {
    if (!rename($tracefile, $backup_tracefile)) {
        EMAGENT_PERL_WARN("Could not rename file $trace_file : $!\n");
        unlink($tracefile);
    }
}

TRACE("orahome : $orahome\n");
TRACE("myorahome : $myorahome\n");
TRACE("sid : $sid\n");
TRACE("args = $args\n");
TRACE("temp_folder = $temp_folder\n");

$target_adrbase = $ENV{"EM_TARGET_ADR_BASE"};
$target_adrhome = $ENV{"EM_TARGET_ADR_HOME"};
TRACE("EM_TARGET_ADR_BASE = $target_adrbase\n");
TRACE("EM_TARGET_ADR_HOME = $target_adrhome\n");
$sweep = $ENV{"EM_TARGET_SWEEP"};
TRACE("EM_TARGET_SWEEP = $sweep\n");

$uidrv_adrbase = File::Spec->catdir($orahome, "log");
$uidrvhome = File::Spec->catdir($orahome, "bin");
$uidrvlib = File::Spec->catdir($orahome, "lib");
$target_ccrhome = File::Spec->catdir($orahome, "ccr", "bin");
$agent_ccrhome = File::Spec->catdir($myorahome, "ccr", "bin");

TRACE("NT = $NT\n");

################################
# -- BEGIN WORKAROUND --
# Restore the following line to get_stdinvars when the workaround for bug
# 5924743 is no longer necessary.
%stdinArgs = get_stdinvars_workaround();
#%stdinArgs = get_stdinvars();
# -- END WORKAROUND --
################################

@requests = ();
$use_arglist = 0;

if ($args eq "ARGLIST") {
    my $arglist = $stdinArgs{"ARGLIST"};
    @requests = split('\n', $arglist);
    $use_arglist = 1;
} else {
    push(@requests, $args);
}

@results = ();

# setup the environment
if ($orahome ne "") {
    $ENV{'ORACLE_HOME'} = $orahome;
}

if ($sid ne "") {
    $ENV{'ORACLE_SID'} = $sid;
}

if ($NT) {
    my $ldpath = $ENV{'PATH'};
    $ldpath = "$uidrvhome;$uidrvlib;$ldpath";
    $ENV{'PATH'} = $ldpath;
} else {
    my $sep_token = get_shared_lib_path_separator();
    my $current_lib_path = get_complete_lib_path();
    my $new_lib_path = "$uidrvlib"."$sep_token"."$current_lib_path";
    set_complete_lib_path("$new_lib_path");

    my $path = $ENV{'PATH'};
    $path = "$uidrvhome"."$sep_token"."$path";
    $ENV{'PATH'} = $path;
}

# Conditionally sweep ADR.
sweepADR($target_adrbase, $target_adrhome, $orahome, $sweep);

if ($args ne "") {
    for ($i = 0; $i < @requests; $i++) {

        $args = @requests[$i];
        $args =~ s/&#061/=/g;
        $args =~ s/&#044/,/g;
        $args =~ s/&#034/"/g;
        $args =~ s/&#039/'/g;

        if ($args =~ m/^EM_TARGET/) {
            $args = "";
        }

        if ($args ne "") {
            invokeCmd;

            if (($i + 1) < @requests) {
                print "RESP\n";
            }
        }       
    }
}

exit;
