#!/usr/bin/ksh93

#
# This file is a part of the NsCDE - Not so Common Desktop Environment
# Author: Hegel3DReloaded
# Licence: GPLv3
#

PATH="/sbin:/usr/sbin:/usr/local/sbin:/bin:/usr/bin:/usr/local/bin:$PATH"
Action=$1

# Check for pm-utils
pmcnt=0
for cmd in pm-suspend pm-hibernate pm-suspend-hybrid
do
   whence -q $cmd
   if (($? == 0)); then
      (( pmcnt = pmcnt + 1 ))
   fi
done

# Check for FreeBSD (acpiconf) or SunOS
OS=$(uname -s)

# Check for systemd
whence -q systemctl
systemctlretval=$?

if [ "$OS" == "Linux" ]; then
   initmode=$(ps -p 1 -o comm=)
fi

if (($pmcnt == 3)); then
   Opmode="pm"
elif  (($systemctlretval == 0)) && [ "$initmode" == "systemd" ]; then
   Opmode="systemd"
elif [ "$OS" == "FreeBSD" ]; then
   whence -q acpiconf
   if (($? == 0)); then
      Opmode="acpiconf"
   fi
elif [ "$OS" == "DragonFly" ]; then
   whence -q acpiconf
   if (($? == 0)); then
      Opmode="acpiconf"
   fi
elif [ "$OS" == "SunOS" ]; then
   Opmode="sunos"
elif [ "$OS" == "NetBSD" ]; then
   Opmode="netbsd"
elif [ "$OS" == "OpenBSD" ]; then
   Opmode="openbsd"
else
   Opmode=$2
   if [ "x$Opmode" == "x" ]; then
      echo "Error: Unknown ACPI operation mode."
      exit 4
   fi
fi

function s3_suspend
{
   if [ "$Opmode" == "pm" ]; then
      pm-suspend
   elif [ "$Opmode" == "systemd" ]; then
      systemctl suspend -i
   elif [ "$Opmode" == "acpiconf" ]; then
      acpiconf -s 3
   elif [ "$Opmode" == "sunos" ]; then
      pfexec sys-suspend -n
   elif [ "$Opmode" == "netbsd" ]; then
      /sbin/sysctl -w hw.acpi.sleep.state=3
   elif [ "$Opmode" == "openbsd" ]; then
      /usr/sbin/apm -z
   fi
}

function hibernate
{
   if [ "$Opmode" == "pm" ]; then
      pm-hibernate
   elif [ "$Opmode" == "systemd" ]; then
      systemctl hibernate -i
   elif [ "$Opmode" == "acpiconf" ]; then
      acpiconf -s 4
   elif [ "$Opmode" == "sunos" ]; then
      pfexec sys-suspend -n
   elif [ "$Opmode" == "netbsd" ]; then
      echo "Notice: Hibernate to disk is not supported on NetBSD."
   elif [ "$Opmode" == "openbsd" ]; then
      /usr/sbin/apm -Z
   fi
}

function hybrid_suspend
{
   if [ "$Opmode" == "pm" ]; then
      pm-suspend-hybrid
   elif [ "$Opmode" == "systemd" ]; then
      systemctl hybrid-sleep -i
   elif [ "$Opmode" == "acpiconf" ]; then
      echo "Not available on $OS" >&2
   elif [ "$Opmode" == "sunos" ]; then
      pfexec sys-suspend -n
   elif [ "$Opmode" == "netbsd" ]; then
      echo "Notice: Hybrid suspend is not supported on NetBSD."
   elif [ "$Opmode" == "openbsd" ]; then
      echo "Notice: Hybrid suspend is not supported on OpenBSD."
   fi
}

function f_poweroff
{
   if [ "$OS" == "Linux" ]; then
      if  (($systemctlretval == 0)) && [ "$initmode" == "systemd" ]; then
         systemctl poweroff -i
      else
         shutdown -h now
      fi
   elif [ "$OS" == "FreeBSD" ]; then
      shutdown -p now
   elif [ "$OS" == "SunOS" ]; then
      pfexec shutdown -i5 -g0 -y
   elif [ "$OS" == "NetBSD" ]; then
      /sbin/shutdown -p now
   elif [ "$OS" == "OpenBSD" ]; then
      /sbin/shutdown -p now
   elif [ "$OS" == "DragonFly" ]; then
      /sbin/shutdown -p now
   fi
}

function f_reboot
{
   if [ "$OS" == "Linux" ]; then
      if  (($systemctlretval == 0)) && [ "$initmode" == "systemd" ]; then
         systemctl reboot -i
      else
         shutdown -r now
      fi
   elif [ "$OS" == "FreeBSD" ]; then
      shutdown -r now
   elif [ "$OS" == "SunOS" ]; then
      pfexec shutdown -i6 -g0 -y
   elif [ "$OS" == "NetBSD" ]; then
      /sbin/shutdown -r now
   elif [ "$OS" == "OpenBSD" ]; then
      /sbin/shutdown -r now
   elif [ "$OS" == "DragonFly" ]; then
      /sbin/shutdown -r now
   fi
}

function usage
{
   echo "Usage: ${0##*/} [ suspend | hibernate | hybrid-suspend | poweroff | reboot ] [ opmode ]"
   exit 0
}

if [[ -z $Action || -z $Opmode ]]; then
   usage
   exit 1
fi

case $Action in
   'suspend')
      s3_suspend
   ;;
   'hibernate')
      hibernate
   ;;
   'hybrid-suspend')
      hybrid_suspend
   ;;
   'poweroff')
      f_poweroff
   ;;
   'reboot')
      f_reboot
   ;;
   'help')
      usage
   ;;
esac

