#!/usr/bin/env mksh
# $MirOS: contrib/hosted/tg/code/kwalletcli/kwalletcli_getpin,v 1.23 2016/08/30 17:38:44 tg Exp $
#-
# Copyright © 2009, 2010, 2011, 2016
# mirabilos <m@mirbsd.org>
#
# Provided that these terms and disclaimer and all copyright notices
# are retained or reproduced in an accompanying document, permission
# is granted to deal in this work without restriction, including un‐
# limited rights to use, publicly perform, distribute, sell, modify,
# merge, give away, or sublicence.
#
# This work is provided “AS IS” and WITHOUT WARRANTY of any kind, to
# the utmost extent permitted by applicable law, neither express nor
# implied; without malicious intent or gross negligence. In no event
# may a licensor, author or contributor be held liable for indirect,
# direct, other damage, loss, or other issues arising in any way out
# of dealing in the work, even if advised of the possibility of such
# damage or existence of a defect, except proven that it results out
# of said person’s immediate fault when using the work as intended.
unset LC_ALL LANGUAGE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY \
LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
[[ -z $LC_CTYPE ]] && LC_CTYPE=en_US.UTF-8
export LANG=C LC_CTYPE LC_MESSAGES GPG_TERM GPG_TTY
set -U
quiet=0
nl='
'
function die {
local rv=$1
shift
(( quiet )) || print -u2 -r -- "$@"
exit $rv
}
function checkline {
local res
print -pr -- "$@"
read -p res || die 3 pinentry died
[[ $res = OK@(| *) ]] || die 4 "got '$res' for '$*'"
}
function toutf8 {
local intext="$*" outtext=''
typeset -i i=0 n=${#intext}
typeset -i1 c
typeset -Uui16 -Z5 x
while (( i < n )); do
c=1#${intext:(i++):1}
if (( (c & 0xFF80) == 0xEF80 )); then
(( c &= 0xFF ))
fi
if (( c < 32 || c == 1#% || c == 1#_ )); then
let x=c
outtext=${outtext}%${x#16#}
elif (( c > 0x7E && c < 0xA0 )); then
outtext=${outtext}�
else
outtext=${outtext}${c#1#}
fi
done
print -nr -- "$outtext"
}
function tolat1 {
local intext="$*" outtext=''
typeset -i i=0 n=${#intext}
typeset -i1 c
typeset -Uui16 -Z5 x
while (( i < n )); do
c=1#${intext:(i++):1}
(( c = c < 0x80 ? c : (c & 0xFF80) == 0xEF80 ? c :
c < 0x0100 ? c | 0xEF00 : 0xEFFF ))
outtext=${outtext}${c#1#}
done
print -nr -- "$outtext"
}
function usage {
print -u2 "Usage:\tkwalletcli_getpin [-q] [-b | -m | -p prompt]"
print -u2 "\t[-E | -e errortext] [-N NoBtn] [-t desctext] [-Y YesBtn]"
print -u2 "Returns: 0=ok (pw on stdout), 1=cancel, 2+=error"
exit 2
}
function get_tty {
GPG_TTY=$(tty) || GPG_TTY=
[[ -n $GPG_TTY ]] || die 5 Please set GPG_TTY yourself
}
asktext='Hast Du das Paßwort?'
askprompt='Code:'
askerror=''
askbool=0
btnyes=
btnno=
while getopts 'bEe:hmN:p:qt:Y:' ch; do
case $ch {
(b) askbool=1 ;;
(E) askerror='' ;;
(e) askerror=$OPTARG ;;
(m) askbool=2 ;;
(N) btnno=$OPTARG ;;
(p) askprompt=$OPTARG ;;
(q) quiet=1 ;;
(t) asktext=$OPTARG ;;
(Y) btnyes=$OPTARG ;;
(*) usage ;;
}
done
shift $((OPTIND - 1))
(( $# )) && usage
set -A pe_args
if [[ -n $DISPLAY ]]; then
pe_args[${#pe_args[*]}]=--display
pe_args[${#pe_args[*]}]=$DISPLAY
fi
[[ -n $PINENTRY ]] || PINENTRY=pinentry
if "${PINENTRY%-kwallet}" --version >/dev/null 2>&1; then
"${PINENTRY%-kwallet}" "${pe_args[@]}" |&
subpid=$?
read -p res || die 3 pinentry died
[[ $res = OK@(| *) ]] || die 4 "got '$res' for '$*'"
got_pe=1
trap "kill $subpid; die 6 caught SIGHUP" 1
trap "kill $subpid; die 6 caught SIGINT" 2
trap "kill $subpid; die 6 caught SIGQUIT" 3
trap "kill $subpid; die 6 caught SIGTRAP" 5
trap "kill $subpid; die 6 caught SIGPIPE" 13
trap "kill $subpid; die 6 caught SIGTERM" 15
else
got_pe=0
fi
[[ -z $DISPLAY && -z $GPG_TTY ]] && get_tty
[[ -z $GPG_TERM ]] && GPG_TERM=${TERM:-vt100}
if (( !got_pe )); then
thetext=
sep=
(( askbool )) || if [[ -n $askerror ]]; then
thetext="*ERROR*: $(toutf8 "$askerror")"
sep=$nl$nl
fi
if [[ -n $asktext ]]; then
thetext=$thetext$sep$(toutf8 "$asktext")
sep=$nl$nl
fi
(( askbool )) || if [[ -n $askprompt ]]; then
thetext=$thetext$sep$(toutf8 "$askprompt")
fi
whence -p xmessage >/dev/null || unset DISPLAY
if (( askbool )) && [[ -n $DISPLAY ]]; then
buttons=${btnyes:-OK},${btnno:-Cancel}
(( askbool == 2 )) && buttons=${btnyes:-OK}
LC_ALL=C xmessage -nearmouse -buttons "$buttons" \
-default "${btnyes:-OK}" "$(tolat1 "$thetext")"
rc=$?
(( rc == 101 )) && exit 0
(( rc == 102 )) && exit 1
die 3 xmessage errored out
fi
if (( askbool == 2 )); then
thetext="$thetext$nl${nl}[OK${btnyes:+=$btnyes}] "
elif (( askbool )); then
thetext="$thetext$nl${nl}[Y${btnyes:+=$btnyes}|N${btnno:+=$btnno}] "
elif [[ -n $askprompt ]]; then
thetext="$thetext "
else
thetext=$thetext$nl
fi
trap 'stty echo; exit 1' 1 2 3 13 15
[[ -n $GPG_TTY ]] || get_tty
while :; do
print -nru2 -- "$thetext"
stty -echo
IFS= read -r resp
rc=$?
print -u2
stty echo
if (( rc )); then
exit 3
elif (( askbool == 2 )); then
exit 0
elif (( !askbool )); then
print -nr -- "$resp"
exit 0
fi
[[ $resp = ?(1|-1|[Tt]?([Rr][Uu][Ee])|[Yy]?([Ee][Ss])) ]] && \
exit 0
[[ $resp = @(0|[Ff]?([Aa][Ll][Ss][Ee])|[Nn]?([Oo])) ]] && \
exit 1
print -u2 "Try again: 1/T[rue]/Y[es] vs 0/F[alse]/N[o]"
done 0<>$GPG_TTY 2>&0
fi
[[ -z $GPG_TTY ]] || checkline "OPTION ttyname=$GPG_TTY"
[[ -z $GPG_TERM ]] || checkline "OPTION ttytype=$GPG_TERM"
[[ -z $LC_CTYPE ]] || checkline "OPTION lc-ctype=$LC_CTYPE"
[[ -z $LC_MESSAGES ]] || checkline "OPTION lc-messages=$LC_MESSAGES"
[[ -n $asktext ]] && checkline "SETDESC $(toutf8 "$asktext")"
[[ -n $askprompt ]] && checkline "SETPROMPT $(toutf8 "$askprompt")"
[[ -n $askerror ]] && checkline "SETERROR $(toutf8 "$askerror")"
[[ -n $btnyes ]] && checkline "SETOK $(toutf8 "$btnyes")"
[[ -n $btnno ]] && checkline "SETCANCEL $(toutf8 "$btnno")"
if (( askbool == 2 )); then
print -p MESSAGE
elif (( askbool )); then
print -p CONFIRM
else
print -p GETPIN
fi
read -p res || die 3 pinentry died
if [[ $res = @(D )* ]]; then
pass=${res#D }
read -p res || die 3 pinentry died
else
pass=
fi
if [[ $res = OK@(| *) ]]; then
rv=0
print -nr -- "$pass"
else
rv=1
fi
exec 3>&p; exec 3>&-
exit $rv