#!/bin/sh

# bb-msgs.sh
#
# BIG BROTHER MONITORING SCRIPT
# Sean MacGuire
# Version 1.9
# Mar 13th, 2002
#
# (c) Copyright Quest Software, Inc.  1997-2002  All rights reserved.
#
# echo "***** BBHOME IS SET TO $BBHOME"
# echo "***** BBTMP IS SET TO $BBTMP"

if test ! "$BBTMP"                      # GET DEFINITIONS IF NEEDED
then
	 # echo "*** LOADING BBDEF ***"
        . $BBHOME/etc/bbdef.sh          # INCLUDE STANDARD DEFINITIONS
fi

PID="$$"

if test ! "$MACHINEDOTS"		# THIS SHOULD ALREADY BE SET...
then
	# Setup the name of the local host
	# Save a version of the machine name with '.' 
	# instead of ',', if any are there
	MACHINEDOTS=`echo $MACHINE | $SED 's/,/\./g'`
	if [ "$FQDN" != "TRUE" ]
	then
		OLDIFS=$IFS
		IFS='.'
		set $MACHINEDOTS >/dev/null
		IFS=$OLDIFS
		MACHINEMASK="${1}"
	else
		MACHINEMASK="${MACHINEDOTS}"
	fi
	export MACHINEDOTS MACHINEMASK
fi

#=====================================================================
# NOTIFY ON BAD MESSAGES
#=====================================================================
#
# echo "*** MESSAGES TEST ***"

#
# SET UP EXPIRY INFO
#
if test ! "$MSGEXPIRE"
then
	MSGEXPIRE="10:20"	# EXPIRE WARNINGS IN 10 MIN, PANICS IN 20
fi

set `echo $MSGEXPIRE | $SED "s/:/\ /g"`

EXPIREWARN="$1"			# EXPIRATION IN MINUTES
EXPIREPANIC="$2"

CHKDATE=`$DATE`

#
# REMOVE EXPIRED BAD MESSAGES FILES
#
if [ "$OLDSTYLEBBMSGS" = "TRUE" ]
then
	$RM -f $BBTMP/.expire $BBTMP/MSG.*
else
	$BBHOME/bin/touchtime 0 $BBTMP/.expire
	$FIND $BBTMP/. -name "MSG*" ! -newer $BBTMP/.expire -exec $RM -f {} \; 2> /dev/null
fi

#
# YOU CAN OVERRIDE VALUES SET IN etc/bbdef.sh
# IF THE CURRENT HOST HAS MATCHING ENTRIES IN etc/bb-msgstab
#

$RM -f $BBTMP/BBMSGS.$PID $BBTMP/BBMSGS.1.$PID $BBTMP/BBMSGS.2.$PID $BBTMP/BBMSGS.3.$PID $BBTMP/BBMSGS.4.$PID
if [ -f "$BBMSGSTAB" ]
then
	# a line can start with
	# :....
	#  :....
	# localhost:...
	# www:....
	# www.bb4.com:...
	#
	# All mask should allow for spaces/tabs before :
	# Grep for each mask
	for mask in "[ 	]*:" "[ 	]*localhost[ 	]*:" "[ 	]*${MACHINEDOTS}[ 	]*:" "[ 	]*${MACHINEDOTS}\..*:"
	do
		# SAVE MATCHING LINES in BBMSGS.$PID
		bbmsgsline=`$GREP "^${mask}" $BBMSGSTAB >>$BBTMP/BBMSGS.$PID 2>/dev/null`
	done

	# IF any line matched then continue
	if [ -s $BBTMP/BBMSGS.$PID ]
	then
		# If any ":" are found, force spaces around it to
		# make Solaris happy :(
		# Thanks to  Larry Parmelee <parmelee@CS.Cornell.EDU>
		# Remove the host also (last SED) - Douwe.Dijkstra@I-Pay.com
		$CAT $BBTMP/BBMSGS.$PID | $SORT -u | $SED 's/:/ : /g' | $SED 's/[^:]*://' | \
		while read line
		do
			OLDIFS=$IFS
			IFS=':'
			set bogus $line 2>/dev/null
			shift
			IFS=$OLDIFS
			# Results are sent to a file because some shells go into a subshell
			# during a while preceded by a pipe such that variables set within
			# that while will not be visible after exiting the while. The {} should
			# not send it within a subshell but I'm wary (especially SUN & DIGITAL)
			echo "${1} : ${2} : ${3} : ${4} : ${5}" >> $BBTMP/BBMSGS.1.$PID
			# Save the file names by themselves
			echo "${1}" >> $BBTMP/BBMSGS.2.$PID
		done
	fi
	$RM -f $BBTMP/BBMSGS.$PID
fi

#
# Build the list of message files
#
if [ -s $BBTMP/BBMSGS.2.$PID ]
then
	$CAT $BBTMP/BBMSGS.2.$PID | \
	while read file
	do
		if [ "$file" = "" ]
		then
			continue
		fi
		set $file
		while [ "$#" -ge 1 ]
		do
			echo $1 >> $BBTMP/BBMSGS.3.$PID
			shift
		done
	done
	if [ -s $BBTMP/BBMSGS.3.$PID ]
	then
		$SORT -u $BBTMP/BBMSGS.3.$PID > $BBTMP/BBMSGS.4.$PID
	fi
	$RM -f $BBTMP/BBMSGS.2.$PID $BBTMP/BBMSGS.3.$PID
fi

if [ -s $BBTMP/BBMSGS.4.$PID ]
then
	#
	# OK, entries in bb-msgstab overrides bbdef.sh entries
	# 
	MSGFILE=`$CAT $BBTMP/BBMSGS.4.$PID 2>/dev/null`
fi

# Use defaults if undefined
if [ "$REDMSGSLINES" = "" ]
then
	REDMSGSLINES=20
fi
if [ "$YELLOWMSGSLINES" = "" ]
then
	YELLOWMSGSLINES=10
fi

BADMSGFILE=""
for file in $MSGFILE
do
	MFILE=`echo $file | $SED "s:/:_:g"`
	if [ ! -f $file ] 
	then
		echo "
&red $file has vanished" >> $BBTMP/MSG.red.file
		$BBHOME/bin/touchtime $EXPIREPANIC $BBTMP/MSG.red.file

	elif [ ! -r $file ] 	# UNREADABLE
	then
		echo "
&red $file is unreadable" >> $BBTMP/MSG.red.file
		$BBHOME/bin/touchtime $EXPIREPANIC $BBTMP/MSG.red.file

	elif test "$CHKMSGLEN" = "TRUE" && test ! -s "$file"
	then
		echo "
&red $file is empty" >> $BBTMP/MSG.red.file
		$BBHOME/bin/touchtime $EXPIREPANIC $BBTMP/MSG.red.file
		BADMSGFILE="$BADMSGFILE $file"

	else			# PROCESS THE FILE NORMALLY
		$BBHOME/bin/touchtime $EXPIREPANIC $BBTMP/MSG.red.file

		# echo "Processing $file"
		if [ -f "$BBTMP/$MFILE" -a "$OLDSTYLEBBMSGS" != "TRUE" ]
		then
			LINES=`$CAT $BBTMP/$MFILE`
			LINES=`echo $LINES`
		else
			LINES="0"
		fi
		set bogus $WC
		shift
		TMPWC=$1
		set bogus `$TMPWC -c $file`
		shift
		NEWLINES="$1"
		if test "$NEWLINES" != "$LINES"
		then
			echo "$NEWLINES" > $BBTMP/$MFILE
			if test "$NEWLINES" -lt "$LINES"	# ROTATED!
			then
				LINES="0"			# SO RESET
				# REMOVE RED/YELLOW TEMP FILES FOR RECENT MESSAGES AS FILE HAS BEEN ROTATED
				$RM -f $BBTMP/MSG.red.$MFILE.* $BBTMP/MSG.yellow.$MFILE.*
			else
				LINES=`expr $LINES + 1`
			fi
	
			#
			# Are we using MSGS and PAGEMSG values from bb-msgstab ?
			# if $BBTMP/BBMSGS.4.$PID exists, then we are
			#
			if [ -s $BBTMP/BBMSGS.4.$PID ]
			then
				MSGS=""
				PAGEMSG=""
				IGNMSGS=""
				$RM -f $BBTMP/BBMSGS.PAGEMSG.$PID $BBTMP/BBMSGS.MSGS.$PID $BBTMP/BBMSGS.IGNMSGS.$PID
				$TOUCH $BBTMP/BBMSGS.PAGEMSG.$PID $BBTMP/BBMSGS.MSGS.$PID $BBTMP/BBMSGS.IGNMSGS.$PID
				$GREP "^${file}[ 	]*:" $BBTMP/BBMSGS.1.$PID |\
				while read line
				do
					OLDIFS=$IFS
					IFS=':'
					set bogus $line 2>/dev/null
					shift
					IFS=$OLDIFS
					echo "$3;" >> $BBTMP/BBMSGS.MSGS.$PID
					echo "$4;" >> $BBTMP/BBMSGS.PAGEMSG.$PID
					echo "$5;" >> $BBTMP/BBMSGS.IGNMSGS.$PID
				done
				PAGEMSG=`$CAT $BBTMP/BBMSGS.PAGEMSG.$PID | $GREP -v "^[ 	]*;$" | $SORT -u 2>/dev/null`
				MSGS=`$CAT $BBTMP/BBMSGS.MSGS.$PID | $GREP -v "^[ 	]*;$" | $SORT -u 2>/dev/null`
				# PAGEMSG must be in MSGS
				MSGS="$PAGEMSG;$MSGS"
				IGNMSGS=`$CAT $BBTMP/BBMSGS.IGNMSGS.$PID | $GREP -v "^[ 	]*;$" | $SORT -u 2>/dev/null`
				$RM -f $BBTMP/BBMSGS.PAGEMSG.$PID $BBTMP/BBMSGS.MSGS.$PID $BBTMP/BBMSGS.IGNMSGS.$PID
				# NEW WAY, DELIMITER IS ";"
				OLDIFS=$IFS
				IFS=";"
			else
				# OLD WAY, DELIMITER IS " "
				OLDIFS=$IFS
			fi	

			# NOW CHECK THIS PORTION OF THE MESSAGES FILE FOR
			# BAD WORDS.  IF WE FIND SOME, PUT THEM IN A MSG
			# TEMP FILE WITH AN EXPIRATION DATE
			set -f
			$RM -f $BBTMP/MSG.red.$PID.1 $BBTMP/MSG.yellow.$PID.1 $BBTMP/MSG.regex.checked.$PID
			for word in $MSGS
			do
				IFS=$OLDIFS
				word="`echo $word | $SED 's/^[ 	]*//g' | $SED 's/[ 	]*$//g'`"
				set +f
				if [ "$word" = "" ]
				then
					continue
				fi

				# Don't test twice for the same regular expression
				if [ -f $BBTMP/MSG.regex.checked.$PID ]
				then
					match="`$GREP \"$word\" $BBTMP/MSG.regex.checked.$PID 2>/dev/null`"
					if [ "$match" = "$word" ]
					then
						continue
					fi
				fi
				echo "$word" >> $BBTMP/MSG.regex.checked.$PID

				echo "$PAGEMSG" | $GREP "$word" > /dev/null 2>&1
				if test "$?" = "0"
				then
					MBAD="$BBTMP/MSG.red.$PID.1"
				else
					MBAD="$BBTMP/MSG.yellow.$PID.1"
				fi

				# Scan only the required lines in the log file
				$RM -f $BBTMP/MSG.tail.$PID
				$TAIL +${LINES}c $file 2>$BBTMP/MSG.tail.$PID | $GREP "$word" >> $MBAD
				# Did tail +<offset>c fail ? if so , try tail -c <offset>
				if [ -s $BBTMP/MSG.tail.$PID ]
				then
					$TAIL -c +${LINES} $file 2>$BBTMP/MSG.tail.$PID | $GREP "$word" >> $MBAD
				fi
				$RM -f $BBTMP/MSG.tail.$PID
				# NOW GET RID OF ANY MESSAGES TO IGNORE
				if [ -s $MBAD ]
				then
					OLDIFS1=$IFS
                        		IFS=";"
                        		for ignmsg in $IGNMSGS
                        		do
						IFS=$OLDIFS
						set -f
						ignmsg="`echo $ignmsg | $SED 's/^[ 	]*//g' | $SED 's/[ 	]*$//g'`"
						set +f
						if [ "$ignmsg" = "" ]
						then
							continue
						fi
                                		# Save in a file to keep new lines
                                		$GREP -v "$ignmsg" $MBAD > ${MBAD}.tmp
                                		$MV ${MBAD}.tmp ${MBAD}
                        		done
                        		IFS=$OLDIFS1
				fi
			done
			$RM -f $BBTMP/MSG.regex.checked.$PID
			set +f
			IFS=$OLDIFS
			#
			# Put filename & color on its own line
			#
			if [ -s $BBTMP/MSG.red.$PID.1 ]
			then
				echo "
&red $file (scanned at $CHKDATE)" >> $BBTMP/MSG.red.$MFILE.$PID
				$CAT $BBTMP/MSG.red.$PID.1 | $TAIL -$REDMSGSLINES >> $BBTMP/MSG.red.$MFILE.$PID
				$BBHOME/bin/touchtime $EXPIREPANIC $BBTMP/MSG.red.$MFILE.$PID
			fi
			if [ -s $BBTMP/MSG.yellow.$PID.1 ]
			then
				echo "
&yellow $file (scanned at $CHKDATE)" >> $BBTMP/MSG.yellow.$MFILE.$PID
				$CAT $BBTMP/MSG.yellow.$PID.1 | $TAIL -$YELLOWMSGSLINES >> $BBTMP/MSG.yellow.$MFILE.$PID
				$BBHOME/bin/touchtime $EXPIREWARN $BBTMP/MSG.yellow.$MFILE.$PID
			fi
			$RM -f $BBTMP/MSG.red.$PID.1 $BBTMP/MSG.yellow.$PID.1
		fi
	fi
done

$RM -f $BBTMP/BBMSGS.1.$PID $BBTMP/BBMSGS.4.$PID

COLOR="green"
MSGLINE="All message files OK"

# Return the most recent red messages
redfiles=`$LS -t $BBTMP/MSG.red* 2>/dev/null`
if [ "$redfiles" != "" ]
then
	$CAT $redfiles 2>/dev/null  > $BBTMP/MSGSTATUS.$PID
	if test -s "$BBTMP/MSGSTATUS.$PID"
	then
		MSGLINE="Urgent message file problems reported
"
		COLOR="red"
	fi
fi

# Return the most recent yellow messages
yellowfiles=`$LS -t $BBTMP/MSG.yellow* 2>/dev/null`
if [ "$yellowfiles" != "" ]
then
	$CAT $yellowfiles 2>/dev/null  >> $BBTMP/MSGSTATUS.$PID
	if test -s "$BBTMP/MSGSTATUS.$PID"
	then
		if test "$COLOR" = "green"
		then
			MSGLINE="Message file problems reported
"
			COLOR="yellow"
		fi
	fi
fi

if [ ! -f $BBTMP/MSGSTATUS.$PID ]
then
	$TOUCH $BBTMP/MSGSTATUS.$PID
fi

$BBHOME/bin/bb-combo.sh add "status $MACHINE.msgs $COLOR `date` ${MSGLINE}
`$CAT $BBTMP/MSGSTATUS.$PID`
"

$RM -f $BBTMP/MSGSTATUS.$PID
if [ "$OLDSTYLEBBMSGS" = "TRUE" ]
then
	$RM -f $BBTMP/.expire $BBTMP/MSG.*
fi

$RM -f $BBTMP/MSG.red.file
