aboutsummaryrefslogtreecommitdiff
path: root/pw
blob: 90be310972fafa13bf87ad7dbdbbae85ba040fbe (plain)
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
#!/usr/bin/env bash
# pw - a mnml password manager

# export PW_DIR to your own path
[[ -z "$PW_DIR" ]] && PW_DIR="$HOME/.pw"

init() {
    if [[ ! -e "$PW_DIR" ]]; then
        mkdir -p "$PW_DIR"
        echo "pw: password directory initialized at $PW_DIR"
    else
        echo "PW_DIR is $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)"
        echo "pw: generated password for $1"
    fi
    if [[ ! -f "$PW_DIR/$1.gpg" ]]; then
        echo "$pass" | gpg2 -er "$PW_KEY" -o "$PW_DIR/$1.gpg"
        echo "pw: $PW_DIR/$1.gpg created"
    else
        die "the file $PW_DIR/$1.gpg exists"
    fi
}

list() {
    for f in "$PW_DIR"/*.gpg; do
        printf '%s\n' "$(basename "${f%.gpg}")"
    done
}

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"
        echo "pw: deleted $1"
    }
}

show() {
    checkf "$PW_DIR/$1.gpg"
    gpg2 --decrypt --quiet --use-agent "$PW_DIR/$1.gpg" | head -1
}

# TODO: rework having to checkf twice

copy() {
    checkf "$PW_DIR/$1.gpg"
    show "$1" | xclip -rmlastnl -selection clipboard
    echo "pw: copied $1 to clipboard"
}

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.
"

    echo "$usage"
    exit 1
}

checkf() {
    [[ ! -f "$1" ]] &&
        die "$1 does not exist"
}

die() {
    printf "error: %s\n" "$1"
    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 "$@"