#!/bin/csh -f
#
#                   ************************************************************
#                   ****                                                    ****
#                   ****  Originally designed for the USACOM GCCS Network.  ****
#                   ****                                                    ****
#                   ************************************************************
#
# sagrep            Author:   Joe Wulf - 960708@19:10 EDT.
#
#
# FUNCTION: sagrep: Super-ACOM-grep; or System-Administrator grep.  Companion
# --------  to the zlister process.  zlister generates and compresses complete
#           listings of the filesystem.  sagrep is the tool used to query
#           those accumulated files for any desireable pattern of text.
#           sagrep basically performs the following command:
#           "zcat {/path/to/compressed/filename.Z} | grep {pattern}."
#           Utilize "sagrep" without any arguments to receive a help message
#           showing command usage.  The display of that information is placed
#           near the bottom of this script.
#
#
# STANDARD SCRIPT LOCATION (and purpose):
# --------------------------------------
# /sysadmin/zlister.bin/sagrep:
#           Post-zlister-execution script to support retrieval of data.
#           zlister must have been executed at least once for sagre to be
#           useful.  Tool used to query compressed output of zlister for desired
#           pattern.  It is benificial to have a link to this script from
#           "/usr/local/bin" to ease access to general users.
#
#
# FILES/DIRECTORIES USED:
# ----------------------
#
#
# HISTORY:
# -------
# 1.0  Provided basic capability of identifying and querying the current file
#      for the current server as well as other (remote) servers.  Included
#      usage/help for the user.  Some documentation/explaination.
# 1.1  Enhanced logic when temporarily installed or referenced from somewhere
#      else (especially if that location is on the users' path).
#
#
# INSTALLATION INSTRUCTIONS:
# -------------------------
# 1)  This sagrep csh script will execute without modification, providing the
#     zlister csh script is installed, without modification, in the "standard"
#     location: /sysadmin/zlister.bin/sagrep.  When only testing the execution
#     of zlister file generation and subsequent sagrep data retrieval, then
#     the expected location will be /tmp/zlister.bin (because that is where the
#     files will untar to).
#
# 2)  The typical configuration will have zlister and its accompanying scripts
#     reside on a single master server.  The directory "/sysadmin" (or where
#     you establish) will be physically/logically resident on that master
#     server.  /sysadmin will then be NFS 'share'd from that master server.
#     The remaining servers/clients within the network will remotely mount
#     "/sysadmin" from the master server.  This will provide for easy and
#     consistent execution and data retrieval.
#
# 3)  To change the standard location from /sysadmin, the $Prod variable
#     (below) should be modified.  Set it to the same location used in the
#     zlister script.
#
# 4)  Make a soft link from a location that will typically appear in the users'
#     path (/usr/local/bin for example) to the sagrep script.
#     "ln -s /usr/local/bin/sagrep /sysadmin/zlister.bin/sagrep"
#     This will simplify management of the script/process when changes are made.
#     Of course, the link target will need to be changed if you choose to move
#     the default location.
#
#
#
#
# PLANNED ENHANCEMENTS:
# --------------------
# The logic will have to change to support server names that begin with
#   uppercase letters.
#
# Incorporate fix(s) to support mounting/umounting of /sysadmin.  In support of
#   normally unmounted /sysadmin.
#
# Implement a review header option.  This would zcat the top of the selected
#   file until the filesystem listing begins
#   (at: "---[Begin Server File System Listing]---").
#
# Implement an option to cut the output text so that only the path is displayed.
#
# Real home of this scripts should be /sysadmin/zlister.bin/sagrep.  If not
#   found there, check /tmp/zlister.bin.  If not found there attempt to use
#   the current working directory.
#
# Test:  SABusyMsg 80 130 Installing Selected Segments ...
# Test:  Access to the files, via sagrep, by all users.
#
# Consider adding a numerical report at the end of how many lines were found.
# Consider adding an option to review an entire file.
#
# Add logic to check Current for "Never" and properly handle.
#
#
#
#
#
#
#
#
# SCRIPT EXECUTION BEGINS:
# -----------------------
# set echo
set VerDate         = "960518"
set sagrep_version  = "1.1"

set bad = "999"

# Modify $path to support implementation on other than Solaris servers; path is protected in support of manual execution.
set prot_path = "$path"
# echo "Path var was already set with: ($path)."
# echo " "

# Improve the following with aliases for non-Solaris commands.
set IAM=`uname`
switch ( $IAM )
       case "SunOS":
            #Solaris 2.3 (GCCS Standard), though this has also worked under 2.4 and 2.5.
            # echo "SunOS"
            set path=( /bin /usr/bin /etc /sbin /usr/bin/X11 /usr/sbin /usr/etc /usr/local/bin )
            set path=($path /usr/ucb /usr/ccs/bin /usr/lib /usr/lib/nis )
            alias df-k '/bin/df -k'
            breaksw
       case "HP":
            # Not tested (guessed).    {Need specific Version #'s}
            # echo "HP"
            set path=( /bin /usr/bin /etc /sbin /usr/bin/X11 /usr/sbin /usr/etc /usr/local/bin )
            set path=($path /usr/lib /usr contrib/bin )
            alias df-k '/bin/bdf -L'
            breaksw
       case "HP-UX":
            # (Tac-3) "HP-UX starbase A.09.01 E 9000/750"
            # (Tac-4) "HP-UX hpinst1  A.09.07 E 9000/712"
            # (Tac-4) "HP-UX orbiter  B.10.00 A 9000/712"
            # echo "HP-UX"
            set path=( /bin /usr/bin /etc /sbin /usr/bin/X11 /usr/sbin /usr/etc /usr/contrib/bin )
            set path=($path /usr/local/bin /usr/lib /usr/tran/sparc/bin /utils )
            set ver = `uname -a | cut -d' ' -f3`
            if ( $ver == "B.10.00" ) then
                 alias df-k '/bin/bdf -L'
            else
                 if ( $ver == "A.09.01" || $ver == "A.09.07" ) then
                      alias df-k '/usr/bin/bdf -L'
                 else
                      echo "Your specific version of HP-UX is unknown to this environment."
                      echo "Locate your 'bdf' and 'automount' executables, then"
                      echo "update this script (zlister and zlister.stats) with"
                      echo "the locations for those binarys."
                      echo " "
                      exit $bad
                 endif
            endif
            breaksw
       case "Linux":
            # echo "Linux"
            set path=( /etc /bin /usr/bin /usr/sbin /usr/ucb /sbin /usr/X11R6/bin /usr/X11/bin )
            set path=($path /usr/openwin/bin /usr/local/bin )
            alias df-k '/bin/df -k'
            breaksw
       default:
            echo "Your operating system ($IAM) is unknown to this environment."
            echo "Might have to include code to figure out where the basic commands are."
            echo "Exiting..."
            exit $bad
            breaksw
endsw
if ( -e /sysadmin ) then
   set path=( $path /sysadmin /sysadmin/zlister.bin )
else
   if ( -e /tmp/sysadmin ) then
        set path=( $path /tmp/sysadmin /tmp/sysadmin/zlister.bin )
   endif
   # Update this piece with the current location of the executable scripts, else exit.
endif
# echo "Path var now set with: ($path)."
# echo " "

# Identify the location of our data.
if ( -e /sysadmin/zhostlists ) then
     # Found data location under /sysadmin (standard location)
     set Prod='/sysadmin/zhostlists'
else
     if ( -e /tmp/zhostlists ) then
          # Found data location under /tmp (alternate when just starting)
          set Prod='/tmp/zhostlists'
     else
          # Data location not found.
          echo "Data location not found.  Most likely zlister has not yet"
          echo "been successfully run."
          echo " "
          echo "Exiting..."
          exit $bad
     endif
endif

# Add logic to properly isolate the work output subdirectory and utilize /tmp if not found.

# We should be checking default current date from 'Current' not $IT.
set ERROR       = " "                     # Try ' ' ","
set Dest        = "Usage"                 # Default destination should nothing else modify this course.
set DT          = `date +%y%m%d`
set case        = " "                     # Supports "sensitive"; contains "-i" for "insensitive".
set sensitiv    = "sensitive"
set Srvr        = `hostname`

if ( -e $Prod/$Srvr/Current ) then
     set Crnt   = `cat $Prod/$Srvr/Current | head -1`
else
     set Crnt   = "Never"
endif

set DIFF        = "Z"                     # or can be set to = diff.Z
set DF          = ""
set greps       = "1"                     # Number of greps to perform: one file (1) or many (2).
set SFlag       = "False"                 # Test if we have manually figured out what servers we
                                          #   have data available to query from/to.
set DFlag       = "False"                 # Test if we have manually figured out what dates we
                                          #   have data available to query from/to.
set AvailSrv    = ""                      # Servers available to search/query.
set Star        = "$*"                    # Preserve what was entered by the user.


# VH is the list of valid hosts (servers) available to query.  Is equivlent to the
#    relative parent for each storage place.  Add to this list as you see fit.
#    MIGHT have to modify the logic, though, if we exceed seven hosts - to protect
#    what is displayed on each line.  Only include servers here that listings actually
#    exist for (or that you'll be immediately creating).
#    Apply logic to auto-determine these.
#
  set VH           = "`find $Prod/* -prune -type d -exec basename {} \; | tr '\012' ' '`"

# Write process to auto-build the proper number of dashes and blank spaces for proper # of servers.
  set VHL         = "---------- ---------- ---------- ---------- ---------- ---------- ----------"


#echo "(0), ${#argv}, ($1)"
if ( ${#argv} == 0 ) then
   # No arguments were supplied."
   goto Usage
endif

# Must do special handling when patterns begin with a dash (dealt with via 'od').
if ( ${#argv} == 1 ) then
   set TextPattern = $1
   set First = `echo $TextPattern | cut -c1-2 | od -bc | head -1 | cut -c9-15`
   switch ( "$First" )
       case "055 150":   # "-h"
            goto Usage
            breaksw;
       case "055 154":   # "-l"
            # Must take into account width of window (if determinable) and the number of servers to list.
            #   If a long list, then must parse to be pleasing to the eye.
            # Could parse anyway with an auto-determination of 5 servers to a line.(?)
            goto ListAvail
            breaksw;
       default:
            # When not asking for usage help or a list of available dates,
            #   then, by default, grep current server and current date.
            goto OneGrep
            breaksw
   endsw
endif

#    set i = # of arguments minus one for the text/pattern; to make sure we get them all.
@ i        = ${#argv} - 1
#set echo
while ( i != 0 )
    set one = $1
    set First = `echo $one | cut -c1-2 | od -b | head -1 | cut -c9-15`
    #echo "(1--) i($i), one($one), First($First), Dest($Dest)."
    switch ( "$First" )
         case "055 150":   # "-h", put here if the user made this mistake.
              set ERROR = "$ERROR, Too many arguments: (-h)"
              breaksw;
         case "055 154":   # "-l", put here if the user made this mistake.
              set ERROR = "$ERROR, Too many arguments: (-l)"
              breaksw;
         case "055 151": # -i
              #echo "(4s) -i, 055 151"
              set case     = "-i"
              set sensitiv = "insensitive"
              # Set to one if not already set to 2 (MultGrep).
              if ( $greps != "2" ) then
                 set greps    = "1"
              endif
              breaksw;
         case "055 144": # -d
              #echo "(4s) -d, 055 144"
              # Validate proper diff-file exists or exit with error msg
              set DIFF     = "diff.Z"
              set DF       = ".diff"
                 # Does this really belong here???????????????????
                 # Set to one if not already set to 2 (MultGrep).
                 #if ( $greps != "2" ) then
                 #   set greps    = "1"
                 #endif
              breaksw;
         case "055 123": # -S
              # In the future, allow for selectively searching multiple servers (-Sa -Sb -Sc, etc...).
              # echo "Case made for -S...  (4s) -S, 055 123"
              set two = `echo $one | cut -dS -f2`
              # echo "two($two)."
              if ( $two == "all" || $two == "ALL" ) then
                 set greps   = "2"
                 set Srvr    = "All Servers"   # Shouldn't this be set to $VH instead???
                 #Insert logic to support getting contents of Current from all servers...
                 #  This side of .else. is for searching all servers.
                 # echo "two($two), greps ($greps), Srvr($Srvr)."

                 # Revalidate this if-check, as everything is NOT needed.
                 if ( $SFlag == "False" ) then
                      # echo "(1) SFlag($SFlag), VH(.$VH.), AvailSrv($AvailSrv)"
                      # FUNCTION to determine all searchable servers
                      #          (csh does not have functions).
                      #          (Must manually place every instance its use is desired).
                      #   Allow to be executed twice;
                      #     1) if from -D (flag fail check)
                      #        -or from first -S
                      #     2) from first use of -S
                      #                When called by -S, check for "all" and handle/modify as appropriate.
                      #                If not "all" then modify for server desired (if avail).
                      #        If server-text = "all" then return all server names and MultGrep="2"
                      #                               else if server-text <> valid hostname($VH) then
                      #                                       display usage
                      #
                 endif
                 set SFlag = "True"
                 # echo "SFlag($SFlag)"
              else
                 # This side of else is for determining only the name of one server.
                 # When desired server does not exist, exit to Usage
                 # Validate Server file exists or exit with error message
                 #   SFlag is True, we've already ID'd searchable servers.
                 # Test-Server-Existance (tse).
                 # echo "two($two) <> all"
                    foreach tse ($VH)
                        # echo "Long check... (2): tse($tse), VH($VH), AvailSrv($AvailSrv)"
                        # echo " "
                        if ( ( ( -e $Prod/$tse ) & ( -d $Prod/$tse ) ) & ( $tse == $two ) ) then
                           # echo "We found our match... (3)AvailSrv($AvailSrv), Prod/tse($Prod/$tse)"
                           # echo " "
                           set AvailSrv = $AvailSrv "$tse "
                           set Srvr = $tse
                           set Crnt = `cat $Prod/$Srvr/Current | head -1`
                           # echo "(4)AvailSrv($AvailSrv), tse($tse), Srvr($Srvr)."
                           break
                        endif
                    end
                    #IF the above check did not match requested server to existing searchable
                    # Server(s) than exit to usage.
                    #echo "After foreach"
                    #echo " "
                    if ( $tse != $two ) then
                       set ERROR   = "$ERROR, Failed to find server($two)"
                    endif
              endif
              unset two
              breaksw;
         case "055 104": # -D
              #echo "(4s) -D, 055 104"
              set two = `echo $one | cut -dD -f2`
              if ( $two == "all" ) then
                 set greps   = "2"
                 set DT      = "All Dates"
              else
                 # When requested date does not exist, exit to Usage
                 # Validate date file exists or exit with error message
                 # Only check normal dated files hostname.yymmdd.Z and
                 #   hostname.yymmdd.diff.Z.  Others are specials, privately created.
                 # Most likely will have to force the user to always enter
                 #   this arg AFTER -S...
              endif
              unset two
              breaksw;
         default:
              echo "(4s) default"
              set ERROR   = "$ERROR, Unknown Argument: ($First)"
              set Dest    = "Usage"
              breaksw
    endsw
    @ i--
    #echo " "
    if ( $i == 0 ) then
       break
    endif
    shift
end
#echo "End of While and switch."

# Should equal the final shifted argument (TextPattern)
shift; set TextPattern = $1

#echo "(5) i($i), one($one), First($First), Dest($Dest), ERROR($ERROR)."
if ( "$ERROR" != " " ) then
      #echo "ERROR was not equal to dot(.)"
      #echo $ERROR | od -bc
      set $Dest = "Usage"
   else
      if ( $greps == "1" ) then
         #echo "greps($greps)"
         set Dest = "OneGrep"
      else
         if ( $greps == "2" ) then
            #echo "greps($greps)"
            set Dest = "MultGrep"
         endif
      endif
endif
goto $Dest

OneGrep:
# Possibly expedite this using egrep?  Must test.
echo "sagrep(V:$sagrep_version):  Checking $Srvr$DF, date($Crnt), case($sensitiv), for($TextPattern)."
echo "zcat $Prod/$Srvr/$Srvr.$Crnt.$DIFF | grep $case $TextPattern"
echo "------------------------------------------------------------------------------------------------"
zcat $Prod/$Srvr/$Srvr.$Crnt.$DIFF | grep $case $TextPattern
goto AllDone

MultGrep:
# Similiar in form to original OneGrep, utilize several loops:
#   Outer loop will walk thru each server
#     Inner loop will walk a defined range of servers
#     This range will identify a starting/ending filename.
echo "sagrep(V:$sagrep_version):  Checking $Srvr$DF, date($Crnt), case($sensitiv), for("$TextPattern")."
echo "zcat $Prod/$Srvr/$Srvr.$Crnt.$DIFF | grep $case $TextPattern"
echo "------------------------------------------------------------------------------------------------"
echo " "
echo "No search functionality in place yet for multigrep."
echo " "
goto AllDone

Usage:
echo "You entered:  $0 $Star"
if ( $ERROR != " " ) then
     echo "ERROR($ERROR)"
endif
echo " "
echo "Usage: /usr/local/bin/sagrep [-h]                             V: $sagrep_version    $VerDate"
echo " "
echo "       /usr/local/bin/sagrep [-l]"
echo " "
echo "       /usr/local/bin/sagrep [-i] [-d] [-SserverName] [-Dyymmdd] text/pattern"
echo " "
echo "At this time, arguments must be given independently."
echo "Where: [-h]:            Displays usage."
echo "       [-l]:            Displays server(s) and dates available for searching."
echo "       [-i]:            Will ignore case, otherwise not."
echo "       [-d]:            Will search the .diff file(s) vice the normal listing."
echo "       [-Sservername]:  Valid servername to check for text/pattern."
echo "                        Without this, will default to \`hostname\`."
echo "                       *If 'all' is used, will search files for all servers."
echo "                        Currently, -S is REQUIRED before -D."
echo "      *[-Dyymmdd.hhmm]: Valid date to check for (based on ServerName)."
echo "                        If 'all' is used, will search files for all dates."
echo "                        Used where applicable (Older files have only the date.)"
echo "       text/pattern:    Any text/pattern grep will accept is valid here"
echo "                        and MUST be the last entry on the line."
echo "                        Double-qoutes must be escaped with backslashes."
echo " "
echo "* Indicates capabilities that are not yet complete."
#Give examples (& include doublequoted ones too)."
#echo "     To look for files containing \"-L" (<-><L>) use:"
#echo "        sagrep \"\"-L\"\""
#echo "        sagrep \"-L\"""
echo " "
goto AllDone

ListAvail:
# Generate list headed by servername and underneath the reverse sorted list of dates (i.e. Most current on top).
# Possibly open a scrollable xterm with the information requested; have window accept <RETURN> to disappear.
#   But make sure of the DISPLAY Variable.
# Get contents of all Current's | sort -f; eliminate non-standard files.
#
# Will have to make some spacing modifications here when a four character year is implemented.
echo "  Available servers (and dates per server):";echo "  (Please be patient while the list is generated)"
echo " "
setenv Dashes "";setenv x 0;setenv VH1 "";setenv VHT "";setenv y ""
setenv i ""
foreach i ( $VH )
    setenv Dashes " ----------- $Dashes"
    setenv x      `echo "$i" | awk '{print length($1)}'`
    setenv y      "`echo '       ' | cut -c $x-8`"
    if ( "$VHT" == "" ) then
         setenv VHT "$i$y"
    else
         setenv VHT "$VHT     $i$y"
    endif
    # setenv VHT    "$VH1"
    # echo "i($i), x($x), y($y), VH1($VH1)."
end
# Need to pretty up the end of $VHT spacing.
echo "[ $VHT]"
echo "[$Dashes]"
echo "But there currently is no logic here to decently list"
echo " all the files for each server.  See the next version."


AllDone:
set path = "$prot_path"
unset echo i First Dest DT Crnt Prod Srvr VH senitiv TextPattern DIFF one ERROR case Star
unset DF SFlag DFlag prot_path
