Password Manager Made with Only Bash 2
Hello, it's me, the incompetent one.
You know, there's this convenient .bashrc, right?
_ssh_hosts() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "$(awk '{print $1}' ~/.ssh/known_hosts | cut -d, -f1 | sort -u)" -- "$cur") )
}
complete -F _ssh_hosts ssh
(I found it somewhere before and copied it)
So, I thought these convenient built-in bash commands are super useful! And I tried incorporating them into a password manager I made myself.
It wasn't so much that I wanted to create a password manager, but rather that I just wanted to use complete.
GitHub - haturatu/ppbash: My own password generation & manager made with only bash
Explanation
_usage
This is an internal helper function used when no arguments are passed. It's just made to be reusable even if more password generation commands are added.
_usage() {
local pass_func="$1"
local phrase="$2"
local filename="$3"
if [[ -z "$filename" ]]; then
echo "Usage: $pass_func <filename> <phrase>"
echo
echo "Description:"
echo " $pass_func generates a password from the specified <phrase>,"
echo " and saves it encrypted as <filename> in ~/.${pass_func}/."
echo
echo "Arguments:"
echo " <filename> : Identifier (filename) used for saving/loading"
echo " <phrase> : The original phrase (enclose in quotes if it contains spaces)"
echo
echo "Example:"
echo " $pass_func mymail 'Like a rolling stone'"
echo
echo "Reuse:"
echo " If you specify an already saved <filename>, its password will be displayed again."
echo
echo "Completion:"
echo " ${pass_func} <Tab> will complete with saved filenames."
echo
echo "Related commands:"
echo " ppmenu : Lists registered password directories."
echo
return 1
fi
return 0
}
_init_pass_dir
I wondered if it was necessary to write this specifically, but it would be redundant, so I made this a helper function too.
_init_pass_dir() {
local dir=$1
if [[ ! -d $dir ]]; then
mkdir -p $dir
fi
}
_pass_list
It stores the completion files to be passed to complete in an array.printf "%s " "${passfiles[@]##*/}" lists only the filenames from an array of full paths.
It's similar to awk, but for example, if it's /uoo/ooo/genki, it will only be genki.
_pass_list() {
local dir="$1"
local passfiles=()
if [[ -d "$dir" ]]; then
passfiles=("$dir"/*)
printf "%s " "${passfiles[@]##*/}"
fi
}
_register_func_dir
It's a bit confusing, so maybe I should fix the function name...
Functions are stored in an array.declare -F extracts functions defined in bash that start with pb.
These are then stored in the PASS_DIRS array.
After that, complete -W enables completion for space-separated words when the $fn function is entered.
_register_func_dir() {
while read -r fn _; do
local dir="$HOME/.$fn"
PASS_DIRS+=("$dir")
complete -W "$(_pass_list "$dir")" "$fn"
done < <(declare -F | awk '{print $3}' | grep '^pb')
}
I think complete -F is more versatile than complete -W.
This is because it dynamically generates completions by executing a function.-W completes from static values, but for the ssh completion mentioned earlier,
_ssh_hosts() {
local cur=${COMP_WORDS[COMP_CWORD]}
COMPREPLY=( $(compgen -W "$(awk '{print $1}' ~/.ssh/known_hosts | cut -d, -f1 | sort -u)" -- "$cur") )
}
complete -F _ssh_hosts ssh
If you press Tab after ssh, _ssh_hosts will be executed.
My future self will probably make it so that it can be completed with complete -F later...
The rest of the password generation functions aren't very interesting, so I'll stop here.
[Creepy] Password Manager Made with Only .bashrc - SOULMINIGRIG
The mechanism is described around here, and basically, it just uses the helper functions I've already introduced.
See you next time. Thank you.