Path: utzoo!utgpu!watmath!uunet!crdgw1!rpi!tale
From: tale@pawl.rpi.edu (David C Lawrence)
Newsgroups: gnu.emacs
Subject: Re: Editing a file as super user
Message-ID: <1989Sep22.222554.12242@rpi.edu>
Date: 22 Sep 89 22:25:54 GMT
References:  <45953@bbn.COM>
Organization: Rensselaer Polytechnic Institute, Troy NY
Lines: 61
In-Reply-To: jr@bbn.com's message of 22 Sep 89 15:43:59 GMT

In <45953@bbn.COM> jr@bbn.com (John Robinson) writes:
jr> (anticipating the nits: yes, I know the password echos as you type it.
jr> However, putting the two arguments in the order they are at least
jr> overwrites the minibuffer as soon as you finish the password.  Anyone
jr> who wants to add the get-a-string-sliently logic to the following is
jr> welcome to do it and repost).

Here you go; simple blanking.

;; From jr@bbn.com Fri Sep 22 18:15:02 1989
;; added blanking passwd, Sep 22 18:20 -- tale

;;; suggested binding (# is the prompt when superuser):
;;; (global-set-key "\e#" 'su-command)

(defun su-command (password command)
  "Prompt for root password and a command, then do the latter as root."
  (interactive (list (read-passwd "root password: ")
                     (read-string "shell command: ")))
  (let ((buffer (get-buffer-create "*Shell Command Output*"))
        proc)
    (save-excursion
          (set-buffer buffer)
          (erase-buffer))
    (setq proc (start-process "su-emacs" buffer "/bin/su" "-c" command))
    (if (save-excursion
          (set-buffer buffer)
          (goto-char (point-min))
          (while (not (looking-at "Password:"))
            (accept-process-output proc)
            (goto-char (point-min)))
          (erase-buffer)
          (send-string proc (concat password "\n"))
          (while (not (looking-at "\n"))
            (accept-process-output proc)
            (goto-char (point-min)))
          (delete-char 1)
          (while (not (equal (process-status proc) 'exit))
            (accept-process-output))
          (> (buffer-size) 0))
        (set-window-start (display-buffer buffer) 1)
      (message "(Command completed with no output)"))))

(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.
  ;; also didn't bother moving the cursor to the minibuffer
  (let ((passwd "") (echo-keystrokes 0) 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))