axnet
users
projects
fun
  
 
  Permanently Hide Close

fprintkill
is a POSIX-compliant (pure bourne shell) script that allows you to launch any executable and have it terminated by fingerprint... especially useful for screen-lockers that do not support fingerprint unlocking.

githup holds the latest version, have more information and exensive examples on how to use fprintkill including the nifty multi-environment console and screen locker wrapper, fraxlock :-)
Further down this page, you will find a download-link and highlighted source code of fprintkill, but firstly, the background of how it came to be and an example on how to use it:

I do like to use simple lightweight screen lockers like xtrlock or slock and have them launched by xautolock. They have low impact on the system and gives me full control to tweak exactly how I like them to work (have wrappers shutting off the screen, additional notify warnings before locking via yad, etc, etc).

BUT now that we have fingerprint readers on almost all laptops I also do want to be able to unlock my computer using that ... which those lockers do not support, not even via libpam-fprintd, so to fix that dilemma I wrote this small script (with large USAGE section and heavily commented to show exactly what it's doing :-) ) fixing the problem. It's originally written to be used with xtrlock and/or slock, but you could use it to launch any executable you like and close (kill -TERM) it using your fingerprint :-)

E.g. one could use fprintkill in a wrapper script /usr/local/bin/xtrlock looking like this:


#!/bin/sh
EXEC=/usr/bin/xtrlock
test -x $EXEC || { 
    echo "Executable '$EXEC' not present!" >/dev/stderr
    exit 1
}
which fprintkill >/dev/null || exec $EXEC "$@"
eval "exec fprintkill $EXEC \"$@\""

    

As /usr/local/bin should preceed /usr/bin in the $PATH it would serve as a transparent xtrlocker replacement (wrapper).

So, in case somebody else have use for this, here you are:

Download:fprintkill
GitHub:https://github.com/fraxflax/fprintkill
Source Code:(syntax highlighting by highlight.js)

#!/bin/sh
#
# fprintkill is a POSIX-compliant (pure bourne shell) script for
# launching an executable and be able to kill it by reading your
# fingerprint.
# 
# This is free software created by frax@axnet.nu,
# feel free to use, modify and/or distribute as you see fit.
# 
DEPS="fprintd-verify pgrep pkill ps sed setsid" 
USAGE() {
    fprintkill="`basename "$0" 2>/dev/null`" || fprintkill="fprintkill"
    COLS=72; ___=''; __=''; which tput>/dev/null && { COLS=`tput cols`; ___=`tput bold`; __=`tput sgr0`; }
    FMT=cat;which fmt>/dev/null && FMT="fmt -w $COLS"
    $FMT<<EOU

${___}SYNOPSIS:
	$fprintkill$__ [ cmd [ arg ...] ]

	Executes cmd [ arg ...] and for as long as cmd is running,
	upon successfull fingerprint verify, cmd is terminated (SIGTERM).

	If no arguments are given to fprintkill, enviroment variables
	FPK_EXEC and FPK_ARGS are used for cmd [ arg ...]

${___}EXIT STATUS:$__
        $fprintkill exits with the same code as the cmd.  If cmd is
	terminated after fingerprint verify, $fprintkill exits with
	the SIGTERM exit code (143 in linux).

${___}DEPENDENCIES:$__
	$fprintkill will always launch the cmd, but the fingerprint
	termination depends on the following executables:
${___}	$DEPS	$__
	If they are not found in the path, a
	warning will be printed to stderr but the cmd will still be
	launched, even though it cannot be killed by fingerprint. (To
	satisfy the dependencies in Debian/Ubuntu: apt install
	util-linux procps sed fprintd util-linux).

${___}EXAMPLES:$__
	Lock the screen with slock, terminating it upon verified
	fingerprint:
${___}	   $fprintkill slock	$__

	Run '/usr/bin/xtrlock -b' in the background terminating it
	upon verified fingerprint:
${___}	   $fprintkill /usr/bin/xtrlock -b &	$__

	Alternative using environment variables:
${___}	   env FPK_EXEC=/usr/bin/xtrlock FPK_ARGS=-b $fprintkill &	$__

	Arguments with whitespaces are ok:
${___}	   $fprintkill sh -c "xset dpms force off ; xtrlock" &	$__

	Alternative using environment variables:
	   env FPK_EXEC=sh FPK_ARGS='-c  "xset dpms force off ; xtrlock"' $fprintkill &	$__

	Also daemons are properly handled.  To launch xtrlock in the
	background as a daemon that will be terminated upon verified
	fingerprint:
${___}	   $fprintkill xtrlock -f	$__

	In the case the cmd is a daemon spawning several parallel
	processes (spawn) before exiting, all of the spawn will be
	monitored and terminated upon verified fingerprint. Cleanup
	will not be performed before all of the parallell processes
	have exited or have been terminated. In this example:
${___}	   $fprintkill sh -c "proc1 & proc2 & proc3 & exit 0" 	$__
	... if proc1 exits, fprintkill will keep monitoring proc2 and
        proc3. If proc1, proc2 and proc3 all exits fprintkill will
        clean up. Upon verified fingerprint, proc1, proc2 and proc3
        (and their child processes, if any) will be terminated (cleaned up).

EOU
    exit 1
}
test -n "$1" && {
    FPK_EXEC="$1"
    FPK_ARGS=
    n=2
    while eval "test -n \"\$$n\""; do
	eval "FPK_ARGS=\"$FPK_ARGS '\$$n'\""
	n=$((n+1))
    done
}
which "$FPK_EXEC">/dev/null 2>&1 || test -x "$FPK_EXEC" || USAGE

lacking=
for x in $DEPS; do which $x>/dev/null || lacking="$lacking $x"; done
test -n "$lacking" && {
    cat<<EOW>/dev/stderr

WARNING!

The following executables are lacking in your PATH:
 $lacking
preventing fingerprint killing from being performed.

The full depencies (apart from coreutils) for fingerprint kill are:
  $DEPS
(in debian/ubuntu: apt install util-linux procps sed fprintd )

EOW

    eval "exec '$FPK_EXEC' $FPK_ARGS"
}


# The process id of cmd (exec below)
xpid=$$

# Process group
pgid=`ps -opgid= $xpid` || { echo "ERROR: ps: $!" > /dev/stderr; exit 1 ;}

# Ensure we have a separate process group with $xpid as root
test $xpid -eq $pgid || exec setsid sh $0 "$@"


{   # --- Fork twice ---
    # Inner fork: Terminate cmd (or daemon spawn) upon verified fingerprint,
    # Outer fork: Kill potentially remaining processes (e.g. fprintd-verify)
    #             once the cmd (or daemon spawn) has exited / been terminated

    sleep 1 # allow cmd to launch (and possibly become a daemon)

    ps -opid= $xpid >/dev/null 2>&1 || { # cmd has exited 
	# get pids of daemon spawn
	GPIDS=`pgrep -g $pgid`
	cpids=`echo $GPIDS | sed -E 's/[^ ]+ //'` # (first pid is `self`)
	test "$cpids" = "$GPIDS" || xpid=$cpids
    }
	
    # Fork & do fprintd-verify for as long as cmd or spawn still alive
    while ps -opid= $xpid >/dev/null; do
	fprintd-verify -f any >/dev/null 2>&1 && {
	    pkill -TERM -g $pgid >/dev/null 2>&1
	    exit 0
	}
    done &
	
    # Monitoring: Every 5:th second, check if cmd (or spawn) is still alive
    while ps -opid= $xpid >/dev/null; do sleep 5; done 

    # Cleanup: Kill potentially remaining children 
    pkill -TERM -g $pgid >/dev/null 2>&1
    exit 0
}&

eval "exec '$FPK_EXEC' $FPK_ARGS"
# exec will exit with code 143 if killed