#!/bin/sh

[ $(id -u) -eq 0 ] || exec su -c "$0 $@"

DIALOG=dialog

ddq()
{
	dd $@ 2> /dev/null
}

get()
{
	od -v -j $1 -N ${4:-${3:-2}} -t u${3:-2} -w${3:-2} -An "$2" 2>/dev/null ||
	hexdump -v -s $1 -n ${4:-${3:-2}} -e "\"\" 1/${3:-2} \" %d\n\"" "$2"
}

bytes2bin()
{
	for i in $@ ; do
		printf '\\\\x%02X' $(($i&255))
	done | xargs echo -en
}

words2bin()
{
	for i in $@ ; do
		printf '\\\\x%02X\\\\x%02X' $(($i&255)) $((($i>>8)&255))
	done | xargs echo -en
}

gettazboot()
{
	echo "Creating $(basename $1) ..."
	O=$(($(get 64 "$ISO") - 0xC0))
	L=$(($(get 20 "$ISO") - 0xC0 - $(get 24 "$ISO") - $O))
	S=$((32+$L))
	P=$((($S+511)/512))
	E=$((4096-(32*$P)))
	words2bin 0x5A4D $(($S%512)) $P 0 2 $E -1 $((${2:-0}-16)) \
			-2 0 256 -16 28 0x6C53 0x5469 0x7A61 > $1
	ddq bs=1 count=$L skip=$(echo $O) if="$ISO" >> $1
}

uncpio()
{
	[ -s "$1" ] || return
	echo -en "\n Extracting $(basename $1) ..."
	case $(get 0 $1) in
	*35615)	( zcat || gunzip ) ;;
	*14333) unxz ;;
	*\ 93)	unlzma ;;
	*)	cat ;;
	esac < $1 | ( cd ${2:-/} ; cpio -idmu > /dev/null 2>&1 )
}

dotwait()
{
	echo -n "${1:-Install filesystem}.."
	touch /tmp/wait
	[ "$REQUEST_URI" ] && return
	while [ -e /tmp/wait ]; do
		echo -n "." > /dev/tty
		sleep 1
	done &
}

getuuid()
{
	dev=$(mount | sed "/ $(echo $mnt | sed 's|/|\\/|g') /!d;s/ .*//;s|/dev/||;q")
	[ "$dev" ] &&
	blkid | sed "/$dev:/!d;s/.* UUID=.\\([^ ]*\\)\".*/\\1/" ||
	echo "/dev/hda1"
}

tazusbinitfs()
{
	PAD=$(($(stat -c %s $1) % 4))
	[ $PAD -ne 0 ] && ddq if=/dev/zero bs=1 count=$((4 - $PAD)) >> $1
	mkdir -p /tmp/fs$$/etc /tmp/fs$$/lib /tmp/fs$$/home
	cp -a /etc/locale.conf /tmp/fs$$/etc 2> /dev/null
	cp -a /etc/keymap.conf /tmp/fs$$/etc 2> /dev/null
	cat > /tmp/fs$$/init1 <<EOT
#!/bin/sh
sed -i 's|sbin/init|init2|' /init
exec /init
EOT
	cat > /tmp/fs$$/init2 <<EOT
#!/bin/sh

mount -t proc /proc /proc
for i in /lib/*.ko* ; do insmod \$i 2> /dev/null ; done; sleep 2
v=\$(sed '/\\/home=/!d;s|.*/home=\\([^ ]*\\).*|\\1|' /proc/cmdline /cmdline 2> /dev/null)
mount / -o remount,rw
mkdir /mnt/dos
rm -f /cmdline 2> /dev/null
mount / -o remount,ro
mnt=/mnt/dos/\${v#*/}
dev=\$( (blkid /dev/[sh]d* || blkid) | grep \${v%%/*} | sed 's/:.*//;q')
echo "Mount \$dev in /mnt/dos for \$v..." | tee -a /run/boot.log
mount \$dev /mnt/dos
if [ ! -d /mnt/dos/slitaz ]; then
	umount /mnt/dos 2> /dev/null
	(blkid /dev/[sh]d* || blkid) | while read dev line; do
		case "\$line" in
		*ntfs*|*vfat*|*msdos*) ;;
		*) continue ;;
		esac
		mount \${dev%:} /mnt/dos
		[ -d /mnt/dos/slitaz ] && break
		umount /mnt/dos
	done
fi
$([ "$2" ] || echo '# ')mount.posixovl -F \$mnt -- -oallow_other -odefault_permissions -osuid
mount --bind \$mnt /home
umount /proc
exec /sbin/init
EOT
	chmod 755 /tmp/fs$$/init?
	( cd /tmp/fs$$ ; find * | cpio -o -H newc ) | gzip -9 >> $1
	rm -rf /tmp/fs$$
}

mkinitrd()
{
	echo -en "\nCreating $(basename $1) "
	fs=/tmp/fs$$
	for i in bin lib dev proc tmp mnt etc ; do
		mkdir -p $fs/$i
	done
	for i in /dev/console /dev/null /dev/tty /dev/tty0 /dev/tty1 /dev/tty2 \
		 /dev/fuse /dev/hd* /dev/sd* ; do
		cp -a $2$i $fs/dev/
	done
	for i in /bin/busybox $(which mount.posixovl) $(which blkid); do
		cp $(LD_TRACE_LOADED_OBJECTS=1 /lib/ld*.so $i | \
		sed 's|.*=> \(.*/lib/l[^ ]*\).*|\1|;/^\//!d') $fs/lib
		cp $i $fs/bin
	done
	cp -a /lib/ld-* $fs/lib
	for i in $(busybox | sed '/Current/,$!d'); do
		[ -e $fs/bin/${i%,} ] || ln -s busybox $fs/bin/${i%,}
	done
	ln -s /proc/mounts $fs/etc/mtab
	sed 's/ .*//' /proc/modules | while read mod ; do
		find /lib/modules/ | grep $mod.ko | \
			sed 's|.*|cp & $fs/lib|' | sh
	done
	cat > $fs/init <<EOT
#!/bin/sh

arg()
{
	grep -q \$1 /proc/cmdline &&
	val="\$(sed "s/.*\$1=\\([^ ]*\\).*/\\1/" < /proc/cmdline)" &&
	echo "\$2 \$val"
}

mount -t proc /proc /proc
  arg debug "shell" && debug=true && set -x
for i in /lib/*.ko* ; do insmod \$i 2> /dev/null ; done; sleep 2
arg mount "Mount device"
mount \$( (blkid /dev/[sh]d* || blkid) | grep \$val | sed 's/:.*//;q') /mnt
arg subroot "Change root to directory"
if [ -d /mnt/\$val ]; then
	umount /mnt 2> /dev/null
	(blkid /dev/[sh]d* || blkid) | while read dev line; do
		case "\$line" in
		*ntfs*|*vfat*|*msdos*) ;;
		*) continue ;;
		esac
		mount \${dev%:} /mnt
		[ -d /mnt/\$val ] && break
		umount /mnt
	done
fi
$([ "$3" ] || echo '# ')mount.posixovl -F /mnt/\$val -- -oallow_other -odefault_permissions -osuid
mount --bind /mnt /mnt/\$val/mnt/dos
mount -o size=0 -t tmpfs tmpfs /mnt/\$val/mnt/dos/\$val
LDSO=\$(ls /mnt/\$val/lib/ld-* | sed q)
export LD_LIBRARY_PATH=\$val/lib:\$val/usr/lib:/lib
  [ "$debug" = "true" ] && sh
umount /proc
exec /bin/switch_root /mnt \${LDSO#/mnt/} \$val/usr/sbin/chroot \$val /sbin/init
EOT
	chmod +x $fs/init
	( cd $fs ; find * | cpio -o -H newc ) | lzma e $1 -si 2> /dev/null
	rm -rf $fs /tmp/wait
}

ls_r()
{
	ls -r $@ 2> /dev/null || ls $@
}

doinstall()
{
	unset useposixovl
	blkid | grep $(df $mnt | sed '$!d;s/ .*/:/') | \
		grep -qiE "(msdos|vfat|ntfs)" && useposixovl=YES
	case "$mnt" in
	*mkzip*) useposixovl=YES
	esac
	mkdir -p $mnt/slitaz/boot $mnt/slitaz/mnt/dos
	[ "$useposixovl" ] &&
	if ! mount.posixovl -F $mnt/slitaz -- \
		-oallow_other -odefault_permissions -osuid; then
		echo "Can't install SliTaz. Abort."
		sleep 5
		return 1
	fi
	dotwait "Install root filesystem in /slitaz.."
	if [ "$1" ]; then
		ls_r $media/boot/rootfs*gz | \
		xargs cat > $mnt/slitaz/boot/rootfs.gz
		tazusbinitfs $mnt/slitaz/boot/rootfs.gz $useposixovl
		initrd=rootfs.gz
		extraargs="/home=$(getuuid)/slitaz rdinit=/init1"
	else
		for i in $(ls_r $media/boot/rootfs*gz); do
			uncpio $i $mnt/slitaz
		done
		for i in $packages_list; do
			tazpkg get-install $i --root=$mnt/slitaz
		done
		for i in $packages_dir/*.tazpkg; do
			[ -s "$i" ] &&
			tazpkg install $i --root=$mnt/slitaz
		done
		cp -a /etc/locale.conf $mnt/slitaz/etc 2> /dev/null
		cp -a /etc/keymap.conf $mnt/slitaz/etc 2> /dev/null
		mkinitrd $mnt/slitaz/boot/initrd $mnt/slitaz $useposixovl
		initrd=initrd
		extraargs="mount=$(getuuid) subroot=slitaz"
	fi
	echo -en "\nInstall boot files..."
	for i in $media/boot/bzImage* $media/boot/*pxe* \
		$media/boot/isolinux/he* $media/boot/isolinux/opt* \
		$media/README $media/boot/memtest* ; do
		[ -s $i ] && cp $i $mnt/slitaz/boot
	done
	for i in $mnt/slitaz/boot/memtest $mnt/slitaz/boot/*pxe* ; do
		[ $(get 0 $i 2> /dev/null || echo 0) -eq 23117 ] &&
		mv $i $i.exe
	done
	bzimage=$(cd $mnt/slitaz/boot ; ls bzimage*)
	gettazboot $mnt/slitaz/boot/tazboot.exe	# autoappend 64 suffix
	unix2dos > $mnt/slitaz/boot/tazboot.cmd <<EOT
kernel=/slitaz/boot/bzimage
initrd=/slitaz/boot/$initrd
rw root=/dev/null $extraargs autologin
EOT
	unix2dos $mnt/slitaz/boot/he* $mnt/slitaz/boot/opt* \
		$mnt/slitaz/boot/README
	[ -d $mnt/slitaz/usr/sbin -a ! -x $mnt/slitaz/usr/sbin/mount.posixovl ] &&
	cp $(which mount.posixovl) $mnt/slitaz/usr/sbin
	if [ "$useposixovl" ] && grep -qs " $mnt " /proc/mounts &&
	   [ ! -d $mnt/boot/grub ]; then
		mkdir -p $mnt/boot/grub
		echo -en "\nInstall grub in /boot/grub..."
		cp -a /usr/lib/grub/*/* $mnt/boot/grub
		cat > $mnt/boot/grub/menu.lst <<EOT
# /boot/grub/menu.lst: GRUB boot loader configuration.

# By default, boot the first entry.
default 0

# Boot automatically after 8 secs.
timeout 8

title Microsoft Windows
	chainloader +1

EOT
		dev=$(grep " $mnt " /proc/mounts | awk '{ print $1 }')
		base=${dev//[0-9]/}
		dd if=$base bs=32k count=1 of=$mnt/boot/grub/$(basename $base)
		cat > $mnt/boot/grub/uninstall-grub.sh <<EOT
#!/bin/sh

[ -s /boot/grub/$(basename $base) ] &&
dd if=/boot/grub/$(basename $base) of=$base
EOT
		grub-install --no-floppy --root-directory=$mnt $base
	fi
	if [ -s $mnt/boot/grub/menu.lst ] &&
	   ! grep -q /slitaz/boot/$bzimage $mnt/boot/grub/menu.lst; then
		echo -en "\nUpdate /boot/grub/menu.lst..."
		cat >> $mnt/boot/grub/menu.lst <<EOT
title SliTaz GNU/Linux $(cat $mnt/slitaz/etc/slitaz-release)
	kernel /slitaz/boot/$bzimage rw root=/dev/null $extraargs autologin
	initrd /slitaz/boot/$initrd

EOT
	fi
	rm -f /tmp/wait
	[ "$useposixovl" ] && umount $mnt/slitaz
	return 0
}

windev()
{
	if [ -b "$1" ]; then
		device=$1
	elif [ "$1" ]; then
		echo "Invalid Linux/Windows partition"
		return 1
	else
		DEV="$(blkid | grep -iE "(msdos|vfat|ntfs|ext[234]|xfs|btrfs)" | sed 's/:.*//;s|/dev/||')"
		[ "$DEV" ] || return
	cat > /tmp/dialog$$ <<EOT
$DIALOG --clear \
	--title " Select your Linux/Windows partition " \
	--menu "\nPlease select the Linux/Windows partition according to its known size.
The data will be kept untouched.\n" \
	17 70 8 \
	$(for i in $DEV ; do
		label="$(blkid | sed "/$i:/!d;s/.*://;s/[^ ]*UUID=[^ ]* //g;s/LABEL=//")"
		echo -n "/dev/$i \"$(($(cat /sys/block/*/$i/size)/2048))MB $label\" "
	done)
EOT
		exec 3>&1
		[ $? -eq 0 ] || return
		device=$(. /tmp/dialog$$ 2>&1 1>&3)
		exec 3>&-
		rm -f /tmp/dialog$$
	fi
	mnt=/tmp/mnt$$
	mkdir -p $mnt && mount $device $mnt
}

extra_packages()
{
	packages_list=
	packages_dir=
	$DIALOG --clear \
		--title " Extra packages " \
		--defaultno --yesno \
"
Do you want to add extra packages ?
" 7 70
	[ $? -eq 0 ] || return
	[ -s /var/lib/tazpkg/packages.txt ] || tazpkg recharge
	if [ -s $media/boot/vmlinuz-$(uname -r) ]; then
		cat > /tmp/dialog$$ <<EOT
$DIALOG --clear \
	--title " Select the packages " \
	--separate-output \
	--cancel-label "Skip" \
	--checklist "Please select the packages you want to install. Try with the first letter." \
	0 0 0 \\
EOT
		awk -F\| '{ printf "%s \"%s\" off ",$1,$3 }' \
			/var/lib/tazpkg/packages.desc >> /tmp/dialog$$
		sh /tmp/dialog$$ 2> /tmp/dialog.out$$
		[ $? -eq 0 ] && packages_list="$(cat /tmp/dialog.out$$)"
	fi
	cat > /tmp/dialog$$ <<EOT
$DIALOG --clear \
	--title "Please select the directory with every custom package to install." \
	--cancel-label "Skip" \
	--dselect $PWD 13 78
EOT
	sh /tmp/dialog$$ 2> /tmp/dialog.out$$
	[ $? -eq 0 ] && packages_dir="$(cat /tmp/dialog.out$$)"
	rm -f /tmp/dialog$$ /tmp/dialog.out$$
}

_install()
{
	extra_packages
	$DIALOG --clear \
		--title " SliTaz UMSDOS way installation " \
		--yes-label "Install" --yesno \
"\nSliTaz will be installed in the subdirectory \\slitaz of the current
Linux/DOS/Windows partition. You can see your files from /mnt/dos.\n\n
You can start SliTaz with \\slitaz\\boot\\tazboot.exe\n\n
To uninstall SliTaz, you have only to remove this directory.
The file \\boot.ini or \\config.sys may be modified too.\n\n
SliTaz may run slowly on the 'UMSDOS way' installation due to the 
posixovl filesystem. The 'TAZUSB way' installation runs faster.\n\n
To do a traditional installation with disk partitioning,
start SliTaz Live with the 'SliTaz RAM boot' menu.\n
" 19 70
	[ $? -eq 0 ] || return
	doinstall
}

readtazbootconf()
{
	kernel="$(sed '/^kernel=/!d;s/.*=//' $mnt/slitaz/boot/tazboot.cmd)"
	initrd="$(sed '/^initrd=/!d;s/.*=//' $mnt/slitaz/boot/tazboot.cmd)"
	cmdline="$(sed '/^kernel=/d;/^initrd=/d' $mnt/slitaz/boot/tazboot.cmd)"
}

bootinstalled()
{
	[ "$(which kexec)" ] || return
	[ -x $mnt/slitaz$1 ] || return
	[ -s $mnt/slitaz/boot/tazboot.cmd ] || return
	readtazbootconf
	kexec -l $kernel --initrd $initrd --command-line "$cmdline" || return
	umount $mnt
	rm -rf $mnt
	quit "kexec -e"
}

mkzip()
{
	device=
	packages_list=
	packages_dir=
	mnt=/tmp/mkzipmnt$$
	mkdir -p $mnt
	$1 $2 || return
	for i in bootlace.com grubinst.exe grldr ; do
		wget -O $mnt/slitaz/boot/$i http://mirror.slitaz.org/boot/$i
	done
	readtazbootconf
	cat > $mnt/slitaz/boot/menu.lst <<EOT
title SliTaz
	kernel $kernel $cmdline
	initrd $initrd

EOT
	while read file title; do
		file=$(ls $mnt/slitaz/boot/*$file* 2> /dev/null)
		[ -s "$file" ] && cat >> $mnt/slitaz/boot/menu.lst <<EOT
title $title
	kernel ${file#$mnt}

EOT
	done <<EOT
memtest	MemTest
pxe	Web boot
EOT
	unix2dos $mnt/slitaz/boot/menu.lst
	unix2dos > $mnt/slitaz/boot/install.txt <<EOT
For DOS users (real mode only):

Start SliTaz with \\slitaz\\boot\\tazboot.exe


For NT/2000/XP users:

1- Move the files grldr and menu.lst into the root directory

C:\\> copy \\slitaz\\boot\\grldr \\
C:\\> copy \\slitaz\\boot\\menu.lst \\

2- Remove boot.ini attributes

C:\\> attrib -r -h -s boot.ini

3- Append the following line to boot.init

C:\\grldr="slitaz"

4- Restore boot.ini attributes

C:\\> attrib +r +h +s boot.ini

See http://diddy.boot-land.net/grub4dos/files/README_GRUB4DOS.txt
and http://xpt.sourceforge.net/techdocs/nix/disk/boot/boot07-GrubForDosInfo/ar01s03.html
EOT
	( cd $mnt ; echo 'See \slitaz\boot\install.txt to launch SliTaz.' | \
	  zip -zr9 $(basename "$ISO" .iso).zip slitaz )
	[ "$(which advzip)" ] &&
	echo "Recompressing $(basename "$ISO" .iso).zip ..." &&
	advzip -z4 $mnt/*.zip
	mv $mnt/*.zip .
	du -h $PWD/$(basename "$ISO" .iso).zip
	umount $mnt
	rm -rf $mnt
}

install()
{
	windev $1 || return
	packages_list=
	packages_dir=
	if [ "$1" ]; then
		doinstall
	else
		_install && bootinstalled /sbin/init
	fi
	umount $mnt
	rm -rf $mnt
}

inst2zip()
{
	if [ "$1" ]; then
		mkzip doinstall
	else
		mkzip _install
	fi
}

_installtaz()
{
	$DIALOG --clear \
		--title " SliTaz TAZUSB way installation " \
		--yes-label "Install" --yesno \
"\nSliTaz will be installed in the subdirectory \\slitaz of the current
Linux/DOS/Windows partition. You can see your files from /mnt/dos.\n\n
You can start SliTaz with \\slitaz\\boot\\tazboot.exe\n\n
To uninstall SliTaz, you have only to remove this directory.
The file \\boot.ini or \\config.sys may be modified too.\n\n
The filesystem is loaded entirely into memory upon boot to
increase responsiveness. Only /home lands on the hard disk.\n\n
To do a traditional installation with disk partitioning,
start SliTaz Live with the 'SliTaz RAM boot' menu.\n
" 19 70
	[ $? -eq 0 ] || return
	doinstall tazusblike
}

installtaz()
{
	windev $1 || return
	packages_list=
	packages_dir=
	if [ "$1" ]; then
		doinstall tazusblike
	else
		_installtaz && bootinstalled /boot/bzimage
	fi
	umount $mnt
	rm -rf $mnt
}

insttaz2zip()
{
	if [ "$1" ]; then
		mkzip doinstall tazusblike
	else
		mkzip _installtaz
	fi
}

bootiso()
{
	cd /tmp
	for i in $(ls_r $media/boot/rootfs*gz); do
		grep -q ' lm ' /proc/cpuinfo && [ -s ${i}64 ] && i=${i}64
		cat $i
		n=$((4 - ($(stat -c %s $i) % 4)))
		[ $n -eq 4 ] || dd if=/dev/zero bs=1 count=$n
	done > initrd$$
	cmdline="root=/dev/null autologin lang=$LANG"
	[ -s /etc/keymap.conf ] && cmdline="$cmdline kmap=$(cat /etc/keymap.conf)"
	[ -s /etc/TZ ] && cmdline="$cmdline tz=$(cat /etc/TZ)"
	rm -f cmdline initrd 2> /dev/null
	getcustomconf kexec >/dev/null
	[ -s cmdline ] && cmdline="$cmdline $(cat cmdline)" && rm cmdline
	[ -s initrd ] && cat initrd >> initrd$$ && rm initrd
	kernel=$media/boot/bzImage
	grep -q ' lm ' /proc/cpuinfo && [ -s ${kernel}64 ] && kernel=${kernel}64
	. /etc/locale.conf
	kexec -l $kernel --initrd initrd$$ --command-line "$cmdline" &&
	rm -f initrd$$
	quit "kexec -e"
}

tazboot()
{
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " SliTaz bootloader for DOS " \
			--yes-label "Install" --yesno \
"\nThe file TAZBOOT.EXE will be created in the top directory. It supports
any linux kernel, multiple initramfs, a kernel command line and
an ISO image file loopback (retrieves files from an ISO file).\n\n
Usage: tazboot.exe [[@commands]|[kernel=<bzimage>] 
[initrd=<rootfs>[,<rootfs2>...]] [bootfrom=<isofile>] cmdline args ...]\n\n
Defaults: tazboot @tazboot.cmd or tazboot kernel=bzImage auto\n\n\
Examples for tazboot.cmd:\n\n\
  bootfrom=\\isos\\slitaz-4.0.iso\n\
  kernel=boot/bzImage\n\
  initrd=boot/rootfs4.gz,boot/rootfs3.gz,boot/rootfs2.gz,boot/rootfs1.gz\n\
  rw root=/dev/null autologin\n\n\
  kernel=\\slitaz\\vmlinuz root=/dev/sda5 ro\n\n
Unlike GRUB4DOS, it doesn't require unfragmented ISO image files.\n
" 0 0
		[ $? -eq 0 ] || return
	fi
	gettazboot tazboot.exe
	du -h $PWD/tazboot.exe
}

md5()
{
	dotwait "Checking files"
	( cd $media ; ${md5sum:-md5sum -c md5sum*} 2>&1 | sort ) > /tmp/data
	unset md5sum
	rm -f /tmp/wait
	if [ "$1" ]; then
		cat /tmp/data
	else
		$DIALOG --clear \
			--title " Checked files " \
			--textbox /tmp/data 0 0
	fi
	rm -f /tmp/data
}

gotcdfile()
{
	for i in "$media/$1" "$media/*/$1" "$media/*/isolinux/$1" ; do
		file=$(ls $i 2> /dev/null | sed q)
		[ -s "$file" ] && break
	done
}

sha()
{
	gotcdfile 'sha*sum*'
	sha=$(basename $file)
	md5sum="${sha%sum*}sum -c ${file#$media/}"
	md5 $@
}

readme()
{
	gotcdfile 'README*'
	if [ "$1" ]; then
		cat $file
	else
		$DIALOG --clear \
			--title " Readme " \
			--textbox $file 0 0
	fi
}

bzimage()
{
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " Create linux.exe ? " \
			--yes-label "Install" --yesno \
"\nLinux.exe launches the linux kernel under DOS (in real mode only).
The cmdline arguments are supported except initrd=,
vga= (you can try 'rdev -v') and mem= (partially).
\nExample:\nC:\\> linux.exe root=/dev/hda2 ro panic=60\n
" 12 70
		[ $? -eq 0 ] || return
	fi
	cp $media/boot/bzImage linux.exe
	du -h $PWD/linux.exe
}

memtest()
{
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " Create memtest.exe ? " \
			--yes-label "Install" --yesno \
"\nMemtest86 is a thorough, stand alone memory test for x86 architecture
computers. BIOS based memory tests are a quick, cursory check and often
miss many of the failures that are detected by Memtest86.\n
" 0 0
		[ $? -eq 0 ] || return
	fi
	gotcdfile 'memtest*' && cp $file memtest.exe
	du -h $PWD/memtest.exe
}

mkfat12()
{
	[ $(($(get 0 $1) - 0x5A4D)) -eq 0 ] || return
	J=$(($(get 3 $1 1) + 0x02))
	R=$((1 + $(get 497 $1 1) + 1 + ($(get 500 $1)-1)/32))
	[ $R -lt 2500 ] || return
	[ $((($(get 500 $1)-1) & 31)) -lt 30 ] &&
	ddq if=$file bs=32 count=1 seek=$(($R*16 - 1)) of=/dev/fd0
	G="18 0 2 0 0 0 0 0"
	[ $J -gt 25 ] || G=""
	F=0
	for i in 1 2 3; do
		F=$((((2880-$R-$F-$F)*3+1023)/1024))
	done
	bytes2bin 0xEB $J 0x90 0x20 0x20 0x20 0x20 0x20 0x20 0x20 0x20 \
		0 2 2 $(($R%256)) $(($R/256)) 2 64 0 64 11 0xF0 $F 0 \
		$G | ddq bs=1 of=/dev/fd0
	ddq if=/dev/zero bs=512 count=$((4+$F+$F)) seek=$R of=/dev/fd0
	for i in $R $(($R+$F)) ; do
		bytes2bin 0xF0 0xFF 0xFF | ddq bs=512 seek=$i of=/dev/fd0
	done
	echo -n $(basename $1) | ddq bs=1 seek=3 count=8 of=/dev/fd0
}

mkfloppy()
{
	dotwait "Create a $(basename $1) boot floppy"
	ddq if=$1 of=/dev/fd0
	mkfat12 $1
	rm -f /tmp/wait
}

fdmemtest()
{
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " Create a Memtest86 boot floppy " \
			--yes-label "Create floppy" --yesno \
"\nMemtest86 is a thorough, stand alone memory test for x86 architecture
computers. BIOS based memory tests are a quick, cursory check and often
miss many of the failures that are detected by Memtest86.\n\n
Please insert a blank disk in floppy drive.\n
" 0 0
		[ $? -eq 0 ] || return
	fi
	gotcdfile 'memtest*' && mkfloppy $file
}

pxe()
{
	gotcdfile '?pxe'
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " Create $(basename $file).exe ? " \
			--yes-label "Install" --yesno \
"\nBoot your operating system from the internet and enjoy a full system
working entirely in RAM with speed and stability in mind. The Linux Kernel
and the complete SliTaz compressed root filesystem will be loaded into RAM
from the Web using PXE and HTTP protocols.\n
" 0 0
		[ $? -eq 0 ] || return
	fi
	cp $file $(basename $file).exe
	du -h $PWD/$(basename $file).exe
}

fdpxe()
{
	if [ -z "$1" ]; then
		$DIALOG --clear \
			--title " Create a SliTaz Web boot floppy " \
			--yes-label "Create floppy" --yesno \
"\nBoot your operating system from the internet and enjoy a full system
working entirely in RAM with speed and stability in mind. The Linux Kernel
and the complete SliTaz compressed root filesystem will be loaded into RAM
from the Web using PXE and HTTP protocols.\n\n
Please insert a blank disk in floppy drive.\n
" 0 0
		[ $? -eq 0 ] || return
	fi
	gotcdfile '?pxe' && mkfloppy $file
}

menuitem()
{
	[ "$3" ] && shift
	echo -en "\"$1\"	\"$2\""
}

gotposixovl()
{
	mount.posixovl 2>&1 | grep -qi usage && gotcdfile 'rootfs*.gz' &&
	menuitem "$@"
}

gotposixovlzip()
{
	[ "$(which zip)" ] && gotposixovl "$1" "$2"
}

xfile()
{
	[ "$(which $1)" ] && menuitem "$@"
}

cdfile()
{
	gotcdfile "$1" && menuitem "$@"
}

gottazusb()
{
	gotcdfile 'rootfs*.gz' && xfile tazusb "$@"
}

isbzImage()
{
	[ $(get 514 $file 4) -eq 1400005704 ] &&
	[ $(($(get 529 $file 1) & 1)) -eq 1 ]
}

cdfilex()
{
	gotcdfile "$1" && [ "$(which kexec)" ] && isbzImage && menuitem "$@"
}

cdfilef()
{
	[ -e /sys/block/fd0 ] && cdfile "$@"
}

cdexe()
{
	gotcdfile "$1" &&
	[ $(get 0 $file 2>/dev/null || echo 0) -eq 23117 ] &&
	menuitem "$@"
}

misspkg()
{
	for i in zip kexec-tools posixovl cdrkit cdrkit-isoinfo ; do
		[ -d /var/lib/tazpkg/installed/$i/ ] && continue
		[ "$1" != "install" ] && menuitem "$@" && return
		tazpkg get-install $i
	done
}

missing()
{
	misspkg install
}

ishybrid()
{
	[ $(get 510 "$ISO") -eq 43605 ] || return
	C=$((2048*$(get $(((17*2048) + 71)) "$ISO" 4)))
	[ $(get $C "$ISO" 4) -eq 1 ] || return
	[ $(get $(($C+30)) "$ISO" 4) -eq $((0x88AA55)) ] || return
	C=$((2048*$(get $(($C+40)) "$ISO" 4)))
	[ $(get $(($C+64)) "$ISO" 4) -eq 1886961915 ] && menuitem "$@"
}

isiso()
{
	[ $(get 32769 "$ISO" 4) -eq 808469571 ] && menuitem "$@"
}

hastazboot()
{
	[ $(get 0 "$ISO") -eq 23117 ] && menuitem "$@"
}

burnable()
{
	[ "$(sed '/Can wr.*1$/!d' /proc/sys/dev/cdrom/info 2> /dev/null)" ] &&
	menuitem "$@"
}

blankable()
{
	[ "$(sed '/Can wr.*RW.*1$/!d' /proc/sys/dev/cdrom/info 2> /dev/null)" ] &&
	menuitem "$@"
}

burniso()
{
	wodim -v speed=$(fgrep "drive speed" /proc/sys/dev/cdrom/info | cut -f3) \
		-eject -multi "$ISO"
}

blankcd()
{
	wodim -v -blank=fast
}

customsector()
{
	local c=$(echo $(get 32848 "$ISO" 4))
	hascustomconf $(($c+16)) && echo $(($c+16)) || echo $c
}

hascustomconf()
{
	[ "$(ddq bs=2k skip=${1:-$(customsector)} if="$ISO" | ddq bs=1 count=6)" \
	  == "#!boot" ]
}

gotcustomconf()
{
	hascustomconf && menuitem "$@"
}

hasflavor()
{
	[ -x /usr/bin/tazlito ] && [ -s $media/boot/bzImage ] && menuitem "$@"
}

gotisomd5()
{
	[ "$(which md5sum 2> /dev/null)" ] &&
	[ $(get 0 "$ISO") -eq 23117 ] &&
	[ $(get 18 "$ISO") -ne 0 ] && menuitem "$@"
}

getcustomconf()
{
	ddq bs=2k skip=$(customsector) if="$ISO" | while read line; do
		case "$line" in
		\#!boot*) ;;
		append=*) echo ${line#append=} > cmdline && ls -l $PWD/cmdline ;;
		initrd:*) cnt=${line#initrd:}
			  { ddq bs=512 count=$(($cnt / 512));
			    ddq bs=1 count=$(($cnt % 512)); } > initrd &&
			  ls -l $PWD/initrd
			  break ;;
		*)	  break ;;	  
		esac
	done
	[ "$1" ] && return 0
	echo -e "\rPress RETURN to continue."
	read n
}

isomd5()
{
	dotwait "Checking iso image"
	[ "$(ddq if="$ISO" bs=2k skip=16 \
	     count=$(($(get 32848 "$ISO" 4)-16)) | md5sum)" == \
	  "$(ddq if="$ISO" bs=16 count=1 skip=2047 | od -N 16 -t x1 -An | \
	     sed 's/ //g')  -" ] && echo "OK" || echo "ERROR"
	echo -en "\rChecking iso hybrid boot..."
	n=$(($(get 2 "$ISO")-1+($(get 4 "$ISO")-1)*512))
	if [ $n -lt 40000 -a $n -gt 32768 ]; then
		s=$(get 0 "$ISO" 2 $n | awk '{ i+= $0 } END { print i }')
		[ $(((1+$s+$(get $(($n+1)) "$ISO" 1)) % 65536)) -eq 0 ] &&
		echo "OK" || echo "ERROR"
	fi
	if hascustomconf; then
		echo -en "\rChecking iso custom config..."
		TMP=/tmp/$(basename $0)$$md5
		md5="$(ddq bs=2k skip=$(customsector) if="$ISO" | while read line; do
			case "$line" in
			\#!boot*) echo ${line#*boot } > $TMP ;;
			append=*) echo $line ;;
			initrd:*) echo $line
				  cnt=${line#initrd:}
				  ddq bs=512 count=$((cnt / 512))
				  ddq bs=1 count=$((cnt % 512))
				  break ;;
			*)	  break ;;	  
			esac
		done | md5sum | cut -c1-32)"
		[ "$md5" == "$(cat $TMP)" ] && echo "OK" || echo "ERROR"
		rm -f $TMP
	fi
	rm -f /tmp/wait
	[ "$1" ] && return 0
	echo -e "\rPress RETURN to continue."
	read n
}

usbdev()
{
	dotwait "Wait 5 seconds for USB devices"
	sleep 5
	rm -f /tmp/wait
	DEV="$(grep -l 1 /sys/block/*/removable | \
		sed 's|/sys/block/\(.*\)/removable|\1|')"
	grep -qs 1 /sys/block/$DEV/ro && return
	[ "$DEV" ] || return
	cat > /tmp/dialog$$ <<EOT
$DIALOG  --clear \
	--title " Select your USB key " \
	--menu "\nPlease select the USB key according to its known size.\n\n" \
	0 0 0 \
	$(for i in $DEV ; do
		echo -n "/dev/$i \"$(($(cat /sys/block/$i/size)/2048))MB $(cat /sys/block/$i/device/model 2> /dev/null)\" "
	done) \

EOT
	exec 3>&1
	device=$(. /tmp/dialog$$ 2>&1 1>&3)
	rm -f /tmp/dialog$$
	retval=$?
	exec 3>&-
	rm -f /tmp/dialog$$
	[ $retval -eq 0 ]
}

tazusbmsg()
{
	[ "$(which tazusb 2> /dev/null)" ] || return
	echo "You should choose 'USB key read/write installation' to be
able to save the package updates or your own configuration and data files.\n\n"
}

usbbootkey()
{
	if [ -b "$1" ]; then
		device=$1
	elif [ "$1" ]; then
		echo "Invalid USB key device"
		return 1 
	else
		$DIALOG --clear \
			--title " Create a USB boot key " \
			--yes-label "Continue" --yesno \
"\nThe USB key will be used like a CD-ROM. You will not be able to write
any data on the boot partition.\n\n
An extra FAT32 partition will be created with the remaining free space.\n\n
$(tazusbmsg)Please plug your USB stick in now.\n 
" 16 70
		[ $? -eq 0 ] || return
		usbdev || return
	
		# perform dd in progress bar
		max=$(($(stat -c %s "$ISO")/2048))
		i=0; ddq if="$ISO" bs=1024k | ( 
		while ddq bs=1024k count=1 ; do 
			i=$(($i + 1))
			[ $i -gt $max ] && break
			echo $((($i*100)/$max)) | dialog --gauge \
				" The ISO image transfer can be long. Please wait..." \
				6 70 0 > /dev/tty 2>&1
		done ) > $device
	fi

	# partition + fat32 format for the remaining space
	for p in 0 16; do
		get $((450+$p)) $device 2 12 | xargs echo | {
		read dx cx ol oh ll lh
		[ $dx -eq $((0x3F17)) ] || continue
		cx=$(($cx & 0xFF00))
		ofs=$(($ll+($lh<<16)))
		n=$(($(cat /sys/block/${device#/dev/}/size)-$ofs))
		m=$(($cx+($n/8)))
		[ $m -gt $((0x3FF00)) ] && m=$((0x3FF00))
		m=$((($m & 0xFF00)+(($m>>16)<<6)))
		words2bin 0 $((0x101+$cx)) 0x3F0B $((32+$m)) \
			$ll $lh $(($n & 0xFFFF)) $(($n >> 16)) | \
			ddq bs=1 seek=$((462-$p)) of=$device
		if [ "$(which mkdosfs 2> /dev/null)" ]; then
			losetup -o $((512*$ofs)) /dev/loop2 $device
			mkdosfs -n "SLITAZ BOOT" /dev/loop2
			words2bin $(($ofs & 0xFFFF)) $(($ofs >> 16)) | \
				ddq bs=1 seek=28 of=/dev/loop2
			sync
			losetup -d /dev/loop2
		fi
 		}
 	done
}

usbkey()
{
	$DIALOG --clear \
		--title " Create a SliTaz USB key " \
		--yes-label "Continue" --yesno \
"\nUnlike a hard drive install, the filesystem is kept in a compressed
rootfs.gz. The filesystem is loaded entirely into memory upon boot.
This should increase responsiveness, protect the filesystem against
accidental corruption and reduce read/writes to the USB drive.
Once setup, the tazusb utility can rewrite the root filesystem
with any changes you have made since booting up, 
giving the effective benefits of a hard drive install.\n\n
/home is mounted on boot using the UUID of your particular flash drive.
Unlike a device name, the UUID has the benefit of never changing from machine
to machine.\n\n
Please plug your USB stick in now.\n 
" 19 70
	[ $? -eq 0 ] || return
	usbdev || return
	exec 3>&1
	format=`$DIALOG  --clear \
	--title " Select the filesystem " \
	--radiolist "\nPlease select the filesystem type to create.\n\n\
The filesystem creation will erase all the data \
in the USB key." 14 70 4 \
		"none"	"Do not erase the USB key" on \
		"ext3"	"Ext3 journaling filesystem" off \
		"ext2"	"Ext2 filesystem" off \
		"fat32"	"Windows FAT32 filesystem" off \
	2>&1 1>&3`
	retval=$?
	exec 3>&-
	[ $retval -eq 0 ] || return
	[ "$format" != "none" ] && tazusb format $device "SliTaz" $format
	tazusb gen-iso2usb "$ISO" $device
}

dokexec()
{
	kexec -l $file || return
	quit "kexec -e"
}

runmemtest()
{
	gotcdfile 'memtest*' && dokexec
}

runpxe()
{
	gotcdfile '?pxe' && dokexec
}

flavdata()
{
	[ $(get 1024 "$ISO") -eq 35615 ] && n=2 || n=$((1+$(get 417 "$ISO" 1)))
	[ $n -eq 4 ] && n=20
	ddq if="$ISO" bs=512 skip=$n count=20 | zcat 2>/dev/null
}

hasflavinfo()
{
	[ "$(flavdata | ddq bs=1 count=8 | strings)" == \
	  "07070100" ] && menuitem "$@"
}

showfavinfo()
{
	mkdir -p /tmp/data
	flavdata | ( cd /tmp/data ; cpio -i )
	file=/tmp/data/info
	cat /tmp/data/*desc > $file
	if [ -s /tmp/data/*receipt ]; then
		echo "=== receipt ==="
		cat /tmp/data/*receipt
	fi >> $file
	for i in /tmp/data/*list* ; do
		echo "=== extra ${i#*list} files"
		cat $i
	done >> $file
	if [ "$1" ]; then
		cat $file
	else
		$DIALOG --clear \
			--title " Flavor info " \
			--textbox $file 0 0
	fi
	rm -rf /tmp/data
}

flavor()
{
	name="$(flavdata | cpio -t 2> /dev/null | sed 's/.[a-z]*$//;q')"
	echo "Create ${name:=flavor}.flavor..."
	tazlito iso2flavor "$ISO" $name
	ls -l $name.flavor 2> /dev/null && return
	sleep 5
	[ "$1" ] && return
	echo -e "\rPress RETURN to continue."
	read n
}

parse_isolinux()
{
	awk 'BEGIN { IGNORECASE=1 }
function multi(n)
{
	auto=$n
	for (--n; n < NF; n+=2) {
		s=$n
		if (s ~ /M$/) s = substr(s,0,length(s)-1)
		else s /= 1024
		sizes=int(s) " " sizes
	}
	next
}
{
	if ($1 == "LABEL") {
		label=$2
		if (auto == "") auto=label
	}
	if ($1 == "KERNEL" || $1 == "COM32") kernel[label]=$2
	if ($1 == "INITRD") initrd[label]=$2
	if ($1 == "APPEND") {
		i=2
		if (kernel[label] ~ "ifmem.c32") multi(3)
		if (kernel[label] ~ "c32box.c32") {
			if ($2 == "linux") { kernel[label]=$3; i=4 }
			if ($2 == "ifmem") multi(4)
		}
		if (kernel[label] ~ "ifcpu64.c32") { auto=$4; next }
		while (i <= NF) {
			if ($i ~ "^initrd=") initrd[label]=substr($i,8)
			else cmdline[label]=cmdline[label] " " $i
			i++
		}
	}
}
END {
	print "KERNEL=\"" kernel[auto] "\""
	print "INITRD=\"" initrd[auto] "\""
	print "CMDLINE=\"" substr(cmdline[auto],2) "\""
	print "SIZES=\"" sizes "\""
}'
}

locase()
{
	echo "$1" | tr [A-Z] [a-z]
}

ifmemcode()
{
	uudecode <<EOT
begin-base64 644 -
gUwQIIBmYLkaAGoA4vxmYYnnsRS4IOhmulBBTVPNFWYZwnUM/00QdQMDbQoJ
23Xgg8QUwe0EdQi0iM0VlcHtCkXoAABfvu4Bra+DwAQ4BHYIOa0YAHbyiARm
Ycs=
====
EOT
}

floppyset()
{
	gotcdfile 'isolinux.cfg'
	$0 include $file | parse_isolinux > /tmp/var$$
	. /tmp/var$$
	[ -z "$KERNEL" ] && echo "Can't parse isolinux.cfg" && return
	for i in $media/$KERNEL $(dirname $file)/$KERNEL $media/$(locase $KERNEL) \
		 $(dirname $file)/$(locase $KERNEL); do
		i="$(ls $i* | sed q)"
		[ -n "$i" ] && KERNEL=$i && break
	done
	rm -f /tmp/var$$ 
	[ $(get 514 $KERNEL 4) -eq 1400005704 ] || return
	n=$(($(get 497 $KERNEL 1)+1))
	ddq bs=512 count=$n if=$KERNEL of=/tmp/fd$$
	uudecode <<EOT | ddq of=/tmp/fd$$ conv=notrunc
begin-base64 644 -
v8adaACQF4n8FgcxwLk7APOqWx+g8X1AD6H6xXd4XwZXvQAAsQbzpRYfZGaP
R3jGRfg/l1hB6DABvgACgUwQIIDGRCWb6IYBMfYLdxt0OsdHGT+j6HoBsCDo
TAEsGHP5TuhQAZg8CHQDiAStOXcbdPDoNAE8CnXfiHz+Fge/AICJ/od3G7UC
86Rbieb/SBDHQBQIk4DzCHXzu/QBsQWhFQJmix9mS2bT62ZDiUQbZr+AAAAA
Zin7nHMCAd9XUFNWMdtoAIAH6I8AXluMwbSHFgfNFVhf0ecB+BBMH513zLkJ
Ar/uAYsdgwUE020QdBgJ23QptIjNFT0AsHIGiGwfiG0toRkC65pTZotf/GYB
XS4uxgZyfdxbOl0CcoXjFJfNE+oAACCQWjjBdzRgzRP56HIAYVJQKMh3ArAB
OfhyAon4ULQCzRNaWHLclQHRjukA1wDXKddadEyM6ZU4wXXUiMixATDOdcz+
xYD9UHXFtQBgvuEBU+hZAFuJ9eg2AHUc/gyLTDV0lVKYzRO4AQLNE1rQ1Dpm
/nXjRUh13wwgPGJ04OuOsDEcA7QOuwcAzRA8DXTzw79sBGTGBaa4DQFkOiV0
Cs0WdPSYzRaO50fDA3QOsA3o0v+sPAB/+MNCIG9yIE5leHQhBw0AFAAAAADq
Ae4=
====
EOT
	pos=$(($n*512))
	if [ -n "$CMDLINE" ]; then
		echo -n "$CMDLINE" | ddq bs=512 count=1 conv=sync >> /tmp/fd$$
		bytes2bin $n | ddq conv=notrunc \
			bs=1 seek=497 count=1 of=/tmp/fd$$
		words2bin $pos | ddq conv=notrunc \
			bs=1 seek=34 count=2 of=/tmp/fd$$
		[ $(get 518 $KERNEL 4) -ge 514 ] &&
		words2bin 32768 9 | ddq conv=notrunc \
			bs=1 seek=552 count=4 of=/tmp/fd$$
	fi
	syssize=$(echo $(get 500 /tmp/fd$$ 4))
	ddq bs=512 skip=$n if=$KERNEL | cat - /dev/zero | \
	ddq bs=512 count=$((($syssize+31)/32)) conv=sync >> /tmp/fd$$
	base=$(stat -c %s /tmp/fd$$)
	len=
	if [ "$INITRD" ]; then
		l=0
		for i in ${INITRD//,/ }; do
			for j in $media/$i $(dirname $KERNEL)/$i $media/$(locase $i) \
				 $(dirname $KERNEL)/$(locase $i); do
				j="$(ls $j* | sed q)"
				[ -n "$j" ] && i=$j && break
			done
			ddq if=$i >> /tmp/fd$$
			l=$(($l+$(stat -c %s $i)))
			r=$((4 - ($l % 4)))
			if [ $r -ne 4 ]; then
				ddq if=/dev/zero bs=1 count=$r >> /tmp/fd$$
				l=$(($l + $r))
			fi
			case "$i:$INITRD" in
				*rootfs.gz:*rootfs.gz,*) continue	# loram
			esac
			len="$len $l"; l=0
		done
		rdadrs=${RDADRS:-$(((($syssize*16)+0x1F0000) & -4096))}
		words2bin $(($rdadrs & 0xFFFF)) $(($rdadrs >> 16)) | ddq \
			conv=notrunc bs=1 seek=536 count=4 of=/tmp/fd$$
	fi
	n=$(echo $len | wc -w)
	if [ $((494 - $(get 494 /tmp/fd$$))) -ge $(($n * 4)) ]; then
		i=$(($(get 494 /tmp/fd$$)))
		bytes2bin $(($i + ($n*4) - 256)) | ddq bs=1 conv=notrunc \
			seek=496 count=1 of=/tmp/fd$$
	else
		i=$(($pos + 0x1FC - ($n*4)))
		bytes2bin $(($i % 256)) $((i / 256)) 252 | ddq bs=1 \
			conv=notrunc seek=494 count=3 of=/tmp/fd$$
		s=$(($i - 2*$(echo "$SIZES" | wc -w)))
		p=$(($s - $(ifmemcode | wc -c)))
		ifmemcode | ddq bs=1 conv=notrunc seek=$p of=/tmp/fd$$
		words2bin $SIZES | ddq bs=1 conv=notrunc seek=$s of=/tmp/fd$$
		bytes2bin 154 $(($p%256)) $(($p/256)) 0 144 | \
		ddq bs=1 conv=notrunc seek=60 of=/tmp/fd$$
	fi
	for r in $len ; do
		words2bin $(($r & 0xFFFF)) $(($r >> 16)) | ddq conv=notrunc \
			bs=1 seek=$i count=4 of=/tmp/fd$$
		i=$(($i + 4))
	done
	split -b 1440k /tmp/fd$$ fd$$
	rm -f /tmp/fd$$
	n=1; i=0; r=0
	set -- $len
	ls fd$$* | while read file ; do
		if [ $i -gt $(($1+$base)) ]; then
			shift
			r=$(($r+100)); n=0; i=0; base=0
		fi
		ddq of=$file bs=18k seek=80 count=0
		i=$(($i+1474560))
		printf "mv %s fd%03d.img\n" $file $(($r+$n))
		n=$(($n+1))
	done | sh
	du -ch $PWD/fd???.img
}

quit()
{
	umount -d $media
	rmdir $media
	${1:-exit}
}

infoiso()
{
	isoinfo -d -i "$ISO" > /tmp/isoinfo$$
	if [ -x "$(which iso2exe)" ]; then
		echo "----"
		blkid "$ISO" | while read args; do
			set -- $args
			while [ -n "$2" ]; do
				case "$2" in
				*UUID*|PT*) echo $2;;
				esac
				shift
			done
		done
		if ! fdisk -l "$ISO" | grep -q 'valid partition'; then
			fdisk -l "$ISO" | grep heads
			fdisk -l "$ISO" | sed 's/^ *[^ ]* *//;s/  */ /g;$!d'
		fi
		echo "----"
		iso2exe -l "$ISO"
	fi >> /tmp/isoinfo$$
	if [ "$1" ]; then
		cat /tmp/isoinfo$$
	else
		$DIALOG --clear \
			--title " Info ISO " \
			--textbox /tmp/isoinfo$$ 0 0
	fi
	rm -f /tmp/isoinfo$$
}

isotitle()
{
	echo "$(blkid "$ISO" | sed 's/.*LABEL="\([^"]*\).*/\1/')  $(stat \
		-c %y $media/.|sed 's/ .*//')  $(basename "$ISO")"
}

if [ "$1" == "include" ]; then
	[ -s "$2" ] && cd $(dirname "$2") && awk -v exe=$0 \
	'{ if ($1 == "include") system(exe " include " $2); else print }' <"$2"
	exit
fi
ISO="${1:-/dev/null}"
[ -z "$(isiso 2> /dev/null)" ] && echo "Usage : $0 file.iso" && exit 1
media=/tmp/media$$
mkdir -p $media
mount -o loop,ro "$ISO" $media

if [ "$2" == "list" ]; then
	sed '/^\$(.*") \\/!d;s/^\$(\(.*\)").*/\1"/' $0 | while read line; do
		eval $line
		echo
	done | sed '/^$/d;/"usbkey"/d'
	quit
fi
if grep -q "^$2()" $0; then
	exe=$2
	shift 2
	if [ -n "$(eval $(grep "\"$exe\"" $0 | sed \
		   '/^\$/!d;s/.(\(.*\)[\t ]*".*"[\t ]*".*/\1/'))" ]; then
		isotitle
		grep "\"$exe\"" $0 | sed '/^\$/!d;s/.*"[\t ]*"\(.*\)".*/\1/'
		echo ----
		$exe "$@"
	fi
	quit
fi

while true; do
	cat > /tmp/dialog$$ <<EOT
$DIALOG  --clear \
	--title " $(isotitle) " \
	--menu "" -2 70 0 \
$(cdfile 'README*'	"readme"	"Show the README file") \
$(gotcustomconf		"getcustomconf"	"Get custom config") \
$(gotisomd5		"isomd5"	"Check the ISO image") \
$(cdfile 'md5sum*'	"md5"		"Check the ISO files") \
$(cdfile 'sha*sum*'	"sha"		"Check the ISO files") \
$(xfile isoinfo		"infoiso"	"ISO image info") \
$(cdfilex boot/bzImage	"bootiso"	"Boot the ISO image") \
$(burnable		"burniso"	"Burn the ISO image") \
$(blankable		"blankcd"	"Blank the CD/DVD") \
$(gotposixovl		"install"	"Hard disk installation (UMSDOS way)") \
$(gotposixovl		"installtaz"	"Hard disk installation (TAZUSB way)") \
$(gotposixovlzip	"inst2zip"	"ZIP installation archive (UMSDOS way)") \
$(gotposixovlzip	"insttaz2zip"	"ZIP installation archive (TAZUSB way)") \
$(gottazusb 		"usbkey"	"USB key read/write installation") \
$(ishybrid		"usbbootkey"	"USB boot key (read only)") \
$(hasflavinfo		"showfavinfo"	"Show flavor extra info") \
$(hasflavor		"flavor"	"Get flavor file") \
$(cdfile isolinux.cfg	"floppyset"	"Boot floppy set") \
$(hastazboot		"tazboot"	"Get tazboot.exe Linux loader") \
$(cdexe boot/bzImage	"bzimage"	"Get linux DOS/EXE file") \
$(cdexe 'memtest*'	"memtest"	"Get Memtest86 DOS/EXE file") \
$(cdfilef 'memtest*'	"fdmemtest"	"Create a Memtest86 boot floppy") \
$(cdfilex 'memtest*'	"runmemtest"	"Start Memtest86") \
$(cdexe '?pxe'		"pxe"		"Get SliTaz Web boot DOS/EXE utility") \
$(cdfilef '?pxe'	"fdpxe"		"Create a SliTaz Web boot floppy") \
$(cdfilex '?pxe'	"runpxe"	"Start the SliTaz Web boot utility") \
$(misspkg		"missing"	"Install packages to get more options") \
$(menuitem		"quit"		"Quit this utility")
EOT
	exec 3>&1
	value=$(. /tmp/dialog$$ 2>&1 1>&3)
	retval=$?
	exec 3>&-
	rm -f /tmp/dialog$$
	[ $retval -eq 0 ] || quit
	$value
done
