From c0ada759210b090944e0a23ed4879ca1a3ad38a7 Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Fri, 11 Jul 2014 11:09:54 +0200 Subject: [PATCH] Hide password in batch mode * doc/lispref/minibuf.texi (Intro to Minibuffers, Reading a Password): Password hiding is available in batch mode, do not mention it in the exclusion list. Mention `read-hide-char'. * lisp/subr.el (read-passwd): Use `read-hide-char' if non-nil. Bind it when calling `read-string'. * src/minibuf.c (top): Include systty.h. Declare external emacs_get_tty and emacs_set_tty. (Vread_hide_char): New lisp variable. (read_minibuf_noninteractive): Hide characters with Vread_hide_char if it is a character. * src/sysdep.c (emacs_get_tty, emacs_set_tty): Make them externally visible. Fixes: debbugs:17839 --- doc/lispref/ChangeLog | 6 ++++++ doc/lispref/minibuf.texi | 11 ++++++----- lisp/ChangeLog | 5 +++++ lisp/subr.el | 13 +++++-------- src/ChangeLog | 10 ++++++++++ src/minibuf.c | 35 +++++++++++++++++++++++++++++++++++ src/sysdep.c | 8 ++++---- 7 files changed, 71 insertions(+), 17 deletions(-) diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog index c15bbebbe59..17af128ae49 100644 --- a/doc/lispref/ChangeLog +++ b/doc/lispref/ChangeLog @@ -1,3 +1,9 @@ +2014-07-11 Michael Albinus + + * minibuf.texi (Intro to Minibuffers, Reading a Password): + Password hiding is available in batch mode, do not mention it in + the exclusion list. Mention `read-hide-char'. (Bug#17839) + 2014-07-09 Stefan Monnier * debugging.texi (Function Debugging, Debugger Commands): diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi index e76b827cd2f..1c6a74a89fd 100644 --- a/doc/lispref/minibuf.texi +++ b/doc/lispref/minibuf.texi @@ -102,8 +102,8 @@ the minibuffer is in a separate frame. @xref{Minibuffers and Frames}. When Emacs is running in batch mode, any request to read from the minibuffer actually reads a line from the standard input descriptor that was supplied when Emacs was started. This supports only basic input: -none of the special minibuffer features (history, completion, -password hiding, etc.) are available in batch mode. +none of the special minibuffer features (history, completion, etc.) +are available in batch mode. @node Text from Minibuffer @section Reading Text Strings with the Minibuffer @@ -2147,9 +2147,10 @@ function @code{read-passwd}. @defun read-passwd prompt &optional confirm default This function reads a password, prompting with @var{prompt}. It does -not echo the password as the user types it; instead, it echoes @samp{.} -for each character in the password. (Note that in batch mode, the -input is not hidden.) +not echo the password as the user types it; instead, it echoes +@samp{.} for each character in the password. If you want to apply +another character to hide the password, let-bind the variable +@code{read-hide-char} with that character. The optional argument @var{confirm}, if non-@code{nil}, says to read the password twice and insist it must be the same both times. If it isn't diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 4e19be4d3ea..3965da7287b 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,8 @@ +2014-07-11 Michael Albinus + + * subr.el (read-passwd): Use `read-hide-char' if non-nil. Bind it + when calling `read-string'. (Bug#17839) + 2014-07-10 Eli Zaretskii * files.el (warn-maybe-out-of-memory): Fix the wording of the diff --git a/lisp/subr.el b/lisp/subr.el index a0c56bf9752..9accb9d36c5 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -2016,7 +2016,7 @@ If optional CONFIRM is non-nil, read the password twice to make sure. Optional DEFAULT is a default password to use instead of empty input. This function echoes `.' for each character that the user types. -Note that in batch mode, the input is not hidden! +You could let-bind `read-hide-char' to another hiding character, though. Once the caller uses the password, it can erase the password by doing (clear-string STRING)." @@ -2041,7 +2041,7 @@ by doing (clear-string STRING)." beg))) (dotimes (i (- end beg)) (put-text-property (+ i beg) (+ 1 i beg) - 'display (string ?.))))) + 'display (string (or read-hide-char ?.)))))) minibuf) (minibuffer-with-setup-hook (lambda () @@ -2055,12 +2055,9 @@ by doing (clear-string STRING)." (setq-local show-paren-mode nil) ;bug#16091. (add-hook 'after-change-functions hide-chars-fun nil 'local)) (unwind-protect - (let ((enable-recursive-minibuffers t)) - (read-string - (if noninteractive - (format "%s[INPUT WILL NOT BE HIDDEN!] " prompt) ; bug#17839 - prompt) - nil t default)) ; t = "no history" + (let ((enable-recursive-minibuffers t) + (read-hide-char (or read-hide-char ?.))) + (read-string prompt nil t default)) ; t = "no history" (when (buffer-live-p minibuf) (with-current-buffer minibuf ;; Not sure why but it seems that there might be cases where the diff --git a/src/ChangeLog b/src/ChangeLog index 93ad0ded350..e2a7bb8a0f0 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,13 @@ +2014-07-11 Michael Albinus + + * sysdep.c (emacs_get_tty, emacs_set_tty): Make them externally visible. + + * minibuf.c (top): Include systty.h. Declare external + emacs_get_tty and emacs_set_tty. + (Vread_hide_char): New lisp variable. + (read_minibuf_noninteractive): Hide characters with + Vread_hide_char if it is a character. (Bug#17839) + 2014-07-10 Eli Zaretskii Implement memory-info for MS-Windows. diff --git a/src/minibuf.c b/src/minibuf.c index 3042b13b7d6..122f77fff96 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -35,6 +35,10 @@ along with GNU Emacs. If not, see . */ #include "keymap.h" #include "termhooks.h" +#include "systty.h" +extern void emacs_get_tty (int, struct emacs_tty *); +extern int emacs_set_tty (int, struct emacs_tty *, bool); + /* List of buffers for use as minibuffers. The first element of the list is used for the outermost minibuffer invocation, the next element is used for a recursive minibuffer @@ -224,6 +228,22 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, char *line; Lisp_Object val; int c; + unsigned char hide_char = 0; + struct emacs_tty old, new; + + /* Check, whether we need to suppress echoing. */ + if (CHARACTERP (Vread_hide_char)) + hide_char = XFASTINT (Vread_hide_char); + + /* Manipulate tty. */ + if (hide_char) + { + emacs_get_tty (fileno (stdin), &old); + new = old; + new.main.c_lflag &= ~ICANON; /* Disable buffering */ + new.main.c_lflag &= ~ECHO; /* Disable echoing */ + emacs_set_tty (fileno (stdin), &new, 0); + } fprintf (stdout, "%s", SDATA (prompt)); fflush (stdout); @@ -242,6 +262,8 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, } else { + if (hide_char) + fprintf (stdout, "%c", hide_char); if (len == size) { if (STRING_BYTES_BOUND / 2 < size) @@ -253,6 +275,13 @@ read_minibuf_noninteractive (Lisp_Object map, Lisp_Object initial, } } + /* Reset tty. */ + if (hide_char) + { + fprintf (stdout, "\n"); + emacs_set_tty (fileno (stdin), &old, 0); + } + if (len || c == '\n') { val = make_string (line, len); @@ -2079,6 +2108,12 @@ properties. */); initialization-order problems. */ Vminibuffer_prompt_properties = list2 (intern_c_string ("read-only"), Qt); + DEFVAR_LISP ("read-hide-char", Vread_hide_char, + doc: /* Whether to hide input characters in noninteractive mode. +It must be a character, which will be used to mask the input +characters. This variable should never be set globally. */); + Vread_hide_char = Qnil; + defsubr (&Sactive_minibuffer_window); defsubr (&Sset_minibuffer_window); defsubr (&Sread_from_minibuffer); diff --git a/src/sysdep.c b/src/sysdep.c index 211a3bb706f..14d9f43c4db 100644 --- a/src/sysdep.c +++ b/src/sysdep.c @@ -105,8 +105,8 @@ int _cdecl _getpid (void); #include "syssignal.h" #include "systime.h" -static void emacs_get_tty (int, struct emacs_tty *); -static int emacs_set_tty (int, struct emacs_tty *, bool); +void emacs_get_tty (int, struct emacs_tty *) EXTERNALLY_VISIBLE; +int emacs_set_tty (int, struct emacs_tty *, bool) EXTERNALLY_VISIBLE; /* ULLONG_MAX is missing on Red Hat Linux 7.3; see Bug#11781. */ #ifndef ULLONG_MAX @@ -779,7 +779,7 @@ widen_foreground_group (int fd) /* Set *TC to the parameters associated with the terminal FD, or clear it if the parameters are not available. */ -static void +void emacs_get_tty (int fd, struct emacs_tty *settings) { /* Retrieve the primary parameters - baud rate, character size, etcetera. */ @@ -795,7 +795,7 @@ emacs_get_tty (int fd, struct emacs_tty *settings) *SETTINGS. If FLUSHP, discard input. Return 0 if all went well, and -1 (setting errno) if anything failed. */ -static int +int emacs_set_tty (int fd, struct emacs_tty *settings, bool flushp) { /* Set the primary parameters - baud rate, character size, etcetera. */ -- 2.39.2