#!/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; }