#!/bin/sh
#
# Termwrap detects the type of terminal that it is run on, and the language
# the user is using, and sets up the terminal for that language. This is
# useful for languages (e.g., Japanese) where a special program is needed
# to display that language at the console.
#
# Termwrap is used to run programs including base-config on the
# second-stage install.
#
# This is really something of a hack, since once termwrap is done the user
# still gets a standard login prompt and is no longer shielded by
# termwrap.

######################################################################
##	Display usage if no argument.
######################################################################
if [ -z "$1" ]; then
	echo "usage: $0 [-nnt] <command> [...]"
	echo "-nnt: don't run another terminal"
	exit 0
fi

######################################################################
##	Some functions
######################################################################

# Get a variable from the debconf database of the first stage installer.
get_db () {
	DI_DB=/var/log/debian-installer/cdebconf/questions.dat
	if [ -e $DI_DB ]; then
		debconf-copydb d-i stdout -c Name:d-i -c Driver:File \
		               -c Filename:$DI_DB -c Name:stdout \
			       -c Driver:Pipe -c InFd:none \
			       --pattern="^$1$" | \
		grep ^Value: | cut -d ' ' -f 2
	fi
}

info() {
	echo "info: $@"
	logger -p user.info -t termwrap "info: $@"
}
warning() {
	echo "warning: $@"
	logger -p user.warning -t termwrap "warning: $@"
}
error() {
	echo "error: $@"
	logger -p user.crit -t termwrap "error: $@"
}

unset_lang_language() {
	# The requested charset is not supported.  Do not use the
	# given locale.	 If it was used, the translated texts might be
	# completely unreadable in the current terminal

	if [ "$LANG" ] ; then
		warning "Disabling unsupported locale '$LANG'."
		unset LANG
		unset LC_ALL
		unset LC_COLLATE
		unset ENCODING
	fi
	if [ "$LANGUAGE" ] ; then
		warning "Disabling unsupported language list '$LANGUAGE'."
		unset LANGUAGE
	fi
}

try_load_charset() {
	ENCODING=$1
	ACM=$2
	FONT=$3
	
	# Load character map into the console
	# ACM name is from /usr/share/consoletrans/$ACM.acm.gz
	case $TERMINAL in
	    console)
		info "Switching console charset mapping to $ENCODING"
		for vc in `seq 0 6` 
		do
			consolechars --tty=/dev/tty$vc -f $FONT
			charset --tty=/dev/tty$vc G0 $ACM
		done
		;;
	    *)
		error "Unable to switch charset mapping to $ENCODING with terminal '$TERMINAL'"
		unset_lang_language
		;;
	esac
}

try_load_fb() {
	# Load framebuffer module (debian-installer/framebuffer value is null(not true!) or false.)
	if [ "$(get_db debian-installer/framebuffer)" != "false" ]; then
		case $(dpkg --print-installation-architecture) in 
		    i386)
			case $(uname -r) in
			2.6.*)
				(modprobe -q vesafb >/dev/null 2>&1 && modprobe -q fbcon >/dev/null 2>&1) || (modprobe -q vga16fb >/dev/null 2>&1 && modprobe -q fbcon >/dev/null 2>&1)
				;;
			*)
				modprobe -q vesafb >/dev/null 2>&1 || modprobe -q vga16fb >/dev/null 2>&1
				;;
			esac
                      ;;
		esac
	fi
}

######################################################################
##	Generate the locale data files if missing
######################################################################

# Keep the locale info in the _INST variables until they are verified.
if [ "$LANG" ]; then
	LANG_INST=$LANG
	unset LANG
else
	LANG_INST=$(get_db debian-installer/locale)
fi
if [ "$LANGUAGE" ]; then
	LANGUAGE_INST=$LANGUAGE
	unset LANGUAGE
fi

if [ "$LANG_INST" ]; then
	localeconf=/etc/locale.gen
	tmpfile=`/bin/tempfile`

	# Use this to detect if the 'locales' package is installed
	localegen=`which locale-gen`

	validlocale $LANG_INST 2> /dev/null > $tmpfile || true
	read locale charset < $tmpfile || true
	rm -f $tmpfile
	unset tmpfile

	if ! validlocale $LANG_INST > /dev/null 2>&1; then
		# Hm, should we install the 'locales' package if it is missing?
		if [ "$localegen" ] && [ -x $localegen ]; then
			if grep -q "^$locale " /usr/share/i18n/SUPPORTED; then
				if ! grep -q "^$locale $charset$" $localeconf 2>/dev/null; then
					echo "$locale $charset" >> $localeconf
					$localegen | sed 's/^/termwrap: locale-gen: /' || true
				fi
			else
				# Try without euro since d-i currently gets
				# this wrong for some locales.
				locale=$(echo "$locale" | sed 's/@euro$//')
				if grep -q "^$locale " /usr/share/i18n/SUPPORTED; then
					LANG_INST=$locale
					if ! grep -q "^$locale $charset$" $localeconf 2>/dev/null; then
						echo "$locale $charset" >> $localeconf
						$localegen | sed 's/^/termwrap: locale-gen: /' || true
					fi
				fi
			fi
		else
			warning "Package 'locales' not installed.  Unable to generate locale '$LANG'"
		fi

		# Make sure the locale is valid
		if validlocale $LANG_INST > /dev/null 2>&1 ; then
			if [ "$LANGUAGE_INST" ]; then
				LANGUAGE=$LANGUAGE_INST
				export LANGUAGE
				unset LANGUAGE_INST
			fi
			LANG=$LANG_INST
			LC_ALL=$LANG_INST
			LC_COLLATE=C
			export LANG LC_ALL LC_COLLATE
			unset LANG_INST
		else
			unset LANG_INST
			unset LANGUAGE_INST
		fi
	else
		if [ "$LANGUAGE_INST" ]; then
			LANGUAGE=$LANGUAGE_INST
			export LANGUAGE
			unset LANGUAGE_INST
		fi
		LANG=$LANG_INST
		LC_ALL=$LANG_INST
		LC_COLLATE=C
		export LANG LC_ALL LC_COLLATE
		unset LANG_INST
	fi

	unset locale
	unset charset
	unset localeconf
	unset localegen
fi

######################################################################
##	Recognize terminal type.
######################################################################
case `/usr/bin/tty` in
/dev/console)
	# Use fgconsole to detect if it is a serial console.
	if command -v fgconsole >/dev/null 2>&1 && [ serial = "$(fgconsole)" ] ; then
		TERMINAL=serial
	else
		TERMINAL=console
	fi

	# Or try another way, copied from d-i udeb rootskel.
	#case `readlink /proc/self/fd/0` in
	#        /dev/console)
	#		TERMINAL=serial
	#		;;
	#	*)
	#		TERMINAL=console
	#		;;
	#esac

	;;
/dev/tty|/dev/tty[1-9]*|/dev/vc/*)
	TERMINAL=console
	;;
/dev/tty[p-za-e]*|/dev/pts/*)
	TERMINAL=pseudo
	if [ ! -z "$DISPLAY" ]; then
		TERMINAL=x
	else
		case $TERM in
		rxvt|xterm*|kterm)	TERMINAL=x;;
		esac
	fi
	;;
/dev/tty[A-Z]*|/dev/cu*)
	TERMINAL=serial
	;;
esac

# If the default linux kernel TERM setting is used for serial consoles, change
# it to vt100.  This assume serial consoles understand vt100.  Almost
# all terminal programs can handle vt100.
if [ serial = "$TERMINAL" ] && [ linux = "$TERM" ] ; then
	TERM=vt100
fi

case $TERM in
dumb)	TERMINAL=dumb
esac

export TERMINAL

case $(dpkg --print-installation-architecture) in 
i386)	/bin/grep -q 9800 /proc/version && SUBARCH=pc9800 ;;
esac

######################################################################
##	Select suitable terminal as wrapper.
######################################################################
WRAPPER=""
WRAPPER_OPTION=""

# For this to work, the current locale must be valid.  The block
# generating the locale should have taken care of that.  If it isn't
# valid, the output is 'ANSI_X3.4-1968' (at least on my test machine
# 2002-02-09), and the case test below should unset both LANG and
# LOCALE
ENCODING=$(locale charmap)

case $ENCODING in
ANSI_X3.4-1968)
	unset LANG
	unset LOCALE
	unset ENCODING

	# Linux console sucks, always load ISO-8859-1 charset mapping
	try_load_charset "C" iso01 lat0-sun16
	;;
ISO-8859-1)
	# Linux console sucks, always load ISO-8859-1 charset mapping
	try_load_charset "$ENCODING" iso01 lat0-sun16
	;;
ISO-8859-2)
	# Load ISO-8859-2 charset mapping into console
	try_load_charset "$ENCODING" iso02 lat2-sun16
	;;
ISO-8859-7)
	# Load ISO-8859-7 charset mapping into console
	try_load_charset "$ENCODING" iso07 iso07.f16
        ;;
ISO-8859-9)
	# Load ISO-8859-9 charset mapping into console
	try_load_charset "$ENCODING" iso09 ter-916f
	;;
ISO-8859-13)
	# Load ISO-8859-13 charset mapping into console
	try_load_charset "$ENCODING" iso13 LatArCyrHeb-16
	;;
ISO-8859-15)
	# Load ISO-8859-15 charset mapping into console
	try_load_charset "$ENCODING" iso15 lat0-sun16
	;;
KOI8-U)
	# Load KOU8-U charset mapping into console
	if [ -x /usr/bin/cyr ]; then
		/usr/bin/cyr -s uni -f 16 -e koi8-u ua_ms ctrl_shift_toggle
	else
		try_load_charset "$ENCODING" koi8u koi8u_8x16
	fi
	;;
eucJP|EUC-JP)
	# Japanese
	case $TERMINAL in
	x)
		WRAPPER="/usr/X11R6/bin/krxvt"
		WRAPPER_OPTION="-e"
		;;
	console)
		if [ "$SUBARCH" != pc9800 ] && [ "$TERMINAL" = console ]; then
			# Any platform except PC9800 require jfbterm
			# to display japanese fonts on console.
			try_load_fb
			WRAPPER="/usr/bin/jfbterm"
			WRAPPER_OPTION="-q -c other,EUC-JP,iconv,UTF-8 -e"
		fi
		;;
	# On pseudo and serial, we can't tell
	# if the terminal can display japanese fonts...
	esac
	;;
KOI8-R)
	# Russian
	case $TERMINAL in
	console)
		if [ -x /usr/bin/cyr ]; then
			/usr/bin/cyr -s uni -f 16 -e koi8-r --ttys=/dev/tty1 ru_ms ctrl_shift_toggle
		else
			# Don't try to install in russian withour cyrrilic support on console
			LANG=C
			LC_ALL=C
			unset LC_COLLATE
		fi
		;;
	esac
	;;
UTF-8)
	# Enable UTF-8 in console
	case $TERMINAL in
	console)
		try_load_fb
		WRAPPER="/usr/bin/jfbterm"
		WRAPPER_OPTION="-q -e"
		;;
	esac
	;;
*)
	# Fallback jfbterm
	# Mainly Korean, Chinese, Greek, Bulgarian
	case $TERMINAL in
	console)
		try_load_fb
		WRAPPER="/usr/bin/jfbterm"
		WRAPPER_OPTION="-q -c other,$ENCODING,iconv,UTF-8 -e"
		;;
	esac
	;;
esac

if [ "$1" = "-nnt" ]; then
	WRAPPER=""
	shift
fi

######################################################################
##	Execute Wrapper.
######################################################################
if [ ! -z "$WRAPPER" ] && [ -x "$WRAPPER" ]; then
	$WRAPPER $WRAPPER_OPTION /bin/true && exec $WRAPPER $WRAPPER_OPTION $@
	
	# Fallback to C
	case $ENCODING in
	ISO-8859-1|ISO-8859-2|ISO-8859-9|ISO-8859-13|ISO-8859-15|KOI8-R|KOI8-U)
		# Nothing to do
		;;
	*)
		# Unset LANG
		unset_lang_language
		;;
	esac
fi

$@

# The console font loaded before termwrap started.  No idea how to
# detect it, so we assume it was ISO-8859-1.
ORIG_ENCODING="ISO-8859-1"
ORIG_ACM="iso01"
ORIG_FONT="lat0-sun16"

case $ENCODING in
ISO-8859-1)
	# Nothing to do, using default config
	;;
ISO-8859-2)
	# Unload ISO-8859-2 charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
	;;
ISO-8859-7)
	# Unload ISO-8859-7 charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
	;;
ISO-8859-9)
	# Unload ISO-8859-9 charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
        ;;
ISO-8859-13)
	# Unload ISO-8859-13 charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
	;;
ISO-8859-15)
	# Unload ISO-8859-15 charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
	;;
KOI8-R|KOI8-U)
	# Unload KOI8-R or KOI8-U charset mapping, by loading ISO-8859-1 instead
	try_load_charset $ORIG_ENCODING $ORIG_ACM $ORIG_FONT
	;;
UTF-8)
	# Disable UTF-8 in console
	#if [ "$TERM" = console ] ; then
	#	echo -ne "\033%@"
	#else
	#	: # Nothing to do
	#fi
	;;
*)
	# Nothing to do
	;;
esac
