#!/bin/sh -e
#
# description:	Starts and stops each hotpluggable subsystem.
#		On startup, may simulate hotplug events for devices
#		that were present at boot time, before filesystems
#		used by /sbin/hotplug became available.

PATH=/sbin:/bin

[ -x /sbin/hotplug ] || exit 0

. /lib/lsb/init-functions
. /etc/default/rcS
if [ "x$VERBOSE" = "xno" ]; then
        MODPROBE_OPTIONS="$MODPROBE_OPTIONS -Q"
        export MODPROBE_OPTIONS
fi

if [ ! -f /proc/sys/kernel/hotplug ]; then
   log_warning_msg "Kernel hotplug support not enabled."
   exit 0
fi

[ -e /etc/default/hotplug ] && . /etc/default/hotplug

# Takes two parameters, list to sort through, and list of elements
# that should be removed from it.  Returns prune_output, which is
# the list with the elements removed, and prune_discard, which is
# a list of the discarded elements.
#
# Some days I wish shell had tuples.
prune()
{
        unset prune_output prune_discard

        for x in ${1}; do
                keep=y
                for y in ${2}; do
                        if [ ${x} = ${y} ]; then
                                keep=n
                        fi
                done
                if [ ${keep} = y ]; then
                        prune_output="${prune_output} ${x}"
                else
                        prune_discard="${prune_discard} ${x}"
                fi
        done

#       echo "1: ${1}"
#       echo "2: ${2}"
#       echo "prune_output: ${prune_output}"
#       echo "prune_discard: ${prune_discard}"

}


# The purpose of this is to generate an ordered list, where the list
# is taken from LIST, and DEPLIST specified the order that elements
# iff they exist must be in.
#
# 1 is the LIST, 2 is the DEPLIST
sort_with_deps()
{
    # Get the list of elements that have no ordering requirement
    prune "${1}" "${2}"

    # Put these at the top of our list
    sorted_list=${prune_output}

    # Reverse psychology here.  Throw away all items of the DEPLIST
    # that we actually want.  prune_discard will have them in the right
    # order
    prune "${2}" "${prune_discard}"

    # append it to the new list, knowing that dependancies are satisfied.
    sorted_list="${sorted_list} ${prune_discard}"

    unset prune_output prune_discard

}

run_rcs() {
    PRINTK=`cat /proc/sys/kernel/printk`
    [ "$VERBOSE" = no ] && echo "0 0 0 0" > /proc/sys/kernel/printk

    LIST=/etc/hotplug/*.rc
    ORDERING="/etc/hotplug/pci.rc /etc/hotplug/usb.rc /etc/hotplug/ide.rc /etc/hotplug/scsi.rc"

    sort_with_deps "${LIST}" "${ORDERING}"

    for RC in ${sorted_list}; do
	basename=${RC#/etc/hotplug/}
	name=${basename%.rc}
	[ "$VERBOSE" != no ] && log_begin_msg "Running $basename..."
	if [ "$(eval echo \$HOTPLUG_RC_$name)" = no ]; then
	    [ "$VERBOSE" != no ] && log_end_msg 1 || true
	    continue
	fi
	set +e
	if [ "$VERBOSE" != no ]; then
		$RC $1
		RC_STATUS=$?
	else
		$RC $1 >/dev/null 2>&1
		RC_STATUS=$?
	fi
	set -e
	if [ "$1" = status ]; then
	    continue
	fi
	[ "$VERBOSE" != no ] && log_end_msg $RC_STATUS || true
    done
    echo "$PRINTK" > /proc/sys/kernel/printk
    return 0
}


case "$1" in
start)
    log_begin_msg "Starting hotplug subsystem..."
    #echo /sbin/hotplug > /proc/sys/kernel/hotplug
    run_rcs $1
    log_end_msg 0
    ;;

stop)
    log_begin_msg "Stopping hotplug subsystem..."
    run_rcs $1
    #echo /bin/true > /proc/sys/kernel/hotplug
    log_end_msg 0
    ;;

restart|force-reload)
    log_begin_msg "Restarting hotplug subsystem..."
    run_rcs stop
    run_rcs start
    log_end_msg 0
    ;;

status)
    run_rcs $1
    ;;

*)
    log_success_msg "Usage: $0 {start|stop|restart|status|force-reload}"
    exit 1
    ;;
esac

exit 0
