[PATCH] RFC: hooks for clipboard manager integration
Allan Odgaard
lists+pass at simplit.com
Mon Jul 6 05:00:08 CEST 2020
On 6 Jul 2020, at 1:03, Dov Feldstern wrote:
> I'm not sure exactly what you mean by a "callback" here: a specific
> implementation of how exactly to do the copy and paste (which the
> current code seems to *almost* support, in the form of "copy_cmd" and
> "paste_cmd", all that's missing is a means for changing them less
> intrusively than by adding more if cases in the code itself)? Or
> remiplementing the entire clip() function as a whole?
I was talking more in the abstract :)
But yes, I think the practical implementation would be for a simple way
to fully replace the clip function, without having to send patches
upstream, but of course also with a more clearly defined “contract”.
An implementation could be something like this:
for file in "$PASS_DIR"/override.d/* /etc/default/pass
"${XDG_CONFIG_HOME:-$HOME/.config}/pass/default"; do
[[ -x "$file" ]] && . "$file"
done
⋮
${clip_function:-clip} $password $duration
Distribution ("$PASS_DIR"/override.d/) could define multiple clip
functions and set $clip_function to the one appropriate for the
platform, and user could change that to either an alternative function
from the distribution, or define their own clip function and set that to
be used (either globally via /etc/default or locally via ~/.config).
> IIUC, the latter can already be achieved by providing a
> platform-specific implementation of clip()?
Yes, the problem currently is only that adding support for clipboard
manager by providing new clip override requires patching the existing
source; so this part should be made overridable.
> The problem with reimplementation, though (and why I ultimately
> preferred to use hooks), is that there is non-trivial logic going on
> in the function, which might be lost by the reimplementations. For
> example, the sample snippet you provide above doesn't deal with the
> subtlety of avoiding a second call to 'pass -c' restoring
I do not directly disagree, however, the non-trivial logic boils down to
running sleep in a subprocess with a special name so that pass can kill
it.
This is not complex (one line), but I agree that it would be nice to
“abstract” it because there are some hardcoded assumptions about how
to name the process, furthermore, the current implementation does not
look ideal, as pkill (called by pass, which would still be outside the
clip function) is followed by sleep 0.5, which is to give time for the
clip function to restore the clipboard.
It would be good to get this replaced with a proper wait (for old clip
function/process to exit): Especially on macOS, this delay could be too
short, as Apple in their infinite wisdom have littered the system with
“code signature verification” that does online certificate
revocation checks that have a 3s timeout, so these days, it is sadly not
uncommon to see delays from low-level APIs of 0.5 seconds and more.
What I was originally thinking was to provide a “sleeper function”
to the clip override, e.g. something like this:
function user_function {
password="$1"
sleeper="$2"
old="$(pbpaste)"
printf "%s" "$password" | pbcopy
$sleeper
if [[ "$(pbpaste)" == "$password" ]]; then
printf "%s" "$old" | pbcopy
fi
}
I was originally rejecting this idea, because it requires bash code
“in the middle” of the function, e.g. for macOS I was thinking of
writing the entire clip function in Swift or Objective-C (necessary to
tag clipboard content and restore non-text data), but possible could do
it with a pre-sleep and post-sleep argument passed to the compiled
function, the downside is it then needs external storage for old
clipboard content, but it avoids introducing a “contract” for how to
abort
An alternative would be to also make the pkill a user override, so for
macOS I could have this in ~/.config/pass/default:
clip_function=/path/to/pass_helper clip
abort_function=/path/to/pass_helper abort
Calling `pass_helper clip …` would setup SIGTERM handler, and calling
`pass_helper abort` would be responsible for sending SIGTERM and wait
for the process to terminate.
I am leaning toward the simpler $sleeper argument though, so
~/.config/pass/default would contain:
function macos_clip_function {
password="$1"
sleeper="$2"
/path/to/pass_helper copy "$password"
$sleeper
/path/to/pass_helper restore
}
clip_function=macos_clip_function
> […] Although, perhaps for a platform-specific implementation it
> makes more sense to expect a high-quality implementation […]
Yes, although an attempt should be made to simplify the interface for
platform-specific implementations, that was really what I was aiming for
with my reply: Allow overrides to be provided by users, simplify and/or
document the contract, provide helper functions if necessary (or use
higher order functions), etc.
And if you still think hooks make sense: provide a “platform
specific” override that uses hooks. So a user can put this in
~/.config/pass/default:
clip_function=xclip_with_user_hooks
And it will use xclip for read/write, but call user hooks before/after
touching the clipboard.
More information about the Password-Store
mailing list