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