#!/usr/bin/env perl
# ./acquire_obsys 19990721 180000 060000 6 sonde_hirs
# Script to make the acquire resource file and then call acquire script to get
#  observation data.
# See usage() of this script for more information.
#
# !REVISION HISTORY:
#
# 2001.07.31 Eueng-nan Yeh   Specs and man page.
# 2001.08.06 Eueng-nan Yeh   Initial code.
# 2001.10.02 Eueng-nan Yeh   obsys.rc format changed
# 2001.10.17 Eueng-nan Yeh   Accept multiple obclasses
# 2002.03.18 Eueng-nan Yeh   Added standard name output
# 2002.08.12 Tommy Owens     Returned with Warning if no records found for a given class
# 2002.08.14 Eueng-nan Yeh   Set the standard name after the old name
#                            Removed look ahead calculation from subroutine mk_date
# 2004.10.21 Todling         Work around /bin/time command
# 2013.09.30 Todling         Fix -h opt; add opt acqonly
# 2018.05.04 Stassi          Modified to use increment value for each obsclass from
#                            obsys.rc rather than using one value for all obsclasses
#=========================================================================
use strict;
use warnings;
use File::Basename qw(basename dirname);
use File::Path qw(mkpath);
use Getopt::Long qw(GetOptions);

use FindBin qw($Bin);
use lib "$Bin";
use Manipulate_time qw(tick num_days_in_month);

# global variables
#-----------------
my ($acqonly, $acquire, $copyspool, $dtime, $errfile, $forcecopy);
my ($longnames, $lookahead, $obsys_acq, $outdir, $preserve, $obsysrc);
my ($spooldir, $ssh, $strict, $today, $user, $verbose);
my (@acq_opts, %standardHash, %templateHash);

# main program
#-------------
{
    my ($all_acq, $com, $com_, $incr, $incr_acq, $increment, $inq_acq, $istep);
    my ($class, $datatype, $standard, $status, $template);
    my (%classHash, @acq_args, @classList, @ymdList);
    my (@modisL2List, $bymd_, $bhms_);

    # get input parameters
    #---------------------
    my ($bymd, $bhms, $ihms, $nstep, $obsclass) = init();

    # generate yyyymmdd list, @ymdList
    #---------------------------------
    @ymdList = mk_date($bymd, $bhms, $ihms, $nstep);
    print "ymdList=@ymdList\n" if $verbose;

    # extract class info from obsys rcfile
    #-------------------------------------
    @classList = split(/,/, $obsclass);
    foreach $class (@classList) {
        ($standard, $increment, $template) = ck_table($class, @ymdList);
        if ($template eq "#") {
            msg("W", "No valid records found on $obsysrc for $class.");
            next;
        }
        $standardHash{$class} = $standard;
        $templateHash{$class} = $template;
        if ($classHash{$increment}) { $classHash{$increment} .= ",$class" }
        else                        { $classHash{$increment}  =  "$class" }
    }

    # $all_acq is for informational purposes only;
    # it is not used for acquire calls in this script
    #------------------------------------------------
    if (scalar(keys %classHash) == 1) {
        $all_acq = "";
    } 
    else {
        $all_acq = $obsys_acq;
        unlink($all_acq) if -e $all_acq;
    }

    # loop through $incr groups
    #--------------------------
    foreach $incr (sort keys %classHash) {

        @classList = split(/,/, $classHash{$incr});
        $bymd_ = $bymd;
        $bhms_ = $bhms;

        # calculate # of steps
        #---------------------
        if ($incr == $ihms) { $istep = $nstep }
        else                { $istep = $nstep * numsecs($ihms) / numsecs($incr) }

        # rename obsys_acq, if more than one $incr group
        #-----------------------------------------------
        if (scalar(keys %classHash) == 1) {
            $incr_acq = $obsys_acq;
        }
        else {
            $incr_acq = obsys_incr_acq($obsys_acq, $incr);
        }
        unlink($incr_acq) if -e $incr_acq;

        # special processing for MODIS L2 data
        #-------------------------------------
        if ($incr eq "000500") {

            # if using staged MODIS data, then warn about acquiring MODIS L2 data
            #--------------------------------------------------------------------
            if ($ENV{"USE_MODIS_STAGE"}) {

                @modisL2List = ();
                foreach $class (@classList) {
                    chomp($datatype = `$Bin/aod_data.py aod_type $class $obsysrc`);
                    push @modisL2List, $class if $datatype eq "modisL2";
                }

                if (@modisL2List) {
                    print "\nWARNING: USE_MODIS_STAGE variable is turned on.\n"
                        . "Acquiring MODIS data which might not be used:\n";
                    foreach (@modisL2List) { print "=> $_\n" }
                }
            }

            # back time up 90 minutes to get inputs into 3-hr L2a product
            #------------------------------------------------------------
            ($bymd_, $bhms_) = tick($bymd, $bhms, -5400);
            print "INFO: ticking clock back 90 mins, "
                . "${bymd}_$bhms -> ${bymd_}_$bhms_, "
                . "for classes, [@classList]\n";
        }

        # write acq file(s)
        #------------------
        write_acq_file($incr_acq, \@classList, \@ymdList);
        write_acq_file($all_acq, \@classList, \@ymdList) if $all_acq;

        # stop after creating $acqfile
        #-----------------------------
        if ($acqonly) {
            print "Job finished.\n" if $verbose;
            exit(0);   #0 as a success exit
        }

        # process acquire script
        #-----------------------
        # $com is command to run
        # $com_ is for display only
        #--------------------------
        @acq_args = ($bymd_, $bhms_, $incr, $istep);
        $com = "$acquire @acq_opts -rc $incr_acq @acq_args";
        $com_ = basename($acquire) ." @acq_opts -rc $incr_acq @acq_args";

        if (-e "/bin/time") {
            $com  = "/bin/time $com";
            $com_ = "/bin/time $com_";
        }

        if ($verbose) {
            print "com = $com_\n";
            print ">> Processing acquire...\n";
        }
        $status = system($com);
        if ($status) { msg("E", "$com_ failed.") }
    }
 
    # all done
    #---------
    print "Job finished.\n" if $verbose;
}

#=======================================================================
# name - init
# purpose - get command line arguments and options
#=======================================================================
sub init {
    my ($bymd, $bhms, $ihms, $nstep, $obsclass);
    my (%opts, $help, $acqpath);

    $user = $ENV{"USER"};
    $user = getlogin() unless $user;

    chomp($dtime = `date '+%a %d %b %Y %H:%M:%S %p %Z'`);
    chomp($today = `date '+%Y%m%d'`);

    %opts = ("verbose" => 1);

    GetOptions( "d=s"       => \$outdir,
                "h"         => \$help,
                "la=s"      => \$lookahead,
                "v"         => \$verbose,
                "drc=s"     => \$obsysrc,   # database table rcfile
                "acqfile=s" => \$obsys_acq,
                "acqonly"   => \$acqonly,

                # options to pass through to acquire script
                #------------------------------------------
                "cp"        => \$copyspool,
                "e=s"       => \$errfile,
                "f"         => \$forcecopy,
                "lfn"       => \$longnames,
                "p"         => \$preserve,
                "s=s"       => \$spooldir,
                "ssh"       => \$ssh,        # deprecated
                "strict"    => \$strict );

    usage() if $help;
    usage() if scalar(@ARGV) != 5;
    ($bymd, $bhms, $ihms, $nstep, $obsclass) = @ARGV;

    # get output directory path
    #--------------------------
    $outdir = "." unless $outdir;
    $outdir =~ s/\/$//;
    unless (-d $outdir) {
        msg("P", "Creating output path $outdir");
        mkpath($outdir, \%opts) or msg("E", "Fail to make path $outdir");
    }

    # get $obsys_acq name
    #--------------------
    $obsys_acq = "$outdir/obsys.acq" unless $obsys_acq;
    $acqpath = dirname($obsys_acq);
    unless (-d $acqpath) {
        msg("P", "Creating obsys_acq path $acqpath");
        mkpath($acqpath, \%opts) or msg("E", "Fail to make path $acqpath");
    }
    print "obsys_acq = $obsys_acq\n" if $verbose;

    # get obsysrc name
    #------------------
    $obsysrc = "obsys.rc" unless $obsysrc;
    msg("E", "Database resource file '$obsysrc' not found.") unless -e $obsysrc;
    print "Database resource file = $obsysrc\n" if $verbose;

    # check inputs
    #-------------
    msg("E", "Beginning YYYYMMDD wrong: $bymd")
        unless datetime_check($bymd, "yyyymmdd");

    msg("E", "Beginning HHMMSS wrong: $bhms")
        unless datetime_check($bhms, "hhmmss");

    msg("E", "Time step increment HHMMSS wrong: $ihms")
        unless datetime_check($ihms, "hhmmss");

    msg("E", "Number of timesteps '$nstep' wrong") if $nstep < 1;

    # find acquire script
    #--------------------
    $ENV{"PATH"} = "./:$ENV{PATH}";
    chomp($acquire = `which acquire`);
    msg("E", "acquire script not found: $acquire") unless -e "$acquire";
    msg("P", "Using acquire script: $acquire") if $verbose;

    # create lists of options and arguments to send to acquire script
    #----------------------------------------------------------------
    @acq_opts = ();
    push @acq_opts, "-cp"            if $copyspool;
    push @acq_opts, "-d $outdir";
    push @acq_opts, "-e $errfile"    if $errfile;
    push @acq_opts, "-f"             if $forcecopy;
    push @acq_opts, "-lfn"           if $longnames;
    push @acq_opts, "-la $lookahead" if $lookahead;
    push @acq_opts, "-p"             if $preserve;
    push @acq_opts, "-s $spooldir"   if $spooldir;
    push @acq_opts, "-ssh"           if $ssh;
    push @acq_opts, "-strict"        if $strict;
    push @acq_opts, "-v"             if $verbose;

    return ($bymd, $bhms, $ihms, $nstep, $obsclass);
}

#=======================================================================
# name - mk_date
# purpose - return a list of unique records of YYYYMMDD
#=======================================================================
sub mk_date {
    my ($bymd, $bhms, $ihms, $nstep);
    my ($ymd, $hms, %date);

    ($bymd, $bhms, $ihms, $nstep) = @_;
    $ymd = $bymd;
    $hms = $bhms;

    foreach (1..$nstep) {
        $date{$ymd} = 1;
        ($ymd, $hms) = tick($ymd, $hms, 0, $ihms);
    }
    return(sort keys %date);
}

#=======================================================================
# name - ck_table
# purpose - get valid records info from database template file $obsysrc
#
# input arguments
# => $class:  obs class to read from $obsysrc
# => @ymdList: list of yyyymmdd dates
#
# return value(s)
#  => ($standard, $increment, $template)
#=======================================================================
sub ck_table {
    my ($class, @ymdList);
    my ($date, $datestring, $edate, $found_class, $increment, $msgstr);
    my ($rcd, $sdate, $standard, $template, @field);

    $class = shift @_;
    @ymdList = @_;

    $found_class = 0;
    $standard = "";
    $increment = "";
    $template = "";

    open(RCF,"< $obsysrc") or die "Fail to open file: $obsysrc $!\n";

    foreach $rcd (<RCF>) {
        $rcd =~ s/^\s+|\s+$//g;    # remove leading/trailing blanks
        next if $rcd =~ m/^#/;     # skip commented lines
        next unless $rcd;          # skip blank lines

        # look for start of $class
        #-------------------------
        @field = split /\s+/, $rcd;
        unless ($found_class) {
            next unless scalar(@field) >= 2;
            next unless $field[0] eq "BEGIN" and $field[1] eq $class;
            if ($#field >= 3 and $field[2] eq "=>") { $standard = $field[3] }
            $found_class = 1;
            next;
        }

        # check for end of $class
        #------------------------
        if ($rcd =~ m/^END/) {
            unless ($template) {
                $msgstr = "No valid record found for class '$class' "
                    . "from $ymdList[0] to $ymdList[-1] on $obsysrc.";
                msg("W", $msgstr);
                $template = "#";
            }
            last;
        }

        # get start and end dates
        #------------------------
        $sdate = "";
        $edate = "";
        $datestring = $field[0];

        ($sdate) = ( $datestring =~ m/^(\d{8})_\d{2}z-(.*)/ );
        ($edate) = ( $datestring =~ m/-(\d{8})_\d{2}z$/ )
            or     ( $datestring =~ m/-(present)$/i );
        $edate = $today if lc($edate) eq "present";

        unless ( datetime_check($sdate, "yyyymmdd") ) {
            msg("E", "Invalid startdate from $obsysrc: $sdate");
            next;
        }
        unless ( datetime_check($edate, "yyyymmdd") ) {
            msg("E", "Invalid enddate from $obsysrc: $sdate");
            next;
        }

        # check dates against record
        #---------------------------
        foreach $date ( @ymdList ) {
            if ( $sdate <= $date and $date <= $edate ) {
                $template = $field[2];
                $increment = $field[1];
                $standard = (split("/", $template))[-1] unless $standard;
                last;
            }
        }
    }
    close(RCF);

    # check results        
    #--------------
    msg("E", "Class name '$class' not found.") unless $template;
    return $standard, $increment, $template;
}

#=======================================================================
# name - obsys_incr_acq
# purpose - create alternate obsys acquire file name with $incr label,
#           if more than one increment group is found in obsclass list.
#=======================================================================
sub obsys_incr_acq {
    my ($obsys_acq, $increment, $incr_acq);
    $obsys_acq = shift @_;
    $increment = shift @_;

    if ($obsys_acq =~ m/\.acq$/) {
        ($incr_acq = $obsys_acq) =~ s/\.acq$/.$increment.acq/;
    }
    else {
        $incr_acq = "$obsys_acq.$increment";
    }
    return $incr_acq;
}

#=======================================================================
# name - write_acq_file
# purpose - 
#=======================================================================
sub write_acq_file {
    my ($acq_file, $classListAddr, $ymdListAddr, @classList, @ymdList);
    my ($class, $standard, $template);

    $acq_file = shift @_;
    $classListAddr = shift @_;
    $ymdListAddr = shift @_;

    @classList = @$classListAddr;
    @ymdList = @$ymdListAddr;

    open(ACQF, ">> $acq_file") or die "Fail to open files:$acq_file $!\n";
    unless (-s $acq_file) {
        print ">> Creating acquire resource file $acq_file...\n" if $verbose;
        print ACQF "#\n";
        print ACQF "# Acquiring rules                 $dtime\n";
        print ACQF "# Created by $user\n" if $user;
        print ACQF "#" ."."x64 ."\n";
    }

    # write $acq_file records
    #------------------------
    foreach $class (@classList) {
        $standard = $standardHash{$class};
        $template = $templateHash{$class};
        write_acq_rec($class, $standard, $template, @ymdList);
    }
    close(ACQF)|| die "Couldn't close file: $acq_file $!\n";
    print "Acquire file '$acq_file' completed.\n" if $verbose;
}

#=======================================================================
# name - write_acq_rec
# purpose - write class record to acquire resource file $obsys_acq
#=======================================================================
sub write_acq_rec {
    my ($class, $standard, $template, @ymdList);
    my ($nnn);

    $class = shift @_;
    $standard = shift @_;
    $template = shift @_;
    @ymdList = @_;

    if($verbose) {
        print "Acquired records:\n";
        print "$template\n";
    }
    $nnn = length($class)+7;
    print ACQF "#\n";
    print ACQF "#      " ."-"x$nnn ."\n";
    print ACQF "#       $class Data\n";
    print ACQF "#      " ."-"x$nnn ."\n";
    print ACQF "$template => $standard\n";
}

#=======================================================================
# name - datetime_check
# purpose - check for correct date and/or time format
#
# input arguments
# => $dtstr : date and/or time string to check
# => $flag  : format of $dtstr to check against ("yyyymmdd" or "hhmmss")
#
# return value
# => 0  invalid date/time format
# => 1  valid date/time format
#=======================================================================
sub datetime_check {
    my ($dtstr, $flag, $valid);
    my ($y4, $m2, $d2, $lastday, $hh, $mm, $ss);

    $dtstr = shift @_;
    $flag = lc(shift @_);

    $valid = 1;
    {
        # check date format
        #------------------
        if ($flag eq "yyyymmdd") {
            unless ($dtstr =~ m/^\d{8}$/) {
                $valid = 0;
                last;
            }
            $y4 = substr($dtstr, 0, 4);
            $m2 = substr($dtstr, 4, 2);
            $d2 = substr($dtstr, 6, 2);
            $lastday = num_days_in_month($y4, $m2);

            if ( ($m2 > 12) or ($d2 > $lastday) ) {
                $valid = 0;
                last;
            }
        }

        # check time format
        #------------------
        elsif ($flag eq "hhmmss") {
            unless ($dtstr =~ m/^\d{6}$/) {
                $valid = 0;
                last;
            }
            $hh = substr($dtstr, 0, 2);
            $mm = substr($dtstr, 2, 2);
            $ss = substr($dtstr, 4, 2);

            if ( ($hh > 24) or ($mm > 59) or ($ss > 59) ) {
                $valid = 0;
                last;
            }
        }
    }
    return $valid;
}

#=======================================================================
# name - msg
# purpose - print out error and warning messages; exit software if
#           first input argument indicates an error "E"
#=======================================================================
sub msg {
    my ($code, $errmsg) = @_;
    $code = uc($code);
    print("-$code: $errmsg\n");
    if ($code =~ m/^E/) { exit(1) }  # Exit for error
}

#=======================================================================
# name - numsecs
# purpose - convert from hhmmss to seconds
#=======================================================================
sub numsecs {
    my ($hhmmss, $mmss, $hh, $mm, $ss, $seconds);
    $hhmmss = shift @_;

    $hh = int($hhmmss/10000);
    $mmss = $hhmmss - ($hh*10000);
    $mm = int($mmss/100);
    $ss = $mmss - ($mm*100);

    $seconds = $hh*60*60 + $mm*60 + $ss;
    return $seconds;
}

#=======================================================================
# name - pause
# purpose - pause processing to evaluate output
#=======================================================================
sub pause {
    print "Hit <cr> to continue ... ";
    my $dummy = <STDIN>;
    return;
}

#=======================================================================
# name - usage
# purpose - print usage information
#=======================================================================
sub usage {

    print <<"EOF";

NAME
     acquire_obsys - Makes an observation resource file and then calls acquire
                     script to retrieve these observation data from mass
                     storage with look-ahead capability

SYNOPSIS

     acquire_obsys [...options...]  bymd bhms ihms nstep obclass

DESCRIPTION

     Acquire is a general purpose utility for retrieving files from
     mass storage with a look-ahead spooling capability. The full path
     names of the files to be retrieved are specified in a resource file
     (see RESOURCE FILE below) by means of GrADS-like templates which
     will be generated by acquire_obsys.  For example, a resource file
     could specify a file name of the form:

      gatun:/silo3/dao_ops/conv+tovs/ods/Y%y4/M%m2/r4ods.t%y4%m2%d2_%h2z

     The following parameters are required on input:

     bymd     beginning year-month-day, e.g., 19980101
     bhms     beginning hour-min-sec, e.g., 120000
     ihms     time step increment in hour-min-sec format, e.g., 060000
     nstep    number of timesteps for time looping, e.g., 6.
     obclass  file class, e.g., conv_tovs, ers2, qscat, ssmi_wentz_tpw,
              ssmi_wentz_wind, sonde_hirs, and tovs_l1b etc.
              Note: You can enter multiple obclasses such as conv_tovs,ers2
              (no blank spaces and comma is the separator)

     Note that the script has been updated to use the actual time step increment
     for each obsclass as listed in the obsys.rc file, which allows classes with
     different time step values to be listed together. The ihms and nstep
     arguments have been retained and are now used only to determine the overall
     timespan (ihms*nstep) for which to acquire observation data files.

     For example,

         acquir_obsys 19980107 120000 060000 6 conv_tovs

     will generate the followings pairs of date/time

          nymd       nhms
         -------    -------
         19980107   120000
         19980107   180000
         19980108   000000
         19980108   060000
         19980108   120000
         19980108   180000

    For each one of these dates/time, acquire will expand the
    GrADS-like template and retrieve the corresponding files from
    mass storage. For the examples above, the files to be retrieved
    are:

    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980107_12z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980107_18z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980108_00z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980108_06z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980108_12z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980108_18z

    Upon transfer from mass storage, these files are made available
    at the user local directory (see "-d" option).

    The look-ahead capability allows the user to retrieve files for
    future use. For example,

         acquir_obsys -la 4 19980107 120000 060000 6 conv_tovs

    will generate 4 additional date/time pairs:

          nymd       nhms
         -------    -------
         19980109   000000
         19980109   060000
         19980109   120000
         19980109   180000

   and transfer the files
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980109_00z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980109_06z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980109_12z
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980109_18z

   to a spool directory. Next time the user issues an "acquire_obsys" to
   retrieve these files, they will already be available locally.
   For this "look-ahead" transfer acquire forks itself, performing
   this task in the background.

   Acquire is also smart enough to avoid retrieving the same file
   more than once. If in the example above we replace the file name
   template with

     gatun:/silo3/dao_ops/conv+tovs/ods/Y%y4/M%m2/r4ods.t%y4%m2%d2

   only the files

    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980107
    gatun:/silo3/dao_ops/conv+tovs/ods/Y1998/M01/r4ods.t19980108

   would be retrieved.

OPTIONS

     -cp            when files are to be preserved in spool directory
                     (see -p) a copy is made to the user destination directory
                     (the default is to make a symlink)
     -d path        destination (local) directory (default: .\/)
     -e logfile     name of error log file. (default: no logging enabled)
     -f             forces remote copy whether the file exists locally or not
     -h             prints this page
     -lfn           use long file names in spool directory to
                     prevent file name conflicts
     -la lstep      Look ahead lstep time steps, that is, future data
                     can be pre-fetched and kept in spool directory
                     (default: lstep=0)
     -p             preserve files in spool directory, simply making
                     a symlink() or copy to the local directory (see -cp);
                     this is useful if the file is expected to be reused.
                     In such cases one should monitor disk usage in the
                     spool directory.
     -s path        spool directory (default: /scratch1/$ENV{USER}/spool)
     -ssh           use ssh and scp (default: rsh and rcp)
     -strict        returns non-zero exit code if not all files
                     specified in the rc file are acquired
     -v             verbose mode (default is real quiet)
     -drc fullName  user specified database resource file with file path
                     (default: obsys.rc)
     -acqfile fullName  The path and filename of the generated acq file.
                        (the default path is the option "-d" and the
                         default filename is obsys.acq)
     -acqonly       create acqfile (from obsys.rc) but do not exec acquire

RESOURCE FILES

     The acquire_obsys will generate the resource file (with the file name
     as the_given_obclass_name.acq) by extracting records from the given
     obclass out of the observation database file which consists of
     information blocks for each obclass.
     Records defined by the obclass block show the remote file name template
     (will be used to form the resource file) and the time range (start/end
     date and time increment) which the remote file name template can be
     applied to.  For examp;e:

     BEGIN obclass
       startYYYYMMDD_HHz-endYYYYMMDD_HHz incrementHHMMSS remote_file_name_template
     END

     Acquire resource files consist of comment lines starting with
     '#' or a remote file name templates of the form

           rhost:path/fname

     This is better explained with an example:

     helios1:/u/joiner/tovs/l1b/%y4%m2/l1c_new/hirs.nj.hdf.t%y4%m2%d2

     In this example, the remote host (rhost) is "helios1", the path
     is /u/joiner/tovs/l1b/%y4%m2/l1c_new, and the fname is
     hirs.nj.hdf.t%y4%m2%d2.
     This file name "template" is a GrADS like pattern for matching
     remote file names (that is, files to be retrieved).
     Supported tokens are:

          %y4       year,  e.g., 1997
          %y2       year,  e.g., 97
          %m2       month, e.g., 12
          %d2       day,   e.g., 31
          %h2       hour,  e.g., 18
          %c        matches any character [?]
          %n        matches any single digit [0-9]

    In addition to GrADS-like tokens, any defined environment variable
    can be used in the remote file name template. For example,

     \${MHOST}:/u/joiner/tovs/l1b/%y4%m2/l1c_new/hirs.nj.hdf.t%y4%m2%d2

   would take the remote host name from the environment variable \$MHOST.

SEE ALSO

    acquire - Retrives files from mass storage with look-ahead capability

AUTHORS

     Eueng-nan Yeh (enyeh\@dao.gsfc.nasa.gov)

EOF
;
    exit(1)
}
