#!/bin/sh

set -e

test -f /sbin/discover || exit 0

# file that determines the discover program's default behavior
CONFFILE=/etc/discover.conf

# list of modules for which to skip loading attempts
SKIPFILE=/etc/discover-autoskip.conf

# file that controls this init script's management of device symlinks
INITFILE=/etc/default/discover

case "$1" in
    start|restart) ;;
    stop|reload|force-reload) exit 0 ;;
esac

# Load init script parameters.
if [ -r $INITFILE ]; then
    . $INITFILE
fi

# Determine the hardware to scan for by extracting "boot" lines from
# the config file:
if [ -f $CONFFILE ]
then
    TYPES=$(sed -n "s/#.*$//;s/^boot //p" $CONFFILE)
    # Deal with pre-0.9.7 syntax:
    TYPES=$(echo $TYPES | sed "s/,/ /g")
fi

run_discover()
{
    if [ -f $CONFFILE ] ; then
        # Extract "enable" and "disable" lines from /etc/discover.conf:
	ARGUMENTS=`sed "s/#.*$//" $CONFFILE | \
	    awk '{
                if ($1 == "enable")
                    print "--enable=" $2;
		else if ($1 == "disable")
		    print "--disable=" $2;
		}'`
    fi

    discover $ARGUMENTS "$@"
    unset ARGUMENTS
}
            
# Detect hardware:
echo -n "Detecting hardware: " >&2
MODULES=$(run_discover --module $TYPES)
# Get rid of ide-scsi for kernels that don't need it. This is a horrible hack,
# but since we're retiring this version anyway I don't care
case $(uname -r) in
    2.[0-4].*) true;;
    *) MODULES=$(echo $MODULES | sed 's/ide-scsi //' | sed 's/-/_/');;
esac

echo $MODULES >&2

if [ -f /var/lib/discover/crash ]
then
    # The system crashed trying to load a module during the last boot
    # cycle, so add an appropriate "skip" line to the skip file:
    echo "skip $(cat /var/lib/discover/crash)" >> $SKIPFILE
    rm -f /var/lib/discover/crash
    sync
fi

# Determine if we should skip a given module:
SKIPLIST=""
if test -f $CONFFILE; then
    test -f $SKIPFILE || SKIPFILE=""
    SKIPLIST=$(sed -n 's/#.*$//;y/	/ /;s/   */ /g;s/^ *skip //p' $CONFFILE $SKIPFILE)
fi

skip()
{
    echo "$SKIPLIST" | grep -wq -e "$1"
}
            
# Determine if the module is already loaded
is_loaded() {
    module="$1"
    if cut -d" " -f1 /proc/modules | grep -q "^${module}\$" ; then
        true
    else
        false
    fi
}

# Load the appropriate modules:
for MODULE in $MODULES
do
    # See if we should skip $MODULE:
    if [ "$MODULE" = "ignore" -o "$MODULE" = "unknown" ]
    then
        continue
    fi

    if skip $MODULE
    then
        echo "Skipping $MODULE module; edit $CONFFILE and/or"
        echo "$SKIPFILE to re-enable it." >&2
        continue
    fi

    if expr "$MODULE" : "Server:.*" > /dev/null 2>&1
    then
        # silently skip X server "modules"
        continue
    fi

    if ! (modprobe -n ${MODULE}) > /dev/null
    then
        echo "Skipping $MODULE module; assuming it is compiled into the kernel." >&2
        continue
    fi

    if is_loaded "$MODULE" ; then
        echo "Skipping Module $MODULE. It's already loaded." >&2
        continue
    fi

    echo "Loading $MODULE module." >&2

    # Note the module being loaded in /var/lib/discover/crash. If loading
    # the module crashes the machine, this file will exist at the next
    # boot, and we'll add an appropriate "skip" line to the conffile so we
    # don't try to load it again.
    echo $MODULE > /var/lib/discover/crash
    sync

    # '|| true' make sure we start up, even if one module fails to load.
    modprobe $MODULE || true

    # The module loaded without incident, so we can safely remove the crash
    # file.
    rm -f /var/lib/discover/crash
    sync
done

if [ "$MANAGE_CDROM_DEVICES" = "true" ]; then
    # Remove all old optical drive mount points:
    for CDMOUNT in /cdrom?
    do
        rm -rf $CDMOUNT
    done

    # Link /dev/cdromX to all detected CD/DVD drives, and create mount points:
    CDNUM=0
    for CDROM in $(run_discover --device cdrom | sort)
    do
        ALTCDROM=$(echo $CDROM | sed 's/\/dev\/scd/\/dev\/sr/')
        if [ ! -e $CDROM -a ! -e $ALTCDROM ] 
        then
            echo -n "discover reports that $CDROM is a CD/DVD device, but it and $ALTCDROM " >&2
            echo "do not exist.  Not updating /dev/cdrom$CDNUM." >&2
        elif [ ! -b $CDROM -a ! -e $ALTCDROM ]
        then
            
            echo -n "discover reports that $CDROM is a CD/DVD device, but it and $ALTCDROM " >&2
            echo "are not block devices.  Not updating /dev/cdrom$CDNUM." >&2
        elif [ -e /dev/cdrom$CDNUM -a ! -L /dev/cdrom$CDNUM ]
        then
            echo -n "/dev/cdrom$CDNUM exists and is not a symlink.  Not updating " >&2
            echo "/dev/cdrom$CDNUM." >&2
            CDNUM=$(( $CDNUM + 1 ))
        else
            ln -fs $CDROM /dev/cdrom$CDNUM
            if ! awk '{print $2}' < /proc/mounts | grep -qs $CDROM_BASE_MOUNTPOINT"cdrom$CDNUM"
            then
                mkdir -p $CDROM_BASE_MOUNTPOINT"cdrom$CDNUM"
            else
                echo "Cannot create directory at "$CDROM_BASE_MOUNTPOINT"cdrom$CDNUM because it exists."
            fi
            CDNUM=$(( $CDNUM + 1 ))
        fi
    done

    # Link /dev/cdrom to the appropriate device:
    if [ -e /dev/cdrom0 ]
    then
        if [ -L /dev/cdrom -o ! -e /dev/cdrom ]
        then
            ln -fs /dev/cdrom0 /dev/cdrom
            # link the mountpoint only if nothing is mounted there
            if ! cat /proc/mounts | awk '{print $2}' | grep -qs "^"$CDROM_BASE_MOUNTPOINT"cdrom"
            then
                ln -fs $CDROM_BASE_MOUNTPOINT"cdrom0" $CDROM_BASE_MOUNTPOINT"cdrom"
            else
                echo "Cannot create link from "$CDROM_BASE_MOUNTPOINT"cdrom to "$CDROM_BASE_MOUNTPOINT"cdrom0," >&2
                echo "because a filesystem is already mounted at "$CDROM_BASE_MOUNTPOINT"cdrom." >&2
            fi
        else
            echo "/dev/cdrom exists and is not a symlink.  Not updating /dev/cdrom." >&2
        fi
    else
        echo "No CD/DVD drives found." >&2
    fi
fi

# vim:ai:et:sts=4:sw=4:tw=0:
