[gnu.emacs] Getting Emacs to not echo characters

pete@milton.acs.washington.edu (Pete Pulliam) (11/26/89)

I am writing a short emacs lisp program which, at one point, requires a
password to be typed.  I don't want this password to be displayed on
the screen, but am having difficulty turning echoing off in emacs.  
Any info on how to do this would be appreciated.

Please send replies by e-mail to one of the following:
	pete@milton.u.washington.edu
	pete@blake.acs.washington.edu
	pete@128.95.152.1

Thanks in advance

-----------------------------------------------------------------------------
Pete Pulliam
Student, Staff, dreaming of Faculty.   University of Washington

deven@rpi.edu (Deven T. Corzine) (11/27/89)

On 26 Nov 89 04:07:20 GMT,
pete@milton.acs.washington.edu (Pete Pulliam) said:

Pete> I am writing a short emacs lisp program which, at one point,
Pete> requires a password to be typed.  I don't want this password to
Pete> be displayed on the screen, but am having difficulty turning
Pete> echoing off in emacs.  Any info on how to do this would be
Pete> appreciated.

Since this may be of general usefulness, I am posting this as well as
Email to the original poster.  [credit due to tale@rpi.edu for
function, I modified to select minibuffer window when prompting for a
password.]

(defun read-passwd (&optional prompt)
  "Allow user to type a string without it showing.  Returns string.
If optional PROMPT non-nil, use it as the prompt string in the mini-buffer.
Not meant to be called by the user explicitly."
  (let ((passwd "") (echo-keystrokes 0) char (win (selected-window)))
    (if prompt
        (progn
          (select-window (minibuffer-window))
          (message prompt)))
    (while (not (or (= (setq char (read-char)) 13) (= char 10)))
      (if (or (= char 8) (= char 127))
          (if (> (length passwd) 0)
              (setq passwd (substring passwd 0 (1- (length passwd)))))
        (setq passwd (concat passwd (char-to-string char))))
      (if prompt (message (concat prompt (make-string (length passwd) ?*)))))
    (if prompt (progn
                 (select-window win)
                 (message "")))
    passwd))

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2151 12th St. Apt. 4, Troy, NY 12180   Phone:  (518) 274-0327
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.

tale@pawl.rpi.edu (David C Lawrence) (11/27/89)

In <DEVEN.89Nov26160956@netserv2.rpi.edu> deven@rpi.edu (Deven T. Corzine):
Deven> Since this may be of general usefulness, I am posting this as well as
Deven> Email to the original poster.  [credit due to tale@rpi.edu for
Deven> function, I modified to select minibuffer window when prompting for a
Deven> password.]

I wish you had asked me about this first; when you informed me of your
idea a couple of months ago, I did it "the right way", because your
modifications did not work for putting the cursor in the minibuffer
when I incorporated it verbatim into another package.  Pete already
had the correct function last night, but now, for the sake of everyone else:

(defun read-passwd (&optional prompt)
  "Allow user to type a string without it showing.  Returns string.
If optional PROMPT non-nil, use it as the prompt string in the minibuffer." 
  ;; this is based on a similar function in telnet.el
  ;; the major drawback is that while being prompted for a password
  ;; it stays in this routine until C-g, RET or LFD is typed.
  (let ((passwd "") (echo-keystrokes 0) (cursor-in-echo-area t) char)
    (if prompt (message prompt))
    (while (not (or (= (setq char (read-char)) 13) (= char 10)))
      ;; naughty bit.  take C-h to mean DEL.
      (if (or (= char 8) (= char 127))
          (if (> (length passwd) 0)
              (setq passwd (substring passwd 0 (1- (length passwd)))))
        (setq passwd (concat passwd (char-to-string char))))
      (if prompt (message (concat prompt (make-string (length passwd) ?*)))))
    (if prompt (message ""))
    passwd))

trost@reed.bitnet (Bill Trost) (11/28/89)

That reminds me of something --- a while ago I wrote a bit of lisp to
let me type passwords at su and the like.  Thing is, I don't remember
if I posted it.  Did I, and if I didn't should I?

Reply to trost%reed@tektronix.tek.com.
--
--

hollen@eta.megatek.uucp (Dion Hollenbeck) (12/07/89)

On 26 Nov 89 04:07:20 GMT,
pete@milton.acs.washington.edu (Pete Pulliam) said:
 
Pete> I am writing a short emacs lisp program which, at one point,
Pete> requires a password to be typed.  I don't want this password to
Pete> be displayed on the screen, but am having difficulty turning
Pete> echoing off in emacs.  Any info on how to do this would be
Pete> appreciated.

Deven T. Corzine thoughtfully posted a solution to this, but it
does not quite fit my problem.  When I am typing in a password,
I am in an Emacs shell and are doing a "rlogin" to another host
which is asking for my password.  Maybe somehow turning off
echoing in this shell would work.

The other problem I am having is also in the shell, after I
have completed the remote login.  Emacs echoes everything to
the screen in addition to the remote host echoing it and every
line is followed my ^M.  Is there a mode or process-filter
which I can apply to get rid of this behaviour?



	Dion Hollenbeck             (619) 455-5590 x2814
	Megatek Corporation, 9645 Scranton Road, San Diego, CA  92121

        uunet!megatek!hollen       or  hollen@megatek.uucp

tale@cs.rpi.edu (Dave Lawrence) (12/08/89)

In article <842@megatek.UUCP> hollen@eta.megatek.uucp (Dion Hollenbeck) writes:

   Deven T. Corzine thoughtfully posted a solution to this, but it
   does not quite fit my problem.  When I am typing in a password,
   I am in an Emacs shell and are doing a "rlogin" to another host
   which is asking for my password.  Maybe somehow turning off
   echoing in this shell would work.

The following is from comint.el, a package by Olin Shivers
<olin.shivers@cs.cmu.edu>:

;;; These two functions are for entering text you don't want echoed or
;;; saved -- typically passwords to ftp, telnet, or somesuch.
;;; Just enter M-x send-invisible and type in your line.

(defun comint-read-noecho (prompt)
  "Prompt the user with argument PROMPT. Read a single line of text
without echoing, and return it. Note that the keystrokes comprising
the text can still be recovered (temporarily) with \\[view-lossage]. This
may be a security bug for some applications."
  (let ((echo-keystrokes 0)
	(answ "")
	tem)
    (if (and (stringp prompt) (not (string= (message prompt) "")))
	(message prompt))
    (while (not(or  (= (setq tem (read-char)) ?\^m)
		    (= tem ?\n)))
      (setq answ (concat answ (char-to-string tem))))
    (message "")
    answ))

(defun send-invisible (str)
  "Read a string without echoing, and send it to the process running
in the current buffer. A new-line is additionally sent. String is not 
saved on comint input history list.
Security bug: your string can still be temporarily recovered with
\\[view-lossage]."
; (interactive (list (comint-read-noecho "Enter non-echoed text")))
  (interactive "P") ; Defeat snooping via C-x esc
  (let ((proc (get-buffer-process (current-buffer))))
    (if (not proc) (error "Current buffer has no process")
	(process-send-string proc
			     (if (stringp str) str
				 (comint-read-noecho "Enter non-echoed text")))
	(process-send-string proc "\n"))))

   The other problem I am having is also in the shell, after I
   have completed the remote login.  Emacs echoes everything to
   the screen in addition to the remote host echoing it and every
   line is followed my ^M.  Is there a mode or process-filter
   which I can apply to get rid of this behaviour?

This sounds like telnet doing this.  If you were to use telnet.el it
probably wouldn't have the problem, since it deletes the input and
removes the the filter blasts C-m characters at the end of lines.
shell-mode as currently distributed does no such trimming.  This
problem is also apparent when using a shell like tcsh which echos
characters back and outputs RET LFD pairs.  I think BASH tests whether
it is running within Emacs, by checking for the EMACS environment
variable, to avoid such echoing.

Dave
-- 
   (setq mail '("tale@cs.rpi.edu" "tale@ai.mit.edu" "tale@rpitsmts.bitnet"))

worley@EDDIE.MIT.EDU (Dale Worley) (12/08/89)

    The other problem I am having is also in the shell, after I
    have completed the remote login.  Emacs echoes everything to
    the screen in addition to the remote host echoing it and every
    line is followed my ^M.  Is there a mode or process-filter
    which I can apply to get rid of this behaviour?

Use "stty -echo nl" in the remote shell.  The problem is that the
remote system is echoing your input, which is rediculous since it is
after-the-fact; and it is emitting RET LFD for end-of-line, which is
standard for talking to terminals, but nonstandard for communication
between Unix entities.

Dale Worley		Compass, Inc.			worley@compass.com
--
Fax: Originally a last resort for procrastinators who missed the final
Federal Express pickup; these days, an expensive way to order lunch
from the pizza place around the corner.

deven@rpi.edu (Deven T. Corzine) (12/09/89)

On 6 Dec 89 18:28:21 GMT, hollen@eta.megatek.uucp (Dion Hollenbeck) said:

Dion> Deven T. Corzine thoughtfully posted a solution to this, but it
Dion> does not quite fit my problem.  When I am typing in a password,
Dion> I am in an Emacs shell and are doing a "rlogin" to another host
Dion> which is asking for my password.  Maybe somehow turning off
Dion> echoing in this shell would work.

Dion> The other problem I am having is also in the shell, after I have
Dion> completed the remote login.  Emacs echoes everything to the
Dion> screen in addition to the remote host echoing it and every line
Dion> is followed my ^M.  Is there a mode or process-filter which I
Dion> can apply to get rid of this behaviour?

The same things were bothering me, so I wrote a simple fix for them.

The following is from my .emacs:

--------
(defun shell-filter (proc str)
  "Output filter for shell-mode buffers."
  (save-excursion
    (set-buffer (process-buffer proc))
    (goto-char (process-mark proc))
    (let ((start (point))
          end)
      (insert-before-markers str)
      (setq end (point))
      (goto-char start)
      (while (or (looking-at "^\r\\|\r$")
                 (re-search-forward "^\r\\|\r$" end t))
        (replace-match ""))
      (goto-char start)
      (while (or (looking-at "\C-g")
                 (re-search-forward "\C-g" end t))
        (replace-match "")
        (ding 'noterminate)))))

(defun shell-save-history ()
  "Hook for shell-mode to delete the input from the buffer after sending
it.  (so double-echo is avoided)"
  (delete-region last-input-start last-input-end))

(setq shell-mode-hook
      '(lambda ()
         (set-process-filter (get-buffer-process (current-buffer))
                             'shell-filter))
      shell-read-history nil)

--------

The filter removes ^M's from the beginning or end of a line, and
removes any ^G's, dinging in their place.  The shell-save-history
function (is it called by the standard shell.el distribution?  hmm.)
does retroactive un-echoing.  it deletes the input, which is normally
then echoed by the shell or remote host.  In the case of password
prompting, it is not re-echoed.  So, the password shows while you type
it, but not after.  Not ideal, but an acceptable compromise for me.
(just put your hand over the screen or something.  :-)

Deven
-- 
Deven T. Corzine        Internet:  deven@rpi.edu, shadow@pawl.rpi.edu
Snail:  2151 12th St. Apt. 4, Troy, NY 12180   Phone:  (518) 274-0327
Bitnet:  deven@rpitsmts, userfxb6@rpitsmts     UUCP:  uunet!rpi!deven
Simple things should be simple and complex things should be possible.