#!/bin/bash
#
# wssshd        Startup script for WebSocket SSH Daemon
#
# chkconfig: 345 85 15
# description: WebSocket SSH Daemon - Handles WebSocket connections from wsssh/wsscp clients
# processname: wssshd
# pidfile: /var/run/wssshd.pid
# config: /etc/wssshd.conf

### BEGIN INIT INFO
# Provides: wssshd
# Required-Start: $local_fs $network $syslog
# Required-Stop: $local_fs $network $syslog
# Default-Start: 3 4 5
# Default-Stop: 0 1 2 6
# Short-Description: WebSocket SSH Daemon
# Description: WebSocket SSH Daemon handles WebSocket connections from wsssh/wsscp clients
### END INIT INFO

# Source function library (Debian/Ubuntu)
. /lib/lsb/init-functions

# Configuration
NAME="wssshd"
DAEMON="/usr/bin/wssshd"
WATCHDOG="/usr/sbin/wssshd-watchdog"
PIDFILE="/var/run/wssshd.pid"
WATCHDOG_PIDFILE="/var/run/wssshd-watchdog.pid"
CONFIG="/etc/wssshd.conf"
LOG_FACILITY="daemon"
USER="wssshd"
GROUP="wssshd"

# Check if we're running as root
if [ $(id -u) != 0 ]; then
    echo "Error: This script must be run as root"
    exit 1
fi

# Function to check if process is running
is_running() {
    if [ -f "$PIDFILE" ]; then
        local pid=$(cat "$PIDFILE")
        if [ -d "/proc/$pid" ]; then
            return 0
        else
            # Stale PID file
            rm -f "$PIDFILE"
            return 1
        fi
    fi
    return 1
}

# Function to start the daemon
start() {
    echo -n "Starting $NAME: "

    # Check if daemon is already running
    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "already running (PID: $pid)"
        return 0
    fi

    # Check if config file exists
    if [ ! -f "$CONFIG" ]; then
        echo "configuration file $CONFIG not found"
        echo "Please create $CONFIG with the required settings."
        echo "You can use the example configuration as a template:"
        echo "  cp /usr/share/wsssh/wssshd.conf.example $CONFIG"
        return 1
    fi

    # Check if daemon executable exists
    if [ ! -x "$DAEMON" ]; then
        echo "daemon executable $DAEMON not found or not executable"
        return 1
    fi

    # Create necessary directories
    mkdir -p /var/run /var/log/wssshd
    chown $USER:$GROUP /var/run /var/log/wssshd 2>/dev/null || true

    # Start the daemon directly
    echo "Starting daemon..."
    if start-stop-daemon --start --quiet --pidfile "$PIDFILE" \
        --chuid $USER:$GROUP --background --make-pidfile \
        --exec "$DAEMON" --output /var/log/wssshd/wssshd.log; then
        echo "Daemon started successfully"
    else
        echo "start-stop-daemon failed, trying direct execution..."
        if "$DAEMON" >> /var/log/wssshd/wssshd.log 2>&1 &
        then
            echo $! > "$PIDFILE"
            echo "Daemon started successfully (direct execution)"
        else
            echo "FAILED"
            echo "Could not start daemon"
            return 1
        fi
    fi

    # Wait for daemon to be fully running
    local count=0
    while [ $count -lt 10 ] && ! is_running; do
        echo "Waiting for daemon to start... ($count/10)"
        sleep 1
        count=$((count + 1))
    done

    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "Daemon is running (PID: $pid)"

        # Stop any existing watchdog before starting a new one
        if [ -f "$WATCHDOG_PIDFILE" ] || pgrep -f "wssshd-watchdog" >/dev/null 2>&1; then
            echo "Stopping existing watchdog..."
            $WATCHDOG stop >/dev/null 2>&1
            sleep 2
        fi

        # Now start the watchdog to monitor the running daemon
        echo "Starting watchdog..."
        if [ -x "$WATCHDOG" ]; then
            $WATCHDOG start >/dev/null 2>&1

            # Wait for watchdog PID file to be created (max 5 seconds)
            local count=0
            while [ $count -lt 10 ] && [ ! -f "$WATCHDOG_PIDFILE" ]; do
                sleep 0.5
                count=$((count + 1))
            done

            if [ -f "$WATCHDOG_PIDFILE" ]; then
                watchdog_pid=$(cat "$WATCHDOG_PIDFILE" 2>/dev/null)
                if [ -n "$watchdog_pid" ] && kill -0 "$watchdog_pid" 2>/dev/null; then
                    echo "OK"
                    return 0
                else
                    echo "OK (daemon running, watchdog process not responding)"
                    return 0
                fi
            else
                echo "OK (daemon running, watchdog PID file not found)"
                return 0
            fi
        else
            echo "OK (daemon running, no watchdog available)"
            return 0
        fi
    else
        echo "FAILED"
        echo "Daemon failed to start properly"
        return 1
    fi
}

# Function to stop the daemon
stop() {
    echo -n "Stopping $NAME: "

    # First, try to stop the watchdog if it's running
    if [ -f "$WATCHDOG_PIDFILE" ]; then
        echo "Stopping watchdog..."
        $WATCHDOG stop >/dev/null 2>&1
        sleep 2
    fi

    # Check if daemon is running via PID file
    if is_running; then
        echo "Stopping daemon via PID file..."
        local pid=$(cat "$PIDFILE")
        # Try to stop gracefully first
        kill -TERM "$pid" 2>/dev/null
        sleep 2

        # Check if it's still running
        if kill -0 "$pid" 2>/dev/null; then
            # Force kill if still running
            kill -KILL "$pid" 2>/dev/null
            sleep 1
        fi
    fi

    # Also kill any wssshd processes that might be running (regardless of PID file)
    echo "Ensuring all wssshd processes are stopped..."
    pkill -TERM -f "^/usr/bin/wssshd" 2>/dev/null || true
    sleep 2
    pkill -KILL -f "^/usr/bin/wssshd" 2>/dev/null || true

    # Clean up PID files
    rm -f "$PIDFILE" "$WATCHDOG_PIDFILE"

    # Final check
    if is_running; then
        echo "FAILED"
        return 1
    else
        echo "OK"
        return 0
    fi
}

# Function to restart the daemon
restart() {
    stop
    sleep 2
    start
}

# Function to check status
status() {
    # Check watchdog status
    if [ -f "$WATCHDOG_PIDFILE" ]; then
        local watchdog_pid=$(cat "$WATCHDOG_PIDFILE")
        if kill -0 "$watchdog_pid" 2>/dev/null; then
            echo "Watchdog is running (PID: $watchdog_pid)"
        else
            echo "Watchdog PID file exists but process is not running"
            rm -f "$WATCHDOG_PIDFILE"
        fi
    else
        echo "Watchdog is not running"
    fi

    # Check daemon status
    if is_running; then
        local pid=$(cat "$PIDFILE")
        echo "$NAME daemon is running (PID: $pid)"
        return 0
    else
        echo "$NAME daemon is not running"
        return 3
    fi
}

# Function to reload configuration
reload() {
    echo -n "Reloading $NAME configuration: "

    if ! is_running; then
        echo "not running"
        return 1
    fi

    local pid=$(cat "$PIDFILE")
    kill -HUP $pid 2>/dev/null

    if [ $? -eq 0 ]; then
        echo "OK"
        return 0
    else
        echo "FAILED"
        return 1
    fi
}

# Main script logic
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    reload)
        reload
        ;;
    status)
        status
        ;;
    condrestart|try-restart)
        if is_running; then
            restart
        fi
        ;;
    *)
        echo "Usage: $0 {start|stop|restart|reload|status|condrestart}"
        exit 2
        ;;
esac

exit $?