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