diff options
Diffstat (limited to 'bin/laptop/pass')
-rwxr-xr-x | bin/laptop/pass | 88 |
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; +} |