🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.emacs
Article #9623

Re: cmushell-mode [was: Re: comint (generally) and gdb/comint]

#9623
From: John Robinson
Date: Mon, 26 Feb 1990 05:23
143 lines
7419 bytes
In article <SCOTT.90Feb21103559@grlab.grlab.UUCP>, scott@grlab (Scott Blachowicz) writes:
>  -Could it recognize a "Password:" prompt at the beginning of a line
>   and not echo the chars? or is there a better way to get a
>   super-user shell?

(Another idea about how to supress echoes - cause a signal in emacs
when the tty/pty has switched modes, and hang a function on that to
toggle echoing (or enable non-echoing reading) when the process does
stty -echo.)

In reverse order; here's a function I use to execute one command as
super-user.  Modeled on shell-command (M-!).  This version collects
the password with echoing (if you type slowly :-); it could be
modified to use one of the read-no-echo functions, like the one in the
second lisp bit below.

(defun su-command (password command)
  "Prompt for root password and a command, then do the latter as root."
;;; (don't say "Password: "; it might give you away on a net.)
  (interactive "sMagic cookie: \nsCommand: ")
  (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)"))))
;;; suggested binding (su prompt is #):
;;; (global-set-key "\e#" 'su-command)

Now, for part two, Silver (Andy Gaynor) posted this a while back:
========8<----------------------------------------------------------------
(provide 'shell-filter)

;;Date:         Fri, 15 Dec 89 23:22:36 GMT
;;Reply-To:     gaynor@topaz.rutgers.edu
;;From:         Silver <paul.rutgers.edu!gaynor%RUTGERS.EDU>
;;Subject:      Giving shell filters one last kick...

;; When logging in remotely, you might want to give the command "stty -echo" to
;; suppress the echoing of commands as they're executed.  For tcsh, you may
;; also want to unset editmode and/or filec.  Up to you, though...

;; The regexp is a little convoluted, but I think it covers most of the bases.
(defvar shell-filter-password-prompt "\\<passw\\(or\\)?d[\ \t]*[:>][\ \t]*\\'"
"Regular expression used to determine whether shell output contains a request
for a password.  The successful candidate will match the end of the buffer,
handle whitespace appropriately, and various convolutions of `password'.  The
ambient value of case-fold-search is non-nil during matching.")

(defun read-string-no-echo (&optional prompt)
"Read and return a string without echoing it.  Newline and return characters
terminate input.  If optional PROMPT is non-nil, it is displayed and the cursor
placed in the minibuffer while reading.  \(Warning: view-lossage/recent-keys
can access the last 100 characters typed.\)"
  (interactive)
  (save-window-excursion
    (let ((echo-keystrokes 0)
          (string "")
          char)
      (if prompt
        (progn (select-window (minibuffer-window))
               (set-window-buffer (selected-window)
                                  (get-buffer-create " *Temporary*"))
               (erase-buffer)
               (insert prompt)))
      ;; Grossly inefficient.  BFD.
      (while (not (memq (setq char (read-char)) '(?\r ?\n)))
        (setq string (concat string (char-to-string char))))
      string)))

(defun shell-filter-read-password ()
"Read a password in-line (without display, of course) and return it."
  (read-string-no-echo))

(defun shell-filter-nuke-1    () (delete-char 1))
(defun shell-filter-ding      () (delete-char 1) (ding 'continue))
(defun shell-filter-backspace () (delete-char 1) (delete-char (if (eq ?_
 (preceding-char)) -1 1)))

;; I would have done this by regexp instead of character, but I think that this
;; would be putting more computation and effort than the task warrants.
(defvar shell-filter-specials-alist
  '((?\C-m . shell-filter-nuke-1)
    (?\C-l . shell-filter-nuke-1)
    (?\C-g . shell-filter-ding)
    (?\C-h . shell-filter-backspace))
"Alist of (CHARACTER . ACTION).  When CHARACTER is encountered in shell output,
call ACTION with no parameters.")

(defun shell-filter (process string)
"Output filter for shell-mode buffers.  See shell-filter-specials-alist for
information about special character handling.  See shell-filter-password-prompt
and shell-filter-read-password for information about password handling."
  (save-excursion
    (set-buffer (process-buffer process))
    (goto-char (marker-position (process-mark process)))
    (let ((begin (point))
          (end (progn (insert-before-markers string) (point)))
          (case-fold-search t)
          (specials (concat "^" (mapconcat (function (lambda (el)
                                                       (char-to-string (car
 el))))
                                           shell-filter-specials-alist ""))))
      (goto-char begin)
      ;; Alternatively, things could be based around re-search-foward.  There's
      ;; no need for the added overhead, imho.
      (while (progn (skip-chars-forward specials end) (< (point) end))
        (funcall (cdr (assoc (following-char) shell-filter-specials-alist))))
      ;; It might be more `correct' to match against string instead of the buffer.
      (if (re-search-backward shell-filter-password-prompt begin t)
        (progn (goto-char (match-end 0))
               (process-send-string process (concat (shell-filter-read-password)
 "\n")))))))

;; RU's site-init contains a function named add-hook.  I don't know if it's
;; standard, but its intent is fairly obvious.
(setq shell-mode-hook
      (function (lambda ()
		  ;; Uncomment this if you want shells to die easily.
		  ;; (process-kill-without-query (get-buffer-process (current-buffer)))
		  (set-process-filter (get-buffer-process (current-buffer))
                                          (function shell-filter)))))
========8<----------------------------------------------------------------
/jr, nee John Robinson     Life did not take over the globe by combat,
jr@bbn.com or bbn!jr          but by networking -- Lynn Margulis
Technical Details
Message-ID: <52635@bbn.COM>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!husc6!bbn!jr@bbn.com
References: <YZql0La00htFQ074U2@cs.cmu.edu> <SCOTT.90Feb21103559@grlab.grlab.UUCP>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!cs.utexas.edu!tut.cis.ohio-state.edu!ucbvax!husc6!bbn!jr@bbn.com
From: jr@bbn.com (John Robinson)
Newsgroups: comp.emacs
Subject: Re: cmushell-mode [was: Re: comint (generally) and gdb/comint]
Summary: some random elisp to help shell.el
Message-ID: <52635@bbn.COM>
Date: 26 Feb 90 05:23:45 GMT
References: <YZql0La00htFQ074U2@cs.cmu.edu> <SCOTT.90Feb21103559@grlab.grlab.UUCP>
Sender: news@bbn.COM
Reply-To: jr@bbn.com (John Robinson)
Organization: BBN Systems and Technologies Corporation, Cambridge MA
Lines: 143
In-reply-to: scott@grlab.UUCP (Scott Blachowicz)