#!/usr/bin/env perl
#----------------------------------------------------------------------------
#
# Name: copy_any
#
# Description:
#
#  A script run by XPOLL to provide a very generalized copy (push) process based
#  on the OSF_DATASET name from the OSF trigger, and using ENV variables
#  provided by the resource file to define the copy parameters to the
#  netcopy utility which is not a pipeline process.
#  It only uses sftp and only does put commands (so PKI keys need to be in
#  place on the destination system).
#
#  The process allows the same flexibility as netcopy with regard to optional 
#  parameters, only requiring INPATH, 
#  REMOTE_COPY_ALLOWED, REMOTE_MACHINE,  and 
#  REMOTE_FILESPEC, The netcopy LOCAL_FILESPEC value will be built from INPATH,
#  a file mask, and OSF_DATASET. See the NETCOPY help page 
#  for a description of all the optional netcopy parameters that can be set in
#  the resource file. This scripts supports: REMOTE_LOGIN,
#  DELETE_AFTER_COPY, SAFE_COPY, ROLLBACK_PARTIAL_COPY, DISK_SLOP_PERCENT, 
#  NO_COPY_CONFIRMATION, NO_DELETION_CONFIRMATION, and TEMP_DIR. 
#
#  The REMOTE_COPY_ALLOWED variable is meant to be set in the path file to
#  provide a quick way to turn the copying on or off without changing the
#  pipeline configuration. 
#
#  The wild cards in the FILE_MASK depend on the OS.
#  Unix has flexible matching rules with 
#  asterisk for any number of characters, question mark (?) for any 
#  single character, and characters in square brackets ([abc...]) to match one
#  occurence of any of the listed characters (abc...). In addition to 
#  wildcards, the string "<OSF_DATASET>" indicates the replacement of this 
#  string with all of the OSF_DATASET value passed form XPOLL. The string 
#  "<OSF_DATASET_nn>", where nn is a one or two digit integer, indicates the
#  replacement of this string with the first nn characters of the OSF_DATASET
#  value. The FILEMASK should not include the directory, which is supplied by
#  INPATH, and it must include wildcards that will match the desired file 
#  extensions to be copied.
# 
# History:
# Date     OPR      Who      Reason
# -------- ------ ---------- ---------------------------------------------
# 05/30/02 xxxxx  Baum       Initial code.
# 07/20/06 55869  Sherbert   Place subroutine prototypes before calls
# 06/17/10 65423  MSwam      Reworked for netcopy/SFTP, and removed VMS
#----------------------------------------------------------------------------
  unshift @INC,(split /:/, $ENV{PATH});

  require 'printmsg.pl';

# subroutine prototypes
  sub flag_option($);
  sub CheckPW();
  sub CopyFiles($$);

#specify exit status values
  $PROCESS_SUCCESS = 11; # exit status for XPOLL
  $PROCESS_FAILURE = 13; # exit status for XPOLL
  $PROCESS_ABORT   = 111; # kill XPOLL - bad resource file 

#specify netcopy return status values
  $netcopy_success = 3;
  $netcopy_no_files = 5;
  $netcopy_missing_files = 7;
  $netcopy_failure = 9;
  $netcopy_usage = 11;
  $netcopy_insuff_disk_space = 13;
  $netcopy_delete_failed = 15;
  $netcopy_missing_directory = 17;

#check for arguments
  $num_arg = scalar @ARGV;

  if ($num_arg == 0) {
    PrintMsg("F","Failed to get required arguments in COPY_ANY call");
    exit( $PROCESS_ABORT);
  }
# check if copyinng is used in this path file
  $copy_allowed = $ENV{"REMOTE_COPY_ALLOWED"};
  if (!defined($copy_allowed)) {
    PrintMsg("I","REMOTE_COPY_ALLOWED not set. No action.");
    exit ($PROCESS_SUCCESS);
  } 
  if ($copy_allowed ne "YES") {
    PrintMsg("I","REMOTE_COPY_ALLOWED not YES. No action.");
    exit ($PROCESS_SUCCESS);
  }
# get ENV variable set by pipeline via XPOLL
  $event_type = $ENV{"EVENT_TYPE"};

  if (!defined($event_type)) {
    PrintMsg("F","Missing pipeline ENV variable EVENT_TYPE.");
    exit( $PROCESS_ABORT);
  }
  if ($event_type eq "EVENT_TIME_EVENT") {
     $osf_dataset = "NONE";
  } else {
     $osf_dataset = $ENV{"OSF_DATASET"};
  }
  if (!defined($osf_dataset)) {
    PrintMsg("F","Missing pipeline ENV variable OSF_DATASET.");
    exit( $PROCESS_ABORT);
  }
  PrintMsg("I",
   "Starting copy_any.pl script for event: $event_type osf: $osf_dataset ");

# collect required $ENV variables set from resource file
  $inpath = $ENV{"INPATH"};
  $binary_file_mask = $ENV{"BINARY_FILE_MASK"};
  $remote_machine = $ENV{"REMOTE_MACHINE"};
  $remote_filespec = $ENV{"REMOTE_FILESPEC"};

# validate $ENV variables
  if ((!defined($binary_file_mask))) {
     PrintMsg("F",
       "Missing ENV resource keyword: BINARY_FILE_MASK.");
    exit( $PROCESS_ABORT);
  }
  if (!(defined($inpath) && defined($remote_machine) && 
        defined($remote_filespec))) {
    PrintMsg("F",
"Must have ENV keywords: INPATH, REMOTE_MACHINE, and ".
"REMOTE_FILESPEC.");
    exit( $PROCESS_ABORT);
  }
# collect optional keywords
  $remote_login = $ENV{"REMOTE_LOGIN"};
  $disk_slop_percent = $ENV{"DISK_SLOP_PERCENT"};
  $temp_dir = $ENV{"TEMP_DIR"};
  $delete_after_copy = flag_option("DELETE_AFTER_COPY");
  $safe_copy = flag_option("SAFE_COPY");
  $rollback_partial_copy = flag_option("ROLLBACK_PARTIAL_COPY"); 
  $no_copy_confirmation = flag_option("NO_COPY_CONFIRMATION");
  $no_deletion_confirmation = flag_option("NO_DELETION_CONFIRMATION");

# check password if TIME EVENT
  if ($event_type eq "EVENT_TIME_EVENT") {
     exit( CheckPW());
  }
# process binary mask
  if (defined($binary_file_mask)) {
    CopyFiles( $binary_file_mask, "BINARY");
  }
  exit( $PROCESS_SUCCESS);
#--------------------------------------------------------------------------
#  end of main - subroutines below
#--------------------------------------------------------------------------
sub flag_option($)
{
  my ($option) = @_;
  my $opt_val = $ENV{$option};
  my $return_val =0;
  if (defined($opt_val)) {
    $return_val =  ($opt_val eq "TRUE" || $opt_val eq "YES");
  }
}
#--------------------------------------------------------------------------
sub CheckPW()
{
    PrintMsg("I","Password check not needed for SFTP.");
    return ($PROCESS_SUCCESS);
}
#--------------------------------------------------------------------------
sub CopyFiles($$)    # copy files using file mask
{
# get arguments
  my($mask, $file_type) = @_;

# netcopy status values
  my $netcopy_success = 3;

# parse mask
  my $ds_token = "<OSF_DATASET";
  my $len_token = length($ds_token);
  my $ds_end = ">";
  my $len_end = length($ds_end);
  my $fld_size;   # size of number field in mask
  my $dataset_size;  # size specified by number field

  if (-1 == ($ds_tok_idx = index( $mask, $ds_token))) {
    PrintMsg("F","Cannot find $ds_token in file mask: $mask");
    exit( $PROCESS_ABORT);
  }
  if (-1 == ($ds_end_idx = index( $mask, $ds_end, $ds_tok_idx))) {
    PrintMsg("F","Cannot find $ds_end in file mask: $mask");
    exit( $PROCESS_ABORT);
  } 
  if ( $ds_end_idx == $len_token ) {
    $dataset_size = length($osf_dataset);  # use full string
    $fld_size = -1;     # account for missing "_" separator
  } else {
    $fld_size = $ds_end_idx - $len_token - 1;  # size of number less separator
    my $fld_offset = ($len_token + 1); # skip separator
    $dataset_size = 0+substr($mask, $fld_offset, $fld_size);
  }
  my $replace_size =  $len_token + $len_end + $fld_size + 1;
  
# replace tokens in mask by all or part of dataset name
  substr($mask,$ds_tok_idx,$replace_size) = 
    substr($osf_dataset,0,$dataset_size);
  $mask = lc($mask);   # assume lowercase for file spec
  my $local_filespec = $inpath.$mask;
  my @files = glob( $local_filespec );  # expand wildcards
  my $file_count = scalar @files;

  if ($file_count == 0) {  # no files found
    PrintMsg("W","No files found using $local_filespec.");
  } else {   # copy files to remote node
#   prepare netcopy command using $file_type, $local_filespec and globals
    my $command = "netcopy -rm $remote_machine ".
      " -pg put -rf $remote_filespec -lf $local_filespec ";
    $command = $command." -rl $remote_login" if (defined($remote_login));
    $command = $command." -ds $disk_slop_percent" if (defined($disk_slop_percent));
    $command = $command." -t $temp_dir" if (defined($temp_dir));
    $command = $command." -de" if ($delete_after_copy);
    $command = $command." -sa" if ($safe_copy);
    $command = $command." -ro" if ($rollback_partial_copy);
    $command = $command." -nc" if ($no_copy_confirmation);
    $command = $command." -nd" if ($no_deletion_confirmation);
    $command = $command." 2>&1";  # redirect stderr to stdout
    PrintMsg("I","command=$command");
    my $netcopy_log = `$command`;
    my $savestat = 0;
    $savestat = ($? >> 8);
    if ($savestat != $netcopy_success) {
      PrintMsg("E","Netcopy failed with status $savestat\n$netcopy_log");
      exit( $PROCESS_FAILURE);
    } else {
      PrintMsg("I",
        "Netcopy copied $file_count $file_type files $local_filespec");
    }
  }
}
