#!	/bin/sh
# Please make sure this file can be executed by both "bash" and "ash".

x=0
umask 022
readonly rm=rm

ttydev=/dev/tty

if [ -x /usr/bin/tput ]; then
    readonly bold=`tput bold`
    readonly clear=`tput clear`
    readonly norm=`tput sgr0`
else
    readonly bold='[1m'
    readonly clear='[H[J'
    readonly norm='[0;10m'
fi

if [ -x /bin/star ]; then
    readonly extract="star"
else 
    readonly extract="cpio -i -d"
fi

if [ -x /target/bin/sed ]; then
    readonly sed="/target/bin/sed"
else 
    readonly sed="sed"
fi

source_eval () {
	if [ -z "$LANG" ]; then
		. $ModuleHelp/eval_C
	else
		LINGUA=`echo $LANG | $sed -e 's/_.*//'`
		if [ -f $ModuleHelp/eval_$LINGUA ]; then
			. $ModuleHelp/eval_$LINGUA
		else
			. $ModuleHelp/eval_C
		fi
	fi
}

if [ -x /usr/bin/tempfile ]; then
    readonly TempFile=`tempfile`
else 
    readonly TempFile="/tmp/`echo $0|$sed -e 's/^.*\///'`.$$"
fi

count_words () {
	echo "$#"
}

first () {
	echo "$1"
}

second () {
	echo "$2"
}

third () {
	echo "$3"
}

fourth () {
	echo "$4"
}

last () {
	eval echo $"$#"
}

mkmodulevarname () {
    echo $1 | $sed 's/[-+,]/_/g'
}

write_it_down () {
	local reply
	echo ""
	echo "$1"
	echo ""
	echo $bold"$msg_Something_went_wrong"$norm
	read reply
	return $?
}

# Shell interface to "dialog"
# Bruce Perens, November 1995
# This is free software under the GNU General Public License.

# Global options
#	The variable $BACKTITLE specifies the back title.
#	The variable $DIALOG_OPTIONS, initialized here to --clear, provides
#	options you want on the command line of each dialog invocation.
#	The variable $DIALOG_TEST can be set to "echo" to see the calls
#	to dialog without executing them.

DIALOG_OPTIONS=""

# Make any dialogue box, with default settings and backtitle from
# $BACKTITLE in the environment.
#
# dialog --type arg arg ...
#
dialogBox () {
	local type="$1"
	shift
	local title=""
	local backtitle=""
	local result
	local status

	local text="$1"
	shift

	if [ $# -ge 1 ]; then
		title="$1"
		shift
	fi

	if [ -n "$BACKTITLE" ]; then
		backtitle="$BACKTITLE"
	fi

	$DIALOG_TEST whiptail $DIALOG_OPTIONS --title "$title" \
     --backtitle "$backtitle" "$type" "$text " 0 0 "$@" 2>&1 1>$ttydev
	
	return $?
}

# Display a file.
#
# fileBox filename [title]
#
fileBox () {
	dialogBox --textbox "$1" "$2"
}

msgBox () {
	dialogBox --msgbox "$1" "$2"
}

infoBox () {
	dialogBox --infobox "$1" "$2"
}

yesNoBox () {
	dialogBox --yesno "$1" "$2"
	return $?
}

inputBox () {
	dialogBox --inputbox "$1" "$2" "$3"
	return $?
}

# menu text title tag1 item1 ...
menu () {
	local text="$1"
	shift
	local title="$1"
	shift
	dialogBox --menu "$text" "$title" 0 "$@"
	return $?
}

# menu text title tag1 item1 status1 ...
checklist () {
	local text="$1"
	shift
	local title="$1"
	shift
	dialogBox --checklist "$text" "$title" 0 "$@"
	return $?
}

# menu text title tag1 item1 status1 ...
radiolist () {
	local text="$1"
	shift
	local title="$1"
	shift
	dialogBox --radiolist "$text" "$title" 0 "$@"
	return $?
}

build_lists () {
	installed_module_list="`$sed -e '/#.*$/d' -e 's/[ 	].*$//' \
	 < $MODULESFILE`"
	return 0;
}

in_list ()
{
	local a=$1
	local i
	shift

	for i in $*; do
		if [ $i = $a ]; then
			return 0
		fi
	done
	return 1
}

module_is_installed () {
	in_list $1 "$installed_module_list"
	local status=$?
	return $status
}

module_args () {
	local module=$1

	zcat < $ModuleHelp/descr.gz | $sed -e 's/^#.*//' \
		| (IFS=\n; retcode=0;
		    while read line ; do
			case $line in
			"Module: $module")
				while read line; do
					case "$line" in
					" "*)
						echo "$line"
						;;
					"NoParams:")
						retcode=3
#						retcode=2
						;;
					*)
						return $retcode
						;;
					esac
				done
				return $retcode
			esac
		done
		return 1)
	return $?;
}

module_summary () {
	local summary=""
	local modulevarname=`mkmodulevarname $1`

	eval "summary=$`echo summary_$modulevarname`"
	echo -n "$summary".
}

build_module_directory_menu () {
	local directory="$1"
	local list

	if [ $Source = floppy ]; then
		eval "list=$`echo dir_content_$directory`"
	else
		list="$Dir_Prefix/$directory/*.o"
	fi

	for i in $list; do
		local module="`echo $i | $sed -e 's:^.*/::' -e 's/\.o$//'`"
		if [ "$module" != '*' ]; then
			local selected=" -"

			if module_is_installed $module; then
				selected=" +"
			fi

			echo -n \"
			echo -n $module |$sed -e 's/^\(...............\).*$/\1/'
			echo -n \" \"$selected" "
			module_summary $module
			echo \" \\
		fi
	done
	echo ""
}

module_directory_menu () {
	local directory="$1"
	local text="$2"
	local title="$3"

	while true; do

		build_lists

		echo 'menu "$text" "$title" \' > $TempFile.1
		echo '"$msg_Exit" "   $msg_Finished_these" \' >> $TempFile.1
		echo '" " " " \' >> $TempFile.1
		
		infoBox "$msg_Please_wait_l" "$msg_Please_wait"

		build_module_directory_menu $directory >> $TempFile.1

		local result
		result="$(. $TempFile.1)"
		if [ $? -ne 0 ]; then return 1; fi

		case "$result" in
		" ")
			;;
		"$msg_Exit")
			return 0;;
		*)
			if [ $Source = floppy ]; then
				local list
				eval "list=$`echo dir_content_$directory`"
				for i in $list; do
					case "$i" in
					$result*)
						result=$i;
						break;
						;;
					esac
				done
			else
				set `echo $Dir_Prefix/$directory/$result*.o`
				result=`echo "$1" | \
					$sed -e 's/^.*\///' \
						-e 's/\.o//'`
			fi

			edit_module "$result"
			;;
		esac
		${rm} -f $TempFile.1
	done
}

edit_module () {
	local module="$1"
	local help="`module_summary $module`"
	local selected=" -"
	local text="$help
$msg_module_not_installed"

	if module_is_installed $module; then
		selected=" +"
		text="$help
$msg_module_installed"
	fi

	cat > $TempFile.2 << EOF
	menu "$text" "Module $module $selected" \\
	"$msg_Exit" "$msg_Finished_these" \\
EOF
	
	if [ "$selected" = " +" ]; then
		echo '"$msg_Remove" "$msg_Remove_l" \' >> $TempFile.2
	else
		echo '"$msg_Install" "$msg_Install_l" \' >> $TempFile.2
	fi

	echo "" >> $TempFile.2

	local result
	result="$(. $TempFile.2)"
	local status=$?
	${rm} -f $TempFile.2

	if [ $status -ne 0 -o -z "$result" ]; then return 1; fi

	case "$result" in
	"$msg_Exit")
		return 0
		;;
	"$msg_Install")
		install_module $module
		return 0
		;;
	"$msg_Remove")
		remove_module $module
		return 0
		;;
	esac
	return 1
}

parse_arguments ()
{
        local module="$1"
	for i in $MODUTILSDIR/* ; do
		if [ -d $i ]; then
			continue
		fi
		cat $i | \
			( while read line; do \
				set -- $line; \
				if [ "$1" = options -a "$2" = "$module" ]; then \
					shift; shift; echo $@; break; \
				fi; \
			done)
	done
}


update_conf_modules ()
{
	local module="$1"
	local arguments="$2"
	local done=""
	local modd=""

	for i in $MODUTILSDIR/* ; do
		if [ -d $i ]; then
			continue
		fi
		cat $i | \
		( while read line; do \
			set -- $line; \
			if [ "$1" = options -a "$2" = "$module" ]; then \
				if [ -n "$arguments" ] ; then \
					shift; shift; modd=true; done=true; \
					echo options $module "$arguments" ; \
				fi; \
			else echo $line; \
			fi; \
	    	done; \
		)   > $TempFile.4
		if [ $modd ]; then
			cat $TempFile.4 > $i
			modd=""
		fi
	done
	${rm} -f $TempFile.4
	if [ -z "$done" -a -n "$arguments" ]; then
		if [ -f $MODCONFFILE ]; then
			echo options $module "$arguments" >> $MODCONFFILE
		else
			echo options $module "$arguments" > $MODCONFFILE
			chown 0.0 $MODCONFFILE
			chmod 644 $MODCONFFILE
		fi		
	fi;
	sync
	$Target/sbin/update-modules
	sync
}

edit_arguments ()
{
	local module="$1"
	local old_arguments="`parse_arguments $module`"

	local arguments
	module_args $module >$TempFile.3
	local status=$?
	if [ $status -eq 1 ]; then
		cat > $TempFile.2 << EOF
msgBox "$msg_doc_unavailable" "$msg_Error"
EOF
		arguments="`. $TempFile.2`"
#		return 1
	elif [ $status -eq 2 ]; then
		echo -n "msgBox \"" >$TempFile.2
		cat $TempFile.3 >>$TempFile.2
		echo "\" \"Module info\"">>$TempFile.2
		arguments="`. $TempFile.2`"
		return 0
	fi
	if [ $status -ne 3 ]; then
		echo -n "inputBox \"" >$TempFile.2
		cat $TempFile.3 >>$TempFile.2 
		echo "">>$TempFile.2
		echo "$msg_enter_arguments_l\" \\" >>$TempFile.2
		echo "\"$msg_enter_arguments\"" >>$TempFile.2

		arguments="`. $TempFile.2`"
		if [ $? -ne 0 ]; then return 1; fi
	else
		arguments=''
	fi

	arguments=`echo $arguments|$sed 's/ *= */=/g'`
	if [ "$old_arguments" != "$arguments" ]; then
		update_conf_modules $module "$arguments"
	fi
}

install_module () {
	local module="$1"
	sync

	edit_arguments $module
	if [ $? -ne 0 ]; then return 1; fi	

	echo $clear$bold"`eval echo \\\"$msg_Installing_module\\\"`"$norm
	echo ""
	sync

	get_and_insmod $module
	local status=$?

	echo ""
	if [ $status -eq 0 ]; then
		echo "$msg_Installation_succeeded"
		echo "$module" >> $MODULESFILE
	else
		echo "$msg_Installation_failed"
	fi

	echo ""
	echo $bold"$msg_Please_press_ENTER"$norm
	local reply
	read reply

}

get_and_insmod () {
	local module=$1
	local file
	local i

	case $Source in
	floppy)
		echo -n $clear "`eval echo \\\"$msg_Extracting_module\\\"`"
		if [ ! -f /floppy/modules.tgz ]; then
			write_it_down "$msg_tgz_does_not_exist"
		fi
		(cd /; zcat < /floppy/modules.tgz | $extract \*/$module.o)
		file="/lib/modules/*/*/$module.o"
		echo "$msg_done"
		depmod -a
		modprobe $module
		local status=$?
		${rm} -f $file
		;;
	mounted)
		modprobe $module
		local status=$?
		;;
	esac

	for i in $Run_Shell; do
		local script
		local modulevarname=`mkmodulevarname $1`
		eval "script=$`echo shell_${i}_$modulevarname`"
		if [ -n "$script" ]; then
			echo 
			echo "`eval echo \\\"$msg_Executing_postinst\\\"`"
			echo script: $script
			eval $script
			if [ $? -ne 0 ]; then
				write_it_down "`eval echo \\\"$msg_postinst_failed\\\"`"
			fi
			echo "`eval echo \\\"$msg_postinst_done\\\"`"
		fi
	done
	return $status
}

remove_module () {
	sync
	local module="$1"

	echo $clear$bold"`eval echo \\\"$msg_Removing_module\\\"`"$norm
	echo ""
	sync
	modprobe -r $module
	if [ $? -ne 0 ]; then
		write_it_down "`eval echo \\\"$msg_not_removed\\\"`"
		return 1
	fi
	${rm} -f $MODULESFILE.tmp
	$sed -e /^$module\$/d < $MODULESFILE >$MODULESFILE.tmp
	if [ $? -ne 0 ]; then return 1; fi
	chown 0.0 $MODULESFILE.tmp
	chmod 644 $MODULESFILE.tmp
	sync
	${rm} -f $MODULESFILE.old
	ln $MODULESFILE $MODULESFILE.old
	mv $MODULESFILE.tmp $MODULESFILE
	sync

	return 0
}

interactive_main () {

	local text="$msg_Select_Category_l"

	echo 'menu "$text" "$msg_Select_Category" \' > $TempFile

	echo '"$msg_Exit" "$msg_Finished_these" \'  >> $TempFile
	echo '" " " " \' >> $TempFile

	local directory
	for directory in $dir_descrs; do
		if [ ! -d $Dir_Prefix/$directory -a \
				$Source = mounted ]; then 
			continue;
		fi

		if [ -n "$Restrict_Section" ]; then
			if in_list $directory $Restrict_Section; then
				true
			else
				continue
			fi
		fi

		local help=""
		local summary=""

		eval "summary=$`echo dir_descr_$directory`"

		echo "\"$directory\"" \\ >> $TempFile
		echo "\"$summary."\" \\ >> $TempFile
	done
	echo "" >> $TempFile

	while true; do
		local directory status
		if [ -n "$One_Restricted_Section" ]; then
			directory=$One_Restricted_Section
		else
			directory="`. $TempFile`"
			if [ $? -ne 0 ]; then return 1; fi
		fi

		case "$directory" in
		" ")
			;;
		"$msg_Exit")
			return 0;;
		*)
			module_directory_menu "$directory" \
			 "$msg_Select_modules_l" "`eval echo \\\"$msg_Select_modules\\\"`"
			if [ -n "$One_Restricted_Section" ]; then
				return 0;
			fi
			;;
		esac
	done
	${rm} -f $TempFile
}

check_conf_modules ()
{
	local HEADER="### This file is automatically generated by update-modules"
	if [ -f $CFGFILE ]; then
		if [ ! "`$sed -n 1p $CFGFILE |$sed -n \"/^$HEADER/p\"`" ]; then 
                	echo "Error: the current $CFGFILE is not automatically generated."
                        echo "Use \"update-modules force\" to force (re)generation."
			exit 1
                fi
        fi
}

Source=mounted

ModuleHelp=/usr/lib/module_help

while [ $# -ne 0 ]; do
	case $1 in
	--source)
		Source=$2
		shift
		;;
	--target)
		Target=$2
		shift
		;;
	--libdir)
		ModuleHelp=$2
		shift
		;;
	--restrict-section)
		Restrict_Section="$Restrict_Section $2"
		shift
		;;
	--exclude-section)
		Exclude_Section="$Exclude_Section $2"
		shift
		;;
	--load-after)
		Load_After="$Load_After $2"
		shift
		;;
	--load-before)
		Load_Before="$Load_Before $2"
		shift
		;;
	--load-only)
		Load_Only="$Load_Only $2"
		shift
		;;
	--run-shell)
		Run_Shell="$Run_Shell $2"
		shift
		;;
	--tty)
		ttydev=$2
		shift
		;;
	*)
		source_eval
		write_it_down "$msg_Invalid_option"
	esac
	shift
done

source_eval

KernelVersion=$(third `cat /proc/version`)
if [ $? -ne 0 -o -z "$KernelVersion" ]; then
	msgBox "$msg_kernel_version_problem" "$msg_Problem"
	return 1
fi

Dir_Prefix=$Target/lib/modules/$KernelVersion

CFGFILE=/etc/conf.modules
MODULESFILE=/etc/modules
MODUTILSDIR=$Target/etc/modutils
MODCONFFILE=$MODUTILSDIR/modconf

check_conf_modules

if [ $Source = floppy ]; then
	if [ -f $ModuleHelp/modcont ]; then
		. $ModuleHelp/modcont
	else
		echo "$msg_Cannot_open $ModuleHelp/modcont"
		exit 1
	fi
else
	dir_descrs=""
	for i in `cd $Dir_Prefix; echo *`; do
		if [ -d $Dir_Prefix/$i -a \
			-f `first $Dir_Prefix/$i/*.o ` ]; then
			if [ -n "$Exclude_Section" ] && 
                       	   in_list $i $Exclude_Section ; then
				true
                	else
				dir_descrs="$dir_descrs $i"
			fi
		fi
	done
fi

s=`second $Restrict_Section`
if [ -n "$Restrict_Section" -a -z "$s" ]; then
    One_Restricted_Section=`first $Restrict_Section`
fi

for i in $Load_Before; do
	get_and_insmod $i;
done

if [ -z "$Load_Only" ]; then
	interactive_main
else
	Load_After=$Load_Only
fi

for i in $Load_After; do
	get_and_insmod $i
done

${rm}  -f $TempFile $TempFile.1 $TempFile.2 $TempFile.3 $TempFile.4
exit 0
