#!/bin/bash set -eo pipefail [ -n "$DEBUG" ] && set -x secretmgr=${_SECM_MGR:-rbw} printpass=${_SECM_PRINT:-} listandexit= while getopts bpPlh opt; do case ${opt} in b) secretmgr=rbw ;; p) secretmgr=pass ;; P) printpass=1 ;; l) listandexit=1 ;; h | ?) echo "usage: secretmenu [-bp] [-P] [-l] [query]" echo exit 2 ;; esac done shift $((OPTIND - 1)) # check requirements for tool in bemenu fd flock fzf $secretmgr; do if ! command -v "$tool" >/dev/null; then printf "%s: %s not installed but required\n" "$(basename "$0")" "$tool" >&2 exit 1 fi done __menu() { if [ -t 1 ]; then echo "terminal mode not implemented" exit 1 fi MENU_PROMPT="󰌆 secret" menu -l10 --accept-single ${@:+--filter "$@"} } if [ "$secretmgr" = "rbw" ] && command -v rbw >/dev/null 2>&1; then __list_secrets() { rbw list --fields name,user,folder,id | column -t -s $'\t' } __query_secret() { # query by the last space-separated item (id) rbw get --full -- "${1##* }" 2>&1 } fi if [ "$secretmgr" = "pass" ] && command -v pass >/dev/null 2>&1; then __list_secrets() { prefix=${PASSWORD_STORE_DIR-~/.password-store} prefix=$(readlink -f -- "${prefix}") fd -e gpg . "${prefix}" | sed -e "s#${prefix}/##" -e 's#\.gpg$##' } __query_secret() { pass show "$1" 2>&1 } fi if [ -n "$printpass" ]; then __handle() { awk 'NR==1 {print $0;hit+=1} END{if(hit==0){print("no secret found") >/dev/stderr; exit(1);}}' } else __handle() { awk 'NR==1 {system("wl-copy -n \"" $0 "\"");hit+=1} /^Username: / {gsub("Username: ", "", $0); system("wl-copy -n -p \"" $0 "\"");hit+=1} END{if(hit==0){print("no secret found") >/dev/stderr; exit(1);}}' } fi # main if [ -n "$listandexit" ]; then __list_secrets exit 0 fi # ensure only one menu runs at a time lockfile="$XDG_RUNTIME_DIR"/secretmenu.lock [ "$FLOCKER" != "$lockfile" ] && exec env FLOCKER="$lockfile" _SECM_MGR="$secretmgr" _SECM_PRINT="$printpass" flock -ew 30 "$lockfile" "$0" "$@" trap '{ env UNSAFE=1 rm $lockfile 2>/dev/null || true; }' EXIT TERM INT ico=$(iconez -fs -n dialog-password-symbolic) trap '{ notify-send -a secretmenu -i "${ico}" -c error "secretmenu: failed :(" "pipefail"; exit 1; }' ERR pw=$({ __list_secrets echo ">>pass" echo ">>rbw" } | __menu "$@") case "$pw" in "") exit 1 ;; ">>pass") exec "$0" -p ;; ">>rbw") exec "$0" -b ;; esac __query_secret "$pw" | __handle __ok=$? [ -n "$printpass" ] && exit "$__ok" if [ "$__ok" -eq 0 ]; then notify-send \ -a secretmenu \ -i "${ico}" \ 'secretmenu: secret copied' \ 'will be removed after next paste' fi exit "$__ok"