#! /bin/sh
# Copyright (c) 1996-2007 SuSE Linux Products GmbH, Nuernberg, Germany.
# All rights reserved.
#
# Author: Florian La Roche, 1996
#	  Werner Fink <werner@suse.de>, 1996-2001
#
# Please send feedback to http://www.suse.de/feedback
#
# /etc/init.d/halt (and symlinked to reboot)
#

. /etc/rc.status
. /etc/sysconfig/clock
. /etc/sysconfig/shutdown

test -s /etc/sysconfig/bootsplash && . /etc/sysconfig/bootsplash
test -e /proc/splash || SPLASH="no"

#
# Avoid being interrupted by child or keyboard
#
trap "echo" SIGINT SIGSEGV SIGQUIT SIGTERM
set +e

case "${0##*/}" in
    *halt)
	message="The system will be halted immediately."
	arch=$(/bin/uname -m)
	opts=""
	command="halt"
	#
	# Sysvinit's shutdown is knowning about the option -P and -H to set
	# the environment variable INIT_HALT within init for the runlevel 0.
	# If this variable is not set we use the system default.
	#
	if test -z "$INIT_HALT" ; then
	    case "$HALT" in
	    [Pp]*) INIT_HALT=POWEROFF ;;
	    [Hh]*) INIT_HALT=HALT     ;;
	    *)
		INIT_HALT=POWEROFF
		#
		# Check this if valid for AMD/Intel based systems
		#
		case "$arch" in
		i?86|x86_64)
		    if test -e /proc/apm -o -e /proc/acpi -o -e /proc/sys/acpi ; then
			INIT_HALT=POWEROFF
		    else
		    	INIT_HALT=HALT
			read -t 2 cmdline < /proc/cmdline
			case "$cmdline" in
			*apm=smp-power-off*|*apm=power-off*) INIT_HALT=POWEROFF
			esac
		    fi
		esac
	    esac
	fi
	#
	# The manual page of shutdown utilizes POWEROFF whereas in
	# the code the word POWERDOWN shows up for the option -P.
	#
	case "$INIT_HALT" in
	POWEROFF|POWERDOWN)
	    opts="${opts:+$opts }-p"
	esac
	#
	# Sometimes wake-on-lan isn't wanted, if so stop network
	#
	if test "$HALT_NETWORK" = "yes" ; then
	    opts="${opts:+$opts }-i"
	fi
	#
	# Sometimes it is wanted to stop also the disks, but
	# do not do this for software raids.
	#
	if test "$HALT_DISKS" = "yes" ; then
	    while read line ; do
		case "$line" in
		md.*active) HALT_DISKS=no; break
		esac
	    done < /proc/mdstat
	    test "$HALT_DISKS" = "no" || opts="${opts:+$opts }-h"
	fi
	;;
    *reboot)
	message="Please stand by while rebooting the system..."
	opts="-i"
	command="reboot"
	;;
    *)
	echo "$0: call me as \"halt\" or \"reboot\" please!"
	exit 1
	;;
esac

#
# first do local stuff
#
rc_reset
if test -e /etc/init.d/halt.local ; then
    echo Running /etc/init.d/halt.local
    /bin/sh /etc/init.d/halt.local
    rc_status -v1 -r
fi

# Write to wtmp file before unmounting /var
$command -w 

# Set a flag that we had success upto this point
> /success

# Stop blogd before umounting /var
test -x /sbin/blogd && killproc -QUIT /sbin/blogd

# give processes in front a chance to quit
hupon=""
for tty in tty1 tty2 tty3 tty4 tty5 tty6; do
    test -w /dev/$tty || continue
    test -c /dev/$tty || continue
    > /dev/$tty > /dev/null 2>&1 || continue
    hupon="${hupon:+$hupon }/dev/$tty"
done
test -z "$hupon" || fuser -sk -HUP $hupon

echo "Sending all processes the TERM signal..."
killall5 -15
echo -e "$rc_done_up"

# Wait between last SIGTERM and the next SIGKILL
declare -i etime=$SECONDS
if test -f /fastboot ; then
    etime=$((etime+2))
else
    etime=$((etime+6))
fi

ppid=$$
parent_processes="$ppid"
while test $ppid -ne 0; do
    read -t 1 pid comm state ppid rest < /proc/$ppid/stat
    parent_processes="${parent_processes:+$parent_processes }${ppid}"
done
for comm in /sbin/splash /sbin/blogd; do
    ppid="$(/sbin/pidofproc $comm)" || continue
    parent_processes="${parent_processes:+$parent_processes }${ppid}"
done
unset comm state ppid rest

while test $SECONDS -lt $etime; do
    left_processes=""
    for proc in /proc/[0-9]* ; do
	pid=${proc##*/}
	case "${parent_processes// /:}" in
	*:${pid}:*) continue
	esac
	/bin/ls -L ${proc}/exe > /dev/null 2>&1 || continue
	left_processes="${left_processes:+$left_processes }${pid}"
    done
    test -n "${left_processes}" || break
    usleep 500000
done
unset pid proc etime parent_processes left_processes

echo "Sending all processes the KILL signal..."
killall5 -9
echo -e "$rc_done_up"

# Redirect our mesages to default console
test -n "$REDIRECT" && exec 0<> $REDIRECT 1>&0 2>&0

#
# call modules in boot.d via K* symlinks
# (reverse sequence)
#

if test -d /etc/init.d/boot.d/ ; then
    for i in /etc/init.d/boot.d/K*; do
	test -f $i || continue
	if test -x "$i" ; then
	    # Active boot scripts, should have their own messages
	    $i stop
	else
	    # Old boot scripts, may not have any message
	    echo Skipping $i, not executable
	fi
    done
fi

# kill splash animation
test "$SPLASH" = yes && /sbin/splash -q


# on umsdos fs this would lead to an error message, so direct errors to
# /dev/null
mount -no remount,ro / 2> /dev/null
sync

# show "the system is down" message
test "$SPLASH" = yes && /sbin/splash -q -p 65535 -t "isdown"

# we do not really unmount /proc any more since halt(8) might need it
#umount -anvt proc

# Make reboot noise and wait a few seconds to give harddisks the chance
# to really flush their buffers before power goes down.
if test -n "$REDIRECT" ; then
    case "$HALT_SOUND" in
    "yes"|"quint")
	echo -en "\033[10;393]\a\033[10;262]"
	;;
    "octave")
	for tone in 524 491 440 393 349 328 295 262; do
	    echo -en "\033[10;${tone}]\a"
	    usleep 125000
	done
	echo -en "\033[10;262]"
	;;
    "no")
	;;
    *)
    	echo -en "\033[10;440]\a"
	usleep 250000
	;;
    esac
else
    test "$HALT_SOUND" = "no" || echo -en "\a"
fi
echo $message
test "$HALT_SOUND" = "no" || echo -en "\a"

test -n "$HALT_POWERDOWN_INSERT" && $HALT_POWERDOWN_INSERT

# Set system console back to intial value
test -n "$REDIRECT" -a -n "$CONSOLE" && setconsole $REDIRECT < $CONSOLE

# Now talk to kernel
exec $command -d -f -n $opts
