#!/bin/sh
#
# Public Domain, 2009-2011 - Juan RP <xtraeme@gmail.com>
#
trap "echo; error_out $?" INT QUIT

info_msg()
{
	printf "\033[1m$@\n\033[m"
}

mount_pseudofs()
{
	local fs

	if [ -n "$ROOTDIR" ]; then
		mount --bind "$ROOTDIR" "$ROOTFS" || error_out $?
	fi

	for fs in sys proc dev; do
		if [ ! -d "$ROOTFS/$fs" ]; then
			mkdir -p "$ROOTFS/$fs"
		fi
		mount --bind /$fs "$ROOTFS/$fs" || error_out $?
	done
}

umount_pseudofs()
{
	local fs

	for fs in sys proc dev; do
		umount -f "$ROOTFS/$fs" >/dev/null 2>&1
	done
	if [ -n "$1" -a -n "$ROOTDIR" ]; then
		umount -f "$ROOTFS" >/dev/null 2>&1
	fi
}

error_out()
{
	umount_pseudofs

	if [ "$1" -ne 0 ]; then
		echo "ERROR: stage mentioned above returned $1!"
	fi
	info_msg "Cleaning up $BUILDDIR..."
	rm -rf "$BUILDDIR"
	exit 1
}

write_etc_motd()
{
	cat >> "$ROOTFS/etc/motd" <<_EOF
###############################################################################
  Autogenerated by vanilla-mklive @@MKLIVE_VERSION@@.
-------------------------------------------------------------------------------

Welcome to the Vanilla GNU/Linux Live system, you have been autologged in.
This user has full sudo(8) permissions without any password, be careful
executing commands through sudo(8).

To play with package management use the xbps-bin(8) and xbps-repo(8)
utilities. Please visit:

	http://code.google.com/p/xbps/

For more information and/or documentation about using the X Binary
Package System. Enjoy it.

Please also visit my personal blog and click to any of the Google ADs,
to help continuining developping XBPS. Thank you.

	http://xtraeme.blogspot.com/

-- Juan RP <xtraeme@gmail.com>

###############################################################################
_EOF
}

write_default_isolinux_conf()
{
	local kver="$1"

	if [ -r "$SPLASH_IMAGE" ]; then
		BACKGROUND="MENU BACKGROUND $(basename $SPLASH_IMAGE)"
	fi

	cat >> "$ISOLINUX_CFG" << _EOF
DEFAULT vesamenu.c32
PROMPT 0
TIMEOUT 100
ONTIMEOUT linux

$BACKGROUND
MENU VSHIFT 5
MENU ROWS 20
MENU TABMSGROW 10
MENU TABMSG Press ENTER to boot or TAB to edit a menu entry
MENU AUTOBOOT BIOS default device boot in # second{,s}...
MENU TIMEOUTROW 12

MENU COLOR title        * #FF5255FF *
MENU COLOR border       * #00000000 #00000000 none
MENU COLOR sel          * #ffffffff #FF5255FF *

LABEL linux
MENU LABEL Boot Vanilla GNU/Linux ${kver} ($(uname -m))
KERNEL /casper/vmlinuz
INITRD /casper/initrd.lz
APPEND boot=casper keymap=${KEYMAP:-es} locale=${LOCALE:-es_ES} ro

LABEL linuxtoram
MENU LABEL Boot Vanilla GNU/Linux ${kver} (toram) ($(uname -m))
KERNEL /casper/vmlinuz
INITRD /casper/initrd.lz
APPEND boot=casper toram keymap=${KEYMAP:-es} locale=${LOCALE:-es_ES} ro

LABEL c
MENU LABEL Boot first HD found by the BIOS
LOCALBOOT 0x80
_EOF
}

usage()
{
	cat <<_EOF
Usage: $(basename $0) [options]

Options:
	-c comptype	Compression type for the squashfs image.
	-o outfile	Output file name for the ISO image.
	-r rootdir	Rootfs directory.
	-s splash	Splash image file for isolinux.
	-v volname	ISO Volume name.
	-h		Shows this message.
_EOF
	exit 1
}

#
# main()
#
while getopts "c:o:r:s:v:h" opt; do
	case $opt in
		c) export SQUASHFS_COMPRESSION="$OPTARG";;
		o) export OUTPUT_FILE="$OPTARG";;
		r) export ROOTDIR="$OPTARG";;
		s) export SPLASH_IMAGE="$OPTARG";;
		v) export ISO_VOLUME="$OPTARG";;
		h) usage;;
	esac
done
shift $(($OPTIND - 1))

if [ "$(id -u)" -ne 0 ]; then
	echo "ERROR: EPERM... got root?"
	exit 1
fi

CONFIG_DIR="$HOME/.mklive"
CONFIG_FILE="$CONFIG_DIR/default.conf"

if [ -z "$OUTPUT_FILE" ]; then
	OUTPUT_FILE="$HOME/vanilla-live-$(uname -m)-$(date +%Y%m%d).iso"
fi
if [ -z "$ISO_VOLUME" ]; then
	ISO_VOLUME="Vanilla GNU/Linux Live $(uname -m)"
fi

#
# The following vars can be overwritten by the config file.
#
PACKAGE_REPO="/storage/xbps/packages"
SYSLINUX_DATADIR="/usr/share/syslinux"
XBPS_REPO_CMD="xbps-repo"
XBPS_BIN_CMD="xbps-bin"
XBPS_UHELPER_CMD="xbps-uhelper"

if [ ! -r $CONFIG_FILE ]; then
	echo "Cannot find $CONFIG_FILE! exiting..."
	error_out
fi

. $CONFIG_FILE

if [ -z "$PACKAGE_LIST" ]; then
	PACKAGE_LIST="base-system xbps-casper"
else
	PACKAGE_LIST="base-system xbps-casper $PACKAGE_LIST"
fi
BUILDDIR=$(mktemp --tmpdir="$(pwd)" -d) || exit 1
BUILDDIR=$(readlink -f $BUILDDIR)
ROOTFS="$BUILDDIR/casper/rootfs"
ISOLINUX_DIR="$BUILDDIR/isolinux"
ISOLINUX_CFG="$ISOLINUX_DIR/isolinux.cfg"

if [ ! -f $SYSLINUX_DATADIR/isolinux.bin ]; then
	echo "Missing required isolinux files in $SYSLINUX_DATADIR!"
	error_out
fi

#
# Mount pseudofs in the target rootfs.
#
mount_pseudofs
mkdir -p "$ROOTFS/tmp"

if [ -z "$ROOTDIR" ]; then
	#
	# Register all package repositories in the target rootfs.
	#
	xver=$(${XBPS_BIN_CMD} -V|awk '{print $2}')
	if [ -z "$xver" -o "$xver" = "" ]; then
		for _repo_ in ${PACKAGE_REPO}; do
			info_msg "Adding ${_repo_} package repository..."
			${XBPS_REPO_CMD} -r "$ROOTFS" add "${_repo_}" || error_out $?
		done
	fi
	${XBPS_BIN_CMD} -r "$ROOTFS" -y install ${PACKAGE_LIST} || error_out $?
	${XBPS_BIN_CMD} -r "$ROOTFS" -y autoupdate || error_out $?
	${XBPS_BIN_CMD} -r "$ROOTFS" -yp autoremove || error_out $?
	${XBPS_BIN_CMD} -r "$ROOTFS" -yvp purge all || error_out $?
fi

${XBPS_BIN_CMD} -r "$ROOTFS" list > \
	"${OUTPUT_FILE%.iso}"-package-list.txt || error_out $?

#
# Prepare /etc/motd.
#
info_msg "Creating /etc/motd..."
write_etc_motd

#
# We must know the installed kernel package version.
#
kver=$(${XBPS_UHELPER_CMD} -r "$ROOTFS" version kernel)
if [ -z "$kver" ]; then
	echo "Missing 'kernel' package in repository pool!"
	error_out
fi

#
# Rebuild the initramfs image with LZMA compression.
#
info_msg "Rebuilding and copying initramfs image..."
sed -i -e "s|COMPRESS=gzip|COMPRESS=lzma|" \
	"$ROOTFS"/etc/initramfs-tools/initramfs.conf
${XBPS_BIN_CMD} -r "$ROOTFS" -f reconfigure kernel || error_out $?

cp -f "${INITRD_IMG:-$ROOTFS/boot/initrd.img-${kver}}" \
	"$BUILDDIR/casper/initrd.lz" || error_out $?
mkdir -p "$ROOTFS"/cow

#
# Copy the linux image to the target directory.
#
info_msg "Copying kernel image..."
cp -f "${KERNEL_IMG:-$ROOTFS/boot/vmlinuz-${kver}}" \
	"$BUILDDIR/casper/vmlinuz" || error_out $?

#
# Remove stuff that uses a lot of space.
#
info_msg "Cleaning up rootfs..."
rm -f "$ROOTFS"/boot/initrd*
rm -f "$ROOTFS"/boot/vmlinuz*

#
# The pseudofs aren't needed anymore in target rootfs.
#
umount_pseudofs

#
# Copy required isolinux files in the target rootfs.
#
mkdir -p "$ISOLINUX_DIR"
cp -f $SYSLINUX_DATADIR/isolinux.bin "$ISOLINUX_DIR"
cp -f $SYSLINUX_DATADIR/vesamenu.c32 "$ISOLINUX_DIR"
write_default_isolinux_conf ${kver}
if [ -f "$SPLASH_IMAGE" ]; then
	cp -f $SPLASH_IMAGE "$ISOLINUX_DIR"
fi

#
# Prepare the squashed rootfs image.
#
info_msg "Building squashed root filesystem..."
mksquashfs "$ROOTFS" "$BUILDDIR/casper/filesystem.squashfs" \
	-root-becomes / -comp ${SQUASHFS_COMPRESSION:-gzip} && \
	chmod 444 "$BUILDDIR/casper/filesystem.squashfs" || error_out $?

if [ -n "$ROOTDIR" ]; then
	umount_pseudofs yes
else
	info_msg "Removing rootfs directory..."
	rm -rf "$ROOTFS" || error_out $?
fi

#
# Prepare the ISO image.
#
info_msg "Building ISO image..."
mkisofs -J -r -V "$ISO_VOLUME" -b isolinux/isolinux.bin \
	-c isolinux/boot.cat -no-emul-boot \
	-boot-load-size 4 -boot-info-table \
	-o "$OUTPUT_FILE" "$BUILDDIR" || error_out $?

info_msg "Removing build directory..."
rm -rf "$BUILDDIR" || error_out $?

info_msg "Created $(readlink -f $OUTPUT_FILE) successfully."

exit 0
