#!/bin/sh

### BEGIN INIT INFO
# Provides:          fll-reboot
# Required-Start:
# Required-Stop:     umountroot
# X-Stop-After:      umountfs lvm2
# X-Interactive:     true
# Default-Start:     1 2 3 4 5
# Default-Stop:      0 6
# Short-Description: shutdown and eject live media
# Description:       This script provides the equivalent of umountfs,
#                    umountroot, reboot and halt on a standard debian system.
#                    It umounts live mounts and ejects the live media at
#                    shutdown/reboot.
### END INIT INFO

###
# F.U.L.L.S.T.O.R.Y init script
#
# Copyright: (C) 2007-2008, Kel Modderman <kel@otaku42.de>
# Copyright: (C) 2008-2016, Stefan Lippers-Hollmann <s.l-h@gmx.de>
# License:   GPLv2
#
# F.U.L.L.S.T.O.R.Y Project Homepage:
# https://github.com/fullstory
###

PATH=/sbin:/usr/sbin:/bin:/usr/bin
NAME="fll-reboot"

###
# source distro-defaults, no-op unless in live mode
###
FLL_DISTRO_MODE="installed"

if [ -r /etc/default/distro ]; then
	. /etc/default/distro
fi

if [ "${FLL_DISTRO_MODE}" != "live" ]; then
	exit 0
fi

###
# VERBOSE setting and other rcS variables
###
. /lib/init/vars.sh

###
# source lsb functions
###
. /lib/lsb/init-functions

###
# don't prompt for ejecting in a virtual machine, unless overriden
###
if [ -r /sys/devices/virtual/dmi/id/bios_vendor ]; then
	case "$(head -n1 /sys/devices/virtual/dmi/id/bios_vendor)" in
		"Bochs")
			# qemu/ kvm
			NOPROMPT="1"
			;;
		"innotek GmbH")
			# VirtualBox
			NOPROMPT="1"
			;;
	esac
fi

if [ -f /proc/cmdline ]; then
	for param in $(cat /proc/cmdline); do
		case "${param}" in
			noeject|toram)
				NOEJECT="1"
				;;
			doprompt)
				unset NOPROMPT
				;;
			noprompt)
				NOPROMPT="1"
				;;
		esac
	done
fi

###############################################################################
# Adapted from initscripts: /etc/init.d/umountfs (2.86.ds1-62)
###############################################################################
do_umount() {
	exec 9<&0 < /proc/mounts

	REG_MTPTS=""
	TMPFS_MTPTS=""
	while read -r DEV MTPT FSTYPE OPTS REST; do
		case "$MTPT" in
			#
			# live hack
			#
			/fll/*)
				case "$FSTYPE" in
					iso9660)
						[ "$MTPT" = /fll/fromiso ] && LIVE_MTPTS="$MTPT $LIVE_MTPTS"
						;;
					*)
						LIVE_MTPTS="$MTPT $LIVE_MTPTS"
						;;
				esac
				continue
				;;
		esac
		case "$FSTYPE" in
			overlay|overlayfs|aufs|unionfs)
				UNION_MTPTS="$MTPT $UNION_MTPTS"
				;;
			squashfs)
				SQUSH_MTPTS="$MTPT $SQUSH_MTPTS"
				;;
		esac
	done

	exec 0<&9 9<&-

	#
	# live hack: any command after this point must be prefixed with ${BINDIR}
	#
	UMOUNT_V=""
	if [ "$VERBOSE" != no ]; then
		UMOUNT_V="-v"
	fi

	if [ "$UNION_MTPTS" ]; then
		echo "Unmounting union filesystems."
		for MTPT in $UNION_MTPTS ; do
			case "$MTPT" in
				/)
					# umount / and it's game-over
					mount -o remount,ro $MTPT
					[ "$?" -eq 0 ] || echo  "\"mount -o remount,ro $MTPT\" returned $?"
					;;
				*)
					umount -l -n -f -d $UMOUNT_V $UNION_MTPTS
					[ "$?" -eq 0 ] || echo "\"umount -l -n -f -d $UMOUNT_V $UNION_MTPTS\" returned $?"
					;;
			esac
		done
	fi

	if [ "$SQSH_MTPTS" ]; then
		echo "Unmounting squashfs filesystems."
		umount -l -n -f -d $UMOUNT_V $SQSH_MTPTS
		[ "$?" -eq 0 ] || echo "\"umount -l -n -f -d $UMOUNT_V $SQSH_MTPTS\" returned $?"
	fi

	if [ "$LIVE_MTPTS" ]; then
		echo "Unmounting live filesystems."
		umount -l -n -f -d $UMOUNT_V $LIVE_MTPTS
		[ "$?" -eq 0 ] || echo "\"umount -l -n -f -d $UMOUNT_V $LIVE_MTPTS\" returned $?"
	fi
}
###############################################################################
# Adapted from initramfs-tools hook-functions (0.87b)
###############################################################################
# $1 is source
# $2 is relative destination
copy_exec() {
	verbose="${VERBOSE}"
	final_destination=${DESTDIR}/${2}/$(basename ${1})

	if [ -L "$final_destination" ]; then
		if ! [ `readlink ${final_destination}` = "${1}" ]; then
			return
		fi
	else
		cp ${1} ${DESTDIR}/${2}
		if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
			echo "Adding binary ${1}"
		fi
	fi

	# Copy the dependant libraries
	for x in $(ldd ${1} 2>/dev/null | sed -e '
	    /\//!d;
	    /linux-gate/d;
	    /=>/ {s/.*=>[[:blank:]]*\([^[:blank:]]*\).*/\1/};
	    s/[[:blank:]]*\([^[:blank:]]*\) (.*)/\1/' 2>/dev/null); do

		# Try to use non-optimised libraries where possible.
		# We assume that all HWCAP libraries will be in tls.
		nonoptlib=$(echo ${x} | sed -e 's#/lib/tls.*/\(lib.*\)#/lib/\1#')

		if [ -e ${nonoptlib} ]; then
			x=${nonoptlib}
		fi

		libname=$(basename ${x})
		dirname=$(dirname ${x})

		mkdir -p ${DESTDIR}/${dirname}
		if [ ! -e ${DESTDIR}/${dirname}/${libname} ]; then
			cp ${x} ${DESTDIR}/${dirname}
			if [ -n "${verbose}" ] && [ "${verbose}" = "y" ]; then
				echo "Adding library ${x}"
			fi
		fi
	done
}
###############################################################################
# End adapted functions
###############################################################################

do_stop() {
	# calculate runlevel
	runlevel_pair="$(runlevel)"
	runlevel="${runlevel_pair#* }"

	# set sane defaults for /dev/console
	stty sane < /dev/console

	# prepare binaries for post-umount of live media
	DESTDIR="$(mktemp -d -p / fll.XXXXX)"
	mkdir -p ${DESTDIR}/bin

	# cache utilities required for the final stages of shutdown
	for path in $(which echo) $(which umount) $(which halt) \
		$(which reboot) $(which eject); do
		copy_exec "${path}" /bin
	done

	LD_LIBRARY_PATH="${DESTDIR}/lib"
	if [ -e "${DESTDIR}/lib64" ]; then
		LD_LIBRARY_PATH="${DESTDIR}/lib64:${LD_LIBRARY_PATH}"
	fi
	for path in $(awk '/^\/lib/ {print $1}' /etc/ld.so.conf.d/*) ; do
		if [ -e "${DESTDIR}${path}" ]; then
			LD_LIBRARY_PATH="${DESTDIR}${path}:${LD_LIBRARY_PATH}"
		fi
	done
	export LD_LIBRARY_PATH

	LD_LINUX="${DESTDIR}/lib/ld-linux.so.2"
	if [ -e "${DESTDIR}/lib64/ld-linux-x86-64.so.2" ]; then
		LD_LINUX="${DESTDIR}/lib64/ld-linux-x86-64.so.2"
	elif [ ! -e $LD_LINUX ]; then
		LD_LINUX="${DESTDIR}/lib/ld.so.1"
		if [ -e "${DESTDIR}/lib64/ld64.so.1" ]; then
			LD_LINUX="${DESTDIR}/lib64/ld64.so.1"
		fi
	fi
	export LD_LINUX

	echo() { ${LD_LINUX} ${DESTDIR}/bin/echo "$@"; }
	umount() { ${LD_LINUX} ${DESTDIR}/bin/umount "$@"; }
	eject() { ${LD_LINUX} ${DESTDIR}/bin/eject "$@"; }

	# umount the live media and other mount points
	do_umount

	case "${runlevel}" in
		0)
			echo "System halted." > /dev/console
			command="${LD_LINUX} ${DESTDIR}/bin/halt"
			options="-h -n -p -i -f"
			;;
		6)
			echo "Preparing for reboot..." > /dev/console
			command="${LD_LINUX} ${DESTDIR}/bin/reboot"
			options="-n -i -f"
			;;
		*)
			echo "${NAME}: attempted execution in invalid runlevel!"
			exit 1
			;;
	esac

	if [ -b /dev/fll-cdrom ] && [ -z "${NOEJECT}" ]; then
		# disable kernel messages while ejecting cdrom (libata noise)
		echo "0" > /proc/sys/kernel/printk

		eject -m -p /dev/fll-cdrom

		if [ -z "${NOPROMPT}" ]; then
			echo "" > /dev/console
			echo "Please remove CD, close cdrom drive then press enter." > /dev/console
			echo "" > /dev/console
			read x < /dev/console
		fi
	fi

	# shutdown/reboot
	exec ${command} ${options} > /dev/console 2>&1 < /dev/console
}

case "${1}" in
	start)
		# no-op
		exit 0
		;;
	restart|reload|force-reload)
		echo "Error: argument '${1}' not supported" >&2
		exit 3
		;;
	stop)
		# live-hack, umount and eject
		do_stop
		;;
	status)
		log_success_msg "${0} is no dæmon."
		exit 0
		;;
	*)
		echo "Usage: ${NAME} {start|stop}" >&2
		exit 3
		;;
esac
