#! /bin/sh
#set -xv
#=========================================================================
# Copyright (C) GemTalk Systems 1986-2024.  All Rights Reserved.
#
# Name - searchlogs.sh
#
# Purpose - Script to search tranlogs in a directory for particular oops.
#           See "help" text for details.
#
#=========================================================================

usage() {
    cat <<EOF
===================================================================="
Usage:
`basename $0` [-h]|[<filters>][keyring <path>][privkey <file>][privkeypf <string>][privkeypffn <file>] <oop> ... <oop>

Purpose:

  To search all tranlogs in the current directory for selected oops.
  Secure tranlogs to be searched must all use the same private key.

  Make sure \$GEMSTONE is set.


Secure Tranlog Options (Required with tranlog*.sdbf files)

  keyring - Path to a directory containing private key files. May be specified
            more than once. Required for searching secure tranlogs.

  privkey - Name of the private key file. File name only, no path. If the 
            private key is protected by a passphrase, then ONE of privkeypf
            or privkeypffn must also be specified.

  privkeypf - passphrase for privkey.

  privkeypffn - name of a file containing the passphrase for privkey.

Options:

  -h (or no arguments)

    print this message and exit.

  <filters>

      Only print records that match any of the filtering criteria.
      One or more of the following pairs:

      user      username  - filter by GS UserProfile name 
      host      hostname  - filter by gem/topaz process host 
      client    X.X.X.X   - filter by client IP Address 
      euid      <integer> - filter by gem's effective UNIX user ID
      ruid      <integer> - filter by gem's real UNIX user ID
      luid      <integer> - filter by gem's login UNIX user ID
      euidstr   <string>  - filter by gem's effective UNIX user name
      ruidstr   <string>  - filter by gem's real UNIX user name
      luidstr   <string>  - filter by gem's login UNIX user name
      gempid    <integer> - filter by gem's process ID
      sessionid <integer> - filter by gem's session ID

      Filters must be listed in this order: user host client 

  Tranlogs are assumed to be named 'tranlogXXX.dbf'.
  Secure tranlogs are assumed to be named 'tranlogXXX.sdbf'.
  Override by setting \$GS_TRANLOG_PREFIX to the prefered value.

  WARNING: a maximum of 256 tranlogs can be analyzed in one set.

====================================================================

EOF
}

# check for -h or no args; print usage and exit
if [ "x$1" = "x" ] || [ "$1" = "-h" ]; then
    usage
    exit 0
fi 


# check that $GEMSTONE is set
if [ "x$GEMSTONE" = "x" ]; then
    echo "ERROR:  \$GEMSTONE not set" 1>&2
    exit 1
fi

# determine tranlog naming convention
if [ "x$GS_TRANLOG_PREFIX" = "x" ]; then
    GS_TRANLOG_PREFIX="tranlog"
fi

# debug
# echo "Using tranlog prefix $GS_TRANLOG_PREFIX"

# Check for $GEMSTONE/sys/pgsvrslow
if [ -f $GEMSTONE/sys/pgsvrslow ]; then
    pgsvrExe=$GEMSTONE/sys/pgsvrslow
else
    echo "ERROR:  \$GEMSTONE/sys/pgsvrslow not found" 1>&2
    exit 1;
fi

# debug
# echo "Using $pgsvrExe"


# setup list of tranlog names
tranlogs=`ls -1rt *$GS_TRANLOG_PREFIX*.dbf` 2>/dev/null
rc=$?
stranlogs=`ls -1rt *$GS_TRANLOG_PREFIX*.sdbf` 2>/dev/null
src=$?
haveTranlogs=0
haveTranlogsS=0
if [ $rc -ne 0 -a $src -ne 0 ]; then    
    echo "[Error]: No tranlogs or secure tranlogs found"
    exit 1
else
    if [ $rc -eq 0 ]; then
	haveTranlogs=1
    fi
    if [ $src -eq 0 ]; then
	haveTranlogsS=1
    fi        
fi

# initialize variables
filters=""
pFilter=""
oops=""
tmpfile="/tmp/gssearchlog$$"
privkey=""
privkeypf=""
privkeypffn=""
keyring=""

# debug
# echo "tmpfile = $tmpfile"

echo "quiet " >> $tmpfile

# loop over arguments..
while [ "x$1" != "x" ]
do

    # check for filtering keywords

    if [ "$1" = "user" ]; then
	echo "'$2' username" >>$tmpfile
	filters="$filters user $2"
	pFilter="$pFilter user $2"
	shift 2

    elif [ "$1" = "host" ]; then
	echo "'$2' gemhost" >>$tmpfile
	filters="$filters host $2"
	pFilter="$pFilter host $2"
	shift 2

    elif [ "$1" = "client" ]; then
	echo "'$2' clientip" >>$tmpfile
	filters="$filters client $2"
	pFilter="$pFilter client $2"
	shift 2

    elif [ "$1" = "euid" ]; then
	echo "$2 findeuid" >>$tmpfile
	filters="$filters findeuid $2"
	pFilter="$pFilter euid $2"
	shift 2

    elif [ "$1" = "ruid" ]; then
	echo "$2 findruid" >>$tmpfile
	filters="$filters findruid $2"
	pFilter="$pFilter ruid $2"
	shift 2

    elif [ "$1" = "luid" ]; then
	echo "$2 findluid" >>$tmpfile
	filters="$filters findluid $2"
	pFilter="$pFilter luid $2"
	shift 2

    elif [ "$1" = "euidstr" ]; then
	echo "'$2' findeuidstr" >>$tmpfile
	filters="$filters findeuidstr $2"
	pFilter="$pFilter euidstr $2"
	shift 2

    elif [ "$1" = "ruidstr" ]; then
	echo "'$2' findruidstr" >>$tmpfile
	filters="$filters findruidstr $2"
	pFilter="$pFilter ruidstr $2"
	shift 2

    elif [ "$1" = "luidstr" ]; then
	echo "'$2' findluidstr" >>$tmpfile
	filters="$filters findluidstr $2"
	pFilter="$pFilter luidstr $2"
	shift 2

    elif [ "$1" = "gempid" ]; then
	echo "$2 findgempid" >>$tmpfile
	filters="$filters findgempid $2"
	pFilter="$pFilter gempid $2"
	shift 2

    elif [ "$1" = "sessionid" ]; then
	echo "$2 findsessionid" >>$tmpfile
	filters="$filters findsessionid $2"
	pFilter="$pFilter sessionid $2"
	shift 2

    elif [ "$1" = "keyring" ]; then
	if [ ! -d "$2" ]; then
	    echo "[Error]: $2 is not a directory"
	    exit 1
	fi    
	keyring="$keyring $2"
	echo "'$2' setkeyring " >>$tmpfile
	shift 2

    elif [ "$1" = "privkey" ]; then
	privkey="$2"
	echo "'$2' setprivatekey " >>$tmpfile
	shift 2

    elif [ "$1" = "privkeypf" ]; then
	privkeypf="$2"
	echo "'$2' setprivatekeypf " >>$tmpfile
	shift 2

    elif [ "$1" = "privkeypffn" ]; then
	if [ ! -r "$2" ]; then
	    echo "[Error]: Cannot read private key passphrase file $2"
	    exit 1
	fi      
	privkeypffn="$2"
	echo "'$2' setprivatekeypffn " >>$tmpfile
	shift 2           
	
	# check if it's an oop number
    elif [ $1 -gt 0 ]; then
	oops="$oops $1"
	shift
	
	# otherwise don't know what it is
    else
	echo "Unrecognized keyword $1"
	shift
    fi

    # done with argument processing loop..
done

if [ $haveTranlogsS -eq 1 ]; then
    if [ "X$privkey" = "X" -o "X$keyring" = "X" ]; then
	echo "[Error]: privkey and keyring must be specified when searching secure tranlogs"	
	exit 1
    fi
fi

# privkeypffn and privkeypf are optional

# construct pgsvr commands
for each in $oops
do
    echo "$each findoop" >>$tmpfile
done

for each in $tranlogs
do
    echo "'$each' openlog 0 100000000 searchlog closedbf" >>$tmpfile
done

for each in $stranlogs
do
    echo "'$each' openlog 0 100000000 searchlog closedbf" >>$tmpfile
done

# debug: print out contents of temporary file
# echo "PGSVRSLOW command file contents:"
# cat $tmpfile
# exit

# print summary info
echo "Tranlog Analysis Search Log"
echo
echo "Searching for oops: $oops"
echo
echo "Searching tranlogs:"
echo
for each in $tranlogs
do
    echo "  $each"
done
echo
if [ "$filters" != "" ]; then
    echo "Filtering on: $pFilter"
fi

# now execute..
$pgsvrExe < $tmpfile
pStatus=$?
if [ $pStatus -ne 0 ]; then
    echo "pgsvr returned $pStatus";
    exit $pStatus
fi

# delete temporary file
rm -f $tmpfile 

#
# end of script


