#!/bin/sh
# Do unmount/remount-ro. Wait.
# KILL everybody. Wait.
# Repeat.

umountcnt=2
writeout=2

# No /usr - we are expecting all binaries to be accessible from
# root fs alone
PATH=/bin

function say() {
    printf "\r%s\n\r" "$*"
}

# Useful for debugging
function doit() {
    ## say "# $@"
    "$@"
}

function showps() {
    # sleep 1 ensures that xargs will have time to start up
    # this makes pslist less prone to random jitter
    pslist=`{ sleep 1; ps -A -o comm=; } | xargs`
    pscnt=$(( 0 + `say "$pslist" | wc -w` ))
    say "* `date '+%H:%M:%S'` Processes ($pscnt): $pslist"
}

say "<*> `date '+%Y-%m-%d %H:%M:%S'` Executing '$0 $*'"

showps

i="$umountcnt"
while test "$i" -gt 0; do
    say "* `date '+%H:%M:%S'` Unmounting filesystems"
    doit umount -a -n -r -v -f 2>&1 | tee /dev/tty12
    # In case we unmounted proc...
    test -e /proc/version || mount -t proc none /proc
    # Remounting / RO isn't necessary when /etc/mtab is linked to /proc/mounts:
    # already done. But let's be more paranoid here...
    say "* `date '+%H:%M:%S'` Remounting root filesystem read-only"
    doit mount -n -v -o remount,ro /
    say "* `date '+%H:%M:%S'` Freeing loop devices"
    for a in /dev/loop*; do
	test -b "$a" && doit losetup -d "$a"
    done
    say "* `date '+%H:%M:%S'` Syncing"
    sync

    sleep 1

    say "* `date '+%H:%M:%S'` Executing: killall5 -KILL"
    doit killall5 -9

    showps
    i=$((i-1))
done

say "* `date '+%H:%M:%S'` Filesystem status (/proc/mounts)"
cat /proc/mounts \
| { 
    bad=0
    while read dev mntpoint fstype opt n1 n2; do
        say "$dev $mntpoint $fstype $opt $n1 $n2"
	case "$dev" in
	( rootfs | devfs | devpts | proc | none )
	    continue
	    ;;
	esac
        if test "${opt:0:2}" = "rw"; then
	    bad=1
	fi
    done
    exit "$bad"
}
if test "$?" = "1"; then
    say "ERROR: we have filesystems mounted RW! Press <Enter> (^J)..."
    read junk </dev/console
fi

say "* `date '+%H:%M:%S'` TODO: disk cache writeout"
sleep "$writeout"

exit 0
