#!/usr/bin/perl -w
# +-======-+ 
#  Copyright (c) 2003-2007 United States Government as represented by 
#  the Admistrator of the National Aeronautics and Space Administration.  
#  All Rights Reserved.
#  
#  THIS OPEN  SOURCE  AGREEMENT  ("AGREEMENT") DEFINES  THE  RIGHTS  OF USE,
#  REPRODUCTION,  DISTRIBUTION,  MODIFICATION AND REDISTRIBUTION OF CERTAIN 
#  COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE UNITED STATES GOVERNMENT AS 
#  REPRESENTED BY THE GOVERNMENT AGENCY LISTED BELOW ("GOVERNMENT AGENCY").  
#  THE UNITED STATES GOVERNMENT, AS REPRESENTED BY GOVERNMENT AGENCY, IS AN 
#  INTENDED  THIRD-PARTY  BENEFICIARY  OF  ALL  SUBSEQUENT DISTRIBUTIONS OR 
#  REDISTRIBUTIONS  OF THE  SUBJECT  SOFTWARE.  ANYONE WHO USES, REPRODUCES, 
#  DISTRIBUTES, MODIFIES  OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED 
#  HEREIN, OR ANY PART THEREOF,  IS,  BY THAT ACTION, ACCEPTING IN FULL THE 
#  RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT.
#  
#  Government Agency: National Aeronautics and Space Administration
#  Government Agency Original Software Designation: GSC-15354-1
#  Government Agency Original Software Title:  GEOS-5 GCM Modeling Software
#  User Registration Requested.  Please Visit http://opensource.gsfc.nasa.gov
#  Government Agency Point of Contact for Original Software:  
#  			Dale Hithon, SRA Assistant, (301) 286-2691
#  
# +-======-+ 
#=======================================================================
#
# Name: getsponsor.pl
# Purpose: get task groupID either from a file which maps users to tasks
#          or from the getsponsor utility or from the groups command
#
# output
# => $groupID (printed to standard output)
#
# Notes:
# 1. If more than one groupID is available, then the user is prompted
#    to select one.
# 2. If no groupID is found, a blank is printed.
#
# !REVISION HISTORY:
# 03May2007  Stassi  Initial version.
# 27Apr2009  Stassi  Divided script into subprograms and added "noprompt" option
# 24Jun2009  Stassi  Added option to get groupID from task map file
# 24Jul2009  Stassi  Added option to get groupID from "groups" command
#=======================================================================
use strict;

# global variables
#-----------------
my (@GID, @lines);
my ($groupID, $user);
my ($noprompt, $usefirst, $quiet);
my ($getsponsor, $mapfile);

# main program
#-------------
{
    init();

    # get info into global variables: @GID and @lines
    #------------------------------------------------
    get_info_from_file();
    get_info_from_utility() unless @GID;
    get_info_from_groups() unless @GID;

    # select groupID from info
    #-------------------------
    prompt_for_groupID();
    warn ">> Warning << groupID has not been set;" unless $groupID or $quiet;
    print "$groupID\n";
}

#=======================================================================
# name - init
# purpose - initialize variables, get runtime parameters
#=======================================================================
sub init {
    use Getopt::Long;
    my $help;

    # initializations
    #----------------
    $groupID = "";
    $user = $ENV{"USER"};

    # runtime parameters
    #-------------------
    GetOptions("noprompt" => \$noprompt,
               "1"        => \$usefirst,
               "f=s"      => \$mapfile,
               "q"        => \$quiet,
               "h"        => \$help);
    usage() if $help;

    # automatically set quiet flag for noprompt mode
    #-----------------------------------------------
    $quiet = 1 if $noprompt;

    # default name for task map file
    #-------------------------------
    $mapfile = "/share/fvpsas/etc/MapGIDLoginIDTask.rc" unless $mapfile;
}

#=======================================================================
# name - get_info_from_file
# purpose - get groupID info from a file which maps users to groupIDs
#
# output 
# => values stored in global variables: @lines and @GID
#=======================================================================
sub get_info_from_file {
    my (@all, $line, $title);
    my ($name, $gid, $desc);

    # return if map file is not found
    #--------------------------------
    unless (-e $mapfile) {
        warn ">> Warning << $mapfile not found;" unless $quiet;
        return;
    }

    # get lines from map file
    #------------------------
    open MAP, $mapfile or die ">> Error << opening $mapfile: $!";
    chomp(@all = <MAP>);
    close MAP;
    @lines = grep { /$user/ } @all;

    # extract group IDs for each valid task
    #--------------------------------------
    foreach $line (@lines) {

        # remove leading/trailing blanks
        #-------------------------------
        $line = $1 if $line =~ /^\s*(.+)\s*$/;

        # valid groupID, if first item is user name
        #------------------------------------------
        ($name, $gid, $desc) = split /\s+/, $line;
        push @GID, $gid if $name eq $user;
    }

    # warn if no valid tasks found
    #-----------------------------
    warn ">> Warning << no tasks found in $mapfile for <$user>;"
        unless @GID or $quiet;

    # Add title to front of @lines and blank to end
    #----------------------------------------------
    $title = "\nAuthorized GroupIDs for <$user> from $mapfile\n"
        .      "-"x77;
    unshift @lines, $title;
    push @lines, "";
}

#=======================================================================
# name - get_info_from_utility
# purpose - use groupID info from the getsponsor utility
#
# output 
# => values stored in global variables: @lines and @GID
#=======================================================================
sub get_info_from_utility {
    my ($getsponsor, $status, $line, @items);

    # check availability of getsponsor utility
    #-----------------------------------------
    $getsponsor = "xxx";
    $status = system("which getsponsor >& /dev/null");
    chomp($getsponsor = `which getsponsor`) unless $status;

    unless (-x $getsponsor) {
        warn ">> Warning << getsponsor utility not found;" unless $quiet;
        return;
    }

    # get info from getsponsor
    #-------------------------
    chomp(@lines = `$getsponsor`);

    foreach $line (@lines) {
        next unless $line;

        # remove leading/trailing blanks
        #-------------------------------
        $line = $1 if $line =~ /^\s*(.+)\s*$/;

        # assume first item is valid groupID if it matches correct pattern
        #-----------------------------------------------------------------
        @items = split /\s+/, $line;
        push @GID, $items[0] if $items[0] =~ /\b\w{1}\d{4,5}\b/;
    }

    # warn if no valid tasks found
    #-----------------------------
    warn ">> Warning << no tasks found with getsponsor utility for <$user>;"
        unless @GID or $quiet;
}

#=======================================================================
# name - get_info_from_groups
# purpose - use groupID info from the groups command
#
# output 
# => values stored in global variables: @lines and @GID
#=======================================================================
sub get_info_from_groups {
    my ($groups, $status, @groupinfo, $line, @items, $item);

    # check availability of groups command
    #-------------------------------------
    $groups = "xxx";
    $status = system("which groups >& /dev/null");
    chomp($groups = `which groups`) unless $status;

    unless (-x $groups) {
        warn ">> Warning << groups command not found;" unless $quiet;
        return;
    }

    # Load a label for first line when prompting user
    #------------------------------------------------
    push @lines, "\n\nSp Code";
    push @lines,     "-------";

    # get info from groups
    #---------------------
    chomp(@groupinfo = `$groups`);

    foreach $line (@groupinfo) {
        next unless $line;

        # remove leading/trailing blanks
        #-------------------------------
        $line = $1 if $line =~ /^\s*(.+)\s*$/;

        # extract valid groupIDs from each line
        #--------------------------------------
        @items = split /\s+/, $line;
        foreach $item (@items) {
            if ( $item =~ /\b\w{1}\d{4,5}\b/ ) {
                push @GID, $item;
                push @lines, $item;
            }
        }
    }
    push @lines, "\n";

    # warn if no valid tasks found
    #-----------------------------
    warn ">> Warning << no tasks found with groups command for <$user>;"
        unless @GID or $quiet;
}

#=======================================================================
# name - prompt_for_groupID
# purpose - prompt user for which groupID to use
#=======================================================================
sub prompt_for_groupID {
    my ($default, $cnt, $MAXTRIES, $ans, $found);

    # don't prompt if no task groupIDs found
    #---------------------------------------
    return unless @GID;

    # if only one task groupID found, then use it
    #--------------------------------------------
    if (scalar(@GID) == 1) {
        $groupID = $GID[0];
        return;
    }

    # use default groupID, if noprompt
    #---------------------------------
    $default = $GID[0]      if $usefirst;
    $default = $GID[-1] unless $usefirst;

    if ($noprompt) {
        $groupID = $default;
        return;
    }

    # query for group ID
    #-------------------
    $cnt = 1;
    $MAXTRIES = 3;

    while (1) {

        # print choices
        #--------------
        foreach (@lines) { print STDERR "$_\n"; }
        print STDERR "select group: ";
        print STDERR "[$default] " if $default;

        # get response
        #-------------
        chomp($ans = <STDIN> );
        $ans =~ s/\s*//g;
        $groupID = $default unless $groupID = $ans;

        # check validity of response
        #---------------------------
        foreach (@GID) { $found = 1 if $groupID eq $_; }
        last if $found;

        # too many unsuccessful attempts
        #-------------------------------
        if (++$cnt > $MAXTRIES) {
            $groupID = "";
            warn ">> Warning << Invalid input;";
            last;
        }

        # try again
        #----------
        warn "\n\n!!! groupID $groupID not found in list."
            . " Please choose a groupID from list below;";
    }
}

#=======================================================================
# name - usage
# purpose - print usage information to standard output
#=======================================================================
sub usage {
    use File::Basename;
    my $name;

    $name = basename $0;
    print STDERR <<"EOF";

usage: $name [options]

   options:
     -f mapfile     file containing mapping between users and tasks
     -h             Print this usage information
     -noprompt      Do not prompt for response; return default response
     -q             Quiet mode; do not print some of the warning messages
     -1             (This is #1) Use first available groupID as the default.
                    Otherwise the script defaults to last available groupID.

EOF
exit;
}
