#!/bin/bash
### BEGIN INIT INFO
# Provides:           apache2
# Required-Start:     $local_fs $remote_fs $network $syslog $named
# Required-Stop:      $local_fs $remote_fs $network $syslog $named
# Default-Start:      2 3 4 5
# Default-Stop:       0 1 6
# X-Interactive:      true
# Short-Description:  Apache2 web server
# Description:        Start the web server
# This script will start the apache2 web server.
### END INIT INFO

DESC="Apache httpd web server"
NAME=apache2
DAEMON=/usr/sbin/${NAME}

SCRIPTNAME="${0##*/}"
SCRIPTNAME="${SCRIPTNAME##[KS][0-9][0-9]}"
if [[ -n "${APACHE_CONFDIR}" ]]; then
  if [[ "${APACHE_CONFDIR##/etc/apache2-}" != "${APACHE_CONFDIR}" ]]; then
    DIR_SUFFIX="${APACHE_CONFDIR##/etc/apache2-}"
  else
    DIR_SUFFIX=
  fi
elif [[ "${SCRIPTNAME##apache2-}" != "${SCRIPTNAME}" ]]; then
  DIR_SUFFIX="-${SCRIPTNAME##apache2-}"
  APACHE_CONFDIR=/etc/apache2${DIR_SUFFIX}
else
  DIR_SUFFIX=
  APACHE_CONFDIR=/etc/apache2
fi
if [[ -z "${APACHE_ENVVARS}" ]]; then
  APACHE_ENVVARS=${APACHE_CONFDIR}/envvars
fi
export APACHE_CONFDIR APACHE_ENVVARS

ENV="env -i LANG=C PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
if [[ "${APACHE_CONFDIR}" != /etc/apache2 ]]; then
  ENV="${ENV} APACHE_CONFDIR=${APACHE_CONFDIR}"
fi
if [[ "${APACHE_ENVVARS}" != "${APACHE_CONFDIR}/envvars" ]]; then
  ENV="${ENV} APACHE_ENVVARS=${APACHE_ENVVARS}"
fi

PIDFILE=$( . ${APACHE_ENVVARS} && echo "${APACHE_PID_FILE}" )

VERBOSE=no
if [[ -f /etc/default/rcS ]]; then
  # shellcheck source=/dev/null
  . /etc/default/rcS
fi
# shellcheck source=/dev/null
. /lib/lsb/init-functions


# Now, set defaults:
APACHE2CTL="${ENV} apache2ctl"
PIDFILE=$( . ${APACHE_ENVVARS} && echo "${APACHE_PID_FILE}" )
APACHE2_INIT_MESSAGE=""

CONFTEST_OUTFILE=
cleanup() {
  if [[ -n "${CONFTEST_OUTFILE}" ]]; then
    rm -f "${CONFTEST_OUTFILE}"
  fi
}
trap cleanup 0  # "0" means "EXIT", but "EXIT" is not portable.


apache_conftest() {
  [[ -z "${CONFTEST_OUTFILE}" ]] || rm -f "${CONFTEST_OUTFILE}"
  CONFTEST_OUTFILE=$( mktemp )
  if ! ${APACHE2CTL} configtest > "${CONFTEST_OUTFILE}" 2>&1; then
    return 1
  else
    rm -f "${CONFTEST_OUTFILE}"
    CONFTEST_OUTFILE=
    return 0
  fi
}

clear_error_msg() {
  [[ -z "${CONFTEST_OUTFILE}" ]] || rm -f "${CONFTEST_OUTFILE}"
  CONFTEST_OUTFILE=
  APACHE2_INIT_MESSAGE=
}

print_error_msg() {
  [[ -z "${APACHE2_INIT_MESSAGE}" ]] || log_warning_msg "${APACHE2_INIT_MESSAGE}"
  if [[ -n "${CONFTEST_OUTFILE}" ]]; then
    echo "Output of config test was:" >&2
    cat "${CONFTEST_OUTFILE}" >&2
    rm -f "${CONFTEST_OUTFILE}"
    CONFTEST_OUTFILE=
  fi
}

apache_wait_start() {
  local STATUS=${1}
  local i=0

  if [[ ${STATUS} != 0 ]]; then
    return "${STATUS}"
  fi
  while : ; do
    PIDTMP=$( pidofproc -p "${PIDFILE}" "${DAEMON}" )
    if [[ -n "${PIDTMP:-}" ]] && kill -0 "${PIDTMP:-}" 2> /dev/null; then
      return "${STATUS}"
    fi

    if [[ ${i} == "20" ]]; then
      APACHE2_INIT_MESSAGE="The apache2${DIR_SUFFIX} instance did not start within 20 seconds. Please read the log files to discover problems"
      return 2
    fi

    [[ "${VERBOSE}" != no ]] && log_progress_msg "."
    sleep 1
    i=$(( i + 1 ))
  done
}

apache_wait_stop() {
  local STATUS=${1}
  local METH=${2}

  if [[ ${STATUS} != 0 ]]; then
    return "${STATUS}"
  fi

  PIDTMP=$( pidofproc -p "${PIDFILE}" "${DAEMON}" )
  if [[ -n "${PIDTMP:-}" ]] && kill -0 "${PIDTMP:-}" 2> /dev/null; then
    if [[ "${METH}" == "kill" ]]; then
      killproc -p "${PIDFILE}" "${DAEMON}"
    else
      ${APACHE2CTL} "${METH}" > /dev/null 2>&1
    fi

    local i=0
    while kill -0 "${PIDTMP:-}" 2> /dev/null; do
      if [[ ${i} == '60' ]]; then
        STATUS=2
        break
      fi
      [[ "${VERBOSE}" != no ]] && log_progress_msg "."
      sleep 1
      i=$(( i + 1 ))
    done
    return ${STATUS}
  else
    return ${STATUS}
  fi
}


#
# Function that starts the daemon/service.
#
do_start() {
  # Return:
  #   0 if daemon has been started.
  #   1 if daemon was already running.
  #   2 if daemon could not be started.

  if pidofproc -p "${PIDFILE}" "${DAEMON}" > /dev/null 2>&1; then
    return 1
  fi

  if apache_conftest; then
    ${APACHE2CTL} start
    apache_wait_start $?
    return $?
  else
    APACHE2_INIT_MESSAGE="The apache2${DIR_SUFFIX} configtest failed."
    return 2
  fi
}

#
# Function that stops the daemon/service.
#
do_stop() {
  # Return:
  #   0 if daemon has been stopped.
  #   1 if daemon was already stopped.
  #   2 if daemon could not be stopped.
  #   other if a failure occurred.

  # Either "stop" or "graceful-stop".
  local STOP=${1}
  # Can't use pidofproc from LSB here.
  local AP_RET=0

  if pidof ${DAEMON} > /dev/null 2>&1; then
    if [[ -e ${PIDFILE} ]] && pidof ${DAEMON} | tr ' ' '\n' | grep -w "$( cat "${PIDFILE}" )" > /dev/null 2>&1; then
      AP_RET=2
    else
      AP_RET=1
    fi
  else
    AP_RET=0
  fi

  # AP_RET is:
  #   0 if Apache (whichever) is not running.
  #   1 if Apache (whichever) is running.
  #   2 if Apache from the PIDFILE is running.

  if [[ ${AP_RET} == 0 ]]; then
    return 1
  fi

  if [[ ${AP_RET} == 2 ]] && apache_conftest; then
    apache_wait_stop $? "${STOP}"
    return $?
  else
    if [[ ${AP_RET} == 2 ]]; then
      clear_error_msg
      APACHE2_INIT_MESSAGE="The apache2${DIR_SUFFIX} configtest failed, so we are trying to kill it manually. This is almost certainly suboptimal, so please make sure your system is working as you'd expect now!"
      apache_wait_stop $? "kill"
      return $?
    elif [[ ${AP_RET} == 1 ]]; then
      APACHE2_INIT_MESSAGE="There are processes named 'apache2' running which do not match your pid file which are left untouched in the name of safety, Please review the situation by hand".
      return 2
    fi
  fi
}


#
# Function that sends a SIGHUP to the daemon/service.
#
do_reload() {
  if apache_conftest; then
    if ! pidofproc -p "${PIDFILE}" "${DAEMON}" > /dev/null 2>&1; then
      APACHE2_INIT_MESSAGE="Apache2 is not running"
      return 2
    fi
    ${APACHE2CTL} graceful > /dev/null 2>&1
    return $?
  else
    APACHE2_INIT_MESSAGE="The apache2${DIR_SUFFIX} configtest failed. Not doing anything."
    return 2
  fi
}


# Sanity checks. They need to occur after function declarations.
[[ -x ${DAEMON} ]] || exit 0

if [[ ! -x ${DAEMON} ]]; then
  echo "No apache-bin package installed"
  exit 0
fi

if [[ -z "${PIDFILE}" ]]; then
  echo "ERROR: APACHE_PID_FILE needs to be defined in ${APACHE_ENVVARS}" >&2
  exit 2
fi


case "${1}" in
  start)
    log_daemon_msg "Starting ${DESC}" "${NAME}"
    do_start
    RET_STATUS=$?
    case "${RET_STATUS}" in
      0|1)
        log_success_msg
        [[ "${VERBOSE}" != no ]] && [[ ${RET_STATUS} == 1 ]] && log_warning_msg "Server was already running"
        ;;
      2)
        log_failure_msg
        print_error_msg
        exit 1
        ;;
    esac
    ;;
  stop|graceful-stop)
    log_daemon_msg "Stopping ${DESC}" "${NAME}"
    do_stop "${1}"
    RET_STATUS=$?
    case "${RET_STATUS}" in
      0|1)
        log_success_msg
        [[ "${VERBOSE}" != no ]] && [[ ${RET_STATUS} == 1 ]] && log_warning_msg "Server was not running"
        ;;
      2)
        log_failure_msg
        print_error_msg
        exit 1
        ;;
    esac
    print_error_msg
    ;;
  status)
    status_of_proc -p "${PIDFILE}" "apache2" "${NAME}"
    exit $?
    ;;
  reload|force-reload|graceful)
    log_daemon_msg "Reloading ${DESC}" "${NAME}"
    do_reload
    RET_STATUS=$?
    case "${RET_STATUS}" in
      0|1)
        log_success_msg
        [[ "${VERBOSE}" != no ]] && [[ ${RET_STATUS} == 1 ]] && log_warning_msg "Server was already running"
        ;;
      2)
        log_failure_msg
        print_error_msg
        exit 1
        ;;
    esac
    print_error_msg
    ;;
  restart)
    log_daemon_msg "Restarting ${DESC}" "${NAME}"
    do_stop stop
    case "$?" in
      0|1)
        do_start
        case "$?" in
          0)
            log_end_msg 0
            ;;
          1|*)
            log_end_msg 1 # Old process is still or failed to running.
            print_error_msg
            exit 1
            ;;
        esac
        ;;
      *)
        # Failed to stop.
        log_end_msg 1
        print_error_msg
        exit 1
        ;;
    esac
    ;;
  start-htcacheclean|stop-htcacheclean)
    echo "Use 'service apache-htcacheclean' instead"
    ;;
  *)
    echo "Usage: ${SCRIPTNAME} {start|stop|graceful-stop|restart|reload|force-reload}" >&2
    exit 3
    ;;
esac

exit 0

# vim: syntax=sh ts=2 sw=2 sts=2 sr noet
