#!/bin/sh

msg='Starting udevd...'
check() {
	local f
	for f in "/lib/$1"/*; do
		"$f" ${2-} || return 1
	done
}

run() {
	# Save the environment, to use it inside udev filters.
	showenv -q |
	while read l; do
		s="${l%%=*}"
		[ -z "${s##*[!A-Za-z0-9_]*}" ] ||
			printf '%s\n' "$l"
	done > /dev/.initramfs/env

	udevd --daemon --resolve-names=never

	udevadm control --property=STARTUP=1
	udevadm trigger --type=subsystems --action=add >/dev/null 2>&1
	udevadm trigger --type=devices    --action=add >/dev/null 2>&1

	# Load user-defined modules
	load_modules postudev

	local handler fail=

	# It is not currently limit since the execution of programs
        # takes time, which is not counted. But we do not want to use
        # additional utilities to calculate the time limit.
	local sec=$((${ROOTDELAY:-180}*10))

	while [ "$sec" -gt 0 ]; do
		# Wait udev event queue
		udevadm settle

		# Stop queue to avoid race
		udevadm control --stop-exec-queue

		! check success -q ||
			break

		if ! glob -q "$udev_eventdir"/*; then
			sleep 0.1
			sec=$(($sec-1))
			udevadm control --start-exec-queue
			continue
		fi

		# Some handler uses udev, so we have to start it before
		# start queue handlers.
		mv -- "$udev_eventdir"/* "$handler_eventdir"
		udevadm control --start-exec-queue

		# Run udev handlers
		for handler in /lib/handlers/*; do
			name="${handler##*/}"
			name="${name#*-}"

			glob -q "$handler_eventdir/$name"* ||
				continue

			verbose "Running $name handler ..."
			if ! "$handler"; then
				fail="$name"
				break 2
			fi
		done
		remove_done_events "$handler_eventdir"

		sleep 0.1
		sec=$(($sec-1))
	done

	if [ -n "$fail" ]; then
		error "event handler failed: $fail"
		return 1
	fi

	check success ||
		return 1
}
