#!/bin/bash

if [ "$1" != "halt" ];then
    if [ "$1" != "reboot" ]; then
	if [ "$1" != "poweroff" ]; then
	    echo "Have to use $0 [reboot|halt|poweroff]"
	    exit 1
	fi
    fi
fi


echo " shutdown_script, doing an $1 "

# Try to resit term and kill signals sent to me.
trap SIGKILL
trap SIGTERM


echo " Sending all processes the TERM signal ..."

if [ -x /sbin/killall5 ]
then
    /sbin/killall5 -15
else
    /sbin/killalli5 -15
fi

echo -n " Sleeping 2 seconds ."

sleep 1; echo -n "."
sleep 1; echo "."

echo " Sending all processes the KILL signal ..."

if [ -x /sbin/killall5 ]
then
    /sbin/killall5 -9
else
    /sbin/killalli5 -9
fi

echo " Sleeping 1 second ... "

sleep 1

# Try to unmount all tmpfs filesystems not in use, else a deadlock may
# occure, bug #13599.
umount -art tmpfs &>/dev/null

# Unmounting should use /proc/mounts and work with/without devfsd running

# Credits for next function to unmount loop devices, goes to:
#
#	Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#	Modified for RHS Linux by Damien Neil
#
#
# Unmount file systems, killing processes if we have to.
# Unmount loopback stuff first
# Use `umount -d` to detach the loopback device

# Remove loopback devices started by dm-crypt

remaining="`awk '!/^#/ && $1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts | \
            sort -r | grep -v '/newroot' | grep -v '/mnt/livecd'`"
[ -n "${remaining}" ] && {
	sig=
	retry=3

	while [ -n "${remaining}" -a "${retry}" -gt 0 ]
	do
		if [ "${retry}" -lt 3 ]
		then
			echo "Unmounting loopback filesystems (retry) ..."
			umount -d ${remaining} &>/dev/null
		else
			echo "Unmounting loopback filesystems ..."
			umount -d ${remaining} &>/dev/null
		fi

		remaining="`awk '!/^#/ && $1 ~ /^\/dev\/loop/ && $2 != "/" {print $2}' /proc/mounts | \
		            sort -r | grep -v '/newroot' | grep -v '/mnt/livecd'`"
		[ -z "${remaining}" ] && break
		
		/bin/fuser -k -m ${sig} ${remaining} &>/dev/null
		sleep 5
		retry=$((${retry} - 1))
		sig=-9
	done
}

# Try to unmount all filesystems (no /proc,tmpfs,devfs,etc).
# This is needed to make sure we don't have a mounted filesystem 
# on a LVM volume when shutting LVM down ...
echo "Unmounting filesystems ..."
unmounts="$( \
	awk '{ \
	    if (($3 !~ /^(proc|sysfs|devfs|tmpfs|usb(dev)?fs)$/) && \
	        ($1 != "none") && \
	        ($1 !~ /^(rootfs|\/dev\/root)$/) && \
	        ($2 != "/")) \
	      print $2 }' /proc/mounts | sort -ur)"
for x in $unmounts
do
	# Do not umount these if we are booting off a livecd
	if [ -n "${CDBOOT}" ] && \
	   [ "${x}" = "/mnt/cdrom" -o "${x}" = "/mnt/livecd" ]
	then
		continue
	fi

	x="${x//\\040/ }"
	if ! umount "${x}" &>/dev/null
	then
		# Kill processes still using this mount
		/bin/fuser -k -m -9 "${x}" &>/dev/null
		sleep 2
		# Now try to unmount it again ...
		umount -f -r "${x}" &>/dev/null
	fi
done

# Stop LVM
if [ -x /sbin/vgchange ] && [ -f /etc/lvmtab -o -d /etc/lvm ] && \
   [ -d /proc/lvm  -o "`grep device-mapper /proc/misc 2>/dev/null`" ]
then
	echo "Shutting down the Logical Volume Manager"
	/sbin/vgchange -a n >/dev/null
fi

# This is a function because its used twice below this line as:
#   [ -f /etc/killpower ] && ups_kill_power
ups_kill_power() {
	if [ -x /sbin/upsdrvctl ]
	then
		echo "Signalling ups driver(s) to kill the load!"
		/sbin/upsdrvctl shutdown
		echo "Halt system and wait for the UPS to kill our power"
		/sbin/halt -id
		while [ 1 ]; do sleep 60; done
	fi
}

mount_readonly() {
	local x=
	local retval=0
	local cmd="$1"

	# Get better results with a sync and sleep
	sync; sync
	sleep 1

	for x in $(awk '$1 != "none" { print $2 }' /proc/mounts | sort -r)
	do
		x="${x//\\040/ }"
		if [ "${cmd}" = "u" ]
		then
			umount -r -r "${x}"
		else
			mount -n -o remount,ro "${x}" &>/dev/null
		fi
	done
}

# Since we use `mount` in mount_readonly(), but we parse /proc/mounts, we 
# have to make sure our /etc/mtab and /proc/mounts agree
cp /proc/mounts /etc/mtab &>/dev/null
echo "Remounting remaining filesystems readonly ..."
mount_worked=0
if ! mount_readonly
then
	if ! mount_readonly
	then
		# If these things really don't want to remount ro, then 
		# let's try to force them to unmount
		if ! mount_readonly u
		then
			mount_worked=1
		fi
	fi
fi

if [ ${mount_worked} -eq 1 ]
then
        echo "Umount failed"
	#[ -f /etc/killpower ] && ups_kill_power
	#can't use ngc here, the sockets are closed.
	/sbin/sulogin -t 10 /dev/console
fi

# Inform if there is a forced or skipped fsck
if [ -f /fastboot ]
then
	echo
	echo "Fsck will be skipped on next startup"
elif [ -f /forcefsck ]
then
	echo
	echo "A full fsck will be forced on next startup"
fi
echo "Filesystems unmounted"

echo "syncing filesystem ..."
sync; sync

[ -f /etc/killpower ] && echo "ups kill power" && ups_kill_power

sync

/sbin/system_off $1

# Now idle forever.

while /bin/true; do sleep 1; done

#never get here.
