Article View: comp.emacs
Article #9623Re: cmushell-mode [was: Re: comint (generally) and gdb/comint]
From: John Robinson
Date: Mon, 26 Feb 1990 05:23
Date: Mon, 26 Feb 1990 05:23
143 lines
7419 bytes
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.comReferences:
<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)