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