#!/bin/sh

pid_file=/var/run/cbt_check_internet.pid
stock_displaced=/var/run/auto-ipoe-cbt-stock-displaced
private_monitor=/usr/share/auto-ipoe/bin/cbt_check_internet.sh
stock_monitor=/usr/bin/cbt_check_internet.sh

read_monitor_pid() {
	pid="$(cat "$pid_file" 2>/dev/null || true)"
	case "$pid" in
		''|*[!0-9]*) return 1 ;;
	esac
	[ -d "/proc/$pid" ] || return 1
	printf '%s\n' "$pid"
}

monitor_kind() {
	pid=$1
	[ -r "/proc/$pid/cmdline" ] || return 1
	if tr '\000' '\n' <"/proc/$pid/cmdline" | grep -Fxq "$private_monitor"; then
		printf '%s\n' private
	elif tr '\000' '\n' <"/proc/$pid/cmdline" | grep -Fxq "$stock_monitor"; then
		printf '%s\n' stock
	else
		printf '%s\n' unknown
	fi
}

stop_verified_monitor() {
	pid=$1
	kind="$(monitor_kind "$pid")" || return 1
	case "$kind" in
		private|stock) ;;
		*)
			echo "error: refusing to stop an unknown process from $pid_file" >&2
			return 1
			;;
	esac
	start-stop-daemon -K -q -p "$pid_file" >/dev/null 2>&1 || true
	sleep 1
	if kill -0 "$pid" 2>/dev/null; then
		kill -KILL "$pid" 2>/dev/null || return 1
	fi
	rm -f "$pid_file"
}

start_monitor() {
	monitor=$1
	start-stop-daemon -S -b -m -p "$pid_file" -a "$monitor" || return 1
	sleep 1
	pid="$(cat "$pid_file" 2>/dev/null || true)"
	case "$pid" in
		''|*[!0-9]*) return 1 ;;
	esac
	kill -0 "$pid" 2>/dev/null
}

start_private_monitor() {
	if pid="$(read_monitor_pid)"; then
		kind="$(monitor_kind "$pid")" || return 1
		case "$kind" in
			private) return 0 ;;
			stock) touch "$stock_displaced" ;;
			*)
				echo "error: $pid_file identifies an unknown running process" >&2
				return 1
				;;
		esac
		stop_verified_monitor "$pid" || return 1
	else
		rm -f "$pid_file"
	fi

	if start_monitor "$private_monitor"; then
		return 0
	fi

	if [ -f "$stock_displaced" ] && [ -x "$stock_monitor" ]; then
		if start_monitor "$stock_monitor" >/dev/null 2>&1; then
			rm -f "$stock_displaced"
		fi
	fi
	echo "error: could not start the Auto-IPoE connectivity monitor" >&2
	return 1
}

stop_private_monitor() {
	if ! pid="$(read_monitor_pid)"; then
		rm -f "$pid_file"
		return 0
	fi
	kind="$(monitor_kind "$pid")" || return 1
	case "$kind" in
		private) stop_verified_monitor "$pid" ;;
		stock) return 0 ;;
		*)
			echo "error: $pid_file identifies an unknown running process" >&2
			return 1
			;;
	esac
}

restore_stock_monitor() {
	if pid="$(read_monitor_pid)"; then
		kind="$(monitor_kind "$pid")" || return 1
		if [ "$kind" = stock ]; then
			rm -f "$stock_displaced"
			return 0
		fi
	fi
	stop_private_monitor || return 1
	if [ -f "$stock_displaced" ] && [ -x "$stock_monitor" ]; then
		start_monitor "$stock_monitor" || return 1
	fi
	rm -f "$stock_displaced"
}

case "${1:-}" in
	start)
		[ -x "$private_monitor" ] || {
			echo "error: packaged Auto-IPoE connectivity monitor is unavailable" >&2
			exit 1
		}
		command -v cbt_led.sh >/dev/null 2>&1 || {
			echo "error: Linksys LED controller is unavailable" >&2
			exit 1
		}
		start_private_monitor || exit 1
		;;
	stop)
		stop_private_monitor || exit 1
		;;
	restore)
		restore_stock_monitor || {
			echo "error: could not restore the stock connectivity monitor" >&2
			exit 1
		}
		;;
	*)
		echo "usage: auto-ipoe-cbt-monitor {start|stop|restore}" >&2
		exit 2
		;;
esac

exit 0
