#!/bin/sh
##### DO NOT CHANGE COMMENT LINES WITH start/end STATEMENT
##### DO NOT ADD LINE BEFORE THIS ONE: --install depends on it

VERSION="0.18"
if ( echo $@ | grep -e "--version" ) 1> /dev/null; then
    echo "Installation script:     $0"
    echo "suspend script (Version: $VERSION)"
    exit 0
fi

PATH=$PATH:/sbin:/usr/sbin:/usr/local/sbin


##################### CHANGELOG start #########################################
# ChangeLog:
# 0.18: - disable module loading during swsusp to avoid automatic reloading
#         from Josh Litherland (josh at emperorlinux dot com)
#       - fixed gentoo modules_autoload location (cr at darav dot de)
#       - always restore clock even if suspend noted some failure
#         (markus-dreyer at gmx dot de)
#       - added SWSUSP_START_PROGS_BEFORE_SUSPEND option (Kim Oldfield)
# 0.17: - changed help message handling
#       - detect /proc/sys/kernel/swsusp or /proc/swsusp/all_settings
#       - create Xauthority file in /tmp to avoid clobbering user's xauth
#         from Josh Litherland (josh at emperorlinux dot com)
#       - eliminated compilation of usleep
# 0.16: - fix RedHat RLVLDIR bug.
#       - standardised install into /usr/local/sbin
#       - made installer portion of the script saner
#       from Hiroshi Miura (miura at da-cha org) &
#            Dustin Mitchell (djmitche at sf net):
#       - added "auto" option on SWSUSP_UNLOAD_MODULES_BEFORE_SUSPEND
#       - added SWSUSP_REMOVEMODS.
#       - elaborated on $PATH - Marius Groeger (mag at sysgo de)
#       - added alternate usleep method (perl select)
# 0.15: - Fix for SuSE detection (nico at nickas de)
#       - POSIX compliancy fixes
#            -- Gabor Fleischer (swsusp at exodus fleischer hu)
#       - Commented out swap detection for now (Gabor Fleischer)
#       - Customisable VT (Ka-shu Wong - kswong at zip com au)
# 0.14.2: - Use /proc/swsusp/activate to activate. shutdown+z no longer required
#            -- BernardB.
# 0.14.1: - Call shutdown+z instead of echo. shutdown+z must be in path
#            -- BernardB.
# 0.14: - Add a --verbose option
#       - Remove ppp0 as default interface to stop (ifdown script cannot
#         work with ppp0).
#       - Change pppd for /usr/sbin/pppd in Mandrake conf (add a distro
#         depending variable for that).
# 0.13: - Add ppp0 as default in interfaces to stop
#       - Add vmware and pppd progs as non compatible progs
#       - Use of tee instead of cat for LOGCMD (problem with redirection char)
#         and redirection to /dev/null for standard output of LOGCMD.
#       - Add beep mention (beta19 and above) in comment of
#         SWSUSP_FORCE_SUSPEND_MODE (default unchanged)
# 0.12: - Add -x c for gcc compilation (roland.stigge@antcom.de)
#       - Change lock dir to /var/lock for Debian
#       - Defaults to VT number 7 if ORIGINAL_VT isn't correct
#       - Fix a return bug in SwitchFromX
#       - Introduce a "| $LOGCMD" instead of "> $VERBOSE". This is first step
#         of a modification that would allow to log to stdout, VT9, /tmp/logfile,
#         etc. in parallel
#       - When compiling usleep, enter directory instead of fullname
# 0.11: - Modification of Mandrake detection
#       - Change order of variables in default configuration file
# 0.10: - Merge with 0.9-go1 version by Gunter Ohrner
#        <G.Ohrner@post.rwth-aachen.de>:
#          - extended the PATH to contain /usr/local/s?bin - why is this script meddeling
#            with the PATH anyway? (OK suppressed)
#          - improved usleep auto generation/installation procedure
#          - fixed incorrect double-start of the fake X if SWSUSP_LEAVE_X_BEFORE_SUSPEND is
#            set to nVidia and incorrect VT switching in other cases. The new logic DEPENDS
#            on the presense of fgconsole but that could easily be conditionalized to
#            get the old behaviour again if fgconsole is not present. (If there ARE systems
#            where it's missing.)
#       - Fix INITDIR/RLVLDIR bug that makes the services not started/stopped.
#       - Change behaviour of SWSUSP_START/STOP_SERVICES to *not* check init states. Some
#         distros (e.g. Mandrake) have scripts called directly by rc.sysinit and we want to
#         force a start/stop.
#       - Change Mandrake defaults to properly restore usb devices.
# 0.9: - Change suspend script name to hibernate upon installation.
#      - Create a suspend.conf.new file to help merging between versions of this script.
#      - Merge version 0.7-cr7 sent by Carsten Rietzschel <cr@daRav.de>
#      - fixed a typo in RemountDevices() (REMOUNT_S_)
#      - added kill_prog/start_progs: the apps are killed or started (no need to be an service)
#         - hwclock output directed to $VERBOSE
#         - xinit and xauth output directed to /dev/null
#      - update for Gentoo (there the script is in /sbin/sw-suspend
#         - no >$VERBOSE in installation part
#         - colorfull ouput
#         - more informations and verbose-console setting (default is console 9)
#      - Merge with changes by Ulrich.Lauther@siemens.com:
#         - install and changelog sections are NOT copied to output script
#         - changed name of generated script to "hibernate" to avoid
#           conflict with bash's suspend command and with (hopefully to come?)
#           suspend to RAM
#         - added check for activated swap-space
#         - added Slackware section
#         - added more explanation to FORCE_SUSPEND_MODE parameter
#         - improved support for systems without usleep
#      - As suggested by Gunter, add a sanity check before using gcc
# 0.8: - Redhat updates sent by Nicolas Appert <Nicolas.Aspert@epfl.ch>
# 0.7: - Fix auto bug in start services with 0.6-go1 version by Gunter Ohrner
#        <G.Ohrner@post.rwth-aachen.de>:
#         - splitted SWSUSP_STOP_SERVICES_BEFORE_SUSPEND/auto into
#           SWSUSP_RESTART_SERVICES, SWSUSP_STOP_SERVICES_BEFORE_SUSPEND
#           and SWSUSP_START_SERVICES_AFTER_RESUME so you can "start but
#           not stop" or "stop but not start" scripts without loosing the
#           "smart" service restart facility (suspend.sh's "auto"
#           behaviour)
#         - Tweaked the init-script-call-order a bit such that
#           incorrectly switched script calls are avoided (I hope...)
#         - A bug in STOP_SERVICES-auto-mode introduced in 0.6 and caused
#           by merging my 0.5-go1 changes into the official script was
#           fixed/removed by these changes.
#         - cleaned up and sorted Debian GNU/Linux's RESTART_SERVICES
#           default list
# 0.6: - Change pcmcia order for redhat (default stuff)
#      - Merge with 0.5-go1 version by Gunter Ohrner <G.Ohrner@post.rwth-aachen.de>:
#        - Fix a bug introduced in RestartServices: one want to restart services in
#          reverse order in auto mode.
# 0.5-go1:
#      - Check for all init scripts mentioned in the config file whether
#        they need to be called and call them in the order specified in the
#        runlevel configuration.
#      - Add support for Debian GNU/Linux
# 0.5: - Fix for multiple ttys by server X (deleted)
#      - Fix uncorrect trick with nvidia option, deal with xauth,
#        and add more user friendly pop-up message
#      - Add an hdparm command to disable cache writing before suspend
# 0.4: - Add a --version option
#      - Add the xinit /bin/false trick for NVidia cards
#      - Suppress vmware in defaults stopped services
#      - Add a sync call
#      - Reverse the default SWSUSP_SAVE_CLOCK_ON_SUSPEND to "no" because
#        if a problem occur and we don't restore clock on resume, then
#        we'll corrupt the CMOS clock.
#      - Use /bin/echo instead of builtin for suspending. It seems that
#        sometimes echo 4 > /proc/acpi/sleep never returns, so we execute
#        it in background.
#      - Test executables /etc/init.d scripts instead of readable.
#      - Modify Mandrake detection since drakconf place has changed.
#      - Add postfix and nfs to default stop services
#      - /dev/tty may not be available: adding a test and /dev/console output
# 0.3: - Add version, fix typos (french message :-) and add changelog.
#      - Modify hw clock use. Always read on resume, but write before
#        suspend is configurable (to fix drift amplification problem)
#      - Add a diff in install phase when configuration file already exists
#      - Change gpm place in default start/stop services.
#      - Add a test for root id
#      - Add some udelays for proper unloading of modules
#      - Add a lock file to prevent two scripts from running together
#      - Add a configuration option for using acpi interface or
#        enable reboot instead of halt
#      - Change alsa place in default start/stop services, since usb
#        and pcmcia can use snd module to notify events.
#      - Add a check on running of some incompatible programs.
#      - Restore console font
#      - Add a --nosuspend option
#      - Modify --install procedure to suit different distros
# 0.2: - Modification by Florent (fchabaud@free.fr): first version
#        published at sourceforge.net
#      - Add a --install option that installs the script and its
#        configuration file /etc/suspend.conf
#      - Add state control to exactly recover session when suspending
#        is aborted.
#      - Completely reorganize script (sorry Doug :-)
#        - suppress the smbfs and nfs unmounts (rationale: this
#          should be left to configuration - the user can set its samba
#          mount points if he/she wants them to be unmounted)
#        - suppress the grub/lilo alteration (rationale: I don't like
#          the idea that swsusp can modify the boot configuration of a machine ;-)
#        - modify the modules loading/unloading. The script now try to
#          unload all unused modules. On resume the specified modules
#          are loaded, whether they were unloaded or not (rationale:
#          this should be more robust).
# 0.1: First script posted by Doug (doug@tunl.duke.edu)
#
##################### CHANGELOG end #########################################

TMP=/dev/shm/suspend.$$
if ! touch $TMP 2> /dev/null ; then
    TMP=/tmp/suspend.$$
    if ! touch $TMP 2> /dev/null ; then
        echo "Can't open a temporary file in /dev/shm nor /tmp"
        echo "Aborting !"
        exit 1
    fi
fi

ID=`id -u`
if [ "$ID" != "0" ]; then
    echo "You must be root to use this script."
    echo "Use sudo to enable it for users."
    exit 1
fi

if ( echo $@ | grep -e "--verbose" ) 1> /dev/null; then
    if [ -w /dev/tty ] ;then
        VERBOSE='/dev/tty'
    else
        VERBOSE='/dev/console'
    fi
else
    VERBOSE='/dev/null'
fi

# This overides failsafe cancellation and forces suspend or installation
if ( echo $@ | grep -e "--force" ) 1> $VERBOSE; then
    FORCE='yes'
else
    FORCE='no'
fi

EXE=`basename $0`
unset AM_IN_INSTALLER

##################### INSTALL start ###########################################

AM_IN_INSTALLER=1

if ( echo $@ | grep -e "--install" ) 1> $VERBOSE; then
    DISTRIB=Unknown
    if [ -d /etc/rc.config.d ] ; then
        DISTRIB=SuSE
    elif [ -f /etc/SuSE-release ] ; then
        DISTRIB=New_SuSE
    elif [ -f /etc/mandrake-release ] ; then
        DISTRIB=Mandrake
    elif [ -f /etc/debian_version ] ; then
        DISTRIB=Debian
    elif [ -f /etc/redhat-release ] ; then
        DISTRIB=Redhat
    elif [ -f /etc/gentoo-release ] ; then
        DISTRIB=Gentoo
    elif [ -f /etc/slackware-version ] ; then
        DISTRIB=Slackware
    fi
    echo Detected distribution: $DISTRIB
    BINNAME=hibernate
    INSTALLER=`pwd`/$0
    case "$DISTRIB" in
        SuSE)
            CONFIGFILE=/etc/rc.config.d/suspend.rc.config
            INITDIR=/etc/init.d
            RLVLDIR=/etc/rc.d
            INSTALLDIR=/usr/local/sbin
            IFDOWN=$INITDIR/network
            OPTDOWN=stop
            IFUP=$INITDIR/network
            OPTUP=start
            SHELL=/bin/bash
            LOCKFILE=/var/lock/subsys/swsusp
            SETSYSFONT=$INITDIR/kbd
            OPTSYSFONT=start
            DEFAULTSTARTSERVICES=
            DEFAULTRESTARTSERVICES="postfix alsasound irda gpm xntpd inetd nfs dhclient network pcmcia usbmgr"
            DEFAULTSTOPSERVICES=
            SWSUSP_UMOUNTS="/floppy /cdrom /var/adm/mount"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
        ;;
        New_SuSE)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc/rc.d
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/sbin/ifdown
            OPTDOWN=
            IFUP=/sbin/ifup
            OPTUP=
            SHELL=/bin/bash
            LOCKFILE=/var/lock/subsys/swsusp
            SETSYSFONT=$INITDIR/kbd
            OPTSYSFONT=start
            DEFAULTSTARTSERVICES=
            DEFAULTRESTARTSERVICES="postfix alsasound irda gpm xntpd inetd nfs dhclient network pcmcia usbmgr"
            DEFAULTSTOPSERVICES=
            SWSUSP_UMOUNTS="/floppy /cdrom /var/adm/mount"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
        ;;
        Mandrake)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc/rc.d
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/etc/sysconfig/network-scripts/ifdown
            OPTDOWN=
            IFUP=/etc/sysconfig/network-scripts/ifup
            OPTUP=
            SHELL=/bin/bash
            LOCKFILE=/var/lock/subsys/swsusp
            SETSYSFONT=/sbin/setsysfont
            OPTSYSFONT=
            DEFAULTSTARTSERVICES="usb netfs alsa"
            DEFAULTRESTARTSERVICES="postfix xntpd xinetd nfs gpm pcmcia irda sound"
            DEFAULTSTOPSERVICES="alsa netfs usb"
            SWSUSP_UMOUNTS="/mnt/floppy /mnt/cdrom"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS="/usr/sbin/pppd"
        ;;
        Debian)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/bin/true
            OPTDOWN=
            IFUP=/bin/true
            OPTUP=
            SHELL=/bin/sh
            LOCKFILE=/var/lock/swsusp
            SETSYSFONT=$INITDIR/console-screen.sh
            OPTSYSFONT=
            DEFAULTSTARTSERVICES="mountnfs.sh modutils"
            DEFAULTRESTARTSERVICES="postfix exim ntpdate xntpd inetd xinetd noflushd sleepd anacron gpm pcmcia irda alsa setserial etc-setserial nfs-common networking ifupdown netenv laptop-net ipsec"
            DEFAULTSTOPSERVICES="umountnfs.sh"
            SWSUSP_UMOUNTS="/mnt /floppy /cdrom"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
            ;;
        Slackware)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc
            INSTALLDIR=/usr/local/sbin
            IFDOWN=$INITDIR/ifdown
            OPTDOWN=""
            IFUP=$INITDIR/ifup
            # note: 
            # you must provide ifdown and ifup, typically just
            # ifconfig eth0 up/down
            OPTUP=""
            SHELL=/bin/sh
            LOCKFILE=/var/lock/subsys/swsusp
            SETSYSFONT=
            OPTSYSFONT=
            DEFAULTSTARTSERVICES=
            DEFAULTRESTARTSERVICES="postfix inetd pcmcia irda sound sshd lpd "
            DEFAULTSTOPSERVICES=""
            SWSUSP_UMOUNTS="/mnt /floppy /cdrom"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
            ;;
        Redhat)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/etc/init.d/network
            OPTDOWN=stop
            IFUP=/etc/init.d/network
            OPTUP=start
            SHELL=/bin/bash
            LOCKFILE=/var/lock/subsys/swsusp
            SETSYSFONT=/sbin/setsysfont
            OPTSYSFONT=
            DEFAULTSTARTSERVICES=
            DEFAULTRESTARTSERVICES="postfix ntpd xinetd nfs network pcmcia irda gpm"
            DEFAULTSTOPSERVICES=""
            SWSUSP_UMOUNTS="/mnt/floppy /mnt/cdrom"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
            ;;
        Gentoo)
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc/init.d
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/etc/init.d/net.eth0
            OPTDOWN=stop
            IFUP=/etc/init.d/net.eth0
            OPTUP=start
            SHELL=/bin/sh
            LOCKFILE=/var/lock/swsusp
            SETSYSFONT=
            OPTSYSFONT=
            DEFAULTSTARTSERVICES=""
            DEFAULTRESTARTSERVICES=""
            DEFAULTSTOPSERVICES=""
            SWSUSP_UMOUNTS="/mnt /floppy /cdrom"
            SWSUSP_INSERTMODS="modules.autoload"
            SWSUSP_NON_COMPATIBLE_PROGS=""
            ;;
        *) 
            CONFIGFILE=/etc/suspend.conf
            INITDIR=/etc/init.d
            RLVLDIR=/etc/rc.d
            INSTALLDIR=/usr/local/sbin
            IFDOWN=/etc/sysconfig/network-scripts/ifdown
            OPTDOWN=
            IFUP=/etc/sysconfig/network-scripts/ifup
            OPTUP=
            SHELL=/bin/sh
            LOCKFILE=/var/lock/swsusp
            SETSYSFONT=/sbin/setsysfont
            OPTSYSFONT=
            DEFAULTSTARTSERVICES=
            DEFAULTRESTARTSERVICES="postfix xntpd inetd xinetd nfs pcmcia network gpm irda sound alsa alsasound kbd usb usbmgr"
            DEFAULTSTOPSERVICES=
            SWSUSP_UMOUNTS="/misc/floppy /misc/cd /mnt/floppy /mnt/cdrom /floppy /cdrom"
            SWSUSP_INSERTMODS=""
            SWSUSP_NON_COMPATIBLE_PROGS=""
        ;;
    esac

    DATE=`date`
    cat > $TMP <<EOF
#! $SHELL

if ( echo \$@ | grep -e "--version" ) 1> $VERBOSE; then
    echo "Script:       \$0"
    echo "Installed by: $INSTALLER"
    echo "Installation: $DATE"
    echo "Distribution: $DISTRIB"
    echo "Version:      $VERSION"
    exit 0
fi

CONFIGFILE=$CONFIGFILE
INITDIR=$INITDIR
RLVLDIR=$RLVLDIR
IFDOWN=$IFDOWN
OPTDOWN=$OPTDOWN
IFUP=$IFUP
OPTUP=$OPTUP
LOCKFILE=$LOCKFILE
SETSYSFONT=$SETSYSFONT
OPTSYSFONT=$OPTSYSFONT
DISTRIB=$DISTRIB

# DO NOT EDIT THIS FILE (change the script `pwd`/$0 and reinstall)
EOF
    awk '
      BEGIN { copy = 1
              # skip first three lines:
              getline
              getline
              getline
      }
      # note: patterns below match twice!! once where they occur in
      # the rest of the script, once right here,
      # that is why we do not set copy, but increment
      # the idea is, NOT to copy install and changelog section to the
      # output script
      /CHANGELOG start/ { copy--; next }
      /CHANGELOG end/   { copy++; next }
      /INSTALL start/   { copy--; next }
      /INSTALL end/     { copy++; next }
      { if (copy > 0) print $0
      } ' $0 >> $TMP
    
    if [ ! -d $INSTALLDIR ] ;then
        echo "Directory $INSTALLDIR doesn't exist: installation aborted"
        rm $TMP
        exit 2
    fi
   
    echo "Creating $INSTALLDIR/$BINNAME"
    if ! (mv -f $TMP $INSTALLDIR/$BINNAME) ;then
        echo "Cannot install $INSTALLDIR/$BINNAME"
        rm $TMP
        exit 1
    fi
    chmod 700 $INSTALLDIR/$BINNAME

    # todo: Maybe create a small function to prevent this code duplication?
    SWSUSP_STOP_SERVICES_BEFORE_SUSPEND=
    for service in $DEFAULTSTOPSERVICES ;do
        if [ -x $INITDIR/$service ] ; then
            SWSUSP_STOP_SERVICES_BEFORE_SUSPEND="$SWSUSP_STOP_SERVICES_BEFORE_SUSPEND $service"
        fi
    done
    SWSUSP_START_SERVICES_AFTER_RESUME=
    for service in $DEFAULTSTARTSERVICES ;do
        if [ -x $INITDIR/$service ] ; then
            SWSUSP_START_SERVICES_AFTER_RESUME="$SWSUSP_START_SERVICES_AFTER_RESUME $service"
        fi
    done
    SWSUSP_RESTART_SERVICES=
    for service in $DEFAULTRESTARTSERVICES ;do
        if [ -x $INITDIR/$service ] ; then
            SWSUSP_RESTART_SERVICES="$SWSUSP_RESTART_SERVICES $service"
        fi
    done

    cat > $TMP <<EOF
#-*-mode: sh-*-
# Configuration of software suspension
#

# If your graphic device is not able to return properly from suspend
# you can switch to textconsole before suspend and return to your
# X-console after resume.
# If you use an nvidia card, you can set this to nvidia. This
# will try to restore your 3D upon resume. This trick may be useful
# for other cards.
# Default: "no"
SWSUSP_LEAVE_X_BEFORE_SUSPEND="no"

# Some services (e.g. network) may cause some hangs if they are not
# stopped before a suspend/resume cycle. You can set
# SWSUSP_RESTART_SERVICES to a list of services to stop before suspend
# and automatically restart after resume.
# If suspending results in killing some application because of lack
# of memory, you may also add here some of your launched services,
# so as to save memory. Good candidates are httpd, nfsserver, sendmail, etc.
# Default: "$SWSUSP_RESTART_SERVICES"
SWSUSP_RESTART_SERVICES="$SWSUSP_RESTART_SERVICES"

# Some services may need to be stopped before a suspend/resume cycle.
# You can set STOP_SERVICES_BEFORE_SUSPEND to a list of services to stop
# before suspend. These services will NOT automatically be restarted after
# the resume, use SWSUSP_RESTART_SERVICES instead if you want this
# behaviour.
# Default: "$SWSUSP_STOP_SERVICES_BEFORE_SUSPEND"
SWSUSP_STOP_SERVICES_BEFORE_SUSPEND="$SWSUSP_STOP_SERVICES_BEFORE_SUSPEND"

# Conversely, you can set START_SERVICES_AFTER_RESUME to a list
# of services to start after resuming.
# Default: "$SWSUSP_START_SERVICES_AFTER_RESUME"
SWSUSP_START_SERVICES_AFTER_RESUME="$SWSUSP_START_SERVICES_AFTER_RESUME"

# Those are programs that prevent from suspending. If they are
# running and --force or --kill option aren't used, suspension
# is aborted.
# Default: "$SWSUSP_NON_COMPATIBLE_PROGS"
SWSUSP_NON_COMPATIBLE_PROGS="$SWSUSP_NON_COMPATIBLE_PROGS"

# You can ask to killall these applications before suspend.
# Default: none
SWSUSP_STOP_PROGS_BEFORE_SUSPEND=""

# You can ask to run some applications before suspend using this variable.
# For instance, it may stop your VPN.
# Default: none
SWSUSP_START_PROGS_BEFORE_SUSPEND=""

# You can ask to run some applications after resume using this variable.
# For instance, it may restart your ADSL connection.
# Default: none
SWSUSP_START_PROGS_AFTER_RESUME=""

# If the following mount points cannot be unmounted, 
# then suspension is aborted unless --force or --kill
# option is used on command line
# Default: "$SWSUSP_UMOUNTS"
SWSUSP_UMOUNTS="$SWSUSP_UMOUNTS"

# These mount points should be mounted after suspend
# They should appear in /etc/fstab
# Default: none
SWSUSP_REMOUNTS=""

# If the following interfaces cannot be stopped, 
# then suspension is aborted unless --force or --kill
# option is used on command line
# Default: "eth0"
SWSUSP_DOWNIFS="eth0"

# These interfaces should be started after suspend
# With "auto" the interfaces stopped before suspension
# will be started in reverse order.
# Default: "auto"
SWSUSP_UPIFS="auto"

# Some modules should be unloaded before a suspend/resume cycle. You
# can set UNLOAD_MODULES_BEFORE_SUSPEND to "yes" if you want
# unused modules to be removed from kernel space before suspend. 
# This will be done after stopping services.
# With "no", nothing will be done before suspension.
# With "auto", it only does "rmmod -a" to clean modules
# which are marked "(autoclean)" in lsmod. 
# 
# Default: "yes"
SWSUSP_UNLOAD_MODULES_BEFORE_SUSPEND="yes"

# These modules should be unloaded after stopping services but
# before suspending.
# Default: $SWSUSP_INSERTMODS
SWSUSP_REMOVEMODS="$SWSUSP_INSERTMODS"

# These modules should be loaded after suspend
# Gentoo users can use "modules.autoload" here to read modules out of
# /etc/modules.autoload (this requires other Gentoo-specific scripts)
# Default: $SWSUSP_INSERTMODS
SWSUSP_INSERTMODS="$SWSUSP_INSERTMODS"

# Use SWSUSP_FORCE_SUSPEND_MODE to reset the behaviour of
# suspension. If empty, this let the suspension
# behaviour unchanged. Otherwise, these values will cause:
#   echo "0 \$SWSUSP_FORCE_SUSPEND_MODE" > /proc/swsusp/all_settings"
#
# This is simply a quick way of setting your favourite swsusp
# parameters. To determine the value of SWSUSP_FORCE_SUSPEND_MODE,
# tweak the files in /proc/swsusp to your heart's content, and then
# use `cat /proc/swsusp/all_settings`. The value of
# SWSUSP_FORCE_SUSPEND_MODE will be all but the first number. eg,
#     # cat /proc/swsusp/all_settings
#     0 2048 0 100
# means you should have SWSUSP_FORCE_SUSPEND_MODE="2048 0 100"
#
# Alternatively, you can use the keyword "acpi" to use the
# /proc/acpi/sleep interface in place of /proc/swsusp/all_settings
#
# Default: "0", i.e. halt, escape disabled. extra settings are untouched
SWSUSP_FORCE_SUSPEND_MODE="0"

# If you have problems with hardware clock drift amplified by
# suspension, try to set SAVE_CLOCK_ON_SUSPEND to "yes". The
# kerneltime will being saved before suspending. If you have
# network access, best is to set this variable to yes and add
# xntpd in services to start/stop below. If you haven't such
# a service permanently available, it is better to leave it
# to no, so that hardware clock remains as a reference for
# the system.
# Default: "no"
SWSUSP_SAVE_CLOCK_ON_SUSPEND="no"

# On some hardware, the power is cut off before the disk has 
# flushed his own hardware cache. Insert the device of your
# swap partition here (e.g. /dev/hda) if you want to issue
# hdparm -W 0 <device>
# before suspension.
# Default: none
SWSUSP_DISABLE_HW_DISK_CACHE=""

# This specifies the VT on which logging will occur if --silent
# is not enabled. This is also the VT which will be switched to
# if SWSUSP_LEAVE_X_BEFORE_SUSPEND is enabled.
# Default: 9
SWSUSP_VT="9"
EOF
    if [ ! -f $CONFIGFILE -o "$FORCE" = "yes" ] ;then
        echo "Creating file $CONFIGFILE"
        mv $TMP $CONFIGFILE 
    else
        echo "Configuration file $CONFIGFILE exists: not overwritten" 
        echo -e "These are the differences:\n" 
        diff -u $CONFIGFILE $TMP 
        echo "Creating file $CONFIGFILE.new"
        mv $TMP $CONFIGFILE.new
    fi

    exit 0
fi

if [ -n "$AM_IN_INSTALLER" ] ; then
    cat <<EOF
Usage: $EXE --install [--force]

This is the installer for the software suspend script. The script is 
intended to cleanly call software suspend. You may pass the following
options to the install script:

--install    Install this file in $INSTALLDIR and a configuration
             template as $CONFIGFILE. The existing script will be 
             overwritten, but not configuration file, unless --force
             is used. 
--force      Overwrite existing configuration file in installation
             procedure. 
EOF
    exit 1
fi

############################### INSTALL end ##################################

usage() {

cat <<EOF
Usage: $EXE [options]

The script file $EXE uses a configuration file $CONFIGFILE.
It is intended to cleanly call software suspend. Its 
options are as follows:
--help      Prints this help.
--force     Ignore devices that cannot be stopped or unmounted.
--kill      Kill processes that prevent from suspending.
--silent    Be silent on processing
--verbose   Be really verbose on standard output
--nosuspend Performs everything except actually suspend (configuration
                testing and debugging purpose)
To help suspension, it is strongly advisable to use automount for 
devices like cdrom floppy fat partitions, so that remount will
automatically take place when needed. For the same purpose
autoload of modules in kernel is a good point.
EOF
}

if [ -f "$CONFIGFILE" ] ; then
    . $CONFIGFILE
else
    echo "No configuration file $CONFIGFILE !!! Try reinstalling from suspend.sh?"
    usage
    exit 1
fi

if ( echo $@ | grep -e "--help" ) 1> $VERBOSE; then
    usage
    exit 0
fi
rm $TMP

VT_CONSOLE="/dev/tty$SWSUSP_VT"

if ( echo $@ | grep -e "--silent" ) 1> /dev/null; then
    CONSOLE='/dev/null'
    HWCLKDEBUG=""
else
    if [ -w $VT_CONSOLE ] ;then
        CONSOLE="$VT_CONSOLE"
    elif [ -w /dev/tty ] ;then
        CONSOLE='/dev/tty'
    else
        CONSOLE='/dev/console'
    fi
    HWCLKDEBUG="--debug"
fi

LOGCMD="tee -a $CONSOLE"

# No longer needed because swsusp does the same job?
#[ `cat /proc/swaps | grep partition | wc -l` -lt 1 ] && {
#    echo "No swap partition activated, cannot suspend"
#    exit 0
#}

#Defining a few more command-line options...

if ( echo $@ | grep -e "--kill" ) 1> $VERBOSE; then
    KILL_PROCS='yes'
else
    KILL_PROCS='no'
fi


# This does everything except suspension
if ( echo $@ | grep -e "--nosuspend" ) 1> $VERBOSE; then
    NOSUSPEND='yes'
else
    NOSUSPEND='no'
fi
#############################################################
# Function definitions
#############################################################
T_IFS=

if ! which usleep 1> $VERBOSE 2> $VERBOSE ; then
    # fallback function if usleep-utility isn't available
    usleep() {
        # try using perl
        perl -e "select(undef,undef,undef,$1/1000000)" && return 0

        # calculate sleep time in seconds
        sleeptime=$((($1)/100000))
        [ $((($1) % 100000)) -ne 0 ] && $sleeptime=$(($sleeptime+1))

        sleep $sleeptime
    }
fi

CheckProgs() {
    ret=0;
    if [ $KILL_PROCS = "yes" ]; then
        for sig in 15 9 ;do
            for prog in $SWSUSP_NON_COMPATIBLE_PROGS; do
                ps ax > $TMP
                pids=`awk '($5 == "'$prog'"){print $1}' $TMP`
                for pid in $pids; do
                    echo -e "\033[1;32m * \033[0mKilling($sig) $prog($pid)..." | $LOGCMD > $VERBOSE
                    kill -$sig $pid 2> $VERBOSE | $LOGCMD > $VERBOSE
                    usleep 500000
                done
            done
        done
    fi
    for prog in $SWSUSP_NON_COMPATIBLE_PROGS; do
        ps ax > $TMP
        pids=`awk '($5 == "'$prog'"){print $1}' $TMP`
        if [ "$pids" != "" ];then
            echo -e "Exception (non compatible) program $prog: $pids" | $LOGCMD > $VERBOSE
            ret=1
        fi        
    done
    test -f $TMP && rm $TMP
    return $ret
}

KillProgs() {
    for prog in $SWSUSP_STOP_PROGS_BEFORE_SUSPEND; do
            echo -e "\033[1;32m * \033[0mKilling $prog..." | $LOGCMD > $VERBOSE
            killall $prog 1> $VERBOSE  2> $VERBOSE
    done
    return 0;
}


ExecuteSuspendProgs() {
    for prog in $SWSUSP_START_PROGS_BEFORE_SUSPEND; do
            echo -e "\033[1;32m * \033[0mRunning $prog..." | $LOGCMD > $VERBOSE
            $prog 1> $VERBOSE  2> $VERBOSE &
    done
}

ExecuteResumeProgs() {
    for prog in $SWSUSP_START_PROGS_AFTER_RESUME; do
            echo -e "\033[1;32m * \033[0mStarting $prog..." | $LOGCMD > $VERBOSE
            $prog 1> $VERBOSE  2> $VERBOSE &
    done
}


SwitchFromX() {
    which fgconsole > $VERBOSE && ORIGINAL_VT=`fgconsole`
    if [ "$SWSUSP_LEAVE_X_BEFORE_SUSPEND" != "yes" -a "$SWSUSP_LEAVE_X_BEFORE_SUSPEND" != "nvidia" ]; then
        return 0;
    fi
    echo -e "\033[1;32m * \033[0mSwitching to suspend console..." | $LOGCMD > $VERBOSE
    chvt $SWSUSP_VT
    ret=$?
    
    usleep 500000 # This to ensure usb mouse is released by X
    return $ret
}

SwitchToX() {
    if [ "$SWSUSP_LEAVE_X_BEFORE_SUSPEND" = "nvidia" ]; then
	export XAUTHORITY=/tmp/.Xauthority-swsusp-fake-x-server
        export HOME=/dev/shm
        xauth 2> $VERBOSE 1> $VERBOSE <<EOF
add :3 . 00
generate :3.0 .
EOF
        if [ -x /usr/bin/X11/xmessage -a "$DISTRIB" != "Gentoo" ] ;then
            xinit /usr/bin/X11/xmessage -font huge -display :3.0 -center -timeout 2 "  Fake Xserver for restoring nvidia cards properly  " -- :3
        else
            xinit /bin/false -- :3 2> $VERBOSE 1> $VERBOSE
        fi
        xauth 2> $VERBOSE 1> $VERBOSE <<EOF
remove :3
remove :3.0
EOF
    fi

    test $SWSUSP_LEAVE_X_BEFORE_SUSPEND != "no" && echo -e "\033[1;32m * \033[0mSwitching back to X..." | $LOGCMD > $VERBOSE

    # if fgconsole is available, the original VT will be stored in this var
    if [ "$ORIGINAL_VT" != "" ]; then
        chvt "$ORIGINAL_VT"
    else
        echo "Original virtual terminal not memorized (trying 7)"
        chvt 7
    fi
    
    return $?
}

ExecuteServices() {
    ret=0
    # What action to execute on init scripts?
    startstop="$1"
    shift
    # What scripts to execute at all?
    services_to_execute=" $@ "

    if [ "$DISTRIB" != "Gentoo" ] ;then
        # in gentoo this does not work       
        runlevel=`runlevel | cut -d\  -f2`

        # only start/stop services really active in this runlevel and
        # do it in the correct order
        if [ "$startstop" = "start" ] ; then
            startscripts="$RLVLDIR/rcS.d/S* $RLVLDIR/rc$runlevel.d/S*"
        elif [ "$startstop" = "stop" ] ; then
            startscripts="$RLVLDIR/rc$runlevel.d/S*"

            # stop services - reverse the order in which the scripts are called
            for script in $startscripts ; do
                tmp_scriptlist="$script $tmp_scriptlist"
            done
            # (order of rc0.d/S* scripts *must not* be reversed!)
            startscripts="$tmp_scriptlist $RLVLDIR/rc0.d/S*"
        fi

        # execute all needed init scripts
        tmp_scriptlist=""
        for startscript in $startscripts ; do
            service=${startscript##*/S??} # strip off directory and startup sequence number
            if [ -z "${services_to_execute##* $service *}" ] ; then
                # service is active, start/stop it
                tmp_scriptlist="$tmp_scriptlist $service"
            fi
        done
        if [ "$startstop" = "START" ] ; then
            startstop="start"
            tmp_scriptlist=" $services_to_execute "
        elif [ "$startstop" = "STOP" ] ; then
            startstop="stop"
            tmp_scriptlist=" $services_to_execute "
        fi
        echo -e "\033[1;33m$tmp_scriptlist\033[0m" | $LOGCMD > $VERBOSE
        for service in $tmp_scriptlist ; do
            test -x /etc/init.d/"$service" || continue
            /etc/init.d/"$service" "$startstop" 2>&1 | $LOGCMD > $VERBOSE || ret=$? # remember the last error code
        done
    else
        # gentoo use this
        echo -e "\033[1;33m$services_to_execute\033[0m" | $LOGCMD > $VERBOSE
 
        if [ "$startstop" = "stop" ] ; then
            # start services - reverse the order in which the scripts are called
            for script in $services_to_execute ; do
                tmp_scriptlist="$script $tmp_scriptlist"
            done
            startscripts="$tmp_scriptlist"
        else
            startscripts="$services_to_execute"
        fi
        
        # execute all needed init scripts
        for service in $startscripts ; do
            echo -n " $service" | $LOGCMD > $VERBOSE
            /etc/init.d/"$service" "$startstop" 2>&1 | $LOGCMD > $VERBOSE  || ret=$? # remember the last error code
        done
    fi
    echo -e "\033[0m" | $LOGCMD > $VERBOSE
    return $ret # return the last error code
}

StopServices() {
    ExecuteServices "stop" "$SWSUSP_RESTART_SERVICES"
    ExecuteServices "STOP" "$SWSUSP_STOP_SERVICES_BEFORE_SUSPEND"
    return 0 # we don't want to abort if stopping one of the services failed
}

RestartServices() {
    ExecuteServices "start" "$SWSUSP_RESTART_SERVICES"
    ExecuteServices "START" "$SWSUSP_START_SERVICES_AFTER_RESUME"
    return $?
}

UmountDevices() {
    ret=0
    if [ $KILL_PROCS = "yes" ]; then
        for MNT in $SWSUSP_UMOUNTS; do
            if [ `grep -c " $MNT " /proc/mounts` != 0 ]; then
                echo -e "\033[1;32m * \033[0mTerminating users of $MNT..." | $LOGCMD > $VERBOSE
                fuser -s -k -15 $MNT 2> $VERBOSE | $LOGCMD > $VERBOSE
            fi
        done
        #sleep a few seconds before SIGKILL and umount
        sleep 3
    fi

    #Now kill procs and do umount
    for MNT in $SWSUSP_UMOUNTS; do
        if [ `grep -c " $MNT " /proc/mounts` != 0 ]; then
            if [ $KILL_PROCS = "yes" ]; then
                echo -e "\033[1;32m * \033[0mSending SIGKILL to remaining users of $MNT" | $LOGCMD > $VERBOSE
                fuser -s -k -9 $MNT 2> $VERBOSE | $LOGCMD > $VERBOSE
            fi  
            echo -e "\033[1;32m * \033[0mUnmounting $MNT" | $LOGCMD > $VERBOSE
            # make sure everything really is being unmounted
            if ! ( umount $MNT ); then
                ret=1
            fi
        fi
    done
    return $ret
}

RemountDevices() {
    ret=0
    for MNT in $SWSUSP_REMOUNTS ;do
        if [ `grep -c " $MNT " /proc/mounts` = 0 ]; then
            echo -e "\033[1;32m * \033[0mMounting $MNT..." | $LOGCMD > $VERBOSE
            /bin/mount $MNT
        fi
    done
}

StopInterfaces() {
    ret=0
    for IF in $SWSUSP_DOWNIFS; do
        if [ `ifconfig | grep -c "^$IF "` != 0 ]; then
            if [ ! -x $IFDOWN ] ;then
                echo -e "\033[1;32m * \033[0mNo script $IFDOWN !!!" | $LOGCMD > $VERBOSE
                return 2
            else
                echo "Bringing $IF down..." | $LOGCMD > $VERBOSE
                if ! ($IFDOWN $OPTDOWN $IF | $LOGCMD > $VERBOSE) ;then
                    echo -e "\033[1;32m * \033[0mBringing $IF down failed !" | $LOGCMD > $VERBOSE
                    ret=1
                else
                    T_IFS="$IF $T_IFS"
                fi
            fi
        fi
    done
    return $ret
}

RestartInterfaces() {
    ret=0
    if [ "$SWSUSP_UPIFS" = "auto" ] ;then
        SWSUSP_UPIFS="$T_IFS"
    fi
    for IF in $SWSUSP_UPIFS ;do
        echo -e "\033[1;32m * \033[0mBringing up $IF..." | $LOGCMD > $VERBOSE
        if ! ($IFUP $OPTUP $IF | $LOGCMD > $VERBOSE) ;then
            ret=1
        fi
    done
    return $ret
}

UnloadModules() {
    oldmodprobe=
    [ -f /proc/sys/kernel/modprobe ] && \
        old_modprobe=`cat /proc/sys/kernel/modprobe` && \
        echo "/bin/true" > /proc/sys/kernel/modprobe
    if [ "$SWSUSP_UNLOAD_MODULES_BEFORE_SUSPEND" != "yes" ] ;then
        ret=0
        if [ "$SWSUSP_REMOVEMODS" != "" ] ;then
            for MOD in $SWSUSP_REMOVEMODS ;do
                echo -e "\033[1;32m * \033[0mUnloading $MOD..." | $LOGCMD > $VERBOSE
                if ! (modprobe -r $MOD 2> $VERBOSE 1> $VERBOSE) ;then
                        ret=1
                fi
            done
        fi
        if [ "$SWSUSP_UNLOAD_MODULES_BEFORE_SUSPEND" != "auto" ] ;then
            echo -e "\033[1;32m * \033[0mUnloading autocleaned modules" | $LOGCMD > $VERBOSE
            if ! (rmmod -a 2> $VERBOSE 1> $VERBOSE) ;then
                    ret=1
            fi
        fi
        return $ret
    fi
    cat /proc/modules | $LOGCMD > $VERBOSE
    modules=`awk '($3==0){print $1}' /proc/modules`
    for module in $modules ;do
        echo -e "\033[1;32m * \033[0mRemoving $module" | $LOGCMD > $VERBOSE
        modprobe -r $module 2> $VERBOSE 1> $VERBOSE
        # usleep 100000
    done
    modaft=`awk '($3==0){print $1}' /proc/modules`
    while [ "$modaft" != "$modules" ] ; do
        #cat /proc/modules | $LOGCMD > $VERBOSE
        modules=$modaft
        usleep 500000
        for module in $modules ;do
            echo -e "\033[1;32m * \033[0mRemoving $module" | $LOGCMD > $VERBOSE
            modprobe -r $module 2> $VERBOSE 1> $VERBOSE
        done
        modaft=`awk '($3==0){print $1}' /proc/modules`
    done
    echo -e "\033[1;33mmodules failed to unload:\033[0m" | $LOGCMD > $VERBOSE
    cat /proc/modules | $LOGCMD > $VERBOSE
}

ReloadModules() {
    [ -n "$old_modprobe" ] && [ -f /proc/sys/kernel/modprobe ] && \
        echo "$old_modprobe" > /proc/sys/kernel/modprobe
    ret=0
    if [ "$SWSUSP_INSERTMODS" = "modules.autoload" ] ; then
        # for gentoo users
        source /sbin/functions.sh
        # cr: taken from gentoo's /etc/init.d/modules
        if [ -f /etc/modules.autoload -a ! -L /etc/modules.autoload ] ; then
            modules_autoload_file= /etc/modules.autoload
        else
            local KV="$(uname -r)"
            local KV_MAJOR="`KV_major "${KV}"`"
            local KV_MINOR="`KV_minor "${KV}"`"
     
            # New support for /etc/modules.autoload/kernel-$KV
            if [ "$(get_KV)" -ge "$(KV_to_int '2.5.48')" ] && \
               [ -f /etc/modules.autoload.d/kernel-"${KV_MAJOR}.${KV_MINOR}" ]
            then
                modules_autoload_file="/etc/modules.autoload.d/kernel-${KV_MAJOR}.${KV_MINOR}"
     
            elif [ ! -f /etc/modules.autoload.d/kernel-"${KV_MAJOR}.${KV_MINOR}" ]
            then
                ewarn "Missing /etc/modules.autoload.d/kernel-${KV_MAJOR}.${KV_MINOR}"
                modules_autoload_file="/etc/modules.autoload.d/kernel-2.4"
            else
                modules_autoload_file="/etc/modules.autoload.d/kernel-2.4"
            fi
        fi
     
        # Loop over every line in $modules_autoload_file.
        echo -e "\033[1;33mLoading modules listed $modules_autoload_file\033[0m" | $LOGCMD > $VERBOSE
        (cat "$modules_autoload_file"; echo) | # make sure there is a LF at the end

        while read MOD args ; do
            case "${MOD}" in
                \#*|"") continue ;;
            esac
            echo -e "\033[1;32m * \033[0mLoading $MOD..." | $LOGCMD > $VERBOSE
            modprobe ${MOD} ${args} 2> $VERBOSE 1> $VERBOSE
            #sleep 1
        done
    else
        for MOD in $SWSUSP_INSERTMODS ;do
            echo -e "\033[1;32m * \033[0mLoading $MOD..." | $LOGCMD > $VERBOSE
            if ! (modprobe $MOD 2> $VERBOSE 1> $VERBOSE) ;then
                ret=1
                fi
        done
    fi
    return $ret
}

Suspend() {
    ret=0
	[ -f /proc/swsusp/all_settings ] && sysctl="/proc/swsusp/all_settings" || sysctl="/proc/sys/kernel/swsusp"
    if [ "$SWSUSP_SAVE_CLOCK_ON_SUSPEND" = "yes" ] ;then
        echo -e "\033[1;32m * \033[0mSaving clock state..." | $LOGCMD > $VERBOSE
        hwclock --systohc $HWCLKDEBUG
        sleep 1 #This is to be sure that the clock syncing is done
    fi
    if [ -x $SETSYSFONT ];then
        chvt $SWSUSP_VT
    fi

    sync
    if [ "$NOSUSPEND" = "yes" ] ;then
        echo -e "\033[1;31m\nSuspension system call not performed...\n\033[0m" | $LOGCMD > $VERBOSE
        if [ "$SWSUSP_FORCE_SUSPEND_MODE" = "acpi" -o "$SWSUSP_FORCE_SUSPEND_MODE" = "ACPI" ];then
            echo "/bin/echo 4 > /proc/acpi/sleep" | $LOGCMD > $VERBOSE
        else
            echo "/bin/echo \"0 $SWSUSP_FORCE_SUSPEND_MODE\" > $sysctl " "&& echo > /proc/swsusp/activate"
        fi
    else
        if [ -w "$SWSUSP_DISABLE_HW_DISK_CACHE" ] ;then
            echo -e "\033[1;32m * \033[0mDisabling hardware disk cache on $SWSUSP_DISABLE_HW_DISK_CACHE" | $LOGCMD > $VERBOSE
            hdparm -W 0 $SWSUSP_DISABLE_HW_DISK_CACHE
        fi
        echo -e "\033[1;33m\nSuspension system call in progress...\n\033[0m" | $LOGCMD > $VERBOSE
        if [ "$SWSUSP_FORCE_SUSPEND_MODE" = "acpi" -o "$SWSUSP_FORCE_SUSPEND_MODE" = "ACPI" ];then
            if ! (/bin/echo 4 > /proc/acpi/sleep &) ;then
                ret=1
            fi
        else
            if ! (/bin/echo "0 $SWSUSP_FORCE_SUSPEND_MODE" > $sysctl && echo > /proc/swsusp/activate) ;then
                ret=1
            fi
        fi
    fi
    # Some people have reported that echo 4 > /proc/sleep acpi never returns.
    # The following kills the echo process if it's still hanging around.
    if [ $ret = 0 ] ;then    
        #sleep 5
        ps ax > $TMP
        pids=`awk '($5 == "/bin/echo"){print $1}' $TMP`
        for pid in $pids; do
            echo -e "\033[1;32m * \033[0mKilling($sig) $prog($pid)..." | $LOGCMD > $VERBOSE
            #kill -$sig $pid 2> $VERBOSE | $LOGCMD > $VERBOSE
            usleep 500000
        done
    fi
    if [ -x $SETSYSFONT ];then
        chvt $SWSUSP_VT
        $SETSYSFONT $OPTSYSFONT
    fi
    return $ret
}

RestoreClock() {
    ret=0
    echo -e "\033[1;32m * \033[0mRestoring clock..." | $LOGCMD > $VERBOSE
    hwclock --hctosys $HWCLKDEBUG | $LOGCMD > $VERBOSE
    ret=$?
    sleep 1 #This is to be sure that the clock syncing is done
    return $ret
}


RESUME() {
    state=$1
    resumestate=7
    
    # we'd always like to restore the clock
    echo -e "\033[1;32mResuming\033[0m (suspend script vers. $VERSION)..." | $LOGCMD > $VERBOSE
    RestoreClock

    resumestate=$(($resumestate - 1))
    
    if [ $state -ge $resumestate ];then
        echo -e "\033[1;32mReload modules...\033[0m" | $LOGCMD > $VERBOSE
        ReloadModules
    fi

    resumestate=$(($resumestate - 1))
    
    if [ $state -ge $resumestate ];then
        echo -e "\033[1;32mStarting interfaces...\033[0m" | $LOGCMD > $VERBOSE
        RestartInterfaces
    fi

    resumestate=$(($resumestate - 1))
    
    if [ $state -ge $resumestate ];then
        echo -e "\033[1;32mRemounting devices...\033[0m" | $LOGCMD > $VERBOSE
        RemountDevices
    fi

    resumestate=$(($resumestate - 1))
    
    if [ $state -ge $resumestate ];then
        echo -e "\033[1;32mRestarting progs...\033[0m" | $LOGCMD > $VERBOSE
        ExecuteResumeProgs
    fi
        

    resumestate=$(($resumestate - 1))
    
    if [ $state -ge $resumestate ];then
        echo -e "\033[1;32mRestarting services...\033[0m" | $LOGCMD > $VERBOSE
        RestartServices
    fi

    resumestate=$(($resumestate - 1))

    if [ $state -ge $resumestate ];then
        SwitchToX
    fi
    
    resumestate=$(($resumestate - 1))
    # resumestate should be zero at this point
    return $resumestate
}

FAIL() {
   if [ $FORCE = "yes" ]; then
#  Then continue anyway.
     echo | $LOGCMD > $VERBOSE
     echo "WARNING...FAILSAFES OVERIDDEN..." | $LOGCMD > $VERBOSE
     echo "Do not mount shared drives from other OS's while suspended" | $LOGCMD > $VERBOSE
     echo | $LOGCMD > $VERBOSE
   else
     echo | $LOGCMD > $VERBOSE
     echo "         ********* SUSPEND CANCELLED *********" | $LOGCMD > $VERBOSE
     echo | $LOGCMD > $VERBOSE
     RESUME $1
     rm $LOCKFILE
     echo -e "\033[1;31m\nBack! Suspend failed. Try to configure $CONFIGFILE.\033[0m\n\n" | $LOGCMD > $VERBOSE
     exit 255
   fi 
}





SUSPEND() {
    state=0

    if ! CheckProgs ;then
        FAIL $state
    fi

    if ! SwitchFromX ;then
        FAIL $state
    fi

    echo -e "\033[1;31mPreparing to suspend\033[0m (suspend script vers. $VERSION)..." | $LOGCMD > $VERBOSE

    echo -e "\033[1;31mRunning suspend programs...\033[0m (suspend script vers. $VERSION)..." | $LOGCMD > $VERBOSE
    if ! ExecuteSuspendProgs ; then
        FAIL $state
    fi

    state=$(($state + 1))

    echo -e "\033[1;31mStopping services...\033[0m" | $LOGCMD > $VERBOSE
    if ! StopServices ;then
        FAIL $state
    fi
    
    state=$(($state + 1))

    echo -e "\033[1;31mKilling progs...\033[0m" | $LOGCMD > $VERBOSE
    if ! KillProgs ;then
        FAIL $state
    fi

    state=$(($state + 1))

    echo -e "\033[1;31mUnmounting devices...\033[0m" | $LOGCMD > $VERBOSE
    if ! UmountDevices ;then
        FAIL $state
    fi

    state=$(($state + 1))

    echo -e "\033[1;31mStopping interfaces...\033[0m" | $LOGCMD > $VERBOSE
    if ! StopInterfaces ;then
        FAIL $state
    fi

    state=$(($state + 1))

    echo -e "\033[1;31mUnloading modules...\033[0m" | $LOGCMD > $VERBOSE
    if ! UnloadModules ;then
        FAIL $state
    fi

    state=$(($state + 1))

    if ! Suspend ;then
        FAIL $state
    fi
    state=$(($state + 1))
    return $state
}

#############################################################
# Main 
#############################################################

if [ -f $LOCKFILE ] ;then
    pid=`cat $LOCKFILE`
    if (ps $pid > $VERBOSE 2> $VERBOSE) ;then
        echo "File $LOCKFILE is present. Suspension script `cat $LOCKFILE`"
        echo "should be in progress. If this is not the case, then erase"
        echo "this file"
        exit 1
    fi
fi
echo $$ > $LOCKFILE

SUSPEND
state=$?
RESUME $state
ret=$?
rm $LOCKFILE

echo -e "\033[1;32m\nWelcome back! Suspend done.\033[0m\n\n" | $LOGCMD > $VERBOSE

exit $ret

# vi:ts=8:
