#!/bin/bash
#-------------------------------------------------------------------------
# charon_common_menu for Charon-PAR
#-------------------------------------------------------------------------
# Copyright (C) 2013-2023 STROMASYS.
# All rights reserved.
#
# Products: PAR
VERSION=2.2

test $TERM = "putty" && export TERM=xterm

#=============================================================================
# Function: Press_Enter
#=============================================================================
function Press_Enter
{
  echo
  echo -n "[44m[37mPress enter[0m"
  read ENTER
  tput cuu1;tput el
}

#=============================================================================
# Function: display_guestslist
#=============================================================================
function display_guestslist
{
  if test ! -e /usr/bin/bc
  then
    tput bold
    echo "${BGORANGE} WARNING [0m 'bc' is not installed on this system".
    echo "          Please install the missing package before continuing."
    tput sgr0
    echo
    Press_Enter
    exit 1
  fi
  LITEON="$1"
  test "${LITEON}" = "-num" && LITEON="$2"
  test "${LITEON}" = "-l" || LITEON=""
  get_preferences

  get_lastused
  VMSEL=`cat ${LASTUSED} 2>/dev/null`

  CR=`echo -e "\r"`
  if test -e ${NCUBIN}
  then
    NCUDIR=`dirname ${NCUBIN}`
    eval `grep ^NCU_CFG= ${NCUDIR}/* 2>/dev/null | cut -f2 -d':' | sort -u | head -1`
  fi
  PORTCF=/tmp/charon_chkport_conflict.tmp.$$
  NICCF=/tmp/charon_chknic_conflict.tmp.$$
  LOGCF=/tmp/charon_chklog_conflict.tmp.$$
  CONSCF=/tmp/charon_chkcons_conflict.tmp.$$
  rm -f ${PORTCF} ${NICCF} ${LOGCF} ${CONSCF} 2>/dev/null
  SRVBOOT=`who -b | sed "s=.*system boot ==g"`
  SRVBOOT=`date +"%d-%b-%Y %H:%M" -d "${SRVBOOT}"`

  echo "${FGBLUE}[1mServer booted on:[0m ${SRVBOOT}"
  echo
  tput sgr0
  tput bold
  echo -n "${FGBLUE}"
  echo "Configuration File                           Cpu Memory State/Uptime[0m${FGBLUE}: d hh:mm:ss[0m"
  tput sgr0
  test ! -e ${BOOTLIST} && touch ${BOOTLIST}
  if test `grep -v ^# ${BOOTLIST} | wc -l` -eq 0
  then
    if test "${SEMIGRAPH}" = "enabled"
    then
      tput smacs
      echo "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq qqq qqqqqq qqqqqqqqqqqqqqqqqqqqqqqq"
      tput rmacs
    else
      echo "-------------------------------------------- --- ------ ------------------------"
    fi
    echo "No virtual machine defined."
  else
    typeset -i I=0
    NICALERT1=0
    NICALERT2=0
    NICALERT3=0
    NICALERT4=0
    NICALERT5=0
    for LINE in `grep -v ^# ${BOOTLIST}`
    do
      I=I+1

      if test $I -eq 1
      then
        if test "${SEMIGRAPH}" = "enabled"
        then
          tput smacs
          echo "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq qqq qqqqqq qqqqqqqqqqqqqqqqqqqqqqqq"
          tput rmacs
        else
          echo "-------------------------------------------- --- ------ ------------------------"
        fi
      else
        case "${LISTSEPAR}"
        in
          "line")
            if test "${SEMIGRAPH}" = "enabled"
            then
              tput smacs
              echo "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq qqq qqqqqq qqqqqqqqqqqqqqqqqqqqqqqq"
              tput rmacs
            else
              echo "-------------------------------------------- --- ------ ------------------------"
            fi
            ;;
          "blank")
            echo
            ;;
        esac
      fi
      tput sgr0

      test "$1" = "-num" && printf "%2d" $I
      CHARON_EXE=`echo ${LINE} | cut -f1 -d';'`
      CHARON_CFG=`echo ${LINE} | cut -f2 -d';'`
      if test -s ${CHARON_CFG}
      then
        if test `grep -c "${CR}$" ${CHARON_CFG}` -gt 0
        then
          cat ${CHARON_CFG} | tr -d "\r" >${CHARON_CFG}.noCR
          mv -f ${CHARON_CFG} ${CHARON_CFG}.bak
          mv -f ${CHARON_CFG}.noCR ${CHARON_CFG}
        fi

        CHARON_CFGBAS=`basename ${CHARON_CFG}|sed "s=\.cfg==g"`
        CHARON_BOO=`echo ${LINE} | cut -f3 -d';'`

        HWM=`grep "^[ ]*model" ${CHARON_CFG} | awk '{print $2}' | tr -d "'\"" | tr -d " "`

        EMUX1=${HWM}
        EMUX2=${CHARON_CFG}

        test $I -eq ${VMSEL:-0} && IDN="*" || IDN="-"

        echo -n "[1m"
        echo -n "${IDN} "
        echo -n `dirname ${EMUX2}`
        echo -n "/${FGBLUEBOLD}"
        echo -n `basename ${EMUX2} | sed "s=\.cfg$=[0m[1m.cfg=g"`
        echo -n "[0m"

        EMUCPU=`grep "^${HWM}=" ${CHARONDIR}/utils/charon_hwmodel.cpus 2>/dev/null | cut -f2 -d'='`

        EMUMEM=`grep -w memory ${CHARON_CFG} | grep -v ^# | awk '{print $2}'`
        if test -n "${EMUMEM}"
        then
          if test -z "`echo ${EMUMEM} | tr -d [:digit:]`"
          then
            if test ${EMUMEM} -lt 1000
            then
              EMUMEM="${EMUMEM}M"
            else
              EMUMEM="`echo ${EMUMEM}/1024|bc`G"
            fi
          fi
        else
          EMUMEM="2G"
        fi

        tput hpa 44
        echo -n " "
        printf "%3s %6s" "${EMUCPU:--}" "${EMUMEM:--}"

        GETIME=""
        CSTATE1=""
        CSTATE2=""
        CSTATE3=""

        OOMKPROT=""
        if test "${SEMIGRAPH}" = "enabled"
        then
          OOMKD1="`tput smacs`l`tput rmacs`"
          OOMKD2="`tput smacs`m`tput rmacs`"
          OOMKDM="`tput smacs`x`tput rmacs`"
        else
          OOMKD1="+"
          OOMKD2="+"
          OOMKDM="|"
        fi

        SVC_IS_ACTIVE=`systemctl is-active charon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f1 -d'-' | tr [:lower:] [:upper:]`
        case "${SVC_IS_ACTIVE}"
        in
          ACTIVE)
            CSTATE1="[42m[30m${SVC_IS_ACTIVE}[0m"
            GSTA=`systemctl show -p ActiveEnterTimestamp charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            GPID=`systemctl show -p ExecMainPID charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            GETIME=`ps -o etime -p ${GPID} | tail -1 | sed -e "s=-= =g"`

            OOMKPROT=""
            get_preferences
            if test "${OOMPRVPIDKILL}" = "enabled"
            then
              if test "`cat /proc/${GPID}/oom_score_adj 2>/dev/null`" = "-1000"
              then
                OOMKPROT="Protected against OOM Killer."
              else
                echo "-1000" >/proc/${GPID}/oom_score_adj
                OOMKPROT="[36mProtection set against OOM Killer."
              fi
            else
              echo "0" >/proc/${GPID}/oom_score_adj 2>/dev/null
              OOMKPROT="[90mNot protected against OOM Killer."
            fi

            GMEM=`pmap ${GPID} | tail -1 | awk '{print $2}' | tr -d "K"`
            GMEM=`echo ${GMEM} / 1024 | bc | sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'`
            CSTATE2="${FGBLUE}Started:[0m        ${OOMKD1} ${GSTA} PID=${GPID} Memory=${GMEM}M"

            GSTADAT=`systemctl show -p ActiveEnterTimestamp charon_${CHARON_CFGBAS}.service | awk '{print $2,$3}'`
            GCFGDAT=`date +"%Y%m%d%H%M%S" -r ${CHARON_CFG}`
            if test "${GCFGDAT}" -gt "`echo ${GSTADAT} | tr -dc [:digit:]`"
            then
              CSTATE3="                  ${BGORANGE}Configuration file updated after process started ![0m"
            fi
            ;;
          ACTIVATING)
            CSTATE1="[40m[32m[1m${SVC_IS_ACTIVE}[0m"
            GSUB=`systemctl show -p SubState charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            CSTATE2="${FGBLUE}Substate:[0m [1m[32m${GSUB}[0m"
            ;;
          INACTIVE)
            if test -s /etc/systemd/system/charon_${CHARON_CFGBAS}.service
            then
              CSTATE1="[40m[37m[1m${SVC_IS_ACTIVE}[0m"
            else
              CSTATE1="[40m[37m[1m${SVC_IS_ACTIVE}[0m [41m[30mUNKNOWN[0m"
              CHARON_BOO="-"
            fi
            GSTO=`systemctl show -p InactiveEnterTimestamp charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            if test -n "${GSTO}"
            then
              GSIG=`systemctl show -p Result charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
              CSTATE2="${FGBLUE}Stopped:[0m          ${GSTO} (${GSIG})"
            else
              CSTATE2="${FGBLUE}Stopped:[0m          Not started since server booted"
            fi
            ;;
          DEACTIVATING)
            CSTATE1="${BGORANGE}${SVC_IS_ACTIVE}[0m"
            ;;
          FAILED)
            CSTATE1="[41m[37m[1m${SVC_IS_ACTIVE}[0m"
            GSTO=`systemctl show -p InactiveEnterTimestamp charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            GSIG=`systemctl show -p Result charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            GMST=`systemctl show -p ExecMainStatus charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            if test ${GMST:-0} = 0
            then
              GMST=`systemctl show -p ExecStart charon_${CHARON_CFGBAS}.service | cut -f8 -d';' | tr -d '{ }' | cut -f2 -d'='`
            else
              GMST=`kill -l ${GMST} 2>/dev/null`
            fi
            CSTATE2="${FGBLUE}Stopped:[0m          ${GSTO} ([31m${GSIG}[0m/${GMST:-unknown})"
            ;;
          UNKNOWN)
            CSTATE1="[45m[37m[1m${SVC_IS_ACTIVE}[0m"
            if test "${CHARON_BOO}" != "N"
            then
              CSTATE2="${FGORANGE}Warning:[0m Service not defined in systemd -> remove guest and add again"
            else
              SVC_IS_ACTIVE=`systemctl show -p ActiveState charon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f2 -d'=' | tr [:lower:] [:upper:]`
              if test "${SVC_IS_ACTIVE}" = "INACTIVE"
              then
                CSTATE1="[40m[37m[1m${SVC_IS_ACTIVE}[0m"

                #--Workaround for CentOS7: on RHEL7 services go "inactive", on CentOS7, it's "unknown" !
                GSTO=`systemctl -o short-iso status charon_${CHARON_CFGBAS}.service 2>/dev/null |grep -w systemd | grep -w Stopped | awk '{print $1}'`
                if test -n "${GSTO}"
                then
                  GSTO=`date -d ${GSTO} +"%d-%b-%Y %H:%M:%S"`
                  GSIG=`systemctl show -p Result charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
                  CSTATE2="${FGBLUE}Stopped:[0m          ${GSTO} (${GSIG})"
                else
                  CSTATE2="${FGBLUE}Stopped:[0m          <unknown>"
                fi
              else
                SVC_IS_ENABLED=`systemctl is-enabled charon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f1 -d'-' | tr [:lower:] [:upper:]`
                CSTATE2="${FGBLUE}State:[0m            ${SVC_IS_ACTIVE} / ${SVC_IS_ENABLED}"
              fi
            fi
            ;;
          *)
            CSTATE1="${SVC_IS_ACTIVE}"
            ;;
        esac

        #--- systemctl correction if needed
        if test "${SVC_IS_ACTIVE}" != "UNKNOWN"
        then
          SVC_IS_ENABLED=`systemctl is-enabled charon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f1 -d'-' | tr [:lower:] [:upper:]`
          if test "${CHARON_BOO}" = "N" -a "${SVC_IS_ENABLED}" = "ENABLED"
          then
            systemctl disable charon_${CHARON_CFGBAS}.service 2>/dev/null
          fi
          if test "${CHARON_BOO}" = "Y" -a "${SVC_IS_ENABLED}" = "DISABLED"
          then
            systemctl enable charon_${CHARON_CFGBAS}.service 2>/dev/null
          fi
        fi

        tput hpa 56
        echo -n "${CSTATE1}"

        tput hpa 68
        printf "%12s\n" "${GETIME}"

        if test -x ${CHARONDIR}/utils/charon_gstart.stop
        then
          CHK=`grep "${CHARON_CFG})" ${CHARONDIR}/utils/charon_gstart.stop`
          if test -n "${CHK}"
          then
            CSEQ="[31mTo customize[0m"
            ACFG=`echo ${CHARON_CFG} | sed "s=/=\\\\\\/=g"`
            awk "/${ACFG})/,/;;/" ${CHARONDIR}/utils/charon_gstart.stop >/tmp/display_guests$$.tmp1
            grep -v -e "#\\$" -e "^#" -e "#/" -e "#--" /tmp/display_guests$$.tmp1 | grep -v -e "${CHARON_CFG})" -e ";;" >/tmp/display_guests$$.tmp2
            ACFG=`cat /tmp/display_guests$$.tmp2`
            rm -f /tmp/display_guests$$.tmp[12] >/dev/null 2>&1
            if test -n "`echo ${ACFG} | grep '/utils/charon_gstop_rsh'`"
            then
              CSEQ="[32m[Using RSH][0m"
            else
              if test -n "`echo ${ACFG} | grep '/utils/charon_gstop_ssh'`"
              then
                CSEQ="[32m[Using SSH][0m"
              else
                if test -n "`echo ${ACFG} | grep '/utils/charon_gstop_expect'`"
                then
                  CSEQ="[32m[Using EXPECT][0m"
                else
                  if test "`echo ${ACFG} | tr -dc [:alnum:]`" = "exit1"
                  then
                    CSEQ="[31mEXIT 1 ![0m"
                  else
                    if test -z "${ACFG}"
                    then
                      CSEQ="${FGORANGE}No action![0m"
                    else
                      CSEQ="${FGBLUE}Customized[0m"
                    fi
                  fi
                fi
              fi
            fi
          else
            CSEQ="${FGORANGE}Case not set[0m"
          fi
        else
          CSEQ="${FGORANGE}Not found[0m"
        fi

        test "$1" = "-num" && echo -n "  "
        echo -n "  ${FGBLUE}Model:[0m            [1m${EMUX1}[0m"

        GPAR=`echo ${CHARON_CFG} | sed "s=\.cfg$=\.params=g"`
        if test -s ${GPAR}
        then
          GPAR=`cat ${GPAR}`
          echo "  ${FGBLUE}Params:[0m ${GPAR}"
        else
          echo
        fi

        if test ! -x ${CHARON_EXE}
        then
          test "$1" = "-num" && echo -n "  "
          echo "  [31mThe virtual machine exe file is not installed![0m"
        fi

        GSTOPOST="ExecStopPost=${CHARONDIR}/utils/charon_gstart check ${CHARON_CFG}"
        GCHKPOST=`systemctl cat charon_${CHARON_CFGBAS}.service 2>/dev/null | grep ^ExecStopPost=`
        if test "${GCHKPOST}" != "${GSTOPOST}"
        then
          test "$1" = "-num" && echo -n "  "
          echo "  [31mThe 'ExecStopPost' line is missing in service definition![0m"
          test "$1" = "-num" && echo -n "  "
          echo "  [31mPlease edit service and add:[0m"
          test "$1" = "-num" && echo -n "  "
          echo "  ExecStopPost=${CHARONDIR}/utils/charon_gstart check ${CHARON_CFG}"
          test "$1" = "-num" && echo -n "  "
          echo "  [31mfollowed by a 'systemctl daemon-reload' command.[0m"
        fi

        GSTA=`systemctl show -p LoadState charon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f2 -d'='`
        if test "${GSTA}" = "loaded"
        then
          test "$1" = "-num" && echo -n "  "
          echo -n "  ${FGBLUE}Description:[0m      "
          systemctl show -p Description charon_${CHARON_CFGBAS}.service | cut -f2 -d'='

          if test "${LITEON}" = ""
          then
            GRESTART=`systemctl show -p Restart charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            if test "${GRESTART}" != "no"
            then
              GRESTARTUSEC=`systemctl show -p RestartUSec charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
              GRESTARTLBUR=`systemctl show -p StartLimitBurst charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
              GRESTARTLINT=`systemctl show -p StartLimitInterval charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
              GRESTARTLINT=`echo ${GRESTARTLINT}/1000000 | bc`
              test "$1" = "-num" && echo -n "  "
              echo "  ${FGBLUE}Auto-restart:[0m     ${GRESTART} after ${GRESTARTUSEC}, max ${GRESTARTLBUR} times in ${GRESTARTLINT} seconds"
            fi
            GTIMEOUT1=""
            if test -n "`grep ^TimeoutStartSec= /etc/systemd/system/charon_${CHARON_CFGBAS}.service 2>/dev/null`" -o \
                    -n "`grep ^TimeoutSec= /etc/systemd/system/charon_${CHARON_CFGBAS}.service 2>/dev/null`"
            then
              GTIMEOUT1=`systemctl show -p TimeoutStartUSec charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            fi
            GTIMEOUT2=""
            if test -n "`grep ^TimeoutStopSec= /etc/systemd/system/charon_${CHARON_CFGBAS}.service 2>/dev/null`" -o \
                    -n "`grep ^TimeoutSec= /etc/systemd/system/charon_${CHARON_CFGBAS}.service 2>/dev/null`"
            then
              GTIMEOUT2=`systemctl show -p TimeoutStopUSec charon_${CHARON_CFGBAS}.service | cut -f2 -d'='`
            fi

            test "$1" = "-num" && echo -n "  "
            echo -n "  ${FGBLUE}Startup type:[0m     "
            case "${CHARON_BOO:-Y}"
            in
              Y|y) echo -n "[32mAutomatic[0m";;
              *)   echo -n "Manual";;
            esac
            if test -n "${GTIMEOUT1}${GTIMEOUT2}"
            then
              echo -n "  / ${FGBLUE}Service Timeouts:[0m "
              test -n "${GTIMEOUT1}" && echo -n "Start=${GTIMEOUT1} "
              test -n "${GTIMEOUT2}" && echo -n "Stop=${GTIMEOUT2} "
              echo
            else
              echo
            fi
          fi
        fi

        if test "${LITEON}" = ""
        then
          test "$1" = "-num" && echo -n "  "
          echo -n "  ${FGBLUE}Stop script:[0m      "
          echo "${CSEQ}"


          if test -x ${CHARONDIR}/utils/charon_gstart.prestart
          then
            CHK=`grep "${CHARON_CFG})" ${CHARONDIR}/utils/charon_gstart.prestart`
            if test -n "${CHK}"
            then
              CSEQ=""
              ACFG=`echo ${CHARON_CFG} | sed "s=/=\\\\\\/=g"`
              awk "/${ACFG})/,/;;/" ${CHARONDIR}/utils/charon_gstart.prestart >/tmp/display_guests$$.tmp1
              grep -v -e "#\\$" -e "^#" -e "#/" -e "#--" /tmp/display_guests$$.tmp1 | grep -v -e "${CHARON_CFG})" -e ";;" >/tmp/display_guests$$.tmp2
              ACFG=`cat /tmp/display_guests$$.tmp2`
              if test -n "${ACFG}"
              then
                typeset -i P=0
                cat /tmp/display_guests$$.tmp2 | while read PST
                do
                  PSC=`echo ${PST} | cut -c1`
                  if test "${PSC}" != "#" -a -n "`echo ${PST} | tr -d "\t" | tr -d " "`"
                  then
                    P=P+1
                    test "$1" = "-num" && echo -n "  "
                    case $P
                    in
                      1)    echo "  ${FGBLUE}Pre-start:[0m        ${PST}";;
                      2|3)  echo "                    ${PST}";;
                      4)    echo "                    ${PST} [32m(truncated)[0m";;
                    esac
                  fi
                done
              fi
              rm -f /tmp/display_guests$$.tmp[12] >/dev/null 2>&1
            fi
          fi

          if test -n "${CSTATE2}"
          then
            test "$1" = "-num" && echo -n "  "
            echo "  ${CSTATE2}"

            if test -n "${OOMKPROT}"
            then
              test "$1" = "-num" && echo -n "  "
              echo "                  ${OOMKD2} ${OOMKPROT}[0m"
            fi

            if test -x ${CHARONDIR}/utils/charon_gstart.chkrun
            then
              CHK=`grep "${CHARON_CFG})" ${CHARONDIR}/utils/charon_gstart.chkrun`
              if test -n "${CHK}"
              then
                if test "${SVC_IS_ACTIVE}" = "ACTIVE"
                then
                  CHK=`${CHARONDIR}/utils/charon_gstart.chkrun ${CHARON_CFG}|tr -d "\r"|grep -v ^$`
                  CHKDISP=`echo ${CHK} | sed "s:\(^.*\)\(==RETVAL=.*$\):\1:g"`
                  CHKRETV=`echo ${CHK} | sed "s:\(^.*==RETVAL=\)\(.*\)\(==.*$\):\2:g"`
                  test "$1" = "-num" && echo -n "  "
                  case "${CHKRETV}"
                  in
                    "0")
                      echo "  ${FGBLUE}Guest OS answer:[0m  [1m${CHKDISP}[0m"
                      ;;
                    "")
                      echo "  ${FGBLUE}Guest OS answer:[0m  ${BGORANGE}Script misconfigured, RETVAL missing[0m"
                      ;;
                    *)
                      test -z "${CHKDISP}" && CHKDISP="Return code ${CHKRETV}"
                      echo "  [31mGuest OS answer:[0m  [1m${CHKDISP}[0m"
                      ;;
                  esac
                fi
              fi
            fi
          fi
          if test -n "${CSTATE3}"
          then
            test "$1" = "-num" && echo -n "  "
            echo "  ${CSTATE3}"
          fi
        fi

        PORT=`grep -v ^# ${CHARON_CFG} | grep -e uart0.device.port -e gsc.lasi.uart.device.port | cut -f2 -d'=' | tr -d ":'\""`
        echo "${PORT}" >>${PORTCF}

        if test "${LITEON}" = ""
        then
          test "$1" = "-num" && echo -n "  "
          echo -n "  ${FGBLUE}Console port:[0m     ${PORT:-<Unknown>}"
          if test -n "${PORT}" -a -n "`netstat -an 2>/dev/null | grep -w ${PORT:-UNKNOWN} | grep ESTABLISHED`" 
          then
            CHK=`ps -ef | grep SCREEN | grep telnet | grep localhost | grep -w ${PORT}`
            if test -n "${CHK}"
            then
              echo " / ${FGORANGE}Console locked by AUTOCONNECT utility[0m"
            else
              CHK=`ps -ef | grep telnet | grep localhost | grep ${PORT}$ | awk '{print $2}' | tr "\n" " "`
              if test -n "${CHK}"
              then
                echo " / ${FGORANGE}Console locked by 'telnet' pid(s) ${CHK}[0m"
              else
                CHK=`ps -ef | grep putty | grep "\-P ${PORT}" | awk '{print $2}' | tr "\n" " "`
                if test -n "${CHK}"
                then
                  echo " / ${FGORANGE}Console locked by 'putty' pid(s) ${CHK}[0m"
                else
                  CHK=`ps -ef | grep xhpterm | grep "\-port ${PORT}" | awk '{print $2}' | tr "\n" " "`
                  if test -n "${CHK}"
                  then
                    echo " / ${FGORANGE}Console locked by 'xhpterm' pid(s) ${CHK}[0m"
                  else
                    CHK=`netstat -an | grep -w ${PORT} | grep ESTABLISHED | awk '{print $5}'`
                    echo " / ${FGORANGE}Console locked by foreign host `echo ${CHK}|cut -f1 -d':'`, port `echo ${CHK}|cut -f2 -d':'`[0m"
                  fi
                fi
              fi
            fi
          else
            echo
          fi

          if test "$2" = "-console"
          then
            CHK=`grep -v ^# ${CHARON_CFG} | grep "set.*OPA[0-9].*log.*="`
            if test -n "${CHK}"
            then
              get_logfile ${CHARON_CFG} OPA0
              test "$1" = "-num" && echo -n "  "
              echo "  ${FGBLUE}Console log:[0m      ${LOGCONS:-<Unknown>}"
              LOGUNIQ=`grep "^${LOGCONS};" ${CONSCF} 2>/dev/null`
              if test -n "${LOGUNIQ}"
              then
                test "$1" = "-num" && echo -n "  "
                echo "  [31mThe log file is already used in `echo ${LOGUNIQ}|cut -f2 -d";"` virtual machine. Please check[0m"
              else
                echo "${LOGCONS};${EMUCFG}" >>${CONSCF}
              fi
            fi
          else
            #echo
            get_logfile ${CHARON_CFG}
            LOGUNIQ=`grep "^${LOGF};" ${LOGCF} 2>/dev/null`

            test "$1" = "-num" && echo -n "  "
            echo "  ${FGBLUE}Log file:[0m         ${LOGF:-Full path not specified}"

            if test -n "${LOGF}"
            then
              if test -s ${LOGF}
              then
                typeset -i LOGISSUES=0
                typeset -i LOGNBWARN=`grep ':warn:' ${LOGF} | wc -l`
                typeset -i LOGNBERRO=`grep ':err:'  ${LOGF} | wc -l`
                typeset -i LOGNBFATA=`grep ':ERR:'  ${LOGF} | wc -l`
                LOGISSUES=LOGNBWARN+LOGNBERRO+LOGNBFATA
                if test ${LOGISSUES} -gt 0
                then
                  test "$1" = "-num" && echo -n "  "
                  echo -n "                    ${FGORANGE}Issues found[m: "
                  test ${LOGNBWARN} -gt 0 && echo -n "Warning:${LOGNBWARN} "
                  test ${LOGNBERRO} -gt 0 && echo -n "Error:${LOGNBERRO} "
                  test ${LOGNBFATA} -gt 0 && echo -n "Fatal:${LOGNBFATA} "
                  echo
                fi
              fi
            fi

            if test -n "${LOGUNIQ}"
            then
              test "$1" = "-num" && echo -n "  "
              echo "                    [31mAlready used in `echo ${LOGUNIQ}|cut -f2 -d";"` virtual machine.[0m"
              echo "                    [31mPlease check[0m"
            else
              echo "${LOGF};${EMUCFG}" >>${LOGCF}
            fi

            if test -z "`echo ${LOGF} | grep '/'`"
            then
              test "$1" = "-num" && echo -n "  "
              echo "                    [31mNo full path specified: not monitored![0m"
            fi

            if test -z "`echo ${LOGF} | grep \.log$`"
            then
              test "$1" = "-num" && echo -n "  "
              echo "                    [36mNo '.log' extension defined for log file ![0m"
              if ! test -d ${LOGF}
              then
                test "$1" = "-num" && echo -n "  "
                echo "                    [36mThe file specified is not an existing folder (no log rotation)[0m"
              fi
            fi

            if test -z "`grep ^${LOGF}$ ${LOGFLIST:-/opt/charon/utils/charon_logchk.list} 2>/dev/null`"
            then
              test "$1" = "-num" && echo -n "  "
              if test "${GLOBALLOGMON}" = "enabled"
              then
                echo "                    [31mLog file is not monitored![0m"
              fi
            else
              if test -s /etc/systemd/system/charon_logmon_${CHARON_CFGBAS}.service
              then
                EXECTOP=0
                for EX in ExecStart ExecStop
                do
                  SVCLOGF=`grep ^${EX}= /etc/systemd/system/charon_logmon_${CHARON_CFGBAS}.service 2>/dev/null | awk '{print $3}'`
                  if test -s ${LOGF} -a "${LOGF}" != "${SVCLOGF}"
                  then
                    if test ${EXECTOP} = 0
                    then
                      test "$1" = "-num" && echo -n "  "
                      echo "                    [31mLog monitor service: log file monitored does[0m"
                      test "$1" = "-num" && echo -n "  "
                      echo "                    [31mnot match configuration file[0m"
                      test "$1" = "-num" && echo -n "  "
                      echo "                    Please update the log monitoring service definition file:"
                      test "$1" = "-num" && echo -n "  "
                      echo "                    Use 'Manage monitored guests logs' option and 'Update"
                      test "$1" = "-num" && echo -n "  "
                      echo "                    log files list' then the \"Manage 'systemd' services\""
                      test "$1" = "-num" && echo -n "  "
                      echo "                    option. Finally restart the service."
                      EXECTOP=1
                    fi
                    test "$1" = "-num" && echo -n "  "
                    echo "                    ${FGBLUE}Check log file definition in \"${EX}=\" line[0m"
                  fi
                done
              fi
              SVCL_IS_ACTIVE=`systemctl is-active charon_logmon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f1 -d'-' | tr [:lower:] [:upper:]`
              if test "${SVCL_IS_ACTIVE}" != "ACTIVE" -a "${GLOBALLOGMON}" = "enabled"
              then
                test "$1" = "-num" && echo -n "  "
                echo "                    [31mLog monitor service state: ${SVCL_IS_ACTIVE:-unknown}[0m"
              fi
              if test "${SVCL_IS_ACTIVE}" != "UNKNOWN"
              then
                SVC_IS_ENABLED=`systemctl is-enabled charon_logmon_${CHARON_CFGBAS}.service 2>/dev/null | cut -f1 -d'-' | tr [:lower:] [:upper:]`
                if test "${SVC_IS_ENABLED}" != "ENABLED"
                then
                  test "$1" = "-num" && echo -n "  "
                  echo "                    [31mLog monitor is not enabled at system startup![0m"
                else
                  if test "${SVC_IS_ACTIVE}" = "ACTIVE" -a "${GLOBALLOGMON}" = "enabled"
                  then
                    if test -s ${CHARONDIR}/utils/events/${CHARON_CFGBAS}.license_status
                    then
                      test "$1" = "-num" && echo -n "  "
                      echo -n "  ${FGBLUE}License:[0m        "
                      if test "${SEMIGRAPH}" = "enabled"
                      then
                        tput smacs;echo -n "l";tput rmacs;echo -n " "
                      else
                        echo -n "+ "
                      fi
                      LICST=`cat ${CHARONDIR}/utils/events/${CHARON_CFGBAS}.license_status`
                      case "`echo ${LICST} | cut -f2 -d';'`"
                      in
                        "WARN")  echo -n "${BGORANGE}";;
                        "ERROR") echo -n "[41m[30m";;
                      esac
                      LICSTM=`echo ${LICST} | cut -f3 -d';'`
                      if test -z "`echo ${LICSTM} | grep 'Application will stop'`"
                      then
                        if test -z "`echo ${LICSTM} | grep 'Communication restored'`"
                        then
                          if test -z "`echo ${LICSTM} | grep 'Communication lost with'`"
                          then
                            echo "${LICSTM}`tput sgr0`"
                          else
                            echo "`echo ${LICSTM} | cut -f1 -d','``tput sgr0`"
                            test "$1" = "-num" && echo -n "  "
                            echo -n "                  "
                            if test "${SEMIGRAPH}" = "enabled"
                            then
                              tput smacs;echo -n "x";tput rmacs
                            else
                              echo -n "|"
                            fi
                            echo "`echo ${LICSTM} | sed "s=license=License=g" | cut -f2 -d','`."
                          fi
                        else
                          echo "`echo ${LICSTM} | cut -f1 -d','``tput sgr0`"
                          test "$1" = "-num" && echo -n "  "
                          echo -n "                  "
                          if test "${SEMIGRAPH}" = "enabled"
                          then
                            tput smacs;echo -n "x";tput rmacs
                          else
                            echo -n "|"
                          fi
                          echo "`echo ${LICSTM} | sed "s=license=License=g" | cut -f2 -d','`."
                        fi
                      else
                        LICSTM1=`echo ${LICSTM} | sed "s=\(^.*\)\( Application.*$\)=\1=g"`
                        LICSTM2=`echo ${LICSTM} | sed "s=\(^.*\)\( Application.*$\)=\2=g"`
                        echo "${LICSTM1}`tput sgr0`"
                        test "$1" = "-num" && echo -n "  "
                        echo -n "                  "
                        if test "${SEMIGRAPH}" = "enabled"
                        then
                          tput smacs;echo -n "x";tput rmacs
                        else
                          echo -n "|"
                        fi
                        echo "${LICSTM2}"
                      fi
                      test "$1" = "-num" && echo -n "  "
                      echo -n "                  "
                      if test "${SEMIGRAPH}" = "enabled"
                      then
                        tput smacs;echo -n "m";tput rmacs;echo -n " "
                      else
                        echo -n "+ "
                      fi
                      echo -n "Event date/time: "
                      echo ${LICST} | cut -f1 -d';'                     
                    fi
                  fi
                fi
              else
                if test "${GLOBALLOGMON}" = "enabled"
                then
                  echo "                    [31mLog monitor is not configured ! (${LOGF})[0m"
                fi
              fi
            fi
          fi

          test "$1" = "-num" && echo -n "  "
          echo -n "  ${FGBLUE}Network:[0m          "
          NNIC=0
          for LOADPKT in `grep -e 'system.lan' -e 'EW' ${CHARON_CFG} | grep -e '\.iface' -e "\.mapping_mode" | grep -v ^# | sed -e "s=system\.==g" -e "s=\.card==g" -e "s=\.iface==g"  -e "s=\.mapping_mode==g" | tr -d "'\""`
          do
            PKP=`echo ${LOADPKT} | cut -f1 -d"="`
            ETH=`echo ${LOADPKT} | cut -f2 -d"="`
            NNIC=1
            test -z "${ETH}" && ETH="UNKNOWN"
            case "`echo ${ETH} | tr [:upper:] [:lower:]`"
            in
              "dummy")
                echo -n "${PKP}/"
                echo -n "[36m${ETH}[0m "
                ;;
              "raw"|"tap")
                DoNothing=1
                ;;
              *)
                echo -n "${PKP}/"
                # ifconfig ${ETH} >/dev/null 2>&1
                ip a | grep -q -w ${ETH}:
                if test $? = 0
                then
                  # IFADDR=`ifconfig ${ETH} | grep -w inet | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1`
                  IFADDR=`ip -o a show ${ETH} | grep -w inet | grep -oE "\b([0-9]{1,3}\.){3}[0-9]{1,3}\b" | head -1`
                  if test -n "${IFADDR}"
                  then
                    NICALERT4=1
                    echo -n "[31m${ETH}[0m(4) "
                  else
                    if test -e ${NCUBIN}
                    then
                      if test -z "`grep -w ${ETH} ${NCU_CFG} 2>/dev/null`"
                      then
                        NICALERT2=1
                        if test -z "`grep ^${ETH}$ ${NICCF} 2>/dev/null`"
                        then
                          echo -n "[31m${ETH}[0m(2) "
                          echo ${ETH} >>${NICCF}
                        else
                          NICALERT3=1
                          echo -n "[31m${ETH}[0m(2,3) "
                        fi
                      else
                        if test -z "`grep ^${ETH}$ ${NICCF} 2>/dev/null`"
                        then
                          echo -n "[32m${ETH}[0m "
                          echo ${ETH} >>${NICCF}
                        else
                          NICALERT3=1
                          echo -n "${FGORANGE}${ETH}[0m(3) "
                        fi
                      fi
                    else
                      if test -z "`grep ^${ETH}$ ${NICCF} 2>/dev/null`"
                      then
                        echo -n "[32m${ETH}[0m "
                        echo ${ETH} >>${NICCF}
                      else
                        NICALERT3=1
                        echo -n "${FGORANGE}${ETH}[0m(3) "
                      fi
                    fi
                  fi
                else
                  NICALERT1=1
                  echo -n "[31m[1m${ETH}[0m(1) "
                fi
                ;;
            esac
          done
          test ${NNIC} = 0 && echo -n "No network card defined"
          echo
        fi
      else
        EMUX1=`basename ${CHARON_EXE}`
        EMUX2=${CHARON_CFG}

        test $I -eq ${VMSEL:-0} && IDN="*" || IDN="-"
        echo -n "[1m"
        echo -n "${IDN} "
        echo -n `dirname ${EMUX2}`
        echo -n "/${FGBLUEBOLD}"
        echo -n `basename ${EMUX2} | sed "s=\.cfg$=[0m[1m.cfg=g"`
        echo "[0m"

        test "$1" = "-num" && echo -n "  "
        echo "  [31mConfiguration file does not exist![0m"
      fi
    done

    if test ${NICALERT1} = 1 -o ${NICALERT2} = 1 -o ${NICALERT3} = 1 -o ${NICALERT4} = 1
    then
      echo
      echo -n "${FGBLUEBOLD}Legend[0m: "
      test ${NICALERT1} = 1 && echo -n "(1)=NIC does not exist "
      test ${NICALERT2} = 1 && echo -n "(2)=NIC not managed by ncu "
      test ${NICALERT3} = 1 && echo -n "(3)=NIC already used "
      test ${NICALERT4} = 1 && echo -n "(4)=NIC has an IP address "
      echo
    fi

    sort    ${PORTCF} >${PORTCF}.sorted
    sort -u ${PORTCF} >${PORTCF}.sortedunique
    if test -n "`diff ${PORTCF}.sorted ${PORTCF}.sortedunique`"
    then
      echo
      echo "${BGORANGE} WARNING [0m Found duplicated console ports. Please check!"
    fi
    rm -f ${PORTCF} ${PORTCF}.sorted ${PORTCF}.sortedunique ${NICCF} ${LOGCF} ${CONSCF} 2>/dev/null
    
  fi

  #-- Displays an alert if virtual machines are not in separate folders
  ( for LINE in `grep -v ^# ${BOOTLIST}`
  do
    dirname `echo ${LINE} | cut -f2 -d';'`
  done ) | sort -u >${BOOTLIST}.tmp.$$
  NBFOLD=`cat ${BOOTLIST}.tmp.$$ | wc -l`
  NBGUES=`grep -v ^# ${BOOTLIST} | wc -l`
  rm -f ${BOOTLIST}.tmp.$$ 2>/dev/null
  if test ${NBFOLD} -ne ${NBGUES}
  then
    echo
    echo "${BGORANGE} WARNING [0m There are virtual machines using the same folder !"
    echo "          This will cause files lock. Please update accordingly."
  fi

  #-- Displays an alert if the root password has expired
  chage -l root | grep "^Password expires" | grep -q "password must be changed"
  if test $? = 0
  then
    echo
    echo "${BGORANGE} WARNING [0m Root password has expired. Some functionalities could be inoperative!"
  fi
}

#=============================================================================
# Function: display_licfound
#=============================================================================
function display_licfound
{
  echo "[1mLocal licenses found (on this server)[0m:"
  echo -n "- ${FGBLUE}USB dongles: "
  /usr/bin/lsusb -d 0529: | wc -l
  echo -n "[0m"
  if test "$1" = "full"
  then
    /usr/bin/lsusb -d 0529:0001 -v | grep -e ^Bus -e iProduct | sed "s=^=    =g"
  fi

  echo -n "- ${FGBLUE}Software licenses (SL): "
  ls /var/hasplm/installed/68704/*.v2c 2>/dev/null | cut -f1 -d "_" | sort -u | wc -l
  echo -n "[0m"
  if test "$1" = "full"
  then
    for LIC in `ls /var/hasplm/installed/68704/*_base.v2c 2>/dev/null`
    do
      LICID=`basename ${LIC} | cut -f1 -d "_"`
      echo -n "    License Id: ${LICID} "
      NBUPD=`ls /var/hasplm/installed/68704/${LICID}_update*.v2c 2>/dev/null | wc -l`
      test ${NBUPD:-0} -eq 0 && echo || echo "(updates: ${NBUPD})"      
    done
  fi

  echo
}

#=============================================================================
# Function: select_logfile
#=============================================================================
function select_logfile
{
  # Input field = $LOGF
  LOGLISTFIL=/tmp/charon.loglist.tmp
  LOGFSAV=${LOGF}

  while test 1
  do
    rm -f ${LOGLISTFIL} 2>/dev/null
    LOGF=${LOGFSAV}

    if test -L ${LOGF}
    then
      FILFCURR=`dirname ${LOGF}`"/"`file ${LOGF}|cut -f2 -d'\`'|tr -d "'"`
      FILFLIST="`echo ${LOGF} | sed "s=\.log==g"`.??????-??????-????.log"
    else
      FILFCURR=${LOGF}
      FILFLIST="${LOGF}.upto* ${LOGF}"
    fi    

    ls -1tr ${FILFLIST} | tail -16 | while read FILF
    do
      ls -l --full-time ${FILF} 2>/dev/null | tail -15 | while read LINE
      do
        LOGNAME=`echo ${LINE} | awk '{print $9}'`
        echo ${LOGNAME} >>${LOGLISTFIL}
        NBF=`cat ${LOGLISTFIL} | wc -l`
        if test ${NBF} -eq 1
        then
          echo "${FGBLUEBOLD}Log files found (most recent ones)[0m:"
          echo
          echo "No  From                      To                        Size          Lines"
          if test "${SEMIGRAPH}" = "enabled"
          then
            tput smacs
            echo "qq  qqqqqqqqqqqqqqqqqqqqqqqq  qqqqqqqqqqqqqqqqqqqqqqqq  qqqqqqqqqqqq  qqqqqqqqq"
            tput rmacs
          else
            echo "--  ------------------------  ------------------------  ------------  ---------"
          fi
        fi
        echo -n "[0m"
        test `echo ${NBF}%2 | bc` = 1 && echo -n "${FGBLUE}"
        test "${FILF}" = "${FILFCURR}" && tput smso

        printf "%2d  " ${NBF}
        LOGFROM=`head -24 ${LOGNAME} | grep ^[0-9]*:[0-9]*\. | head -1 | sed "s=\(^........\):\(..\)\(..\)\(..\)\.\(.*$\)=\1 \2:\3:\4=g"`
        test -z "${LOGFROM}" && LOGFROM=`echo ${LINE} | awk '{print $6,$7}' | awk -F '.' '{print $1}'`
        LOGFROM=`date +"%a %d-%b-%Y %H:%M:%S" -d "${LOGFROM}"`

        #LOGTO=`echo ${LINE} | awk '{print $9}' | sed "s=\(^.*upto\)\(.*$\)=\2=g" | sed "s=\(^....-..-..\)\(\-\)\(..\)\(..\)\(..\)=\1 \3:\4:\5=g"`
        LOGTO=`tail -24 ${LOGNAME} | grep ^[0-9]*:[0-9]*\. | tail -1 | sed "s=\(^........\):\(..\)\(..\)\(..\)\.\(.*$\)=\1 \2:\3:\4=g"`
        if test -z "${LOGTO}"
        then
          LOGTO="<unknown>"
        else
          LOGTO=`date +"%a %d-%b-%Y %H:%M:%S" -d "${LOGTO}"`
        fi
        LOGSIZE=`echo ${LINE} | awk '{print $5}'`
        LOGLINES=`wc -l ${LOGNAME} | awk '{print $1}'`
        printf "%-24s  %-24s  %'12d  %9d[0m\n" "${LOGFROM}" "${LOGTO}" "${LOGSIZE}" "${LOGLINES}"
        tput rmso
        tput sgr0
        LOGFLOCK=`fuser ${LOGNAME} 2>/dev/null | cut -f2 -d':'`
        if test -n "${LOGFLOCK}"
        then
          echo -n "    Lock status: "
          for P in ${LOGFLOCK}
          do
            ps -P ${P} | grep "${TAILCMD}" >/dev/null 2>&1
            test $? = 0 && echo -n "[32m<Monitored>[0m "
            ps -P ${P} | grep -w "\-d" | grep "\.cfg$" >/dev/null 2>&1
            test $? = 0 && echo -n "[32m<Guest running>[0m "
          done
          echo
        fi
      done
    done
    echo
  
    if test -s ${LOGLISTFIL}
    then
      while test 1
      do
        echo -n "Select the log file you want to view (q to quit, r to refresh): "
        read ANS
        test "${ANS}" = "q" && break 2
        test "${ANS}" = "r" && break
        if test -n "${ANS}"
        then
          if test -z "`echo ${ANS} | tr -d [0123456789]`"
          then
            if test ${ANS} -lt 1 -o ${ANS} -gt `cat ${LOGLISTFIL} | wc -l`
            then
              tput bold
              echo "Incorrect value, out of range."
              tput sgr0
              sleep 2
              tput cuu1;tput el
            else
              LOGF=`head -${ANS} ${LOGLISTFIL} | tail -1`
              if test -e ${LOGF}
              then
                if test -s ${LOGF}
                then
                  echo
                  echo "File selected: ${FGBLUE}${LOGF}[0m"
                  echo
                  ask_editor
                  if test -n "${EDI}"
                  then
                    SPEC=""
                    CVIMRC="${CHARONDIR}/utils/charonlog.vimrc"
                    test -n "`echo ${EDI} | grep -w gvim`"                 && SPEC="-m"
                    test -n "`echo ${EDI} | grep -w gvim`" -a -e ${CVIMRC} && SPEC="-m -u ${CVIMRC}"
                    test "${EDI}" = "/usr/bin/vim"                         && SPEC="-m"
                    test "${EDI}" = "/usr/bin/vim"  -a -e ${CVIMRC}        && SPEC="-m -u ${CVIMRC}"
                    test "${EDI}" = "/bin/vi"                              && SPEC="-m"
                    if test -n "`grep ':ll_sentine' ${LOGF}`"
                    then
                      echo
                      while test 1
                      do
                        echo "Do you want the full log or its shortened version without 'regular license"
                        echo -n "check' messages ['f' for full (default), 's' for short, 'q' to quit] ? "
                        read ANS
                        case "${ANS}"
                        in
                          ""|"f")
                            ${EDI} ${SPEC} ${LOGF} 2>/dev/null
                            break
                            ;;
                          "s")
                            cat ${LOGF} | grep -v -e ":000003BA:" -e ":000003DC:" -e ":000003E6:" -e ":000003E7:" \
                                >/tmp/`basename ${LOGF}`.short
                            ${EDI} ${SPEC} /tmp/`basename ${LOGF}`.short 2>/dev/null
                            break
                            ;;
                          "q")
                            break
                            ;;
                          *)
                            tput cuu1;tput el;tput cuu1;tput el
                            ;;
                        esac
                      done
                    else
                      ${EDI} ${SPEC} ${LOGF} 2>/dev/null
                    fi
                  fi
                  break
                else
                  tput bold
                  echo "Log file is empty."
                  tput sgr0
                  sleep 2
                  tput cuu1;tput el
                fi
              else
                tput bold
                echo "Log file ${LOGF} does not exist."
                tput sgr0
                sleep 2
                tput cuu1;tput el
              fi
            fi
          else
            tput bold
            echo "Incorrect value, must be numeric."
            tput sgr0
            sleep 2
            tput cuu1;tput el
          fi
        fi
        tput cuu1;tput el
      done
    else
      echo "No log file found."
      sleep 1
      break
    fi
  done
}

#=============================================================================
# Function: tail_log_colored
#=============================================================================
function end_tail
{
  echo
  echo "[44m[37m Continuous view of ${LOGT} aborted [0m"
  kill -9 `ps -f|grep 'tail -Fn12'|grep -v grep|awk '{print $2}'` 2>/dev/null
  sleep 1
  echo
}

function tail_log_colored
{ 
  LOGT=$1
  TAMO=$2
  tput clear
  typeset -i NBL=0
  echo "[44m[37m Continuous view of ${LOGT} [0m"
  echo -n "[31mPress CTRL-C to stop[0m"
  if test `tput cols` -lt 132
  then
    echo " (it is recommended to enlarge screen to 132 cols minimum)"
  else
    echo
  fi
  if test "${SEMIGRAPH}" = "enabled"
  then
    tput smacs
    echo "qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq"
    tput rmacs
  else
    echo "--------------------------------------------------------------------------------"
  fi
  trap 'end_tail' 1 2 9 14 15
  #STADAT=`date +%Y%m%d%H%M%S`
  STADAT=`head -24 ${LOGT} | grep ^[0-9]*:[0-9]*\. | head -1 | awk -F':' '{print $1 $2}' | tr -d '.'`

  CHKSTA=0
  CHKSTO=0
  tail -Fn12 --retry ${LOGT} | while read LINE
  do
    case "`echo ${LINE} | cut -f3 -d:`"
    in
      "warn")
        #echo -n "[46m[30m"
        echo -n "${BGORANGE}"
        ;;
      "err"|"ERR")
        echo -n "[41m[37m"
        ;;
      "Charon-PAR"|"Charon-HPA")
        echo -n "[42m[30m"
        ;;
      "log file"|"config load")
        echo -n "${FGBLUE}"
        ;;
      "System model"|"RAM size"|"Host CPU freq")
        echo -n "${FGBLUE}"
        ;;
      "Found license key"|"License number")
        echo -n "[42m[37m"
        ;;
      "emulator is about to exit")
        echo -n "[31m"
        ;;
      "starting the emulator")
        echo -n "[42m[30m"
        ;;
      "run cpu loop")
        #--- Up to Version 3.0.0
        CURDAT=`echo ${LINE} | awk -F':' '{print $1 $2}' | tr -d '.'`
        test `echo ${CURDAT}-${STADAT}|bc` -gt 0 && CHKSTA=1
        echo -n "[42m[30m"
        ;;
      cpu*)
        #--- Starting with Version 3.0.1
        if test -n "`echo ${LINE} | grep 'run cpu loop'`"
        then
          CURDAT=`echo ${LINE} | awk -F':' '{print $1 $2}' | tr -d '.'`
          test `echo ${CURDAT}-${STADAT}|bc` -gt 0 && CHKSTA=1
          echo -n "[42m[30m"
        fi
        ;;
      "exit"|" ... exiting since no valid license is available.")
        CURDAT=`echo ${LINE} | awk -F':' '{print $1 $2}' | tr -d '.'`
        test `echo ${CURDAT}-${STADAT}|bc` -gt 0 && CHKSTO=1
        echo -n "[31m"
        ;;
      *)
        if test -n "`echo ${LINE} | grep 'Got connection from'`"
        then
          echo -n "[36m"
        fi
        ;;
    esac
    echo "${LINE}[0m"
    NBL=NBL+1
    if test ${NBL} -gt `tput lines`
    then
      NBL=0
      get_preferences
      if test "${LOGTAILCT}" = "enabled"
      then
        echo "[100m[37m ------ Press CTRL-C to stop the continuous log view ------ [0m"
      fi
    fi

    if test ${AUTOSTOPLOGTAIL:-1} = 1 -a "${TAMO}" != "NOSTOP"
    then
      if test ${CHKSTA} = 1
      then
        echo
        echo "Emulator started, use the '[1mvmconsole[0m' command or use the '[1mConnect to guest[0m"
        echo "[1mconsole[0m' menu option to open the console."
        kill -9 `ps -f|grep "tail -Fn12 --retry ${LOGT}"|grep -v grep|awk '{print $2}'` 2>/dev/null
        sleep 1
        CHKSTA=2
      fi
      if test ${CHKSTO} = 1
      then
        tput smso
        echo "Emulator stopped!"
        tput rmso
        kill -9 `ps -f|grep "tail -Fn12 --retry ${LOGT}"|grep -v grep|awk '{print $2}'` 2>/dev/null
        sleep 1
        CHKSTO=2
      fi
    fi

  done
  trap 'exit' 1 2 9 14 15
}

#=============================================================================
# Function: FollowServiceStatus
#=============================================================================
function FollowServiceStatus {
  case "$1"
  in 
    "start")
      kill -9 `ps | grep journalctl | awk '{print $1}'` 2>/dev/null
      trap "echo" 9
      ( journalctl -lfu $2 -qn0 -o export 2>/dev/null | while read JL
        do
          JLP=`echo ${JL} | cut -f1 -d'='`
          case "${JLP}"
          in
            "__REALTIME_TIMESTAMP")
               JLV=`echo ${JL} | cut -f2 -d'='`
               TSTAMP=`echo ${JLV} / 1000000 | bc`
               ;;
            "MESSAGE")
               JLV=`echo ${JL} | cut -c9-`
               case "`echo ${JLV} | cut -c1-7`"
               in
                 "Startin")  echo -n "[32m";;
                 "Started")  echo -n "[42m";;
                 "Stoppin")  echo -n "[31m";;
                 "Stopped")  echo -n "[41m[37m";;
                 "Failed ")  echo -n "[31m[1m";;
                 *)          echo -n "${FGBLUE}";;
               esac
               if test -n "`echo ${JL} | grep -w EXPECT`"
               then
                 EXPLVL=`echo ${JL} | sed "s=^.*%EXPECT-\([A-Z]\)-.*$=\1=g"`
                 case "${EXPLVL}"
                 in
                   "S") echo -n "[42m[30m";;
                   "I") echo -n "[32m";;
                   "W") echo -n "${BGORANGE}";;
                   "E") echo -n "[31m";;
                   "F") echo -n "[41m[37m";;
                 esac
                 echo `date +"%b %d %T" -d @${TSTAMP}`" ${JLV}[0m"
               else
                 echo `date +"%b %d %T" -d @${TSTAMP}`"[0m ${JLV}"
               fi
               ;;
          esac
        done ) &
      ;;
    "stop")
      sleep 3
      kill -9 `ps | grep journalctl | awk '{print $1}'` 2>/dev/null
      trap "exit" 9
      ;;
  esac
}
