#!/bin/bash
#-------------------------------------------------------------------------------
# charon_logchk - CHARON guest log file monitoring
#----------------------------------------------------------
# Copyright (C) 2013-2023 STROMASYS.
# All rights reserved.
# Products: PAR
#
# Notes:
# Script must be installed in the "utils" directory of the CHARON installation
# folder
#
# Parameters:
# $1 = start|stop|status|force-reload|restart|check|resetlog
# $2 = log filename: optional, full path or completion /opt/charon/log/$2.log
#-------------------------------------------------------------------------------
# chkconfig: 345 98 00
# description: CHARON guest log monitoring for key removal

for P in $(ls /etc/profile.d/charon*);do . $P;done
. /opt/charon/utils/charon_common

VERSION=2.42
LOCKFILE=/var/lock/subsys/charon_logchk

if test $(id -u) -ne 0
then
  echo "Must be root !"
  exit 1
fi

GLOG=$2
if test -n "${GLOG}"
then
  if test ! -e "${GLOG}"
  then
    if test -z "$(echo ${GLOG} | grep '/')" -a -z "$(echo ${GLOG} | grep '\.log$')"
    then
      GLOG="/opt/charon/log/${GLOG}.log"
    fi
  fi
fi
CHKHOST=$(basename ${GLOG} 2>/dev/null | cut -f1 -d.)

SCRIPT=$(basename $0 | sed "s=[KS][0-9][0-9]==g")

LOGFILE="${CHARONDIR}/log/${SCRIPT}.log"
LOGDATE=$(date +"%Y%m%d;%H%M%S")
INFOTERM=""
STARTLIST="${CHARONDIR}/utils/${SCRIPT}.list"
BOOTLIST="${CHARONDIR}/utils/charon_gstart.boot"
DONGLESFILE="${CHARONDIR}/utils/charon_licenses.list"

ANSI_TO_HEX="FF2020 00D200 FFFF00 2020FF FF00FF 00FFFF C0C0C0"

test -d ${CHARONDIR}/utils/events || mkdir ${CHARONDIR}/utils/events

LASTALERTDAT=0
typeset -i ALTCNT=0
typeset -i ALTCHK=0

#TAILCMD="tail -Fn0 --retry --max-unchanged-stats=1"
TAILCMD="tail -Fn0 --retry"

function get_usbbusdev
{
  USBBUSDEV=$(/usr/bin/lsusb -d 0529:0001 | cut -f1 -d: | awk '{print $2"/"$4}')
  TIM=$(date +"%Y%m%d;%H%M%S")
  echo "${TIM};USB_DEVICE;Bus/Dev ${USBBUSDEV}" >>${LOGFILE}

  USBHCI=$(/bin/dmesg | grep 'Vendor=0529,' | tail -1 | cut -f2 -d']' | cut -f1 -d: | sed "s=^ ==g")
  USBHCIMODE=$(/bin/dmesg | grep "${USBHCI}:" | grep hci_hcd | grep -w using | tail -1 | sed "s=\(^.* using \)\(.*$\)=\2=g")
  echo "${TIM};USB_HCI;${USBHCI};${USBHCIMODE}" >>${LOGFILE}
}

function get_licensenum
{
  OPTKEY=""
  if test -n "$(strings /opt/charon/bin/hasp_srm_view | grep ^-key)"
  then
    test -n "${LICENSE_KEY_ID}" && OPTKEY="-key ${LICENSE_KEY_ID}"
  fi
  LICENSENUM=$(hasp_srm_view ${OPTKEY} | grep "^The License Number" | cut -f2 -d: | tr -d [:cntrl:] | tr -d " ")
  if test -z "${LICENSENUM}"
  then
    #--- Retry once
    sleep 10
    LICENSENUM=$(hasp_srm_view ${OPTKEY} | grep "^The License Number" | cut -f2 -d: | tr -d [:cntrl:] | tr -d " ")
    test -z "${LICENSENUM}" && LICENSENUM="UNKNOWN_LIM"
  fi
}

function format_datetime
{
  FDD=$(echo ${LINE} | cut -f1 -d':')
  FDD=$(date -d ${FDD} +"%d-%b-%Y")
  FDT=$(echo ${LINE} | cut -f2 -d':')
  FDT="$(echo ${FDT} | cut -c1-2):$(echo ${FDT} | cut -c3-4):$(echo ${FDT} | cut -c5-6)"
  FMTDAT="${FDD} ${FDT}"
}

function check_max_alerts_reached
{
  #--- $1 = MONUSB, MONHASPERR or service name
  CHKRET=0
  if test ${MAXALERTSINTERVAL:-0} -gt 0
  then
    ALTCHK=$(date +%s)-${LASTALERTDAT}
    if test ${ALTCHK} -lt ${MAXALERTSINTERVAL}
    then
      ALTCNT=ALTCNT+1
      echo "${LOGDATE};$1;ALERTCOUNTER;INCR;${ALTCNT}" >>${LOGFILE}
      if test ${ALTCNT} -gt ${MAXALERTSCOUNT}
      then
        echo "${LOGDATE};$1;ALERTCOUNTER;MAXREACHED;${MAXALERTSCOUNT} in ${MAXALERTSINTERVAL} seconds" >>${LOGFILE}
        CHKRET=1
        case "$1"
        in
          "MONUSB"|"MONSEH")
            touch ${MONUSBALTDISABLED}
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd USBALERTFREEZE | at now >/dev/null 2>&1
            fi
            ;;
          "MONHASPERR")
            touch ${MONHASPALTDISABLED}
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd HASPERRLOGALERTFREEZE | at now >/dev/null 2>&1
            fi
            ;;
          "MONVESVRLOG")
            touch ${MONVESVRALTDISABLED}
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd HASPERRLOGALERTFREEZE | at now >/dev/null 2>&1
            fi
            ;;
          *)
            touch ${ETCCHARON}/CharonToolkit.${1}.alertsdisabled
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd EMULATORALERTFREEZE $1 | at now >/dev/null 2>&1
            fi
            ;;
        esac
        ALTCNT=0
      fi
    else
      ALTCNT=0
      echo "${LOGDATE};$1;ALERTCOUNTER;RESET;${ALTCNT}" >>${LOGFILE}
    fi
  fi
  LASTALERTDAT=$(date +%s)
  return ${CHKRET}
}


RETVAL=0
case "$1" in
  start)
    echo "${LOGDATE};COMMAND;$1;${GLOG}" >>${LOGFILE}
    touch ${LOCKFILE}
    if test -z "${2}"
    then
      if test -s ${STARTLIST}
      then
        cat ${STARTLIST} | while read LINE
        do
          OKSTART=1
          PRC=$(ps -ef | grep "${TAILCMD} ${LINE}" | grep -v grep)
          if test -n "${PRC}"
          then
            PRC=$(echo ${PRC} | awk '{print $3}')
            test -n "$(ps -P ${PRC} | tail -1)" && OKSTART=0
          fi
          echo -n "Starting charon_logchk $(basename ${LINE}): "
          if test ${OKSTART} = 1
          then
            echo $0 check ${LINE} | at now 2>/dev/null
            echo "success"
          else
            echo "already running"
          fi
          echo
        done
      else
        echo -n "Starting charon_logchk/ALL: failure"
      fi
      $0 monusbstart
    else
      if test -n "$(grep ^${GLOG}$ ${STARTLIST})"
      then
        OKSTART=1
        PRC=$(ps -ef | grep "${TAILCMD} ${GLOG}" | grep -v grep)
        if test -n "${PRC}"
        then
          PRC=$(echo ${PRC} | awk '{print $3}')
          test -n "$(ps -P ${PRC} | tail -1)" && OKSTART=0
        fi
        echo -n "Starting charon_logchk $(basename ${GLOG}): "
        if test ${OKSTART} = 1
        then
          echo $0 check ${GLOG} | at now 2>/dev/null
          echo "success"
        else
          echo "failure"
        fi
      else
        echo "Starting charon_logchk $(basename ${GLOG}): not in list"
      fi
    fi
    echo
    ;;
  status)
    echo "${LOGDATE};COMMAND;$1" >>${LOGFILE}
    cat ${STARTLIST} | while read LINE
    do
      echo -n "charon_logchk status for $(basename ${LINE})"
      PRC=$(ps -ef | grep "${TAILCMD} ${LINE}" | grep -v grep)
      if test -n "${PRC}"
      then
        PRC=$(echo ${PRC} | awk '{print $3}')
        test -n "$(ps -P ${PRC} | tail -1)" && echo "success" || echo "failure"
      else
        echo "failure"
      fi
      echo
    done  
    echo -n "charon_monusb status: "
    PRC=$(ps -ef | grep "${TAILCMD} /var/log/messages" | grep -v grep)
    if test -n "${PRC}"
    then
      PRC=$(echo ${PRC} | awk '{print $3}')
      if test -n "$(ps -P ${PRC} | tail -1 | grep 'charon_logchk monusb')"
      then
        echo "running"
      else
        echo "not running"
      fi
    else
      echo "not running"
    fi
    echo
    ;;
  restart)
    $0 stop ${GLOG}
    $0 start ${GLOG}
    ;;
  stop)
    echo "${LOGDATE};COMMAND;$1;${GLOG:-ALL}" >>${LOGFILE}
    if test -z "${GLOG}"
    then
      echo
      cat ${STARTLIST} | while read LINE
      do
        #--- force to full path and not $0 for Fedora compatibility
        ${CHARONDIR}/utils/${SCRIPT} stop ${LINE}
      done  
      echo
      ${CHARONDIR}/utils/${SCRIPT} monusbstop
    else
      echo -n "Stopping charon_logchk for $(basename ${GLOG}): "
      ps -ef | grep "${TAILCMD} ${GLOG}" | grep -v grep | awk '{print $2}' | xargs -i kill -15 {}
      test -z "$(ps -ef | grep "${TAILCMD} ${GLOG}" | grep -v grep)" && echo "success" || echo "failure"
      echo
    fi
    #  rm -f ${LOCKFILE} 2>/dev/null
    ;;
  monusbstop)
    #MONCMD="${TAILCMD} /var/log/messages"
    MONCMD="journalctl -lfn0"

    PRCT=$(ps -ef | grep -e "${MONCMD}" | grep -v grep)
    if test -n "${PRCT}"
    then
      ps -ef | grep "${MONCMD}" | grep -v grep | while read LINE
      do
        PRC=$(echo ${LINE} | awk '{print $2}')
        PRCF=$(echo ${LINE} | awk '{print $3}')
        echo -n "Stopping charon_monusb: pid ${PRC}"
        if test -n "$(ps -P ${PRCF} | tail -1 | grep 'charon_logchk monusb')"
        then
          kill -15 ${PRC}
          sleep 1
          rm -f /var/run/charon_logchk.monusb 2>/dev/null
          ps -P ${PRC} >/dev/null
          test $? = 0 && echo "failure" || echo "success"
        else
          echo -n "/not related"
          passed
        fi
      done
    else
      echo "Stopping charon_monusb: not running"
    fi
    echo
    ;;
  monusb)
    if test -x /usr/sbin/aksusbd
    then
      get_preferences
      if test "${GLOBALLOGMON}" = "enabled"
      then
        get_licensenum
        test -z "${LICENSENUM}" && LICENSENUM="UNKNOWN_MONUSB"
        echo "[INFO ] Starting monitoring /var/log/messages (aksusbd)"
        MONCMD="journalctl -lfn0"

        rm ${MONUSBALTDISABLED} 2>/dev/null
        LASTALERTDAT=0

        echo ${VERSION} >/var/run/charon_logchk.monusb
        ${MONCMD} | while read LINE
        do
          LOGDATE=$(date +"%Y%m%d;%H%M%S")
          if test -z "$(echo ${LINE} | grep 'failed:')" -a -n "$(echo ${LINE} | grep 'aksusbd_')"
          then
  	    DONGLEFND=$(lsusb 2>/dev/null | grep HASP | wc -l)
  	    if test -n "$(echo ${LINE} | grep '_dev_remove:')"
	    then
              echo "[WARN ] Detected removal of a dongle: ${DONGLEFND} connected"
	      echo "${LOGDATE};COMMAND;$1;remove" >>${LOGFILE}

	      if test ! -e ${MONUSBALTDISABLED}
	      then
	        if test -x ${CHARONDIR}/utils/charon_check.alertcmd
                then
	          echo ${CHARONDIR}/utils/charon_check.alertcmd USBDISCONNECT ${DONGLEFND} | at now >/dev/null 2>&1
                fi
                check_max_alerts_reached MONUSB
	      fi
	    else
	      if test -n "$(echo ${LINE} | grep '_dev_connect:')"
	      then
                echo "[INFO ] Detected dongle connection: ${DONGLEFND} connected"
                echo "${LOGDATE};COMMAND;$1;connect" >>${LOGFILE}
                get_licensenum

                if test ! -e ${MONUSBALTDISABLED}
                then
                  if test -x ${CHARONDIR}/utils/charon_check.alertcmd
                  then
  	            echo ${CHARONDIR}/utils/charon_check.alertcmd USBCONNECT ${DONGLEFND} | at now >/dev/null 2>&1
                  fi
                  check_max_alerts_reached MONUSB
	        fi
	      fi
	    fi
          else
            #--- Monitor SEH alerts if there are
            if test -n "$(echo ${LINE} | grep -w sehutnservice)" -o -n "$(echo ${LINE} | grep -w systemd | grep -w seh_vhcd)"
            then
              if test ! -e ${MONUSBALTDISABLED}
              then
                if test -x ${CHARONDIR}/utils/charon_check.alertcmd
                then
                  echo ${CHARONDIR}/utils/charon_check.alertcmd SEHALERT \"${LINE}\" | at now >/dev/null 2>&1
                fi
                check_max_alerts_reached MONSEH
              fi
            fi
          fi  
        done
      else
        echo "[INFO ] Global monitoring is disabled"
      fi
    fi
    ;;
  monhasperrlogstop)
    if test -x /usr/sbin/aksusbd
    then
      MONCMD="${TAILCMD} ${HASPERRLOG}"
      PRCT=$(ps -ef | grep -e "${MONCMD}" | grep -v grep)
      if test -n "${PRCT}"
      then
        ps -ef | grep "${MONCMD}" | grep -v grep | while read LINE
        do
          PRC=$(echo ${LINE} | awk '{print $2}')
          PRCF=$(echo ${LINE} | awk '{print $3}')
          echo -n "Stopping charon_monhasperrlog: pid ${PRC}"
          if test -n "$(ps -P ${PRCF} | tail -1 | grep 'charon_logchk monhasperrlog')"
          then
            kill -15 ${PRC}
            sleep 1
            rm -f /var/run/charon_logchk.monhasperrlog 2>/dev/null
            ps -P ${PRC} >/dev/null
            test $? = 0 && echo "failure" || echo "success"
          else
            echo -n "/not related"
            passed
          fi
        done
      else
        echo -n "Stopping charon_monhasperrlog: not running"
      fi
      echo
    fi
    ;;
  monhasperrlog)
    if test -x /usr/sbin/aksusbd
    then
      get_preferences
      if test "${MONHASPERROR}" = "enabled"
      then
        MONCMD="${TAILCMD} ${HASPERRLOG}"
        echo "[INFO ] Starting monitoring /var/hasplm/error.log"

        rm ${MONHASPALTDISABLED} 2>/dev/null
        LASTALERTDAT=0
        typeset -i ALTCNT=0
        typeset -i ALTCHK=0

        test -e ${HASPERRLOG} || touch ${HASPERRLOG}

        LASTERROR="This is the way"
        echo ${VERSION} >/var/run/charon_logchk.monhasperrlog
        ${MONCMD} | while read LINE
        do
          THISERROR=$(echo ${LINE} | sed "s=^....-..-.. ..:..:.. ==g")
          if test "${THISERROR}" != "${LASTERROR}"
          then
            if test -z "$(echo ${LINE} | grep '^.*Loaded VLIB.*for vendor 68704.*$')"
            then
              if test -z "$(echo ${LINE} | grep '^.*Unrecognized entry.*hasplm.ini.*$')"
              then
  	        LOGDATE=$(date +"%Y%m%d;%H%M%S")
    	        if test ! -e ${MONHASPALTDISABLED}
  	        then
                  if test -x ${CHARONDIR}/utils/charon_check.alertcmd
                  then
	            echo ${CHARONDIR}/utils/charon_check.alertcmd HASPERRLOG \"${LINE}\" | at now >/dev/null 2>&1
                  fi
                  check_max_alerts_reached MONHASPERR
                fi
              else
                if test -x ${CHARONDIR}/utils/charon_check.alertcmd
                then
                  echo ${CHARONDIR}/utils/charon_check.alertcmd HASPERRLOGINFO \"${LINE}\" | at now >/dev/null 2>&1
                fi
	      fi
            fi
          fi
          LASTERROR=${THISERROR}
        done
      else
        echo "[INFO ] HASP error log file monitoring is disabled"
      fi
    fi
    ;;
  monvesvrlogstop)
    if test -x /opt/license-server/license_viewer
    then
      MONCMD="${TAILCMD} ${VESVRLOG}"
      PRCT=$(ps -ef | grep -e "${MONCMD}" | grep -v grep)
      if test -n "${PRCT}"
      then
        ps -ef | grep "${MONCMD}" | grep -v grep | while read LINE
        do
          PRC=$(echo ${LINE} | awk '{print $2}')
          PRCF=$(echo ${LINE} | awk '{print $3}')
          echo -n "Stopping charon_monvesvrlog: pid ${PRC}"
          if test -n "$(ps -P ${PRCF} | tail -1 | grep 'charon_logchk monvesvrlog')"
          then
            kill -15 ${PRC}
            sleep 1
            rm -f /var/run/charon_logchk.monvesvrlog 2>/dev/null
            ps -P ${PRC} >/dev/null
            test $? = 0 && echo "failure" || echo "success"
          else
            echo -n "/not related"
            passed
          fi
        done
      else
        echo "Stopping charon_monvesvrlog: not running"
      fi
      echo
    fi
    ;;
  monvesvrlog)
    if test -x /opt/license-server/license_viewer
    then
      get_preferences
      if test "${GLOBALLOGMON}" = "enabled"
      then
        MONCMD="${TAILCMD} ${VESVRLOG}"
        echo "[INFO ] Starting monitoring ${VESVRLOG}"

        rm ${MONVESVRALTDISABLED} 2>/dev/null
        test -e ${VESVRLOG} || touch ${VESVRLOG}

        echo ${VERSION} >/var/run/charon_logchk.monvesvrlog
        ${MONCMD} | while read LINE
        do
          LOGDATE=$(date +"%Y%m%d;%H%M%S")
          if test -n "$(echo ${LINE} | grep '^.* WARN .*$')"
          then
            echo "${LOGDATE};MONVESVRLOG;WARN ;${LINE}" >>${LOGFILE}
            if test ! -e ${MONVESVRALTDISABLED}
            then
              if test -x ${CHARONDIR}/utils/charon_check.alertcmd
              then
                echo ${CHARONDIR}/utils/charon_check.alertcmd VESVRLOG_DEFAULT \"${LINE}\" | at now >/dev/null 2>&1
              fi
              check_max_alerts_reached MONVESVRLOG
            fi
          elif test -n "$(echo ${LINE} | grep '^.* ERROR .*$')"
          then
            echo "${LOGDATE};MONVESVRLOG;ERROR;${LINE}" >>${LOGFILE}
            if test ! -e ${MONVESVRALTDISABLED}
            then
              if test -x ${CHARONDIR}/utils/charon_check.alertcmd
              then
                echo ${CHARONDIR}/utils/charon_check.alertcmd VESVRLOG_HIGH \"${LINE}\" | at now >/dev/null 2>&1
              fi
              check_max_alerts_reached MONVESVRLOG
            fi
          elif test -n "$(echo ${LINE} | grep '^.* FATAL .*$')"
          then
            echo "${LOGDATE};MONVESVRLOG;FATAL;${LINE}" >>${LOGFILE}
            if test ! -e ${MONVESVRALTDISABLED}
            then
              if test -x ${CHARONDIR}/utils/charon_check.alertcmd
              then
                echo ${CHARONDIR}/utils/charon_check.alertcmd VESVRLOG_HIGH \"${LINE}\" | at now >/dev/null 2>&1
              fi
              check_max_alerts_reached MONVESVRLOG
            fi
          fi
        done
      fi
    fi
    ;;
  aksusbrestart)
    if test -x /usr/sbin/aksusbd
    then
      typeset -i N=0
      while test $N -lt 15
      do
        N=N+1
        TIM=$(date +"%Y%m%d;%H%M%S")
        echo "${TIM};AKSUSBD_RESTART;Restarting try#${N}" >>${LOGFILE}
        #echo "[INFO ] aksusbd service restart, try#${N}"
        systemctl restart aksusbd >>${LOGFILE} 2>&1
        sleep 2
        if test -n "$(ps -ef | grep aksusbd | grep -v grep)"
        then
          echo "${TIM};AKSUSBD_RESTART;Restart successful" >>${LOGFILE}
          #echo "[INFO ] aksusbd service restart successful."
          break
        fi
        sleep 18
      done
      if test -z "$(ps -ef | grep aksusbd | grep -v grep)"
      then
        echo "${TIM};AKSUSBD_RESTART;Restart failed" >>${LOGFILE}
        echo "[ERROR] aksusbd service restart failed !"
        if test -x ${CHARONDIR}/utils/charon_check.alertcmd
        then
          echo ${CHARONDIR}/utils/charon_check.alertcmd AKSUSBFAIL | at now >/dev/null 2>&1
        fi
      fi
    fi
    ;;
  check)
    echo "${LOGDATE};COMMAND;$1;${GLOG}" >>${LOGFILE}
    LICENSE_KEY_ID=""
    get_usbbusdev
    get_licensenum
    test -z "${LICENSENUM}" && LICENSENUM="UNKNOWN_BEG"

    echo "[INFO ] Starting monitoring of ${GLOG} file"

    #--- Loop until log file exists and for max 5 min.
    if test ! -e ${GLOG}
    then
      typeset -i NSLEEP=0
      while test ! -e ${GLOG}
      do
        NSLEEP=NSLEEP+1
        if test ${NSLEEP} -le 60
        then
          echo "[WARN ] Log file '${GLOG}' does not exist. Retrying in 5 seconds (try#${NSLEEP}/60)"
          TAILCMD="tail -Fn500 --retry"
          sleep 5
        else
          exit 2
        fi
      done
      echo "[INFO ] Log file '${GLOG}' found"
    fi

    KEYID=""
    SVCCFG=$(systemctl -l status $$ | head -1 | sed "s=\(^.*charon_logmon_\)\(.*\)\(\.service.*$\)=\2=g")
    rm ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled 2>/dev/null

    echo ${VERSION} >/var/run/charon_logchk.vm.${SVCCFG}

    TOPRUNCPULOOP=0
    ${TAILCMD} ${GLOG} 2>/dev/null | while read LINE
    do
      TOPEVT=1
      MSGCODE=$(echo ${LINE} | cut -f3 -d:)
      MSGCOD4=$(echo ${LINE} | cut -f4 -d:)
      if test -n "$(echo ${LINE}|cut -c1-8|tr -d [0123456789])"
      then
        TIM=$(date +"%Y%m%d;%H%M%S")
      else
        TIM=$(echo ${LINE}|awk -F: '{print $1";"$2}' | cut -c1-15)
      fi

      #--- Get Charon product version
      if test -n "$(echo ${MSGCODE} | grep -w Version | grep -w build)"
      then
        CHVERSION=$(echo ${LINE} | sed "s=^.*:Version \(.*\), build.*$=\1=g")
        echo "${TIM};INFO;${CHKHOST};${LICENSENUM};Charon Version = ${CHVERSION}" >>${LOGFILE}
        TOPRUNCPULOOP=0
      fi

      #--- Get license keyid
      if test "${MSGCODE}" = "Found license key"
      then
        KEYID=$(echo ${LINE} | sed "s=\(^.* license key: \"\)\(.*\)\(\"\.$\)=\2=g")
        LICENSE_KEY_ID=${KEYID}
        #KEYMOD=$(echo ${LINE} | sed "s=\(^.* Looking for \)\(.*\)\( license key .*\)=\2=g")
      fi

      #--- Entry added by the service stop request
      if test -n "$(echo ${LINE} | grep ':SERVICE STOP REQUEST')"
      then
        INFOTERM="Service stop requested by user or shutdown."
        echo "[INFO ] ${INFOTERM}"
      fi

      #--- Entry added by the systemd stop request when service died
      if test -n "$(echo ${LINE} | grep ':SERVICE FAILED')"
      then
        INFOTERM="Service failed."
        SVCNAME="charon_$(systemctl -l status $$ | head -1 | sed "s=\(^.*charon_logmon_\)\(.*\)\(\.service.*$\)=\2=g").service"
        INFOTERM="Service failed."
        INFOSTOP="Emulator stopped at "$(echo ${LINE} | awk -F: '{print $1 $2}' | sed "s=\(^....\)\(..\)\(..\)\(..\)\(..\)\(..\)=\1-\2-\3 \4:\5:\6=g")
        LVLINFO="STOPPED"
        echo "[ERROR] ${INFOTERM}"
        TOPEVT=0
        echo "${TIM};FAILURE;${CHKHOST};${LICENSENUM};" >>${LOGFILE}
        USBCON=$(/usr/bin/lsusb | grep HASP | wc -l)
        if test ${USBCON:-0} -gt 0
        then
          LSUSBINFO="CONNECTED:${USBCON:-unknown}"
        else
          if test -x /usr/sbin/aksusbd
          then
            LSUSBINFO="DISCONNECTED"
          else
            LSUSBINFO="SOFTWARE LICENSE"
          fi
        fi
        if test -x ${CHARONDIR}/utils/charon_check.alertcmd
        then
          echo ${CHARONDIR}/utils/charon_check.alertcmd ${LVLINFO} ${CHKHOST} ${LICENSENUM} \"${INFOSTOP}\" \"${INFOTERM}\" \"${LSUSBINFO}\" | at now >/dev/null 2>&1
          INFOTERM=""
        fi
      fi

      #--- Emulator stop
      if test "${MSGCODE}" = "exit" 
      then
        TOPEVT=0
        echo "${TIM};STOPPED;${CHKHOST};${LICENSENUM};" >>${LOGFILE}
        INFOSTOP="Emulator stopped at "$(echo ${LINE} | awk -F: '{print $1 $2}' | cut -c1-14 | sed "s=\(^....\)\(..\)\(..\)\(..\)\(..\)\(..\)=\1-\2-\3 \4:\5:\6=g")
        echo "[INFO ] ${INFOSTOP}"
        USBCON=$(/usr/bin/lsusb | grep HASP | wc -l)
        if test ${USBCON:-0} -gt 0
        then
          LSUSBINFO="CONNECTED:${USBCON:-unknown}"
        else
          if test -x /usr/sbin/aksusbd
          then
            LSUSBINFO="DISCONNECTED"
          else
            LSUSBINFO="SOFTWARE LICENSE"
          fi
        fi

        LVLINFO="STOPPED"

        if test -x ${CHARONDIR}/utils/charon_check.alertcmd
        then
          # In this case alert is not using 'at' cause in case of server shutdown, the alert is not sent
          ${CHARONDIR}/utils/charon_check.alertcmd ${LVLINFO} ${CHKHOST} ${LICENSENUM} "${INFOSTOP}" "${INFOTERM}" "${LSUSBINFO}"
          INFOTERM=""
          TIM=$(date +"%Y%m%d;%H%M%S")
          echo "${TIM};STOPPED;${CHKHOST};ALERT_SENT" >>${LOGFILE}
        fi
      fi

      #--- Emulator start request (before 3.0.1)
      if test "${MSGCODE}" = "run cpu loop"
      then
        get_licensenum
        test -z "${LICENSENUM}" && LICENSENUM="UNKNOWN_EMULSTART"
        EMULSTART="Emulator start request on "$(echo ${LINE} | awk -F: '{print $1 $2}' | cut -c1-14 | sed "s=\(^....\)\(..\)\(..\)\(..\)\(..\)\(..\)=\1-\2-\3 \4:\5:\6=g")
        if test ${TOPRUNCPULOOP:-0} = 0
        then
          echo "[INFO ] ${EMULSTART}"
          rm -f ${CHARONDIR}/utils/events/${SVCCFG}.license_status 2>/dev/null
          echo "${TIM};EMULATORSTART;${CHKHOST};${LICENSENUM};${EMULSTART}" >>${LOGFILE}
          if test -x ${CHARONDIR}/utils/charon_check.alertcmd
          then
            echo ${CHARONDIR}/utils/charon_check.alertcmd EMULSTART ${CHKHOST} ${LICENSENUM} \"${EMULSTART}\" | at now >/dev/null 2>&1
          fi
          TOPRUNCPULOOP=1
        fi
      fi
      #--- Emulator start request (starting with 3.0.1)
      if test "${MSGCODE}" = "cpu0" -a "$(echo ${MSGCOD4} | tr -d [:space:])" = "runcpuloop"
      then
        get_licensenum
        test -z "${LICENSENUM}" && LICENSENUM="UNKNOWN_EMULSTART"
        EMULSTART="Emulator start request on "$(echo ${LINE} | awk -F: '{print $1 $2}' | cut -c1-14 | sed "s=\(^....\)\(..\)\(..\)\(..\)\(..\)\(..\)=\1-\2-\3 \4:\5:\6=g")
        if test ${TOPRUNCPULOOP:-0} = 0
        then
          echo "[INFO ] ${EMULSTART}"
          rm -f ${CHARONDIR}/utils/events/${SVCCFG}.license_status 2>/dev/null
          echo "${TIM};EMULATORSTART;${CHKHOST};${LICENSENUM};${EMULSTART}" >>${LOGFILE}
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd EMULSTART ${CHKHOST} ${LICENSENUM} \"${EMULSTART}\" | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
          TOPRUNCPULOOP=1
        fi
      fi

      #--- ... found license 
      if test "${MSGCODE}" = "License number"
      then
        get_usbbusdev
        #get_licensenum
        LICENSENUM=$(echo ${LINE} | cut -f2 -d'"')
        format_datetime
        echo "${FMTDAT};INFO;Found license key ${KEYID}, license number ${LICENSENUM}" \
             >${CHARONDIR}/utils/events/${SVCCFG}.license_status
        INFOFOUND="License detected"
        if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
        then
          if test -x ${CHARONDIR}/utils/charon_check.alertcmd
          then
            echo ${CHARONDIR}/utils/charon_check.alertcmd FOUND ${CHKHOST} ${LICENSENUM} \"${LICENSEMOD}\" \"${INFOFOUND}\" ${LICENSE_KEY_ID:-NA} \"${LICDESC:-None}\" \"${COLHEX:-000000}\" | at now >/dev/null 2>&1
          fi
          check_max_alerts_reached ${SVCCFG}
        fi
      fi

      #--- Communication lost/restored with the license key
      if test -n "$(echo ${LINE} | grep 'Communication with the license key')"
      then
        TOPEVT=0
        LICKEYID=$(echo ${LINE} | cut -f2 -d'"')
        if test -n "$(echo ${LINE} | grep ' lost.')"
        then
          echo "${TIM};WARN;${CHKHOST};Communication lost with key id ${LICKEYID};License number ${LICENSENUM}" >>${LOGFILE}
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd COMMLOST ${CHKHOST} ${LICENSENUM} ${LICKEYID} | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
          format_datetime
          echo "${FMTDAT};WARN;Communication lost with key id ${LICKEYID}, license number ${LICENSENUM}" \
               >${CHARONDIR}/utils/events/${SVCCFG}.license_status
        else
          if test -n "$(echo ${LINE} | grep ' restored.')"
          then
            echo "${TIM};INFO;${CHKHOST};Communication restored with key id ${LICKEYID};License number ${LICENSENUM}" >>${LOGFILE}
            if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
            then
              if test -x ${CHARONDIR}/utils/charon_check.alertcmd
              then
                echo ${CHARONDIR}/utils/charon_check.alertcmd COMMREST ${CHKHOST} ${LICENSENUM} ${LICKEYID} | at now >/dev/null 2>&1
              fi
              check_max_alerts_reached ${SVCCFG}
            fi
            format_datetime
            echo "${FMTDAT};INFO;Communication restored with key id ${LICKEYID}, license number ${LICENSENUM}" \
                 >${CHARONDIR}/utils/events/${SVCCFG}.license_status
          fi
        fi
      fi

      #--- Alerts to filter or not
      get_preferences
      if test "${WARNONDONGLEREMOVAL}" = "reduced"
      then
        test -n "$(echo ${LINE} | grep 'Unable to log in to the key' | grep ', feature')" && TOPEVT=0
        test -n "$(echo ${LINE} | grep 'HASP runtime (7)' | grep 'Sentinel protection key not available.')" && TOPEVT=0
        test -n "$(echo ${LINE} | grep 'Failed to login at the Sentinel HASP key:')" && TOPEVT=0
      fi

      #--- Detected removal of the license 
      if test -n "$(echo ${LINE} | grep 'Connection to license key:' | grep 'lost.')"
      then
        TOPEVT=0
        NORMOPER=$(echo ${LINE} | sed "s=\(^.* lost. \)\(.*$\)=\2=g")
        format_datetime
        APPSTO=$(echo ${LINE} | sed "s=^.*:warn:\(.*$\)=\1=g")
        echo "${FMTDAT};ERROR;${APPSTO}" >${CHARONDIR}/utils/events/${SVCCFG}.license_status

        echo "${TIM};KEY_REMOVED;${CHKHOST};${LICENSENUM};${LICENSEMOD}" >>${LOGFILE}
        if test -x /usr/sbin/aksusbd
        then
          AKSUSBINFO="Service state/aksusbd: $(/usr/bin/systemctl is-active aksusbd)"
        else
          AKSUSBINFO="n/a"
        fi
        sleep 1
        if test -z "$(/usr/bin/lsusb | grep HASP)"
        then
          echo "[ERROR] Detected removal of the license"
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd REMOVED ${CHKHOST} ${LICENSENUM} \"${LICENSEMOD}\" \"${NORMOPER}\" \"${AKSUSBINFO}\" | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
        else
          echo "[ERROR] Detected removal of the license whereas dongle is connected"

          USBCON=$(/usr/bin/lsusb | grep HASP | wc -l)
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd REMOVRESET ${CHKHOST} ${LICENSENUM} \"${LICENSEMOD}\" \"${NORMOPER}\" \"${AKSUSBINFO}\" \"CONNECTED:${USBCON:-0}\" | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
        fi
        if test -n "${USBHCIMODE}"
        then
          echo "[INFO ] Trying to solve the problem with unbind/bind"
          ls /sys/bus/pci/drivers/${USBHCIMODE} | grep : | while read L
          do
            TIM=$(date +"%Y%m%d;%H%M%S")
            echo "${TIM};USB_UNBIND;Unbinding ${USBHCI}/${USBHCIMODE}/${L}" >>${LOGFILE}
            echo "[INFO ] Unbinding ${USBHCIMODE} / ${L}"
            echo ${L} >/sys/bus/pci/drivers/${USBHCIMODE}/unbind
            sleep 1
            TIM=$(date +"%Y%m%d;%H%M%S")
            echo "${TIM};USB_BIND;Binding ${USBHCI}/${USBHCIMODE}/${L}" >>${LOGFILE}
            echo "[INFO ] Binding ${USBHCIMODE} / ${L}"
            echo ${L} >/sys/bus/pci/drivers/${USBHCIMODE}/bind
          done
        else
          echo "[ERROR] Cannot Unbind, USBHCI variable is empty"
          TIM=$(date +"%Y%m%d;%H%M%S")
          echo "${TIM};USB_UNBIND;Cannot Unbind, USBHCI variable is empty" >>${LOGFILE}
        fi

        #-----------------------------------------------
        # Restarting Sentinel runtime due to some hangs
        #-----------------------------------------------
        if test -x /usr/sbin/aksusbd
        then
          echo "[INFO ] Restarting aksusbd service"
          ATJ=$(echo $0 aksusbrestart | at now 2>&1)
          echo "${TIM};AKSUSBD_RESTART;${ATJ}" >>${LOGFILE}
        fi
        #-----------------------------------------------
      fi

      #--- Sentinel HASP RunTime Error xxx.
      if test -n "$(echo ${LINE} | grep 'Sentinel HASP RunTime Error')"
      then
        if test -s ${HASPERRCODES}
        then
          HASPERR=$(echo ${LINE} | sed "s=\(^.*Sentinel HASP RunTime Error \)\(.*\)\(\..*$\)=\2=g" | cut -f1 -d '.')
          #LINE="${LINE} "$(grep "^${HASPERR};" ${HASPERRCODES} 2>/dev/null | cut -f2 -d';' | sed -e "s=<KEYID>=${KEYID}=g" -e "s=<KEYMOD>=${KEYMOD}=g")"."
          LINE="${LINE} "$(grep "^${HASPERR};" ${HASPERRCODES} 2>/dev/null | cut -f2 -d';' | sed -e "s=<KEYID>=${KEYID}=g")"."
        fi
      fi

      #--- MPE system fail
      if test -n "$(echo ${LINE} | grep ':MPE system fail')"
      then
        TOPEVT=0
        echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
      fi

      #--- Console connection
      if test -n "$(echo ${LINE} | grep -w uart | grep 'Client connected')"
      then
        get_preferences
        TOPEVT=0
        if test "${MONCONSOLECON}" = "enabled"
        then
          echo "${TIM};WARN;${CHKHOST};Console connection detected" >>${LOGFILE}
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd CONSOLECONNECT ${CHKHOST} \"${LINE}\" | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
        fi
      fi

      #--- Console disconnection
      if test -n "$(echo ${LINE} | grep -w uart | grep 'Client disconnected')"
      then
        get_preferences
        TOPEVT=0
        if test "${MONCONSOLECON}" = "enabled"
        then
          echo "${TIM};INFO;${CHKHOST};Console disconnection detected" >>${LOGFILE}
          if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
          then
            if test -x ${CHARONDIR}/utils/charon_check.alertcmd
            then
              echo ${CHARONDIR}/utils/charon_check.alertcmd CONSOLEDISCONNECT ${CHKHOST} \"${LINE}\" | at now >/dev/null 2>&1
            fi
            check_max_alerts_reached ${SVCCFG}
          fi
        fi
      fi


      if test ${TOPEVT} = 1
      then
        get_preferences
        typeset -i LVLEVENT=${LOGSEVERITYALERT}


        if test ! -e ${ETCCHARON}/CharonToolkit.${SVCCFG}.alertsdisabled
        then
          case ${LVLEVENT}
          in
            1)
              #-- warning: no information lines here so all lines will be pushed (in a 1st time)
              echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
              check_max_alerts_reached ${SVCCFG}
              ;;
            2)
              if test "${MSGCODE}" = "warn"
              then
                echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
                check_max_alerts_reached ${SVCCFG}
              fi
              if test "${MSGCODE}" = "err"
              then
                echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
                check_max_alerts_reached ${SVCCFG}
              fi
              if test "${MSGCODE}" = "ERR"
              then
                echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
                check_max_alerts_reached ${SVCCFG}
              fi
              ;;
            3)
              if test "${MSGCODE}" = "err"
              then
                echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
                check_max_alerts_reached ${SVCCFG}
              fi
              if test "${MSGCODE}" = "ERR"
              then
                echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
                check_max_alerts_reached ${SVCCFG}
              fi
              ;;
          esac
        fi
  
        if test -n "$(echo ${LINE} | grep :WARNING:)"
        then
          echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
          check_max_alerts_reached ${SVCCFG}
        fi
        if test -n "$(echo ${LINE} | grep :ERROR:)"
        then
          echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
          check_max_alerts_reached ${SVCCFG}
        fi
        if test -n "$(echo ${LINE} | grep :FATAL:)"
        then
          echo "${LINE}" >>${CHARONDIR}/utils/events/${CHKHOST}.partlog
          check_max_alerts_reached ${SVCCFG}
        fi
      fi
    done
    ;;
  resetlog)
    echo "${LOGDATE};COMMAND;$1" >>${LOGFILE}
    mv -f ${LOGFILE} ${LOGFILE}.old
    touch ${LOGFILE}
    ;;
  -v)
    echo "Version ${VERSION}"
    ;;
  *)
    echo "$0, wrong parameter1: $1"
    ;;
esac
exit $RETVAL
