# -*- 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 ! 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 | grep __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 cause 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 avail_sessions
    local displays
    local display
    local ret

    # find a list of running X servers
    displays=$(find /tmp -name '.X*-lock' -maxdepth 1 -print | sed -e 's/.*X\([0-9]\+\)-lock/\1/g')

    ret=0

    for display in $displays; do
	local xpid xauth
	xpid=$(awk '{print $1}' /tmp/.X$display-lock)

	# ensure xpid is numeric
	case "$xpid" in
	    *[!0-9]*|"")
		vecho 2 "Display :$display's pid ($xpid) is not numeric. Skipping"
		continue ;;
	esac

	xauth=$(cat /proc/$xpid/cmdline | sed -e 's/\(.\|[^.]\)*[^[:print:]]-auth[^[:print:]]\(.*\)[^[:print:]]\(.\|[^.]\)*/\2/g')

	vecho 2 "Locking xscreensaver on display :$display using authority file $xauth"
	DISPLAY=:$display XAUTHORITY=$xauth xscreensaver-command -lock
	if [ $? -ne 0 ] ; then
	    vecho 0 "Failed to activate xscreensaver on :$display using authority file $xauth."
	    ret=1
	fi
    done

    return $ret
}

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 "vlock -a"

    # This will hang until the root password is entered.

    # Switch back to original console
    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 vlock > /dev/null 2>&1 ; then
	vecho 0 'Cannot lock console. `vlock` program not found.'
	LOCK_CONSOLE_USER=
	return 1 # abort, unless forced
    fi

    which fgconsole > /dev/null 2>&1 && LOCK_ORIGINAL_VT=`fgconsole` || LOCK_ORIGINAL_VT=1
    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
		# do it before switching out of X
		AddSuspendHook 95 LockKDE
		KDELOCK_HOOKED=1
	    fi
	    ;;

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

        lockconsoleas)
	    LOCK_CONSOLE_USER="$2"

	    if [ -z "$CONSOLELOCK_HOOKED" ] ; then
		# call vlock just after resuming to avoid switching consoles
		# and ask for password
		AddResumeHook 98 LockConsole

		# This ensures the console we switch back to will have vlock on
		# it. (and not go via X first, or something)
		AddSuspendHook 98 SwitchToLockConsole

		CONSOLELOCK_HOOKED=1
	    fi
	    ;;

	*)
	    return 1
    esac

    return 0
}

