From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 18570 invoked by alias); 2 Feb 2011 04:35:12 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 15759 Received: (qmail 1493 invoked from network); 2 Feb 2011 04:35:10 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-1.9 required=5.0 tests=BAYES_00,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received-SPF: none (ns1.primenet.com.au: domain at closedmail.com does not designate permitted sender hosts) From: Bart Schaefer Message-id: <110201203449.ZM18939@torch.brasslantern.com> Date: Tue, 01 Feb 2011 20:34:49 -0800 In-reply-to: Comments: In reply to Julien Nicoulaud "Commands with passwords as options" (Feb 1, 10:15pm) References: X-Mailer: OpenZMail Classic (0.9.2 24April2005) To: zsh-users Subject: Re: Commands with passwords as options MIME-version: 1.0 Content-type: text/plain; charset=us-ascii On Feb 1, 10:15pm, Julien Nicoulaud wrote: } } Some commands take passwords as option values, which is not very } secure... I was wondering if there is some way to handle that, for } example through a custom completer. I don't know about a custom completer -- it's pretty difficult to have the completion system go off and do something interactive in the middle, at least not without the display ending up hopelessly muddled afterward -- but it should be possible to implement it as a widget. send-invisible() { emulate -L zsh # Shamelessly cribbed from read-from-minibuffer. # send-invisible reads a line from the terminal, displaying an # asterisk for each character typed. It stores the line in the # global variable INVISIBLE, and when finished reading, inserts # the string ${INVISIBLE} into the original command buffer. # If one argument is given, it is the prompt. The default is # "Non-echoed text: " # If two or three arguments are given, they form the prefix and # suffix of the inserted INVISIBLE. Defaults are '${' and '}' # but these can be replaced, for example with '"${' and '}"' to # enclose the whole word in double quotes, or '${(z)' and '}' to # split the value of $INVISIBLE like the shell parser. # Hide the value of INVISIBLE in any output of set and typeset typeset -g -H INVISIBLE= local pretext="$PREDISPLAY$LBUFFER$RBUFFER$POSTDISPLAY"$'\n' # Can't directly make these locals because send-invisible is # called as a widget, so these special variables are already # local at the current level and wouldn't get restored local save_lbuffer=$LBUFFER local save_rbuffer=$RBUFFER local save_predisplay=$PREDISPLAY local save_postdisplay=$POSTDISPLAY local -a save_region_highlight save_region_highlight=("${region_highlight[@]}") { local lb rb opn=${2:-'${'} cls=${3:-'}'} LBUFFER= RBUFFER= PREDISPLAY="$pretext${1:-Non-echoed text: }" POSTDISPLAY= region_highlight=("P${(m)#pretext} ${(m)#PREDISPLAY} bold") while zle -R && zle .read-command do # There are probably more commands that should go into # the first clause here to harmlessly beep, because ... case $REPLY in (send-invisible|run-help|undefined-key|where-is|which-command) zle .beep;; (push-*|send-break) INVISIBLE=;& (accept-*) break;; (*) LBUFFER=$lb RBUFFER=$rb zle $REPLY # ... this could expose something lb=$LBUFFER rb=$RBUFFER INVISIBLE=$BUFFER LBUFFER=${(l:$#LBUFFER::*:):-} RBUFFER=${(l:$#RBUFFER::*:):-} ;; esac done } always { LBUFFER=$save_lbuffer RBUFFER=$save_rbuffer PREDISPLAY=$save_predisplay POSTDISPLAY=$save_postdisplay region_highlight=("${save_region_highlight[@]}") zle -R # Now that the highlight has been restored with all the old # text and cursor positioning, insert the new text. LBUFFER+=${INVISIBLE:+${opn}INVISIBLE${cls}} } } zle -N send-invisible } Ideally, I here is how it should behave: } - When reaching an option which expected value is a password, prompt for it } and read it from stdin If you can figure out how to auto-invoke the above in these circumstances, go for it. Possibly something in zle-line-init that examines the word at the end of $LBUFFER. } - Do not display it in the buffer (just replace it with "XXXX" for example) } - When accepting the buffer, replace the displayed buffer with the real one } - Save the displayed buffer in the history rather than the real one I think the above covers all of this.