#!/bin/bash -eu

. shell-error
. shell-signal

. /.initrd/initenv
. uevent-sh-functions

message_time=1

pidfile="/var/run/$PROG.pid"
logfile="/var/log/$PROG.log"
inotifyd='/sbin/inotifyd'

[ "${RDLOG-}" != 'console' ] ||
	logfile=/dev/console

UEVENT_MODE="${UEVENT_MODE:-server}"

if [ "$UEVENT_MODE" = 'server' ]; then
	exec >"$logfile" 2>&1

	message "starting server ..."

	[ -d "$filterdir" ] ||
		fatal "$filterdir: bad directory"

	echo "$$" > "$pidfile"

	exit_handler()
	{
		local d rc="$?"
		trap - EXIT
		for d in "$filterdir"/*; do
			[ ! -d "$d" ] || [ ! -f "$d.pid" ] ||
				rm -f -- "$d.pid"
		done
		[ ! -f "$pidfile" ] ||
			rm -f -- "$pidfile"
		exit $rc
	}
	set_cleanup_handler exit_handler

	mkdir -p -- "$uevent_confdb/queue/pause"

	export UEVENT_MODE='queue-processor'

	for d in "$filterdir"/*; do
		[ ! -d "$d" ] || "$0" "n" "${d%/*}" "${d##*/}"
	done

	"$inotifyd" "$0" "$pidfile:x" "$filterdir:nd" &
	wait

	exit 0
fi

evtype="$1"
name="${3-}"
event="$2${name:+/$name}"

if [ "$UEVENT_MODE" = 'queue-processor' ]; then
	case "$evtype" in
		n)
			[ -d "$event" ] && [ -n "${name##.*}" ] ||
				exit 0

			export UEVENT_MODE='queue-handler'
			export QUEUE="$name"
			export INDIR="$event"

			message "starting sub-process for '$QUEUE' queue ..."

			mkdir -p -- "$ueventdir/$QUEUE"

			:> "$event.startup"
			:> "$event.pid"
			:> "$event.timer"

			"$inotifyd" "$0" "$pidfile:x" "$event.pid:x" "$event.startup:0" "$event.timer:0" "$event:ny" &

			while [ -e "$event.startup" ]; do
				:<"$event.startup"
				sleep 0.1
			done

			echo "$!" >"$event.pid"
			;;
		d)
			[ ! -d "$event" ] || [ ! -f "$event.pid" ] ||
				rm -f -- "$event.pid"
			;;
		x)
			kill "$PPID"
			;;
	esac
	exit 0
fi

[ "$UEVENT_MODE" = 'queue-handler' ] ||
	fatal "unexpected mode: $UEVENT_MODE"

if [ "$2" = "$INDIR.startup" ]; then
	[ "$evtype" = '0' ] ||
		exit 0
	rm -f "$INDIR.startup"
fi

if [ "$evtype" = 'x' ]; then
	kill "$PPID"
	exit 0
fi

if [ -e "$uevent_confdb/queue/pause/.all" ] || [ -e "$uevent_confdb/queue/pause/$QUEUE" ]; then
	message "$QUEUE: queue paused"
	exit 0
fi

udevadm settle --timeout=3 ||:

glob()
{
	[ -e "$1" ]
}

queuedir="$ueventdir/$QUEUE"

mv -f -- "$INDIR"/* "$queuedir" 2>/dev/null ||:
glob "$queuedir"/* || exit 0

[ "$evtype" != '0' ] || [ "$2" = "$INDIR.startup" ] ||
	message "$QUEUE: retrying with failed events ..."

for ev in "$queuedir"/*; do
	message "$QUEUE: event $ev"
done

get_name()
{
	[ ! -d "$fn" ] && [ -x "$fn" ] || return 1
	name="${fn##*/}"
	name="${name#[0-9][0-9][0-9]-}"
}

run_scripts()
{
	local exe

	for exe in "/lib/uevent/each/$1"/*; do
		[ -x "$exe" ] || continue
		"$exe" "$2" ||:
	done
}

for fn in "$handlerdir/$QUEUE"/*; do
	get_name || continue

	run_scripts pre "$QUEUE"

	message "$QUEUE: running queue-specific handler: $fn"
	"$fn" "$queuedir" || message "$QUEUE: event handler failed: $fn"

	run_scripts post "$QUEUE"
done

for fn in "$handlerdir"/*; do
	get_name && glob "$queuedir/$name".* || continue

	run_scripts pre "$QUEUE"

	message "$QUEUE: running handler: $fn"
	"$fn" || message "$QUEUE: event handler failed: $fn"

	run_scripts post "$QUEUE"
done

if glob "$queuedir"/*; then
	sleep ${RDUEVENT_TIMEOUT:-1}
	:<"$filterdir/$QUEUE.timer"
fi
