(replace_buffer_in_all_windows):
[bpt/emacs.git] / lisp / rlogin.el
CommitLineData
76550a57
ER
1;;; rlogin.el --- remote login interface
2
13709db5 3;; Copyright (C) 1992, 1993, 1994, 1995, 1997 Free Software Foundation, Inc.
b578f267 4
8ae3bc9f 5;; Author: Noah Friedman
76550a57 6;; Maintainer: Noah Friedman <friedman@prep.ai.mit.edu>
5d1dd3c0 7;; Keywords: unix, comm
76550a57 8
140835c2
NF
9;; $Id: rlogin.el,v 1.39 1997/05/05 01:00:35 rms Exp $
10
b578f267
EN
11;; This file is part of GNU Emacs.
12
13;; GNU Emacs is free software; you can redistribute it and/or modify
d9ecc911
ER
14;; it under the terms of the GNU General Public License as published by
15;; the Free Software Foundation; either version 2, or (at your option)
16;; any later version.
b578f267
EN
17
18;; GNU Emacs is distributed in the hope that it will be useful,
d9ecc911
ER
19;; but WITHOUT ANY WARRANTY; without even the implied warranty of
20;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21;; GNU General Public License for more details.
b578f267 22
d9ecc911 23;; You should have received a copy of the GNU General Public License
b578f267
EN
24;; along with GNU Emacs; see the file COPYING. If not, write to the
25;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
26;; Boston, MA 02111-1307, USA.
d9ecc911
ER
27
28;;; Commentary:
29
0b899bd2 30;; Support for remote logins using `rlogin'.
32992017
NF
31;; This program is layered on top of shell.el; the code here only accounts
32;; for the variations needed to handle a remote process, e.g. directory
33;; tracking and the sending of some special characters.
97b83d9d 34
d933a756
NF
35;; If you wish for rlogin mode to prompt you in the minibuffer for
36;; passwords when a password prompt appears, just enter m-x send-invisible
37;; and type in your line, or add `comint-watch-for-password-prompt' to
38;; `comint-output-filter-functions'.
c7986c18 39
76550a57
ER
40;;; Code:
41
c7986c18 42(require 'comint)
10939dc6 43(require 'shell)
c7986c18 44
c4cfc3dc
RS
45(defgroup rlogin nil
46 "Remote login interface"
47 :group 'processes
48 :group 'unix)
c7986c18 49
8d30fe17 50
c4cfc3dc
RS
51(defcustom rlogin-program "rlogin"
52 "*Name of program to invoke rlogin"
53 :type 'string
54 :group 'rlogin)
c7986c18 55
c4cfc3dc
RS
56(defcustom rlogin-explicit-args nil
57 "*List of arguments to pass to rlogin on the command line."
58 :type '(repeat (string :tag "Argument"))
59 :group 'rlogin)
60
61(defcustom rlogin-mode-hook nil
62 "*Hooks to run after setting current buffer to rlogin-mode."
63 :type 'hook
64 :group 'rlogin)
65
4cab4c5b
NF
66(defcustom rlogin-process-connection-type
67 (save-match-data
68 ;; Solaris 2.x `rlogin' will spew a bunch of ioctl error messages if
69 ;; stdin isn't a tty.
70 (cond ((and (boundp 'system-configuration)
71 (stringp system-configuration)
72 (string-match "-solaris2" system-configuration))
73 t)
74 (t nil)))
2601d12e
NF
75 "*If non-`nil', use a pty for the local rlogin process.
76If `nil', use a pipe (if pipes are supported on the local system).
8d30fe17 77
8ae3bc9f
NF
78Generally it is better not to waste ptys on systems which have a static
79number of them. On the other hand, some implementations of `rlogin' assume
c4cfc3dc
RS
80a pty is being used, and errors will result from using a pipe instead."
81 :type '(choice (const :tag "ptys" t)
82 (const :tag "pipes" nil))
83 :group 'rlogin)
8d30fe17 84
c4cfc3dc 85(defcustom rlogin-directory-tracking-mode 'local
ce992678 86 "*Control whether and how to do directory tracking in an rlogin buffer.
32992017 87
ce992678 88nil means don't do directory tracking.
32992017 89
ce992678 90t means do so using an ftp remote file name.
32992017 91
ce992678
RS
92Any other value means do directory tracking using local file names.
93This works only if the remote machine and the local one
32992017
NF
94share the same directories (through NFS). This is the default.
95
96This variable becomes local to a buffer when set in any fashion for it.
97
98It is better to use the function of the same name to change the behavior of
99directory tracking in an rlogin session once it has begun, rather than
100simply setting this variable, since the function does the necessary
c4cfc3dc
RS
101re-synching of directories."
102 :type '(choice (const :tag "off" nil)
103 (const :tag "ftp" t)
104 (const :tag "local" local))
105 :group 'rlogin)
32992017
NF
106
107(make-variable-buffer-local 'rlogin-directory-tracking-mode)
108
c4cfc3dc
RS
109(defcustom rlogin-host nil
110 "*The name of the remote host. This variable is buffer-local."
111 :type '(choice (const nil) string)
112 :group 'rlogin)
32992017 113
c4cfc3dc 114(defcustom rlogin-remote-user nil
32992017
NF
115 "*The username used on the remote host.
116This variable is buffer-local and defaults to your local user name.
117If rlogin is invoked with the `-l' option to specify the remote username,
c4cfc3dc
RS
118this variable is set from that."
119 :type '(choice (const nil) string)
120 :group 'rlogin)
97b83d9d 121
c7986c18
ER
122;; Initialize rlogin mode map.
123(defvar rlogin-mode-map '())
2601d12e 124(cond
32992017
NF
125 ((null rlogin-mode-map)
126 (setq rlogin-mode-map (if (consp shell-mode-map)
127 (cons 'keymap shell-mode-map)
128 (copy-keymap shell-mode-map)))
129 (define-key rlogin-mode-map "\C-c\C-c" 'rlogin-send-Ctrl-C)
130 (define-key rlogin-mode-map "\C-c\C-d" 'rlogin-send-Ctrl-D)
131 (define-key rlogin-mode-map "\C-c\C-z" 'rlogin-send-Ctrl-Z)
132 (define-key rlogin-mode-map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash)
133 (define-key rlogin-mode-map "\C-d" 'rlogin-delchar-or-send-Ctrl-D)
134 (define-key rlogin-mode-map "\C-i" 'rlogin-tab-or-complete)))
c7986c18 135
32992017 136\f
67398f34
RS
137;;;###autoload (add-hook 'same-window-regexps "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)")
138
cd17ae3f
RM
139(defvar rlogin-history nil)
140
0b899bd2 141;;;###autoload
965f7ac9 142(defun rlogin (input-args &optional buffer)
4131662f
RS
143 "Open a network login connection via `rlogin' with args INPUT-ARGS.
144INPUT-ARGS should start with a host name; it may also contain
145other arguments for `rlogin'.
146
8d30fe17
NF
147Input is sent line-at-a-time to the remote connection.
148
67398f34
RS
149Communication with the remote host is recorded in a buffer `*rlogin-HOST*'
150\(or `*rlogin-USER@HOST*' if the remote username differs\).
151If a prefix argument is given and the buffer `*rlogin-HOST*' already exists,
32992017 152a new buffer with a different connection will be made.
8d30fe17 153
4131662f
RS
154When called from a program, if the optional second argument BUFFER is
155a string or buffer, it specifies the buffer to use.
965f7ac9 156
8d30fe17 157The variable `rlogin-program' contains the name of the actual program to
2601d12e 158run. It can be a relative or absolute path.
8d30fe17
NF
159
160The variable `rlogin-explicit-args' is a list of arguments to give to
ce992678
RS
161the rlogin when starting. They are added after any arguments given in
162INPUT-ARGS.
b79164c7 163
32992017
NF
164If the default value of `rlogin-directory-tracking-mode' is t, then the
165default directory in that buffer is set to a remote (FTP) file name to
166access your home directory on the remote machine. Occasionally this causes
167an error, if you cannot access the home directory on that machine. This
168error is harmless as long as you don't try to use that default directory.
ce992678 169
32992017 170If `rlogin-directory-tracking-mode' is neither t nor nil, then the default
ce992678
RS
171directory is initially set up to your (local) home directory.
172This is useful if the remote machine and your local machine
32992017
NF
173share the same files via NFS. This is the default.
174
175If you wish to change directory tracking styles during a session, use the
176function `rlogin-directory-tracking-mode' rather than simply setting the
177variable."
5236f937 178 (interactive (list
cd17ae3f
RM
179 (read-from-minibuffer "rlogin arguments (hostname first): "
180 nil nil nil 'rlogin-history)
5236f937 181 current-prefix-arg))
32992017 182
8ae3bc9f 183 (let* ((process-connection-type rlogin-process-connection-type)
32992017
NF
184 (args (if rlogin-explicit-args
185 (append (rlogin-parse-words input-args)
186 rlogin-explicit-args)
187 (rlogin-parse-words input-args)))
188 (host (car args))
189 (user (or (car (cdr (member "-l" args)))
190 (user-login-name)))
191 (buffer-name (if (string= user (user-login-name))
192 (format "*rlogin-%s*" host)
193 (format "*rlogin-%s@%s*" user host)))
194 proc)
195
965f7ac9 196 (cond ((null buffer))
e48e5617 197 ((stringp buffer)
965f7ac9 198 (setq buffer-name buffer))
e48e5617
NF
199 ((bufferp buffer)
200 (setq buffer-name (buffer-name buffer)))
965f7ac9
RM
201 ((numberp buffer)
202 (setq buffer-name (format "%s<%d>" buffer-name buffer)))
e1f06ce8
NF
203 (t
204 (setq buffer-name (generate-new-buffer-name buffer-name))))
205
e48e5617 206 (setq buffer (get-buffer-create buffer-name))
e1f06ce8 207 (pop-to-buffer buffer-name)
e48e5617 208
32992017 209 (cond
e1f06ce8 210 ((comint-check-proc buffer-name))
32992017 211 (t
e48e5617
NF
212 (comint-exec buffer buffer-name rlogin-program nil args)
213 (setq proc (get-buffer-process buffer))
32992017
NF
214 ;; Set process-mark to point-max in case there is text in the
215 ;; buffer from a previous exited process.
216 (set-marker (process-mark proc) (point-max))
2601d12e 217
32992017
NF
218 ;; comint-output-filter-functions is just like a hook, except that the
219 ;; functions in that list are passed arguments. add-hook serves well
220 ;; enough for modifying it.
fb7741f5
NF
221 ;; comint-output-filter-functions should already have a
222 ;; permanent-local property, at least in emacs 19.27 or later.
223 (if (fboundp 'make-local-hook)
224 (make-local-hook 'comint-output-filter-functions)
225 (make-local-variable 'comint-output-filter-functions))
7e939f29 226 (add-hook 'comint-output-filter-functions 'rlogin-carriage-filter)
32992017 227
9fa128e8
NF
228 (rlogin-mode)
229
32992017
NF
230 (make-local-variable 'rlogin-host)
231 (setq rlogin-host host)
60667917
NF
232 (make-local-variable 'rlogin-remote-user)
233 (setq rlogin-remote-user user)
32992017 234
fb7741f5
NF
235 (condition-case ()
236 (cond ((eq rlogin-directory-tracking-mode t)
237 ;; Do this here, rather than calling the tracking mode
238 ;; function, to avoid a gratuitous resync check; the default
239 ;; should be the user's home directory, be it local or remote.
240 (setq comint-file-name-prefix
241 (concat "/" rlogin-remote-user "@" rlogin-host ":"))
242 (cd-absolute comint-file-name-prefix))
243 ((null rlogin-directory-tracking-mode))
244 (t
245 (cd-absolute (concat comint-file-name-prefix "~/"))))
246 (error nil))))))
ce992678 247
991465cb
RS
248(put 'rlogin-mode 'mode-class 'special)
249
c7986c18 250(defun rlogin-mode ()
2601d12e 251 "Set major-mode for rlogin sessions.
8ae3bc9f 252If `rlogin-mode-hook' is set, run it."
c7986c18 253 (interactive)
8d30fe17 254 (kill-all-local-variables)
09567b5c 255 (shell-mode)
c7986c18 256 (setq major-mode 'rlogin-mode)
8d30fe17 257 (setq mode-name "rlogin")
c7986c18 258 (use-local-map rlogin-mode-map)
32992017 259 (setq shell-dirtrackp rlogin-directory-tracking-mode)
f3417b13 260 (make-local-variable 'comint-file-name-prefix)
c7986c18
ER
261 (run-hooks 'rlogin-mode-hook))
262
32992017
NF
263(defun rlogin-directory-tracking-mode (&optional prefix)
264 "Do remote or local directory tracking, or disable entirely.
265
266If called with no prefix argument or a unspecified prefix argument (just
267``\\[universal-argument]'' with no number) do remote directory tracking via
268ange-ftp. If called as a function, give it no argument.
269
270If called with a negative prefix argument, disable directory tracking
271entirely.
272
2601d12e 273If called with a positive, numeric prefix argument, e.g.
32992017
NF
274``\\[universal-argument] 1 M-x rlogin-directory-tracking-mode\'',
275then do directory tracking but assume the remote filesystem is the same as
276the local system. This only works in general if the remote machine and the
277local one share the same directories (through NFS)."
278 (interactive "P")
279 (cond
280 ((or (null prefix)
281 (consp prefix))
282 (setq rlogin-directory-tracking-mode t)
f9c4665a 283 (setq shell-dirtrackp t)
2601d12e 284 (setq comint-file-name-prefix
60667917 285 (concat "/" rlogin-remote-user "@" rlogin-host ":")))
32992017
NF
286 ((< prefix 0)
287 (setq rlogin-directory-tracking-mode nil)
f9c4665a 288 (setq shell-dirtrackp nil))
32992017
NF
289 (t
290 (setq rlogin-directory-tracking-mode 'local)
291 (setq comint-file-name-prefix "")
f9c4665a 292 (setq shell-dirtrackp t)))
2601d12e 293 (cond
f9c4665a 294 (shell-dirtrackp
32992017
NF
295 (let* ((proc (get-buffer-process (current-buffer)))
296 (proc-mark (process-mark proc))
297 (current-input (buffer-substring proc-mark (point-max)))
298 (orig-point (point))
299 (offset (and (>= orig-point proc-mark)
300 (- (point-max) orig-point))))
301 (unwind-protect
302 (progn
303 (delete-region proc-mark (point-max))
304 (goto-char (point-max))
305 (shell-resync-dirs))
306 (goto-char proc-mark)
307 (insert current-input)
308 (if offset
309 (goto-char (- (point-max) offset))
310 (goto-char orig-point)))))))
311
8ae3bc9f 312\f
32992017
NF
313;; Parse a line into its constituent parts (words separated by
314;; whitespace). Return a list of the words.
315(defun rlogin-parse-words (line)
316 (let ((list nil)
317 (posn 0)
318 (match-data (match-data)))
319 (while (string-match "[^ \t\n]+" line posn)
320 (setq list (cons (substring line (match-beginning 0) (match-end 0))
321 list))
322 (setq posn (match-end 0)))
323 (store-match-data (match-data))
324 (nreverse list)))
325
2601d12e
NF
326(defun rlogin-carriage-filter (string)
327 (let* ((point-marker (point-marker))
328 (end (process-mark (get-buffer-process (current-buffer))))
329 (beg (or (and (boundp 'comint-last-output-start)
330 comint-last-output-start)
331 (- end (length string)))))
332 (goto-char beg)
333 (while (search-forward "\C-m" end t)
32992017
NF
334 (delete-char -1))
335 (goto-char point-marker)))
336
c7986c18
ER
337(defun rlogin-send-Ctrl-C ()
338 (interactive)
339 (send-string nil "\C-c"))
340
099dcd39
RM
341(defun rlogin-send-Ctrl-D ()
342 (interactive)
343 (send-string nil "\C-d"))
344
c7986c18
ER
345(defun rlogin-send-Ctrl-Z ()
346 (interactive)
347 (send-string nil "\C-z"))
348
349(defun rlogin-send-Ctrl-backslash ()
350 (interactive)
351 (send-string nil "\C-\\"))
352
353(defun rlogin-delchar-or-send-Ctrl-D (arg)
057795ba 354 "\
2601d12e
NF
355Delete ARG characters forward, or send a C-d to process if at end of buffer."
356 (interactive "p")
c7986c18 357 (if (eobp)
057795ba 358 (rlogin-send-Ctrl-D)
c7986c18
ER
359 (delete-char arg)))
360
32992017 361(defun rlogin-tab-or-complete ()
60667917 362 "Complete file name if doing directory tracking, or just insert TAB."
32992017
NF
363 (interactive)
364 (if rlogin-directory-tracking-mode
365 (comint-dynamic-complete)
60667917 366 (insert "\C-i")))
32992017 367
140835c2
NF
368(provide 'rlogin)
369
76550a57 370;;; rlogin.el ends here