new tool
[hband-tools.git] / half-baked / cred
blob2c3f1703daaf3115b8a3e63edc55c192638206d9
1 #!/bin/bash
3 # need to set these shell options before they are relied upon when bash parses the big { ... } block later down.
4 shopt -s nocasematch
5 shopt -s expand_aliases
6 # aliases in non-interactive bash script are not evaluated in the same scope where they are defined,
7 # but they are in the big { ... } block below.
8 alias set_site='if [ -z "${site:-}" ]; then set_site_func "${1:-}"; shift; fi;'
11 set -eE
12 set -o pipefail
13 set -u
15 . /usr/lib/tool/bash-utils
16 . /usr/lib/tool/ansi-codes
18 TAB=$'\t'
20 print_traceback()
22 local i stack_size=${#FUNCNAME[@]}
23 for (( i=1; i<stack_size; i++ )); do
24 local func="${FUNCNAME[$i]}"
25 [[ $func = "" ]] && func=MAIN
26 local linen="${BASH_LINENO[$(( i - 1 ))]}"
27 local src="${BASH_SOURCE[$i]}"
28 [[ "$src" = "" ]] && src=non_file_source
30 echo -n "$ANSI_bold$ANSI_fg_black"
31 echo " function: $func"
32 echo " file: $src (line $linen)"
33 echo -n "$ANSI_reset"
35 local line_number_text_sep='| '
36 nl -ba -w ${#linen} -s " $line_number_text_sep" "$src" | grep -C 2 -E "^\s*$linen " |\
37 prefixlines " " |\
38 sed -e "s/^\(\s*$linen\) \(.\{${#line_number_text_sep}\}\)\(.*\)/\1-\2$ANSI_italic\3$ANSI_normal/" |\
39 sd '^' "$ANSI_bold$ANSI_fg_black" | sd '$' "$ANSI_reset"
40 done
43 trap 'print_traceback >&2' ERR
45 set_site_func()
47 local param=$1
48 if [ -z "$1" ]
49 then
50 errx 1 "Enter site name or directory!"
51 elif [ -d "$param" ]
52 then
53 site=`basename "$param"`
54 else
55 site=$1
59 is_secret()
61 [[ $1 =~ password|key|cvc|secret|pin ]]
64 do_clip()
66 local prop=$1
67 if type copyq 1>/dev/null 2>&1 && is_secret "$prop"
68 then
69 copyq_monitoring=`copyq monitoring`
70 if [ "$copyq_monitoring" = true ]
71 then
72 copyq disable
74 copyq copy -
75 if [ "$copyq_monitoring" = true ]
76 then
77 copyq enable
79 else
80 xclip -i -selection clipboard
85 basedir=~/cred
86 site=''
89 if [ "${1:-}" = site ]
90 then
91 shift || true
92 set_site
95 subcmd=${1:-}
96 shift || true
100 case "$subcmd" in
101 (dump)
102 set_site
103 options=("$@")
106 cd "$basedir/$site"
107 GLOBIGNORE=${GLOBIGNORE:-}${GLOBIGNORE:+:}".:..:.[!/.]*:..[!/]*:-*"
108 for file in *
110 if [ ! -f "$file" ]
111 then
112 continue
114 if is_secret "$file"
115 then
116 if in_list reveal-secrets "${options[@]}"
117 then
118 true
119 elif in_list hash-secrets "${options[@]}"
120 then
121 hash=`cat "$file" | md5sum | cut -c 1-32`
122 echo "$file$TAB$hash$TAB""hash-algo=md5"
123 continue
124 else
125 echo "$file"$'\t'"*****"
126 continue
130 grep . "$file" | prefixlines "$file"$'\t'
131 done
133 site=${site%/}
134 if [[ $site =~ / ]]
135 then
136 parent=${site%/*}
137 cred dump "$parent" "${options[@]}"
141 (password)
142 set_site
143 cat "$basedir/$site/PASSWORD"
145 (list-sites)
146 find -L "$basedir" -path "$basedir/${1:-}*" -type d -printf "%P\n"
148 (prop|clip)
149 set_site
150 prop=${1:?'enter property name!'}
151 shift
152 if [ $# = 0 ]
153 then
154 case "$subcmd" in
155 (prop)
156 if is_secret "$prop"
157 then
158 warnx "$prop is a secret."
159 warnx "enter 'cred [...] prop [...] $prop show' explicitely, or"
160 warnx "more preferably 'cred [...] prop [...] $prop clip' to copy to the clipboard!"
161 false
162 else
163 cat "$basedir/$site/$prop"
166 (clip)
167 cat "$basedir/$site/$prop" | do_clip "$prop"
169 esac
170 elif [ "$subcmd" = prop ]
171 then
172 case "$1" in
173 (set)
174 shift
175 val=$*
176 mkdir -p "$basedir/$site"
177 printf '%s' "$val" > "$basedir/$site/$prop"
179 (edit)
180 mkdir -p "$basedir/$site"
181 "${EDITOR:-$VISUAL}" "$basedir/$site/$prop"
183 (read)
184 if is_secret "$prop"
185 then
186 read -s -p "$prop: " -e val
187 else
188 read -p "$prop: " -e val
190 printf '%s' "$val" > "$basedir/$site/$prop"
192 (del)
193 rm "$basedir/$site/$prop"
195 (show)
196 cat "$basedir/$site/$prop"
198 (clip)
199 cat "$basedir/$site/$prop" | do_clip "$prop"
202 false "invalid argument"
204 esac
207 (fill-form)
208 set_site
209 if [ $# -gt 0 ]
210 then
211 strings=''
212 for prop in "$@"
214 val=`cat "$basedir/$site/$prop"`
215 strings="$strings$val"$'\t'
216 done
217 xdotool key Alt+Tab type "$strings"
218 else
219 errx 1 "Enter property names in order to fill the form on the window brought to focus by Alt+Tab."
222 (list-props)
223 set_site
224 find "$basedir/$site" -type f -printf "%P\n"
226 (generate-password)
227 set_site
228 newpwd=$(pwgen -y 8 1)$(pwgen -y 8 1)
229 [ -n "$newpwd" ]
230 pwdfile=$basedir/$site/PASSWORD
231 mkdir -p "$basedir/$site"
232 if [ -s "$pwdfile" ]
233 then
234 cur_pwd=`cat "$pwdfile"`
235 atime=`stat -c %x "$pwdfile"`
236 now=`date +'%F %T.%N %z'`
237 echo "$atime $now $cur_pwd" >> "$basedir/$site/OLDPASSWORDS"
239 printf '%s' "$newpwd" > "$pwdfile"
241 (compscript)
242 cat <<'EOF'
243 _autocomplete_cred() {
244 local compreply
245 local curr_word=${COMP_WORDS[$COMP_CWORD]}
246 local prev_word=${COMP_WORDS[$[COMP_CWORD - 1]]}
247 local site_subcmds="list-sites dump generate-password list-props prop clip fill-form"
249 case $COMP_CWORD in
251 compreply="compscript site $site_subcmds"
254 local site=$curr_word; site=${site/#'~/'/$HOME/}
255 compreply=`cred list-sites "$site"`
258 local subcmd=${COMP_WORDS[1]}
259 local site=${COMP_WORDS[2]}; site=${site/#'~/'/$HOME/}
260 local cword_idx=$COMP_CWORD
261 if [ "$subcmd" = site ]
262 then
263 if [ $COMP_CWORD = 3 ]
264 then
265 compreply="$site_subcmds"
266 else
267 subcmd=${COMP_WORDS[3]}
268 let cword_idx-=1
271 case "$subcmd" in
272 (prop)
273 case $cword_idx in
275 compreply=`cred list-props "$site"`
278 compreply="set edit read del show clip"
280 esac
282 (clip|fill-form)
283 compreply=`cred list-props "$site"`
285 (dump)
286 case $cword_idx in
288 compreply="reveal-secrets mask-secrets hash-secrets"
290 esac
291 esac
293 esac
294 COMPREPLY=($(compgen -W "$compreply" -- "${COMP_WORDS[$COMP_CWORD]}"))
295 return 0
297 complete -F _autocomplete_cred cred
298 # use this in your bash session by eg: eval "$(cred compscript)"
302 warnx 'Use tab-completion!'
303 warnx 'Example: eval "$(cred compscript)"'
304 false
306 esac
308 exit