pass-pdf
A password-store extension to archive your passwords as a PDF
pass-pdf/pdf.bash
Download raw file: pdf.bash
#!/usr/bin/env bash ROFF_INPUT_DEBUG_FILE="" VERSION=1.0.0 OUTPUT_FILE="" PREAMBLE_FILE="" declare -a EXCLUDE_REGEXES declare -a PASSWORDS PASSWORD_STORE_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}" print_help () { cat <<-_EOF Source: https://sr.ht/~thalia/pass-pdf Usage: $PROGRAM pdf [version,--version,-v] Print extension version. $PROGRAM pdf [help,--help,-h] Print help for the pdf extension. $PROGRAM pdf [-d,--debug-file] Save generated roff input to the specified file for debugging. $PROGRAM pdf [-o,--output path.pdf] [-x,--exclude regex] [-p,--preamble path.txt] [optional passwords...] Save your passwords to a PDF generated with roff. If no arguments are supplied, dump the roff source for all passwords to stdout. If some passwords are supplied on the command line, only save those ones. Pass -o to save to a pdf file instead of dumping the source. Pass -x multiple times to exclude some passwords from being archived. Pass -p to add some preamble to the PDF, if it's a '-' this will be read from stdin instead of a file. _EOF } user_real_name() { grep "^$(whoami)" /etc/passwd | cut -d ':' -f5 | cut -d ',' -f1 } insert_user_supplied_preamble() { if [ "$PREAMBLE_FILE" = "-" ]; then while read -r l; do echo "$l"; done </dev/stdin elif [ -n "$PREAMBLE_FILE" ]; then cat "$PREAMBLE_FILE" fi } escape_roff_input() { sed 's/\\/\\\\/g' } pdf_generate_preamble() { printf ".TL\nPassword Store Backup Created $(date +'%Y-%m-%d %R %Z')\n" printf ".AU\n%s\n" "$(user_real_name)" printf ".CW %s@%s\n" "$(whoami)" "$(hostname -f)" printf ".PP\n%s\n" "$(insert_user_supplied_preamble)" } pdf_generate_password_section() { printf ".NH\n$1\n" pass "$1" | while read -r line; do printf ".LP\n.CW\n%s\n" "$line" | escape_roff_input done } is_password_excluded () { for re in "${EXCLUDE_REGEXES[@]}"; do [[ "$1" =~ $re ]] && return 0 done return 1 } pdf_generate_source () { pdf_generate_preamble if [ $# -eq 0 ]; then find "$PASSWORD_STORE_DIR" -name '*.gpg' | while read -r p; do p="${p#"$PASSWORD_STORE_DIR"/}" p="${p%.gpg}" is_password_excluded "$p" \ || pdf_generate_password_section "$p" done else for p in "$@"; do is_password_excluded "$p" \ || pdf_generate_password_section "$p" shift done fi } maybe_save_roff_input_to_debug_file() { if [ -n "$ROFF_INPUT_DEBUG_FILE" ]; then tee "$ROFF_INPUT_DEBUG_FILE" else tee fi } create_pdf_or_dump_source () { if [ -n "$OUTPUT_FILE" ]; then (pdf_generate_source "$@") \ | preconv \ | maybe_save_roff_input_to_debug_file \ | groff -ms -T pdf > "$OUTPUT_FILE" else pdf_generate_source "$@" fi } assert_arg () { [ -n "$2" ] || { echo "Fatal: Argument '$1' requires an option." 1>&2 (print_help) 1>&2 exit 1; } } while true; do case "$1" in help|--help|-h) print_help; exit 0 ;; version|--version|-v) echo "pass-pdf: $VERSION"; exit 0 ;; --debug-file|-d) assert_arg "$1" "$2"; ROFF_INPUT_DEBUG_FILE="$2"; shift 2;; --output|-o) assert_arg "$1" "$2"; OUTPUT_FILE="$2"; shift 2 ;; --preamble|-p) assert_arg "$1" "$2"; PREAMBLE_FILE="$2"; shift 2 ;; --exclude|-x) assert_arg "$1" "$2"; EXCLUDE_REGEXES+=("$2"); shift 2 ;; *) if [ -n "$1" ]; then PASSWORDS+=("$1"); shift else break fi ; esac done create_pdf_or_dump_source "${PASSWORDS[@]}"