#!/bin/sh
#BIN=../..
BIN=/sbin

INSMOD=$BIN/insmod
RMMOD=$BIN/rmmod

do_ksyms() {
$BIN/ksyms | grep '\(base\)\|\(mid\)\|\(top\)'
}

do_lsmod() {
$BIN/lsmod | grep '\(base\)\|\(mid\)\|\(top\)'
}

page_me() {
echo "Press RETURN to continue..."
read dummy
tput clear
}

if [ ! -f base.o ]
then
	echo building modules
	make
	page_me
else
	tput clear
fi

echo "This is a demo of stackable modules."
echo
echo "Loading base module, a module with a function that shows it has been called."
$INSMOD ./base.o
echo
echo "This is the output of lsmod:"
do_lsmod
echo
echo "This is the output of ksyms:"
do_ksyms
echo
echo "As you can see, the function 'base' is defined as global by this module"

page_me

echo "Now, let's load the module 'top' on top of the base module."
echo "This new module will call the base function with two parameters:"
echo "an integer named level and a string 'hello'."
echo "The call will be performed when loading 'top', so watch closely now:"
echo
$INSMOD ./top.o
echo
echo "The kernel shows this for lsmod and ksyms:"
echo
do_lsmod
echo
do_ksyms
echo
echo "The top module doesn't export any symbols, so ksyms doesn't show any..."

page_me

echo "Now I'm going to attempt to remove the base module, in spite of it"
echo "being used by the top module:"
echo
$RMMOD base
echo
echo "...no way, as you see!"
echo
do_lsmod
echo

page_me

echo "Instead I'm going to remove the top module, and insert a new module: mid"
echo "The 'mid' module calls the base function, and also exports the name of"
echo "a function of its own. _BUT_ it will rename its function so that it will"
echo "have the same name as the function in the base module. Watch:"
echo
$RMMOD top
$INSMOD ./mid.o
do_lsmod
echo
do_ksyms
echo

echo "See! The symbol '_base' is defined in _two_ modules!"
echo "Just so it's easy to see what happens, 'mid' increments the integer 'level'"
echo "Let's load 'top' on top of this stack:"
echo
$INSMOD ./top.o
echo

page_me

echo "The stack looked like this:"
echo
do_lsmod
echo
echo "Now I'm going to remove 'top' and install a copy of 'mid'"
echo "The copy will be named 'mid2' with the use of the '-o' option to insmod"
echo
$RMMOD top
$INSMOD -o mid2 ./mid.o
do_lsmod
echo
do_ksyms
echo
echo "Guess what happens when we load 'top' on this stack..."

page_me

echo "OK, let's see, here we go:"
echo
$INSMOD ./top.o
echo
echo "Nice, huh?  This shows that symbols are resolved from the top of the stack!"
echo "The stack looks like this now:"
echo
do_lsmod
echo
do_ksyms
echo

page_me

echo "As an extra feature, I'm going to show that it is possible to change"
echo "the values defined inside a module while loading it."
echo "The integer 'level' is defined (static) inside 'top'."
echo "Now I'm going to remove 'top' and then reload it with level set to 100"
echo "This is done by the command: 'insmod top.o level=100'"
echo
$RMMOD top
$INSMOD ./top.o level=100
echo

echo "All integers in a module can be set to any value at load-time!!!"
echo "Now, you try...(begin with the man pages)"
page_me

$RMMOD -r top

echo bye...