#!/bin/sh
#! -*- perl -*-
eval 'exec /usr/bin/perl -x $0 ${1+"$@"} ;'
if 0;
  
$| = 1;
  
use File::Basename;
BEGIN {
  $scriptdir = &File::Basename::dirname($0);
  # May want to use shift to put it at the beginning
  push @INC, "$scriptdir/../lib/";
}
 

#
# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
# This software is the proprietary information of Sun Microsystems, Inc.
# Use is subject to license terms.
# 
# Copyright 2004 Sun Microsystems, Inc.  Tous droits rservs.
# Ce logiciel est proprit de Sun Microsystems, Inc.
# Distribu par des licences qui en restreignent l'utilisation.
#
# ident        "@(#)mfwkadm 1.17     04/09/06 SMI"
#
#

# Solaris 8 does not have Gettext in standard
# We provide our own implem
use JesmfGettext;
use JesmfMessages;


use Getopt::Long;
use POSIX;

#-------------------------------------------------
#  Usage
#-------------------------------------------------


sub usage
{
  printMessage ($JesmfMessages::MFWK_USG1);
  printMessage ($JesmfMessages::MFWK_USG2);
  printMessage ($JesmfMessages::MFWK_USG3);
  printMessage ($JesmfMessages::MFWK_USG4);
  printMessage ($JesmfMessages::MFWK_USG5);
  printMessage ($JesmfMessages::MFWK_USG6);
  printMessage ($JesmfMessages::MFWK_USG7);
  printMessage ($JesmfMessages::MFWK_USG8);
  printMessage ($JesmfMessages::MFWK_USG9);
  printMessage ($JesmfMessages::MFWK_USG10);
  printMessage ($JesmfMessages::MFWK_USG11);
  printMessage ($JesmfMessages::MFWK_USG12);
  printMessage ($JesmfMessages::MFWK_USG13);
  printMessage ($JesmfMessages::MFWK_USG14);
  printMessage ($JesmfMessages::MFWK_USG15);
  printMessage ($JesmfMessages::MFWK_USG16);
  printMessage ($JesmfMessages::MFWK_USG17);
  printMessage ($JesmfMessages::MFWK_USG18);
  printMessage ($JesmfMessages::MFWK_USG19);
  printMessage ($JesmfMessages::MFWK_USG20);
  printMessage ($JesmfMessages::MFWK_USG21);
  printMessage ($JesmfMessages::MFWK_USG22);
  printMessage ($JesmfMessages::MFWK_USG23);
  printMessage ($JesmfMessages::MFWK_USG24);
  printMessage ($JesmfMessages::MFWK_USG25);
  printMessage ($JesmfMessages::MFWK_USG26);
  printMessage ($JesmfMessages::MFWK_USG27);
  printMessage ($JesmfMessages::MFWK_USG28);
  printMessage ($JesmfMessages::MFWK_USG29);
  printMessage ($JesmfMessages::MFWK_USG30);
}


#-------------------------------------------------
#  Command line subcommand parsing
#-------------------------------------------------
sub ParseSubCommands (@)
{
  $true=1;

# we just parse the args that remain after the getoptions
# parsing is very basic and just sets variables corresponding
# to subcommands.
# we do not check subcommands consistency at this level

# the only thing being checked is the case of job creation
# where we can have multiple object
# command consistency has to be checked @ this level.
 
  @allargs = @_;
  
  $firstarg = shift @_;

  # agent subcommands (start/stop/restart/config)

  if ($firstarg eq "start") {
      $agent = $true;
      $start = $true;
  }
  
  if ($firstarg eq "stop") {
      $agent = $true;
      $stop = $true;
  }
  if ($firstarg eq "restart") {
      $agent = $true;
      $restart = $true;
  }
  if ($firstarg eq "list-params") {
      $agent = $true;
      $config = $true;
  }


  # module subcommands
  if ($firstarg eq "info") {
    $module = $true;   
    $info = shift @_;
  }
  if ($firstarg eq "list-modules") {
    $module = $true;   
    $list = $true;      
  }
 
  # perfjob subcommands (list/info/create/delete/suspend/resume)
  if ($firstarg eq "pm-job") {
    $perfjob = $true;
    $secondarg = shift @_;
    if ($secondarg eq "list") {
      $list = $true;
    }
    if  ($secondarg eq "info") {
      $info = shift @_;
    }
    if  ($secondarg eq "delete") {
      $delete = shift @_;
    }
    if  ($secondarg eq "suspend") {
      $suspend = shift @_;
    }
    if  ($secondarg eq "resume") {
      $resume = shift @_;
    }
    if ($secondarg eq "create") {
      $create = shift @_;
      $thirdarg = shift @_;
      if  ($thirdarg =~ /^granularity=/) {
        $granularity = $';
        while (@_) {
          $ntharg = shift @_;
          if ($ntharg =~ /^object=/) {
            $newobject = $';
            if (defined ($newobject)) {
              push @object,$newobject;
	    } else {
              debug ("object empty");
              error_usage();
	    }
	  } else {
            # at this point only object arg should remain.
            # if not it the cli is wrong
            debug ("object loop");
            error_usage();
	  }
	}
      }             
    }
  }

  # opstatusjob subcommands (list/info/create/delete/suspend/resume)
  if ($firstarg eq "opstat-job") {
    $opstatusjob = $true;
    $secondarg = shift @_;
    if ($secondarg eq "list") {
      $list = $true;
    }
    if  ($secondarg eq "info") {
      $info = shift @_;
    }
    if  ($secondarg eq "delete") {
      $delete = shift @_;
    }
    if  ($secondarg eq "suspend") {
      $suspend = shift @_;
    }
    if  ($secondarg eq "resume") {
      $resume = shift @_;
    }
    if ($secondarg eq "create") {
      $create = shift @_;
      $thirdarg = shift @_;
      if  ($thirdarg =~ /^granularity=/) {
        $granularity = $';
        while (@_) {
          $ntharg = shift @_;
          if ($ntharg =~ /^object=/) {
            $newobject = $';
            if (defined ($newobject)) {
              push @object,$newobject;
	    } else {
              debug ("object empty");
              error_usage();
 	    }
	  } else {
            # at this point only object arg should remain.
            # if not it the cli is wrong
            debug ("object loop");
            error_usage();
	  }
	}
      }             
    }
  }

  
}

sub CheckSubCommandsConsistency() {

if ($help) {
     debug ("help");
     usage();
     exit(0);
  } elsif (!($agent xor $module xor $perfjob xor $opstatusjob)) {
     debug ("agent | module | pm-job | opstat-job missing");
     error_usage();
  } elsif ($agent && (!($start xor $stop xor $restart xor $config))) {
     debug ("agent");
     error_usage();
  } elsif ($module && (!($list xor defined ($info) ))) {
     debug ("module");
     error_usage();
  } elsif ($perfjob &&     (!($list xor defined ($info) xor defined ($delete) xor defined ($suspend) xor defined ($resume) xor (defined ($create) && defined ($granularity) && defined (@object))))) {
     debug ("perfjob");
     error_usage();
  } elsif ($opstatusjob && (!($list xor defined ($info) xor defined ($delete) xor defined ($suspend) xor defined ($resume) xor (defined ($create) && defined ($granularity) && defined (@object))))) {
     debug ("opstatusjob");
     error_usage();
  }

}


#-------------------------------------------------
#  Command line parsing
#-------------------------------------------------
sub ParseCommandLineArgs (@)
{   

  $result = GetOptions ('help|?'       => \$help,		      
                        "debug"          => \$debug,	    		    	    		  
 		     ) or error_usage();

  # ARGV does not contain options anymore, only subcommands (not "--" or "-" prefixed)
  # we parse it, set global variables accordingly and check consistency of what has been set
  &ParseSubCommands(@ARGV);

  debug ("\
          help         => $help\ 
          debug        => $debug\ 
          agent        => $agent\ 
	  start        => $start\
          stop         => $stop\ 
          restart      => $restart\ 
          config       => $config\ 
          module       => $module\ 
          pm-job       => $perfjob\ 
          opstat-job   => $opstatusjob\ 
          list         => $list\ 
          info         => $info\ 
          create       => $create\ 
          granularity  => $granularity\ 
          object       => @object\ 
          delete       => $delete\ 
          suspend      => $suspend\ 
          resume       => $resume");

  # check the combination of subcommands is consistent
  &CheckSubCommandsConsistency();		    	 
}



#-------------------------------------------------
#  Set Cacao Paths And Commands
#-------------------------------------------------
sub SetCacaoPathsAndCommands
{

  ($OS, $nodename, $release, $version, $machine) = POSIX::uname();
  debug ("OS $OS");

  # solaris 
  if ($OS eq "SunOS") { 
    $CACAO_ROOT       = "/opt/SUNWcacao/";
    $CACAOCSC = "$CACAO_ROOT/lib/tools/cacaocsc";
    $CACAOADM = "$CACAO_ROOT/bin/cacaoadm";
    $CACAO_CONFIG_DIR = "/etc/opt/SUNWcacao/";
    $SECURITY_DIR     = "/etc/opt/SUNWcacao/security";
    $CACAMODULESDIR = "/etc/opt/SUNWcacao/modules";

  } elsif ($OS eq "Linux") {
    $CACAO_ROOT       = "/opt/sun/cacao/";
    $CACAOCSC = "$CACAO_ROOT/private/bin/cacaocsc";
    $CACAOADM = "$CACAO_ROOT/bin/cacaoadm";
    $CACAO_CONFIG_DIR = "/etc/opt/sun/cacao";
    $SECURITY_DIR     = "/etc/opt/sun/cacao/security";
    $CACAMODULESDIR = "/etc/opt/sun/cacao/modules";

  } else {
   error ($JesmfMessages::MFWK_ERR_OS01, $OS);
  }
  $CACAOCSC_BASE_COMMAND = "$CACAOCSC -h localhost -p $CACAOCSA_PORT -d $SECURITY_DIR/nss/wellknown -f $SECURITY_DIR/password -c ";
}



#-------------------------------------------------
#  Builds the CSC Cacao commands (cmd and args)
#-------------------------------------------------

sub BuildCscCommand {


  $mycmd = undef;


  if ($agent) {  
    debug("agent command");
    if ($config) {
      debug("list-params");
      $mycmd = GetCscString("agent config show");     

    }

  } elsif ($module) {   
    debug("module command");
    if ($list) {
      debug("list");
      $mycmd = GetCscString("module list");     
    } elsif (defined ($info)) {
      debug("info $info");
      $mycmd = GetCscString("module info $info");     
    } else {
     error($JesmfMessages::MFWK_ERR_INT01);
    }

  } elsif ($perfjob) {   
    debug("pm-job command");
    if ($list) {
      debug("list");
      $mycmd = GetCscString("perfjob list");     
    } elsif (defined ($info)) {
      debug("info $info");
      $mycmd = GetCscString("perfjob info $info");     
    } elsif (defined ($delete)) {
      debug("delete $delete");
      $mycmd = GetCscString("perfjob delete $delete");     
    } elsif (defined ($suspend)) {
      debug("suspend $suspend");
      $mycmd = GetCscString("perfjob suspend $suspend");     
    } elsif (defined ($resume)) {
      debug("resume $resume");
      $mycmd = GetCscString("perfjob resume $resume");     
    } elsif (defined ($create)) {
      $objarray = join ('@@@', @object);
      debug("create $create granularity $granularity objarray $objarray");
      $mycmd = GetCscString("perfjob create $create granularity $granularity objarray ".$objarray);     
    } else  {
     error($JesmfMessages::MFWK_ERR_UNK02);
    }

  } elsif ($opstatusjob) {   
    debug("opstat-job command");
    if ($list) {
      debug("list");
      $mycmd = GetCscString("opstatusjob list");     
    } elsif (defined ($info)) {
      debug("info $info");
      $mycmd = GetCscString("opstatusjob info $info");     
    } elsif (defined ($delete)) {
      debug("delete $delete");
      $mycmd = GetCscString("opstatusjob delete $delete");     
    } elsif (defined ($suspend)) {
      debug("suspend $suspend");
      $mycmd = GetCscString("opstatusjob suspend $suspend");     
    } elsif (defined ($resume)) {
      debug("resume $resume");
      $mycmd = GetCscString("opstatusjob resume $resume");     
    } elsif (defined ($create)) {
      $objarray = join ('@@@', @object);
      debug("create $create granularity $granularity object @object");
      $mycmd = GetCscString("opstatusjob create $create granularity $granularity objarray ".$objarray);     
    } else {
     error($JesmfMessages::MFWK_ERR_UNK03);
    } 
  } else {
     error($MFWK_ERR_UNK01);
  }
  return($mycmd);

}


#-------------------------------------------------
#  Builds the CSC Cacao commands (cmd and args)
#-------------------------------------------------

sub GetCscString($) {
  return ("$CACAOCSC_BASE_COMMAND"."\""."$MFWK_BASE_COMMAND"."@_"."\""); 
}


#-------------------------------------------------
# start/stop/restart agent
#-------------------------------------------------

sub startAgent(){

my $count = 0;
my @all_files = {};

   # retrieves cacao module descriptor list
   # that are related to the mfwk agent

   if (-d $CACAMODULESDIR) {
	if (opendir MODULESDIR, "$CACAMODULESDIR") {
	  readdir MODULESDIR; #skip .
	  readdir MODULESDIR; #skip ..
          # retrieves all cacao module descriptor list
	  @all_files = readdir MODULESDIR;
          # keep only the mfwk ones (check based on prefix and extension)
          @mfwkAllCacaoModuleDescritor = grep /^$MFWKMODULEPREFIXPATTERN.*$MFWKMODULEEXTPATTERN$/, @all_files;
          if (scalar (@mfwkAllCacaoModuleDescritor) == 0) {
            error ($JesmfMessages::MFWK_ERR_ST01,$CACAMODULESDIR);
	  }
          # remove the Agent module as it is a special case
          @mfwkCPCacaoModuleDescritor = grep !/^$MFWKAGENTMODULEDESC/, @mfwkAllCacaoModuleDescritor;
        } else {
          error($JesmfMessages::MFWK_ERR_ST02,$CACAMODULESDIR);
	} 
    } else {
      error($JesmfMessages::MFWK_ERR_ST03, $CACAMODULESDIR);
    }
    
    # Does a deploy on the mfwk agent module
    printMessage ($JesmfMessages::MFWK_INFO_ST04, ($CACAMODULESDIR,$MFWKAGENTMODULEDESC));
    executeCmd ("$CACAOADM deploy $CACAMODULESDIR/$MFWKAGENTMODULEDESC");
    # Does a deploy on all remaining modules
    for $module (@mfwkCPCacaoModuleDescritor) {
      printMessage ($JesmfMessages::MFWK_INFO_ST01, ($CACAMODULESDIR,$module));
      executeCmd ("$CACAOADM deploy $CACAMODULESDIR/$module");
    }
}
  
  
 

		
sub stopAgent() {

    # provide a no header version
    @output = `$CACAOADM list-modules 2>&1`;
    if ($? != 0) {
      error($JesmfMessages::MFWK_ERR_EXE01, ($cmd,@output,$!));
    }
        
    for $line (@output) {
      chomp $line;

      # fix for CR 6262977 start
      # now line contains module + version, we are interested in
      # in module only, so we retrieve only first elt before 1st
      # white space
      $line =~ /(.*?)\s(.*)/;
      $line=$1;
      # fix for CR 6262977 end

      push @moduleList,$line;
    }

    # retrieves all modules that have the correct prefix
    @mfwkAllCacaoModuleDescritor = grep /^$MFWKMODULEPREFIXPATTERN/, @moduleList;
    if (scalar (@mfwkAllCacaoModuleDescritor) == 0) {
      error ($JesmfMessages::MFWK_ERR_ST05);
    }

    # remove the Agent module as it is a special case
    @mfwkCPCacaoModuleDescritor = grep !/^$MFWKAGENTMODULE/, @mfwkAllCacaoModuleDescritor;

    # first we undeploy the running cacao modules
    for $module (@mfwkCPCacaoModuleDescritor) {
      printMessage ($JesmfMessages::MFWK_INFO_ST02, $module);
      executeCmd ("$CACAOADM undeploy $module");
    }

    # then we undeploy the agent
    printMessage ($JesmfMessages::MFWK_INFO_ST03,$MFWKAGENTMODULE);
    executeCmd ("$CACAOADM undeploy $MFWKAGENTMODULE");

}



# Check the user ID to see if it matches root's (0).
# Return 0 if the user is root. Exit with status 1 otherwise.
sub CheckRootUser() {

	$userId=`id`;
        debug ("id returned: $userId");
        $userId =~ s/uid=([0-9]*).*/\1/;
        debug ("userId: $userId");
        if ($userId != 0) {
          error ($JesmfMessages::MFWK_ERR_ROOT01)
	}

}




sub executeCmd($){

    my ($cmd) = @_;

    debug("executeCmd: $cmd");
    $output = `$cmd 2>&1`;
    if ($? != 0) {
      error ($JesmfMessages::MFWK_ERR_ST04, ($cmd,$output,$!));
    } else {
      print STDOUT ($output);
    }
}


  sub error_usage () {   
    debug("error_usage:");
    usage();
    exit 1;
  }

 
  sub error ($) {
    my ($message,@args) = @_;
    my $untranslatedGenericMsg = $JesmfMessages::MFWK_ERR_UNK05;
    my $translatedGenericMsg = $GETTEXTHANDLE->gettext($untranslatedGenericMsg); 
    debug("error:\nmessage=$message\nargs=@args\n");

    printf STDERR ($translatedGenericMsg, $0);

    my $translatedmsg = $GETTEXTHANDLE->gettext($message);
    printf STDERR ($translatedmsg,@args);
    exit 1;
  }

  sub printMessage() {
    my ($message,@args) = @_;
    my $translatedmsg = $GETTEXTHANDLE->gettext($message);
    printf STDOUT ($translatedmsg,@args);    
  }
 
  sub debug ($) {
    my ($message) = @_;
    if ($debug) {
      print "$message\n";
    }
  }

  ##################
  # main starts here
  ##################
  
  # CLI options init

  $help        = 0;
  $debug       = 0;
  $agent       = 0;
  $start       = 0;
  $stop        = 0;
  $restart     = 0;
  $config      = undef;
  $module      = 0;
  $perfjob     = 0;
  $opstatusjob = 0;
  $list        = 0;
  $info        = undef;
  $create      = undef;
  $granularity = undef;
  $delete      = undef;
  $suspend     = undef;
  $resume      = undef;

  # for I18N
  # Solaris 8 does not provide gettext in standard 
  # => we had to redevelop it
  $GETTEXTHANDLE = JesmfGettext->new();
  $GETTEXTHANDLE->textdomain("mfwkadm"); 

		 
  # Cacao stuff (paths, commands and ports)
  $CACAO_ROOT = undef;
  $CACAO_CONFIG_DIR = undef;
  $SECURITY_DIR = undef;

  $CACAOCSC = undef;
  $CACAOADM            = undef;
  $CACAOCSA_PORT = 10163;
  $CACAOCSC_BASE_COMMAND = undef;
  $CACAMODULESDIR      = undef;

  #constant for our CLI 
  $MFWK_BASE_COMMAND = "com.sun.mfwk:";
  $MFWKMODULEPREFIXPATTERN = "com.sun.mfwk.";
  $MFWKMODULEEXTPATTERN = ".xml";

  #for deploy
  $MFWKAGENTMODULEDESC = "com.sun.mfwk.mfwk_module.xml";
  #for undeploy
  $MFWKAGENTMODULE = "com.sun.mfwk.mfwk_module";


  # then we parse the args and update the variables accordingly...
  ParseCommandLineArgs(@ARGV);

  # We check if command is run as root (exit 1 if not)
  CheckRootUser();

  # sets OS specific Paths for Cacao
  SetCacaoPathsAndCommands();

  # for "agent show config", "module", "perfjob" and "opstatusjob" cmds, 
  # we use pure cacao CSC commands
  if (($agent && defined ($config)) or $module or $perfjob or $opstatusjob) {

    $cmd = BuildCscCommand();
    # executes the Cacao CSC command
    debug("cmd: $cmd");
    executeCmd ($cmd);
  
  # for "agent start/stop/restart we optionally use cacao CSC to extract
  # some info and then wrap cacaoadm
  } elsif  ($agent && ($start || $stop || $restart)) {
    if ($start) {  
      debug("agent start");
      startAgent();
    } elsif ($stop) {
      debug("agent stop");  
      stopAgent();
    } elsif ($restart) {
      debug("agent restart");  
      stopAgent();
      startAgent();
    } else {
      error($JesmfMessages::MFWK_ERR_UNK01);
    }
  } else {
    error($JesmfMessages::MFWK_ERR_UNK01);
  } 


 


