# -*- sh -*-
# vim:ft=sh:ts=8:sw=4:noet

AddConfigHandler LockOptions
AddConfigHelp "LockKDE <boolean>" "Lock all local KDE sessions before suspending."
AddConfigHelp "LockXScreenSaver <boolean>" "Lock all local X11 sessions with xscreensaver running before suspending."
AddConfigHelp "LockConsoleAs <username>" "Locks the entire system after resuming, requiring you to enter either <username>'s or root's password to unlock it. (Requires vlock)."

LockKDE() {
    [ x"$LOCK_KDE" != "x1" ] && return 0

    if [ "x$DISTRIBUTION" = "xgentoo" ] && ! which dcop > /dev/null 2>&1 ; then
	# Gentoo stashes this in a silly place.
	for i in /usr/kde/*/bin/dcop ; do
	    if [ -x "$i" ] ; then
		PATH=$PATH:${i%%/dcop}
		export PATH
		break
	    fi
	done
    fi

    if ! which dcop > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock KDE. `dcop` program not found.'
	return 1 # abort, unless forced
    fi

    local avail_sessions
    local session

    # get all sessions (ignore non local ones!)
    avail_sessions=`dcop --all-users --list-sessions | grep '.DCOP.*__0'`

    # send the lock command to all sessions
    for session in $avail_sessions; do
	vecho 1 "Locking $session"
	# dev/null because dcop warns if it can't connect to X (this is normal!)
	dcop --session "$session" --all-users kdesktop KScreensaverIface lock > /dev/null 2>&1
    done

    # returning 0 because dcop warns if it can't connect to X (this is normal!)
    return 0
}

LockXScreensaver() {
    [ x"$LOCK_XSCREENSAVER" != "x1" ] && return 0

    if ! which xscreensaver-command > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock xscreensaver. `xscreensaver-command` not found.'
	return 1 # abort, unless forced
    fi

    local xpid

    for xpid in `pidof xscreensaver` ; do
	local xuser xdisp xauth xhome
	xuser=`awk 'BEGIN{RS="\\000";FS="="}($1 == "USER"){print $2}' < /proc/$xpid/environ`
	xdisp=`awk 'BEGIN{RS="\\000";FS="="}($1 == "DISPLAY"){print $2}' < /proc/$xpid/environ`
	xauth=`awk 'BEGIN{RS="\\000";FS="="}($1 == "XAUTHORITY"){print $2}' < /proc/$xpid/environ`
	if [ -z "$xauth" ] ; then
	    xhome=`awk 'BEGIN{RS="\\000";FS="="}($1 == "HOME"){print $2}' < /proc/$xpid/environ`
	    xauth="$xhome/.Xauthority"
	fi

	vecho 2 "Locking $xuser's xscreensaver on display $xdisp using authority file $xauth"
	DISPLAY=$xdisp XAUTHORITY=$xauth su $xuser -c "xscreensaver-command -lock"
	if [ $? -ne 0 ] ; then
	    vecho 0 "Failed to activate xscreensaver on $xdisp using authority file $xauth."
	fi
    done

    # Failing is silly. What would they do about it?
    return 0
}

LockConsole() {
    # Prerequistes are tested for in SwitchToLockConsole

    [ -z "$LOCK_CONSOLE_USER" ] && return 0

    # Use vlock to lock all consoles. We must already be at the given console.
    vecho 1 "Locking all consoles"
    openvt -wfc $LOCK_DEST_VT -- su - "$LOCK_CONSOLE_USER" -c "tput clear; vlock -a"

    # This will hang until the root password is entered.

    # Switch back to original console
    vecho 3 "lock: changing console back to $LOCK_ORIGINAL_VT"
    chvt $LOCK_ORIGINAL_VT
}

SwitchToLockConsole() {
    [ -z "$LOCK_CONSOLE_USER" ] && return 0

    if ! which openvt > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock console. `openvt` program not found.'
	LOCK_CONSOLE_USER=
	return 1 # abort, unless forced
    fi

    if ! which tput > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock console. `tput` program not found.'
	LOCK_CONSOLE_USER=
	return 1 # abort, unless forced
    fi

    if ! which vlock > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock console. `vlock` program not found.'
	LOCK_CONSOLE_USER=
	return 1 # abort, unless forced
    fi

    if which fgconsole > /dev/null 2>&1 ; then
	LOCK_ORIGINAL_VT=`fgconsole`
    else
	LOCK_ORIGINAL_VT=1
    fi

    LOCK_DEST_VT=61 # Choose something different - can't afford to have silent bootsplash there
    vecho 2 "lock: changing console from $LOCK_ORIGINAL_VT to $LOCK_DEST_VT"
    chvt $LOCK_DEST_VT || return 1

    return 0
}

LockOptions() {
    case $1 in
	lockkde)
	    BoolIsOn "$1" "$2" && LOCK_KDE=1 || LOCK_KDE=0

	    if [ -z "$KDELOCK_HOOKED" ] ; then
		AddSuspendHook 91 LockKDE
		KDELOCK_HOOKED=1
	    fi
	    ;;

	lockxscreensaver)
	    BoolIsOn "$1" "$2" && LOCK_XSCREENSAVER=1 || LOCK_XSCREENSAVER=0
	    if [ -z "$XSCREENSAVERLOCK_HOOKED" ]; then
		AddSuspendHook 91 LockXScreensaver
		XSCREENSAVERLOCK_HOOKED=1
	    fi
	    ;;

	lockconsoleas)
	    LOCK_CONSOLE_USER="$2"

	    if [ -z "$CONSOLELOCK_HOOKED" ] ; then
		AddResumeHook 96 LockConsole
		AddSuspendHook 96 SwitchToLockConsole

		CONSOLELOCK_HOOKED=1
	    fi
	    ;;

	*)
	    return 1
    esac

    return 0
}

