#!/bin/sh
# Nico Schottelius (nico-cinit /at/ schottelius.org)
# 2007-05-21
# Behave as being shutdown from Linux' sysvinit

# Always needed variables / functions
_0_short=${0##*/}
_o_seperator=":"
_oecho_seperator=":"
_eecho_seperator=">"

# ok-exit/echo
_oecho()
{
   echo "${_0_short}${_oecho_seperator}" "$@"
}

_oexit()
{
   _oecho "$@"
   exit 0
}

# error-exit/echo
_eecho()
{
   echo "${_0_short}${_oecho_seperator}" "$@" >&2
}

_eexit()
{
   _eecho "$@"
   exit 1
}

# Program specific variables

time_t=0       # -t sec
warn_only_k=0  # -k
reboot_r=0     # -r
halt_h=0       # -h
poweroff_P=0   # -P
cancel_c=0     # -c
time=-1        # [time]
message=""     # [warning-message]
cmd=""         # what to execute internally
pidfile="/var/run/cinit.shutdown"
pid=""
runs=""

version="0.1"
version_date="2007-10-30"

message_intro="The system is going down for"
message_reboot="reboot"
message_halt="halt"
message_poweroff="poweroff"

# unimplemented: -a, -H, -f, -F
# deprecated and thus not implemented: -n

# traping signals
trap_signals()
{
   _oexit "Aborted shutdown"
}

# all the functions

usage()
{

cat << cinit_usage

*** cinit linux-sysvinit shutdown wrapper (Version ${version} ${version_date}) ***

Usage   shutdown [-akrhHPfnc] [-t secs] time [warning message]
        -a:      use /etc/shutdown.allow
        -k:      don't really shutdown, only warn.
        -r:      reboot after shutdown.
        -h:      halt after shutdown.
        -P:      halt action is to turn off power.
        -H:      halt action is to just halt.
        -f:      do a 'fast' reboot (skip fsck).
        -F:      Force fsck on reboot.
        -n:      do not go through "init" but go down real fast.
        -c:      cancel a running shutdown.
        -t secs: delay between warning and kill signal.
        ** the "time" argument is mandatory! (try "now") **

You can also call "cinit.{halt|reboot|poweroff}" directly
(instead of using this wrapper).

cinit_usage

exit 0

}

warn()
{
   ( echo ""; echo "$@"; echo "" ) | wall
   ( echo ""; echo "$@"; echo "" )
}

if [ "$#" -lt 1 ]; then
   usage
fi

# getopt!
while [ "$#" -ge 1 ]; do
   arg="$1"; shift

   case "${arg}" in
      -a|-F|-f|-n)
         _oexit "Sorry, ${arg} is not implemented."
      ;;
      -t)
         if [ "$#" -lt 1 ]; then
            _eexit "-t needs the time argument"
         fi
         time_t="$1"; shift
      ;;
      -k)
         warn_only_k=1
         cmd=true
      ;;
      -r)
         reboot_r=1
         cmd=cinit.reboot
         message_what="${message_reboot}"
      ;;
      -h|-H)
         halt_h=1
         cmd=cinit.halt
         message_what="${message_halt}"
      ;;
      -P)
         poweroff_P=1
         cmd=cinit.poweroff
         message_what="${message_poweroff}"
      ;;
      -c)
         cancel_c=1
      ;;
      *)
         # time unset?
         if [ "${time}" = -1 ]; then
            time="${arg}"
            [ "${time}" = "now" ] && time=0
         elif [ -z "${message}" ]; then
            message="${arg}"
         else
            _eexit "Already specified time and message"
         fi
      ;;
   esac
done

if [ -f "${pidfile}" ]; then
   pid=$(cat "${pidfile}")
   runs=$(kill -CONT "${pid}" >/dev/null 2>&1 && echo yes)
fi

# do cancel or abort or locking
if [ "${cancel_c}" -eq 1 ]; then
   if [ "${runs}" ]; then
      kill -TERM "${pid}"
      _oexit "Terminated running shutdown at \"${pid}\"."
   else
      _eexit "Cannot abort shutdown, not running."
   fi
fi

if [ -z "${time}" ]; then
   usage
fi

if [ -z "${cmd}" ]; then
   _eexit "You need to specify one of -h, -P, -H, -r."
fi

# add lock
if [ "${pid}" ]; then
   if [ "${runs}" ]; then
      _eexit "Shutdown already running."
   else
      _oecho "Overwriting stale pidfile"
   fi
fi
echo $$ > "${pidfile}"

if [ "${message}" ]; then
   warn "${message}"
fi

# signals to abort on
trap trap_signals INT HUP TERM

while [ "${time}" -gt 0 ]; do
   warn "${message_intro} ${message_what} in ${time} minute(s)."
   sleep 60
   time=$((${time}-1))
done

warn "${message_intro} ${message_what} now."
"${cmd}"
