summaryrefslogtreecommitdiffstats
path: root/bin/laptop/pass
diff options
context:
space:
mode:
Diffstat (limited to 'bin/laptop/pass')
-rwxr-xr-xbin/laptop/pass88
1 files changed, 88 insertions, 0 deletions
diff --git a/bin/laptop/pass b/bin/laptop/pass
new file mode 100755
index 0000000..fd4a9aa
--- /dev/null
+++ b/bin/laptop/pass
@@ -0,0 +1,88 @@
+#!/usr/bin/env perl
+use strict;
+use warnings;
+
+my $PASS = '/usr/bin/pass';
+
+my $cmd = $ARGV[0];
+
+if ($cmd && $cmd eq 'search') {
+ shift @ARGV;
+
+ chdir "$ENV{HOME}/.password-store"
+ or die "password store not initialized";
+
+ require Path::Class;
+
+ my $pat_str = pop @ARGV;
+ my $pattern = qr/$pat_str/;
+
+ my $username = grep { $_ eq '-u' } @ARGV;
+ @ARGV = grep { $_ ne '-u' } @ARGV;
+
+ my $clipboard = grep { $_ eq '-c' || $_ eq '--clip' } @ARGV;
+
+ my @found = Path::Class::Dir->new('.')->traverse(sub {
+ my ($file, $c) = @_;
+ return if $file eq '.git';
+ return (
+ $c->(),
+ ((-f $file && $file =~ s/\.gpg$// && $file =~ $pattern)
+ ? ($file)
+ : ()),
+ );
+ });
+
+ if (@found < 1) {
+ die "No passwords found matching '$pat_str'\n";
+ }
+ elsif (@found > 1) {
+ die "Ambiguous pattern '$pat_str': could match any of @found\n";
+ }
+ else {
+ if (my $pass = `$PASS show '$found[0]'`) {
+ if ($username) {
+ if ($found[0] =~ m{^[^/]*/[^/]*/([^/]*)$}) {
+ my $user = $1;
+ if ($clipboard) {
+ clip($user);
+ }
+ else {
+ print "$user\n";
+ }
+ }
+ else {
+ die "$found[0] has no username";
+ }
+ }
+
+ if ($clipboard) {
+ $pass =~ s/\n.*//s;
+ clip($pass);
+ }
+ else {
+ print $pass;
+ }
+ }
+ }
+}
+else {
+ exec { $PASS } $PASS, @ARGV
+}
+
+sub clip {
+ my ($text) = @_;
+ my @pids;
+ for my $selection (qw(primary clipboard)) {
+ my $pid = fork;
+ if (!$pid) {
+ open my $fh, '|-', "timeout 1m xclip -loops 1 -quiet -selection $selection 2> /dev/null"
+ or die "couldn't run xclip";
+ $fh->write("$text\n");
+ $fh->close;
+ exit;
+ }
+ push @pids, $pid;
+ }
+ waitpid($_, 0) for @pids;
+}