#!/bin/bash

################################################################################
# Copyright 2023-2025 by NI SP Software GmbH, All rights reserved.
# Copyright 1999-2023 by Nice, srl., All rights reserved.
#
# This software includes confidential and proprietary information
# of NI SP Software GmbH ("Confidential Information").
# You shall not disclose such Confidential Information
# and shall use it only in accordance with the terms of
# the license agreement you entered into with NI SP Software.
################################################################################

################################################################################
# The following is for the Linux chkconfig utility
# chkconfig: 35 99 01
# description: NI SP EF Portal
################################################################################


#
# http://refspecs.linuxbase.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/tocsysinit.html
#
### BEGIN INIT INFO
# Provides:          enginframe
# Default-Start:     3 5
# Default-Stop:      0 1 2 4 6
# Required-Start:    $local_fs $network
# Required-Stop:     $local_fs $network
# Short-Description: NI SP EF Portal
# Description:       NI SP EF Portal (http://www.ni-sp-software.com)
### END INIT INFO


#-------------------------------------------------------------------------------
# ef_main()
# Main function of this script.
# It calls other functions according to the input options
#-------------------------------------------------------------------------------
ef_main(){

    # Handle special flag for interactive startup of daemons. Default false
    _interactive="false"

    # Enable Tomcat JPDA: disabled by default
    _jpda="false"

    while [ $# -gt 0 ]; do
        case "$1" in
            -i)
                _interactive="true"
                ;;
            --jpda)
                _jpda="true"
                ;;
            --conf)
                EF_CONF="$2"
                shift
                ;;
            --conf-id)
                EF_CONF_ID="$2"
                shift
                ;;
            --)
                shift
                # Get input parameters
                _command="$1"
                _component="$2"
                break
                ;;
            host-setup)
                _command="$1"
                break
                ;;
            *)
                # Get input parameters
                _command="$1"
                _component="$2"
                break
                ;;
        esac
        shift
    done

# Syntax check
if [ "${_interactive}" = "true" ] && [ -z "${_component}" ] ; then
  echo "[ERROR] You cannot start both server and agent interactively"
  exit 1
fi

# This function sets some variable and checks the environment
# If this script stops, then probably the reason is that ef_init
# found something wrong in the configuration file
  _ef_check_user="true"
  case "${_command}" in
    "status") _ef_check_user="false" ;;
  esac

  ef_init

  if [ "${_jpda}" = "true" ] ; then
    TOMCAT_START_OPTIONS="jpda start"
  fi

# Let start with the real stuff
  case "${_command}" in
    host-setup)
      shift
      echo ""
      echo "Launching ${EF_VERSION_ROOT}/enginframe/tools/host.setup.sh..."
      echo ""
      export EF_CONF
      "${EF_VERSION_ROOT}/enginframe/tools/host.setup.sh" "$@"
      _exit_code=$?
      exit $_exit_code
      ;;
    start)
      ef_start "${_component}"
      ;;
    stop)
      ef_stop "${_component}"
      ;;
    status)
      ef_status "${_component}"
      ;;
    restart)
      ef_stop "${_component}"
      sleep 1
      ef_start "${_component}"
      ;;
    *)
      echo "${efmsg_usage}"
      ;;
  esac

# Interactive
if [ "${_interactive}" = "true" ] ; then
  case "${_component}" in
    "agent") wait "$(cat "${EF_AGENTPID}")" ;;
    "server")
      _pid=$(cat "${CATALINA_PID}")
      while ps -p "${_pid}" >/dev/null 2>&1 ; do
        sleep 5
      done
    ;;
  esac
fi
}

#-------------------------------------------------------------------------------
# ef_start()
# manages the startup of EF Portal Daemons
#-------------------------------------------------------------------------------
ef_start(){
  _daemon="$1"
  case "${_daemon}" in
          "") ef_derby "start" ; ef_server "start" ; ef_agent "start" ; ef_shell "start"; ef_proxy "start" ;;
    "server") ef_server "start" ;;
     "agent") ef_agent  "start" ;;
     "derby") ef_derby  "start" ;;
     "shell") ef_shell  "start" ;;
     "proxy") ef_proxy  "start" ;;
    *) echo "${efmsg_usage}" ;;
    esac
}

#-------------------------------------------------------------------------------
# ef_stop()
# manages the shutdown of EF Portal Daemons
#-------------------------------------------------------------------------------
ef_stop(){
  _daemon="$1"
  case "${_daemon}" in
          "") ef_server "stop" ; ef_derby "stop" ;  ef_agent "stop" ; ef_shell "stop" ; ef_proxy "stop" ;;
    "server") ef_server "stop" ;;
     "agent") ef_agent  "stop" ;;
     "derby") ef_derby  "stop" ;;
     "shell") ef_shell  "stop" ;;
     "proxy") ef_proxy  "stop" ;;
    *) echo "${efmsg_usage}" ;;
    esac
}

#-------------------------------------------------------------------------------
# ef_shell()
# manages the startup and shutdown of EF Portal Remote Shell running on Node
#-------------------------------------------------------------------------------
ef_shell(){
  _action="$1"
  if [ "${EF_SHELL_ENABLED}" = "true" ] ; then
    case "${_action}" in
      "start") ef_shellstart ;;
      "stop") ef_shellstop ;;
    esac
  else
    # Let the BASH scripts know Web Shell has been DISABLED
    #echo "${efmsg_shellnotenabled}"
    touch "$EF_CONF_ROOT/shell/not_working"
  fi
}

#-------------------------------------------------------------------------------
# ef_proxy()
# manages the startup and shutdown of EF Portal Web Proxy running on Node
#-------------------------------------------------------------------------------
ef_proxy(){
  _action="$1"
  if [ "${EF_PROXY_ENABLED}" = "true" ] ; then
    case "${_action}" in
      "start") ef_proxystart ;;
      "stop") ef_proxystop ;;
    esac
  else
    # Let the BASH scripts know Web Proxy has been DISABLED
    #echo "${efmsg_proxynotenabled}"
    touch "$EF_CONF_ROOT/proxy/not_working"
  fi
}

#-------------------------------------------------------------------------------
# ef_server()
# manages the startup and shutdown of EF Portal Server (inside Tomcat)
#-------------------------------------------------------------------------------
ef_server(){
  _action="$1"
  if [ "${EF_SERVER_ENABLED}" = "true" ] ; then
    case "${_action}" in
      "start") ef_tomcatstart ;;
      "stop") ef_tomcatstop ;;
    esac
  fi
}

#-------------------------------------------------------------------------------
# ef_derby()
# manages the startup and shutdown of EF Portal Derby DB
#-------------------------------------------------------------------------------
ef_derby(){
  _action="$1"
  case "${_action}" in
    "start") ef_derbystart ;;
    "stop") ef_derbystop ;;
  esac
}

#-------------------------------------------------------------------------------
# ef_agent()
# manages the startup and shutdown of EF Portal Agent
#-------------------------------------------------------------------------------
ef_agent(){
  _action="$1"
  if [ "${EF_AGENT_ENABLED}" = "true" ] ; then

    if [ ! -f "${EF_AGENTPID}" ] ; then
      _pid=""
    else
      _pid="$(cat "${EF_AGENTPID}")"
      if ! ps -p "${_pid}" >/dev/null 2>/dev/null ; then
        rm -f "${EF_AGENTPID}"
        _pid=""
      fi
    fi

    case "${_action}" in
      "start") ef_agentstart "${_pid}" ;;
      "stop") ef_agentstop "${_pid}" ;;
    esac

  fi
}

#-------------------------------------------------------------------------------
# ef_tomcatstart()
# let's start EF Portal Server
#-------------------------------------------------------------------------------
ef_tomcatstart(){
  if [ -f "${CATALINA_PID}" ] ; then
    _pid="$(cat "${CATALINA_PID}")"
    if ps -p "${_pid}" >/dev/null 2>/dev/null ; then
      echo "${efmsg_serverisrunning}" >&2
      echo ">>> LockFile: ${CATALINA_PID}"
      echo ">>> PID: ${_pid}"
      return 1
    else
      # The server isn't running so let's remove the PID file
      rm -f "${CATALINA_PID}"
    fi
  fi

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${TOMCAT_USER}" \
      -s /bin/bash -c "${_initshellenv}; ${TOMCAT_START} ${TOMCAT_START_OPTIONS}" \
      <"/dev/null"
  else
    eval "${_initshellenv}; ${TOMCAT_START} ${TOMCAT_START_OPTIONS}"
  fi

  # shellcheck disable=SC2181
  if [ "$?" = "0" ] ; then
    echo "${efmsg_serverok}"
  else
    echo "${efmsg_servernotok}"
    exit 1
  fi
}

#-------------------------------------------------------------------------------
# ef_derbystart()
# let's start Derby DB
#-------------------------------------------------------------------------------
ef_derbystart(){
  if [ "${EF_DERBY_ENABLED}" != 'true' ]; then
    return 0
  fi

  _cmd="${JAVA_HOME}/bin/java"
  _cmd="${_cmd} $DERBY_JAVA_OPTIONS"
  _cmd="${_cmd} -jar '${DERBY_DIST_HOME}/lib/derbyrun.jar'"
  _cmd="${_cmd} server"
  _cmd="${_cmd} start"
  _cmd="${_cmd} -h ${DERBY_ADDR}"
  _cmd="${_cmd} -p ${DERBY_PORT}"
  _cmd="${_cmd} >'${DERBY_LOGDIR}/derby.out'"
  _cmd="${_cmd} 2>'${DERBY_LOGDIR}/derby.err'"
  _cmd="${_cmd} &"
  _cmd="${_cmd} "'echo $!'" > '${DERBY_LOGDIR}/derby.pid'"

  _cmd="${_initshellenv}; ${_cmd}"

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${DERBY_OS_USER}" \
      -s /bin/bash -c "${_cmd}" \
      <"/dev/null"
  else
    eval "${_cmd}"
  fi

  # shellcheck disable=SC2181
  if [ "$?" = "0" ] ; then
    _derby_pid=$(cat "${DERBY_LOGDIR}/derby.pid")
    echo "Starting Derby DB [PID: ${_derby_pid}]..."
  else
    echo "${efmsg_derbynotok}"
    exit 1
  fi

  sleep 2

  if kill -0 "${_derby_pid}" ; then
    echo "${efmsg_derbyok}"
  else
    echo "${efmsg_derbynotok}"
    echo "derby.out:"
    tail "${DERBY_LOGDIR}/derby.out"
    echo "derby.err:"
    tail "${DERBY_LOGDIR}/derby.err"
    exit 1
  fi
}

get_derby_info() {
  _userpass_pattern='^derby\.user\.\([^=]\{1,\}\)\ *=\ *\(.*\)\ *$'
  _derby_config_file="${DERBY_SYSTEM_HOME}/derby.properties"

  case "$1" in
    user|username)
      sed -n -e "s/${_userpass_pattern}/\1/p" "${_derby_config_file}" | head -1
      ;;
    pass|password)
      sed -n -e "s/${_userpass_pattern}/\2/p" "${_derby_config_file}" | head -1
      ;;
  esac
}

#-------------------------------------------------------------------------------
# ef_derbystatus()
# reports the status of Derby DB
#-------------------------------------------------------------------------------
ef_derbystatus(){
  if [ "${EF_DERBY_ENABLED}" != 'true' ]; then
    return 0
  fi

  _user=$(get_derby_info user)
  _password=$(get_derby_info password)

  _cmd="${JAVA_HOME}/bin/java"
  _cmd="${_cmd} ${DERBY_JAVA_OPTIONS}"
  _cmd="${_cmd} -jar '${DERBY_DIST_HOME}/lib/derbyrun.jar'"
  _cmd="${_cmd} server"
  _cmd="${_cmd} ping"
  _cmd="${_cmd} -user '${_user}'"
  _cmd="${_cmd} -password '${_password}'"
  _cmd="${_cmd} -h ${DERBY_ADDR}"
  _cmd="${_cmd} -p ${DERBY_PORT}"

  _cmd="${_initshellenv}; ${_cmd}"

  echo ""
  echo "---- Derby Information ----"
  echo "user=${_user}"
  echo "DERBY_PORT=${DERBY_PORT}"
  echo ""

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${DERBY_OS_USER}" \
      -s /bin/bash -c "${_cmd}" \
      <"/dev/null"
    _exit_code=$?
  else
    eval "${_cmd}"
    _exit_code=$?
  fi

  echo ""

  case "${_exit_code}" in
    0) echo "Derby is running."    ;;
    *) echo "Derby is not responding. Check the above message." ;;
  esac
}

#-------------------------------------------------------------------------------
# ef_derbystop()
# let's stop Derby DB
#-------------------------------------------------------------------------------
ef_derbystop(){
  if [ "${EF_DERBY_ENABLED}" != 'true' ]; then
    return 0
  fi

  _user=$(get_derby_info user)
  _password=$(get_derby_info password)

  _cmd="${JAVA_HOME}/bin/java"
  _cmd="${_cmd} ${DERBY_JAVA_OPTIONS}"
  _cmd="${_cmd} -jar '${DERBY_DIST_HOME}/lib/derbyrun.jar'"
  _cmd="${_cmd} server"
  _cmd="${_cmd} shutdown"
  _cmd="${_cmd} -user '${_user}'"
  _cmd="${_cmd} -password '${_password}'"
  _cmd="${_cmd} -h ${DERBY_ADDR}"
  _cmd="${_cmd} -p ${DERBY_PORT}"

  _cmd="${_initshellenv}; ${_cmd}"

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${DERBY_OS_USER}" \
      -s /bin/bash -c "${_cmd}" \
      <"/dev/null"
    _exit_code=$?
  else
    eval "${_cmd}"
    _exit_code=$?
  fi

  case "${_exit_code}" in
    0) echo "${efmsg_derbykilled}"    ;;
    *) echo "${efmsg_derbynotkilled}" ;;
  esac
}

#-------------------------------------------------------------------------------
# ef_tomcatstop()
# let's stop EF Portal Server
#-------------------------------------------------------------------------------
ef_tomcatstop(){
  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${TOMCAT_USER}" \
      -s /bin/bash -c "${_initshellenv}; ${TOMCAT_STOP} 30 -force" \
      <"/dev/null"
  else
    eval "${_initshellenv}; ${TOMCAT_STOP} 30 -force"
  fi
}

#-------------------------------------------------------------------------------
# ef_agentstart()
# let's start EF Portal Agent
#-------------------------------------------------------------------------------
ef_agentstart(){
  _agentpid="$1"

  if [ -n "${_agentpid}" ] ; then
    echo "${efmsg_agentisrunning}" >&2
    echo ">>> LockFile: ${EF_AGENTPID}"
    echo ">>> PID: ${_agentpid}"
    exit 1
  fi

  if [ ! "${EF_WHOAMI}" = "root" ] ; then
    echo "${efmsg_agentwarning}"
  fi

  _java="${JAVA_HOME}/bin/java"

  _jar="${EF_ROOT}/agent/agent.jar"

  # -Djava.security.policy, with a double equals, means that just the specified policy file will be used;
  # all others will be ignored.
  _opts="${AGENT_JAVA_OPTIONS} \
         -Dsun.rmi.transport.tcp.readTimeout=30000 \
         -DEF_ROOT=${EF_ROOT} \
         -Dorg.apache.commons.logging.LogFactory=com.enginframe.agent.EnginFrameCommonsLogFactoryImpl \
         -Djava.security.policy==${EF_ROOT}/conf/ef_java.policy"

  _currentpwd="$(pwd)"
  cd "${EF_TEMPDIR}" || exit 1
    # shellcheck disable=SC2086
    "${_java}" ${_opts} -jar "${_jar}" > "${EF_AGENTOUT}" 2>"${EF_AGENTERR}" </dev/null &
    echo "$!" > "${EF_AGENTPID}"
  cd "${_currentpwd}" || exit 1

  sleep 3
  if ps -p "$(cat "${EF_AGENTPID}")" >/dev/null 2>&1 ; then
    echo "${efmsg_agentok}"
  else
    echo "${efmsg_agentnotok}"
    rm -f  "${EF_AGENTPID}"
    exit 1
  fi
}

#-------------------------------------------------------------------------------
# ef_agentstop()
# let's stop EF Portal Agent
#-------------------------------------------------------------------------------
ef_agentstop(){
  _agentpid="$1"
  if [ -z "${_agentpid}" ] ; then
    echo "${efmsg_noagent}"
    exit 1
  fi

  if kill -TERM "${_agentpid}" || kill -KILL "${_agentpid}" ; then
    echo "${efmsg_agentkilled}"
    rm -f "${EF_AGENTPID}"
  else
    echo "${efmsg_agentalive}: PID ${_agentpid}"
    exit 1
  fi
}

#-------------------------------------------------------------------------------
# ef_shellstart()
# let's start EF Portal Remote Shell Server
#-------------------------------------------------------------------------------
ef_shellstart(){
  if [ -f "${EF_SHELLPID}" ] ; then
    _pid="$(cat "${EF_SHELLPID}")"
    if ps -p "${_pid}" >/dev/null 2>/dev/null ; then
      echo "${efmsg_shellserverisrunning}" >&2
      echo ">>> LockFile: ${EF_SHELLPID}"
      echo ">>> PID: ${_pid}"
      return 0
    else
      # The shell isn't running so let's remove the PID file
      rm -f "${EF_SHELLPID}"
    fi
  fi

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${TOMCAT_USER}" \
      -s /bin/bash -c "${EF_SHELL_OPTIONS}; ${EF_SHELL_START}"  >"${EF_SHELLOUT}" 2>"${EF_SHELLERR}" </dev/null
  else
    eval "${EF_SHELL_OPTIONS}; ${EF_SHELL_START}" >"${EF_SHELLOUT}" 2>"${EF_SHELLERR}" </dev/null
  fi

  sleep 3
  if [ -f "${EF_SHELLPID}" ] ; then
    if ps -p "$(cat "${EF_SHELLPID}")" >/dev/null 2>&1 ; then
      echo "${efmsg_shellok}"
      # Let the BASH scripts know Web Shell is working
      rm -fr "$EF_CONF_ROOT/shell/not_working"
    else
      echo "${efmsg_shellnotok}"
      rm -f "${EF_SHELLPID}"
      # Let the BASH scripts know Web Shell is NOT working
      touch "$EF_CONF_ROOT/shell/not_working"
      return 0
    fi
  else
    echo "${efmsg_shellnotok}"
    # Let the BASH scripts know Web Shell is NOT working
    touch "$EF_CONF_ROOT/shell/not_working"
    return 0
  fi
}

#-------------------------------------------------------------------------------
# ef_shellstop()
# let's stop EF Portal Remote Shell Server
#-------------------------------------------------------------------------------
ef_shellstop(){
  if [ ! -f "${EF_SHELLPID}" ] ; then
    echo "${efmsg_noshell}"
    return 0
  fi

  _pid="$(cat "${EF_SHELLPID}")"
  if ! ps -p "${_pid}" >/dev/null 2>/dev/null ; then
    rm -f "${EF_SHELLPID}"
    _pid=""
    echo "${efmsg_noshell}"
    return 0
  fi

  if kill -TERM "${_pid}" || kill -KILL "${_pid}" ; then
    echo "${efmsg_shellkilled}"
    rm -f "${EF_SHELLPID}"
  else
    echo "${efmsg_shellalive}: PID ${_pid}"
    return 0
  fi
}

#-------------------------------------------------------------------------------
# ef_proxystart()
# start EF Portal Web Proxy
#-------------------------------------------------------------------------------
ef_proxystart(){
  if [ -f "${EF_PROXYPID}" ] ; then
    _pid="$(cat "${EF_PROXYPID}")"
    if ps -p "${_pid}" >/dev/null 2>/dev/null ; then
      echo "${efmsg_proxyserverisrunning}" >&2
      echo ">>> LockFile: ${EF_PROXYPID}"
      echo ">>> PID: ${_pid}"
      return 0
    else
      # The proxy isn't running so let's remove the PID file
      rm -f "${EF_PROXYPID}"
    fi
  fi

  if [ "${EF_WHOAMI}" = "root" ] ; then
    su - "${TOMCAT_USER}" \
      -s /bin/bash -c "${EF_PROXY_OPTIONS}; ${EF_PROXY_START}"  >"${EF_PROXYOUT}" 2>"${EF_PROXYERR}" </dev/null
  else
    eval "${EF_PROXY_OPTIONS}; ${EF_PROXY_START}" >"${EF_PROXYOUT}" 2>"${EF_PROXYERR}" </dev/null
  fi

  sleep 3
  if [ -f "${EF_PROXYPID}" ] ; then
    if ps -p "$(cat "${EF_PROXYPID}")" >/dev/null 2>&1 ; then
      echo "${efmsg_proxyok}"
      # Let the BASH scripts know Web Proxy is working
      rm -fr "$EF_CONF_ROOT/proxy/not_working"
    else
      echo "${efmsg_proxynotok}"
      rm -f "${EF_PROXYPID}"
      # Let the BASH scripts know Web Proxy is NOT working
      touch "$EF_CONF_ROOT/proxy/not_working"
      return 0
    fi
  else
    echo "${efmsg_proxynotok}"
    # Let the BASH scripts know Web Proxy is NOT working
    touch "$EF_CONF_ROOT/proxy/not_working"
    return 0
  fi
}

#-------------------------------------------------------------------------------
# ef_proxystop()
# stop EF Portal Web Proxy
#-------------------------------------------------------------------------------
ef_proxystop(){
  if [ ! -f "${EF_PROXYPID}" ] ; then
    echo "${efmsg_noproxy}"
    return 0
  fi

  _pid="$(cat "${EF_PROXYPID}")"
  if ! ps -p "${_pid}" >/dev/null 2>/dev/null ; then
    rm -f "${EF_PROXYPID}"
    _pid=""
    echo "${efmsg_noproxy}"
    return 0
  fi

  if kill -TERM "${_pid}" || kill -KILL "${_pid}" ; then
    echo "${efmsg_proxykilled}"
    rm -f "${EF_PROXYPID}"
  else
    echo "${efmsg_proxyalive}: PID ${_pid}"
    return 0
  fi
}


#-------------------------------------------------------------------------------
# ef_status()
# reports the status of EF Portal Daemons
#-------------------------------------------------------------------------------
ef_status(){

  # HP-UX 11 trick to get ps support -o option
  # shellcheck disable=SC2196
  PSOUTPUT_SUPPORT=$(env | egrep "^UNIX95=" 2>&1)
  if [ -z "$PSOUTPUT_SUPPORT" ]; then
    UNIX95=
    export UNIX95
  fi

  COLUMNS=1000
  export COLUMNS
  ef_derbystatus

  if [ -f "${CATALINA_PID}" ] ; then
    _serverpid="-p $(cat "${CATALINA_PID}")"
  else
    _serverpid=""
  fi
  if [ -f "${EF_AGENTPID}" ] ; then
    _agentpid="-p $(cat "${EF_AGENTPID}")"
  else
    _agentpid=""
  fi
  if [ -f "${EF_SHELLPID}" ] ; then
    _shellpid="-p $(cat "${EF_SHELLPID}")"
  else
    _shellpid=""
  fi
  if [ -f "${EF_PROXYPID}" ] ; then
    _proxypid="-p $(cat "${EF_PROXYPID}")"
  else
    _proxypid=""
  fi

  if [ -n "${_serverpid}${_agentpid}${_shellpid}${_proxypid}" ] ; then
    _nopidrunning=""
    if [ "${_serverpid}" != "" ] ; then
      # shellcheck disable=SC2086
      _server_pid_msg=$(ps -o "user,pid,ppid,pcpu,pmem,stime,time,args" ${_serverpid} 2>/dev/null | sed '1d' | awk '{print $0}')
      if [ -n "${_server_pid_msg}" ] ; then
        echo "${efmsg_serverpidinfo}"
        echo "${_server_pid_msg}"
      else
        _nopidrunning="true"
      fi
      if [ -n "${_server_pid_msg}" ] && [ -f "${CATALINA_OUT}" ] ; then
        echo "${efmsg_serverportinfo}"
        grep 'https\?-' "${CATALINA_OUT}" | sed '$!d'
      fi
    fi

    if [ "${_agentpid}" != "" ] ; then
      # shellcheck disable=SC2086
      _agent_pid_msg=$(ps -o "user,pid,ppid,pcpu,pmem,stime,time,args" ${_agentpid} 2>/dev/null | sed '1d' | awk '{print $0}')
      if [ -n "${_agent_pid_msg}" ] ; then
        echo "${efmsg_agentpidinfo}"
        echo "${_agent_pid_msg}"
      else
        _nopidrunning="true"
      fi
    fi
    if [ "${_nopidrunning}" == "true" ] ; then
      fatal "${efmsg_nodaemonsrunning}" "1"
    fi

    if [ "${_shellpid}" != "" ] ; then
      # shellcheck disable=SC2086
      _shell_pid_msg=$(ps -o "user,pid,ppid,pcpu,pmem,stime,time,args" ${_shellpid} 2>/dev/null | sed '1d' | awk '{print $0}')
      if [ -n "${_shell_pid_msg}" ] ; then
        echo "${efmsg_shellpidinfo}"
        echo "${_shell_pid_msg}"
      else
        _nopidrunning="true"
      fi
    fi

    if [ "${_proxypid}" != "" ] ; then
      # shellcheck disable=SC2086
      _proxy_pid_msg=$(ps -o "user,pid,ppid,pcpu,pmem,stime,time,args" ${_proxypid} 2>/dev/null | sed '1d' | awk '{print $0}')
      if [ -n "${_proxy_pid_msg}" ] ; then
        echo "${efmsg_proxypidinfo}"
        echo "${_proxy_pid_msg}"
      else
        _nopidrunning="true"
      fi
    fi

    if [ "${_nopidrunning}" == "true" ] ; then
      fatal "${efmsg_nodaemonsrunning}" "1"
    fi
  else
    fatal "${efmsg_nodaemonsrunning}"
  fi
}

fatal() {
    echo "$1"
    if [ -n "$2" ]; then
      exit "$2"
    else
      exit 3
    fi
}

check_dir() {
    local _dir="$1"
    local _perm="$2"
    local _owner="$3"
    local _group="$4"

    # This is done to refresh info which may be cached on shared filesystems such as NFS
    ls -la "${_dir}/" > /dev/null 2>/dev/null
    if [ ! -e "${_dir}" ]; then
        mkdir -p "${_dir}" || fatal "Unable to create directory ${_dir}"
        chmod "${_perm}" "${_dir}" || fatal "Unable to set permissions ${_perm} on directory ${_dir}"
        chown "${_owner}" "${_dir}" || fatal "Unable to set owner ${_owner} on directory ${_dir}"
        if [ -n "${_group}" ]; then
          chgrp "${_group}" "${_dir}" || fatal "Unable to set group ${_group} on directory ${_dir}"
        fi
    fi

    local _actual_perm=$(stat --printf='%a' "${_dir}")
    local _actual_owner=$(stat --printf='%U' "${_dir}")
    local _actual_group=$(stat --printf='%G' "${_dir}")

    if [ "${_actual_perm}" != "${_perm}" ]; then
        echo "Wrong permissions on ${_dir}. Expected ${_perm} was ${_actual_perm}!"
        if [ -z "${EF_FIX_PERMISSIONS_AT_LAUNCH}" ] || [ "${EF_FIX_PERMISSIONS_AT_LAUNCH}" = "true" ]; then
            echo "Fixing permissions. (Set EF_FIX_PERMISSIONS_AT_LAUNCH=\"false\" in enginframe.conf to skip.)"
            chmod "${_perm}" "${_dir}" || fatal "Unable to set permissions ${_perm} on directory ${_dir}"
        fi
    fi
    if [ "${_actual_owner}" != "${_owner}" ]; then
        echo "Wrong ownership on ${_dir}. Expected ${_owner} was ${_actual_owner}!"
        if [ -z "${EF_FIX_PERMISSIONS_AT_LAUNCH}" ] || [ "${EF_FIX_PERMISSIONS_AT_LAUNCH}" = "true" ]; then
          echo "Fixing permissions. (Set EF_FIX_PERMISSIONS_AT_LAUNCH=\"false\" in enginframe.conf to skip.)"
          chown "${_owner}" "${_dir}" || fatal "Unable to set owner ${_owner} on directory ${_dir}"
        fi
    fi
    if [ -n "${_group}" ] && [ "${_actual_group}" != "${_group}" ]; then
      echo "Wrong groupship on ${_dir}. Expected ${_group} was ${_actual_group}!"
      if [ -z "${EF_FIX_PERMISSIONS_AT_LAUNCH}" ] || [ "${EF_FIX_PERMISSIONS_AT_LAUNCH}" = "true" ]; then
        echo "Fixing permissions. (Set EF_FIX_PERMISSIONS_AT_LAUNCH=\"false\" in enginframe.conf to skip.)"
        chgrp "${_group}" "${_dir}" || fatal "Unable to set group ${_group} on directory ${_dir}"
      fi
    fi
}

#-------------------------------------------------------------------------------
# ef_init()
# initialize useful stuff
#-------------------------------------------------------------------------------
ef_init(){
  local _role
  local _bin_dir

  # Load utility functions
  _bin_dir=$(dirname "$0")
  . "${_bin_dir}/functions.sh"

  # Welcome message
  printf "\n%s\n" "${efmsg_welcome}"

  # Setting umask
  EF_UMASK=022
  umask ${EF_UMASK}

  # Who am I?
  EF_WHOAMI="$(id | sed -e 's/[^(]*(\([^)]*\)).*/\1/')"

  # The mother of all directories. Example: /opt/nisp/enginframe/2024.0-r1705
  export EF_VERSION_ROOT=$(absolute_path "${_bin_dir}/..")
  export EF_ROOT="${EF_VERSION_ROOT}/enginframe"

  load_env

# Check if EF Portal is installed
  if [ ! -d "${EF_VERSION_ROOT}/enginframe" ] ; then
    echo "${efmsg_wrongdir}"
    echo "${EF_VERSION_ROOT}"
    exit 1
  fi
  echo "Using EF Portal in \"${EF_VERSION_ROOT}\""

    # Decide the role of this EF instance
    EF_AGENT_ENABLED="false"
    EF_SERVER_ENABLED="false"
    EF_DERBY_ENABLED="false"
    EF_SHELL_ENABLED="false"
    EF_PROXY_ENABLED="false"
    ef_enabled_roles=""

    if [ -z "${EF_ROLES}" ]; then
      # Defaults when no custom EF_ROLES is provided (proxy disabled by default)
      ef_enabled_roles="server,agent,shell"
      [ "${DERBY_CONFIGURED}" = "true" ] && ef_enabled_roles="${ef_enabled_roles},derby"
    else
      ef_enabled_roles="${EF_ROLES}"
    fi

    # Append additional roles (e.g., "proxy")
    if [ -n "${EF_ADDITIONAL_ROLES}" ]; then
      if [ -n "${ef_enabled_roles}" ]; then
        ef_enabled_roles="${ef_enabled_roles},${EF_ADDITIONAL_ROLES}"
      else
        ef_enabled_roles="${EF_ADDITIONAL_ROLES}"
      fi
    fi

    # Normalize: remove spaces
    ef_enabled_roles="$(printf '%s\n' "${ef_enabled_roles}" | tr -d '[:space:]')"

    echo "Active roles for this host:"
    OLD_IFS="${IFS}"
    IFS=","
    for _role in ${ef_enabled_roles}; do
      case "${_role}" in
        server) EF_SERVER_ENABLED="true"; echo "  - Server" ;;
        agent)  EF_AGENT_ENABLED="true";  echo "  - Agent" ;;
        derby)  EF_DERBY_ENABLED="true";  echo "  - Derby" ;;
        shell)  EF_SHELL_ENABLED="true";  echo "  - Remote Shell" ;;
        proxy)  EF_PROXY_ENABLED="true";  echo "  - Web Proxy" ;;
      esac
    done
    echo ""
    IFS="${OLD_IFS}"

    if [ "${EF_SERVER_ENABLED}" = "true" ] || [ "${EF_AGENT_ENABLED}" = "true" ]; then
        check_dir "${EF_LOGS_ROOT}" 700 "${TOMCAT_USER}" "${EF_ADMIN_USERGROUP}"
        check_dir "${EF_LOGDIR}" 700 "${TOMCAT_USER}" "${EF_ADMIN_USERGROUP}"
        check_dir "${EF_TEMP_ROOT}" 755 "${TOMCAT_USER}"
        check_dir "${EF_TEMPDIR}" 755 "${TOMCAT_USER}"
        check_dir "${EF_TEMPDIR}/dumps" 755 "${TOMCAT_USER}"
    fi

    if [ "${EF_SERVER_ENABLED}" = "true" ]; then
        check_dir "${CATALINA_TMPDIR}" 755 "${TOMCAT_USER}"
        check_dir "${CATALINA_WORKDIR}" 700 "${TOMCAT_USER}"
        check_dir "${CATALINA_LOGDIR}" 755 "${TOMCAT_USER}"
    fi

    if [ "${EF_DERBY_ENABLED}" = "true" ]; then
        check_dir "${DERBY_LOGDIR}" 755 "${DERBY_OS_USER}"
    fi

    if [ "${EF_SHELL_ENABLED}" = "true" ]; then
        check_dir "${EF_SHELL_HOME}" 755 "${TOMCAT_USER}"
        check_dir "${EF_NODE}" 755 "${TOMCAT_USER}"
    fi

    if [ "${EF_PROXY_ENABLED}" = "true" ]; then
        check_dir "${EF_PROXY_HOME}" 755 "${TOMCAT_USER}"
        check_dir "${EF_NODE}" 755 "${TOMCAT_USER}"
    fi

    # Let's set locale
    if [ -n "${EF_LOCALE}" ] ; then

    # Unfortunately we must set all these variables,
    # because some systems don't accept LC_ALL

    # Character classification and case conversion
    LC_CTYPE="${EF_LOCALE}"
    # Collation order
    LC_COLLATE="${EF_LOCALE}"
    # Date and time formats
    LC_TIME="${EF_LOCALE}"
    # Numeric, non-monetary formatting
    LC_NUMERIC="${EF_LOCALE}"
    # Monetary formatting
    LC_MONETARY="${EF_LOCALE}"
    # Formats of informative and diagnostic messages and interactive responses
    LC_MESSAGES="${EF_LOCALE}"

    # These are the generic variables
    LC_ALL="${EF_LOCALE}"
    LANG="${EF_LOCALE}"

    # This variable is used by some environment
    LANGUAGE="${EF_LOCALE}"

    export LC_CTYPE
    export LC_COLLATE
    export LC_TIME
    export LC_NUMERIC
    export LC_MONETARY
    export LC_MESSAGES
    export LC_ALL
    export LANG
    export LANGUAGE

  fi

# Let's check JAVA
  if [ -z "${JAVA_HOME}" ] ; then
    echo "${efmsg_emptyjava}"
    exit 1
  elif [ ! -f "${JAVA_HOME}/bin/java" ] && [ ! -x "${JAVA_HOME}/bin/java" ] ; then
    echo "${efmsg_missingjava}"
    exit 1
  else
    export JAVA_HOME
  fi

# If we're running EFServer inside the bundled version of tomcat, let's check TOMCAT_USER
  if [ "${EF_SERVER_ENABLED}" = "true" ] ; then
    if [ -z "${TOMCAT_USER}" ] ; then
      echo "${efmsg_emptyuser}"
      exit 1
    # root can NEVER be used to run tomcat
    elif [ "${TOMCAT_USER}" = "root" ] ; then
      echo "${efmsg_rootuser}"
      exit 1
    # If I am root, then check if TOMCAT_USER has its home directory and can execute tomcat
    # Home directory existence is needed since it will be the tomcat working directory
    elif [ "${EF_WHOAMI}" = "root" ] ; then
      _home_dir=$(getent passwd "${TOMCAT_USER}" | cut -d: -f6)
      if [ ! -d "${_home_dir}" ] ; then
        echo "${efmsg_baduserhome}"
        exit 1
      fi
      su - "${TOMCAT_USER}" \
        -s /bin/bash -c "[ -x \"${TOMCAT_START}\" -a -x \"${TOMCAT_STOP}\" ]" \
        <"/dev/null" >"/dev/null" 2>&1
      # shellcheck disable=SC2181
      if [ ! "$?" = "0" ] ; then
        echo "${efmsg_invaliduser}"
        exit 1
      fi
    # If I am not root, then I can run tomcat only as myself
    elif [ ! "${EF_WHOAMI}" = "${TOMCAT_USER}" ] && [ ! "${_ef_check_user}" = "false" ] ; then
      echo "${efmsg_baduser}"
      exit 1
    # If I am not root, then I should be able to execute startup.sh
    elif [ ! -x "${TOMCAT_START}" ] ; then
      echo "${efmsg_badstartup}"
      exit 1
    # If I am not root, then I should be able to execute shutdown.sh
    elif [ ! -x "${TOMCAT_STOP}" ] ; then
      echo "${efmsg_badshutdown}"
      exit 1
    fi
  fi

  if [ -d "${JAVA_HOME}/jre" ]
  then
    _my_jre_home="${JAVA_HOME}/jre"
  else
    _my_jre_home="${JAVA_HOME}"
  fi

# Set the common part of commands
  _initshellenv="JAVA_HOME='${JAVA_HOME}'; \
export JAVA_HOME; \
JRE_HOME='${_my_jre_home}'; \
export JRE_HOME; \
CATALINA_HOME='${CATALINA_HOME}'; \
export CATALINA_HOME; \
CATALINA_BASE='${CATALINA_BASE}'; \
export CATALINA_BASE; \
CATALINA_PID='${CATALINA_PID}'; \
export CATALINA_PID; \
CATALINA_OPTS='${SERVER_JAVA_OPTIONS}'; \
export CATALINA_OPTS; \
LC_CTYPE='${LC_CTYPE}'; \
export LC_CTYPE; \
LC_COLLATE='${LC_COLLATE}'; \
export LC_COLLATE; \
LC_TIME='${LC_TIME}'; \
export LC_TIME; \
LC_NUMERIC='${LC_NUMERIC}'; \
export LC_NUMERIC; \
LC_MONETARY='${LC_MONETARY}'; \
export LC_MONETARY; \
LC_MESSAGES='${LC_MESSAGES}'; \
export LC_MESSAGES; \
LC_ALL='${LC_ALL}'; \
export LC_ALL; \
LANG='${LANG}'; \
export LANG; \
LANGUAGE='${LANGUAGE}'; \
export LANGUAGE; \
EF_ROOT='${EF_ROOT}'; \
export EF_ROOT; \
EF_DYNAMIC_ROOT='${EF_DYNAMIC_ROOT}'; \
export EF_DYNAMIC_ROOT; \
CATALINA_TMPDIR='${CATALINA_TMPDIR}'; \
export CATALINA_TMPDIR; \
LOGGING_CONFIG='${LOGGING_CONFIG}'; \
export LOGGING_CONFIG; \
CATALINA_OUT='${CATALINA_OUT}'; \
export CATALINA_OUT; \
CATALINA_LOGDIR='${CATALINA_LOGDIR}'; \
export CATALINA_LOGDIR; \
CATALINA_WORKDIR='${CATALINA_WORKDIR}'; \
export CATALINA_WORKDIR; \
EF_LOGDIR='${EF_LOGDIR}'; \
export EF_LOGDIR; \
EF_TEMPDIR='${EF_TEMPDIR}'; \
export EF_TEMPDIR; \
EF_REPOSITORYDIR='${EF_REPOSITORYDIR}'; \
export EF_REPOSITORYDIR; \
JPDA_SUSPEND='${JPDA_SUSPEND}'; \
export JPDA_SUSPEND; \
JPDA_ADDRESS='*:8000'; \
export JPDA_ADDRESS; \
UMASK='${EF_UMASK}'; \
export UMASK; \
umask ${EF_UMASK}"

}

#-------------------------------------------------------------------------------
# These are the message strings shown to the user. Modify them as you like
#-------------------------------------------------------------------------------
efmsg_welcome="EF Portal Control Script"

efmsg_usage="
Syntax: enginframe [start [server|agent|derby|shell|proxy] | stop [server|agent|derby|shell|proxy] | status [verbose] | restart [server|agent|derby|shell|proxy] | host-setup [...]]

Usage:

   enginframe start/stop        manages EF Server, EF Agent, EF Shell and Derby (if enabled)
   enginframe start/stop server manages only EF Server
   enginframe start/stop agent  manages only EF Agent
   enginframe start/stop derby  manages only Derby
   enginframe start/stop shell  manages only EF Shell
   enginframe start/stop proxy  manages only EF Web Proxy
   enginframe status            status of EF Server, EF Agent, EF Shell, EF Web Proxy and Derby (if enabled)
   enginframe host-setup        configures the roles for the EF hosts
"
efmsg_wrongdir="
[ERROR] This directory does not contain EF Portal:"
efmsg_emptyjava="
[ERROR] You must specify a valid path for JAVA_HOME inside \$EF_CONF_ROOT/enginframe.conf"
efmsg_missingjava="
[ERROR] java executable is missing inside JAVA_HOME as defined inside \$EF_CONF_ROOT/enginframe.conf"
efmsg_emptyuser="
[ERROR] You must specify a valid username for TOMCAT_USER inside \$EF_CONF_ROOT/enginframe.conf"
efmsg_rootuser="
[ERROR] You cannot run EF Portal Server as user root"
efmsg_baduser="
[ERROR] You cannot run EF Portal Server with the user specified inside \$EF_CONF_ROOT/enginframe.conf"
efmsg_baduserhome="
[ERROR] The user specified inside \$EF_CONF_ROOT/enginframe.conf does not have a home directory and cannot run tomcat safely"
efmsg_invaliduser="
[ERROR] The user specified inside \$EF_CONF_ROOT/enginframe.conf is not able to run tomcat"
efmsg_badstartup="
[ERROR] You are not able to run \$CATALINA_HOME/bin/startup.sh"
efmsg_badshutdown="
[ERROR] You are not able to run \$CATALINA_HOME/bin/shutdown.sh"
efmsg_agentwarning="
[WARNING] EFAgent runs as an unprivileged user and it will not be multi-user"
efmsg_serverok="
[OK] EF Portal Server started"
efmsg_servernotok="
[ERROR] Unable to start EF Portal Server"
efmsg_derbyok="
[OK] Derby Database started"
efmsg_derbynotok="
[ERROR] Unable to start Derby Database. Check port ${DERBY_PORT} is available."
efmsg_derbykilled="
[OK] Derby Database is down"
efmsg_derbynotkilled="
[ERROR] Unable to stop Derby Database"
efmsg_agentok="
[OK] EF Portal Agent started"
efmsg_agentnotok="
[ERROR] EF Portal Agent is not able to start"
efmsg_shellserverisrunning="
[WARN] Unable to start EF Portal Remote Shell Server because there is a lock file
which contains a PID corresponding to a running process.
If you are sure that EF Portal Remote Shell Server is not running,
you can manually erase the lock file and resubmit this script."
efmsg_shellok="
[OK] EF Portal Remote Shell Server started"
efmsg_shellnotok="
[WARN] Unable to start EF Portal Remote Shell Server
please check \$EF_LOGS_ROOT/logs/$(hostname)/ef.shell.stderr log file."
efmsg_noshell="
[WARN] EF Portal Remote Shell Server is down"
efmsg_shellkilled="
[OK] EF Portal Remote Shell Server is down"
efmsg_shellalive="
[WARN] Unable to stop EF Portal Remote Shell Server"
efmsg_shellnotenabled="
[INFO] EF Portal Remote Shell Server is not enabled. To activate it, configure the EF_ROLES variable in the enginframe.conf file."
efmsg_proxyserverisrunning="
[WARN] Unable to start EF Portal Web Proxy Server because there is a lock file
which contains a PID corresponding to a running process.
If you are sure that EF Portal Web Proxy Server is not running,
you can manually erase the lock file and resubmit this script."
efmsg_proxyok="
[OK] EF Portal Web Proxy Server started"
efmsg_proxynotok="
[WARN] Unable to start EF Portal Web Proxy Server,
please check \$EF_LOGS_ROOT/logs/$(hostname)/ef.proxy.stderr log file."
efmsg_noproxy="
[WARN] EF Portal Web Proxy Server is down"
efmsg_proxykilled="
[OK] EF Portal Web Proxy Server is down"
efmsg_proxyalive="
[WARN] Unable to stop EF Portal Web Proxy Server"
efmsg_proxynotenabled="
[INFO] EF Portal Web Proxy Server is not enabled. To activate it, configure the EF_ADDITIONAL_ROLES variable in the enginframe.conf file."
efmsg_serverisrunning="
[WARN] Unable to start EFServer because there is a lock file
which contains a PID corresponding to a running process.
If you are sure that EFServer is not running,
you can manually erase the lock file and resubmit this script."
efmsg_agentisrunning="
[WARN] Unable to start EFAgent because there is a lock file
which contains a PID corresponding to a running process.
It you are sure that EF Agent is not running,
you can manually erase the lock file and resubmit this script."
efmsg_noagent="
[WARN] EF Portal Agent is down"
efmsg_agentkilled="
[OK] EF Portal Agent is down"
efmsg_agentalive="
[ERROR] Unable to stop EF Portal Agent"
efmsg_shellpidinfo="
---- Node Shell PID Information ----"
efmsg_proxypidinfo="
---- Node Proxy PID Information ----"
efmsg_agentpidinfo="
---- Agent PID Information ----"
efmsg_serverpidinfo="
---- Server PID Information ----"
efmsg_serverportinfo="
---- Server Port Information ----"
efmsg_nodaemonsrunning="
---- EF Portal daemons are down ----"

#-------------------------------------------------------------------------------
# The very first command executed: it calls ef_main() passing all parameters
#-------------------------------------------------------------------------------
ef_main "$@"


# ex: ts=2 sw=2 et syntax=sh :
