all repos — dotfiles @ 0a867ad2e58c21d31f0ce106ab5812a152c6b83f

my *nix dotfiles

bin/pw.nix (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
{ pkgs, ... }:

let
  name = "pw";
  gpg = "${pkgs.gnupg}/bin/gpg";
  pwgen = "${pkgs.pwgen}/bin/pwgen";
  git = "${pkgs.git}/bin/git";
  copy = "${pkgs.wl-clipboard}/bin/wl-copy";
in
pkgs.writeShellScriptBin name
  ''
    # pw - a mnml password manager
    [[ -z "$PW_DIR" ]] && PW_DIR="$HOME/.pw"
    init() {
        if [[ ! -e "$PW_DIR" ]]; then
            mkdir -p "$PW_DIR"
            printf "pw: password directory initialized at %s\n" "$PW_DIR"
        else
            printf "PW_DIR is %s\n" "$PW_DIR"
            die "$PW_DIR exists"
        fi
    }
    add() {
        # $1: path to file
        # $2 [optional]: password text
        [[ -z "$PW_KEY" ]] && die "\$PW_KEY not set"
        if [[ "$#" -eq 2 ]]; then
            pass="$2"
        else
            # uses default length of 25 chars, unless PW_LEN is set
            pass="$(${pwgen} "''${PW_LEN:-25}" 1 -s)"
            printf "pw: generated password for %s\n" "$1"
        fi
        if [[ ! -f "$PW_DIR/$1.gpg" ]]; then
            printf "%s" "$pass" | ${gpg} -aer "$PW_KEY" -o "$PW_DIR/$1.gpg"
            printf "pw: %s/%s.gpg created\n" "$PW_DIR" "$1"
        else
            die "the file $PW_DIR/$1.gpg exists"
        fi
        (
            cd $PW_DIR
            ${git} add .
            ${git} commit -m "$(date)"
            remote="$(${git} remote show)"
            branch="$(${git} branch --show-current)"
            ${git} pull -r "$remote" "$branch"
            ${git} push "$remote" "$branch"
        )
    }
    list() {
        (cd "$PW_DIR"; find *.gpg | awk -F '.gpg' '{ print $1 }' )
    }
    del() {
        checkf "$PW_DIR/$1.gpg"
        read -rn 1 -p "pw: are you sure you want to delete $1? [y/n]: "
        printf "\n"
        [[ "$REPLY" == [yY] ]] && {
            rm -f "$PW_DIR/$1.gpg"
            printf "pw: deleted %s" "$1"
        }
    }
    show() {
        checkf "$PW_DIR/$1.gpg"
        ${gpg} --decrypt --quiet --use-agent "$PW_DIR/$1.gpg"
    }
    # TODO: rework having to checkf twice
    copy() {
        checkf "$PW_DIR/$1.gpg"
        if [[ "$OSTYPE" =~ darwin* ]]; then
            show "$1" | head -1 | pbcopy | tr -d '\n'
        else
            show "$1" | head -1 | ${copy} -n
        fi
        printf "pw: copied %s to clipboard\n" "$1"
    }
    usage() {
        usage="
    pw - mnml password manager
    usage: pw [options] [NAME]
    All options except -i and -h require a NAME argument.
    options:
      -i            Initializes password directory at \$HOME/.pw or at \$PW_DIR, if it exists.
      -a            Add a password.
      -g            Generate a password.
      -s            Print password to STDOUT.
      -l            List out all passwords.
      -c            Copy existing password to clipboard.
      -d            Delete password.
      -h            Display this help message and exit.
    Requires PW_KEY to be set. Optionally, set PW_DIR for custom directory location.
    Set PW_LEN to an integer of your choice, to override the default password length of 25.
    "
        printf "%s" "$usage"
        exit 1
    }
    checkf() {
        [[ ! -f "$1" ]] &&
            die "$1 does not exist"
    }
    die() {
        printf "error: %s\n" "$1" >&2
        exit 1
    }
    main() {
        [[ -z "$1" ]] && {
            usage
        }
        while getopts "ila:g:s:c:d:h" options
        do
            # shellcheck disable=SC2221,SC2222
            case "$options" in
                i) init ;;
                l) list ;;
                g) add "$OPTARG" ;;
                a)
                   read -rsp "enter password: " pass
                   printf "\n"
                   add "$OPTARG" "$pass"
                   ;;
                s) show "$OPTARG" ;;
                c) copy "$OPTARG" ;;
                d) del "$OPTARG" ;;
                *|h) usage ;;
            esac
        done
        shift $(( OPTIND -1 ))
    }
    main "$@"
  ''