#!/bin/ksh
#
#H# busybox_httpd.sh
#H#
#H# Function: start or stop the busybox apache daemon (httpd)
#H# 
#H# Usage:    busybox_httpd.sh [-v|--verbose] [-q|--quiet] [-f|--force] [-p|--port httpd_port] [-h|--home homedir] [-c|--config configfile] 
#H#                            [start [httpd_options]|stop|restart [httpd_options]|status|daemon_help]
#H#
#H# Parameter
#H#   -v - verbose mode
#H#   -q - quiet mode
#H#   -f - force execution
#H#   -p - port for httpd (default: 8080)
#H#   -h - home dir , default: ${JWM_DIR}/htdocs or <script_dir>/../htdocs
#H#   -c - config file, default: ${JWM_DIR}/etc or <script_dir>/../etc/httpd.conf
#H#   -C - config file like -c but do NOT change the config file at all
#H#
#H#   httpd_options - additional options for starting the httpd
#H#   daemon_help - list the usage help for the busybox httpd daemon
#H#
#H# Author:
#H#   Bernd Schemmer (Bernd.Schemmer@gmx.de)
#H#
#
# History:  
#   25.10.2016 v1.0.0 /bs
#     initial release
#

# for debugging
#
#PREFIX="echo "
PREFIX=""

# define constants
#
__TRUE=0
__FALSE=1

# variables for the trap handler
#
INSIDE_DIE=${__FALSE}

# script name and directory
#
typeset -r SCRIPTNAME="${0##*/}"
typeset SCRIPTDIR="${0%/*}"
if [ "${SCRIPTNAME}"x = "${SCRIPTDIR}"x ] ; then
  SCRIPTDIR="$( whence ${SCRIPTNAME} )"
  SCRIPTDIR="${SCRIPTDIR%/*}"
fi  
REAL_SCRIPTDIR="$( cd -P ${SCRIPTDIR} ; pwd )"

LOGFILE="${LOGFILE:=/var/tmp/${SCRIPTNAME}.log}"

# define variables
#
FORCE=${FORCE:=${__FALSE}}
QUIET=${QUIET:=${__FALSE}}
VERBOSE=${VERBOSE:=${__FALSE}}

# default for the port used by httpd
#
HTTPD_PORT="8080"

# additional options for the httpd
#
HTTPD_OPTIONS=""

HTTPD_HOME_DIR=""
HTTPD_CONFIG_FILE=""

CHANGE_CONFIG_FILE=${__TRUE}

# ----------------------------------------------------------------------
# general functions
#
function LogMsg {
  [[ ${QUIET} = ${__TRUE} ]] && return

  typeset THISMSG="$*"
  
  if [ "$1"x = "-"x ] ; then
    shift
    THISMSG="$*"
  else
    THISMSG="[$( date +"%d.%m.%Y %H:%M" ) ${THISSCRIPT}] $*"
  fi
  
  echo "${THISMSG}"  
  [ "${LOGFILE}"x != ""x ] && echo "${THISMSG}" >>"${LOGFILE}"
}

# ----------------------------------------------------------------------
#
function LogInfo {
  [ ${VERBOSE} = ${__TRUE} ] && LogMsg "INFO: $*"
}

# ----------------------------------------------------------------------
#
function LogError {
  LogMsg "ERROR: $*"
}

# ----------------------------------------------------------------------
#
function LogWarning {
  LogMsg "WARNING: $*"
}

# ----------------------------------------------------------------------
#
function cleanup {

#  LogMsg "-"
#  LogMsg "-"
  
  return 0
}

# ----------------------------------------------------------------------
# general exit routine
#      
function die {
  typeset THISRC=$1

  INSIDE_DIE=${__TRUE}

  trap "" EXIT

  cleanup

  if [ $# -ne 0 ] ; then
    shift
    if [ $# -ne 0 ] ; then
      if [ ${THISRC} = 0 ] ; then
        LogMsg "$*"
      else
        LogError "$*! RC=${THISRC}"
      fi
    fi      
  fi
  LogMsg "### ${SCRIPTNAME} ended at $( date )"
  exit ${THISRC}
}

# ----------------------------------------------------------------------
#
function signal_handler {
  trap "" exit
  
  if [ ${INSIDE_DIE} = ${__FALSE} ] ; then
    die 100 "Script aborted for unknown reason"
  fi  
}

  	
# ----------------------------------------------------------------------

function search_php_binary {

  typeset CGI_BINARIES="php-cgi php5-cgi php4-cgi"

  LogMsg "Preparing the environment to start the busybox httpd with php support ..."

  LogMsg "Searching for the php-cgi binary ..."

  PHP_BINARY=""
  for CUR_PHP_BINARY in ${CGI_BINARIES} ; do
    PHP_BINARY=$( which ${CUR_PHP_BINARY} )
    if [ $? -eq 0 ] ; then
      break
    else
      PHP_BINARY=""
    fi
  done

  if [ "${PHP_BINARY}"x = ""x ] ; then
    LogWarning "No PHP binary (${CGI_BINARIES}) found."
  else
    LogMsg "Using the PHP binary \"${PHP_BINARY}\" ..."
  fi    
}

# ----------------------------------------------------------------------

function show_httpd_daemon_status {
  LogMsg "The httpd daemon is${1} running; the PID is ${HTTPD_PID}"
  LogMsg "-"
  LogMsg "-" "$( ps -f -p${HTTPD_PID} )"
  LogMsg "-"
  if [ "${HTTPD_PID_USER}"x != "${CUR_USER_NAME}"x ] ; then
    LogWarning "The HTTPD daemon was started from this user: ${HTTPD_PID_USER} (you're ${CUR_USER_NAME})"
  fi    

  if [ "${HTTPD_PID_USER}"x = "${CUR_USER_NAME}"x -o "${CUR_USER_NAME}"x = "root"x ] ; then
    LogMsg "The HTTPD daemon is listening on these ports:"
    LogMsg "-" 
    LogMsg "-" "$( netstat -tlpn  | grep " ${HTTPD_PID}/" )"
    LogMsg "-"
  else
    LogWarning "Can not detect the port used by the HTTPD daemon"
  fi
}

# ----------------------------------------------------------------------
#
LogMsg "### ${SCRIPTNAME} started at $( date )"

# install the trap handler
#
trap "signal_handler" EXIT

# get the parameter
#
PARAMETER_OKAY=${__TRUE}
ACTION=""

while [ $# -ne 0 ] ; do
  case $1 in

    --help | -H | help |  "" )
       grep "^#H#" $0 | cut -c4-
       die 0
       ;;

    -v | --verbose )
       VERBOSE=${__TRUE}
       ;;

    +v | ++verbose )
       VERBOSE=${__FALSE}
       ;;

    -q | --quiet )
       QUIET=${__TRUE}
       ;;

    +q | ++quiet )
       QUIET=${__FALSE}
       ;;

    -f | --force )
       FORCE=${__TRUE}
       ;;

    +f | ++force )
       FORCE=${__FALSE}
       ;;

    -d | --debug )
       PREFIX="echo "
       ;;

    +d | ++debug )
       PREFIX=""
       ;;

    -p | --port )
       if [ $# -ge 2 ] ; then
         HTTPD_PORT="$2"
         shift
       else
         die 7 "Incomplete parameter -p found"
       fi
       ;;

    -h | --homedir )
       if [ $# -ge 2 ] ; then
         HTTPD_HOME_DIR="$2"
         shift
       else
         die 7 "Incomplete parameter -h found (use --help for the usage help)"
       fi
       ;;

    -c | --config | -C | --CONFIG )
       if [ $# -ge 2 ] ; then
         [ "$1" = "-C" -o "$1" = "--CONFIG" ] && CHANGE_CONFIG_FILE=${__FALSE}
         HTTPD_CONFIG_FILE="$2"
         shift
       else
         die 7 "Incomplete parameter -c found"
       fi
       ;;

        
    start )
       [ "${ACTION}"x != ""x ] && die 11 "Duplicate action parameter found"
       ACTION="start"
       shift 
       HTTPD_OPTIONS="$*"
       break
       ;;

    stop )
       [ "${ACTION}"x != ""x ] && die 11 "Duplicate action parameter found"
       ACTION="stop"
       shift 
       [ $# -ne 0 ] && die 8 "Invalid parameter found: $*"
       break
       ;;

    status )
       [ "${ACTION}"x != ""x ] && die 11 "Duplicate action parameter found"
       ACTION="status"
       shift 
       [ $# -ne 0 ] && die 8 "Invalid parameter found: $*"
       break
       ;;

    restart )
       [ "${ACTION}"x != ""x ] && die 11 "Duplicate action parameter found"
       ACTION="restart"
       shift 
       HTTPD_OPTIONS="$*"
       break
       ;;
 
    daemon_help   )
       [ "${ACTION}"x != ""x ] && die 11 "Duplicate action parameter found"
       ACTION="daemon_help"
       shift 
       [ $# -ne 0 ] && die 8 "Invalid parameter found: $*"
       break
       ;;
       
    * ) 
       LogError "Unknown parameter found: $1"
       PARAMETER_OKAY=${__TRUE}
       ;;
     
  esac
  shift
done
[ "${ACTION}"x = ""x ] && ACTION="status"

if [ ${PARAMETER_OKAY} != ${__TRUE} ] ; then
  grep "^#H#" $0 | cut -c4-
  die 2
fi

# ----------------------------------------------------------------------

THISRC=${__FALSE}

CUR_USER_ID="$( id -u )"
CUR_USER_NAME="$( id -un )"
CUR_GROUP_ID="$( id -g )"
CUR_GROUP_NAME="$( id -gn )"

if [ ${HTTPD_PORT} -le 1024 ] ; then
  [ "${CUR_USER_ID}"x != "0"x ] && die 101 "This script must be executed by root only if using a port less then 1024"
fi

HTTPD_PID_FILE="/tmp/httpd.${HTTPD_PORT}.pid"

if [ "${JWM_DIR}"x != ""x ] ; then
  LogMsg "Using the busybox directory based on the the environment variable JWM_DIR (\"${JWM_DIR}\") "
  HTTPD_BASE_DIR="${JWM_DIR}"
else
  HTTPD_BASE_DIR="$( cd $( dirname $0 )/.. 2>/dev/null && pwd  || echo ${PWD} )"
  LogMsg "Environment variable JWM_DIR not set - using the directory based on the script directory ($( dirname $0 )) "
fi

LogMsg "The busybox base directory is ${HTTPD_BASE_DIR}"

[ ! -d "${HTTPD_BASE_DIR}" ] && die 9 "The directory \"${HTTPD_BASE_DIR}\" does not exist"
cd "${HTTPD_BASE_DIR}" || die 10 "Can not change to the directory \"${HTTPD_BASE_DIR}\" "

if [ -x "./busybox/httpd" ] ; then
  HTTPD_BINARY="./busybox/httpd"
  HTTPD_FUNCTION=""
elif  [ -x "./busybox/busybox" ] ; then
  HTTPD_BINARY="./busybox/busybox"
  HTTPD_FUNCTION="httpd"
else  
  die 11 "The busybox binary (either httpd or busybox) does not exist or is not executable"
fi

LogInfo "The busybox httpd binary to use is \"${HTTPD_BINARY} ${HTTPD_FUNCTION}\" "

if [ "${HTTPD_HOME_DIR}"x = ""x ] ; then 
  HTTPD_HOME_DIR="${PWD}/htdocs"
fi

if [ "${HTTPD_CONFIG_FILE}"x  = ""x  -o  "${HTTPD_CONFIG_FILE}"x  = "default"x ] ; then
  HTTPD_CONFIG_FILE="${PWD}/etc/httpd.conf"
fi

if [ -r "${HTTPD_PID_FILE}" ] ; then
  HTTPD_PID="$( cat  "${HTTPD_PID_FILE}" )"
  [ "${HTTPD_PID}"x != ""x ] && ps -p "${HTTPD_PID}" 2>/dev/null 1>/dev/null || HTTPD_PID=""
fi

if [ "${HTTPD_PID}"x = ""x ] ; then
  HTTPD_PID="$( ps -ef | grep -v grep | grep "${HTTPD_BINARY} ${HTTPD_FUNCTION}" | head -1 |awk '{ print $2 };' )"
fi

if [ "${HTTPD_PID}"x != ""x ] ; then
  HTTPD_PID_USER="$( ps -p "${HTTPD_PID}" -o user= )"
else
  HTTPD_PID_USER=""
fi

case ${ACTION} in
   
  start )
    if [ "${HTTPD_PID}"x != ""x ] ; then
      show_httpd_daemon_status " already"
      THISRC=${__FALSE}
    else  
      LogMsg "Starting the httpd daemon ..."
      LogMsg "Using the httpd home directory ${HTTPD_HOME_DIR}"
      LogMsg "Using the httpd config file ${HTTPD_CONFIG_FILE}"
      LogMsg "The port to use for the httpd daemon is ${HTTPD_PORT}"
      if [ "${HTTPD_OPTIONS}"x != ""x ] ; then
        LogMsg "The additional options to use for the httpd daemon are \"${HTTPD_OPTIONS}\" "
        if [[ ${HTTPD_OPTIONS} == *-f* ]] ; then
          die 50 "You can not use this script to start the httpd daemon in the foreground"
        fi
      fi    

      [ ! -d "${HTTPD_HOME_DIR}" ] && die 51 "The directroy ${HTTPD_HOME_DIR} does not exist"
      [ ! -r "${HTTPD_CONFIG_FILE}" ] && die 52 "Can not read the file ${HTTPD_CONFIG_FILE}"

	  CUR_CONFIG_FILE="${HTTPD_CONFIG_FILE}"
      if [ ${CHANGE_CONFIG_FILE} = ${__TRUE} ] ; then
        search_php_binary
        if [ "${PHP_BINARY}"x != ""x ] ; then
          CUR_CONFIG_FILE="/tmp/httpd.${HTTPD_PORT}.conf"
          sed "s#/usr/bin/php-cgi#${PHP_BINARY}#g" "${HTTPD_CONFIG_FILE}" >"${CUR_CONFIG_FILE}"
        fi
      fi

      CUR_OUTPUT="$( set -x  ; "${HTTPD_BINARY}" "${HTTPD_FUNCTION}" -p "${HTTPD_PORT}" -c "${CUR_CONFIG_FILE}" -h "${HTTPD_HOME_DIR}" ${HTTPD_OPTIONS} 2>&1 )"
      THISRC=$?
      HTTPD_PID="$( ps -ef | grep -v grep | grep "${HTTPD_BINARY} ${HTTPD_FUNCTION}" | head -1 |awk '{ print $2 };' )"
      echo "${HTTPD_PID}" >"${HTTPD_PID_FILE}"
      LogMsg "-" "${CUR_OUTPUT}"
      if [ ${THISRC} -ne 0 ] ; then
        LogMsg "Failed to start the httpd daemon -- please check the messages for the cause of the error"
        THISRC=${__FALSE}
      else
        LogMsg "httpd daemon started; the PID is $( cat "${HTTPD_PID_FILE}" )"
        LogMsg "Use http://localhost:${HTTPD_PORT} or http://${HOSTNAME}:${HTTPD_PORT} to access the httpd in your Webbrowser"
        THISRC=${__TRUE}
      fi
    fi  
    ;;

  stop )
    if [ "${HTTPD_PID}"x = ""x ] ; then
      LogMsg "The httpd daemon is NOT running (well, it may be running but it was not started by this script)"
     THISRC=${__FALSE}
    else
      THISRC=${__TRUE}
      LogMsg "The httpd daemon is running; the PID is ${HTTPD_PID}"

      if [ "${HTTPD_PID_USER}"x != "${CUR_USER_NAME}"x ] ; then
        if [ "${CUR_USER_NAME}"x != "root"x ] ; then
          die 55 "The httpd daemon was started from this user: ${HTTPD_PID_USER} but you're ${CUR_USER_NAME} -- can not stop the httpd daemon"
        else
          LogWarning "The httpd daemon was started from this user: ${HTTPD_PID_USER} (you're ${CUR_USER_NAME}) ,,,"
        fi
      fi
              
      LogMsg "Stopping the httpd daemon ..."
      kill "${HTTPD_PID}"
      sleep 1
      ps -p "${HTTPD_PID}" 2>/dev/null 1>/dev/null
      if [ $? -eq 0 ] ; then
        LogMsg "The httpd daemon is still running -- now using \"kill -9  ${HTTPD_PID} \" ..."
        kill -9 "${HTTPD_PID}"
        ps -p "${HTTPD_PID}" 2>/dev/null 1>/dev/null
        if [ $? -eq 0 ] ; then
          LogMsg "The httpd daemon is still running -- please kill the process ${HTTPD_PID} manually"
          THISRC=${__FALSE}        
        fi
      fi
      if [ ${THISRC} -eq ${__TRUE} ] ; then
        [ -r "${HTTPD_PID_FILE}" ] && rm -f  "${HTTPD_PID_FILE}" 2>/dev/null      
      fi  
    fi        
    ;;

  restart )
    "${REAL_SCRIPTDIR}/${SCRIPTNAME}" stop && "${REAL_SCRIPTDIR}/${SCRIPTNAME}" start ${HTTPD_OPTIONS}
    THISRC=$?
    ;;

  status )  
    if [ "${HTTPD_PID}"x != ""x ] ; then
      show_httpd_daemon_status
      THISRC=${__TRUE}
    else
      LogMsg "The httpd daemon is NOT running (well, it may be running but it was not started by this script)"
      THISRC=${__FALSE}
    fi
    ;;

  daemon_help )
    LogMsg "Additional parameter supported by the busybox httpd daemon are:"    
    LogMsg "-" "$( "${HTTPD_BINARY}" "${HTTPD_FUNCTION}" --help )"
    ;;
    
  esac
  
# ----------------------------------------------------------------------
#

# ----------------------------------------------------------------------
#

die ${THISRC}

# ----------------------------------------------------------------------
#
