#!/bin/bash
###########################################################################
#                                                                         #
#                         Powersave Daemon                                #
#                                                                         #
#          Copyright (C) 2004,2005 SUSE Linux Products GmbH               #
#                                                                         #
# This program is free software; you can redistribute it and/or modify it #
# under the terms of the GNU General Public License as published by the   #
# Free Software Foundation; either version 2 of the License, or (at you   #
# option) any later version.                                              #
#                                                                         #
# This program is distributed in the hope that it will be useful, but     #
# WITHOUT ANY WARRANTY; without even the implied warranty of              #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU       #
# General Public License for more details.                                #
#                                                                         #
# You should have received a copy of the GNU General Public License along #
# with this program; if not, write to the Free Software Foundation, Inc., #
# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA                  #
#                                                                         #
###########################################################################
#
# Helper functions for powersaved helper scripts.
# Part of the powersave package.
#

MYNAME=${0##*/}
LOGGER="logger -t powersave-${MYNAME}[$$] "

# these variables are set by the daemon in the environment before
# this script is executed
#
# SYSCONFDIR --> full path to directory where configuration files are
# SCRIPT_DIR --> full path to base directory for scripts
# PUB_SCRIPT_DIR --> $SCRIPT_DIR/scripts
# BIN_DIR --> bindir set by configure
# KDE_BINDIR --> bindir of kde installation set by configure
# GNOME_BINDIR --> bindir of gnome installation set by configure
if [ -z "$SYSCONF_DIR" -o -z "$SCRIPT_DIR" -o -z "$BIN_DIR" \
    -o -z "$PUB_SCRIPT_DIR" -o -z "$KDE_BINDIR" -o -z "$GNOME_BINDIR" ]; then
    $LOGGER "Environment variables not set by the daemon, exiting..."
    exit 1
fi

export PUB_SCRIPT_DIR
export SCRIPT_DIR
export PATH=${PUB_SCRIPT_DIR}:$PATH
export SCRIPT_RETURN="script_return"
export SYSCONF_DIR

WTTYHX=$SCRIPT_DIR/wttyhx

readonly EV_ID="$4" || \
    $LOGGER "readonly EV_ID modified. Multiple invocation of helper_functions?"

# this has to be used instead of exit to reset the exit trap
# before really exiting.
EXIT() {
    trap '' EXIT
    exit $@
}

# prevent an improper exit. We need to do
# $SCRIPT_RETURN before exiting to avoid long timeouts in powersaved.
trap ERROR_EXIT EXIT

ERROR_EXIT() {
    $SCRIPT_RETURN $EV_ID 1 "${MYNAME}: unclean exit!"
    DEBUG "EV_ID: $EV_ID, unclean exit or unconverted script, please read the powersaved manual (chapter 11) if this is a customized event script" WARN || $LOGGER "unclean exit"
    EXIT 1
}

. $SYSCONF_DIR/common

# first paramter string to write to syslog
# second parameter priority: ERROR, WARN, DIAG, INFO or DEBUG
# message will be printed according to DEBUG variable in 
# common configuration file
# e.g. DEBUG "Could not access disk" WARN
DEBUG() {
    [ -z "$DEBUG" ] && DEBUG=3
    [ -z "$1" ] && $LOGGER "no string given in DEBUG function" && return 1
    case "$2" in
	ERROR) 
	    (( $DEBUG & 1 ))  && $LOGGER -p error  "ERROR: $1"
	    ;;
	WARN)
	    (( $DEBUG & 2 ))  && $LOGGER -p warn   "WARNING: $1"
	    ;;
	DIAG)
	    (( $DEBUG & 4 ))  && $LOGGER -p notice "DIAG: $1"
	    ;;
	INFO)
	    (( $DEBUG & 8 ))  && $LOGGER -p info   "INFO: $1"
	    ;;
	DEBUG)
	    (( $DEBUG & 16 )) && $LOGGER -p info   "DEBUG: $1"
	    ;;
	*)  $LOGGER "Undefined priority: $2"
	    return 1
	    ;;
     esac
}


# Function that loads (. file) configurations of a scheme file
# First and only param is the name of the scheme file
# (e.g. scheme_powersave)
#
# if no parameter is given it checks whether we are on battery or AC
# and then loads the right scheme as specified in the common conf file
#
# Take care that common configurations vars have been loaded by
# invoking script (e.g. like: . /etc/sysconfig/powersave/common)
# 
# returns 0 on success, 1 on failure
load_scheme() {
    DEBUG "process function: load_scheme" DEBUG
    local ret ac_bat scheme_file
    ret=0
    if [ $# == 1 ]; then
	scheme_file=$SYSCONF_DIR/$1
    elif [ $# == 0 ]; then
	on_ac_power &>/dev/null
	ac_bat=$?
	if [ $ac_bat = 0 ]; then
	    scheme_file=$SYSCONF_DIR/scheme_$AC_SCHEME
	elif [ $ac_bat = 1 ]; then
	    scheme_file=$SYSCONF_DIR/scheme_$BATTERY_SCHEME
	else
	    DEBUG "Could not figure out AC power state, suppose online. Probably a workstation or broken ACPI table." INFO
	    scheme_file=$SYSCONF_DIR/scheme_$AC_SCHEME
	fi
    fi
    if [ -r $scheme_file ]; then
	DEBUG "load scheme: $scheme_file" INFO
	. $scheme_file
	ret=0
    else
	DEBUG "Could not load scheme configurations for scheme file $scheme_file" WARN
	ret=1
    fi
    return $ret
}

question(){
    local x y i RET DEFAULT_RETURN
    local N=false
    # do not include a file inside a function. Better possibility will be looked for
    . "${PUB_SCRIPT_DIR}/x_helper_functions"

    # query the user for proceeding or not.
    # This function can be invoked either from the daemon throug questions_default_yes/no
    # or manually from a script.
    #
    # When invoked from daemon a fifth argument containing the default return value
    # is appended
    #
    # When invoked from a script: First argument is the text which should be displayed.
    # Second argument is the default return value. If there is only one argument given,
    # first is the default return value and the text will be the powersaved event

    DEBUG "process function: question" DIAG
    
    #######################################################################
    # process arguments:
    MESSAGE="";
    DEFAULT_RETURN="1"
    # invoked from script
    if [ -n "$1" -a -z "$3" ]; then
	MESSAGE=$1"\nInvoked from script. Proceed?"
	DEFAULT_RETURN="$2"
    fi

    # message is empty
    if [ -z "$MESSAGE" ]; then
	MESSAGE="Powersaved event: ${EVENT_TYPE}${EVENT_SUBTYPE:+" $EVENT_SUBTYPE"}${EVENT_EXT:+" $EVENT_EXT"}"
    fi

    # invoked from daemon through question_default_yes/no
    if [ -n "$5" -a -z "$6" ]; then
	MESSAGE="Powersaved event: ${EVENT_TYPE}${EVENT_SUBTYPE:+" $EVENT_SUBTYPE"}${EVENT_EXT:+" $EVENT_EXT"}\nDo you want to proceed?"
	DEFAULT_RETURN="$5"
    fi

    RET="-1"
    # notify_console and notify_acoustic are done first, otherwise they
    # would happen after the user's choice
    for x in ${NOTIFY_METHOD:-notify_popup_fallback notify_acoustic}; do
        case $x in
            notify_console)
                echo "$MESSAGE" | fmt | wall
                RET=$DEFAULT_RETURN ;;
            notify_acoustic)
                for y in . . . ; do
                    echo -en "\007" > /dev/tty0
                    sleep .5
                done
                RET=$DEFAULT_RETURN ;;
            *)  ;;
	esac
    done

    for x in ${NOTIFY_METHOD:-notify_popup_fallback notify_acoustic}; do
	if [ "$x" = "notify_popup_window" -o "$x" = "notify_popup_fallback" ];then    
	    [ -x $ZENITY_BIN ] && ZENITY=true || ZENITY=false
	    get_x_users
	    i=0
	    while [ "${X_USERS[$i]}" ]; do
		X_USER=${X_USERS[$i]}; DISP=${DISPS[$i]}; KDE_RUNNING=${KDE_RUNNING[$i]:-false};
		# evil workaround for checking if X is running but no user is logged in
		if [ ! "`who | grep :0`" ]; then
		    RET=$DEFAULT_RETURN
		    break
		else
		    # switch to the X-server so that the user can make his choice
		    chvt `$WTTYHX`
		fi
		# evil workaround ends here
		
		choose_popup "$MESSAGE" QUESTION
		RET="$?"
		# we only ask once. If we got a valid response, break.
		if [ $RET -eq 0 -o $RET -eq 1 ]; then
		    N=true # we have notified! Yeah!
		    break
		fi
		let i++
	    done
	    # if we did not succeed with the popup... wall.
	    if [ "$x" = "notify_popup_fallback" ] && ! $N; then
                echo "$MESSAGE" | fmt | wall
                RET=$DEFAULT_RETURN
	    fi
	fi
    done

    return $RET
}

script_return() {
    EVENT_ID=$1
    REQUEST=$2
    TEXT=$3

    DEBUG "script_return() invoked: event_id: $EVENT_ID, request: $REQUEST, text: $TEXT" DIAG

    if test -z "$EVENT_ID" -o -z "$REQUEST"; then
	DEBUG "script_return(): event_id or request missing" WARN
	return 1;
    fi

    $BIN_DIR/dbus-send --system --print-reply \
	--dest=com.novell.powersave \
	/com/novell/powersave/scripts \
	com.novell.powersave.scripts.ScriptReturn \
	int32:$EVENT_ID int32:$REQUEST string:"$TEXT" > /dev/null
}

#############################
### main() ##################
#############################
DEBUG "Process script for event $1 ID $4" DIAG

if [ -z "$1" ]; then
    echo "This script is automatically invoked by the powersave " \
             "daemon. Don't use it in your console" >&2
    EXIT 1
fi

###########################################################
# Parse arguments

read DUMMY DUMMY VERSION DUMMY < /proc/version # puts "2.6.11-rc3-..." into $VERSION
_IFS="$IFS"
IFS="."
K_V=($VERSION) # perform word splitting at $IFS, put into array(!) $K_V.
read EVENT_TYPE EVENT_SUBTYPE EVENT_EXT < <(echo "$1" | awk -F/ '{print toupper($1);}')
# set IFS back or we will get trouble at the next read!
IFS="$_IFS"
K_RELEASE="${K_V[0]}.${K_V[1]}"
###########################################################

DEBUG "Event: ${EVENT_TYPE}${EVENT_SUBTYPE:+_$EVENT_SUBTYPE}${EVENT_EXT:+_$EVENT_EXT} occured." INFO
DEBUG "Parameters: Event - $1; Current Active Scheme: $2 - ACPI event line: $3" INFO
