#!/bin/bash
#
# Usage: modload libpath allow_mismatch [tun] [tap] [sheep] 
#
# BE CAREFUL! THIS SCRIPT IS INVOKED FROM A SETUID ROOT BINARY
#

_MOL=1
_EXACT=1
echo $2 | grep -q sheep && _SHEEP=1
echo $2 | grep -q tun && _TUN=1
echo $2 | grep -q tap && _TAP=1
echo $2 | grep -q ^1 && unset _EXACT

grep -q 198 /proc/misc && unset _SHEEP
grep -q 200 /proc/misc && unset _TUN
grep -q 'tap[0-9]' /proc/net/dev && unset _TAP

LOADED=`/sbin/lsmod | sed -e 's/\(^\w*\).*/\1/g'`
for x in $LOADED ; do
    [ $x = "mol" ] && unset _MOL
done

LIB_DIR=$1
BIN_DIR=/$LIB_DIR/bin/
MOD_DIR=/$LIB_DIR/modules
MOL_VERS=`$BIN_DIR/molrcget -V`

# for mol_uname
export BIN_DIR

###################################################
# Where to look for modules
###################################################

# XXX: This is also done in the startmol script
MOD_DIR="$LIB_DIR/modules"

function add_mod_dir() {
    test -d "$1" || return

    for x in $MOD_DIR ; do
	test $x -ef $1 && return
    done
    MOD_DIR="$MOD_DIR $1"
}
add_mod_dir "/usr/local/lib/mol/$MOL_VERS/modules"
add_mod_dir "/usr/lib/mol/$MOL_VERS/modules"


###################################################
# get_mod_name - lookup the module binary
###################################################

function _mol_uname() {
    $BIN_DIR/mol_uname "$@" -- $MOD_DIR
}

function get_mod_name () {
    _MOD_DIR=`_mol_uname -e` || {

	# Is exact match required?
	[ "$_EXACT" ] && {
	    echo "===================================================================="
	    echo "  No mol-$MOL_VERS kernel modules corresponding to the running"
	    echo "  `_mol_uname -p` kernel were found ('startmol --list' displays"
	    echo "  installed version). Recompile the mol kernel modules (recommended)"
	    echo "  or try starting MOL as root using the '-a' switch. The '-a'"
	    echo "  flag can be made default by the 'allow_kver_mismatch: yes' setting."
	    echo "===================================================================="
	    return 2
	} 1>&2

	_MOD_DIR=`_mol_uname -f` || {
	    echo "===================================================================="
	    echo "  No kernel module suitable for this kernel was found. The MOL"
	    echo "  kernel modules must be recompiled (refer to www.maconlinux.org"
	    echo "  for instructions). The command 'startmol --list' can be used"
	    echo "  to display installed kernel modules."
	    echo "===================================================================="
	    return 1;
	} 1>&2
    }

    [ -f $_MOD_DIR/$1.ko ] && {
	echo $_MOD_DIR/$1.ko ; 
	return 0;
    }
    [ -f $_MOD_DIR/$1.o ] && {
	echo $_MOD_DIR/$1.o ; 
	return 0;
    }

    echo "The kernel module '$_MOD_DIR/$1.o' appears to be missing." 1>&2
    return 1
}


###################################################
# load_mol_module
###################################################

function load_mol_module () {
    echo "Loading Mac-on-Linux kernel module:"

    /sbin/modprobe -v mol || {
	echo "===================================================================="
	echo "  Failed to load the Mac-on-Linux kernel module -- please install   "
	echo "  mol-modules-source and build your own, or find a binary package   "
	echo "  providing mol-modules for your running kernel.                    "
	echo "===================================================================="
	echo 
	exit 1
    }
    return 0
}


###################################################
# load the sheep ethernet driver
###################################################

function load_mod () {
    echo "Loading $2 kernel module:"

    /sbin/modprobe -v $1
}


###################################################
# misc checks
###################################################

function sheep_check () {
    [ ! -c /dev/sheep_net -a ! -e /dev/.devfsd -a ! -e /dev/.udev.tdb ] && {
	echo "Creating the /dev/sheep_net device node."
	mknod --mode=600 /dev/sheep_net c 10 198
    }
    return 0
}

function tun_check () {
    [ ! -c /dev/net/tun -a ! -e /dev/.devfsd -a ! -e /dev/.udev.tdb ] && {
	echo "Creating the /dev/net/tun device node."
	[ -d /dev/net ] || mkdir --mode 755 /dev/net
	mknod --mode=600 /dev/net/tun c 10 200
    }
    return 0
}

function mol_dev_check () {
    MINOR=`cat /proc/misc | sed '/[0-9]* mol$/ ! d' | sed s/mol//`
    test $MINOR -gt 0 -a $MINOR -lt 255 || {
	echo "Failed to extract the MOL device number"
	exit 1
    }
    [ ! -c /dev/mol ] && {
	rm -f /dev/mol
	mknod --mode=600 /dev/mol c 10 "$MINOR"
    }
}


###################################################
# main
###################################################
test "$_MOL" && { load_mol_module || exit $? ; }
mol_dev_check

test "$_SHEEP" && { sheep_check && load_mod sheep "SheepNet" ; }
test "$_TUN" && { tun_check && load_mod tun "tun driver" ; }
test "$_TAP" && { load_mod ethertap "tap driver" ; }

exit 0
