#!/bin/bash set -eo pipefail [ -n "$DEBUG" ] && set -x ico=$(iconez -fs -n dialog-password-symbolic) trap '{ notify-send -a secretmenu -i "${ico}" -c error "secretmenu: failed :(" "pipefail"; exit 1; }' ERR secretmgr=rbw printpass= while getopts bpPh name; do case ${name} in b) secretmgr=rbw ;; p) secretmgr=pass ;; P) printpass=1 ;; h | ?) echo "usage: secretmenu [-bp] [-P] [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 # ensure only one menu runs at a time lockfile="$XDG_RUNTIME_DIR"/secretmenu.lock [ "$FLOCKER" != "$lockfile" ] && exec env FLOCKER="$lockfile" flock -ew 30 "$lockfile" "$0" "$@" trap '{ env UNSAFE=1 rm $lockfile 2>/dev/null || true; }' EXIT TERM INT __menu() { if [ -t 1 ]; then echo "terminal mode not implemented" exit 1 fi MENU_PROMPT="󰌆 secret" menu --list=10 --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:/ {system("wl-copy -n -p " $2);hit+=1} END{if(hit==0){print("no secret found") >/dev/stderr; exit(1);}}' } fi # main 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' else notify-send \ -a passmenu \ -i "${ico}" \ -c error \ 'secretmenu: failed :(' \ "check stderr for details" exit 1 fi