#! /sbin/sh 
##################################################################
# This script should not be executed after boot becaue it
# may report system reboot and cause confusion.
#
# availmon always collects data irrespective of whether
# the data is sent outside or not.
#
# availmon's data is always logged into system support
# database.  Please refer to the man page of ESP
# for more information.
# 
# This script identifies any Controlled shutdowns,
# panics or other unscheduled shutdowns.
##################################################################


COMMAND=$0
AMRVERSIONNUM=2.1
AVAILDIR=/var/adm/avail
SAVEDIR=$AVAILDIR/.save
USRETCDIR=/usr/etc
PLATFORM=`uname -m`
NOSTR="NULL"
DBQUERY="/usr/sbin/espquery"
SQLSTMT="select option_default from tool  where tool_name='AVAILMON'"
SSDB=ssdb
FLAG=0
SSLOGGER=/usr/sbin/esplogger

##################################################################
# Binaries and their location
##################################################################

AMTIME1970=$USRETCDIR/amtime1970
AMSYSLOG=$USRETCDIR/amsyslog
AMTICKERD=$USRETCDIR/eventmond
TICKFILE=$SAVEDIR/lasttick

##################################################################
# Get crash directory
##################################################################

CRASHDIR=""
OPTIONS=`cat /etc/config/savecore.options 2>/dev/null`
if [ "$OPTIONS" != "" ] ; then
    for DIR in $OPTIONS ; do
	if [ -d "$DIR" ] ; then
	    CRASHDIR=$DIR
	fi
    done
fi

if [ "$CRASHDIR" = "" ] ; then
    CRASHDIR=/var/adm/crash
fi

################################################################
# For old systems with old savecore script that creates crashlog
# instead of analysis.N files.
################################################################

CRASHLOGFILE=$CRASHDIR/crashlog

##################################################################
# Get the configuration parameters from SSDB
##################################################################

if [ -f "$DBQUERY" ] ; then
    STATUSINTERVAL=`$DBQUERY -t -s "$SQLSTMT and tool_option='statusinterval'" $SSDB 2>/dev/null | cut -d'|' -f2 2>/dev/null`
    TICKERD=`$DBQUERY -t -s "$SQLSTMT and tool_option='tickerd'" $SSDB 2>/dev/null | cut -d'|' -f2 2>/dev/null`
    TICKDURATION=`$DBQUERY -t -s "$SQLSTMT and tool_option='tickduration'" $SSDB 2>/dev/null | cut -d'|' -f2 2>/dev/null`
    SHUTDOWNRSN=`$DBQUERY -t -s "$SQLSTMT and tool_option='shutdownreason'" $SSDB 2>/dev/null | cut -d'|' -f2 2>/dev/null`
else
    logger -t availmon -p err -i "cannot find $DBQUERY. Some daemons may not be started"
fi

STATUSINTERVAL=${STATUSINTERVAL:=0}
STATUSINTERVALHRS=`expr $STATUSINTERVAL \* 24`
TICKERD=${TICKERD:=0}
SHUTDOWNRSN=${SHUTDOWNRSN:=0}
TICKDURATION=${TICKDURATION:=300}

##################################################################
# Get the SYSLOG file and related variables
##################################################################

# First, get the configfile.

SYSLOGDCONF=""
SYSLOGDOPTS="df:m:p:"
OPTIONS=`cat /etc/config/syslogd.options 2>/dev/null`
if [ "$OPTIONS" != "" ] ; then
    while getopts $SYSLOGDOPTS OPTNAME $OPTIONS 2>/dev/null
    do
	if [ "$OPTNAME" = "f" ] ; then
	    if [ -f "$OPTARG" ] ; then
		SYSLOGDCONF="$OPTARG"
		break
	    fi
        fi
    done
fi

if [ "$SYSLOGDCONF" = "" ] ; then
    SYSLOGDCONF=/etc/syslog.conf
fi

if [ -f "$SYSLOGDCONF"  ] ; then
    SYSLOGFILE=`cat $SYSLOGDCONF | grep -v "^#" | grep "\*.crit" | awk '{print $NF}' | sort -u | head -1 2>/dev/null`
    if [ "z$SYSLOGFILE" = "z" -o ! -f "$SYSLOGFILE" ] ; then
        SYSLOGFILE=/var/adm/SYSLOG
    fi
else
    SYSLOGFILE=/var/adm/SYSLOG
fi

# Use SYSLOGFILE to generate its rotated version

OSYSLOGFILE=`dirname $SYSLOGFILE`/o`basename $SYSLOGFILE`
LASTSYSLOG=$SAVEDIR/lastsyslog
AMSYSLOGFILE=$CRASHDIR/syslog

##################################################################
# Other variables/files
##################################################################

BOUND=-1
PREVSTARTFILE=$SAVEDIR/prevstart
SCRATCHFILE=$AVAILDIR/init.scratch
EVENTFILE=$SAVEDIR/event
SUEVENTFILE=$SAVEDIR/suevent
EXTRASUEVENT=0
TMPSUREPORT=$CRASHDIR/suavailreport.$$
TMPREPORT=$CRASHDIR/availreport.$$
CONFIGCHANGEFILE=$SAVEDIR/configchange
CM_STATUS=0
HWCHANGED=0
SWCHANGED=0

##################################################################
# Checks for HINV / VERSIONS Changes on the machine
##################################################################

checkconfigchange()
{

    # Check the exit status of configmon. If it failed, there is no 
    # need to check for configuration changes...

    if [ $CM_STATUS -gt 0 ] ; then
	return 0
    fi

    if [ -f "$DBQUERY" ] ; then
	LASTCONFIGCHANGE=`$DBQUERY -t -s "select cm_event.time,cm_event.type from system_info,cm_event where cm_event.sys_id=system_info.sys_id and system_info.local=1 and system_info.active=1 order by cm_event.time" $SSDB 2>/dev/null | tail -1 2>/dev/null`
	LASTCONFIGCHANGE=${LASTCONFIGCHANGE:='|0|0|'}
	LASTCHANGEDATE=`echo $LASTCONFIGCHANGE | cut -d'|' -f2`
	LASTCHANGETYPE=`echo $LASTCONFIGCHANGE | cut -d'|' -f3`
    else
	return 0
    fi

    if [ -f "$CONFIGCHANGEFILE" ] ; then
	PREVCHANGEDATE=`cat $CONFIGCHANGEFILE`
	if [ "$PREVCHANGEDATE" != "$LASTCHANGEDATE" ] ; then
	    TMPTYPE=128
	    TMPHINVCOUNT=1
	    while [ "$LASTCHANGETYPE" -gt 0 ] 
	    do
		if [ "$LASTCHANGETYPE" -ge "$TMPTYPE" ] ; then
		    LASTCHANGETYPE=`expr $LASTCHANGETYPE - $TMPTYPE`
		    case $TMPHINVCOUNT in
		      3 | 4)
			  SWCHANGED=1
			  ;;
                      5 | 6)
			  HWCHANGED=1
			  ;;
		    esac
		fi
		TMPTYPE=`expr $TMPTYPE / 2`
		TMPHINVCOUNT=`expr $TMPHINVCOUNT + 1`
	    done
	fi
    fi

    echo "$LASTCHANGEDATE" > $CONFIGCHANGEFILE

}

##################################################################
# Runs Configuration Monitor to collect Configuration data
##################################################################

run_configmon()
{
    CONFIGNUM=0
    CONFIGMAXLOOPS=5

    if chkconfig windowsystem ; then
	while true; do
	    sleep 3
            if [ `ps -eo "comm" | grep Xsgi | wc -l` -eq 1 ] ; then
		break
	    fi
	    if test $CONFIGNUM -eq $CONFIGMAXLOOPS ; then
		break;
	    else
		CONFIGNUM=`expr $CONFIGNUM + 1`
            fi
	done
    fi
	#
	# It's hard to get complete config information so close to system 
	# start-up. We'll sleep for one minute, just to try to make the odds
	# better
	#
	sleep 60
    /usr/sbin/configmon -u > /dev/null
    CM_STATUS=$?
    if [ $CM_STATUS -gt 0 ] ; then
	/usr/sbin/esplogger -s 0x00200107 -p syslog.warning \
	    -m "ConfigMon UPDATE FAILED" ;
    fi
}

##################################################################
# Checks for a single-user shutdown
##################################################################

checksingleuser()
{

    EXTRASUEVENT=0
    if [ -f $SUEVENTFILE ] ; then
	#
	# Check boot-time.  If boot-time is > single-user event
	# time, then there is another event that we need to
	# capture.
	#
	BOOTTIME=`$AMTIME1970 -i | cut -f2 -d'|'`
	SUEVENTTIME=`cat $SUEVENTFILE | cut -f2 -d'|'`

	if [ $BOOTTIME -ge $SUEVENTTIME ] ; then
	    EXTRASUEVENT=1
	    SUEVENTCODE=`cat $SUEVENTFILE | cut -f1 -d'|'`
        fi
    fi
}


##################################################################
# Start main function
##################################################################

#
# Startup Configuration Monitor to gather configuration information
#

run_configmon

#
# Initialization
#    Check for proper installation and presence of all required
#    files.
#    

if [ ! -d $AVAILDIR ] ; then
    echo "\n$CMD: Error: Cannot find directory $AVAILDIR"
    echo "Please try re-installing OS\n"
    logger -t availmon -p err -i cannot find $AVAILDIR
    exit
elif [ ! -x $AMTICKERD -o ! -x $AMSYSLOG -o ! -x $AMTIME1970 ] ; then
    echo "\n$CMD: Error: Not all required executable files are present"
    echo "Please try re-installing OS\n"
    logger -t availmon -p err -i Executable files missing
    exit
elif [ ! -d $SAVEDIR ] ; then
    #
    # Create .save directory if first time install
    #
    
    mkdir $SAVEDIR
    if [ $? -ne 0 ] ; then
	echo "$CMD: Error: unable to create $SAVEDIR directory"
	exit 1
    fi

    if [ -f $CRASHDIR/bounds ] ; then
        cp $CRASHDIR/bounds $SAVEDIR/bounds
    else
        echo "0" > $SAVEDIR/bounds
    fi
    
    $AMTIME1970 > $PREVSTARTFILE
    
    if [ -f $SYSLOGFILE ] ; then
        tail -1 $SYSLOGFILE > $LASTSYSLOG
    fi
    
    if [ "$TICKERD" -eq 1 ] ; then
        $AMTICKERD -a on -j $TICKDURATION -e $STATUSINTERVALHRS >/dev/null 2>&1 
    fi

    echo "$SHUTDOWNRSN" > $SAVEDIR/shutdownreason
    
    exit
else
    # Startup-code

    SINCE1970=`$AMTIME1970`
    
    if [ -f $AVAILDIR/install.sh ] ; then
        $AVAILDIR/install.sh
        rm -f $AVAILDIR/install.sh
    fi

    #
    # First, get the lasttick value & start amtickerd.
    #

    if [ -f "$TICKFILE" ] ; then
        LASTTICK=`cat $TICKFILE 2>/dev/null`
    else
	LASTTICK=-1
    fi

    if [ "$TICKERD" -eq 1 ] ; then
	$AMTICKERD -a on -j $TICKDURATION -e $STATUSINTERVALHRS >/dev/null 2>&1
    else
        rm -f $TICKFILE
    fi

    LASTTICK=${LASTTICK:=-1}

    #
    # Check Bounds
    #

    if [ -f $CRASHDIR/bounds ] ; then
	if [ -f $SAVEDIR/bounds ] ; then
	    diff $SAVEDIR/bounds $CRASHDIR/bounds > /dev/null
	    if [ $? -ne 0 ] ; then
		BOUND=`cat $SAVEDIR/bounds`
		cp $CRASHDIR/bounds $SAVEDIR/bounds
		SUMMARYFILE=$CRASHDIR/summary.$BOUND
		FRUFILE=$CRASHDIR/fru.$BOUND
		AMSYSLOGFILE=$CRASHDIR/syslog.$BOUND
	    fi
	else
	    cp $CRASHDIR/bounds $SAVEDIR/bounds
        fi
    else
	echo "0" > $SAVEDIR/bounds
    fi

    echo "$SHUTDOWNRSN" > $SAVEDIR/shutdownreason

    #
    # PREVSTART
    #

    if [ -f $PREVSTARTFILE ] ; then
	PREVSTART=`cat $PREVSTARTFILE`
    else
	PREVSTART=-1
    fi

    #
    # Identify EVENT
    #

    checksingleuser

    SUMMARYLINE="";
    if [ $BOUND -ge 0 ] ; then
	if [ -f $SUMMARYFILE ] ; then
	    if grep 'PANIC STRING' $SUMMARYFILE | grep NMI > /dev/null ; then
		EVENTCODE=2097156
	    elif [ -f $FRUFILE ] ; then
		cat $FRUFILE >> $SUMMARYFILE
		if grep -i 'FRU ANALY' $FRUFILE > /dev/null ; then
		    if grep 'FRU ANALYZER' $FRUFILE | grep -i 'No error' > /dev/null ; then
			EVENTCODE=2097157
		    elif grep -i 'SOFTWARE' $FRUFILE > /dev/null ; then
			EVENTCODE=2097157
                    elif grep 'Inconclusive hardware error state' $FRUFILE > /dev/null ; then
			EVENTCODE=2097168
                    else
			EVENTCODE=2097167
                    fi
		else
		    EVENTCODE=2097168
                fi
	    else
		EVENTCODE=2097168
            fi
	    EVENTTIME=`awk '/CRASH TIME/ {print $3}' $SUMMARYFILE`
	    SUMMARYLINE=`grep 'PANIC STRING' $SUMMARYFILE`
	    if [ $EVENTCODE -eq 2097167 ] ; then
	        SUMMARYLINE="`tail +2 $SUMMARYFILE`"
	    fi
	    DIAGFILE=""
	    if [ -f $CRASHDIR/analysis.$BOUND ] ; then
	        DIAGFILE=$CRASHDIR/analysis.$BOUND
		DIAGTYPE="ICRASH"
	    fi

	    NOCHARS=`echo $SUMMARYLINE | wc -c`
	    if [ "$NOCHARS" -gt 250 ] ; then
		echo "$SUMMARYLINE" > $CRASHDIR/availsummary.$BOUND
		SUMMARYLINE="$CRASHDIR/availsummary.$BOUND"
		FLAG=1;
	    fi
	    
	elif [ -f $CRASHLOGFILE.$BOUND ] ; then
	    EVENTDATE=`awk '/crash time/ {print $3, $4, $5, $6, $7}' $CRASHLOGFILE.$BOUND`
	    EVENTTIME=`$AMTIME1970 -t $EVENTDATE`
	    EVENTCODE=2097168
	    DIAGTYPE=ICRASH
	    DIAGFILE=$CRASHLOGFILE.$BOUND
	else
	    EVENTTIME=`expr $SINCE1970 - 60`
	    EVENTCODE=2097168
	    DIAGFILE="$NOSTR"
	    DIAGTYPE="$NOSTR"
	fi
	
	if [ ! -f $AMSYSLOGFILE ] ; then
	    $AMSYSLOG -S $SYSLOGFILE -O $OSYSLOGFILE >> $AMSYSLOGFILE
	fi
	    
    elif [ -f $EVENTFILE ] ; then
	EVENTCODE=`cat $EVENTFILE | cut -d'|' -f1`
	EVENTTIME=`cat $EVENTFILE | cut -d'|' -f2`
	AMSYSLOGFILE=""
    else
	DIAGTYPE="$NOSTR"
	DIAGFILE="$NOSTR"
        SUMMARYLINE="$NOSTR"
	$AMSYSLOG -S $SYSLOGFILE -O $OSYSLOGFILE > $AMSYSLOGFILE
        EVENTCODE=2097166
        EVENTTIME=-1
    fi
        
    #
    # At this point, we have determined all possible events.
    #
    # LASTTICK will point to the last time amtickerd wrote to file
    # SUEVENTCODE & SUEVENTTIME will point to single user event
    # EVENTCODE & EVENTTIME will point to multi-user event
    #
    # Now is the time to log the event to SEM
    # 

    if [ "$EXTRASUEVENT" -eq 1 ] ; then
	echo -n "$SUEVENTTIME,$LASTTICK,$PREVSTART" >> $TMPSUREPORT
	LASTTICK=-1
	if [ "$EVENTTIME" -eq -1 ] ; then
	    SUSTARTTIME=`expr $SINCE1970 - 60`
        else
	    SUSTARTTIME=$EVENTTIME
	fi
	PREVSTART=$SUSTARTTIME

	echo -n ",$SUSTARTTIME,$STATUSINTERVAL,$BOUND,$NOSTR,$NOSTR" >> $TMPSUREPORT
	TMPFLAG=`expr $FLAG + 2`
	FLAG=`expr $FLAG + 4`
	echo -n ",$NOSTR,$NOSTR,$NOSTR,1,$TMPFLAG,$NOSTR,$NOSTR" >> $TMPSUREPORT
	$SSLOGGER -s $SUEVENTCODE -f $TMPSUREPORT 2>/dev/null
	RETCODE=$?
	if [ $RETCODE != 0 ] ; then
	    logger -t availmon -p err -i "Unable to log availmon event ($SUEVENTCODE) to ESP ($RETCODE)"
	fi
    fi

    checkconfigchange

    echo -n "$EVENTTIME,$LASTTICK,$PREVSTART">> $TMPREPORT
    echo -n ",$SINCE1970,$STATUSINTERVAL,$BOUND," >> $TMPREPORT
    echo -n "'$DIAGTYPE','$DIAGFILE','$AMSYSLOGFILE'," >> $TMPREPORT
    echo -n "$HWCHANGED,$SWCHANGED,1,$FLAG,$NOSTR," >> $TMPREPORT
    echo $SUMMARYLINE | sed -e "s/%/%%/g" -e "s/\\\\/\\\\\\\\/g" -e "s/\'/\\\'/g" -e 's/\"/\\\"/g' -e "s/^/\'/" -e "s/$/\'/" >> $TMPREPORT
    $SSLOGGER -s $EVENTCODE -f $TMPREPORT 2>/dev/null
    RETCODE=$?
    if [ $RETCODE != 0 ] ; then
        logger -t availmon -p err -i "Unable to log availmon event ($EVENTCODE) to ESP ($RETCODE)"
    fi

    tail -1 $SYSLOGFILE > $LASTSYSLOG
    echo $SINCE1970 > $PREVSTARTFILE
    rm -f $SCRATCHFILE $TMPREPORT $TMPSUREPORT $SUMMARYFILE $EVENTFILE $SUEVENTFILE
fi
