nix/bin/pw.nix (view raw)
1{ pkgs, theme, ... }:
2
3let
4 name = "pw";
5 pamixer = "${pkgs.pamixer}/bin/pamixer";
6 lemonbar = "${pkgs.lemonbar-xft}/bin/lemonbar";
7in
8pkgs.writeShellScriptBin name
9 ''
10 #!/usr/bin/env bash
11 # pw - a mnml password manager
12 command -v gpg >/dev/null 2>&1 && gpg=gpg
13 command -v gpg2 >/dev/null 2>&1 && gpg=gpg2
14 # check if xclip or pbcopy exist
15 # command -v xclip >/dev/null 2>&1 && copy="xclip -rmlastnl -selection clipboard"
16 # command -v pbcopy >/dev/null 2>&1 && copy="pbcopy | tr -d '\n'"
17 # export PW_DIR to your own path
18 [[ -z "$PW_DIR" ]] && PW_DIR="$HOME/.pw"
19 init() {
20 if [[ ! -e "$PW_DIR" ]]; then
21 mkdir -p "$PW_DIR"
22 printf "pw: password directory initialized at %s\n" "$PW_DIR"
23 else
24 printf "PW_DIR is %s\n" "$PW_DIR"
25 die "$PW_DIR exists"
26 fi
27 }
28 add() {
29 # $1: path to file
30 # $2 [optional]: password text
31 [[ -z "$PW_KEY" ]] && die "\$PW_KEY not set"
32 if [[ "$#" -eq 2 ]]; then
33 pass="$2"
34 else
35 # uses default length of 25 chars, unless PW_LEN is set
36 pass="$(pwgen "${PW_LEN:-25}" 1 -s)"
37 printf "pw: generated password for %s\n" "$1"
38 fi
39 if [[ ! -f "$PW_DIR/$1.gpg" ]]; then
40 printf "%s" "$pass" | "$gpg" -aer "$PW_KEY" -o "$PW_DIR/$1.gpg"
41 printf "pw: %s/%s.gpg created\n" "$PW_DIR" "$1"
42 else
43 die "the file $PW_DIR/$1.gpg exists"
44 fi
45 (
46 cd $PW_DIR
47 git add .
48 git commit -m "$(date)"
49 remote="$(git remote show)"
50 branch="$(git branch --show-current)"
51 git pull -r "$remote" "$branch"
52 git push "$remote" "$branch"
53 )
54 }
55 list() {
56 (cd "$PW_DIR"; find *.gpg | awk -F '.gpg' '{ print $1 }' )
57 }
58 del() {
59 checkf "$PW_DIR/$1.gpg"
60 read -rn 1 -p "pw: are you sure you want to delete $1? [y/n]: "
61 printf "\n"
62 [[ "$REPLY" == [yY] ]] && {
63 rm -f "$PW_DIR/$1.gpg"
64 printf "pw: deleted %s" "$1"
65 }
66 }
67 show() {
68 checkf "$PW_DIR/$1.gpg"
69 "$gpg" --decrypt --quiet --use-agent "$PW_DIR/$1.gpg"
70 }
71 # TODO: rework having to checkf twice
72 copy() {
73 checkf "$PW_DIR/$1.gpg"
74 if [[ "$OSTYPE" =~ darwin* ]]; then
75 show "$1" | head -1 | pbcopy | tr -d '\n'
76 else
77 show "$1" | head -1 | xclip -rmlastnl -selection clipboard
78 fi
79 printf "pw: copied %s to clipboard\n" "$1"
80 }
81 usage() {
82 usage="
83 pw - mnml password manager
84 usage: pw [options] [NAME]
85 All options except -i and -h require a NAME argument.
86 options:
87 -i Initializes password directory at \$HOME/.pw or at \$PW_DIR, if it exists.
88 -a Add a password.
89 -g Generate a password.
90 -s Print password to STDOUT.
91 -l List out all passwords.
92 -c Copy existing password to clipboard.
93 -d Delete password.
94 -h Display this help message and exit.
95 Requires PW_KEY to be set. Optionally, set PW_DIR for custom directory location.
96 Set PW_LEN to an integer of your choice, to override the default password length of 25.
97 "
98 printf "%s" "$usage"
99 exit 1
100 }
101 checkf() {
102 [[ ! -f "$1" ]] &&
103 die "$1 does not exist"
104 }
105 die() {
106 printf "error: %s\n" "$1" >&2
107 exit 1
108 }
109 main() {
110 [[ -z "$1" ]] && {
111 usage
112 }
113 while getopts "ila:g:s:c:d:h" options
114 do
115 # shellcheck disable=SC2221,SC2222
116 case "$options" in
117 i) init ;;
118 l) list ;;
119 g) add "$OPTARG" ;;
120 a)
121 read -rsp "enter password: " pass
122 printf "\n"
123 add "$OPTARG" "$pass"
124 ;;
125 s) show "$OPTARG" ;;
126 c) copy "$OPTARG" ;;
127 d) del "$OPTARG" ;;
128 *|h) usage ;;
129 esac
130 done
131 shift $(( OPTIND -1 ))
132 }
133 main "$@"
134 ''