#!/bin/bash
### BEGIN INIT INFO
# Provides:          cox-mediaserver
# Required-Start:    networking
# Required-Stop:
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Cox Communications Cox Business Security Solutions Media Server
### END INIT INFO

CUSTOMIZATION="cox"

SECONDS_TO_WAIT_BEFORE_KILL_9=120

SERVICE_NAME="mediaserver"
INSTALL_DIR="/opt/$CUSTOMIZATION"
MEDIASERVER_DIR="$INSTALL_DIR/mediaserver"
LITE_CLIENT_DIR="$INSTALL_DIR/lite_client"
LIBS_DIR="$INSTALL_DIR/lib"
BIN_NAME="mediaserver"
BIN_FILE="$MEDIASERVER_DIR/bin/$BIN_NAME"
LOGS_DIR="$MEDIASERVER_DIR/var/log"

# Touch .flag file to capture all mediaserver output to a file.
MEDIASERVER_OUT_FLAG="$LOGS_DIR/mediaserver-out.flag"
MEDIASERVER_OUT_LOG="$LOGS_DIR/mediaserver-out.log"

# Touch .flag file to capture all output of this script to a file.
OUT_FLAG="$LOGS_DIR/$(basename "$0")-out.flag"
OUT_LOG="$LOGS_DIR/$(basename "$0")-out.log"

VERSION_FILE="$INSTALL_DIR/version.txt"

export VMS_PLUGIN_DIR="$MEDIASERVER_DIR/plugins"
export SASL_PATH="$LIBS_DIR/sasl2"

RUN_ARGS="-e"

source "$INSTALL_DIR/build_info.txt"
FULL_VERSION="$version-$changeSet-$customization"
[ ! -z "$beta" ] && FULL_VERSION+="-beta"

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

# Redirect all output of this script to the log file.
redirectOutput() # log_file
{
    LOG_FILE="$1"

    # If the old log file exists, rename it to first available "filename_#.log", stopping at 9.
    OLD_LOG_FILE_MESSAGE=""
    if [ -f "$LOG_FILE" ]; then
        for i in $(seq 1 9); do
            OLD_LOG_FILE="${LOG_FILE%.*}_$i.log" #< Remove the extension and add the new suffix.
            if [ ! -f "$OLD_LOG_FILE" ]; then # Unused filename found.
                break
            fi
        done
        mv "$LOG_FILE" "$OLD_LOG_FILE"
        OLD_LOG_FILE_MESSAGE=" (old log file renamed to $(basename "$OLD_LOG_FILE"))"
    fi

    echo "$0: See the log in $LOG_FILE$OLD_LOG_FILE_MESSAGE"

    exec 1<&- #< Close stdout fd.
    exec 2<&- #< Close stderr fd.
    exec 1<>"$LOG_FILE" #< Open stdout as $LOG_FILE for reading and writing.
    exec 2>&1 #< Redirect stderr to stdout.
}

logArgs() # "$@"
{
    echo "Script [$0] started with pid $$ (parent pid $PPID), with $# arg(s):"
    echo "{"
    for ARG in "$@"; do
        echo "    [$ARG]"
    done
    echo "}"
    echo ""
}

process_core_dump()
{
    if ! which gdb >/dev/null; then
        return 0 # no gdb on the host
    fi
    if pidof gdb; then
        return 0 # gdb is alrady engaged
    fi

    CORE_ORIG=$(dirname "$BIN_FILE")/core
    TIME=$(date +"%s")
    CORE="$CORE_ORIG.$TIME"
    if mv "$CORE_ORIG" "$CORE" 2>/dev/null; then
        REPORT="${BIN_NAME}_${FULL_VERSION}_$TIME.gdb-bt"

        echo "Generate crash report (in background) $REPORT"
        echo "t apply all bt 25" |gdb "$BIN_FILE" "$CORE" 2>/dev/null >"/tmp/$REPORT" && \
            mv "/tmp/$REPORT" "/root/$REPORT" &

        ls "$CORE_ORIG".* |grep -v "$CORE" |xargs rm 2>/dev/null
    fi
}

start()
{
    SERVICE_PID=$(pidof "$BIN_NAME")
    if [ ! -z "$SERVICE_PID" ]; then
       echo "$SERVICE_NAME is already running with pid $SERVICE_PID"
       return 0
    fi

    process_core_dump

    local -r DISK=$(fdisk -l |grep "Disk" |grep "dev/sd" |awk '{print substr($2, 0, length($2))}')
    if which hdparm >/dev/null; then
        local -r HDPARM="hdparm"
    else
        local -r HDPARM="$MEDIASERVER_DIR/bin/hdparm"
    fi
    if [ ! -z "$DISK" ]; then
        "$HDPARM" -I /dev/sd? |grep 'Model' >/tmp/hddlist
    fi

    if [ -f "$MEDIASERVER_OUT_FLAG" ]; then
        REDIRECT_OUTPUT="$MEDIASERVER_OUT_LOG"
    else
        REDIRECT_OUTPUT="/dev/null"
    fi

    echo "Starting Media Server, outputting to $REDIRECT_OUTPUT, with command:"
    set -x #< Log the next command.
    "$BIN_FILE" $RUN_ARGS >>"$REDIRECT_OUTPUT" 2>&1 &
    { set +x; } 2>/dev/null

    sleep 1
    # See if mediaserver instantly crashes.
    if [ ! -z "$(pidof "$BIN_NAME")" ]; then
        echo "OK"
    else
        echo "FAILED"
        return 1
    fi
}

startquiet()
{
    start
}

stop() # [signal]
{
    SIGNAL="$1" #< Can be empty.

    echo "Stopping $BIN_NAME..."
    killall $SIGNAL "$BIN_NAME" >/dev/null 2>&1
    local i=0
    while [ ! -z "$(pidof "$BIN_NAME")" ]; do
        sleep 1
        let i++
        if [ $i -gt $SECONDS_TO_WAIT_BEFORE_KILL_9 ]; then
            echo "$SERVICE_NAME not stopped after $i seconds; doing killall -9"
            killall -9 "$BIN_NAME" >/dev/null 2>&1
        fi
    done
    echo "Done"
}

printWatchdogPid()
{
    pgrep -f -- "$0 run_watchdog"
}

start_watchdog()
{
    WATCHDOG_PID=$(printWatchdogPid)
    if [ ! -z "$WATCHDOG_PID" ]; then
        echo "$SERVICE_NAME watchdog is already running with pid $WATCHDOG_PID"
        return 0
    fi

    "$0" "run_watchdog" >/dev/null 2>&1 &
    echo "$SERVICE_NAME watchdog has been started"
}

stop_watchdog()
{
    WATCHDOG_PID=$(printWatchdogPid)
    if [ -z "$WATCHDOG_PID" ]; then
        echo "$SERVICE_NAME watchdog is not running"
        return 0
    fi

    echo "Stopping $SERVICE_NAME watchdog..."
    kill "$WATCHDOG_PID"
    sleep 1
    WATCHDOG_PID=$(printWatchdogPid)
    if [ ! -z "$WATCHDOG_PID" ]; then
        echo "$SERVICE_NAME watchdog still not killed; doing kill -9"
        kill -9 "$WATCHDOG_PID"
        sleep 1
    fi
    echo "Done"
}

run_watchdog()
{
    while true; do
        start
        sleep 20
    done
}

help()
{
    cat <<EOF
Usage: $0 <command>
Supported commands:
 start # Start $SERVICE_NAME and watchdog, outputting to $MEDIASERVER_OUT_LOG if $MEDIASERVER_OUT_FLAG exists.
 startquiet # Start $SERVICE_NAME.
 start_console # Run $SERVICE_NAME in foreground without output redirection.
 start_gdb # Run $SERVICE_NAME under gdb.
 stop # Stop watchdog and kill $SERVICE_NAME with SIGINT.
 kill # Stop watchdog and kill $SERVICE_NAME with SIGKILL.
 status # Report whether $SERVICE_NAME is running, and its pid. Exit status is non-zero if stopped.
 server_status # Output 1 if $SERVICE_NAME is running, otherwise, do nothing.
 restart, reload, force-reload # Stop watchdog and $SERVICE_NAME, start $SERVICE_NAME and watchdog.
 start_watchdog # Start watchdog in background.
 run_watchdog # Run watchdog in foreground.
 stop_watchdog # Stop watchdog, if it is running.
EOF
}

#--------------------------------------------------------------------------------------------------
# main

if [ -f "$OUT_FLAG" ]; then
    redirectOutput "$OUT_LOG"
    logArgs "$@"
    set -x #< Log each command.
fi

ulimit -n $(cat /proc/sys/fs/file-max 2>/dev/null || echo 8192)
ulimit -c unlimited

case "$1" in
    start)
        start || true
        start_watchdog
        ;;
    startquiet)
        start
        ;;
    start_console)
        set -x #< Log each command.
        "$BIN_FILE" $RUN_ARGS
        ;;
    start_gdb)
        set -x #< Log each command.
        gdbserver 0.0.0.0:12345 "$BIN_FILE" $RUN_ARGS
        ;;
    stop)
        stop_watchdog
        stop
        ;;
    kill)
        stop_watchdog
        stop -9
        ;;
    status)
        SERVICE_PID=$(pidof "$BIN_NAME")
        if [ ! -z "$SERVICE_PID" ]; then
            echo "$SERVICE_NAME is running with pid $SERVICE_PID"
            exit 0
        else
            echo "$SERVICE_NAME is stopped"
            exit 1
        fi
        ;;
    server_status)
        if [ ! -z "$(pidof "$BIN_NAME")" ]; then
            echo "1"
        fi
        ;;
    restart|reload|force-reload)
        stop_watchdog || true
        stop || true
        start || true
        start_watchdog
        ;;
    start_watchdog)
        start_watchdog
        ;;
    run_watchdog)
        run_watchdog
        ;;
    stop_watchdog)
        stop_watchdog
        ;;
    *)
        help
        exit 1
esac
