commit 86e6d275efee2e6c03451cfa2411b36f425e755b
parent 1bbd90ab203e2615813c4c405285c29711888c9b
Author: Anders Damsgaard <anders@adamsgaard.dk>
Date: Tue, 21 Jan 2020 10:22:52 +0100
Rewrite passmenu for posix shell and add more options
Diffstat:
M | .local/bin/passmenu | | | 154 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------- |
1 file changed, 133 insertions(+), 21 deletions(-)
diff --git a/.local/bin/passmenu b/.local/bin/passmenu
@@ -1,27 +1,139 @@
-#!/usr/bin/env bash
+#!/bin/sh
+# requirements: pass(1), dmenu(1), xdotool(1) for -t, -n and -u options
-shopt -s nullglob globstar
+version=0.1.0
-typeit=0
-if [ "$1" = "--type" ]; then
- typeit=1
- shift
-fi
+pass_dir="$HOME/.password-store"
+
+show_help()
+{
+ echo "usage: ${0##*/} [OPTIONS] [QUERY]"
+ echo "shows all passwords from pass(1) and allows interactive selection"
+ echo "via dmenu(1). By default, the password is copied to the X clipboard."
+ echo
+ echo "OPTIONS are one or more of the following:"
+ echo " -h show this message"
+ echo " -v show version and license information"
+ echo " -V show verbose information"
+ echo " -t type out the password instead of copying to clipboard"
+ echo " -n type out newline character after password type out (-t)"
+ echo " -u VAL type out VAL before copying password or typing it out"
+ echo " -- do not consider any following args as options"
+ echo
+ echo "EXAMPLES:"
+ echo "Open interactive menu with all passwords:"
+ echo " ${0##*/}"
+ echo
+ echo "Type out password matching 'newyorktimes':"
+ echo " ${0##*/} newyorktimes"
+ echo
+ echo "Type out username, tab character, and password selected from menu,"
+ echo "and hit return:"
+ echo " ${0##*/} -n -t -u \"myusername\\t\""
+}
+
+show_version()
+{
+ echo "${0##*/} version $version"
+ echo "licensed under the ISC License"
+ echo "written by Anders Damsgaard, anders@adamsgaard.dk"
+ echo "https://src.adamsgaard.dk/dotfiles"
+}
+
+die()
+{
+ printf '%s: error: %s\n' "${0##*/}" "$1" >&2
+ exit 1
+}
-prefix=${PASSWORD_STORE_DIR-~/.password-store}
-password_files=( "$prefix"/**/*.gpg )
-password_files=( "${password_files[@]#"$prefix"/}" )
-password_files=( "${password_files[@]%.gpg}" )
+get_password_files()
+{
+ find "$pass_dir" -type f -iname "*.gpg"
+}
-password=$(printf '%s\n' "${password_files[@]}" | dmenu -i "$@")
+strip_root_dir()
+{
+ sed "s,${pass_dir%/}/,,"
+}
-[ -n "$password" ] || exit
+match_password_file()
+{
+ local _passfile, _passfiles
+ _passfiles="$(get_password_files | strip_root_dir)"
+ if [ "$#" -gt 0 ]; then
+ _passfile="$(printf '%s' "$_passfiles" | grep -i "$@")"
+ if [ "$(printf '%s\n' "$_passfile" | wc -l)" -eq 0 ]; then
+ die "no password matches '$@'"
+ elif [ "$(printf '%s\n' "$_passfile" | wc -l)" -gt 1 ]; then
+ die "more than one password matches '$@': $_passfile"
+ fi
+ else
+ _passfile="$(printf '%s\n' "$_passfiles" | dmenu -i)"
+ fi
+ if [ ! -r "$pass_dir/$_passfile" ]; then
+ die "no password file: $pass_dir/$_passfile"
+ fi
+ printf '%s\n' "$_passfile"
+}
+
+retrieve_password()
+{
+ local _passfile="${1%%.gpg}"
+ if [ -n "$prefix" ]; then
+ printf "$prefix" | xdotool type --clearmodifiers --file -
+ fi
+
+ if [ "$typeout" = 1 ]; then
+ pass show "$_passfile" | \
+ { IFS= read -r pass; printf %s "$pass"; } | \
+ xdotool type --clearmodifiers --file -
+ if [ "$newline" = 1 ]; then
+ #sleep 1
+ xdotool key Return
+ fi
+ else
+ pass show -c "$_passfile"
+ fi
+}
+
+verbose=0
+typeout=0
+newline=0
+prefix=""
+while :; do
+ case "$1" in
+ -h)
+ show_help
+ exit 0
+ ;;
+ -v)
+ show_version
+ exit 0
+ ;;
+ -V)
+ verbose=1
+ ;;
+ -t)
+ typeout=1
+ ;;
+ -n)
+ newline=1
+ ;;
+ -u)
+ prefix="$2"
+ shift
+ ;;
+ --) # end all options
+ shift
+ break
+ ;;
+ -?*)
+ die 'unknown option specified'
+ ;;
+ *) # No more options
+ break
+ esac
+ shift
+done
-if [ $typeit -eq 0 ]; then
- pass show -c "$password" 2>/dev/null
-else
- pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } |
- xdotool type --clearmodifiers --file -
- sleep 1
- xdotool key Return
-fi
+retrieve_password "$(match_password_file "$@")"