#! perl -w

=head1 NAME

cfx5remote - Run a CFX-5 executable

=cut

#==============================================================================
# @(#) $Id$
#------------------------------------------------------------------------------
##
## Name:
##
## cfx5remote
##
## Purpose:
##
## Run a CFX-5 executable with the correct settings etc.
##
## This command is used internally by the parallel support code, and
## is not intended for users.
##
## Synopsis:
#S
#S cfx5remote [-chdir <dir>] <exec> <args>
#S
## []  denotes an optional argument. 
## |   separates mutually exclusive arguments. 
## ... following an argument indicates that it may be repeated.
## <>  denotes that substitution of a suitable value is required. All other
##     arguments are keywords, some of which have a short form.
##
## Arguments:
##

# get the standard CFX-5 library directory
BEGIN {
  if ($0 =~ m!^([a-z]:)?[\\/]!i) {
    # it's an absolute path, use it as-is
    (my $nd=$0) =~ s!(perllib[\\/])?[^\\/]*$!!i;
    unshift @INC, "$nd/perllib";
  } else {
    # wrap this in an eval, and if it fails, pray ... for example,
    # this can fail on Windows if we're running off a share.
    eval {
      require FindBin;
      FindBin->import();
      unshift @INC, "$FindBin::Bin/perllib";
      push @INC, $FindBin::Bin;
    };
    warn $@ if $@;
  }
  if (defined $ENV{CFX_LOCAL_PERLLIB}) {
     unshift @INC, $ENV{CFX_LOCAL_PERLLIB};
  }

}

use CFX5::Init;
CFX5::Init::init();

use vars qw($CVSVersion);
$CVSVersion='@(#) $Id$\n';

use strict;

use CFX5::Output qw(:all);

use CFX5::CmdLine qw(parse_cmdline);

use CFX5::PkgLoader qw(cfx5_require);

use CFX5::PathManip qw(change_cwd);
#
# read the configuration
#
#CFX5::Config::read_config();

unless (defined $ARGV[0] and $ARGV[0] =~ m!^-!) {
  # cfx5remote doesn't do much without any switches at all!  So add a
  # default set.
  _debug("Adding default switches");
  unshift @ARGV, '-set-rld-path',
                 '-std-vars' => 'PVM_ROOT,PVM_ARCH',
                 '-set-mpich-path',
                 '-set-mport-path' => 'stub';
}

_trace "about to call parse_cmdline";

my @precmd;
my @cmd=parse_cmdline
  ( \@ARGV,
    #'INCLUDE_REQ',
    'INCLUDE_STD',

    # allows us to switch off the default argument list!
    '-no-default' => sub { 1; },

    '-chdir+' => sub {
      my $arg=shift;
      my $dir=shift;

      cfx5_require('CFX5::FileTests');

      if (CFX5::FileTests::datadir($dir, "Directory $dir passed to $arg")) {
        _debug("chdir $dir");
        change_cwd($dir) or _error("Cannot chdir to $dir: $!");
      }
    },

    '-env+' => sub {
      my $arg=shift;
      my $set=shift;

      my ($var,$val) = split(/=/,$set,2);
      if (defined $var and defined $val) {
        cfx5_require("CFX5::Config");
        CFX5::Config::setconf($var => $val);
        CFX5::Config::export_conf($var);
      } else {
        _error("Invalid argument \"$set\" for $arg");
      }
    },

    '-set-rld-path' => sub {
      cfx5_require('CFX5::Config');
      CFX5::Config::set_rld_path();
    },

    '-set-mpich-path' => sub {
      cfx5_require('CFX5::Config');
      CFX5::Config::prepend_to_libpath(CFX5::Config::getconf('CFX5_MPI_LIBDIR'));
    },

    '-set-mport-path+' => sub {
      cfx5_require('CFX5::Parallel::MPI');
      CFX5::Parallel::MPI::export_multiport_conf($_[1]);
    },

    '-std-vars+' => sub {
      cfx5_require('CFX5::Config');
      for my $v (split(/(\s*,|\s+)\s*/, $_[1])) {
        CFX5::Config::export_conf($v);
      }
    },

    # the first non-option argument is the executable name; that's
    # where we stop.
    '*' => sub { 
      $CFX5::CmdLine::Break=1;
      # this counts as processing this arg, so we need to save its
      # value 
      push @precmd, $_[1];
    },
  );


# it's useful to list the host name in cfx5remote errors, but not
# worth loading CFX5::Config for if we don't already have it
if (defined &CFX5::Config::getconf) {
  # reference twice to avoid 'used only once' warning ...
  cfx5_require('CFX5::Output::Base');
  my $prog=$CFX5::Output::Base::ProgramName;
  $CFX5::Output::Base::ProgramName = $prog . " on " . CFX5::Config::getconf('CFX_HOST');
}

unless (@precmd or @cmd) {
  _error("You must specify a command");
}

exit_if_error();

unshift @cmd, @precmd;
_trace "Command is:", @cmd;

cfx5_require('CFX5::Commands');
my $rv=CFX5::Commands::parse_rv(CFX5::Commands::do_cmd(@cmd));

unless ($rv->is_success()) {
  _error($rv->errstr());
  exit_if_error();
}

exit(0);
