#!/usr/bin/perl
# IBM_PROLOG_BEGIN_TAG 
# This is an automatically generated prolog. 
#  
# bos720 src/bos/usr/samples/ahafs/samplePrograms/evMon/mon_1event.pl 1.1 
#  
# Licensed Materials - Property of IBM 
#  
# Restricted Materials of IBM 
#  
# COPYRIGHT International Business Machines Corp. 2009 
# All Rights Reserved 
#  
# US Government Users Restricted Rights - Use, duplication or 
# disclosure restricted by GSA ADP Schedule Contract with IBM Corp. 
#  
# IBM_PROLOG_END_TAG 
# Subroutines in this FILE  mon_1event.pl:
#      read_arguments
#      syntax
#      monitor_a_event
#      aha_mon_file
#      create_parentdir
#      read_data
# PURPOSE:
#    To test monitoring an AHA event represented by an AHA file
#     with suffix ".mon".
#    In more details, this programe issues a select() call on the
#     the corresponding  .mon file, and waits for the event to happen.
# SYNTAX:
#    mon_1event <aha-monitor-file> [<key1>=<value1>[;<key2>=<value2>;...]]
#      e.g. mon_1event.pl  /aha/fs/utilFs.monFactory/var.mon "THRESH_HI=95"
#           mon_1event.pl  /aha/mem/vmo.monFactory/npskill.mon
# CHANGELOG: 2008/04/01 Updated by R.S.Burugula
#            2008/04/09 Updated by J.Jann (/aha/fs/)
#            2008/10/30 Updated by R.S.Burugula, N.Dubey
#            2008/11/15 Updated by J.Jann
#            2009/01/21 Updated by N.Dubey
#            2009/07/30 Updated by N.Dubey
use FileHandle;

undef $monFile;
undef $wrStr;

# Main function
#=============================================================================
# A) Read the arguments
     &read_arguments(@ARGV);

# B) Monitor event/events

     &monitor_a_event;

     exit (0) ;

# 1 ---------------------------------------------------------------------------
# NAME: read_arguments
# PURPOSE: To digest the command line arguments and initialize global variables.
sub read_arguments
{
   if ($#ARGV < 0)
   {
          syntax();
          exit (-1);
   }
   $monFile = shift;
   $wrStr   = shift;
   if (! defined $wrStr )
   {
       $wrStr = "CHANGED=YES"
   }
}

# 2 ---------------------------------------------------------------------------
# NAME: syntax
# PURPOSE: To print the syntax
sub syntax
{
  printf("\nSYNTAX: %s <aha-monitor-file> [<key1>=<value1>[;<key2>=<value2>;...]] \n",$0);
  printf(" where: \n");
  printf("  <aha-monitor-file> : Pathname of an AHA file with suffix \".mon\".\n");
  printf("  The possible keys and their values are:\n");
  printf("   --------------------------------------------------------------- \n");
  printf("        Keys  |       values             |      comments           \n");
  printf("   =============================================================== \n");
  printf("    WAIT_TYPE | WAIT_IN_SELECT (default) | uses select() to wait.  \n");
  printf("              | WAIT_IN_READ             | uses read() to wait.    \n");
  printf("   -----------|--------------------------|------------------------ \n");
  printf("    CHANGED   | YES (default)            | monitors state-change.  \n");
  printf("              | or not-YES               | It cannot be used with  \n");
  printf("              |                          |  THRESH_HI.             \n");
  printf("   -----------|--------------------------|------------------------ \n");
  printf("    THRESH_HI | positive integer         | monitors high threshold.\n");
  printf("   ----------------------------------------------------------------\n\n");
  printf("Examples: \n");
  printf("   1: %s /aha/fs/utilFs.monFactory/var.mon  \"THRESH_HI=95\"\n", $0);
  printf("   2: %s /aha/fs/modFile.monFactory/etc/passwd.mon \"CHANGED=YES\" \n",$0);
  printf("   3: %s /aha/mem/vmo.monFactory/npskill.mon  \n", $0);
  printf("   4: %s /aha/cpu/waitTmCPU.monFactory/waitTmCPU.mon \n", $0);
  printf("                     \"WAIT_TYPE=WAIT_IN_READ;THRESH_HI=50\" \n");
}

# 3 --------------------------------------------------------------------------
sub monitor_a_event
{
    #Make sure the file is an AHA monitor file.
    if ( ! &aha_mon_file($monFile) )
    {
        exit (-1);
    }

    &create_parentdir($monFile);

    print "Monitor file name: $monFile\n";

    open($FHANDLE, "+>$monFile") or die "Cannot open the file $monFile\n";
    $FHANDLE->autoflush(1);

    print "Write String  : $wrStr\n";
    print  $FHANDLE $wrStr or die "Cannot write $wrStr into the file $monFile\n"; ;

    if ($wrStr =~ m/WAIT_TYPE=WAIT_IN_READ/)
    {
        # Nothing to do; just pass through to the read below.
      print "Entering  read() to wait until the event corresponding to the AHA node $monFile occurs.\n";
      print "Please issue a command from another window to trigger this event.\n\n";
    }
    else
    {
        my ($rin, $rout, $nfound);
        $rin = "";
        vec($rin, fileno($FHANDLE),1) = 1;

        print "Entering  select() to wait until the event corresponding to the AHA node $monFile occurs.\n";
        print "Please issue a command from another window to trigger this event.\n";
        $nfound = select($rout=$rin, undef, undef, undef);

        print "\nThe select() completed.\n";
        if ($nfound <= 0) # No event occurred or an error was found.
        {
            print "The select() returned $nfound .\n";
            close($FHANDLE);
            exit (1);
        }
        print "The event corresponding to the AHA node $monFile has occurred.\n\n";
    }
    &read_data($FHANDLE);
    close($FHANDLE);
}

# 4 ---------------------------------------------------------------------------
# NAME: aha_mon_file
# PURPOSE: To check whether the file is an AHA monitor file.
sub aha_mon_file
{
   my $dfAha = "/usr/bin/df | grep -w /aha 2>/dev/null 1>&2";
   my $cwd = $ENV{"PWD"};
   my $mfile = shift;

   system $dfAha ;
   if ($? != 0)
   {
       print "The /aha filesystem is not mounted.\n";
       return 0;
   }

   if  ($mfile =~ /\.mon$/)
     {
       if ($mfile =~ /^\/aha\//)    # Absolute path and starts with /aha
         {
           return 1;
         }
       elsif ( !($mfile =~ /^\//)   # Relative path and
               && ($cwd =~ /^\/aha/)   # cwd contains /aha
             )
         {
           return 1;
         }
     }
   print "The $mfile is not an AHA monitor file.\n";
   return 0;
}

# 5 --------------------------------------------------------------------------
sub create_parentdir
{
    my $mfile = shift;
    my $dirname=`/usr/bin/dirname $mfile`;
    if (! -d $dirname)
    {
      system "/usr/bin/mkdir -p $dirname ";
    }
}

# 6 --------------------------------------------------------------------------
sub read_data
{
    my $start = 0;
    my $tm    = "";
    my $pid   = 0;
    my $uid   = 0;
    my $luid  = 0;
    my $gid   = 0;
    my $uName = "";
    my $lName = "";
    my $gName = "";
    my $prgName = "";

    my $fhandle  = shift;

    # Need to reset the offset to the beginning of the file before reading it.
    seek $fhandle, 0, 0;

  LOOP1:
    while (<$fhandle>)
    {
        if  ( ($start == 0) && ($_ =~ /TIME_tvsec=(\d+)\s*/ ) )
        {
            $start = 1;
            $tm    = localtime($1);
        }
        elsif ($start == 1)
        {
            if( $_ =~ /PID=(\d+)\s*/ )
            {
                $pid = $1;
            }
            elsif ( $_ =~ /UID=(\d+)\s*/ )
            {
                $uid = $1;
            }
            elsif ( $_ =~ /UID_LOGIN=(\d+)\s*/ )
            {
                $luid = $1;
            }
            elsif ( $_ =~ /GID=(\d+)\s*/ )
            {
                $gid = $1;
            }
            elsif ( $_ =~ /PROG_NAME=(\S+)\s*/ )
            {
                $prgName = $1;
            }
            elsif ( $_ =~ /STACK_TRACE:\s*/)
            {
                $uName = getpwuid($uid);
                $lName = getpwuid($luid);
                $gName = getgrgid($gid);

                print "\nUser Info     : userName=$uName, loginName=$lName, groupName=$gName \n";
                print "Process ID    : $pid\n";
                print "Program Name  : $prgName\n";
                print "Time          : $tm\n";

                print "\nStack Trace   :\n";
                $start = 2;
            }
        }
        else
        {
            print "$_";
        }
        if (/^END_EVENT_INFO$/)
        {
            last LOOP1;
        }

        goto LOOP1;
    }
    print "\n";
}
