#!/bin/sh set -eu autotype=0 copyisset=0 fileisuser=0 help=0 onlypassword=0 squash=0 typeisset=0 COPY_CMD="wl-copy" TYPE_CMD="wtype -" _trim() { var="$*" # remove leading whitespace characters var="${var#"${var%%[![:space:]]*}"}" # remove trailing whitespace characters var="${var%"${var##*[![:space:]]}"}" printf '%s' "$var" } # the explicit newlines here are funky, but needed due to command substitution # stripping trailing newlines so `printf '%s\n' "$line"` cannot be used _parse_fields() { has_username=0 fields="$(pass show "$password" | tail -n +2 | cut -d: -f1 -s)" field_list="password " if [ "$fileisuser" -eq 1 ]; then has_username=1 line="username" field_list="$field_list$line " fi for line in $fields; do if [ "$line" = "username" ]; then has_username=1 field_list="$field_list$line " elif [ "$line" = "otpauth" ]; then field_list="${field_list}OTP " elif [ "$line" = autotype_always ]; then autotype=1 else field_list="$field_list$line " fi done if [ "$typeisset" -eq 1 ] && [ "$has_username" -eq 1 ]; then printf "autotype " fi printf '%s' "$field_list" } _pass_field() { _trim "$(pass show "$password" | tail -n+2 | grep "^${*}:.*$" | cut -d: -f1 -s --complement)" } _pass_get() { if [ "$1" = "password" ]; then pass show "$password" | { IFS= read -r pass; printf %s "$pass"; } elif [ "$1" = "OTP" ]; then pass otp "$password" | tail -n1 | { IFS= read -r pass; printf %s "$pass"; } elif [ "$fileisuser" -eq 1 ] && [ "$1" = "username" ]; then printf %s "$passname" else _pass_field "$@" fi } _usage() { printf "Usage: wofi-pass [options]\n" printf " -a, --autotype autotype whatever entry is chosen\n" printf " -c, --copy=[cmd] copy to clipboard. Defaults to wl-copy if no cmd is given.\n" printf " -f, --fileisuser use the name of the password file as username\n" printf " -h, --help show this help message\n" printf " -s, --squash don't show field choice if password file only contains password\n" printf " -t, --type=[cmd] type the selection instead of copying to clipboard.\n" printf " Defaults to wtype if no cmd is given.\n" } OPTS="$(getopt --options ac::fhst:: --longoptions autotype,copy::,fileisuser,help,squash,type:: -n 'wofi-pass' -- "$@")" eval set -- "$OPTS" while true; do case "$1" in -a | --autotype ) autotype=1; shift ;; -c ) copyisset=1; copy_cmd="$COPY_CMD"; shift ;; --copy ) copyisset=1 if [ -n "$2" ]; then copy_cmd="$2" shift 2 else copy_cmd="$COPY_CMD" shift fi ;; -f | --fileisuser ) fileisuser=1; shift;; -h | --help ) help=1; shift ;; -s | --squash ) squash=1; shift ;; -t ) typeisset=1; type_cmd="$TYPE_CMD"; shift ;; --type ) typeisset=1 if [ -n "$2" ]; then type_cmd="$2" shift 2 else type_cmd="$TYPE_CMD" shift fi ;; -- ) shift; break;; * ) break;; esac done if [ "$help" -eq 1 ]; then _usage >&2 exit 0 fi if [ "$typeisset" -eq 1 ] && [ "$copyisset" -eq 1 ]; then printf "copy and type cannot be used at same time. Please pass only one.\n" exit 1 elif [ "$typeisset" -eq 0 ] && [ "$copyisset" -eq 0 ]; then printf "neither -c/--copy or -t/--type passed. Defaulting to copying with wl-copy." copy_cmd="$COPY_CMD" fi cd "${PASSWORD_STORE_DIR:-$HOME/.password-store}" password_files="$(find . -name "*.gpg" | sed "s/^\.\/\(.*\)\.gpg$/\1/")" password=$(printf '%s\n' "$password_files" | wofi --dmenu) [ -n "$password" ] || exit if [ "$fileisuser" -eq 1 ]; then passname=$(printf '%s' "$password" | sed "s,.*/\(\),\1,") fi field_list="$(_parse_fields)" field_count="$(printf '%s' "$field_list" | wc -l)" if [ "$squash" -eq 1 ] && [ "$field_count" -eq 0 ]; then field="password" onlypassword=1 elif [ "$autotype" -ne 1 ]; then field=$(printf '%s\n' "$field_list" | wofi --dmenu) fi # get the command to output to if [ "$typeisset" -eq 1 ]; then output_cmd=$type_cmd else output_cmd=$copy_cmd fi if [ "$autotype" -eq 1 ] || [ "$field" = "autotype" ]; then if [ "$fileisuser" -eq 1 ]; then username="$passname" else username=$(_pass_get "username") fi password=$(_pass_get "password") # check if we are autotyping a password-only file if [ "$onlypassword" -eq 1 ]; then printf '%s\n' "$password" | $output_cmd else printf '%s\t%s\n' "$username" "$password" | $output_cmd fi else _pass_get "$field" | $output_cmd fi