From 0c4f3acb281be6290c55a6e96bc29fab5b5c7a11 Mon Sep 17 00:00:00 2001 From: tv Date: Mon, 11 Sep 2023 18:24:28 +0200 Subject: stockholm -> hrm --- pkgs/simple/pinentry-urxvt/default.nix | 127 +++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 pkgs/simple/pinentry-urxvt/default.nix (limited to 'pkgs/simple/pinentry-urxvt/default.nix') diff --git a/pkgs/simple/pinentry-urxvt/default.nix b/pkgs/simple/pinentry-urxvt/default.nix new file mode 100644 index 0000000..7363f26 --- /dev/null +++ b/pkgs/simple/pinentry-urxvt/default.nix @@ -0,0 +1,127 @@ +{ lib, pkgs, ... }@args: + +let + mylib = import ../../../lib/pure.nix { + inherit lib; + }; + + # config cannot be declared in the input attribute set because that would + # cause callPackage to inject the wrong config. Instead, get it from ... + # via args. + config = args.config or {}; + + cfg = eval.config; + + eval = lib.evalModules { + modules = lib.singleton { + _file = toString ./default.nix; + imports = lib.singleton config; + options = { + appName = lib.mkOption { + default = "pinentry-urxvt"; + type = lib.types.str; + }; + display = lib.mkOption { + default = null; + type = lib.types.nullOr lib.types.str; + }; + xwud.className = lib.mkOption { + default = "PinentryUrxvtXwudFloat"; + type = lib.types.str; + }; + }; + }; + }; + + +in + + # pinentry-urxvt - A mechanism for PIN entry utilizing rxvt-unicode + # + # This spawns a PIN entry terminal on top of a tinted screenshot of the + # current display's root window. The display for spawning the terminal can + # be predefined, in which case both the current and the predefined display + # will show the screenshot. + # + # The purpose of the screenshot, aside from looking nice, is to prevent entry + # of the PIN into the wrong window, e.g. by accidentally moving the cursor + # while typing. If necessary, the screenshot can be closed by sending 'q', + # 'Q', or ctrl-c while its focused. + # + pkgs.write "pinentry-urxvt" { + "/bin/pinentry".link = pkgs.writeDash "pinentry-urxvt-wrapper" '' + set -efu + + trap cleanup EXIT + + cleanup() { + ${pkgs.utillinux}/bin/kill -- $(${pkgs.coreutils}/bin/cat "$displayers") + rm "$displayers" + rm "$screenshot" + } + + displayers=$(${pkgs.coreutils}/bin/mktemp -t pinentry-urxvt.$$.displayers.XXXXXXXX) + screenshot=$(${pkgs.coreutils}/bin/mktemp -t pinentry-urxvt.$$.screenshot.XXXXXXXX) + + ${pkgs.xorg.xwd}/bin/xwd -root | + ${pkgs.imagemagick}/bin/convert xwd:- -fill \#424242 -colorize 80% xwd:"$screenshot" + + display_screenshot() { + ${pkgs.exec "pinentry-urxvt.display_screenshot" { + filename = "${pkgs.xorg.xwud}/bin/xwud"; + argv = [ + cfg.xwud.className + "-noclick" + ]; + }} < "$screenshot" & + wait_for_screenshot $! && echo $! >>"$displayers" + } + + # Wait for the xwud window by trying to intercept the call to munmap(). + # If it cannot be intercepted within 0.1s, assume that attaching strace + # wasn't fast enough or xwud doesn't call munmap() anymore. In either + # case fall back to search the window by class name, assuming there can + # be only one per display. + wait_for_screenshot() { + if ! \ + ${pkgs.coreutils}/bin/timeout 0.1 \ + ${pkgs.strace}/bin/strace -p "$1" -e munmap 2>&1 | + read -r _ + then + until ${pkgs.xdotool}/bin/xdotool search \ + --classname ${mylib.shell.escape cfg.xwud.className} + do + ${pkgs.coreutils}/bin/sleep 0.1 + done + fi + } + + display_screenshot + + ${lib.optionalString (cfg.display != null) /* sh */ '' + if test "$DISPLAY" != ${mylib.shell.escape cfg.display}; then + export DISPLAY=${mylib.shell.escape cfg.display} + display_screenshot + fi + ''} + + exec 3<&0 4>&1 5>&2 + ${pkgs.rxvt_unicode}/bin/urxvt \ + -name ${mylib.shell.escape cfg.appName} \ + -e ${pkgs.writeDash "pinentry-urxvt-tty" '' + set -efu + exec 2>&5 + TTY=$(${pkgs.coreutils}/bin/tty) + while read -r line <&3; do + case $line in + 'OPTION ttyname='*) + echo "OPTION ttyname=$TTY" + ;; + *) + echo "$line" + esac + done | ${pkgs.pinentry.tty}/bin/pinentry-tty "$@" >&4 + ''} \ + "$@" + ''; + } -- cgit v1.2.3