pash/pash

130 lines
2.6 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# pash - simple password manager.
pw_add() {
yn "Generate a password?"
case $REPLY in
[yY])
password=$("${gpg[0]}" --armor --gen-random 0 50)
password=${password:0:50}
;;
*) read -rsp "Enter password: " password ;;
esac
[[ $password ]] ||
die "Failed to generate a password."
"${gpg[0]}" -co "$1.gpg" <<< "$password"
}
pw_del() {
yn "Delete pass file '$1'?"
[[ $REPLY == [yY] ]] &&
rm "$1.gpg"
}
pw_show() {
read -r password < <("${gpg[0]}" -dq "$1.gpg")
[[ ${FUNCNAME[1]} != pw_copy ]] &&
printf '%s\n' "$password"
}
pw_copy() {
pw_show "$1"
if [[ $TMUX ]]; then
tmux load-buffer "$password"
else
hash xclip && xclip -selection clipboard <<< "$password"
fi
}
pw_list() {
shopt -s globstar nullglob
printf '%s\n' "pash"
for pwrd in **; do
[[ -d $pwrd ]] && dir=/ || dir=
nest=${pwrd//[^\/]}
pwrd=${pwrd//[^[:print:]]/^[}
pwrd=${pwrd//.gpg}
printf '%s\n' "${nest//\//│ }├─ ${pwrd##*/}${dir}"
done
printf '└%s\b┘\n' "${nest//\//──┴}"
}
yn() {
read -rn 1 -p "$1 [y/n]: "
printf '\n'
}
die() {
printf 'error: %s\n' "$1" >&2
exit 1
}
usage() { printf '%s' "\
pash 0.1.0 - simple password manager.
=> [a]dd [name] - Create a new password entry.
=> [c]opy [name] - Copy entry to the clipboard.
=> [d]el [name] - Delete a password entry.
=> [l]ist - List all entries.
=> [s]how [name] - Show password for an entry.
"
exit 1
}
main() {
[[ $1 == -? || -z $1 ]] &&
usage
mapfile -t gpg < <(type -p gpg gpg2) && [[ ! -x ${gpg[0]} ]] &&
die "GPG not found."
mkdir -p "${pass_dir:=${XDG_DATA_HOME:=$HOME/.local/share}/pash}" ||
die "Couldn't create password directory."
cd "$pass_dir" ||
die "Can't access password directory."
[[ $1 == [ads]* && -z $2 ]] &&
die "Missing [name] argument."
[[ $1 == [ds]* && ! -f $2.gpg ]] &&
die "Pass file '$2' doesn't exist."
[[ $1 == [a]* && -f $2.gpg ]] &&
die "Pass file '$2' already exists."
[[ $2 == */* && $2 == *../* ]] &&
die "Category went out of bounds."
[[ $2 == /* ]] &&
die "Category can't start with '/'."
[[ $2 == */* ]] &&
{ mkdir -p "${2%/*}" || die "Couldn't create category '${2%/*}'.";}
umask 077
case $1 in
a*) pw_add "$2" ;;
c*) pw_copy "$2" ;;
d*) pw_del "$2" ;;
s*) pw_show "$2" ;;
l*) pw_list ;;
*) usage
esac
}
main "$@"