Replace version 24.2 with 24.3 where appropriate (hopefully)
[bpt/emacs.git] / lisp / net / tramp.el
CommitLineData
b1a2b924 1;;; tramp.el --- Transparent Remote Access, Multiple Protocol
fb7933a3 2
acaf905b 3;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
fb7933a3 4
cdd44874 5;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
d2a2c17f 6;; Michael Albinus <michael.albinus@gmx.de>
fb7933a3 7;; Keywords: comm, processes
0f34aa77 8;; Package: tramp
fb7933a3
KG
9
10;; This file is part of GNU Emacs.
11
874a927a 12;; GNU Emacs is free software: you can redistribute it and/or modify
fb7933a3 13;; it under the terms of the GNU General Public License as published by
874a927a
GM
14;; the Free Software Foundation, either version 3 of the License, or
15;; (at your option) any later version.
fb7933a3
KG
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
874a927a 23;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
fb7933a3
KG
24
25;;; Commentary:
26
27;; This package provides remote file editing, similar to ange-ftp.
28;; The difference is that ange-ftp uses FTP to transfer files between
29;; the local and the remote host, whereas tramp.el uses a combination
30;; of rsh and rcp or other work-alike programs, such as ssh/scp.
31;;
b1a2b924 32;; For more detailed instructions, please see the info file.
fb7933a3
KG
33;;
34;; Notes:
35;; -----
bf247b6e 36;;
b533bc97 37;; This package only works for Emacs 22.1 and higher, and for XEmacs 21.4
00d6fd04 38;; and higher. For XEmacs 21, you need the package `fsf-compat' for
7f4d4a97 39;; the `with-timeout' macro.
fb7933a3 40;;
fb7933a3
KG
41;; Also see the todo list at the bottom of this file.
42;;
b1a2b924 43;; The current version of Tramp can be retrieved from the following URL:
340b8d4f 44;; http://ftp.gnu.org/gnu/tramp/
fb7933a3
KG
45;;
46;; There's a mailing list for this, as well. Its name is:
340b8d4f
MA
47;; tramp-devel@gnu.org
48;; You can use the Web to subscribe, under the following URL:
49;; http://lists.gnu.org/mailman/listinfo/tramp-devel
fb7933a3
KG
50;;
51;; For the adventurous, the current development sources are available
52;; via CVS. You can find instructions about this at the following URL:
c62c9d08 53;; http://savannah.gnu.org/projects/tramp/
fb7933a3
KG
54;; Click on "CVS" in the navigation bar near the top.
55;;
56;; Don't forget to put on your asbestos longjohns, first!
57
58;;; Code:
59
2fe4b125 60(eval-when-compile (require 'cl)) ; ignore-errors
9e6ab520 61(require 'tramp-compat)
fb7933a3 62
fb7933a3
KG
63;;; User Customizable Internal Variables:
64
65(defgroup tramp nil
cf20dee0 66 "Edit remote files with a combination of ssh, scp, etc."
589d30dd 67 :group 'files
26f4b8ab 68 :group 'comm
bf247b6e 69 :version "22.1")
fb7933a3 70
2e271195
MA
71;; Maybe we need once a real Tramp mode, with key bindings etc.
72;;;###autoload
73(defcustom tramp-mode t
fb7ada5f 74 "Whether Tramp is enabled.
2e271195
MA
75If it is set to nil, all remote file names are used literally."
76 :group 'tramp
77 :type 'boolean)
78
00d6fd04 79(defcustom tramp-verbose 3
fb7ada5f 80 "Verbosity level for Tramp messages.
00d6fd04
MA
81Any level x includes messages for all levels 1 .. x-1. The levels are
82
83 0 silent (no tramp messages at all)
84 1 errors
85 2 warnings
86 3 connection to remote hosts (default level)
87 4 activities
88 5 internal
89 6 sent and received strings
90 7 file caching
91 8 connection properties
8fbcce2d 92 9 test commands
00d6fd04 9310 traces (huge)."
fb7933a3
KG
94 :group 'tramp
95 :type 'integer)
96
263c02ef 97;; Emacs case.
38c65fca
KG
98(eval-and-compile
99 (when (boundp 'backup-directory-alist)
100 (defcustom tramp-backup-directory-alist nil
101 "Alist of filename patterns and backup directory names.
102Each element looks like (REGEXP . DIRECTORY), with the same meaning like
103in `backup-directory-alist'. If a Tramp file is backed up, and DIRECTORY
104is a local file name, the backup directory is prepended with Tramp file
00d6fd04 105name prefix \(method, user, host\) of file.
38c65fca
KG
106
107\(setq tramp-backup-directory-alist backup-directory-alist\)
108
109gives the same backup policy for Tramp files on their hosts like the
110policy for local files."
111 :group 'tramp
112 :type '(repeat (cons (regexp :tag "Regexp matching filename")
113 (directory :tag "Backup directory name"))))))
114
115;; XEmacs case. We cannot check for `bkup-backup-directory-info', because
116;; the package "backup-dir" might not be loaded yet.
117(eval-and-compile
118 (when (featurep 'xemacs)
119 (defcustom tramp-bkup-backup-directory-info nil
2fe4b125 120 "Alist of (FILE-REGEXP BACKUP-DIR OPTIONS ...))
38c65fca
KG
121It has the same meaning like `bkup-backup-directory-info' from package
122`backup-dir'. If a Tramp file is backed up, and BACKUP-DIR is a local
123file name, the backup directory is prepended with Tramp file name prefix
00d6fd04 124\(method, user, host\) of file.
38c65fca
KG
125
126\(setq tramp-bkup-backup-directory-info bkup-backup-directory-info\)
127
128gives the same backup policy for Tramp files on their hosts like the
129policy for local files."
bf247b6e 130 :type '(repeat
38c65fca
KG
131 (list (regexp :tag "File regexp")
132 (string :tag "Backup Dir")
133 (set :inline t
134 (const ok-create)
135 (const full-path)
136 (const prepend-name)
137 (const search-upward))))
138 :group 'tramp)))
139
fb7933a3 140(defcustom tramp-auto-save-directory nil
fb7ada5f 141 "Put auto-save files in this directory, if set.
fb7933a3
KG
142The idea is to use a local directory so that auto-saving is faster."
143 :group 'tramp
00d6fd04 144 :type '(choice (const nil) string))
fb7933a3 145
16674e4f
KG
146(defcustom tramp-encoding-shell
147 (if (memq system-type '(windows-nt))
148 (getenv "COMSPEC")
149 "/bin/sh")
fb7ada5f 150 "Use this program for encoding and decoding commands on the local host.
16674e4f
KG
151This shell is used to execute the encoding and decoding command on the
152local host, so if you want to use `~' in those commands, you should
153choose a shell here which groks tilde expansion. `/bin/sh' normally
154does not understand tilde expansion.
155
4c36be58 156For encoding and decoding, commands like the following are executed:
16674e4f
KG
157
158 /bin/sh -c COMMAND < INPUT > OUTPUT
159
160This variable can be used to change the \"/bin/sh\" part. See the
00d6fd04 161variable `tramp-encoding-command-switch' for the \"-c\" part.
fb7933a3 162
36b148cf
MA
163If the shell must be forced to be interactive, see
164`tramp-encoding-command-interactive'.
165
fb7933a3
KG
166Note that this variable is not used for remote commands. There are
167mechanisms in tramp.el which automatically determine the right shell to
168use for the remote host."
169 :group 'tramp
170 :type '(file :must-match t))
171
16674e4f
KG
172(defcustom tramp-encoding-command-switch
173 (if (string-match "cmd\\.exe" tramp-encoding-shell)
174 "/c"
175 "-c")
fb7ada5f 176 "Use this switch together with `tramp-encoding-shell' for local commands.
16674e4f
KG
177See the variable `tramp-encoding-shell' for more information."
178 :group 'tramp
179 :type 'string)
180
36b148cf
MA
181(defcustom tramp-encoding-command-interactive
182 (unless (string-match "cmd\\.exe" tramp-encoding-shell) "-i")
fb7ada5f 183 "Use this switch together with `tramp-encoding-shell' for interactive shells.
36b148cf 184See the variable `tramp-encoding-shell' for more information."
2bed3f04 185 :version "24.1"
36b148cf
MA
186 :group 'tramp
187 :type '(choice (const nil) string))
188
0f34aa77 189;;;###tramp-autoload
03c1ad43 190(defvar tramp-methods nil
fb7ada5f 191 "Alist of methods for remote files.
fb7933a3
KG
192This is a list of entries of the form (NAME PARAM1 PARAM2 ...).
193Each NAME stands for a remote access method. Each PARAM is a
194pair of the form (KEY VALUE). The following KEYs are defined:
f5e29b9b 195 * `tramp-remote-shell'
710dec63
MA
196 This specifies the shell to use on the remote host. This
197 MUST be a Bourne-like shell. It is normally not necessary to
198 set this to any value other than \"/bin/sh\": Tramp wants to
199 use a shell which groks tilde expansion, but it can search
200 for it. Also note that \"/bin/sh\" exists on all Unixen,
201 this might not be true for the value that you decide to use.
202 You Have Been Warned.
f5e29b9b
MA
203 * `tramp-remote-shell-args'
204 For implementation of `shell-command', this specifies the
710dec63 205 arguments to let `tramp-remote-shell' run a single command.
b25a52cc
KG
206 * `tramp-login-program'
207 This specifies the name of the program to use for logging in to the
00d6fd04
MA
208 remote host. This may be the name of rsh or a workalike program,
209 or the name of telnet or a workalike, or the name of su or a workalike.
b25a52cc 210 * `tramp-login-args'
fb7933a3 211 This specifies the list of arguments to pass to the above
00d6fd04 212 mentioned program. Please note that this is a list of list of arguments,
fb7933a3 213 that is, normally you don't want to put \"-a -b\" or \"-f foo\"
00d6fd04
MA
214 here. Instead, you want a list (\"-a\" \"-b\"), or (\"-f\" \"foo\").
215 There are some patterns: \"%h\" in this list is replaced by the host
216 name, \"%u\" is replaced by the user name, \"%p\" is replaced by the
217 port number, and \"%%\" can be used to obtain a literal percent character.
218 If a list containing \"%h\", \"%u\" or \"%p\" is unchanged during
219 expansion (i.e. no host or no user specified), this list is not used as
220 argument. By this, arguments like (\"-l\" \"%u\") are optional.
221 \"%t\" is replaced by the temporary file name produced with
222 `tramp-make-tramp-temp-file'. \"%k\" indicates the keep-date
223 parameter of a program, if exists.
a7723e05
MA
224 * `tramp-async-args'
225 When an asynchronous process is started, we know already that
226 the connection works. Therefore, we can pass additional
227 parameters to suppress diagnostic messages, in order not to
228 tamper the process output.
b25a52cc
KG
229 * `tramp-copy-program'
230 This specifies the name of the program to use for remotely copying
231 the file; this might be the absolute filename of rcp or the name of
232 a workalike program.
233 * `tramp-copy-args'
fb7933a3 234 This specifies the list of parameters to pass to the above mentioned
b25a52cc 235 program, the hints for `tramp-login-args' also apply here.
00d6fd04
MA
236 * `tramp-copy-keep-date'
237 This specifies whether the copying program when the preserves the
238 timestamp of the original file.
b88f2d0a
MA
239 * `tramp-copy-keep-tmpfile'
240 This specifies whether a temporary local file shall be kept
241 for optimization reasons (useful for \"rsync\" methods).
242 * `tramp-copy-recursive'
243 Whether the operation copies directories recursively.
00d6fd04
MA
244 * `tramp-default-port'
245 The default port of a method is needed in case of gateway connections.
246 Additionally, it is used as indication which method is prepared for
247 passing gateways.
248 * `tramp-gw-args'
249 As the attribute name says, additional arguments are specified here
250 when a method is applied via a gateway.
710dec63
MA
251 * `tramp-tmpdir'
252 A directory on the remote host for temporary files. If not
253 specified, \"/tmp\" is taken as default.
b25a52cc
KG
254
255What does all this mean? Well, you should specify `tramp-login-program'
256for all methods; this program is used to log in to the remote site. Then,
257there are two ways to actually transfer the files between the local and the
258remote side. One way is using an additional rcp-like program. If you want
259to do this, set `tramp-copy-program' in the method.
fb7933a3
KG
260
261Another possibility for file transfer is inline transfer, i.e. the
b25a52cc 262file is passed through the same buffer used by `tramp-login-program'. In
fb7933a3 263this case, the file contents need to be protected since the
b25a52cc 264`tramp-login-program' might use escape codes or the connection might not
fb7933a3 265be eight-bit clean. Therefore, file contents are encoded for transit.
00d6fd04
MA
266See the variables `tramp-local-coding-commands' and
267`tramp-remote-coding-commands' for details.
fb7933a3 268
16674e4f 269So, to summarize: if the method is an out-of-band method, then you
b25a52cc 270must specify `tramp-copy-program' and `tramp-copy-args'. If it is an
00d6fd04
MA
271inline method, then these two parameters should be nil. Methods which
272are fit for gateways must have `tramp-default-port' at least.
fb7933a3
KG
273
274Notes:
275
00d6fd04
MA
276When using `su' or `sudo' the phrase `open connection to a remote
277host' sounds strange, but it is used nevertheless, for consistency.
278No connection is opened to a remote host, but `su' or `sudo' is
279started on the local host. You should specify a remote host
280`localhost' or the name of the local host. Another host name is
281useful only in combination with `tramp-default-proxies-alist'.")
fb7933a3 282
a92375d9
MA
283(defun tramp-detect-ssh-controlmaster ()
284 "Call ssh to detect whether it supports the ControlMaster argument.
285This function may return nil when the argument is supported, but
286shouldn't return t when it isn't."
287 (ignore-errors
288 (with-temp-buffer
289 (call-process "ssh" nil t nil "-o" "ControlMaster")
290 (goto-char (point-min))
291 (search-forward-regexp "Missing ControlMaster argument" nil t))))
292
b25a52cc 293(defcustom tramp-default-method
fa463103
PE
294 ;; An external copy method seems to be preferred, because it performs
295 ;; much better for large files, and it hasn't too serious delays
83e20b5c
MA
296 ;; for small files. But it must be ensured that there aren't
297 ;; permanent password queries. Either a password agent like
263c02ef
MA
298 ;; "ssh-agent" or "Pageant" shall run, or the optional
299 ;; password-cache.el or auth-sources.el packages shall be active for
a92375d9
MA
300 ;; password caching. "scpc" is chosen if we detect that the user is
301 ;; running OpenSSH 4.0 or newer.
00d6fd04 302 (cond
362b9d48
GM
303 ;; PuTTY is installed. We don't take it, if it is installed on a
304 ;; non-windows system, or pscp from the pssh (parallel ssh) package
305 ;; is found.
306 ((and (eq system-type 'windows-nt)
307 (executable-find "pscp"))
00d6fd04 308 (if (or (fboundp 'password-read)
263c02ef 309 (fboundp 'auth-source-user-or-password)
563790b6 310 (fboundp 'auth-source-search)
00d6fd04 311 ;; Pageant is running.
70c11b0b 312 (tramp-compat-process-running-p "Pageant"))
00d6fd04
MA
313 "pscp"
314 "plink"))
315 ;; There is an ssh installation.
316 ((executable-find "scp")
a92375d9
MA
317 (cond
318 ((tramp-detect-ssh-controlmaster) "scpc")
319 ((or (fboundp 'password-read)
320 (fboundp 'auth-source-user-or-password)
563790b6 321 (fboundp 'auth-source-search)
a92375d9
MA
322 ;; ssh-agent is running.
323 (getenv "SSH_AUTH_SOCK")
324 (getenv "SSH_AGENT_PID"))
325 "scp")
326 (t "ssh")))
00d6fd04
MA
327 ;; Fallback.
328 (t "ftp"))
fb7ada5f 329 "Default method to use for transferring files.
c62c9d08 330See `tramp-methods' for possibilities.
4007ba5b 331Also see `tramp-default-method-alist'."
c62c9d08
KG
332 :group 'tramp
333 :type 'string)
334
b191c9d9 335;;;###tramp-autoload
03c1ad43 336(defcustom tramp-default-method-alist nil
fb7ada5f 337 "Default method to use for specific host/user pairs.
c62c9d08
KG
338This is an alist of items (HOST USER METHOD). The first matching item
339specifies the method to use for a file name which does not specify a
340method. HOST and USER are regular expressions or nil, which is
341interpreted as a regular expression which always matches. If no entry
342matches, the variable `tramp-default-method' takes effect.
343
344If the file name does not specify the user, lookup is done using the
345empty string for the user name.
346
347See `tramp-methods' for a list of possibilities for METHOD."
348 :group 'tramp
e40fc745
MA
349 :type '(repeat (list (choice :tag "Host regexp" regexp sexp)
350 (choice :tag "User regexp" regexp sexp)
351 (choice :tag "Method name" string (const nil)))))
c62c9d08 352
03c1ad43 353(defcustom tramp-default-user nil
fb7ada5f 354 "Default user to use for transferring files.
00d6fd04
MA
355It is nil by default; otherwise settings in configuration files like
356\"~/.ssh/config\" would be overwritten. Also see `tramp-default-user-alist'.
357
358This variable is regarded as obsolete, and will be removed soon."
359 :group 'tramp
360 :type '(choice (const nil) string))
361
b191c9d9 362;;;###tramp-autoload
03c1ad43 363(defcustom tramp-default-user-alist nil
fb7ada5f 364 "Default user to use for specific method/host pairs.
00d6fd04
MA
365This is an alist of items (METHOD HOST USER). The first matching item
366specifies the user to use for a file name which does not specify a
367user. METHOD and USER are regular expressions or nil, which is
368interpreted as a regular expression which always matches. If no entry
369matches, the variable `tramp-default-user' takes effect.
370
371If the file name does not specify the method, lookup is done using the
372empty string for the method name."
373 :group 'tramp
e40fc745
MA
374 :type '(repeat (list (choice :tag "Method regexp" regexp sexp)
375 (choice :tag " Host regexp" regexp sexp)
376 (choice :tag " User name" string (const nil)))))
00d6fd04 377
03c1ad43 378(defcustom tramp-default-host (system-name)
fb7ada5f 379 "Default host to use for transferring files.
00d6fd04
MA
380Useful for su and sudo methods mostly."
381 :group 'tramp
382 :type 'string)
383
384(defcustom tramp-default-proxies-alist nil
fb7ada5f 385 "Route to be followed for specific host/user pairs.
00d6fd04
MA
386This is an alist of items (HOST USER PROXY). The first matching
387item specifies the proxy to be passed for a file name located on
388a remote target matching USER@HOST. HOST and USER are regular
70c11b0b
MA
389expressions. PROXY must be a Tramp filename without a localname
390part. Method and user name on PROXY are optional, which is
391interpreted with the default values. PROXY can contain the
392patterns %h and %u, which are replaced by the strings matching
393HOST or USER, respectively.
394
395HOST, USER or PROXY could also be Lisp forms, which will be
396evaluated. The result must be a string or nil, which is
397interpreted as a regular expression which always matches."
00d6fd04 398 :group 'tramp
70c11b0b
MA
399 :type '(repeat (list (choice :tag "Host regexp" regexp sexp)
400 (choice :tag "User regexp" regexp sexp)
e40fc745 401 (choice :tag " Proxy name" string (const nil)))))
00d6fd04 402
2fe4b125
MA
403(defcustom tramp-save-ad-hoc-proxies nil
404 "Whether to save ad-hoc proxies persistently."
405 :group 'tramp
406 :type 'boolean)
407
07b151f1
MA
408(defcustom tramp-restricted-shell-hosts-alist
409 (when (memq system-type '(windows-nt))
410 (list (concat "\\`" (regexp-quote (system-name)) "\\'")))
411 "List of hosts, which run a restricted shell.
412This is a list of regular expressions, which denote hosts running
413a registered shell like \"rbash\". Those hosts can be used as
414proxies only, see `tramp-default-proxies-alist'. If the local
415host runs a registered shell, it shall be added to this list, too."
2a1e2476 416 :version "24.3"
07b151f1
MA
417 :group 'tramp
418 :type '(repeat (regexp :tag "Host regexp")))
419
b191c9d9 420;;;###tramp-autoload
b96e6899
MA
421(defconst tramp-local-host-regexp
422 (concat
66feec8b
MA
423 "\\`"
424 (regexp-opt
425 (list "localhost" "localhost6" (system-name) "127\.0\.0\.1" "::1") t)
426 "\\'")
fb7ada5f 427 "Host names which are regarded as local host.")
b96e6899 428
5ec2cc41 429(defvar tramp-completion-function-alist nil
fb7ada5f 430 "Alist of methods for remote files.
b533bc97 431This is a list of entries of the form \(NAME PAIR1 PAIR2 ...\).
16674e4f 432Each NAME stands for a remote access method. Each PAIR is of the form
b533bc97 433\(FUNCTION FILE\). FUNCTION is responsible to extract user names and host
16674e4f
KG
434names from FILE for completion. The following predefined FUNCTIONs exists:
435
5ec2cc41
KG
436 * `tramp-parse-rhosts' for \"~/.rhosts\" like files,
437 * `tramp-parse-shosts' for \"~/.ssh/known_hosts\" like files,
438 * `tramp-parse-sconfig' for \"~/.ssh/config\" like files,
439 * `tramp-parse-shostkeys' for \"~/.ssh2/hostkeys/*\" like files,
440 * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files,
441 * `tramp-parse-hosts' for \"/etc/hosts\" like files,
442 * `tramp-parse-passwd' for \"/etc/passwd\" like files.
443 * `tramp-parse-netrc' for \"~/.netrc\" like files.
2fe4b125 444 * `tramp-parse-putty' for PuTTY registered sessions.
5ec2cc41
KG
445
446FUNCTION can also be a customer defined function. For more details see
447the info pages.")
448
674da028
MA
449(defconst tramp-echo-mark-marker "_echo"
450 "String marker to surround echoed commands.")
451
68712eb6
MA
452(defconst tramp-echo-mark-marker-length (length tramp-echo-mark-marker)
453 "String length of `tramp-echo-mark-marker'.")
454
455(defconst tramp-echo-mark
456 (concat tramp-echo-mark-marker
457 (make-string tramp-echo-mark-marker-length ?\b))
00d6fd04
MA
458 "String mark to be transmitted around shell commands.
459Used to separate their echo from the output they produce. This
460will only be used if we cannot disable remote echo via stty.
461This string must have no effect on the remote shell except for
462producing some echo which can later be detected by
674da028
MA
463`tramp-echoed-echo-mark-regexp'. Using `tramp-echo-mark-marker',
464followed by an equal number of backspaces to erase them will
465usually suffice.")
00d6fd04 466
68712eb6
MA
467(defconst tramp-echoed-echo-mark-regexp
468 (format "%s\\(\b\\( \b\\)?\\)\\{%d\\}"
469 tramp-echo-mark-marker tramp-echo-mark-marker-length)
00d6fd04
MA
470 "Regexp which matches `tramp-echo-mark' as it gets echoed by
471the remote shell.")
472
4cb0aa75
MA
473(defcustom tramp-local-end-of-line
474 (if (memq system-type '(windows-nt)) "\r\n" "\n")
fb7ada5f 475 "String used for end of line in local processes."
2bed3f04 476 :version "24.1"
4cb0aa75
MA
477 :group 'tramp
478 :type 'string)
479
fb7933a3 480(defcustom tramp-rsh-end-of-line "\n"
fb7ada5f 481 "String used for end of line in rsh connections.
fb7933a3 482I don't think this ever needs to be changed, so please tell me about it
2fe4b125 483if you need to change this."
fb7933a3
KG
484 :group 'tramp
485 :type 'string)
486
fb7933a3 487(defcustom tramp-login-prompt-regexp
bc103d00 488 ".*ogin\\( .*\\)?: *"
fb7ada5f 489 "Regexp matching login-like prompts.
bc103d00
MA
490The regexp should match at end of buffer.
491
492Sometimes the prompt is reported to look like \"login as:\"."
fb7933a3
KG
493 :group 'tramp
494 :type 'regexp)
495
821e6e36 496(defcustom tramp-shell-prompt-pattern
aa485f7c 497 ;; Allow a prompt to start right after a ^M since it indeed would be
b81a0b56
MA
498 ;; displayed at the beginning of the line (and Zsh uses it). This
499 ;; regexp works only for GNU Emacs.
2fe4b125
MA
500 ;; Allow also [] style prompts. They can appear only during
501 ;; connection initialization; Tramp redefines the prompt afterwards.
b81a0b56 502 (concat (if (featurep 'xemacs) "" "\\(?:^\\|\r\\)")
2fe4b125 503 "[^]#$%>\n]*#?[]#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*")
821e6e36
KG
504 "Regexp to match prompts from remote shell.
505Normally, Tramp expects you to configure `shell-prompt-pattern'
506correctly, but sometimes it happens that you are connecting to a
507remote host which sends a different kind of shell prompt. Therefore,
508Tramp recognizes things matched by `shell-prompt-pattern' as prompt,
509and also things matched by this variable. The default value of this
b25a52cc 510variable is similar to the default value of `shell-prompt-pattern',
dab816a9
MA
511which should work well in many cases.
512
513This regexp must match both `tramp-initial-end-of-output' and
514`tramp-end-of-output'."
821e6e36
KG
515 :group 'tramp
516 :type 'regexp)
517
fb7933a3 518(defcustom tramp-password-prompt-regexp
00d6fd04 519 "^.*\\([pP]assword\\|[pP]assphrase\\).*:\^@? *"
fb7ada5f 520 "Regexp matching password-like prompts.
ac474af1 521The regexp should match at end of buffer.
fb7933a3
KG
522
523The `sudo' program appears to insert a `^@' character into the prompt."
524 :group 'tramp
525 :type 'regexp)
526
527(defcustom tramp-wrong-passwd-regexp
b1d06e75
KG
528 (concat "^.*"
529 ;; These strings should be on the last line
a4aeb9a4 530 (regexp-opt '("Permission denied"
b1d06e75
KG
531 "Login incorrect"
532 "Login Incorrect"
533 "Connection refused"
27e813fe 534 "Connection closed"
7e5686f0 535 "Timeout, server not responding."
b1d06e75
KG
536 "Sorry, try again."
537 "Name or service not known"
00d6fd04 538 "Host key verification failed."
70c11b0b 539 "No supported authentication methods left to try!") t)
b1d06e75
KG
540 ".*"
541 "\\|"
542 "^.*\\("
543 ;; Here comes a list of regexes, separated by \\|
544 "Received signal [0-9]+"
545 "\\).*")
fb7ada5f 546 "Regexp matching a `login failed' message.
ac474af1
KG
547The regexp should match at end of buffer."
548 :group 'tramp
549 :type 'regexp)
550
551(defcustom tramp-yesno-prompt-regexp
3cdaec13
KG
552 (concat
553 (regexp-opt '("Are you sure you want to continue connecting (yes/no)?") t)
554 "\\s-*")
555 "Regular expression matching all yes/no queries which need to be confirmed.
ac474af1 556The confirmation should be done with yes or no.
3cdaec13
KG
557The regexp should match at end of buffer.
558See also `tramp-yn-prompt-regexp'."
fb7933a3
KG
559 :group 'tramp
560 :type 'regexp)
561
3cdaec13 562(defcustom tramp-yn-prompt-regexp
658052a2
MA
563 (concat
564 (regexp-opt '("Store key in cache? (y/n)"
565 "Update cached key? (y/n, Return cancels connection)") t)
566 "\\s-*")
3cdaec13
KG
567 "Regular expression matching all y/n queries which need to be confirmed.
568The confirmation should be done with y or n.
569The regexp should match at end of buffer.
570See also `tramp-yesno-prompt-regexp'."
571 :group 'tramp
572 :type 'regexp)
487f4fb7
KG
573
574(defcustom tramp-terminal-prompt-regexp
575 (concat "\\("
576 "TERM = (.*)"
577 "\\|"
578 "Terminal type\\? \\[.*\\]"
579 "\\)\\s-*")
580 "Regular expression matching all terminal setting prompts.
581The regexp should match at end of buffer.
582The answer will be provided by `tramp-action-terminal', which see."
583 :group 'tramp
584 :type 'regexp)
3cdaec13 585
01917a18
MA
586(defcustom tramp-operation-not-permitted-regexp
587 (concat "\\(" "preserving times.*" "\\|" "set mode" "\\)" ":\\s-*"
588 (regexp-opt '("Operation not permitted") t))
589 "Regular expression matching keep-date problems in (s)cp operations.
590Copying has been performed successfully already, so this message can
591be ignored safely."
592 :group 'tramp
593 :type 'regexp)
594
6b2633cc
LH
595(defcustom tramp-copy-failed-regexp
596 (concat "\\(.+: "
597 (regexp-opt '("Permission denied"
598 "not a regular file"
599 "is a directory"
600 "No such file or directory") t)
601 "\\)\\s-*")
602 "Regular expression matching copy problems in (s)cp operations."
603 :group 'tramp
604 :type 'regexp)
605
19a87064 606(defcustom tramp-process-alive-regexp
38c65fca 607 ""
19a87064 608 "Regular expression indicating a process has finished.
38c65fca
KG
609In fact this expression is empty by intention, it will be used only to
610check regularly the status of the associated process.
07dfe738 611The answer will be provided by `tramp-action-process-alive',
00d6fd04 612`tramp-action-out-of-band', which see."
38c65fca
KG
613 :group 'tramp
614 :type 'regexp)
615
03c1ad43 616(defconst tramp-temp-name-prefix "tramp."
fb7ada5f 617 "Prefix to use for temporary files.
fb7933a3
KG
618If this is a relative file name (such as \"tramp.\"), it is considered
619relative to the directory name returned by the function
9e6ab520 620`tramp-compat-temporary-file-directory' (which see). It may also be an
fb7933a3 621absolute file name; don't forget to include a prefix for the filename
03c1ad43 622part, though.")
fb7933a3 623
2296b54d
MA
624(defconst tramp-temp-buffer-name " *tramp temp*"
625 "Buffer name for a temporary buffer.
626It shall be used in combination with `generate-new-buffer-name'.")
627
b88f2d0a
MA
628(defvar tramp-temp-buffer-file-name nil
629 "File name of a persistent local temporary file.
630Useful for \"rsync\" like methods.")
631(make-variable-buffer-local 'tramp-temp-buffer-file-name)
d68b0220 632(put 'tramp-temp-buffer-file-name 'permanent-local t)
b88f2d0a 633
00d6fd04
MA
634;; XEmacs is distributed with few Lisp packages. Further packages are
635;; installed using EFS. If we use a unified filename format, then
636;; Tramp is required in addition to EFS. (But why can't Tramp just
637;; disable EFS when Tramp is loaded? Then XEmacs can ship with EFS
638;; just like before.) Another reason for using a separate filename
639;; syntax on XEmacs is that EFS hooks into XEmacs in many places, but
640;; Tramp only knows how to deal with `file-name-handler-alist', not
641;; the other places.
642
643;; Currently, we have the choice between 'ftp, 'sep, and 'url.
644;;;###autoload
645(defcustom tramp-syntax
646 (if (featurep 'xemacs) 'sep 'ftp)
647 "Tramp filename syntax to be used.
648
649It can have the following values:
650
651 'ftp -- Ange-FTP respective EFS like syntax (GNU Emacs default)
652 'sep -- Syntax as defined for XEmacs (not available yet for GNU Emacs)
653 'url -- URL-like syntax."
16674e4f 654 :group 'tramp
00d6fd04
MA
655 :type (if (featurep 'xemacs)
656 '(choice (const :tag "EFS" ftp)
657 (const :tag "XEmacs" sep)
658 (const :tag "URL" url))
659 '(choice (const :tag "Ange-FTP" ftp)
660 (const :tag "URL" url))))
661
662(defconst tramp-prefix-format
663 (cond ((equal tramp-syntax 'ftp) "/")
664 ((equal tramp-syntax 'sep) "/[")
665 ((equal tramp-syntax 'url) "/")
666 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 667 "String matching the very beginning of Tramp file names.
00d6fd04 668Used in `tramp-make-tramp-file-name'.")
16674e4f 669
00d6fd04 670(defconst tramp-prefix-regexp
16674e4f 671 (concat "^" (regexp-quote tramp-prefix-format))
fb7ada5f 672 "Regexp matching the very beginning of Tramp file names.
00d6fd04 673Should always start with \"^\". Derived from `tramp-prefix-format'.")
16674e4f 674
00d6fd04 675(defconst tramp-method-regexp
16674e4f 676 "[a-zA-Z_0-9-]+"
fb7ada5f 677 "Regexp matching methods identifiers.")
16674e4f 678
00d6fd04
MA
679(defconst tramp-postfix-method-format
680 (cond ((equal tramp-syntax 'ftp) ":")
681 ((equal tramp-syntax 'sep) "/")
682 ((equal tramp-syntax 'url) "://")
683 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 684 "String matching delimiter between method and user or host names.
00d6fd04 685Used in `tramp-make-tramp-file-name'.")
16674e4f 686
00d6fd04
MA
687(defconst tramp-postfix-method-regexp
688 (regexp-quote tramp-postfix-method-format)
fb7ada5f 689 "Regexp matching delimiter between method and user or host names.
00d6fd04 690Derived from `tramp-postfix-method-format'.")
16674e4f 691
2fe4b125 692(defconst tramp-user-regexp "[^/|: \t]+"
fb7ada5f 693 "Regexp matching user names.")
16674e4f 694
b191c9d9 695;;;###tramp-autoload
b96e6899 696(defconst tramp-prefix-domain-format "%"
fb7ada5f 697 "String matching delimiter between user and domain names.")
b96e6899 698
b191c9d9 699;;;###tramp-autoload
b96e6899
MA
700(defconst tramp-prefix-domain-regexp
701 (regexp-quote tramp-prefix-domain-format)
fb7ada5f 702 "Regexp matching delimiter between user and domain names.
b96e6899
MA
703Derived from `tramp-prefix-domain-format'.")
704
03c1ad43 705(defconst tramp-domain-regexp "[-a-zA-Z0-9_.]+"
fb7ada5f 706 "Regexp matching domain names.")
b96e6899
MA
707
708(defconst tramp-user-with-domain-regexp
709 (concat "\\(" tramp-user-regexp "\\)"
710 tramp-prefix-domain-regexp
711 "\\(" tramp-domain-regexp "\\)")
fb7ada5f 712 "Regexp matching user names with domain names.")
b96e6899 713
03c1ad43 714(defconst tramp-postfix-user-format "@"
fb7ada5f 715 "String matching delimiter between user and host names.
00d6fd04 716Used in `tramp-make-tramp-file-name'.")
16674e4f 717
00d6fd04 718(defconst tramp-postfix-user-regexp
16674e4f 719 (regexp-quote tramp-postfix-user-format)
fb7ada5f 720 "Regexp matching delimiter between user and host names.
00d6fd04
MA
721Derived from `tramp-postfix-user-format'.")
722
03c1ad43 723(defconst tramp-host-regexp "[a-zA-Z0-9_.-]+"
fb7ada5f 724 "Regexp matching host names.")
00d6fd04 725
b96e6899
MA
726(defconst tramp-prefix-ipv6-format
727 (cond ((equal tramp-syntax 'ftp) "[")
728 ((equal tramp-syntax 'sep) "")
729 ((equal tramp-syntax 'url) "[")
730 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 731 "String matching left hand side of IPv6 addresses.
b96e6899
MA
732Used in `tramp-make-tramp-file-name'.")
733
734(defconst tramp-prefix-ipv6-regexp
735 (regexp-quote tramp-prefix-ipv6-format)
fb7ada5f 736 "Regexp matching left hand side of IPv6 addresses.
b96e6899
MA
737Derived from `tramp-prefix-ipv6-format'.")
738
e0b6e3b9
MA
739;; The following regexp is a bit sloppy. But it shall serve our
740;; purposes. It covers also IPv4 mapped IPv6 addresses, like in
741;; "::ffff:192.168.0.1".
b96e6899 742(defconst tramp-ipv6-regexp
e0b6e3b9 743 "\\(?:\\(?:[a-zA-Z0-9]+\\)?:\\)+[a-zA-Z0-9.]+"
fb7ada5f 744 "Regexp matching IPv6 addresses.")
b96e6899
MA
745
746(defconst tramp-postfix-ipv6-format
747 (cond ((equal tramp-syntax 'ftp) "]")
748 ((equal tramp-syntax 'sep) "")
749 ((equal tramp-syntax 'url) "]")
750 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 751 "String matching right hand side of IPv6 addresses.
b96e6899
MA
752Used in `tramp-make-tramp-file-name'.")
753
754(defconst tramp-postfix-ipv6-regexp
755 (regexp-quote tramp-postfix-ipv6-format)
fb7ada5f 756 "Regexp matching right hand side of IPv6 addresses.
b96e6899
MA
757Derived from `tramp-postfix-ipv6-format'.")
758
00d6fd04
MA
759(defconst tramp-prefix-port-format
760 (cond ((equal tramp-syntax 'ftp) "#")
761 ((equal tramp-syntax 'sep) "#")
762 ((equal tramp-syntax 'url) ":")
763 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 764 "String matching delimiter between host names and port numbers.")
00d6fd04
MA
765
766(defconst tramp-prefix-port-regexp
767 (regexp-quote tramp-prefix-port-format)
fb7ada5f 768 "Regexp matching delimiter between host names and port numbers.
00d6fd04
MA
769Derived from `tramp-prefix-port-format'.")
770
03c1ad43 771(defconst tramp-port-regexp "[0-9]+"
fb7ada5f 772 "Regexp matching port numbers.")
00d6fd04
MA
773
774(defconst tramp-host-with-port-regexp
775 (concat "\\(" tramp-host-regexp "\\)"
776 tramp-prefix-port-regexp
777 "\\(" tramp-port-regexp "\\)")
fb7ada5f 778 "Regexp matching host names with port numbers.")
00d6fd04 779
2fe4b125
MA
780(defconst tramp-postfix-hop-format "|"
781 "String matching delimiter after ad-hoc hop definitions.")
782
783(defconst tramp-postfix-hop-regexp
784 (regexp-quote tramp-postfix-hop-format)
785 "Regexp matching delimiter after ad-hoc hop definitions.
786Derived from `tramp-postfix-hop-format'.")
787
00d6fd04
MA
788(defconst tramp-postfix-host-format
789 (cond ((equal tramp-syntax 'ftp) ":")
790 ((equal tramp-syntax 'sep) "]")
791 ((equal tramp-syntax 'url) "")
792 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 793 "String matching delimiter between host names and localnames.
00d6fd04 794Used in `tramp-make-tramp-file-name'.")
16674e4f 795
00d6fd04 796(defconst tramp-postfix-host-regexp
16674e4f 797 (regexp-quote tramp-postfix-host-format)
fb7ada5f 798 "Regexp matching delimiter between host names and localnames.
00d6fd04 799Derived from `tramp-postfix-host-format'.")
16674e4f 800
03c1ad43 801(defconst tramp-localname-regexp ".*$"
fb7ada5f 802 "Regexp matching localnames.")
16674e4f 803
4a93e698 804;;; File name format:
505edaeb 805
2fe4b125
MA
806(defconst tramp-remote-file-name-spec-regexp
807 (concat
808 "\\(?:" "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp "\\)?"
809 "\\(?:" "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp "\\)?"
810 "\\(" "\\(?:" tramp-host-regexp "\\|"
811 tramp-prefix-ipv6-regexp tramp-ipv6-regexp
812 tramp-postfix-ipv6-regexp "\\)"
813 "\\(?:" tramp-prefix-port-regexp tramp-port-regexp "\\)?" "\\)?")
814"Regular expression matching a Tramp file name between prefix and postfix.")
815
00d6fd04 816(defconst tramp-file-name-structure
16674e4f
KG
817 (list
818 (concat
819 tramp-prefix-regexp
2fe4b125
MA
820 "\\(" "\\(?:" tramp-remote-file-name-spec-regexp
821 tramp-postfix-hop-regexp "\\)+" "\\)?"
822 tramp-remote-file-name-spec-regexp tramp-postfix-host-regexp
00d6fd04 823 "\\(" tramp-localname-regexp "\\)")
2fe4b125
MA
824 5 6 7 8 1)
825 "List of six elements (REGEXP METHOD USER HOST FILE HOP), detailing \
a4aeb9a4 826the Tramp file name structure.
fb7933a3 827
a4aeb9a4 828The first element REGEXP is a regular expression matching a Tramp file
fb7933a3
KG
829name. The regex should contain parentheses around the method name,
830the user name, the host name, and the file name parts.
831
832The second element METHOD is a number, saying which pair of
833parentheses matches the method name. The third element USER is
834similar, but for the user name. The fourth element HOST is similar,
835but for the host name. The fifth element FILE is for the file name.
2fe4b125
MA
836The last element HOP is the ad-hoc hop definition, which could be a
837cascade of several hops.
838
fb7933a3
KG
839These numbers are passed directly to `match-string', which see. That
840means the opening parentheses are counted to identify the pair.
841
00d6fd04 842See also `tramp-file-name-regexp'.")
fb7933a3
KG
843
844;;;###autoload
505edaeb 845(defconst tramp-file-name-regexp-unified
1eb5ca1c 846 (if (memq system-type '(cygwin windows-nt))
2fe4b125
MA
847 "\\`/\\([^[/|:]\\{2,\\}\\|[^/|]\\{2,\\}]\\):"
848 "\\`/\\([^[/|:]+\\|[^/|]+]\\):")
505edaeb
KG
849 "Value for `tramp-file-name-regexp' for unified remoting.
850Emacs (not XEmacs) uses a unified filename syntax for Ange-FTP and
1eb5ca1c
MA
851Tramp. See `tramp-file-name-structure' for more explanations.
852
853On W32 systems, the volume letter must be ignored.")
505edaeb
KG
854
855;;;###autoload
03c1ad43 856(defconst tramp-file-name-regexp-separate "\\`/\\[.*\\]"
505edaeb
KG
857 "Value for `tramp-file-name-regexp' for separate remoting.
858XEmacs uses a separate filename syntax for Tramp and EFS.
00d6fd04 859See `tramp-file-name-structure' for more explanations.")
505edaeb
KG
860
861;;;###autoload
2fe4b125 862(defconst tramp-file-name-regexp-url "\\`/[^/|:]+://"
00d6fd04
MA
863 "Value for `tramp-file-name-regexp' for URL-like remoting.
864See `tramp-file-name-structure' for more explanations.")
865
866;;;###autoload
867(defconst tramp-file-name-regexp
868 (cond ((equal tramp-syntax 'ftp) tramp-file-name-regexp-unified)
869 ((equal tramp-syntax 'sep) tramp-file-name-regexp-separate)
870 ((equal tramp-syntax 'url) tramp-file-name-regexp-url)
871 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 872 "Regular expression matching file names handled by Tramp.
a4aeb9a4 873This regexp should match Tramp file names but no other file names.
b533bc97 874When tramp.el is loaded, this regular expression is prepended to
fb7933a3 875`file-name-handler-alist', and that is searched sequentially. Thus,
a4aeb9a4
MA
876if the Tramp entry appears rather early in the `file-name-handler-alist'
877and is a bit too general, then some files might be considered Tramp
00d6fd04 878files which are not really Tramp files.
fb7933a3
KG
879
880Please note that the entry in `file-name-handler-alist' is made when
b533bc97 881this file \(tramp.el\) is loaded. This means that this variable must be set
fb7933a3
KG
882before loading tramp.el. Alternatively, `file-name-handler-alist' can be
883updated after changing this variable.
884
00d6fd04 885Also see `tramp-file-name-structure'.")
fb7933a3 886
8a798e41
MA
887;;;###autoload
888(defconst tramp-completion-file-name-regexp-unified
1eb5ca1c 889 (if (memq system-type '(cygwin windows-nt))
5bc3b51d 890 "\\`/[^/]\\{2,\\}\\'" "\\`/[^/]*\\'")
16674e4f 891 "Value for `tramp-completion-file-name-regexp' for unified remoting.
8a798e41 892GNU Emacs uses a unified filename syntax for Tramp and Ange-FTP.
1eb5ca1c
MA
893See `tramp-file-name-structure' for more explanations.
894
895On W32 systems, the volume letter must be ignored.")
fb7933a3 896
16674e4f
KG
897;;;###autoload
898(defconst tramp-completion-file-name-regexp-separate
5bc3b51d 899 "\\`/\\([[][^]]*\\)?\\'"
16674e4f
KG
900 "Value for `tramp-completion-file-name-regexp' for separate remoting.
901XEmacs uses a separate filename syntax for Tramp and EFS.
00d6fd04 902See `tramp-file-name-structure' for more explanations.")
fb7933a3 903
16674e4f 904;;;###autoload
00d6fd04 905(defconst tramp-completion-file-name-regexp-url
5bc3b51d 906 "\\`/[^/:]+\\(:\\(/\\(/[^/]*\\)?\\)?\\)?\\'"
00d6fd04
MA
907 "Value for `tramp-completion-file-name-regexp' for URL-like remoting.
908See `tramp-file-name-structure' for more explanations.")
909
910;;;###autoload
911(defconst tramp-completion-file-name-regexp
912 (cond ((equal tramp-syntax 'ftp) tramp-completion-file-name-regexp-unified)
913 ((equal tramp-syntax 'sep) tramp-completion-file-name-regexp-separate)
914 ((equal tramp-syntax 'url) tramp-completion-file-name-regexp-url)
915 (t (error "Wrong `tramp-syntax' defined")))
fb7ada5f 916 "Regular expression matching file names handled by Tramp completion.
a4aeb9a4 917This regexp should match partial Tramp file names only.
16674e4f
KG
918
919Please note that the entry in `file-name-handler-alist' is made when
920this file (tramp.el) is loaded. This means that this variable must be set
921before loading tramp.el. Alternatively, `file-name-handler-alist' can be
922updated after changing this variable.
923
00d6fd04 924Also see `tramp-file-name-structure'.")
fb7933a3 925
00d6fd04 926;; Chunked sending kludge. We set this to 500 for black-listed constellations
7432277c 927;; known to have a bug in `process-send-string'; some ssh connections appear
7177e2a3
MA
928;; to drop bytes when data is sent too quickly. There is also a connection
929;; buffer local variable, which is computed depending on remote host properties
930;; when `tramp-chunksize' is zero or nil.
7432277c
KG
931(defcustom tramp-chunksize
932 (when (and (not (featurep 'xemacs))
933 (memq system-type '(hpux)))
934 500)
55880756
MA
935;; Parentheses in docstring starting at beginning of line are escaped.
936;; Fontification is messed up when
937;; `open-paren-in-column-0-is-defun-start' set to t.
fb7ada5f 938 "If non-nil, chunksize for sending input to local process.
7432277c
KG
939It is necessary only on systems which have a buggy `process-send-string'
940implementation. The necessity, whether this variable must be set, can be
941checked via the following code:
942
943 (with-temp-buffer
11948172
MA
944 (let* ((user \"xxx\") (host \"yyy\")
945 (init 0) (step 50)
946 (sent init) (received init))
947 (while (= sent received)
948 (setq sent (+ sent step))
949 (erase-buffer)
950 (let ((proc (start-process (buffer-name) (current-buffer)
951 \"ssh\" \"-l\" user host \"wc\" \"-c\")))
952 (when (memq (process-status proc) '(run open))
953 (process-send-string proc (make-string sent ?\\ ))
954 (process-send-eof proc)
955 (process-send-eof proc))
956 (while (not (progn (goto-char (point-min))
957 (re-search-forward \"\\\\w+\" (point-max) t)))
958 (accept-process-output proc 1))
959 (when (memq (process-status proc) '(run open))
960 (setq received (string-to-number (match-string 0)))
961 (delete-process proc)
962 (message \"Bytes sent: %s\\tBytes received: %s\" sent received)
963 (sit-for 0))))
964 (if (> sent (+ init step))
965 (message \"You should set `tramp-chunksize' to a maximum of %s\"
966 (- sent step))
967 (message \"Test does not work\")
968 (display-buffer (current-buffer))
969 (sit-for 30))))
970
971In the Emacs normally running Tramp, evaluate the above code
55880756 972\(replace \"xxx\" and \"yyy\" by the remote user and host name,
b533bc97 973respectively\). You can do this, for example, by pasting it into
11948172
MA
974the `*scratch*' buffer and then hitting C-j with the cursor after the
975last closing parenthesis. Note that it works only if you have configured
b533bc97 976\"ssh\" to run without password query, see ssh-agent\(1\).
11948172
MA
977
978You will see the number of bytes sent successfully to the remote host.
979If that number exceeds 1000, you can stop the execution by hitting
980C-g, because your Emacs is likely clean.
981
11948172 982When it is necessary to set `tramp-chunksize', you might consider to
b533bc97
MA
983use an out-of-the-band method \(like \"scp\"\) instead of an internal one
984\(like \"ssh\"\), because setting `tramp-chunksize' to non-nil decreases
11948172 985performance.
c951aecb 986
00d6fd04
MA
987If your Emacs is buggy, the code stops and gives you an indication
988about the value `tramp-chunksize' should be set. Maybe you could just
989experiment a bit, e.g. changing the values of `init' and `step'
990in the third line of the code.
991
7432277c
KG
992Please raise a bug report via \"M-x tramp-bug\" if your system needs
993this variable to be set as well."
994 :group 'tramp
b1a2b924 995 :type '(choice (const nil) integer))
7432277c 996
5ec2cc41
KG
997;; Logging in to a remote host normally requires obtaining a pty. But
998;; Emacs on MacOS X has process-connection-type set to nil by default,
999;; so on those systems Tramp doesn't obtain a pty. Here, we allow
1000;; for an override of the system default.
1001(defcustom tramp-process-connection-type t
1002 "Overrides `process-connection-type' for connections from Tramp.
1003Tramp binds process-connection-type to the value given here before
1004opening a connection to a remote host."
1005 :group 'tramp
1006 :type '(choice (const nil) (const t) (const pty)))
1007
b50dd0d2
MA
1008(defcustom tramp-completion-reread-directory-timeout 10
1009 "Defines seconds since last remote command before rereading a directory.
1010A remote directory might have changed its contents. In order to
1011make it visible during file name completion in the minibuffer,
1012Tramp flushes its cache and rereads the directory contents when
1013more than `tramp-completion-reread-directory-timeout' seconds
4bc3c53d
MA
1014have been gone since last remote command execution. A value of `t'
1015would require an immediate reread during filename completion, `nil'
b50dd0d2
MA
1016means to use always cached values for the directory contents."
1017 :group 'tramp
1018 :type '(choice (const nil) integer))
1019
fb7933a3
KG
1020;;; Internal Variables:
1021
fb7933a3 1022(defvar tramp-current-method nil
00d6fd04 1023 "Connection method for this *tramp* buffer.")
fb7933a3
KG
1024
1025(defvar tramp-current-user nil
00d6fd04 1026 "Remote login name for this *tramp* buffer.")
fb7933a3
KG
1027
1028(defvar tramp-current-host nil
00d6fd04
MA
1029 "Remote host for this *tramp* buffer.")
1030
a01b1e22 1031;;;###autoload
16674e4f 1032(defconst tramp-completion-file-name-handler-alist
a01b1e22 1033 '((file-name-all-completions . tramp-completion-handle-file-name-all-completions)
41c8e348 1034 (file-name-completion . tramp-completion-handle-file-name-completion))
16674e4f 1035 "Alist of completion handler functions.
03c1ad43
MA
1036Used for file names matching `tramp-file-name-regexp'. Operations
1037not mentioned here will be handled by Tramp's file name handler
1038functions, or the normal Emacs functions.")
16674e4f 1039
4007ba5b 1040;; Handlers for foreign methods, like FTP or SMB, shall be plugged here.
0f34aa77 1041;;;###tramp-autoload
03c1ad43 1042(defvar tramp-foreign-file-name-handler-alist nil
4007ba5b
KG
1043 "Alist of elements (FUNCTION . HANDLER) for foreign methods handled specially.
1044If (FUNCTION FILENAME) returns non-nil, then all I/O on that file is done by
1045calling HANDLER.")
1046
0664ff72 1047;;; Internal functions which must come first:
fb7933a3 1048
0f34aa77
MA
1049;; Conversion functions between external representation and
1050;; internal data structure. Convenience functions for internal
1051;; data structure.
1052
2fe4b125
MA
1053(defun tramp-get-method-parameter (method param)
1054 "Return the method parameter PARAM.
1055If the `tramp-methods' entry does not exist, return nil."
1056 (let ((entry (assoc param (assoc method tramp-methods))))
1057 (when entry (cadr entry))))
1058
0f34aa77
MA
1059(defun tramp-file-name-p (vec)
1060 "Check, whether VEC is a Tramp object."
2fe4b125 1061 (and (vectorp vec) (= 5 (length vec))))
0f34aa77
MA
1062
1063(defun tramp-file-name-method (vec)
1064 "Return method component of VEC."
1065 (and (tramp-file-name-p vec) (aref vec 0)))
1066
1067(defun tramp-file-name-user (vec)
1068 "Return user component of VEC."
1069 (and (tramp-file-name-p vec) (aref vec 1)))
1070
1071(defun tramp-file-name-host (vec)
1072 "Return host component of VEC."
1073 (and (tramp-file-name-p vec) (aref vec 2)))
1074
1075(defun tramp-file-name-localname (vec)
1076 "Return localname component of VEC."
1077 (and (tramp-file-name-p vec) (aref vec 3)))
1078
2fe4b125
MA
1079(defun tramp-file-name-hop (vec)
1080 "Return hop component of VEC."
1081 (and (tramp-file-name-p vec) (aref vec 4)))
1082
0f34aa77
MA
1083;; The user part of a Tramp file name vector can be of kind
1084;; "user%domain". Sometimes, we must extract these parts.
1085(defun tramp-file-name-real-user (vec)
1086 "Return the user name of VEC without domain."
1087 (save-match-data
1088 (let ((user (tramp-file-name-user vec)))
1089 (if (and (stringp user)
1090 (string-match tramp-user-with-domain-regexp user))
1091 (match-string 1 user)
1092 user))))
1093
1094(defun tramp-file-name-domain (vec)
1095 "Return the domain name of VEC."
1096 (save-match-data
1097 (let ((user (tramp-file-name-user vec)))
1098 (and (stringp user)
1099 (string-match tramp-user-with-domain-regexp user)
1100 (match-string 2 user)))))
1101
1102;; The host part of a Tramp file name vector can be of kind
1103;; "host#port". Sometimes, we must extract these parts.
1104(defun tramp-file-name-real-host (vec)
1105 "Return the host name of VEC without port."
1106 (save-match-data
1107 (let ((host (tramp-file-name-host vec)))
1108 (if (and (stringp host)
1109 (string-match tramp-host-with-port-regexp host))
1110 (match-string 1 host)
1111 host))))
1112
1113(defun tramp-file-name-port (vec)
1114 "Return the port number of VEC."
1115 (save-match-data
66feec8b
MA
1116 (let ((method (tramp-file-name-method vec))
1117 (host (tramp-file-name-host vec)))
1118 (or (and (stringp host)
1119 (string-match tramp-host-with-port-regexp host)
1120 (string-to-number (match-string 2 host)))
1121 (tramp-get-method-parameter method 'tramp-default-port)))))
0f34aa77
MA
1122
1123;;;###tramp-autoload
1124(defun tramp-tramp-file-p (name)
1125 "Return t if NAME is a string with Tramp file name syntax."
1126 (save-match-data
1127 (and (stringp name) (string-match tramp-file-name-regexp name))))
1128
1129(defun tramp-find-method (method user host)
1130 "Return the right method string to use.
1131This is METHOD, if non-nil. Otherwise, do a lookup in
1132`tramp-default-method-alist'."
1133 (or method
1134 (let ((choices tramp-default-method-alist)
1135 lmethod item)
1136 (while choices
1137 (setq item (pop choices))
1138 (when (and (string-match (or (nth 0 item) "") (or host ""))
1139 (string-match (or (nth 1 item) "") (or user "")))
1140 (setq lmethod (nth 2 item))
1141 (setq choices nil)))
1142 lmethod)
1143 tramp-default-method))
1144
1145(defun tramp-find-user (method user host)
1146 "Return the right user string to use.
1147This is USER, if non-nil. Otherwise, do a lookup in
1148`tramp-default-user-alist'."
1149 (or user
1150 (let ((choices tramp-default-user-alist)
1151 luser item)
1152 (while choices
1153 (setq item (pop choices))
1154 (when (and (string-match (or (nth 0 item) "") (or method ""))
1155 (string-match (or (nth 1 item) "") (or host "")))
1156 (setq luser (nth 2 item))
1157 (setq choices nil)))
1158 luser)
1159 tramp-default-user))
1160
1161(defun tramp-find-host (method user host)
1162 "Return the right host string to use.
1163This is HOST, if non-nil. Otherwise, it is `tramp-default-host'."
1164 (or (and (> (length host) 0) host)
1165 tramp-default-host))
1166
1167(defun tramp-dissect-file-name (name &optional nodefault)
1168 "Return a `tramp-file-name' structure.
1169The structure consists of remote method, remote user, remote host
1170and localname (file name on remote host). If NODEFAULT is
1171non-nil, the file name parts are not expanded to their default
1172values."
1173 (save-match-data
1174 (let ((match (string-match (nth 0 tramp-file-name-structure) name)))
1175 (unless match (error "Not a Tramp file name: %s" name))
1176 (let ((method (match-string (nth 1 tramp-file-name-structure) name))
1177 (user (match-string (nth 2 tramp-file-name-structure) name))
1178 (host (match-string (nth 3 tramp-file-name-structure) name))
2fe4b125
MA
1179 (localname (match-string (nth 4 tramp-file-name-structure) name))
1180 (hop (match-string (nth 5 tramp-file-name-structure) name)))
0f34aa77
MA
1181 (when host
1182 (when (string-match tramp-prefix-ipv6-regexp host)
1183 (setq host (replace-match "" nil t host)))
1184 (when (string-match tramp-postfix-ipv6-regexp host)
1185 (setq host (replace-match "" nil t host))))
1186 (if nodefault
2fe4b125 1187 (vector method user host localname hop)
0f34aa77
MA
1188 (vector
1189 (tramp-find-method method user host)
1190 (tramp-find-user method user host)
1191 (tramp-find-host method user host)
2fe4b125 1192 localname hop))))))
0f34aa77
MA
1193
1194(defun tramp-buffer-name (vec)
1195 "A name for the connection buffer VEC."
1196 ;; We must use `tramp-file-name-real-host', because for gateway
1197 ;; methods the default port will be expanded later on, which would
1198 ;; tamper the name.
1199 (let ((method (tramp-file-name-method vec))
1200 (user (tramp-file-name-user vec))
1201 (host (tramp-file-name-real-host vec)))
1202 (if (not (zerop (length user)))
1203 (format "*tramp/%s %s@%s*" method user host)
1204 (format "*tramp/%s %s*" method host))))
1205
2fe4b125
MA
1206(defun tramp-make-tramp-file-name (method user host localname &optional hop)
1207 "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME.
1208When not nil, an optional HOP is prepended."
1209 (concat tramp-prefix-format hop
0f34aa77
MA
1210 (when (not (zerop (length method)))
1211 (concat method tramp-postfix-method-format))
1212 (when (not (zerop (length user)))
1213 (concat user tramp-postfix-user-format))
1214 (when host
1215 (if (string-match tramp-ipv6-regexp host)
1216 (concat tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
1217 host))
1218 tramp-postfix-host-format
1219 (when localname localname)))
1220
1221(defun tramp-completion-make-tramp-file-name (method user host localname)
1222 "Constructs a Tramp file name from METHOD, USER, HOST and LOCALNAME.
1223It must not be a complete Tramp file name, but as long as there are
1224necessary only. This function will be used in file name completion."
1225 (concat tramp-prefix-format
1226 (when (not (zerop (length method)))
1227 (concat method tramp-postfix-method-format))
1228 (when (not (zerop (length user)))
1229 (concat user tramp-postfix-user-format))
1230 (when (not (zerop (length host)))
1231 (concat
1232 (if (string-match tramp-ipv6-regexp host)
03c1ad43
MA
1233 (concat
1234 tramp-prefix-ipv6-format host tramp-postfix-ipv6-format)
0f34aa77
MA
1235 host)
1236 tramp-postfix-host-format))
1237 (when localname localname)))
1238
1239(defun tramp-get-buffer (vec)
1240 "Get the connection buffer to be used for VEC."
1241 (or (get-buffer (tramp-buffer-name vec))
1242 (with-current-buffer (get-buffer-create (tramp-buffer-name vec))
1243 (setq buffer-undo-list t)
1244 (setq default-directory
1245 (tramp-make-tramp-file-name
1246 (tramp-file-name-method vec)
1247 (tramp-file-name-user vec)
1248 (tramp-file-name-host vec)
1249 "/"))
1250 (current-buffer))))
1251
1252(defun tramp-get-connection-buffer (vec)
1253 "Get the connection buffer to be used for VEC.
1254In case a second asynchronous communication has been started, it is different
1255from `tramp-get-buffer'."
1256 (or (tramp-get-connection-property vec "process-buffer" nil)
1257 (tramp-get-buffer vec)))
1258
66feec8b
MA
1259(defun tramp-get-connection-name (vec)
1260 "Get the connection name to be used for VEC.
1261In case a second asynchronous communication has been started, it is different
1262from the default one."
1263 (or (tramp-get-connection-property vec "process-name" nil)
1264 (tramp-buffer-name vec)))
1265
0f34aa77
MA
1266(defun tramp-get-connection-process (vec)
1267 "Get the connection process to be used for VEC.
1268In case a second asynchronous communication has been started, it is different
1269from the default one."
66feec8b 1270 (get-process (tramp-get-connection-name vec)))
0f34aa77
MA
1271
1272(defun tramp-debug-buffer-name (vec)
1273 "A name for the debug buffer for VEC."
1274 ;; We must use `tramp-file-name-real-host', because for gateway
1275 ;; methods the default port will be expanded later on, which would
1276 ;; tamper the name.
1277 (let ((method (tramp-file-name-method vec))
1278 (user (tramp-file-name-user vec))
1279 (host (tramp-file-name-real-host vec)))
1280 (if (not (zerop (length user)))
1281 (format "*debug tramp/%s %s@%s*" method user host)
1282 (format "*debug tramp/%s %s*" method host))))
1283
1284(defconst tramp-debug-outline-regexp
03c1ad43
MA
1285 "[0-9]+:[0-9]+:[0-9]+\\.[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #"
1286 "Used for highlighting Tramp debug buffers in `outline-mode'.")
1287
1288(defun tramp-debug-outline-level ()
1289 "Return the depth to which a statement is nested in the outline.
1290Point must be at the beginning of a header line.
1291
1292The outline level is equal to the verbosity of the Tramp message."
1293 (1+ (string-to-number (match-string 1))))
0f34aa77
MA
1294
1295(defun tramp-get-debug-buffer (vec)
1296 "Get the debug buffer for VEC."
1297 (with-current-buffer
1298 (get-buffer-create (tramp-debug-buffer-name vec))
1299 (when (bobp)
1300 (setq buffer-undo-list t)
1301 ;; Activate `outline-mode'. This runs `text-mode-hook' and
1302 ;; `outline-mode-hook'. We must prevent that local processes
1303 ;; die. Yes: I've seen `flyspell-mode', which starts "ispell".
1304 ;; Furthermore, `outline-regexp' must have the correct value
1305 ;; already, because it is used by `font-lock-compile-keywords'.
1306 (let ((default-directory (tramp-compat-temporary-file-directory))
1307 (outline-regexp tramp-debug-outline-regexp))
1308 (outline-mode))
1309 (set (make-local-variable 'outline-regexp) tramp-debug-outline-regexp)
03c1ad43 1310 (set (make-local-variable 'outline-level) 'tramp-debug-outline-level))
0f34aa77
MA
1311 (current-buffer)))
1312
00d6fd04
MA
1313(defsubst tramp-debug-message (vec fmt-string &rest args)
1314 "Append message to debug buffer.
1315Message is formatted with FMT-STRING as control string and the remaining
1316ARGS to actually emit the message (if applicable)."
1317 (when (get-buffer (tramp-buffer-name vec))
1318 (with-current-buffer (tramp-get-debug-buffer vec)
1319 (goto-char (point-max))
70c11b0b
MA
1320 ;; Headline.
1321 (when (bobp)
1322 (insert
1323 (format
1324 ";; %sEmacs: %s Tramp: %s -*- mode: outline; -*-"
1325 (if (featurep 'sxemacs) "SX" (if (featurep 'xemacs) "X" "GNU "))
1326 emacs-version tramp-version)))
00d6fd04
MA
1327 (unless (bolp)
1328 (insert "\n"))
70c11b0b 1329 ;; Timestamp.
736ac90f
MA
1330 (let ((now (current-time)))
1331 (insert (format-time-string "%T." now))
1332 (insert (format "%06d " (nth 2 now))))
56761182
MA
1333 ;; Calling Tramp function. We suppress compat and trace
1334 ;; functions from being displayed.
00d6fd04
MA
1335 (let ((btn 1) btf fn)
1336 (while (not fn)
1337 (setq btf (nth 1 (backtrace-frame btn)))
1338 (if (not btf)
1339 (setq fn "")
1340 (when (symbolp btf)
1341 (setq fn (symbol-name btf))
56761182
MA
1342 (unless
1343 (and
1344 (string-match "^tramp" fn)
1345 (not
1346 (string-match
1347 (concat
1348 "^"
1349 (regexp-opt
1350 '("tramp-compat-funcall"
1351 "tramp-compat-with-temp-message"
1352 "tramp-debug-message"
1353 "tramp-error"
1354 "tramp-error-with-buffer"
def722bf
MA
1355 "tramp-message"
1356 "tramp-with-progress-reporter")
56761182
MA
1357 t)
1358 "$")
1359 fn)))
00d6fd04
MA
1360 (setq fn nil)))
1361 (setq btn (1+ btn))))
1362 ;; The following code inserts filename and line number.
e9a452d9 1363 ;; Should be inactive by default, because it is time
00d6fd04
MA
1364 ;; consuming.
1365; (let ((ffn (find-function-noselect (intern fn))))
1366; (insert
1367; (format
1368; "%s:%d: "
1369; (file-name-nondirectory (buffer-file-name (car ffn)))
1370; (with-current-buffer (car ffn)
1371; (1+ (count-lines (point-min) (cdr ffn)))))))
1372 (insert (format "%s " fn)))
70c11b0b 1373 ;; The message.
00d6fd04
MA
1374 (insert (apply 'format fmt-string args)))))
1375
946a5aeb
MA
1376(defvar tramp-message-show-message t
1377 "Show Tramp message in the minibuffer.
1378This variable is used to disable messages from `tramp-error'.
1379The messages are visible anyway, because an error is raised.")
1380
2fe4b125
MA
1381(defvar tramp-message-show-progress-reporter-message t
1382 "Show Tramp progress reporter message in the minibuffer.
48d1354e 1383This variable is used to disable recursive progress reporter messages.")
2fe4b125 1384
00d6fd04 1385(defsubst tramp-message (vec-or-proc level fmt-string &rest args)
fb7933a3 1386 "Emit a message depending on verbosity level.
a4aeb9a4 1387VEC-OR-PROC identifies the Tramp buffer to use. It can be either a
00d6fd04
MA
1388vector or a process. LEVEL says to be quiet if `tramp-verbose' is
1389less than LEVEL. The message is emitted only if `tramp-verbose' is
1390greater than or equal to LEVEL.
1391
1392The message is also logged into the debug buffer when `tramp-verbose'
1393is greater than or equal 4.
1394
1395Calls functions `message' and `tramp-debug-message' with FMT-STRING as
1396control string and the remaining ARGS to actually emit the message (if
1397applicable)."
03c1ad43
MA
1398 (ignore-errors
1399 (when (<= level tramp-verbose)
1400 ;; Match data must be preserved!
1401 (save-match-data
1402 ;; Display only when there is a minimum level.
1403 (when (and tramp-message-show-message (<= level 3))
1404 (apply 'message
1405 (concat
1406 (cond
1407 ((= level 0) "")
1408 ((= level 1) "")
1409 ((= level 2) "Warning: ")
1410 (t "Tramp: "))
1411 fmt-string)
1412 args))
1413 ;; Log only when there is a minimum level.
1414 (when (>= tramp-verbose 4)
1415 (when (and vec-or-proc
1416 (processp vec-or-proc)
1417 (buffer-name (process-buffer vec-or-proc)))
1418 (with-current-buffer (process-buffer vec-or-proc)
1419 ;; Translate proc to vec.
1420 (setq vec-or-proc (tramp-dissect-file-name default-directory))))
1421 (when (and vec-or-proc (vectorp vec-or-proc))
1422 (apply 'tramp-debug-message
1423 vec-or-proc
1424 (concat (format "(%d) # " level) fmt-string)
1425 args)))))))
00d6fd04
MA
1426
1427(defsubst tramp-error (vec-or-proc signal fmt-string &rest args)
1428 "Emit an error.
1429VEC-OR-PROC identifies the connection to use, SIGNAL is the
1430signal identifier to be raised, remaining args passed to
1431`tramp-message'. Finally, signal SIGNAL is raised."
946a5aeb
MA
1432 (let (tramp-message-show-message)
1433 (tramp-message
1434 vec-or-proc 1 "%s"
1435 (error-message-string
1436 (list signal
1437 (get signal 'error-message)
1438 (apply 'format fmt-string args))))
1439 (signal signal (list (apply 'format fmt-string args)))))
00d6fd04
MA
1440
1441(defsubst tramp-error-with-buffer
1442 (buffer vec-or-proc signal fmt-string &rest args)
1443 "Emit an error, and show BUFFER.
1444If BUFFER is nil, show the connection buffer. Wait for 30\", or until
1445an input event arrives. The other arguments are passed to `tramp-error'."
1446 (save-window-excursion
1447 (unwind-protect
1448 (apply 'tramp-error vec-or-proc signal fmt-string args)
4874f5e6 1449 (when (and vec-or-proc
2fe4b125 1450 tramp-message-show-message
4874f5e6
MA
1451 (not (zerop tramp-verbose))
1452 (not (tramp-completion-mode-p)))
00d6fd04
MA
1453 (let ((enable-recursive-minibuffers t))
1454 (pop-to-buffer
1455 (or (and (bufferp buffer) buffer)
1456 (and (processp vec-or-proc) (process-buffer vec-or-proc))
2fe4b125 1457 (tramp-get-connection-buffer vec-or-proc)))
00d6fd04 1458 (sit-for 30))))))
fb7933a3 1459
c62c9d08
KG
1460(defmacro with-parsed-tramp-file-name (filename var &rest body)
1461 "Parse a Tramp filename and make components available in the body.
1462
1463First arg FILENAME is evaluated and dissected into its components.
1464Second arg VAR is a symbol. It is used as a variable name to hold
1465the filename structure. It is also used as a prefix for the variables
1466holding the components. For example, if VAR is the symbol `foo', then
00d6fd04 1467`foo' will be bound to the whole structure, `foo-method' will be bound to
2fe4b125
MA
1468the method component, and so on for `foo-user', `foo-host', `foo-localname',
1469`foo-hop'.
c62c9d08
KG
1470
1471Remaining args are Lisp expressions to be evaluated (inside an implicit
1472`progn').
1473
00d6fd04 1474If VAR is nil, then we bind `v' to the structure and `method', `user',
2fe4b125 1475`host', `localname', `hop' to the components."
c62c9d08 1476 `(let* ((,(or var 'v) (tramp-dissect-file-name ,filename))
c62c9d08
KG
1477 (,(if var (intern (concat (symbol-name var) "-method")) 'method)
1478 (tramp-file-name-method ,(or var 'v)))
1479 (,(if var (intern (concat (symbol-name var) "-user")) 'user)
1480 (tramp-file-name-user ,(or var 'v)))
1481 (,(if var (intern (concat (symbol-name var) "-host")) 'host)
1482 (tramp-file-name-host ,(or var 'v)))
7432277c 1483 (,(if var (intern (concat (symbol-name var) "-localname")) 'localname)
2fe4b125
MA
1484 (tramp-file-name-localname ,(or var 'v)))
1485 (,(if var (intern (concat (symbol-name var) "-hop")) 'hop)
1486 (tramp-file-name-hop ,(or var 'v))))
c62c9d08
KG
1487 ,@body))
1488
1489(put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
00d6fd04 1490(put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
6139f995
MA
1491(tramp-compat-font-lock-add-keywords
1492 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
00d6fd04 1493
9e021389
MA
1494(defun tramp-progress-reporter-update (reporter &optional value)
1495 (let* ((parameters (cdr reporter))
1496 (message (aref parameters 3)))
1497 (when (string-match message (or (current-message) ""))
6139f995 1498 (tramp-compat-funcall 'progress-reporter-update reporter value))))
9e021389 1499
7d520089 1500(defmacro tramp-with-progress-reporter (vec level message &rest body)
b6827fff
MA
1501 "Executes BODY, spinning a progress reporter with MESSAGE.
1502If LEVEL does not fit for visible messages, or if this is a
1503nested call of the macro, there are only traces without a visible
1504progress reporter."
7d520089 1505 (declare (indent 3) (debug t))
a94d821f
MA
1506 `(let (pr tm)
1507 (tramp-message ,vec ,level "%s..." ,message)
1508 ;; We start a pulsing progress reporter after 3 seconds. Feature
1509 ;; introduced in Emacs 24.1.
2fe4b125
MA
1510 (when (and tramp-message-show-progress-reporter-message
1511 tramp-message-show-message
3b30ccda
MA
1512 ;; Display only when there is a minimum level.
1513 (<= ,level (min tramp-verbose 3)))
03c1ad43
MA
1514 (ignore-errors
1515 (setq pr (tramp-compat-funcall 'make-progress-reporter ,message)
1516 tm (when pr
1517 (run-at-time 3 0.1 'tramp-progress-reporter-update pr)))))
a94d821f 1518 (unwind-protect
2fe4b125
MA
1519 ;; Execute the body. Suppress concurrent progress reporter
1520 ;; messages.
1521 (let ((tramp-message-show-progress-reporter-message
1522 (and tramp-message-show-progress-reporter-message (not tm))))
3b30ccda 1523 ,@body)
a94d821f 1524 ;; Stop progress reporter.
0d5852cf 1525 (if tm (tramp-compat-funcall 'cancel-timer tm))
a94d821f
MA
1526 (tramp-message ,vec ,level "%s...done" ,message))))
1527
6139f995 1528(tramp-compat-font-lock-add-keywords
7d520089 1529 'emacs-lisp-mode '("\\<tramp-with-progress-reporter\\>"))
a94d821f 1530
5bc3b51d 1531(defalias 'tramp-drop-volume-letter
628c97b2 1532 (if (memq system-type '(cygwin windows-nt))
5bc3b51d 1533 (lambda (name)
628c97b2 1534 "Cut off unnecessary drive letter from file NAME.
66feec8b 1535The functions `tramp-*-handle-expand-file-name' call `expand-file-name'
628c97b2
GM
1536locally on a remote file name. When the local system is a W32 system
1537but the remote system is Unix, this introduces a superfluous drive
1538letter into the file name. This function removes it."
1539 (save-match-data
5bc3b51d 1540 (if (string-match "\\`[a-zA-Z]:/" name)
628c97b2
GM
1541 (replace-match "/" nil t name)
1542 name)))
1543
5bc3b51d 1544 'identity))
628c97b2 1545
957b3189
MA
1546(if (featurep 'xemacs)
1547 (defalias 'tramp-drop-volume-letter 'identity))
1548
2fe4b125
MA
1549(defun tramp-cleanup (vec)
1550 "Cleanup connection VEC, but keep the debug buffer."
1551 (with-current-buffer (tramp-get-debug-buffer vec)
1552 ;; Keep the debug buffer.
1553 (rename-buffer
1554 (generate-new-buffer-name tramp-temp-buffer-name) 'unique)
1555 (tramp-cleanup-connection vec)
1556 (if (= (point-min) (point-max))
1557 (kill-buffer nil)
1558 (rename-buffer (tramp-debug-buffer-name vec) 'unique))
1559 ;; We call `tramp-get-buffer' in order to keep the debug buffer.
1560 (tramp-get-buffer vec)))
1561
16674e4f
KG
1562;;; Config Manipulation Functions:
1563
f8f91c2b 1564;;;###tramp-autoload
16674e4f
KG
1565(defun tramp-set-completion-function (method function-list)
1566 "Sets the list of completion functions for METHOD.
1567FUNCTION-LIST is a list of entries of the form (FUNCTION FILE).
1568The FUNCTION is intended to parse FILE according its syntax.
1569It might be a predefined FUNCTION, or a user defined FUNCTION.
2fe4b125 1570For the list of predefined FUNCTIONs see `tramp-completion-function-alist'.
8daea7fc 1571
16674e4f
KG
1572Example:
1573
1574 (tramp-set-completion-function
1575 \"ssh\"
8daea7fc
KG
1576 '((tramp-parse-sconfig \"/etc/ssh_config\")
1577 (tramp-parse-sconfig \"~/.ssh/config\")))"
16674e4f 1578
5ec2cc41
KG
1579 (let ((r function-list)
1580 (v function-list))
1581 (setq tramp-completion-function-alist
1582 (delete (assoc method tramp-completion-function-alist)
1583 tramp-completion-function-alist))
1584
1585 (while v
00d6fd04 1586 ;; Remove double entries.
5ec2cc41
KG
1587 (when (member (car v) (cdr v))
1588 (setcdr v (delete (car v) (cdr v))))
00d6fd04 1589 ;; Check for function and file or registry key.
5ec2cc41 1590 (unless (and (functionp (nth 0 (car v)))
00d6fd04
MA
1591 (if (string-match "^HKEY_CURRENT_USER" (nth 1 (car v)))
1592 ;; Windows registry.
1593 (and (memq system-type '(cygwin windows-nt))
a4aeb9a4 1594 (zerop
0f34aa77 1595 (tramp-compat-call-process
a4aeb9a4 1596 "reg" nil nil nil "query" (nth 1 (car v)))))
00d6fd04
MA
1597 ;; Configuration file.
1598 (file-exists-p (nth 1 (car v)))))
5ec2cc41
KG
1599 (setq r (delete (car v) r)))
1600 (setq v (cdr v)))
1601
1602 (when r
4007ba5b 1603 (add-to-list 'tramp-completion-function-alist
5ec2cc41 1604 (cons method r)))))
16674e4f
KG
1605
1606(defun tramp-get-completion-function (method)
00d6fd04 1607 "Returns a list of completion functions for METHOD.
16674e4f 1608For definition of that list see `tramp-set-completion-function'."
00d6fd04
MA
1609 (cons
1610 ;; Hosts visited once shall be remembered.
1611 `(tramp-parse-connection-properties ,method)
1612 ;; The method related defaults.
1613 (cdr (assoc method tramp-completion-function-alist))))
16674e4f 1614
d037d501 1615
0664ff72 1616;;; Fontification of `read-file-name':
d037d501 1617
0664ff72 1618;; rfn-eshadow.el is part of Emacs 22. It is autoloaded.
d037d501
MA
1619(defvar tramp-rfn-eshadow-overlay)
1620(make-variable-buffer-local 'tramp-rfn-eshadow-overlay)
1621
1622(defun tramp-rfn-eshadow-setup-minibuffer ()
1623 "Set up a minibuffer for `file-name-shadow-mode'.
1624Adds another overlay hiding filename parts according to Tramp's
1625special handling of `substitute-in-file-name'."
9ce8462a 1626 (when (symbol-value 'minibuffer-completing-file-name)
d037d501 1627 (setq tramp-rfn-eshadow-overlay
0d5852cf
MA
1628 (tramp-compat-funcall
1629 'make-overlay
1630 (tramp-compat-funcall 'minibuffer-prompt-end)
1631 (tramp-compat-funcall 'minibuffer-prompt-end)))
d037d501 1632 ;; Copy rfn-eshadow-overlay properties.
0d5852cf
MA
1633 (let ((props (tramp-compat-funcall
1634 'overlay-properties (symbol-value 'rfn-eshadow-overlay))))
d037d501 1635 (while props
c6309045
MA
1636 ;; The `field' property prevents correct minibuffer
1637 ;; completion; we exclude it.
1638 (if (not (eq (car props) 'field))
1639 (tramp-compat-funcall
1640 'overlay-put tramp-rfn-eshadow-overlay (pop props) (pop props))
1641 (pop props) (pop props))))))
d037d501
MA
1642
1643(when (boundp 'rfn-eshadow-setup-minibuffer-hook)
1644 (add-hook 'rfn-eshadow-setup-minibuffer-hook
48846dc5
MA
1645 'tramp-rfn-eshadow-setup-minibuffer)
1646 (add-hook 'tramp-unload-hook
aa485f7c
MA
1647 (lambda ()
1648 (remove-hook 'rfn-eshadow-setup-minibuffer-hook
1649 'tramp-rfn-eshadow-setup-minibuffer))))
d037d501 1650
adcbca53
MA
1651(defconst tramp-rfn-eshadow-update-overlay-regexp
1652 (format "[^%s/~]*\\(/\\|~\\)" tramp-postfix-host-format))
1653
d037d501
MA
1654(defun tramp-rfn-eshadow-update-overlay ()
1655 "Update `rfn-eshadow-overlay' to cover shadowed part of minibuffer input.
1656This is intended to be used as a minibuffer `post-command-hook' for
1657`file-name-shadow-mode'; the minibuffer should have already
1658been set up by `rfn-eshadow-setup-minibuffer'."
1659 ;; In remote files name, there is a shadowing just for the local part.
28dbc92f
MA
1660 (ignore-errors
1661 (let ((end (or (tramp-compat-funcall
1662 'overlay-end (symbol-value 'rfn-eshadow-overlay))
2fe4b125
MA
1663 (tramp-compat-funcall 'minibuffer-prompt-end)))
1664 ;; We do not want to send any remote command.
1665 (non-essential t))
28dbc92f
MA
1666 (when
1667 (file-remote-p
1668 (tramp-compat-funcall
1669 'buffer-substring-no-properties end (point-max)))
1670 (save-excursion
1671 (save-restriction
1672 (narrow-to-region
1673 (1+ (or (string-match
1674 tramp-rfn-eshadow-update-overlay-regexp
1675 (buffer-string) end)
1676 end))
1677 (point-max))
1678 (let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
1679 (rfn-eshadow-update-overlay-hook nil)
1680 file-name-handler-alist)
1681 (tramp-compat-funcall
1682 'move-overlay rfn-eshadow-overlay (point-max) (point-max))
1683 (tramp-compat-funcall 'rfn-eshadow-update-overlay))))))))
d037d501
MA
1684
1685(when (boundp 'rfn-eshadow-update-overlay-hook)
1686 (add-hook 'rfn-eshadow-update-overlay-hook
b88f2d0a
MA
1687 'tramp-rfn-eshadow-update-overlay)
1688 (add-hook 'tramp-unload-hook
1689 (lambda ()
1690 (remove-hook 'rfn-eshadow-update-overlay-hook
1691 'tramp-rfn-eshadow-update-overlay))))
d037d501 1692
00d6fd04
MA
1693;; Inodes don't exist for some file systems. Therefore we must
1694;; generate virtual ones. Used in `find-buffer-visiting'. The method
1695;; applied might be not so efficient (Ange-FTP uses hashes). But
1696;; performance isn't the major issue given that file transfer will
1697;; take time.
530739c9 1698(defvar tramp-inodes 0
00d6fd04
MA
1699 "Keeps virtual inodes numbers.")
1700
8daea7fc
KG
1701;; Devices must distinguish physical file systems. The device numbers
1702;; provided by "lstat" aren't unique, because we operate on different hosts.
1703;; So we use virtual device numbers, generated by Tramp. Both Ange-FTP and
1704;; EFS use device number "-1". In order to be different, we use device number
b946a456 1705;; (-1 . x), whereby "x" is unique for a given (method user host).
530739c9 1706(defvar tramp-devices 0
8daea7fc
KG
1707 "Keeps virtual device numbers.")
1708
b86c1cd8
MA
1709(defun tramp-default-file-modes (filename)
1710 "Return file modes of FILENAME as integer.
1711If the file modes of FILENAME cannot be determined, return the
974647ac
MA
1712value of `default-file-modes', without execute permissions."
1713 (or (file-modes filename)
0f34aa77 1714 (logand (default-file-modes) (tramp-compat-octal-to-decimal "0666"))))
b86c1cd8 1715
c23c3394
MA
1716(defun tramp-replace-environment-variables (filename)
1717 "Replace environment variables in FILENAME.
1718Return the string with the replaced variables."
2e271195 1719 (save-match-data
ec5145d6 1720 (let ((idx (string-match "$\\(\\w+\\)" filename)))
2e271195 1721 ;; `$' is coded as `$$'.
ec5145d6
MA
1722 (when (and idx
1723 (or (zerop idx) (not (eq ?$ (aref filename (1- idx)))))
1724 (getenv (match-string 1 filename)))
2e271195
MA
1725 (setq filename
1726 (replace-match
1727 (substitute-in-file-name (match-string 0 filename))
1728 t nil filename)))
1729 filename)))
c23c3394 1730
00d6fd04
MA
1731;; In XEmacs, electricity is implemented via a key map for ?/ and ?~,
1732;; which calls corresponding functions (see minibuf.el).
1733(when (fboundp 'minibuffer-electric-separator)
9e6ab520 1734 (mapc
aa485f7c
MA
1735 (lambda (x)
1736 (eval
1737 `(defadvice ,x
1738 (around ,(intern (format "tramp-advice-%s" x)) activate)
1739 "Invoke `substitute-in-file-name' for Tramp files."
1740 (if (and (symbol-value 'minibuffer-electric-file-name-behavior)
1741 (tramp-tramp-file-p (buffer-substring)))
1742 ;; We don't need to handle `last-input-event', because
1743 ;; due to the key map we know it must be ?/ or ?~.
1744 (let ((s (concat (buffer-substring (point-min) (point))
1745 (string last-command-char))))
1746 (delete-region (point-min) (point))
1747 (insert (substitute-in-file-name s))
1748 (setq ad-return-value last-command-char))
d7ec1df7
MA
1749 ad-do-it)))
1750 (eval
1751 `(add-hook
1752 'tramp-unload-hook
1753 (lambda ()
1754 (ad-remove-advice ',x 'around ',(intern (format "tramp-advice-%s" x)))
1755 (ad-activate ',x)))))
00d6fd04
MA
1756
1757 '(minibuffer-electric-separator
1758 minibuffer-electric-tilde)))
1759
eb562962
MA
1760(defun tramp-find-file-name-coding-system-alist (filename tmpname)
1761 "Like `find-operation-coding-system' for Tramp filenames.
1762Tramp's `insert-file-contents' and `write-region' work over
1763temporary file names. If `file-coding-system-alist' contains an
1764expression, which matches more than the file name suffix, the
1765coding system might not be determined. This function repairs it."
1766 (let (result)
1767 (dolist (elt file-coding-system-alist result)
1768 (when (and (consp elt) (string-match (car elt) filename))
1769 ;; We found a matching entry in `file-coding-system-alist'.
1770 ;; So we add a similar entry, but with the temporary file name
1771 ;; as regexp.
1772 (add-to-list
1773 'result (cons (regexp-quote tmpname) (cdr elt)) 'append)))))
1774
a01b1e22
MA
1775;;;###autoload
1776(progn (defun tramp-run-real-handler (operation args)
fb7933a3 1777 "Invoke normal file name handler for OPERATION.
c62c9d08
KG
1778First arg specifies the OPERATION, second arg is a list of arguments to
1779pass to the OPERATION."
4007ba5b
KG
1780 (let* ((inhibit-file-name-handlers
1781 `(tramp-file-name-handler
946a5aeb 1782 tramp-vc-file-name-handler
4007ba5b
KG
1783 tramp-completion-file-name-handler
1784 cygwin-mount-name-hook-function
1785 cygwin-mount-map-drive-hook-function
1786 .
1787 ,(and (eq inhibit-file-name-operation operation)
1788 inhibit-file-name-handlers)))
1789 (inhibit-file-name-operation operation))
a01b1e22 1790 (apply operation args))))
16674e4f 1791
a01b1e22
MA
1792;;;###autoload
1793(progn (defun tramp-completion-run-real-handler (operation args)
16674e4f
KG
1794 "Invoke `tramp-file-name-handler' for OPERATION.
1795First arg specifies the OPERATION, second arg is a list of arguments to
1796pass to the OPERATION."
4007ba5b
KG
1797 (let* ((inhibit-file-name-handlers
1798 `(tramp-completion-file-name-handler
1799 cygwin-mount-name-hook-function
1800 cygwin-mount-map-drive-hook-function
1801 .
1802 ,(and (eq inhibit-file-name-operation operation)
1803 inhibit-file-name-handlers)))
1804 (inhibit-file-name-operation operation))
a01b1e22 1805 (apply operation args))))
fb7933a3 1806
4007ba5b
KG
1807;; We handle here all file primitives. Most of them have the file
1808;; name as first parameter; nevertheless we check for them explicitly
04bf5b65 1809;; in order to be signaled if a new primitive appears. This
4007ba5b
KG
1810;; scenario is needed because there isn't a way to decide by
1811;; syntactical means whether a foreign method must be called. It would
19a87064 1812;; ease the life if `file-name-handler-alist' would support a decision
4007ba5b
KG
1813;; function as well but regexp only.
1814(defun tramp-file-name-for-operation (operation &rest args)
1815 "Return file name related to OPERATION file primitive.
1816ARGS are the arguments OPERATION has been called with."
1817 (cond
b533bc97 1818 ;; FILE resp DIRECTORY.
4007ba5b
KG
1819 ((member operation
1820 (list 'access-file 'byte-compiler-base-file-name 'delete-directory
1821 'delete-file 'diff-latest-backup-file 'directory-file-name
1822 'directory-files 'directory-files-and-attributes
1823 'dired-compress-file 'dired-uncache
1824 'file-accessible-directory-p 'file-attributes
1825 'file-directory-p 'file-executable-p 'file-exists-p
25f14cdb 1826 'file-local-copy 'file-remote-p 'file-modes
19a87064
MA
1827 'file-name-as-directory 'file-name-directory
1828 'file-name-nondirectory 'file-name-sans-versions
1829 'file-ownership-preserved-p 'file-readable-p
1830 'file-regular-p 'file-symlink-p 'file-truename
1831 'file-writable-p 'find-backup-file-name 'find-file-noselect
1832 'get-file-buffer 'insert-directory 'insert-file-contents
1833 'load 'make-directory 'make-directory-internal
1834 'set-file-modes 'substitute-in-file-name
1835 'unhandled-file-name-directory 'vc-registered
b533bc97 1836 ;; Emacs 22+ only.
ce3f516f 1837 'set-file-times
25f14cdb
MA
1838 ;; Emacs 24+ only.
1839 'file-selinux-context 'set-file-selinux-context
b533bc97 1840 ;; XEmacs only.
4007ba5b
KG
1841 'abbreviate-file-name 'create-file-buffer
1842 'dired-file-modtime 'dired-make-compressed-filename
1843 'dired-recursive-delete-directory 'dired-set-file-modtime
1844 'dired-shell-unhandle-file-name 'dired-uucode-file
5615d63f 1845 'insert-file-contents-literally 'make-temp-name 'recover-file
4007ba5b 1846 'vm-imap-check-mail 'vm-pop-check-mail 'vm-spool-check-mail))
8daea7fc
KG
1847 (if (file-name-absolute-p (nth 0 args))
1848 (nth 0 args)
1849 (expand-file-name (nth 0 args))))
b533bc97 1850 ;; FILE DIRECTORY resp FILE1 FILE2.
4007ba5b
KG
1851 ((member operation
1852 (list 'add-name-to-file 'copy-file 'expand-file-name
1853 'file-name-all-completions 'file-name-completion
1854 'file-newer-than-file-p 'make-symbolic-link 'rename-file
b533bc97 1855 ;; Emacs 23+ only.
263c02ef 1856 'copy-directory
a3fcfa99 1857 ;; Emacs 24+ only.
2fe4b125 1858 'file-in-directory-p 'file-equal-p
b533bc97 1859 ;; XEmacs only.
4007ba5b
KG
1860 'dired-make-relative-symlink
1861 'vm-imap-move-mail 'vm-pop-move-mail 'vm-spool-move-mail))
1862 (save-match-data
1863 (cond
1864 ((string-match tramp-file-name-regexp (nth 0 args)) (nth 0 args))
1865 ((string-match tramp-file-name-regexp (nth 1 args)) (nth 1 args))
1866 (t (buffer-file-name (current-buffer))))))
b533bc97 1867 ;; START END FILE.
4007ba5b
KG
1868 ((eq operation 'write-region)
1869 (nth 2 args))
b533bc97 1870 ;; BUFFER.
4007ba5b 1871 ((member operation
00d6fd04 1872 (list 'set-visited-file-modtime 'verify-visited-file-modtime
b533bc97 1873 ;; Emacs 22+ only.
00d6fd04 1874 'make-auto-save-file-name
b533bc97 1875 ;; XEmacs only.
4007ba5b
KG
1876 'backup-buffer))
1877 (buffer-file-name
1878 (if (bufferp (nth 0 args)) (nth 0 args) (current-buffer))))
b533bc97 1879 ;; COMMAND.
4007ba5b 1880 ((member operation
b533bc97 1881 (list ;; not in Emacs 23+.
00d6fd04 1882 'dired-call-process
b533bc97 1883 ;; Emacs only.
b71c9e75 1884 'shell-command
b533bc97 1885 ;; Emacs 22+ only.
0457dd55 1886 'process-file
b533bc97 1887 ;; Emacs 23+ only.
00d6fd04 1888 'start-file-process
b533bc97 1889 ;; XEmacs only.
00d6fd04 1890 'dired-print-file 'dired-shell-call-process
b533bc97 1891 ;; nowhere yet.
b81a0b56
MA
1892 'executable-find 'start-process
1893 'call-process 'call-process-region))
4007ba5b 1894 default-directory)
b533bc97 1895 ;; Unknown file primitive.
4007ba5b
KG
1896 (t (error "unknown file I/O primitive: %s" operation))))
1897
1898(defun tramp-find-foreign-file-name-handler (filename)
1899 "Return foreign file name handler if exists."
b533bc97 1900 (when (tramp-tramp-file-p filename)
9ce8462a
MA
1901 (let ((v (tramp-dissect-file-name filename t))
1902 (handler tramp-foreign-file-name-handler-alist)
1903 elt res)
1904 ;; When we are not fully sure that filename completion is safe,
1905 ;; we should not return a handler.
1906 (when (or (tramp-file-name-method v) (tramp-file-name-user v)
1834b39f
MA
1907 (and (tramp-file-name-host v)
1908 (not (member (tramp-file-name-host v)
1909 (mapcar 'car tramp-methods))))
9ce8462a
MA
1910 (not (tramp-completion-mode-p)))
1911 (while handler
1912 (setq elt (car handler)
1913 handler (cdr handler))
1914 (when (funcall (car elt) filename)
1915 (setq handler nil
1916 res (cdr elt))))
1917 res))))
4007ba5b 1918
fb7933a3
KG
1919;; Main function.
1920;;;###autoload
1921(defun tramp-file-name-handler (operation &rest args)
ea9d1443 1922 "Invoke Tramp file name handler.
a4aeb9a4 1923Falls back to normal file name handler if no Tramp file name handler exists."
2e271195
MA
1924 (if tramp-mode
1925 (save-match-data
1926 (let* ((filename
1927 (tramp-replace-environment-variables
1928 (apply 'tramp-file-name-for-operation operation args)))
1929 (completion (tramp-completion-mode-p))
1930 (foreign (tramp-find-foreign-file-name-handler filename)))
1931 (with-parsed-tramp-file-name filename nil
4874f5e6
MA
1932 ;; Call the backend function.
1933 (if foreign
2fe4b125
MA
1934 (tramp-compat-condition-case-unless-debug err
1935 (let ((sf (symbol-function foreign))
1936 result)
11d074b2
MA
1937 ;; Some packages set the default directory to a
1938 ;; remote path, before respective Tramp packages
1939 ;; are already loaded. This results in
1940 ;; recursive loading. Therefore, we load the
1941 ;; Tramp packages locally.
1942 (when (and (listp sf) (eq (car sf) 'autoload))
1943 (let ((default-directory
1944 (tramp-compat-temporary-file-directory)))
6a80b297 1945 (load (cadr sf) 'noerror 'nomessage)))
29855149
MA
1946 ;; If `non-essential' is non-nil, Tramp shall
1947 ;; not open a new connection.
2fe4b125 1948 ;; If Tramp detects that it shouldn't continue
29855149 1949 ;; to work, it throws the `suppress' event.
2fe4b125
MA
1950 ;; This could happen for example, when Tramp
1951 ;; tries to open the same connection twice in a
1952 ;; short time frame.
29855149 1953 ;; In both cases, we try the default handler then.
2fe4b125 1954 (setq result
29855149
MA
1955 (catch 'non-essential
1956 (catch 'suppress
1957 (apply foreign operation args))))
1958 (cond
1959 ((eq result 'non-essential)
1960 (tramp-message
1961 v 5 "Non-essential received in operation %s"
1962 (append (list operation) args))
1963 (tramp-run-real-handler operation args))
1964 ((eq result 'suppress)
1965 (let (tramp-message-show-message)
1966 (tramp-message
1967 v 1 "Suppress received in operation %s"
1968 (append (list operation) args))
1969 (tramp-cleanup v)
1970 (tramp-run-real-handler operation args)))
1971 (t result)))
af4b9ae5 1972
51aba3f3 1973 ;; Trace that somebody has interrupted the operation.
56f2d1e1 1974 ((debug quit)
af4b9ae5
MA
1975 (let (tramp-message-show-message)
1976 (tramp-message
1977 v 1 "Interrupt received in operation %s"
1978 (append (list operation) args)))
1979 ;; Propagate the quit signal.
1980 (signal (car err) (cdr err)))
1981
1982 ;; When we are in completion mode, some failed
1983 ;; operations shall return at least a default value
1984 ;; in order to give the user a chance to correct the
1985 ;; file name in the minibuffer.
2fe4b125 1986 ;; In order to get a full backtrace, one could apply
56f2d1e1 1987 ;; (setq debug-on-error t debug-on-signal t)
4874f5e6
MA
1988 (error
1989 (cond
4874f5e6
MA
1990 ((and completion (zerop (length localname))
1991 (memq operation '(file-exists-p file-directory-p)))
1992 t)
1993 ((and completion (zerop (length localname))
1994 (memq operation
1995 '(expand-file-name file-name-as-directory)))
1996 filename)
1997 ;; Propagate the error.
1998 (t (signal (car err) (cdr err))))))
af4b9ae5 1999
4874f5e6
MA
2000 ;; Nothing to do for us.
2001 (tramp-run-real-handler operation args)))))
2002
2e271195
MA
2003 ;; When `tramp-mode' is not enabled, we don't do anything.
2004 (tramp-run-real-handler operation args)))
fb7933a3 2005
07dfe738
KG
2006;; In Emacs, there is some concurrency due to timers. If a timer
2007;; interrupts Tramp and wishes to use the same connection buffer as
2008;; the "main" Emacs, then garbage might occur in the connection
2009;; buffer. Therefore, we need to make sure that a timer does not use
2010;; the same connection buffer as the "main" Emacs. We implement a
2011;; cheap global lock, instead of locking each connection buffer
2012;; separately. The global lock is based on two variables,
2013;; `tramp-locked' and `tramp-locker'. `tramp-locked' is set to true
2014;; (with setq) to indicate a lock. But Tramp also calls itself during
2015;; processing of a single file operation, so we need to allow
2016;; recursive calls. That's where the `tramp-locker' variable comes in
2017;; -- it is let-bound to t during the execution of the current
2018;; handler. So if `tramp-locked' is t and `tramp-locker' is also t,
2019;; then we should just proceed because we have been called
2020;; recursively. But if `tramp-locker' is nil, then we are a timer
2021;; interrupting the "main" Emacs, and then we signal an error.
2022
2023(defvar tramp-locked nil
2024 "If non-nil, then Tramp is currently busy.
2025Together with `tramp-locker', this implements a locking mechanism
2026preventing reentrant calls of Tramp.")
2027
2028(defvar tramp-locker nil
2029 "If non-nil, then a caller has locked Tramp.
2030Together with `tramp-locked', this implements a locking mechanism
2031preventing reentrant calls of Tramp.")
2032
16674e4f 2033;;;###autoload
1ecc6145 2034(progn (defun tramp-completion-file-name-handler (operation &rest args)
a4aeb9a4
MA
2035 "Invoke Tramp file name completion handler.
2036Falls back to normal file name handler if no Tramp file name handler exists."
57671b72
MA
2037 ;; We bind `directory-sep-char' here for XEmacs on Windows, which
2038 ;; would otherwise use backslash.
aff67808
MA
2039 (let ((directory-sep-char ?/)
2040 (fn (assoc operation tramp-completion-file-name-handler-alist)))
aa485f7c
MA
2041 (if (and
2042 ;; When `tramp-mode' is not enabled, we don't do anything.
2043 fn tramp-mode
2044 ;; For other syntaxes than `sep', the regexp matches many common
2045 ;; situations where the user doesn't actually want to use Tramp.
2046 ;; So to avoid autoloading Tramp after typing just "/s", we
2047 ;; disable this part of the completion, unless the user implicitly
2048 ;; indicated his interest in using a fancier completion system.
2049 (or (eq tramp-syntax 'sep)
a94d821f
MA
2050 (featurep 'tramp) ;; If it's loaded, we may as well use it.
2051 ;; `partial-completion-mode' does not exist in XEmacs.
2052 ;; It is obsoleted with Emacs 24.1.
0d5852cf
MA
2053 (and (boundp 'partial-completion-mode)
2054 (symbol-value 'partial-completion-mode))
aa485f7c
MA
2055 ;; FIXME: These may have been loaded even if the user never
2056 ;; intended to use them.
2057 (featurep 'ido)
2058 (featurep 'icicles)))
aff67808
MA
2059 (save-match-data (apply (cdr fn) args))
2060 (tramp-completion-run-real-handler operation args)))))
a01b1e22 2061
b25a52cc 2062;;;###autoload
aa485f7c
MA
2063(progn (defun tramp-register-file-name-handlers ()
2064 "Add Tramp file name handlers to `file-name-handler-alist'."
2065 ;; Remove autoloaded handlers from file name handler alist. Useful,
00d6fd04
MA
2066 ;; if `tramp-syntax' has been changed.
2067 (let ((a1 (rassq 'tramp-file-name-handler file-name-handler-alist)))
aa485f7c
MA
2068 (setq file-name-handler-alist (delq a1 file-name-handler-alist)))
2069 (let ((a1 (rassq
2070 'tramp-completion-file-name-handler file-name-handler-alist)))
2071 (setq file-name-handler-alist (delq a1 file-name-handler-alist)))
2072 ;; Add the handlers.
a01b1e22
MA
2073 (add-to-list 'file-name-handler-alist
2074 (cons tramp-file-name-regexp 'tramp-file-name-handler))
0c0b61f1 2075 (put 'tramp-file-name-handler 'safe-magic t)
aa485f7c
MA
2076 (add-to-list 'file-name-handler-alist
2077 (cons tramp-completion-file-name-regexp
2078 'tramp-completion-file-name-handler))
2079 (put 'tramp-completion-file-name-handler 'safe-magic t)
2080 ;; If jka-compr or epa-file are already loaded, move them to the
2081 ;; front of `file-name-handler-alist'.
2082 (dolist (fnh '(epa-file-handler jka-compr-handler))
2083 (let ((entry (rassoc fnh file-name-handler-alist)))
2084 (when entry
2085 (setq file-name-handler-alist
2086 (cons entry (delete entry file-name-handler-alist))))))))
69cee873 2087
00d6fd04
MA
2088;; `tramp-file-name-handler' must be registered before evaluation of
2089;; site-start and init files, because there might exist remote files
2090;; already, f.e. files kept via recentf-mode.
4a93e698 2091;;;###autoload
aa485f7c 2092(tramp-register-file-name-handlers)
b25a52cc 2093
4a93e698
MA
2094(defun tramp-exists-file-name-handler (operation &rest args)
2095 "Check, whether OPERATION runs a file name handler."
2096 ;; The file name handler is determined on base of either an
2097 ;; argument, `buffer-file-name', or `default-directory'.
2098 (ignore-errors
2099 (let* ((buffer-file-name "/")
2100 (default-directory "/")
2101 (fnha file-name-handler-alist)
2102 (check-file-name-operation operation)
2103 (file-name-handler-alist
2104 (list
2105 (cons "/"
2106 (lambda (operation &rest args)
2107 "Returns OPERATION if it is the one to be checked."
2108 (if (equal check-file-name-operation operation)
2109 operation
2110 (let ((file-name-handler-alist fnha))
2111 (apply operation args))))))))
2112 (equal (apply operation args) operation))))
2113
fb7933a3 2114;;;###autoload
8c04e197 2115(defun tramp-unload-file-name-handlers ()
a69c01a0
MA
2116 (setq file-name-handler-alist
2117 (delete (rassoc 'tramp-file-name-handler
2118 file-name-handler-alist)
2119 (delete (rassoc 'tramp-completion-file-name-handler
2120 file-name-handler-alist)
2121 file-name-handler-alist))))
2122
8c04e197 2123(add-hook 'tramp-unload-hook 'tramp-unload-file-name-handlers)
a69c01a0 2124
0664ff72 2125;;; File name handler functions for completion mode:
a6e96327
MA
2126
2127(defvar tramp-completion-mode nil
2128 "If non-nil, external packages signal that they are in file name completion.
2129
2130This is necessary, because Tramp uses a heuristic depending on last
2131input event. This fails when external packages use other characters
2132but <TAB>, <SPACE> or ?\\? for file name completion. This variable
2133should never be set globally, the intention is to let-bind it.")
16674e4f
KG
2134
2135;; Necessary because `tramp-file-name-regexp-unified' and
00d6fd04
MA
2136;; `tramp-completion-file-name-regexp-unified' aren't different. If
2137;; nil, `tramp-completion-run-real-handler' is called (i.e. forwarding
2138;; to `tramp-file-name-handler'). Otherwise, it takes
2139;; `tramp-run-real-handler'. Using `last-input-event' is a little bit
2140;; risky, because completing a file might require loading other files,
2141;; like "~/.netrc", and for them it shouldn't be decided based on that
2142;; variable. On the other hand, those files shouldn't have partial
a4aeb9a4
MA
2143;; Tramp file name syntax. Maybe another variable should be introduced
2144;; overwriting this check in such cases. Or we change Tramp file name
00d6fd04 2145;; syntax in order to avoid ambiguities, like in XEmacs ...
0f34aa77 2146;;;###tramp-autoload
6c4e47fa 2147(defun tramp-completion-mode-p ()
a94d821f 2148 "Check, whether method / user name / host name completion is active."
6c4e47fa 2149 (or
5f2b693f
MA
2150 ;; Signal from outside. `non-essential' has been introduced in Emacs 24.
2151 (and (boundp 'non-essential) (symbol-value 'non-essential))
a6e96327
MA
2152 tramp-completion-mode
2153 ;; Emacs.
94be87e8 2154 (equal last-input-event 'tab)
6c4e47fa 2155 (and (natnump last-input-event)
94be87e8 2156 (or
a6e96327 2157 ;; ?\t has event-modifier 'control.
800a97b8 2158 (equal last-input-event ?\t)
94be87e8 2159 (and (not (event-modifiers last-input-event))
800a97b8
SM
2160 (or (equal last-input-event ?\?)
2161 (equal last-input-event ?\ )))))
a6e96327 2162 ;; XEmacs.
6c4e47fa
MA
2163 (and (featurep 'xemacs)
2164 ;; `last-input-event' might be nil.
2165 (not (null last-input-event))
2166 ;; `last-input-event' may have no character approximation.
0d5852cf 2167 (tramp-compat-funcall 'event-to-character last-input-event)
94be87e8 2168 (or
a6e96327 2169 ;; ?\t has event-modifier 'control.
800a97b8 2170 (equal
0d5852cf 2171 (tramp-compat-funcall 'event-to-character last-input-event) ?\t)
94be87e8 2172 (and (not (event-modifiers last-input-event))
800a97b8 2173 (or (equal
0d5852cf
MA
2174 (tramp-compat-funcall 'event-to-character last-input-event)
2175 ?\?)
800a97b8 2176 (equal
0d5852cf
MA
2177 (tramp-compat-funcall 'event-to-character last-input-event)
2178 ?\ )))))))
16674e4f 2179
acd1f317
MA
2180(defun tramp-connectable-p (filename)
2181 "Check, whether it is possible to connect the remote host w/o side-effects.
2182This is true, if either the remote host is already connected, or if we are
2183not in completion mode."
2184 (and (tramp-tramp-file-p filename)
2185 (with-parsed-tramp-file-name filename nil
305c07f6
MA
2186 (or (not (tramp-completion-mode-p))
2187 (let ((p (tramp-get-connection-process v)))
2188 (and p (processp p) (memq (process-status p) '(run open))))))))
acd1f317 2189
16674e4f
KG
2190;; Method, host name and user name completion.
2191;; `tramp-completion-dissect-file-name' returns a list of
2192;; tramp-file-name structures. For all of them we return possible completions.
a01b1e22 2193;;;###autoload
16674e4f 2194(defun tramp-completion-handle-file-name-all-completions (filename directory)
00d6fd04 2195 "Like `file-name-all-completions' for partial Tramp files."
16674e4f 2196
2fe4b125
MA
2197 (let ((fullname
2198 (tramp-drop-volume-letter (expand-file-name filename directory)))
2199 hop result result1)
2200
2201 ;; Suppress hop from completion.
2202 (when (string-match
2203 (concat
2204 tramp-prefix-regexp
2205 "\\(" "\\(" tramp-remote-file-name-spec-regexp
2206 tramp-postfix-hop-regexp
2207 "\\)+" "\\)")
2208 fullname)
2209 (setq hop (match-string 1 fullname)
2210 fullname (replace-match "" nil nil fullname 1)))
2211
2212 ;; Possible completion structures.
2213 (dolist (elt (tramp-completion-dissect-file-name fullname))
2214 (let* ((method (tramp-file-name-method elt))
2215 (user (tramp-file-name-user elt))
2216 (host (tramp-file-name-host elt))
2217 (localname (tramp-file-name-localname elt))
00d6fd04
MA
2218 (m (tramp-find-method method user host))
2219 (tramp-current-user user) ; see `tramp-parse-passwd'
2220 all-user-hosts)
2221
2222 (unless localname ;; Nothing to complete.
2223
2224 (if (or user host)
2225
2226 ;; Method dependent user / host combinations.
2227 (progn
9e6ab520 2228 (mapc
00d6fd04
MA
2229 (lambda (x)
2230 (setq all-user-hosts
2231 (append all-user-hosts
2232 (funcall (nth 0 x) (nth 1 x)))))
2233 (tramp-get-completion-function m))
2234
9e6ab520
MA
2235 (setq result
2236 (append result
2237 (mapcar
2238 (lambda (x)
2239 (tramp-get-completion-user-host
2240 method user host (nth 0 x) (nth 1 x)))
2241 (delq nil all-user-hosts)))))
00d6fd04
MA
2242
2243 ;; Possible methods.
2244 (setq result
2fe4b125 2245 (append result (tramp-get-completion-methods m)))))))
00d6fd04 2246
2fe4b125
MA
2247 ;; Unify list, add hop, remove nil elements.
2248 (dolist (elt result)
2249 (when elt
2250 (string-match tramp-prefix-regexp elt)
2251 (setq elt (replace-match (concat tramp-prefix-format hop) nil nil elt))
2252 (add-to-list
2253 'result1
2254 (substring elt (length (tramp-drop-volume-letter directory))))))
00d6fd04
MA
2255
2256 ;; Complete local parts.
2257 (append
2258 result1
03c1ad43
MA
2259 (ignore-errors
2260 (apply (if (tramp-connectable-p fullname)
2261 'tramp-completion-run-real-handler
2262 'tramp-run-real-handler)
2263 'file-name-all-completions (list (list filename directory)))))))
16674e4f
KG
2264
2265;; Method, host name and user name completion for a file.
a01b1e22 2266;;;###autoload
e1e17cae
MA
2267(defun tramp-completion-handle-file-name-completion
2268 (filename directory &optional predicate)
00d6fd04 2269 "Like `file-name-completion' for Tramp files."
e1e17cae
MA
2270 (try-completion
2271 filename
2272 (mapcar 'list (file-name-all-completions filename directory))
acd1f317
MA
2273 (when (and predicate
2274 (tramp-connectable-p (expand-file-name filename directory)))
83e20b5c 2275 (lambda (x) (funcall predicate (expand-file-name (car x) directory))))))
16674e4f
KG
2276
2277;; I misuse a little bit the tramp-file-name structure in order to handle
2278;; completion possibilities for partial methods / user names / host names.
2279;; Return value is a list of tramp-file-name structures according to possible
00d6fd04 2280;; completions. If "localname" is non-nil it means there
16674e4f
KG
2281;; shouldn't be a completion anymore.
2282
2283;; Expected results:
2284
00d6fd04
MA
2285;; "/x" "/[x" "/x@" "/[x@" "/x@y" "/[x@y"
2286;; [nil nil "x" nil] [nil "x" nil nil] [nil "x" "y" nil]
2287;; [nil "x" nil nil]
2288;; ["x" nil nil nil]
2289
2290;; "/x:" "/x:y" "/x:y:"
2291;; [nil nil "x" ""] [nil nil "x" "y"] ["x" nil "y" ""]
2292;; "/[x/" "/[x/y"
2293;; ["x" nil "" nil] ["x" nil "y" nil]
2294;; ["x" "" nil nil] ["x" "y" nil nil]
2295
2296;; "/x:y@" "/x:y@z" "/x:y@z:"
2297;; [nil nil "x" "y@"] [nil nil "x" "y@z"] ["x" "y" "z" ""]
2298;; "/[x/y@" "/[x/y@z"
2299;; ["x" nil "y" nil] ["x" "y" "z" nil]
16674e4f
KG
2300(defun tramp-completion-dissect-file-name (name)
2301 "Returns a list of `tramp-file-name' structures.
2302They are collected by `tramp-completion-dissect-file-name1'."
2303
2304 (let* ((result)
4007ba5b 2305 (x-nil "\\|\\(\\)")
b96e6899
MA
2306 (tramp-completion-ipv6-regexp
2307 (format
2308 "[^%s]*"
2309 (if (zerop (length tramp-postfix-ipv6-format))
2310 tramp-postfix-host-format
2311 tramp-postfix-ipv6-format)))
4007ba5b
KG
2312 ;; "/method" "/[method"
2313 (tramp-completion-file-name-structure1
2314 (list (concat tramp-prefix-regexp "\\(" tramp-method-regexp x-nil "\\)$")
2315 1 nil nil nil))
2316 ;; "/user" "/[user"
2317 (tramp-completion-file-name-structure2
2318 (list (concat tramp-prefix-regexp "\\(" tramp-user-regexp x-nil "\\)$")
2319 nil 1 nil nil))
2320 ;; "/host" "/[host"
2321 (tramp-completion-file-name-structure3
2322 (list (concat tramp-prefix-regexp "\\(" tramp-host-regexp x-nil "\\)$")
2323 nil nil 1 nil))
b96e6899 2324 ;; "/[ipv6" "/[ipv6"
4007ba5b 2325 (tramp-completion-file-name-structure4
b96e6899
MA
2326 (list (concat tramp-prefix-regexp
2327 tramp-prefix-ipv6-regexp
2328 "\\(" tramp-completion-ipv6-regexp x-nil "\\)$")
2329 nil nil 1 nil))
2330 ;; "/user@host" "/[user@host"
2331 (tramp-completion-file-name-structure5
4007ba5b
KG
2332 (list (concat tramp-prefix-regexp
2333 "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp
2334 "\\(" tramp-host-regexp x-nil "\\)$")
2335 nil 1 2 nil))
b96e6899
MA
2336 ;; "/user@[ipv6" "/[user@ipv6"
2337 (tramp-completion-file-name-structure6
2338 (list (concat tramp-prefix-regexp
2339 "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp
2340 tramp-prefix-ipv6-regexp
2341 "\\(" tramp-completion-ipv6-regexp x-nil "\\)$")
2342 nil 1 2 nil))
00d6fd04 2343 ;; "/method:user" "/[method/user" "/method://user"
b96e6899 2344 (tramp-completion-file-name-structure7
4007ba5b 2345 (list (concat tramp-prefix-regexp
00d6fd04 2346 "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp
4007ba5b
KG
2347 "\\(" tramp-user-regexp x-nil "\\)$")
2348 1 2 nil nil))
00d6fd04 2349 ;; "/method:host" "/[method/host" "/method://host"
b96e6899 2350 (tramp-completion-file-name-structure8
4007ba5b 2351 (list (concat tramp-prefix-regexp
00d6fd04 2352 "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp
4007ba5b
KG
2353 "\\(" tramp-host-regexp x-nil "\\)$")
2354 1 nil 2 nil))
b96e6899
MA
2355 ;; "/method:[ipv6" "/[method/ipv6" "/method://[ipv6"
2356 (tramp-completion-file-name-structure9
2357 (list (concat tramp-prefix-regexp
2358 "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp
2359 tramp-prefix-ipv6-regexp
2360 "\\(" tramp-completion-ipv6-regexp x-nil "\\)$")
2361 1 nil 2 nil))
00d6fd04 2362 ;; "/method:user@host" "/[method/user@host" "/method://user@host"
b96e6899 2363 (tramp-completion-file-name-structure10
4007ba5b 2364 (list (concat tramp-prefix-regexp
00d6fd04 2365 "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp
4007ba5b
KG
2366 "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp
2367 "\\(" tramp-host-regexp x-nil "\\)$")
00d6fd04 2368 1 2 3 nil))
b96e6899
MA
2369 ;; "/method:user@[ipv6" "/[method/user@ipv6" "/method://user@[ipv6"
2370 (tramp-completion-file-name-structure11
2371 (list (concat tramp-prefix-regexp
2372 "\\(" tramp-method-regexp "\\)" tramp-postfix-method-regexp
2373 "\\(" tramp-user-regexp "\\)" tramp-postfix-user-regexp
2374 tramp-prefix-ipv6-regexp
2375 "\\(" tramp-completion-ipv6-regexp x-nil "\\)$")
2376 1 2 3 nil))
00d6fd04 2377 ;; "/method: "/method:/"
b96e6899 2378 (tramp-completion-file-name-structure12
00d6fd04
MA
2379 (list
2380 (if (equal tramp-syntax 'url)
2381 (concat tramp-prefix-regexp
2382 "\\(" tramp-method-regexp "\\)"
2383 "\\(" (substring tramp-postfix-method-regexp 0 1)
2384 "\\|" (substring tramp-postfix-method-regexp 1 2) "\\)"
2385 "\\(" "\\)$")
2386 ;; Should not match if not URL syntax.
2387 (concat tramp-prefix-regexp "/$"))
2388 1 3 nil nil))
2389 ;; "/method: "/method:/"
b96e6899 2390 (tramp-completion-file-name-structure13
00d6fd04
MA
2391 (list
2392 (if (equal tramp-syntax 'url)
2393 (concat tramp-prefix-regexp
2394 "\\(" tramp-method-regexp "\\)"
2395 "\\(" (substring tramp-postfix-method-regexp 0 1)
2396 "\\|" (substring tramp-postfix-method-regexp 1 2) "\\)"
2397 "\\(" "\\)$")
2398 ;; Should not match if not URL syntax.
2399 (concat tramp-prefix-regexp "/$"))
2400 1 nil 3 nil)))
4007ba5b 2401
2fe4b125 2402 (mapc (lambda (structure)
16674e4f 2403 (add-to-list 'result
2fe4b125 2404 (tramp-completion-dissect-file-name1 structure name)))
16674e4f
KG
2405 (list
2406 tramp-completion-file-name-structure1
2407 tramp-completion-file-name-structure2
2408 tramp-completion-file-name-structure3
2409 tramp-completion-file-name-structure4
2410 tramp-completion-file-name-structure5
2411 tramp-completion-file-name-structure6
2412 tramp-completion-file-name-structure7
00d6fd04
MA
2413 tramp-completion-file-name-structure8
2414 tramp-completion-file-name-structure9
b96e6899
MA
2415 tramp-completion-file-name-structure10
2416 tramp-completion-file-name-structure11
2417 tramp-completion-file-name-structure12
2418 tramp-completion-file-name-structure13
16674e4f
KG
2419 tramp-file-name-structure))
2420
2421 (delq nil result)))
2422
2423(defun tramp-completion-dissect-file-name1 (structure name)
2424 "Returns a `tramp-file-name' structure matching STRUCTURE.
00d6fd04 2425The structure consists of remote method, remote user,
7432277c 2426remote host and localname (filename on remote host)."
fb7933a3 2427
00d6fd04
MA
2428 (save-match-data
2429 (when (string-match (nth 0 structure) name)
2430 (let ((method (and (nth 1 structure)
2431 (match-string (nth 1 structure) name)))
2432 (user (and (nth 2 structure)
2433 (match-string (nth 2 structure) name)))
2434 (host (and (nth 3 structure)
2435 (match-string (nth 3 structure) name)))
2436 (localname (and (nth 4 structure)
2437 (match-string (nth 4 structure) name))))
2fe4b125 2438 (vector method user host localname nil)))))
16674e4f
KG
2439
2440;; This function returns all possible method completions, adding the
51aba3f3 2441;; trailing method delimiter.
16674e4f
KG
2442(defun tramp-get-completion-methods (partial-method)
2443 "Returns all method completions for PARTIAL-METHOD."
4007ba5b
KG
2444 (mapcar
2445 (lambda (method)
2446 (and method
2447 (string-match (concat "^" (regexp-quote partial-method)) method)
00d6fd04
MA
2448 (tramp-completion-make-tramp-file-name method nil nil nil)))
2449 (mapcar 'car tramp-methods)))
16674e4f
KG
2450
2451;; Compares partial user and host names with possible completions.
2fe4b125
MA
2452(defun tramp-get-completion-user-host
2453 (method partial-user partial-host user host)
16674e4f
KG
2454 "Returns the most expanded string for user and host name completion.
2455PARTIAL-USER must match USER, PARTIAL-HOST must match HOST."
2456 (cond
2457
2458 ((and partial-user partial-host)
2459 (if (and host
2460 (string-match (concat "^" (regexp-quote partial-host)) host)
2461 (string-equal partial-user (or user partial-user)))
2462 (setq user partial-user)
2463 (setq user nil
2464 host nil)))
2465
2466 (partial-user
2467 (setq host nil)
2468 (unless
2469 (and user (string-match (concat "^" (regexp-quote partial-user)) user))
2470 (setq user nil)))
2471
2472 (partial-host
2473 (setq user nil)
2474 (unless
2475 (and host (string-match (concat "^" (regexp-quote partial-host)) host))
2476 (setq host nil)))
2477
2478 (t (setq user nil
2479 host nil)))
2480
292ffc15 2481 (unless (zerop (+ (length user) (length host)))
00d6fd04 2482 (tramp-completion-make-tramp-file-name method user host nil)))
16674e4f 2483
2fe4b125
MA
2484;; Generic function.
2485(defun tramp-parse-group (regexp match-level skip-regexp)
2486 "Return a (user host) tuple allowed to access.
2487User is always nil."
2488 (let (result)
2489 (when (re-search-forward regexp (point-at-eol) t)
2490 (setq result (list nil (match-string match-level))))
2491 (or
2492 (> (skip-chars-forward skip-regexp) 0)
2493 (forward-line 1))
2494 result))
2495
2496;; Generic function.
2497(defun tramp-parse-file (filename function)
16674e4f 2498 "Return a list of (user host) tuples allowed to access.
2fe4b125 2499User is always nil."
00d6fd04
MA
2500 ;; On Windows, there are problems in completion when
2501 ;; `default-directory' is remote.
2fe4b125 2502 (let ((default-directory (tramp-compat-temporary-file-directory)))
8daea7fc 2503 (when (file-readable-p filename)
16674e4f
KG
2504 (with-temp-buffer
2505 (insert-file-contents filename)
2506 (goto-char (point-min))
2fe4b125
MA
2507 (loop while (not (eobp)) collect (funcall function))))))
2508
2509;;;###tramp-autoload
2510(defun tramp-parse-rhosts (filename)
2511 "Return a list of (user host) tuples allowed to access.
2512Either user or host may be nil."
2513 (tramp-parse-file filename 'tramp-parse-rhosts-group))
16674e4f 2514
16674e4f
KG
2515(defun tramp-parse-rhosts-group ()
2516 "Return a (user host) tuple allowed to access.
292ffc15 2517Either user or host may be nil."
16674e4f
KG
2518 (let ((result)
2519 (regexp
2520 (concat
2521 "^\\(" tramp-host-regexp "\\)"
2522 "\\([ \t]+" "\\(" tramp-user-regexp "\\)" "\\)?")))
2fe4b125 2523 (when (re-search-forward regexp (point-at-eol) t)
16674e4f 2524 (setq result (append (list (match-string 3) (match-string 1)))))
16674e4f
KG
2525 (forward-line 1)
2526 result))
2527
f8f91c2b 2528;;;###tramp-autoload
16674e4f
KG
2529(defun tramp-parse-shosts (filename)
2530 "Return a list of (user host) tuples allowed to access.
2531User is always nil."
2fe4b125 2532 (tramp-parse-file filename 'tramp-parse-shosts-group))
16674e4f
KG
2533
2534(defun tramp-parse-shosts-group ()
2535 "Return a (user host) tuple allowed to access.
2536User is always nil."
2fe4b125 2537 (tramp-parse-group (concat "^\\(" tramp-host-regexp "\\)") 1 ","))
16674e4f 2538
f8f91c2b 2539;;;###tramp-autoload
8daea7fc
KG
2540(defun tramp-parse-sconfig (filename)
2541 "Return a list of (user host) tuples allowed to access.
2542User is always nil."
2fe4b125 2543 (tramp-parse-file filename 'tramp-parse-sconfig-group))
8daea7fc
KG
2544
2545(defun tramp-parse-sconfig-group ()
2546 "Return a (user host) tuple allowed to access.
2547User is always nil."
2fe4b125
MA
2548 (tramp-parse-group
2549 (concat "^[ \t]*Host[ \t]+" "\\(" tramp-host-regexp "\\)") 1 ","))
8daea7fc 2550
2fe4b125
MA
2551;; Generic function.
2552(defun tramp-parse-shostkeys-sknownhosts (dirname regexp)
5ec2cc41
KG
2553 "Return a list of (user host) tuples allowed to access.
2554User is always nil."
00d6fd04
MA
2555 ;; On Windows, there are problems in completion when
2556 ;; `default-directory' is remote.
9e6ab520 2557 (let* ((default-directory (tramp-compat-temporary-file-directory))
2fe4b125
MA
2558 (files (and (file-directory-p dirname) (directory-files dirname))))
2559 (loop for f in files
2560 when (and (not (string-match "^\\.\\.?$" f)) (string-match regexp f))
2561 collect (list nil (match-string 1 f)))))
2562
2563;;;###tramp-autoload
2564(defun tramp-parse-shostkeys (dirname)
2565 "Return a list of (user host) tuples allowed to access.
2566User is always nil."
2567 (tramp-parse-shostkeys-sknownhosts
2568 dirname (concat "^key_[0-9]+_\\(" tramp-host-regexp "\\)\\.pub$")))
5ec2cc41 2569
2fe4b125 2570;;;###tramp-autoload
5ec2cc41
KG
2571(defun tramp-parse-sknownhosts (dirname)
2572 "Return a list of (user host) tuples allowed to access.
2573User is always nil."
2fe4b125
MA
2574 (tramp-parse-shostkeys-sknownhosts
2575 dirname
2576 (concat "^\\(" tramp-host-regexp "\\)\\.ssh-\\(dss\\|rsa\\)\\.pub$")))
5ec2cc41 2577
f8f91c2b 2578;;;###tramp-autoload
16674e4f
KG
2579(defun tramp-parse-hosts (filename)
2580 "Return a list of (user host) tuples allowed to access.
2581User is always nil."
2fe4b125 2582 (tramp-parse-file filename 'tramp-parse-hosts-group))
16674e4f
KG
2583
2584(defun tramp-parse-hosts-group ()
2585 "Return a (user host) tuple allowed to access.
2586User is always nil."
2fe4b125
MA
2587 (tramp-parse-group
2588 (concat "^\\(" tramp-ipv6-regexp "\\|" tramp-host-regexp "\\)") 1 " \t"))
16674e4f 2589
8daea7fc
KG
2590;; For su-alike methods it would be desirable to return "root@localhost"
2591;; as default. Unfortunately, we have no information whether any user name
00d6fd04 2592;; has been typed already. So we use `tramp-current-user' as indication,
8daea7fc 2593;; assuming it is set in `tramp-completion-handle-file-name-all-completions'.
f8f91c2b 2594;;;###tramp-autoload
16674e4f
KG
2595(defun tramp-parse-passwd (filename)
2596 "Return a list of (user host) tuples allowed to access.
2597Host is always \"localhost\"."
2fe4b125
MA
2598 (if (zerop (length tramp-current-user))
2599 '(("root" nil))
2600 (tramp-parse-file filename 'tramp-parse-passwd-group)))
16674e4f
KG
2601
2602(defun tramp-parse-passwd-group ()
2603 "Return a (user host) tuple allowed to access.
292ffc15 2604Host is always \"localhost\"."
16674e4f
KG
2605 (let ((result)
2606 (regexp (concat "^\\(" tramp-user-regexp "\\):")))
2fe4b125 2607 (when (re-search-forward regexp (point-at-eol) t)
16674e4f 2608 (setq result (list (match-string 1) "localhost")))
16674e4f
KG
2609 (forward-line 1)
2610 result))
2611
f8f91c2b 2612;;;###tramp-autoload
292ffc15
KG
2613(defun tramp-parse-netrc (filename)
2614 "Return a list of (user host) tuples allowed to access.
2615User may be nil."
2fe4b125 2616 (tramp-parse-file filename 'tramp-parse-netrc-group))
292ffc15
KG
2617
2618(defun tramp-parse-netrc-group ()
2619 "Return a (user host) tuple allowed to access.
2620User may be nil."
292ffc15
KG
2621 (let ((result)
2622 (regexp
2623 (concat
2624 "^[ \t]*machine[ \t]+" "\\(" tramp-host-regexp "\\)"
2625 "\\([ \t]+login[ \t]+" "\\(" tramp-user-regexp "\\)" "\\)?")))
2fe4b125 2626 (when (re-search-forward regexp (point-at-eol) t)
292ffc15 2627 (setq result (list (match-string 3) (match-string 1))))
292ffc15
KG
2628 (forward-line 1)
2629 result))
2630
f8f91c2b 2631;;;###tramp-autoload
2fe4b125 2632(defun tramp-parse-putty (registry-or-dirname)
00d6fd04
MA
2633 "Return a list of (user host) tuples allowed to access.
2634User is always nil."
2fe4b125
MA
2635 (if (memq system-type '(windows-nt))
2636 (with-temp-buffer
2637 (when (zerop (tramp-compat-call-process
2638 "reg" nil t nil "query" registry-or-dirname))
2639 (goto-char (point-min))
2640 (loop while (not (eobp)) collect
2641 (tramp-parse-putty-group registry-or-dirname))))
2642 ;; UNIX case.
2643 (tramp-parse-shostkeys-sknownhosts
2644 registry-or-dirname (concat "^\\(" tramp-host-regexp "\\)$"))))
00d6fd04
MA
2645
2646(defun tramp-parse-putty-group (registry)
2647 "Return a (user host) tuple allowed to access.
2648User is always nil."
2649 (let ((result)
2650 (regexp (concat (regexp-quote registry) "\\\\\\(.+\\)")))
2fe4b125 2651 (when (re-search-forward regexp (point-at-eol) t)
00d6fd04 2652 (setq result (list nil (match-string 1))))
00d6fd04
MA
2653 (forward-line 1)
2654 result))
2655
4a93e698 2656;;; Common file name handler functions for different backends:
b88f2d0a 2657
4a93e698
MA
2658(defvar tramp-handle-file-local-copy-hook nil
2659 "Normal hook to be run at the end of `tramp-*-handle-file-local-copy'.")
2660
2661(defvar tramp-handle-write-region-hook nil
2662 "Normal hook to be run at the end of `tramp-*-handle-write-region'.")
2663
2664(defun tramp-handle-directory-file-name (directory)
2665 "Like `directory-file-name' for Tramp files."
2666 ;; If localname component of filename is "/", leave it unchanged.
2667 ;; Otherwise, remove any trailing slash from localname component.
2668 ;; Method, host, etc, are unchanged. Does it make sense to try
2669 ;; to avoid parsing the filename?
2670 (with-parsed-tramp-file-name directory nil
2671 (if (and (not (zerop (length localname)))
2672 (eq (aref localname (1- (length localname))) ?/)
2673 (not (string= localname "/")))
2674 (substring directory 0 -1)
2675 directory)))
2676
2677(defun tramp-handle-directory-files
2678 (directory &optional full match nosort files-only)
2679 "Like `directory-files' for Tramp files."
2680 ;; FILES-ONLY is valid for XEmacs only.
2681 (when (file-directory-p directory)
2682 (setq directory (file-name-as-directory (expand-file-name directory)))
2683 (let ((temp (nreverse (file-name-all-completions "" directory)))
2684 result item)
2685
2686 (while temp
2687 (setq item (directory-file-name (pop temp)))
2688 (when (and (or (null match) (string-match match item))
2689 (or (null files-only)
2690 ;; Files only.
2691 (and (equal files-only t) (file-regular-p item))
2692 ;; Directories only.
2693 (file-directory-p item)))
2694 (push (if full (concat directory item) item)
2695 result)))
2696 (if nosort result (sort result 'string<)))))
2697
bd8fadca
MA
2698(defun tramp-handle-directory-files-and-attributes
2699 (directory &optional full match nosort id-format)
2700 "Like `directory-files-and-attributes' for Tramp files."
2701 (mapcar
2702 (lambda (x)
2703 (cons x (tramp-compat-file-attributes
2704 (if full x (expand-file-name x directory)) id-format)))
2705 (directory-files directory full match nosort)))
2706
4a93e698
MA
2707(defun tramp-handle-dired-uncache (dir &optional dir-p)
2708 "Like `dired-uncache' for Tramp files."
2709 ;; DIR-P is valid for XEmacs only.
2710 (with-parsed-tramp-file-name
2711 (if (or dir-p (file-directory-p dir)) dir (file-name-directory dir)) nil
2712 (tramp-flush-directory-property v localname)))
2713
bd8fadca
MA
2714(defun tramp-handle-file-exists-p (filename)
2715 "Like `file-exists-p' for Tramp files."
2716 (not (null (file-attributes filename))))
2717
4a93e698
MA
2718(defun tramp-handle-file-modes (filename)
2719 "Like `file-modes' for Tramp files."
2720 (let ((truename (or (file-truename filename) filename)))
2721 (when (file-exists-p truename)
2722 (tramp-mode-string-to-int (nth 8 (file-attributes truename))))))
2723
2724;; Localname manipulation functions that grok Tramp localnames...
2725(defun tramp-handle-file-name-as-directory (file)
2726 "Like `file-name-as-directory' but aware of Tramp files."
2727 ;; `file-name-as-directory' would be sufficient except localname is
2728 ;; the empty string.
2729 (let ((v (tramp-dissect-file-name file t)))
2730 ;; Run the command on the localname portion only.
2731 (tramp-make-tramp-file-name
2732 (tramp-file-name-method v)
2733 (tramp-file-name-user v)
2734 (tramp-file-name-host v)
2735 (tramp-run-real-handler
2736 'file-name-as-directory (list (or (tramp-file-name-localname v) ""))))))
2737
2738(defun tramp-handle-file-name-completion
2739 (filename directory &optional predicate)
2740 "Like `file-name-completion' for Tramp files."
2741 (unless (tramp-tramp-file-p directory)
2742 (error
2743 "tramp-handle-file-name-completion invoked on non-tramp directory `%s'"
2744 directory))
2745 (try-completion
2746 filename
2747 (mapcar 'list (file-name-all-completions filename directory))
2748 (when predicate
2749 (lambda (x) (funcall predicate (expand-file-name (car x) directory))))))
2750
2751(defun tramp-handle-file-name-directory (file)
2752 "Like `file-name-directory' but aware of Tramp files."
2753 ;; Everything except the last filename thing is the directory. We
2754 ;; cannot apply `with-parsed-tramp-file-name', because this expands
2755 ;; the remote file name parts. This is a problem when we are in
2756 ;; file name completion.
2757 (let ((v (tramp-dissect-file-name file t)))
2758 ;; Run the command on the localname portion only.
2759 (tramp-make-tramp-file-name
2760 (tramp-file-name-method v)
2761 (tramp-file-name-user v)
2762 (tramp-file-name-host v)
2763 (tramp-run-real-handler
2764 'file-name-directory (list (or (tramp-file-name-localname v) ""))))))
2765
2766(defun tramp-handle-file-name-nondirectory (file)
2767 "Like `file-name-nondirectory' but aware of Tramp files."
2768 (with-parsed-tramp-file-name file nil
2769 (tramp-run-real-handler 'file-name-nondirectory (list localname))))
2770
bd8fadca
MA
2771(defun tramp-handle-file-newer-than-file-p (file1 file2)
2772 "Like `file-newer-than-file-p' for Tramp files."
2773 (cond
2774 ((not (file-exists-p file1)) nil)
2775 ((not (file-exists-p file2)) t)
2776 (t (tramp-time-less-p (nth 5 (file-attributes file2))
2777 (nth 5 (file-attributes file1))))))
2778
4a93e698
MA
2779(defun tramp-handle-file-regular-p (filename)
2780 "Like `file-regular-p' for Tramp files."
2781 (and (file-exists-p filename)
2782 (eq ?- (aref (nth 8 (file-attributes filename)) 0))))
2783
2784(defun tramp-handle-file-remote-p (filename &optional identification connected)
2785 "Like `file-remote-p' for Tramp files."
2786 (let ((tramp-verbose 3))
2787 (when (tramp-tramp-file-p filename)
2788 (let* ((v (tramp-dissect-file-name filename))
2789 (p (tramp-get-connection-process v))
2790 (c (and p (processp p) (memq (process-status p) '(run open)))))
2791 ;; We expand the file name only, if there is already a connection.
2792 (with-parsed-tramp-file-name
2793 (if c (expand-file-name filename) filename) nil
2794 (and (or (not connected) c)
2795 (cond
2796 ((eq identification 'method) method)
2797 ((eq identification 'user) user)
2798 ((eq identification 'host) host)
2799 ((eq identification 'localname) localname)
2800 (t (tramp-make-tramp-file-name method user host "")))))))))
2801
2802(defun tramp-handle-file-symlink-p (filename)
2803 "Like `file-symlink-p' for Tramp files."
2804 (with-parsed-tramp-file-name filename nil
2805 (let ((x (car (file-attributes filename))))
2806 (when (stringp x)
2807 ;; When Tramp is running on VMS, then `file-name-absolute-p'
2808 ;; might do weird things.
2809 (if (file-name-absolute-p x)
2810 (tramp-make-tramp-file-name method user host x)
2811 x)))))
2812
2813(defun tramp-handle-find-backup-file-name (filename)
2814 "Like `find-backup-file-name' for Tramp files."
2815 (with-parsed-tramp-file-name filename nil
2816 ;; We set both variables. It doesn't matter whether it is
2817 ;; Emacs or XEmacs.
2818 (let ((backup-directory-alist
2819 ;; Emacs case.
2820 (when (boundp 'backup-directory-alist)
2821 (if (symbol-value 'tramp-backup-directory-alist)
2822 (mapcar
2823 (lambda (x)
2824 (cons
2825 (car x)
2826 (if (and (stringp (cdr x))
2827 (file-name-absolute-p (cdr x))
2828 (not (tramp-file-name-p (cdr x))))
2829 (tramp-make-tramp-file-name method user host (cdr x))
2830 (cdr x))))
2831 (symbol-value 'tramp-backup-directory-alist))
2832 (symbol-value 'backup-directory-alist))))
2833
2834 (bkup-backup-directory-info
2835 ;; XEmacs case.
2836 (when (boundp 'bkup-backup-directory-info)
2837 (if (symbol-value 'tramp-bkup-backup-directory-info)
2838 (mapcar
2839 (lambda (x)
2840 (nconc
2841 (list (car x))
2842 (list
2843 (if (and (stringp (car (cdr x)))
2844 (file-name-absolute-p (car (cdr x)))
2845 (not (tramp-file-name-p (car (cdr x)))))
2846 (tramp-make-tramp-file-name
2847 method user host (car (cdr x)))
2848 (car (cdr x))))
2849 (cdr (cdr x))))
2850 (symbol-value 'tramp-bkup-backup-directory-info))
2851 (symbol-value 'bkup-backup-directory-info)))))
2852
2853 (tramp-run-real-handler 'find-backup-file-name (list filename)))))
2854
2855(defun tramp-handle-insert-file-contents
2856 (filename &optional visit beg end replace)
2857 "Like `insert-file-contents' for Tramp files."
2858 (barf-if-buffer-read-only)
2859 (setq filename (expand-file-name filename))
2860 (let (result local-copy remote-copy)
2861 (with-parsed-tramp-file-name filename nil
2fe4b125
MA
2862 (tramp-with-progress-reporter
2863 v 3 (format "Inserting `%s'" filename)
2864 (unwind-protect
2865 (if (not (file-exists-p filename))
2866 ;; We don't raise a Tramp error, because it might be
2867 ;; suppressed, like in `find-file-noselect-1'.
2868 (signal 'file-error
2869 (list "File not found on remote host" filename))
2870
2871 (if (and (tramp-local-host-p v)
2872 (let (file-name-handler-alist)
2873 (file-readable-p localname)))
2874 ;; Short track: if we are on the local host, we can
2875 ;; run directly.
2876 (setq result
2877 (tramp-run-real-handler
2878 'insert-file-contents
2879 (list localname visit beg end replace)))
2880
2881 ;; When we shall insert only a part of the file, we
2882 ;; copy this part.
2883 (when (or beg end)
2884 (setq remote-copy (tramp-make-tramp-temp-file v))
2885 ;; This is defined in tramp-sh.el. Let's assume
2886 ;; this is loaded already.
2887 (tramp-compat-funcall
2888 'tramp-send-command
2889 v
2890 (cond
2891 ((and beg end)
2892 (format "dd bs=1 skip=%d if=%s count=%d of=%s"
2893 beg (tramp-shell-quote-argument localname)
2894 (- end beg) remote-copy))
2895 (beg
2896 (format "dd bs=1 skip=%d if=%s of=%s"
2897 beg (tramp-shell-quote-argument localname)
2898 remote-copy))
2899 (end
2900 (format "dd bs=1 count=%d if=%s of=%s"
2901 end (tramp-shell-quote-argument localname)
2902 remote-copy)))))
2903
2904 ;; `insert-file-contents-literally' takes care to
2905 ;; avoid calling jka-compr. By let-binding
2906 ;; `inhibit-file-name-operation', we propagate that
2907 ;; care to the `file-local-copy' operation.
2908 (setq local-copy
2909 (let ((inhibit-file-name-operation
2910 (when (eq inhibit-file-name-operation
2911 'insert-file-contents)
2912 'file-local-copy)))
2913 (cond
2914 ((stringp remote-copy)
2915 (file-local-copy
2916 (tramp-make-tramp-file-name
2917 method user host remote-copy)))
2918 ((stringp tramp-temp-buffer-file-name)
2919 (copy-file filename tramp-temp-buffer-file-name 'ok)
2920 tramp-temp-buffer-file-name)
2921 (t (file-local-copy filename)))))
2922
2923 ;; When the file is not readable for the owner, it
2924 ;; cannot be inserted, even if it is readable for the
2925 ;; group or for everybody.
2926 (set-file-modes
2927 local-copy (tramp-compat-octal-to-decimal "0600"))
2928
2929 (when (and (null remote-copy)
2930 (tramp-get-method-parameter
2931 method 'tramp-copy-keep-tmpfile))
2932 ;; We keep the local file for performance reasons,
2933 ;; useful for "rsync".
2934 (setq tramp-temp-buffer-file-name local-copy))
2935
4a93e698
MA
2936 ;; We must ensure that `file-coding-system-alist'
2937 ;; matches `local-copy'.
2938 (let ((file-coding-system-alist
2939 (tramp-find-file-name-coding-system-alist
2940 filename local-copy)))
2941 (setq result
2942 (insert-file-contents
2fe4b125
MA
2943 local-copy nil nil nil replace)))))
2944
2945 ;; Save exit.
2946 (progn
2947 (when visit
2948 (setq buffer-file-name filename)
2949 (setq buffer-read-only (not (file-writable-p filename)))
2950 (set-visited-file-modtime)
2951 (set-buffer-modified-p nil))
2952 (when (and (stringp local-copy)
2953 (or remote-copy (null tramp-temp-buffer-file-name)))
2954 (delete-file local-copy))
2955 (when (stringp remote-copy)
2956 (delete-file
2957 (tramp-make-tramp-file-name method user host remote-copy)))))))
4a93e698
MA
2958
2959 ;; Result.
2960 (list (expand-file-name filename)
2961 (cadr result))))
2962
2963(defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
2964 "Like `load' for Tramp files."
2965 (with-parsed-tramp-file-name (expand-file-name file) nil
2966 (unless nosuffix
2967 (cond ((file-exists-p (concat file ".elc"))
2968 (setq file (concat file ".elc")))
2969 ((file-exists-p (concat file ".el"))
2970 (setq file (concat file ".el")))))
2971 (when must-suffix
2972 ;; The first condition is always true for absolute file names.
2973 ;; Included for safety's sake.
2974 (unless (or (file-name-directory file)
2975 (string-match "\\.elc?\\'" file))
2976 (tramp-error
2977 v 'file-error
2978 "File `%s' does not include a `.el' or `.elc' suffix" file)))
2979 (unless noerror
2980 (when (not (file-exists-p file))
2981 (tramp-error v 'file-error "Cannot load nonexistent file `%s'" file)))
2982 (if (not (file-exists-p file))
2983 nil
2984 (let ((tramp-message-show-message (not nomessage)))
7d520089 2985 (tramp-with-progress-reporter v 0 (format "Loading %s" file)
4a93e698
MA
2986 (let ((local-copy (file-local-copy file)))
2987 ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
2988 (unwind-protect
2989 (load local-copy noerror t t)
2990 (delete-file local-copy)))))
2991 t)))
2992
f5e29b9b
MA
2993(defun tramp-handle-shell-command
2994 (command &optional output-buffer error-buffer)
2995 "Like `shell-command' for Tramp files."
2996 (let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
2997 ;; We cannot use `shell-file-name' and `shell-command-switch',
2998 ;; they are variables of the local host.
2999 (args (append
3000 (cons
3001 (tramp-get-method-parameter
3002 (tramp-file-name-method
3003 (tramp-dissect-file-name default-directory))
3004 'tramp-remote-shell)
3005 (tramp-get-method-parameter
3006 (tramp-file-name-method
3007 (tramp-dissect-file-name default-directory))
3008 'tramp-remote-shell-args))
3009 (list (substring command 0 asynchronous))))
3010 current-buffer-p
3011 (output-buffer
3012 (cond
3013 ((bufferp output-buffer) output-buffer)
3014 ((stringp output-buffer) (get-buffer-create output-buffer))
3015 (output-buffer
3016 (setq current-buffer-p t)
3017 (current-buffer))
3018 (t (get-buffer-create
3019 (if asynchronous
3020 "*Async Shell Command*"
3021 "*Shell Command Output*")))))
3022 (error-buffer
3023 (cond
3024 ((bufferp error-buffer) error-buffer)
3025 ((stringp error-buffer) (get-buffer-create error-buffer))))
3026 (buffer
3027 (if (and (not asynchronous) error-buffer)
3028 (with-parsed-tramp-file-name default-directory nil
3029 (list output-buffer (tramp-make-tramp-temp-file v)))
3030 output-buffer))
3031 (p (get-buffer-process output-buffer)))
3032
3033 ;; Check whether there is another process running. Tramp does not
3034 ;; support 2 (asynchronous) processes in parallel.
3035 (when p
3036 (if (yes-or-no-p "A command is running. Kill it? ")
3037 (ignore-errors (kill-process p))
3038 (error "Shell command in progress")))
3039
3040 (if current-buffer-p
3041 (progn
3042 (barf-if-buffer-read-only)
3043 (push-mark nil t))
3044 (with-current-buffer output-buffer
3045 (setq buffer-read-only nil)
3046 (erase-buffer)))
3047
3048 (if (and (not current-buffer-p) (integerp asynchronous))
3049 (prog1
3050 ;; Run the process.
a7b88dc6 3051 (setq p (apply 'start-file-process "*Async Shell*" buffer args))
f5e29b9b
MA
3052 ;; Display output.
3053 (pop-to-buffer output-buffer)
3054 (setq mode-line-process '(":%s"))
a7b88dc6
MA
3055 (shell-mode)
3056 (set-process-sentinel p 'shell-command-sentinel)
3057 (set-process-filter p 'comint-output-filter))
f5e29b9b
MA
3058
3059 (prog1
3060 ;; Run the process.
3061 (apply 'process-file (car args) nil buffer nil (cdr args))
3062 ;; Insert error messages if they were separated.
3063 (when (listp buffer)
3064 (with-current-buffer error-buffer
3065 (insert-file-contents (cadr buffer)))
3066 (delete-file (cadr buffer)))
3067 (if current-buffer-p
3068 ;; This is like exchange-point-and-mark, but doesn't
3069 ;; activate the mark. It is cleaner to avoid activation,
3070 ;; even though the command loop would deactivate the mark
3071 ;; because we inserted text.
3072 (goto-char (prog1 (mark t)
3073 (set-marker (mark-marker) (point)
3074 (current-buffer))))
3075 ;; There's some output, display it.
3076 (when (with-current-buffer output-buffer (> (point-max) (point-min)))
3077 (if (functionp 'display-message-or-buffer)
3078 (tramp-compat-funcall 'display-message-or-buffer output-buffer)
3079 (pop-to-buffer output-buffer))))))))
3080
4a93e698
MA
3081(defun tramp-handle-substitute-in-file-name (filename)
3082 "Like `substitute-in-file-name' for Tramp files.
3083\"//\" and \"/~\" substitute only in the local filename part.
51aba3f3 3084If the URL Tramp syntax is chosen, \"//\" as method delimiter and \"/~\" at
4a93e698
MA
3085beginning of local filename are not substituted."
3086 ;; First, we must replace environment variables.
3087 (setq filename (tramp-replace-environment-variables filename))
3088 (with-parsed-tramp-file-name filename nil
3089 (if (equal tramp-syntax 'url)
3090 ;; We need to check localname only. The other parts cannot contain
3091 ;; "//" or "/~".
3092 (if (and (> (length localname) 1)
3093 (or (string-match "//" localname)
3094 (string-match "/~" localname 1)))
3095 (tramp-run-real-handler 'substitute-in-file-name (list filename))
3096 (tramp-make-tramp-file-name
3097 (when method (substitute-in-file-name method))
3098 (when user (substitute-in-file-name user))
3099 (when host (substitute-in-file-name host))
3100 (when localname
3101 (tramp-run-real-handler
3102 'substitute-in-file-name (list localname)))))
3103 ;; Ignore in LOCALNAME everything before "//" or "/~".
3104 (when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname))
3105 (setq filename
3106 (concat (file-remote-p filename)
3107 (replace-match "\\1" nil nil localname)))
3108 ;; "/m:h:~" does not work for completion. We use "/m:h:~/".
3109 (when (string-match "~$" filename)
3110 (setq filename (concat filename "/"))))
3111 (tramp-run-real-handler 'substitute-in-file-name (list filename)))))
3112
3113(defun tramp-handle-unhandled-file-name-directory (filename)
3114 "Like `unhandled-file-name-directory' for Tramp files."
3115 ;; With Emacs 23, we could simply return `nil'. But we must keep it
3116 ;; for backward compatibility.
3117 (expand-file-name "~/"))
b88f2d0a 3118
4a93e698 3119;;; Functions for establishing connection:
fb7933a3 3120
ac474af1
KG
3121;; The following functions are actions to be taken when seeing certain
3122;; prompts from the remote host. See the variable
3123;; `tramp-actions-before-shell' for usage of these functions.
3124
00d6fd04 3125(defun tramp-action-login (proc vec)
ac474af1 3126 "Send the login name."
00d6fd04 3127 (when (not (stringp tramp-current-user))
a5509865
MA
3128 (setq tramp-current-user
3129 (with-connection-property vec "login-as"
3130 (save-window-excursion
3131 (let ((enable-recursive-minibuffers t))
3132 (pop-to-buffer (tramp-get-connection-buffer vec))
3133 (read-string (match-string 0)))))))
00d6fd04
MA
3134 (with-current-buffer (tramp-get-connection-buffer vec)
3135 (tramp-message vec 6 "\n%s" (buffer-string)))
a5509865 3136 (tramp-message vec 3 "Sending login name `%s'" tramp-current-user)
4cb0aa75 3137 (tramp-send-string vec (concat tramp-current-user tramp-local-end-of-line)))
00d6fd04
MA
3138
3139(defun tramp-action-password (proc vec)
ac474af1 3140 "Query the user for a password."
70c11b0b 3141 (with-current-buffer (process-buffer proc)
8c8fc5df
MA
3142 (let ((enable-recursive-minibuffers t))
3143 (tramp-check-for-regexp proc tramp-password-prompt-regexp)
3144 (tramp-message vec 3 "Sending %s" (match-string 1))
2fe4b125
MA
3145 ;; We don't call `tramp-send-string' in order to hide the
3146 ;; password from the debug buffer.
3147 (process-send-string
3148 proc (concat (tramp-read-passwd proc) tramp-local-end-of-line))
8c8fc5df
MA
3149 ;; Hide password prompt.
3150 (narrow-to-region (point-max) (point-max)))))
00d6fd04
MA
3151
3152(defun tramp-action-succeed (proc vec)
ac474af1 3153 "Signal success in finding shell prompt."
ac474af1
KG
3154 (throw 'tramp-action 'ok))
3155
00d6fd04 3156(defun tramp-action-permission-denied (proc vec)
ac474af1 3157 "Signal permission denied."
00d6fd04 3158 (kill-process proc)
ac474af1
KG
3159 (throw 'tramp-action 'permission-denied))
3160
00d6fd04 3161(defun tramp-action-yesno (proc vec)
3cdaec13
KG
3162 "Ask the user for confirmation using `yes-or-no-p'.
3163Send \"yes\" to remote process on confirmation, abort otherwise.
3164See also `tramp-action-yn'."
ac474af1 3165 (save-window-excursion
00d6fd04
MA
3166 (let ((enable-recursive-minibuffers t))
3167 (save-match-data (pop-to-buffer (tramp-get-connection-buffer vec)))
3168 (unless (yes-or-no-p (match-string 0))
3169 (kill-process proc)
3170 (throw 'tramp-action 'permission-denied))
3171 (with-current-buffer (tramp-get-connection-buffer vec)
3172 (tramp-message vec 6 "\n%s" (buffer-string)))
4cb0aa75 3173 (tramp-send-string vec (concat "yes" tramp-local-end-of-line)))))
00d6fd04
MA
3174
3175(defun tramp-action-yn (proc vec)
3cdaec13
KG
3176 "Ask the user for confirmation using `y-or-n-p'.
3177Send \"y\" to remote process on confirmation, abort otherwise.
3178See also `tramp-action-yesno'."
3179 (save-window-excursion
00d6fd04
MA
3180 (let ((enable-recursive-minibuffers t))
3181 (save-match-data (pop-to-buffer (tramp-get-connection-buffer vec)))
3182 (unless (y-or-n-p (match-string 0))
3183 (kill-process proc)
3184 (throw 'tramp-action 'permission-denied))
3185 (with-current-buffer (tramp-get-connection-buffer vec)
3186 (tramp-message vec 6 "\n%s" (buffer-string)))
4cb0aa75 3187 (tramp-send-string vec (concat "y" tramp-local-end-of-line)))))
00d6fd04
MA
3188
3189(defun tramp-action-terminal (proc vec)
487f4fb7
KG
3190 "Tell the remote host which terminal type to use.
3191The terminal type can be configured with `tramp-terminal-type'."
00d6fd04 3192 (tramp-message vec 5 "Setting `%s' as terminal type." tramp-terminal-type)
7e780ff1
MA
3193 (with-current-buffer (tramp-get-connection-buffer vec)
3194 (tramp-message vec 6 "\n%s" (buffer-string)))
4cb0aa75 3195 (tramp-send-string vec (concat tramp-terminal-type tramp-local-end-of-line)))
487f4fb7 3196
00d6fd04 3197(defun tramp-action-process-alive (proc vec)
a94d821f 3198 "Check, whether a process has finished."
00d6fd04 3199 (unless (memq (process-status proc) '(run open))
19a87064
MA
3200 (throw 'tramp-action 'process-died)))
3201
00d6fd04 3202(defun tramp-action-out-of-band (proc vec)
a94d821f 3203 "Check, whether an out-of-band copy has finished."
00d6fd04
MA
3204 (cond ((and (memq (process-status proc) '(stop exit))
3205 (zerop (process-exit-status proc)))
3206 (tramp-message vec 3 "Process has finished.")
38c65fca 3207 (throw 'tramp-action 'ok))
00d6fd04
MA
3208 ((or (and (memq (process-status proc) '(stop exit))
3209 (not (zerop (process-exit-status proc))))
3210 (memq (process-status proc) '(signal)))
01917a18
MA
3211 ;; `scp' could have copied correctly, but set modes could have failed.
3212 ;; This can be ignored.
00d6fd04
MA
3213 (with-current-buffer (process-buffer proc)
3214 (goto-char (point-min))
3215 (if (re-search-forward tramp-operation-not-permitted-regexp nil t)
3216 (progn
3217 (tramp-message vec 5 "'set mode' error ignored.")
3218 (tramp-message vec 3 "Process has finished.")
3219 (throw 'tramp-action 'ok))
3220 (tramp-message vec 3 "Process has died.")
3221 (throw 'tramp-action 'process-died))))
38c65fca
KG
3222 (t nil)))
3223
4a93e698 3224;;; Functions for processing the actions:
ac474af1 3225
00d6fd04 3226(defun tramp-process-one-action (proc vec actions)
ac474af1 3227 "Wait for output from the shell and perform one action."
00d6fd04 3228 (let (found todo item pattern action)
e6466697 3229 (while (not found)
00d6fd04
MA
3230 ;; Reread output once all actions have been performed.
3231 ;; Obviously, the output was not complete.
3232 (tramp-accept-process-output proc 1)
e6466697
MA
3233 (setq todo actions)
3234 (while todo
e6466697 3235 (setq item (pop todo))
95d610cb 3236 (setq pattern (format "\\(%s\\)\\'" (symbol-value (nth 0 item))))
e6466697 3237 (setq action (nth 1 item))
00d6fd04
MA
3238 (tramp-message
3239 vec 5 "Looking for regexp \"%s\" from remote shell" pattern)
3240 (when (tramp-check-for-regexp proc pattern)
3241 (tramp-message vec 5 "Call `%s'" (symbol-name action))
3242 (setq found (funcall action proc vec)))))
e6466697
MA
3243 found))
3244
bfd31217
MA
3245(defun tramp-process-actions (proc vec pos actions &optional timeout)
3246 "Perform ACTIONS until success or TIMEOUT.
3247PROC and VEC indicate the remote connection to be used. POS, if
3248set, is the starting point of the region to be deleted in the
3249connection buffer."
9e021389 3250 ;; Preserve message for `progress-reporter'.
6139f995 3251 (tramp-compat-with-temp-message ""
2fe4b125 3252 ;; Enable `auth-source' and `password-cache'. We must use
2fb0a219
MA
3253 ;; tramp-current-* variables in case we have several hops.
3254 (tramp-set-connection-property
3255 (tramp-dissect-file-name
3256 (tramp-make-tramp-file-name
3257 tramp-current-method tramp-current-user tramp-current-host ""))
3258 "first-password-request" t)
158d5945
MA
3259 (save-restriction
3260 (let (exit)
3261 (while (not exit)
3262 (tramp-message proc 3 "Waiting for prompts from remote shell")
3263 (setq exit
3264 (catch 'tramp-action
3265 (if timeout
3266 (with-timeout (timeout)
3267 (tramp-process-one-action proc vec actions))
3268 (tramp-process-one-action proc vec actions)))))
3269 (with-current-buffer (tramp-get-connection-buffer vec)
3270 (widen)
3271 (tramp-message vec 6 "\n%s" (buffer-string)))
3272 (unless (eq exit 'ok)
3273 (tramp-clear-passwd vec)
3274 (tramp-error-with-buffer
3275 nil vec 'file-error
3276 (cond
3277 ((eq exit 'permission-denied) "Permission denied")
3278 ((eq exit 'process-died) "Process died")
bfd31217
MA
3279 (t "Login failed"))))
3280 (when (numberp pos)
3281 (with-current-buffer (tramp-get-connection-buffer vec)
3282 (let (buffer-read-only) (delete-region pos (point)))))))))
fb7933a3 3283
4a93e698 3284:;; Utility functions:
fb7933a3 3285
00d6fd04 3286(defun tramp-accept-process-output (&optional proc timeout timeout-msecs)
d2a2c17f
MA
3287 "Like `accept-process-output' for Tramp processes.
3288This is needed in order to hide `last-coding-system-used', which is set
3289for process communication also."
00d6fd04
MA
3290 (with-current-buffer (process-buffer proc)
3291 (tramp-message proc 10 "%s %s" proc (process-status proc))
3292 (let (buffer-read-only last-coding-system-used)
3293 ;; Under Windows XP, accept-process-output doesn't return
3294 ;; sometimes. So we add an additional timeout.
3295 (with-timeout ((or timeout 1))
3296 (accept-process-output proc timeout timeout-msecs)))
3297 (tramp-message proc 10 "\n%s" (buffer-string))))
3298
3299(defun tramp-check-for-regexp (proc regexp)
a94d821f 3300 "Check, whether REGEXP is contained in process buffer of PROC.
00d6fd04
MA
3301Erase echoed commands if exists."
3302 (with-current-buffer (process-buffer proc)
3303 (goto-char (point-min))
674da028 3304
00d6fd04
MA
3305 ;; Check whether we need to remove echo output.
3306 (when (and (tramp-get-connection-property proc "check-remote-echo" nil)
3307 (re-search-forward tramp-echoed-echo-mark-regexp nil t))
3308 (let ((begin (match-beginning 0)))
3309 (when (re-search-forward tramp-echoed-echo-mark-regexp nil t)
3310 ;; Discard echo from remote output.
3311 (tramp-set-connection-property proc "check-remote-echo" nil)
3312 (tramp-message proc 5 "echo-mark found")
b533bc97 3313 (forward-line 1)
00d6fd04
MA
3314 (delete-region begin (point))
3315 (goto-char (point-min)))))
674da028 3316
68712eb6
MA
3317 (when (or (not (tramp-get-connection-property proc "check-remote-echo" nil))
3318 ;; Sometimes, the echo string is suppressed on the remote side.
3319 (not (string-equal
0d5852cf
MA
3320 (tramp-compat-funcall
3321 'substring-no-properties tramp-echo-mark-marker
68712eb6 3322 0 (min tramp-echo-mark-marker-length (1- (point-max))))
0d5852cf
MA
3323 (tramp-compat-funcall
3324 'buffer-substring-no-properties
68712eb6 3325 1 (min (1+ tramp-echo-mark-marker-length) (point-max))))))
70c11b0b 3326 ;; No echo to be handled, now we can look for the regexp.
2fe4b125
MA
3327 ;; Sometimes, lines are much to long, and we run into a "Stack
3328 ;; overflow in regexp matcher". For example, //DIRED// lines of
3329 ;; directory listings with some thousand files. Therefore, we
3330 ;; look from the end.
046e38ce 3331 (goto-char (point-max))
2fe4b125 3332 (ignore-errors (re-search-backward regexp nil t)))))
d2a2c17f 3333
fb7933a3
KG
3334(defun tramp-wait-for-regexp (proc timeout regexp)
3335 "Wait for a REGEXP to appear from process PROC within TIMEOUT seconds.
3336Expects the output of PROC to be sent to the current buffer. Returns
3337the string that matched, or nil. Waits indefinitely if TIMEOUT is
3338nil."
00d6fd04
MA
3339 (with-current-buffer (process-buffer proc)
3340 (let ((found (tramp-check-for-regexp proc regexp))
3341 (start-time (current-time)))
3342 (cond (timeout
3343 ;; Work around a bug in XEmacs 21, where the timeout
3344 ;; expires faster than it should. This degenerates
3345 ;; to polling for buggy XEmacsen, but oh, well.
3346 (while (and (not found)
3347 (< (tramp-time-diff (current-time) start-time)
3348 timeout))
3349 (with-timeout (timeout)
3350 (while (not found)
3351 (tramp-accept-process-output proc 1)
3352 (unless (memq (process-status proc) '(run open))
3353 (tramp-error-with-buffer
3354 nil proc 'file-error "Process has died"))
3355 (setq found (tramp-check-for-regexp proc regexp))))))
3356 (t
3357 (while (not found)
3358 (tramp-accept-process-output proc 1)
3359 (unless (memq (process-status proc) '(run open))
3360 (tramp-error-with-buffer
3361 nil proc 'file-error "Process has died"))
3362 (setq found (tramp-check-for-regexp proc regexp)))))
3363 (tramp-message proc 6 "\n%s" (buffer-string))
fb7933a3 3364 (when (not found)
00d6fd04
MA
3365 (if timeout
3366 (tramp-error
3367 proc 'file-error "[[Regexp `%s' not found in %d secs]]"
3368 regexp timeout)
3369 (tramp-error proc 'file-error "[[Regexp `%s' not found]]" regexp)))
3370 found)))
fb7933a3 3371
7432277c
KG
3372;; It seems that Tru64 Unix does not like it if long strings are sent
3373;; to it in one go. (This happens when sending the Perl
3374;; `file-attributes' implementation, for instance.) Therefore, we
27e813fe 3375;; have this function which sends the string in chunks.
00d6fd04
MA
3376(defun tramp-send-string (vec string)
3377 "Send the STRING via connection VEC.
7432277c
KG
3378
3379The STRING is expected to use Unix line-endings, but the lines sent to
3380the remote host use line-endings as defined in the variable
00d6fd04
MA
3381`tramp-rsh-end-of-line'. The communication buffer is erased before sending."
3382 (let* ((p (tramp-get-connection-process vec))
3383 (chunksize (tramp-get-connection-property p "chunksize" nil)))
3384 (unless p
3385 (tramp-error
3386 vec 'file-error "Can't send string to remote host -- not logged in"))
3387 (tramp-set-connection-property p "last-cmd-time" (current-time))
3388 (tramp-message vec 10 "%s" string)
3389 (with-current-buffer (tramp-get-connection-buffer vec)
3390 ;; Clean up the buffer. We cannot call `erase-buffer' because
3391 ;; narrowing might be in effect.
3392 (let (buffer-read-only) (delete-region (point-min) (point-max)))
27e813fe 3393 ;; Replace "\n" by `tramp-rsh-end-of-line'.
00d6fd04
MA
3394 (setq string
3395 (mapconcat 'identity
70c11b0b 3396 (tramp-compat-split-string string "\n")
00d6fd04
MA
3397 tramp-rsh-end-of-line))
3398 (unless (or (string= string "")
3399 (string-equal (substring string -1) tramp-rsh-end-of-line))
3400 (setq string (concat string tramp-rsh-end-of-line)))
27e813fe 3401 ;; Send the string.
00d6fd04
MA
3402 (if (and chunksize (not (zerop chunksize)))
3403 (let ((pos 0)
3404 (end (length string)))
3405 (while (< pos end)
3406 (tramp-message
3407 vec 10 "Sending chunk from %s to %s"
3408 pos (min (+ pos chunksize) end))
3409 (process-send-string
3410 p (substring string pos (min (+ pos chunksize) end)))
3411 (setq pos (+ pos chunksize))))
3412 (process-send-string p string)))))
fb7933a3 3413
ce3f516f 3414(defun tramp-get-inode (vec)
00d6fd04
MA
3415 "Returns the virtual inode number.
3416If it doesn't exist, generate a new one."
530739c9
MA
3417 (with-file-property vec (tramp-file-name-localname vec) "inode"
3418 (setq tramp-inodes (1+ tramp-inodes))))
00d6fd04
MA
3419
3420(defun tramp-get-device (vec)
c82c5727
LH
3421 "Returns the virtual device number.
3422If it doesn't exist, generate a new one."
530739c9
MA
3423 (with-connection-property (tramp-get-connection-process vec) "device"
3424 (cons -1 (setq tramp-devices (1+ tramp-devices)))))
fb7933a3 3425
00d6fd04 3426(defun tramp-equal-remote (file1 file2)
a94d821f 3427 "Check, whether the remote parts of FILE1 and FILE2 are identical.
00d6fd04
MA
3428The check depends on method, user and host name of the files. If
3429one of the components is missing, the default values are used.
3430The local file name parts of FILE1 and FILE2 are not taken into
3431account.
fb7933a3 3432
00d6fd04
MA
3433Example:
3434
3435 (tramp-equal-remote \"/ssh::/etc\" \"/<your host name>:/home\")
3436
3437would yield `t'. On the other hand, the following check results in nil:
3438
3439 (tramp-equal-remote \"/sudo::/etc\" \"/su::/etc\")"
9e6ab520
MA
3440 (and (stringp (file-remote-p file1))
3441 (stringp (file-remote-p file2))
94be87e8 3442 (string-equal (file-remote-p file1) (file-remote-p file2))))
00d6fd04 3443
2fe4b125 3444;;;###tramp-autoload
4a93e698
MA
3445(defun tramp-mode-string-to-int (mode-string)
3446 "Converts a ten-letter `drwxrwxrwx'-style mode string into mode bits."
3447 (let* (case-fold-search
3448 (mode-chars (string-to-vector mode-string))
3449 (owner-read (aref mode-chars 1))
3450 (owner-write (aref mode-chars 2))
3451 (owner-execute-or-setid (aref mode-chars 3))
3452 (group-read (aref mode-chars 4))
3453 (group-write (aref mode-chars 5))
3454 (group-execute-or-setid (aref mode-chars 6))
3455 (other-read (aref mode-chars 7))
3456 (other-write (aref mode-chars 8))
3457 (other-execute-or-sticky (aref mode-chars 9)))
3458 (save-match-data
3459 (logior
3460 (cond
3461 ((char-equal owner-read ?r) (tramp-compat-octal-to-decimal "00400"))
3462 ((char-equal owner-read ?-) 0)
3463 (t (error "Second char `%c' must be one of `r-'" owner-read)))
3464 (cond
3465 ((char-equal owner-write ?w) (tramp-compat-octal-to-decimal "00200"))
3466 ((char-equal owner-write ?-) 0)
3467 (t (error "Third char `%c' must be one of `w-'" owner-write)))
3468 (cond
3469 ((char-equal owner-execute-or-setid ?x)
3470 (tramp-compat-octal-to-decimal "00100"))
3471 ((char-equal owner-execute-or-setid ?S)
3472 (tramp-compat-octal-to-decimal "04000"))
3473 ((char-equal owner-execute-or-setid ?s)
3474 (tramp-compat-octal-to-decimal "04100"))
3475 ((char-equal owner-execute-or-setid ?-) 0)
3476 (t (error "Fourth char `%c' must be one of `xsS-'"
3477 owner-execute-or-setid)))
3478 (cond
3479 ((char-equal group-read ?r) (tramp-compat-octal-to-decimal "00040"))
3480 ((char-equal group-read ?-) 0)
3481 (t (error "Fifth char `%c' must be one of `r-'" group-read)))
3482 (cond
3483 ((char-equal group-write ?w) (tramp-compat-octal-to-decimal "00020"))
3484 ((char-equal group-write ?-) 0)
3485 (t (error "Sixth char `%c' must be one of `w-'" group-write)))
3486 (cond
3487 ((char-equal group-execute-or-setid ?x)
3488 (tramp-compat-octal-to-decimal "00010"))
3489 ((char-equal group-execute-or-setid ?S)
3490 (tramp-compat-octal-to-decimal "02000"))
3491 ((char-equal group-execute-or-setid ?s)
3492 (tramp-compat-octal-to-decimal "02010"))
3493 ((char-equal group-execute-or-setid ?-) 0)
3494 (t (error "Seventh char `%c' must be one of `xsS-'"
3495 group-execute-or-setid)))
3496 (cond
3497 ((char-equal other-read ?r)
3498 (tramp-compat-octal-to-decimal "00004"))
3499 ((char-equal other-read ?-) 0)
3500 (t (error "Eighth char `%c' must be one of `r-'" other-read)))
3501 (cond
3502 ((char-equal other-write ?w) (tramp-compat-octal-to-decimal "00002"))
3503 ((char-equal other-write ?-) 0)
6196cffe 3504 (t (error "Ninth char `%c' must be one of `w-'" other-write)))
4a93e698
MA
3505 (cond
3506 ((char-equal other-execute-or-sticky ?x)
3507 (tramp-compat-octal-to-decimal "00001"))
3508 ((char-equal other-execute-or-sticky ?T)
3509 (tramp-compat-octal-to-decimal "01000"))
3510 ((char-equal other-execute-or-sticky ?t)
3511 (tramp-compat-octal-to-decimal "01001"))
3512 ((char-equal other-execute-or-sticky ?-) 0)
3513 (t (error "Tenth char `%c' must be one of `xtT-'"
3514 other-execute-or-sticky)))))))
3515
2fe4b125 3516;;;###tramp-autoload
4a93e698
MA
3517(defun tramp-local-host-p (vec)
3518 "Return t if this points to the local host, nil otherwise."
3519 ;; We cannot use `tramp-file-name-real-host'. A port is an
3520 ;; indication for an ssh tunnel or alike.
3521 (let ((host (tramp-file-name-host vec)))
3522 (and
3523 (stringp host)
3524 (string-match tramp-local-host-regexp host)
3525 ;; The method shall be applied to one of the shell file name
3526 ;; handler. `tramp-local-host-p' is also called for "smb" and
3527 ;; alike, where it must fail.
3528 (tramp-get-method-parameter
3529 (tramp-file-name-method vec) 'tramp-login-program)
3530 ;; The local temp directory must be writable for the other user.
3531 (file-writable-p
3532 (tramp-make-tramp-file-name
3533 (tramp-file-name-method vec)
3534 (tramp-file-name-user vec)
3535 host
3536 (tramp-compat-temporary-file-directory)))
3537 ;; On some systems, chown runs only for root.
3538 (or (zerop (user-uid))
3539 ;; This is defined in tramp-sh.el. Let's assume this is
3540 ;; loaded already.
3541 (zerop (tramp-compat-funcall 'tramp-get-remote-uid vec 'integer))))))
3542
710dec63
MA
3543(defun tramp-get-remote-tmpdir (vec)
3544 "Return directory for temporary files on the remote host identified by VEC."
3545 (with-connection-property vec "tmpdir"
3546 (let ((dir (tramp-make-tramp-file-name
3547 (tramp-file-name-method vec)
3548 (tramp-file-name-user vec)
3549 (tramp-file-name-host vec)
3550 (or
3551 (tramp-get-method-parameter
3552 (tramp-file-name-method vec) 'tramp-tmpdir)
3553 "/tmp"))))
3554 (if (and (file-directory-p dir) (file-writable-p dir))
3555 dir
3556 (tramp-error vec 'file-error "Directory %s not accessible" dir)))))
3557
2fe4b125 3558;;;###tramp-autoload
4a93e698
MA
3559(defun tramp-make-tramp-temp-file (vec)
3560 "Create a temporary file on the remote host identified by VEC.
3561Return the local name of the temporary file."
710dec63
MA
3562 (let ((prefix (expand-file-name
3563 tramp-temp-name-prefix (tramp-get-remote-tmpdir vec)))
4a93e698
MA
3564 result)
3565 (while (not result)
3566 ;; `make-temp-file' would be the natural choice for
3567 ;; implementation. But it calls `write-region' internally,
3568 ;; which also needs a temporary file - we would end in an
3569 ;; infinite loop.
3570 (setq result (make-temp-name prefix))
3571 (if (file-exists-p result)
3572 (setq result nil)
3573 ;; This creates the file by side effect.
3574 (set-file-times result)
3575 (set-file-modes result (tramp-compat-octal-to-decimal "0700"))))
3576
3577 ;; Return the local part.
3578 (with-parsed-tramp-file-name result nil localname)))
fb7933a3 3579
4a93e698
MA
3580(defun tramp-delete-temp-file-function ()
3581 "Remove temporary files related to current buffer."
3582 (when (stringp tramp-temp-buffer-file-name)
3583 (ignore-errors (delete-file tramp-temp-buffer-file-name))))
3584
3585(add-hook 'kill-buffer-hook 'tramp-delete-temp-file-function)
f5e29b9b 3586(add-hook 'tramp-unload-hook
4a93e698
MA
3587 (lambda ()
3588 (remove-hook 'kill-buffer-hook
3589 'tramp-delete-temp-file-function)))
3590
3591;;; Auto saving to a special directory:
c1105d05
MA
3592
3593(unless (tramp-exists-file-name-handler 'make-auto-save-file-name)
3594 (defadvice make-auto-save-file-name
3595 (around tramp-advice-make-auto-save-file-name () activate)
03c1ad43 3596 "Invoke `tramp-*-handle-make-auto-save-file-name' for Tramp files."
b533bc97 3597 (if (tramp-tramp-file-p (buffer-file-name))
7f49fe46
MA
3598 ;; We cannot call `tramp-handle-make-auto-save-file-name'
3599 ;; directly, because this would bypass the locking mechanism.
3600 (setq ad-return-value
3601 (tramp-file-name-handler 'make-auto-save-file-name))
a69c01a0 3602 ad-do-it))
191bb792
MA
3603 (add-hook
3604 'tramp-unload-hook
3605 (lambda ()
3606 (ad-remove-advice
3607 'make-auto-save-file-name
d7ec1df7
MA
3608 'around 'tramp-advice-make-auto-save-file-name)
3609 (ad-activate 'make-auto-save-file-name))))
fb7933a3 3610
b533bc97
MA
3611;; In XEmacs < 21.5, autosaved remote files have permission 0666 minus
3612;; umask. This is a security threat.
414da5ab
MA
3613
3614(defun tramp-set-auto-save-file-modes ()
3615 "Set permissions of autosaved remote files to the original permissions."
3616 (let ((bfn (buffer-file-name)))
b533bc97 3617 (when (and (tramp-tramp-file-p bfn)
b50dd0d2 3618 (buffer-modified-p)
414da5ab 3619 (stringp buffer-auto-save-file-name)
340b8d4f
MA
3620 (not (equal bfn buffer-auto-save-file-name)))
3621 (unless (file-exists-p buffer-auto-save-file-name)
3622 (write-region "" nil buffer-auto-save-file-name))
3623 ;; Permissions should be set always, because there might be an old
3624 ;; auto-saved file belonging to another original file. This could
3625 ;; be a security threat.
0f34aa77
MA
3626 (set-file-modes
3627 buffer-auto-save-file-name
3628 (or (file-modes bfn) (tramp-compat-octal-to-decimal "0600"))))))
414da5ab 3629
b533bc97
MA
3630(unless (and (featurep 'xemacs)
3631 (= emacs-major-version 21)
3632 (> emacs-minor-version 4))
a69c01a0
MA
3633 (add-hook 'auto-save-hook 'tramp-set-auto-save-file-modes)
3634 (add-hook 'tramp-unload-hook
aa485f7c
MA
3635 (lambda ()
3636 (remove-hook 'auto-save-hook 'tramp-set-auto-save-file-modes))))
414da5ab 3637
fb7933a3
KG
3638(defun tramp-subst-strs-in-string (alist string)
3639 "Replace all occurrences of the string FROM with TO in STRING.
3640ALIST is of the form ((FROM . TO) ...)."
3641 (save-match-data
3642 (while alist
3643 (let* ((pr (car alist))
3644 (from (car pr))
3645 (to (cdr pr)))
3646 (while (string-match (regexp-quote from) string)
3647 (setq string (replace-match to t t string)))
3648 (setq alist (cdr alist))))
3649 string))
3650
4a93e698 3651;;; Compatibility functions section:
fb7933a3 3652
2fe4b125 3653;;;###tramp-autoload
00d6fd04 3654(defun tramp-read-passwd (proc &optional prompt)
fb7933a3 3655 "Read a password from user (compat function).
5615d63f 3656Consults the auth-source package.
5ec2cc41 3657Invokes `password-read' if available, `read-passwd' else."
00d6fd04
MA
3658 (let* ((key (tramp-make-tramp-file-name
3659 tramp-current-method tramp-current-user
3660 tramp-current-host ""))
3661 (pw-prompt
3662 (or prompt
3663 (with-current-buffer (process-buffer proc)
3664 (tramp-check-for-regexp proc tramp-password-prompt-regexp)
563790b6
TZ
3665 (format "%s for %s " (capitalize (match-string 1)) key))))
3666 auth-info auth-passwd)
7540f029
MA
3667 (with-parsed-tramp-file-name key nil
3668 (prog1
3669 (or
7a6ebb1a
MA
3670 ;; See if auth-sources contains something useful, if it's
3671 ;; bound. `auth-source-user-or-password' is an obsoleted
3672 ;; function, it has been replaced by `auth-source-search'.
7540f029
MA
3673 (and (boundp 'auth-sources)
3674 (tramp-get-connection-property v "first-password-request" nil)
3675 ;; Try with Tramp's current method.
563790b6 3676 (if (fboundp 'auth-source-search)
7a6ebb1a 3677 (setq auth-info
2fb0a219
MA
3678 (tramp-compat-funcall
3679 'auth-source-search
3680 :max 1
3681 :user (or tramp-current-user t)
3682 :host tramp-current-host
3683 :port tramp-current-method)
3684 auth-passwd (plist-get (nth 0 auth-info) :secret)
3685 auth-passwd (if (functionp auth-passwd)
3686 (funcall auth-passwd)
3687 auth-passwd))
563790b6
TZ
3688 (tramp-compat-funcall
3689 'auth-source-user-or-password
3690 "password" tramp-current-host tramp-current-method)))
7540f029
MA
3691 ;; Try the password cache.
3692 (when (functionp 'password-read)
3693 (unless (tramp-get-connection-property
3694 v "first-password-request" nil)
0d5852cf 3695 (tramp-compat-funcall 'password-cache-remove key))
7540f029 3696 (let ((password
0d5852cf
MA
3697 (tramp-compat-funcall 'password-read pw-prompt key)))
3698 (tramp-compat-funcall 'password-cache-add key password)
7540f029
MA
3699 password))
3700 ;; Else, get the password interactively.
3701 (read-passwd pw-prompt))
3702 (tramp-set-connection-property v "first-password-request" nil)))))
00d6fd04 3703
2fe4b125 3704;;;###tramp-autoload
9c13938d
MA
3705(defun tramp-clear-passwd (vec)
3706 "Clear password cache for connection related to VEC."
0d5852cf
MA
3707 (tramp-compat-funcall
3708 'password-cache-remove
3709 (tramp-make-tramp-file-name
3710 (tramp-file-name-method vec)
3711 (tramp-file-name-user vec)
3712 (tramp-file-name-host vec)
3713 "")))
00d6fd04
MA
3714
3715;; Snarfed code from time-date.el and parse-time.el
3716
3717(defconst tramp-half-a-year '(241 17024)
3718"Evaluated by \"(days-to-time 183)\".")
3719
3720(defconst tramp-parse-time-months
3721 '(("jan" . 1) ("feb" . 2) ("mar" . 3)
3722 ("apr" . 4) ("may" . 5) ("jun" . 6)
3723 ("jul" . 7) ("aug" . 8) ("sep" . 9)
3724 ("oct" . 10) ("nov" . 11) ("dec" . 12))
3725 "Alist mapping month names to integers.")
3726
2fe4b125 3727;;;###tramp-autoload
00d6fd04
MA
3728(defun tramp-time-less-p (t1 t2)
3729 "Say whether time value T1 is less than time value T2."
3730 (unless t1 (setq t1 '(0 0)))
3731 (unless t2 (setq t2 '(0 0)))
3732 (or (< (car t1) (car t2))
3733 (and (= (car t1) (car t2))
3734 (< (nth 1 t1) (nth 1 t2)))))
3735
3736(defun tramp-time-subtract (t1 t2)
3737 "Subtract two time values.
3738Return the difference in the format of a time value."
3739 (unless t1 (setq t1 '(0 0)))
3740 (unless t2 (setq t2 '(0 0)))
3741 (let ((borrow (< (cadr t1) (cadr t2))))
3742 (list (- (car t1) (car t2) (if borrow 1 0))
3743 (- (+ (if borrow 65536 0) (cadr t1)) (cadr t2)))))
fb7933a3 3744
2fe4b125 3745;;;###tramp-autoload
fb7933a3
KG
3746(defun tramp-time-diff (t1 t2)
3747 "Return the difference between the two times, in seconds.
1a762140 3748T1 and T2 are time values (as returned by `current-time' for example)."
ea9d1443
KG
3749 (cond ((and (fboundp 'subtract-time)
3750 (fboundp 'float-time))
0d5852cf
MA
3751 (tramp-compat-funcall
3752 'float-time (tramp-compat-funcall 'subtract-time t1 t2)))
ea9d1443
KG
3753 ((and (fboundp 'subtract-time)
3754 (fboundp 'time-to-seconds))
0d5852cf
MA
3755 (tramp-compat-funcall
3756 'time-to-seconds (tramp-compat-funcall 'subtract-time t1 t2)))
fb7933a3 3757 ((fboundp 'itimer-time-difference)
0d5852cf
MA
3758 (tramp-compat-funcall
3759 'itimer-time-difference
3760 (if (< (length t1) 3) (append t1 '(0)) t1)
3761 (if (< (length t2) 3) (append t2 '(0)) t2)))
fb7933a3 3762 (t
00d6fd04 3763 (let ((time (tramp-time-subtract t1 t2)))
ea9d1443
KG
3764 (+ (* (car time) 65536.0)
3765 (cadr time)
3766 (/ (or (nth 2 time) 0) 1000000.0))))))
fb7933a3 3767
fb7933a3
KG
3768;; Currently (as of Emacs 20.5), the function `shell-quote-argument'
3769;; does not deal well with newline characters. Newline is replaced by
3770;; backslash newline. But if, say, the string `a backslash newline b'
3771;; is passed to a shell, the shell will expand this into "ab",
3772;; completely omitting the newline. This is not what was intended.
3773;; It does not appear to be possible to make the function
3774;; `shell-quote-argument' work with newlines without making it
3775;; dependent on the shell used. But within this package, we know that
3776;; we will always use a Bourne-like shell, so we use an approach which
3777;; groks newlines.
3778;;
3779;; The approach is simple: we call `shell-quote-argument', then
3780;; massage the newline part of the result.
3781;;
3782;; This function should produce a string which is grokked by a Unix
3783;; shell, even if the Emacs is running on Windows. Since this is the
3784;; kludges section, we bind `system-type' in such a way that
3785;; `shell-quote-arguments' behaves as if on Unix.
3786;;
3787;; Thanks to Mario DeWeerd for the hint that it is sufficient for this
3788;; function to work with Bourne-like shells.
3789;;
3790;; CCC: This function should be rewritten so that
3791;; `shell-quote-argument' is not used. This way, we are safe from
3792;; changes in `shell-quote-argument'.
0f34aa77 3793;;;###tramp-autoload
fb7933a3
KG
3794(defun tramp-shell-quote-argument (s)
3795 "Similar to `shell-quote-argument', but groks newlines.
3796Only works for Bourne-like shells."
3797 (let ((system-type 'not-windows))
3798 (save-match-data
3799 (let ((result (shell-quote-argument s))
3800 (nl (regexp-quote (format "\\%s" tramp-rsh-end-of-line))))
3801 (when (and (>= (length result) 2)
3802 (string= (substring result 0 2) "\\~"))
3803 (setq result (substring result 1)))
3804 (while (string-match nl result)
3805 (setq result (replace-match (format "'%s'" tramp-rsh-end-of-line)
3806 t t result)))
3807 result))))
3808
a69c01a0
MA
3809;; Checklist for `tramp-unload-hook'
3810;; - Unload all `tramp-*' packages
3811;; - Reset `file-name-handler-alist'
3812;; - Cleanup hooks where Tramp functions are in
3813;; - Cleanup advised functions
3814;; - Cleanup autoloads
3815;;;###autoload
3816(defun tramp-unload-tramp ()
08b1eb21 3817 "Discard Tramp from loading remote files."
a69c01a0 3818 (interactive)
a69c01a0 3819 ;; ange-ftp settings must be enabled.
0d5852cf 3820 (tramp-compat-funcall 'tramp-ftp-enable-ange-ftp)
0f34aa77 3821 ;; Maybe it's not loaded yet.
03c1ad43 3822 (ignore-errors (unload-feature 'tramp 'force)))
ccb4a481 3823
fb7933a3
KG
3824(provide 'tramp)
3825
fb7933a3
KG
3826;;; TODO:
3827
fb7933a3 3828;; * Rewrite `tramp-shell-quote-argument' to abstain from using
b1d06e75 3829;; `shell-quote-argument'.
fb7933a3
KG
3830;; * In Emacs 21, `insert-directory' shows total number of bytes used
3831;; by the files in that directory. Add this here.
3832;; * Avoid screen blanking when hitting `g' in dired. (Eli Tziperman)
3833;; * Make ffap.el grok Tramp filenames. (Eli Tziperman)
fb7933a3 3834;; * abbreviate-file-name
8e754ea2 3835;; * Better error checking. At least whenever we see something
fb7933a3
KG
3836;; strange when doing zerop, we should kill the process and start
3837;; again. (Greg Stark)
3cdaec13 3838;; * Username and hostname completion.
6c4e47fa 3839;; ** Try to avoid usage of `last-input-event' in `tramp-completion-mode-p'.
00d6fd04 3840;; * Make `tramp-default-user' obsolete.
3e2fa353
MA
3841;; * Implement a general server-local-variable mechanism, as there are
3842;; probably other variables that need different values for different
3843;; servers too. The user could then configure a variable (such as
3844;; tramp-server-local-variable-alist) to define any such variables
3845;; that they need to, which would then be let bound as appropriate
6e4f5731 3846;; in tramp functions. (Jason Rumney)
7e5686f0
MA
3847;; * IMHO, it's a drawback that currently Tramp doesn't support
3848;; Unicode in Dired file names by default. Is it possible to
3849;; improve Tramp to set LC_ALL to "C" only for commands where Tramp
3850;; expects English? Or just to set LC_MESSAGES to "C" if Tramp
6e4f5731 3851;; expects only English messages? (Juri Linkov)
7e5686f0 3852;; * Make shadowfile.el grok Tramp filenames. (Bug#4526, Bug#4846)
58179cce 3853;; * I was wondering if it would be possible to use tramp even if I'm
44ffae96
MA
3854;; actually using sshfs. But when I launch a command I would like
3855;; to get it executed on the remote machine where the files really
3856;; are. (Andrea Crotti)
3857;; * Run emerge on two remote files. Bug is described here:
3858;; <http://www.mail-archive.com/tramp-devel@nongnu.org/msg01041.html>.
3859;; (Bug#6850)
fb7933a3
KG
3860
3861;;; tramp.el ends here
57671b72
MA
3862
3863;; Local Variables:
3864;; mode: Emacs-Lisp
3865;; coding: utf-8
3866;; End: