*** empty log message ***
[bpt/emacs.git] / lisp / net / tramp.el
CommitLineData
fb7933a3
KG
1;;; tramp.el --- Transparent Remote Access, Multiple Protocol -*- coding: iso-8859-1; -*-
2
3;; Copyright (C) 1998, 1999, 2000 Free Software Foundation, Inc.
4
5;; Author: Kai.Grossjohann@CS.Uni-Dortmund.DE
6;; Keywords: comm, processes
7
8;; This file is part of GNU Emacs.
9
10;; GNU Emacs is free software; you can redistribute it and/or modify
11;; it under the terms of the GNU General Public License as published by
12;; the Free Software Foundation; either version 2, or (at your option)
13;; any later version.
14
15;; GNU Emacs is distributed in the hope that it will be useful,
16;; but WITHOUT ANY WARRANTY; without even the implied warranty of
17;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18;; GNU General Public License for more details.
19
20;; You should have received a copy of the GNU General Public License
21;; along with GNU Emacs; see the file COPYING. If not, write to the
22;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23;; Boston, MA 02111-1307, USA.
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;;
32;; For more detailed instructions, please see the info file, which is
33;; included in the file `tramp.tar.gz' mentioned below.
34;;
35;; Notes:
36;; -----
37;;
38;; This package only works for Emacs 20 and higher, and for XEmacs 21
39;; and higher. (XEmacs 20 is missing the `with-timeout' macro. Emacs
40;; 19 is reported to have other problems. For XEmacs 21, you need the
41;; package `fsf-compat' for the `with-timeout' macro.)
42;;
43;; This version might not work with pre-Emacs 21 VC unless VC is
44;; loaded before tramp.el. Could you please test this and tell me about
45;; the result? Thanks.
46;;
47;; Also see the todo list at the bottom of this file.
48;;
49;; The current version of tramp.el can be retrieved from the following
50;; URL: ftp://ls6-ftp.cs.uni-dortmund.de/pub/src/emacs/tramp.tar.gz
51;; For your convenience, the *.el file is available separately from
52;; the same directory.
53;;
54;; There's a mailing list for this, as well. Its name is:
55;; tramp-devel@lists.sourceforge.net
56;; Send a mail with `help' in the subject (!) to the administration
57;; address for instructions on joining the list. The administration
58;; address is:
59;; tramp-devel-request@lists.sourceforge.net
60;; You can also use the Web to subscribe, under the following URL:
61;; http://lists.sourceforge.net/lists/listinfo/tramp-devel
62;;
63;; For the adventurous, the current development sources are available
64;; via CVS. You can find instructions about this at the following URL:
65;; http://sourceforge.net/projects/tramp/
66;; Click on "CVS" in the navigation bar near the top.
67;;
68;; Don't forget to put on your asbestos longjohns, first!
69
70;;; Code:
71
72(defconst tramp-version "2.0.0"
73 "This version of tramp.")
74(defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org"
75 "Email address to send bug reports to.")
76
77(require 'timer)
78(require 'format-spec) ;from Gnus 5.8, also in tar ball
79(require 'base64) ;for the mimencode methods
80(require 'shell)
81(require 'advice)
82
83;; ;; It does not work to load EFS after loading TRAMP.
84;; (when (fboundp 'efs-file-handler-function)
85;; (require 'efs))
86
87(eval-when-compile
88 (require 'cl)
89 (require 'custom)
90 ;; Emacs 19.34 compatibility hack -- is this needed?
91 (or (>= emacs-major-version 20)
92 (load "cl-seq")))
93
94(unless (boundp 'custom-print-functions)
95 (defvar custom-print-functions nil)) ; not autoloaded before Emacs 20.4
96
97;;; User Customizable Internal Variables:
98
99(defgroup tramp nil
100 "Edit remote files with a combination of rsh and rcp or similar programs."
101 :group 'files)
102
103(defcustom tramp-verbose 10
104 "*Verbosity level for tramp.el. 0 means be silent, 10 is most verbose."
105 :group 'tramp
106 :type 'integer)
107
108(defcustom tramp-debug-buffer nil
109 "*Whether to send all commands and responses to a debug buffer."
110 :group 'tramp
111 :type 'boolean)
112
113(defcustom tramp-auto-save-directory nil
114 "*Put auto-save files in this directory, if set.
115The idea is to use a local directory so that auto-saving is faster."
116 :group 'tramp
117 :type '(choice (const nil)
118 string))
119
120(defcustom tramp-sh-program "/bin/sh"
121 "*Use this program for shell commands on the local host.
122This MUST be a Bourne-like shell. This shell is used to execute
123the encoding and decoding command on the local host, so if you
124want to use `~' in those commands, you should choose a shell here
125which groks tilde expansion. `/bin/sh' normally does not
126understand tilde expansion.
127
128Note that this variable is not used for remote commands. There are
129mechanisms in tramp.el which automatically determine the right shell to
130use for the remote host."
131 :group 'tramp
132 :type '(file :must-match t))
133
134;; CCC I have changed all occurrences of comint-quote-filename with
135;; tramp-shell-quote-argument, except in tramp-handle-expand-many-files.
136;; There, comint-quote-filename was removed altogether. If it turns
137;; out to be necessary there, something will need to be done.
138;;-(defcustom tramp-file-name-quote-list
139;;- '(?] ?[ ?\| ?& ?< ?> ?\( ?\) ?\; ?\ ?\* ?\? ?\! ?\" ?\' ?\` ?# ?\@ ?\+ )
140;;- "*Protect these characters from the remote shell.
141;;-Any character in this list is quoted (preceded with a backslash)
142;;-because it means something special to the shell. This takes effect
143;;-when sending file and directory names to the remote shell.
144;;-
145;;-See `comint-file-name-quote-list' for details."
146;;- :group 'tramp
147;;- :type '(repeat character))
148
149(defcustom tramp-methods
150 '( ("rcp" (tramp-connection-function tramp-open-connection-rsh)
151 (tramp-rsh-program "rsh")
152 (tramp-rcp-program "rcp")
153 (tramp-remote-sh "/bin/sh")
154 (tramp-rsh-args nil)
155 (tramp-rcp-args nil)
156 (tramp-rcp-keep-date-arg "-p")
157 (tramp-su-program nil)
158 (tramp-su-args nil)
159 (tramp-encoding-command nil)
160 (tramp-decoding-command nil)
161 (tramp-encoding-function nil)
162 (tramp-decoding-function nil)
163 (tramp-telnet-program nil)
164 (tramp-telnet-args nil))
165 ("scp" (tramp-connection-function tramp-open-connection-rsh)
166 (tramp-rsh-program "ssh")
167 (tramp-rcp-program "scp")
168 (tramp-remote-sh "/bin/sh")
169 (tramp-rsh-args ("-e" "none"))
170 (tramp-rcp-args nil)
171 (tramp-rcp-keep-date-arg "-p")
172 (tramp-su-program nil)
173 (tramp-su-args nil)
174 (tramp-encoding-command nil)
175 (tramp-decoding-command nil)
176 (tramp-encoding-function nil)
177 (tramp-decoding-function nil)
178 (tramp-telnet-program nil)
179 (tramp-telnet-args nil))
180 ("scp1" (tramp-connection-function tramp-open-connection-rsh)
181 (tramp-rsh-program "ssh1")
182 (tramp-rcp-program "scp1")
183 (tramp-remote-sh "/bin/sh")
184 (tramp-rsh-args ("-e" "none"))
185 (tramp-rcp-args nil)
186 (tramp-rcp-keep-date-arg "-p")
187 (tramp-su-program nil)
188 (tramp-su-args nil)
189 (tramp-encoding-command nil)
190 (tramp-decoding-command nil)
191 (tramp-encoding-function nil)
192 (tramp-decoding-function nil)
193 (tramp-telnet-program nil)
194 (tramp-telnet-args nil))
195 ("scp2" (tramp-connection-function tramp-open-connection-rsh)
196 (tramp-rsh-program "ssh2")
197 (tramp-rcp-program "scp2")
198 (tramp-remote-sh "/bin/sh")
199 (tramp-rsh-args ("-e" "none"))
200 (tramp-rcp-args nil)
201 (tramp-rcp-keep-date-arg "-p")
202 (tramp-su-program nil)
203 (tramp-su-args nil)
204 (tramp-encoding-command nil)
205 (tramp-decoding-command nil)
206 (tramp-encoding-function nil)
207 (tramp-decoding-function nil)
208 (tramp-telnet-program nil)
209 (tramp-telnet-args nil))
210 ("rsync" (tramp-connection-function tramp-open-connection-rsh)
211 (tramp-rsh-program "ssh")
212 (tramp-rcp-program "rsync")
213 (tramp-remote-sh "/bin/sh")
214 (tramp-rsh-args ("-e" "none"))
215 (tramp-rcp-args ("-e" "ssh"))
216 (tramp-rcp-keep-date-arg "-t")
217 (tramp-su-program nil)
218 (tramp-su-args nil)
219 (tramp-encoding-command nil)
220 (tramp-decoding-command nil)
221 (tramp-encoding-function nil)
222 (tramp-decoding-function nil)
223 (tramp-telnet-program nil)
224 (tramp-telnet-args nil))
225 ("ru" (tramp-connection-function tramp-open-connection-rsh)
226 (tramp-rsh-program "rsh")
227 (tramp-rcp-program nil)
228 (tramp-remote-sh "/bin/sh")
229 (tramp-rsh-args nil)
230 (tramp-rcp-args nil)
231 (tramp-rcp-keep-date-arg nil)
232 (tramp-su-program nil)
233 (tramp-su-args nil)
234 (tramp-encoding-command "uuencode xxx")
235 (tramp-decoding-command
236 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
237 (tramp-encoding-function nil)
238 (tramp-decoding-function uudecode-decode-region)
239 (tramp-telnet-program nil)
240 (tramp-telnet-args nil))
241 ("su" (tramp-connection-function tramp-open-connection-rsh)
242 (tramp-rsh-program "ssh")
243 (tramp-rcp-program nil)
244 (tramp-remote-sh "/bin/sh")
245 (tramp-rsh-args ("-e" "none"))
246 (tramp-rcp-args nil)
247 (tramp-rcp-keep-date-arg nil)
248 (tramp-su-program nil)
249 (tramp-su-args nil)
250 (tramp-encoding-command "uuencode xxx")
251 (tramp-decoding-command
252 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
253 (tramp-encoding-function nil)
254 (tramp-decoding-function uudecode-decode-region)
255 (tramp-telnet-program nil)
256 (tramp-telnet-args nil))
257 ("su1" (tramp-connection-function tramp-open-connection-rsh)
258 (tramp-rsh-program "ssh1")
259 (tramp-rcp-program nil)
260 (tramp-remote-sh "/bin/sh")
261 (tramp-rsh-args ("-e" "none"))
262 (tramp-rcp-args nil)
263 (tramp-rcp-keep-date-arg nil)
264 (tramp-su-program nil)
265 (tramp-su-args nil)
266 (tramp-encoding-command "uuencode xxx")
267 (tramp-decoding-command
268 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
269 (tramp-encoding-function nil)
270 (tramp-decoding-function uudecode-decode-region)
271 (tramp-telnet-program nil)
272 (tramp-telnet-args nil))
273 ("su2" (tramp-connection-function tramp-open-connection-rsh)
274 (tramp-rsh-program "ssh2")
275 (tramp-rcp-program nil)
276 (tramp-remote-sh "/bin/sh")
277 (tramp-rsh-args ("-e" "none"))
278 (tramp-rcp-args nil)
279 (tramp-rcp-keep-date-arg nil)
280 (tramp-su-program nil)
281 (tramp-su-args nil)
282 (tramp-encoding-command "uuencode xxx")
283 (tramp-decoding-command
284 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
285 (tramp-encoding-function nil)
286 (tramp-decoding-function uudecode-decode-region)
287 (tramp-telnet-program nil)
288 (tramp-telnet-args nil))
289 ("rm" (tramp-connection-function tramp-open-connection-rsh)
290 (tramp-rsh-program "rsh")
291 (tramp-rcp-program nil)
292 (tramp-remote-sh "/bin/sh")
293 (tramp-rsh-args nil)
294 (tramp-rcp-args nil)
295 (tramp-rcp-keep-date-arg nil)
296 (tramp-su-program nil)
297 (tramp-su-args nil)
298 (tramp-encoding-command "mimencode -b")
299 (tramp-decoding-command "mimencode -u -b")
300 (tramp-encoding-function base64-encode-region)
301 (tramp-decoding-function base64-decode-region)
302 (tramp-telnet-program nil)
303 (tramp-telnet-args nil))
304 ("sm" (tramp-connection-function tramp-open-connection-rsh)
305 (tramp-rsh-program "ssh")
306 (tramp-rcp-program nil)
307 (tramp-remote-sh "/bin/sh")
308 (tramp-rsh-args ("-e" "none"))
309 (tramp-rcp-args nil)
310 (tramp-rcp-keep-date-arg nil)
311 (tramp-su-program nil)
312 (tramp-su-args nil)
313 (tramp-encoding-command "mimencode -b")
314 (tramp-decoding-command "mimencode -u -b")
315 (tramp-encoding-function base64-encode-region)
316 (tramp-decoding-function base64-decode-region)
317 (tramp-telnet-program nil)
318 (tramp-telnet-args nil))
319 ("smp" (tramp-connection-function tramp-open-connection-rsh)
320 (tramp-rsh-program "ssh")
321 (tramp-rcp-program nil)
322 (tramp-remote-sh "/bin/sh")
323 (tramp-rsh-args ("-e" "none"))
324 (tramp-rcp-args nil)
325 (tramp-rcp-keep-date-arg nil)
326 (tramp-su-program nil)
327 (tramp-su-args nil)
328 (tramp-encoding-command "tramp_mimencode")
329 (tramp-decoding-command "tramp_mimedecode")
330 (tramp-encoding-function base64-encode-region)
331 (tramp-decoding-function base64-decode-region)
332 (tramp-telnet-program nil))
333 ("sm1" (tramp-connection-function tramp-open-connection-rsh)
334 (tramp-rsh-program "ssh1")
335 (tramp-rcp-program nil)
336 (tramp-remote-sh "/bin/sh")
337 (tramp-rsh-args ("-e" "none"))
338 (tramp-rcp-args nil)
339 (tramp-rcp-keep-date-arg nil)
340 (tramp-su-program nil)
341 (tramp-su-args nil)
342 (tramp-encoding-command "mimencode -b")
343 (tramp-decoding-command "mimencode -u -b")
344 (tramp-encoding-function base64-encode-region)
345 (tramp-decoding-function base64-decode-region)
346 (tramp-telnet-program nil)
347 (tramp-telnet-args nil))
348 ("sm2" (tramp-connection-function tramp-open-connection-rsh)
349 (tramp-rsh-program "ssh2")
350 (tramp-rcp-program nil)
351 (tramp-remote-sh "/bin/sh")
352 (tramp-rsh-args ("-e" "none"))
353 (tramp-rcp-args nil)
354 (tramp-rcp-keep-date-arg nil)
355 (tramp-su-program nil)
356 (tramp-su-args nil)
357 (tramp-encoding-command "mimencode -b")
358 (tramp-decoding-command "mimencode -u -b")
359 (tramp-encoding-function base64-encode-region)
360 (tramp-decoding-function base64-decode-region)
361 (tramp-telnet-program nil)
362 (tramp-telnet-args nil))
363 ("tm" (tramp-connection-function tramp-open-connection-telnet)
364 (tramp-rsh-program nil)
365 (tramp-rcp-program nil)
366 (tramp-remote-sh "/bin/sh")
367 (tramp-rsh-args nil)
368 (tramp-rcp-args nil)
369 (tramp-rcp-keep-date-arg nil)
370 (tramp-su-program nil)
371 (tramp-su-args nil)
372 (tramp-encoding-command "mimencode -b")
373 (tramp-decoding-command "mimencode -u -b")
374 (tramp-encoding-function base64-encode-region)
375 (tramp-decoding-function base64-decode-region)
376 (tramp-telnet-program "telnet")
377 (tramp-telnet-args nil))
378 ("tu" (tramp-connection-function tramp-open-connection-telnet)
379 (tramp-rsh-program nil)
380 (tramp-rcp-program nil)
381 (tramp-remote-sh "/bin/sh")
382 (tramp-rsh-args nil)
383 (tramp-rcp-args nil)
384 (tramp-rcp-keep-date-arg nil)
385 (tramp-su-program nil)
386 (tramp-su-args nil)
387 (tramp-encoding-command "uuencode xxx")
388 (tramp-decoding-command
389 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
390 (tramp-encoding-function nil)
391 (tramp-decoding-function uudecode-decode-region)
392 (tramp-telnet-program "telnet")
393 (tramp-telnet-args nil))
394 ("sum" (tramp-connection-function tramp-open-connection-su)
395 (tramp-rsh-program nil)
396 (tramp-rcp-program nil)
397 (tramp-remote-sh "/bin/sh")
398 (tramp-rsh-args nil)
399 (tramp-rcp-args nil)
400 (tramp-rcp-keep-date-arg nil)
401 (tramp-su-program "su")
402 (tramp-su-args ("-" "%u"))
403 (tramp-encoding-command "mimencode -b")
404 (tramp-decoding-command "mimencode -u -b")
405 (tramp-encoding-function base64-encode-region)
406 (tramp-decoding-function base64-decode-region)
407 (tramp-telnet-program nil)
408 (tramp-telnet-args nil))
409 ("suu" (tramp-connection-function tramp-open-connection-su)
410 (tramp-rsh-program nil)
411 (tramp-rcp-program nil)
412 (tramp-remote-sh "/bin/sh")
413 (tramp-rsh-args nil)
414 (tramp-rcp-args nil)
415 (tramp-rcp-keep-date-arg nil)
416 (tramp-su-program "su")
417 (tramp-su-args ("-" "%u"))
418 (tramp-encoding-command "uuencode xxx")
419 (tramp-decoding-command
420 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
421 (tramp-encoding-function nil)
422 (tramp-decoding-function uudecode-decode-region)
423 (tramp-telnet-program nil)
424 (tramp-telnet-args nil))
425 ("sudm" (tramp-connection-function tramp-open-connection-su)
426 (tramp-rsh-program nil)
427 (tramp-rcp-program nil)
428 (tramp-remote-sh "/bin/sh")
429 (tramp-rsh-args nil)
430 (tramp-rcp-args nil)
431 (tramp-rcp-keep-date-arg nil)
432 (tramp-su-program "sudo")
433 (tramp-su-args ("-u" "%u" "-s"))
434 (tramp-encoding-command "mimencode -b")
435 (tramp-decoding-command "mimencode -u -b")
436 (tramp-encoding-function base64-encode-region)
437 (tramp-decoding-function base64-decode-region)
438 (tramp-telnet-program nil)
439 (tramp-telnet-args nil))
440 ("sudu" (tramp-connection-function tramp-open-connection-su)
441 (tramp-rsh-program nil)
442 (tramp-rcp-program nil)
443 (tramp-remote-sh "/bin/sh")
444 (tramp-rsh-args nil)
445 (tramp-rcp-args nil)
446 (tramp-rcp-keep-date-arg nil)
447 (tramp-su-program "sudo")
448 (tramp-su-args ("-u" "%u" "-s"))
449 (tramp-encoding-command "uuencode xxx")
450 (tramp-decoding-command
451 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
452 (tramp-encoding-function nil)
453 (tramp-decoding-function uudecode-decode-region)
454 (tramp-telnet-program nil)
455 (tramp-telnet-args nil))
456 ("multi" (tramp-connection-function tramp-open-connection-multi)
457 (tramp-rsh-program nil)
458 (tramp-rcp-program nil)
459 (tramp-remote-sh "/bin/sh")
460 (tramp-rsh-args nil)
461 (tramp-rcp-args nil)
462 (tramp-rcp-keep-date-arg nil)
463 (tramp-su-program nil)
464 (tramp-su-args nil)
465 (tramp-encoding-command "mimencode -b")
466 (tramp-decoding-command "mimencode -u -b")
467 (tramp-encoding-function base64-encode-region)
468 (tramp-decoding-function base64-decode-region)
469 (tramp-telnet-program nil)
470 (tramp-telnet-args nil))
471 ("multiu" (tramp-connection-function tramp-open-connection-multi)
472 (tramp-rsh-program nil)
473 (tramp-rcp-program nil)
474 (tramp-remote-sh "/bin/sh")
475 (tramp-rsh-args nil)
476 (tramp-rcp-args nil)
477 (tramp-rcp-keep-date-arg nil)
478 (tramp-su-program nil)
479 (tramp-su-args nil)
480 (tramp-encoding-command "uuencode xxx")
481 (tramp-decoding-command
482 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
483 (tramp-encoding-function nil)
484 (tramp-decoding-function uudecode-decode-region)
485 (tramp-telnet-program nil)
486 (tramp-telnet-args nil))
487 ("scpx" (tramp-connection-function tramp-open-connection-rsh)
488 (tramp-rsh-program "ssh")
489 (tramp-rcp-program "scp")
490 (tramp-remote-sh "/bin/sh")
491 (tramp-rsh-args ("-e" "none" "-t" "-t" "/bin/sh"))
492 (tramp-rcp-args nil)
493 (tramp-rcp-keep-date-arg "-p")
494 (tramp-encoding-command nil)
495 (tramp-decoding-command nil)
496 (tramp-encoding-function nil)
497 (tramp-decoding-function nil)
498 (tramp-telnet-program nil)
499 (tramp-telnet-args nil))
500 ("smx" (tramp-connection-function tramp-open-connection-rsh)
501 (tramp-rsh-program "ssh")
502 (tramp-rcp-program nil)
503 (tramp-remote-sh "/bin/sh")
504 (tramp-rsh-args ("-e" "none" "-t" "-t" "/bin/sh"))
505 (tramp-rcp-args nil)
506 (tramp-rcp-keep-date-arg nil)
507 (tramp-su-program nil)
508 (tramp-su-args nil)
509 (tramp-encoding-command "mimencode -b")
510 (tramp-decoding-command "mimencode -u -b")
511 (tramp-encoding-function base64-encode-region)
512 (tramp-decoding-function base64-decode-region)
513 (tramp-telnet-program nil)
514 (tramp-telnet-args nil))
515 ("km"
516 (tramp-connection-function tramp-open-connection-rsh)
517 (tramp-rsh-program "krlogin")
518 (tramp-rcp-program nil)
519 (tramp-remote-sh "/bin/sh")
520 (tramp-rsh-args ("-x"))
521 (tramp-rcp-args nil)
522 (tramp-rcp-keep-date-arg nil)
523 (tramp-su-program nil)
524 (tramp-su-args nil)
525 (tramp-encoding-command "mimencode -b")
526 (tramp-decoding-command "mimencode -u -b")
527 (tramp-encoding-function base64-encode-region)
528 (tramp-decoding-function base64-decode-region)
529 (tramp-telnet-program nil)
530 (tramp-telnet-args nil))
531 ("plinku"
532 (tramp-connection-function tramp-open-connection-rsh)
533 (tramp-rsh-program "plink")
534 (tramp-rcp-program nil)
535 (tramp-remote-sh "/bin/sh")
536 (tramp-rsh-args ("-ssh")) ;optionally add "-v"
537 (tramp-rcp-args nil)
538 (tramp-rcp-keep-date-arg nil)
539 (tramp-su-program nil)
540 (tramp-su-args nil)
541 (tramp-encoding-command "uuencode xxx")
542 (tramp-decoding-command
543 "( uudecode -o - 2>/dev/null || uudecode -p 2>/dev/null )")
544 (tramp-encoding-function nil)
545 (tramp-decoding-function uudecode-decode-region)
546 (tramp-telnet-program nil)
547 (tramp-telnet-args nil))
548 ("plinkm"
549 (tramp-connection-function tramp-open-connection-rsh)
550 (tramp-rsh-program "plink")
551 (tramp-rcp-program nil)
552 (tramp-remote-sh "/bin/sh")
553 (tramp-rsh-args ("-ssh")) ;optionally add "-v"
554 (tramp-rcp-args nil)
555 (tramp-rcp-keep-date-arg nil)
556 (tramp-su-program nil)
557 (tramp-su-args nil)
558 (tramp-encoding-command "mimencode -b")
559 (tramp-decoding-command "mimencode -u -b")
560 (tramp-encoding-function base64-encode-region)
561 (tramp-decoding-function base64-decode-region)
562 (tramp-telnet-program nil)
563 (tramp-telnet-args nil))
564 ("pscp"
565 (tramp-connection-function tramp-open-connection-rsh)
566 (tramp-rsh-program "plink")
567 (tramp-rcp-program "pscp")
568 (tramp-remote-sh "/bin/sh")
569 (tramp-rsh-args ("-ssh"))
570 (tramp-rcp-args nil)
571 (tramp-rcp-keep-date-arg "-p")
572 (tramp-su-program nil)
573 (tramp-su-args nil)
574 (tramp-encoding-command nil)
575 (tramp-decoding-command nil)
576 (tramp-encoding-function nil)
577 (tramp-decoding-function nil)
578 (tramp-telnet-program nil)
579 (tramp-telnet-args nil))
580 ("fcp"
581 (tramp-connection-function tramp-open-connection-rsh)
582 (tramp-rsh-program "fsh")
583 (tramp-rcp-program "fcp")
584 (tramp-remote-sh "/bin/sh -i")
585 (tramp-rsh-args ("sh" "-i"))
586 (tramp-rcp-args nil)
587 (tramp-rcp-keep-date-arg "-p")
588 (tramp-su-program nil)
589 (tramp-su-args nil)
590 (tramp-encoding-command nil)
591 (tramp-decoding-command nil)
592 (tramp-encoding-function nil)
593 (tramp-decoding-function nil)
594 (tramp-telnet-program nil)
595 (tramp-telnet-args nil))
596 )
597 "*Alist of methods for remote files.
598This is a list of entries of the form (NAME PARAM1 PARAM2 ...).
599Each NAME stands for a remote access method. Each PARAM is a
600pair of the form (KEY VALUE). The following KEYs are defined:
601 * `tramp-connection-function'
602 This specifies the function to use to connect to the remote host.
603 Currently, `tramp-open-connection-rsh', `tramp-open-connection-telnet'
604 and `tramp-open-connection-su' are defined. See the documentation
605 of these functions for more details.
606 * `tramp-remote-sh'
607 This specifies the Bourne shell to use on the remote host. This
608 MUST be a Bourne-like shell. It is normally not necessary to set
609 this to any value other than \"/bin/sh\": tramp wants to use a shell
610 which groks tilde expansion, but it can search for it. Also note
611 that \"/bin/sh\" exists on all Unixen, this might not be true for
612 the value that you decide to use. You Have Been Warned.
613 * `tramp-rsh-program'
614 This specifies the name of the program to use for rsh; this might be
615 the full path to rsh or the name of a workalike program.
616 * `tramp-rsh-args'
617 This specifies the list of arguments to pass to the above
618 mentioned program. Please note that this is a list of arguments,
619 that is, normally you don't want to put \"-a -b\" or \"-f foo\"
620 here. Instead, you want two list elements, one for \"-a\" and one
621 for \"-b\", or one for \"-f\" and one for \"foo\".
622 * `tramp-rcp-program'
623 This specifies the name of the program to use for rcp; this might be
624 the full path to rcp or the name of a workalike program.
625 * `tramp-rcp-args'
626 This specifies the list of parameters to pass to the above mentioned
627 program, the hints for `tramp-rsh-args' also apply here.
628 * `tramp-rcp-keep-date-arg'
629 This specifies the parameter to use for `rcp' when the timestamp
630 of the original file should be kept. For `rcp', use `-p', for
631 `rsync', use `-t'.
632 * `tramp-su-program'
633 This specifies the name of the program to use for `su'.
634 * `tramp-su-args'
635 This specifies the list of arguments to pass to `su'.
636 \"%u\" is replaced by the user name, use \"%%\" for a literal
637 percent character.
638 * `tramp-encoding-command'
639 This specifies a command to use to encode the file contents for
640 transfer. The command should read the raw file contents from
641 standard input and write the encoded file contents to standard
642 output. In this string, the percent escape \"%f\" should be used
643 to indicate the file to convert. Use \"%%\" if you need a literal
644 percent character in your command.
645 * `tramp-decoding-command'
646 This specifies a command to use to decode file contents encoded
647 with `tramp-encoding-command'. The command should read from standard
648 input and write to standard output.
649 * `tramp-encoding-function'
650 This specifies a function to be called to encode the file contents
651 on the local side. This function should accept two arguments
652 START and END, the beginning and end of the region to encode. The
653 region should be replaced with the encoded contents.
654 * `tramp-decoding-function'
655 Same for decoding on the local side.
656 * `tramp-telnet-program'
657 Specifies the telnet program to use when using
658 `tramp-open-connection-telnet' to log in.
659 * `tramp-telnet-args'
660 Specifies list of arguments to pass to `telnet'. The hints for
661 `tramp-rsh-args' also apply here.
662
663What does all this mean? Well, you should specify `tramp-rsh-program',
664`tramp-telnet-program' or `tramp-su-program' for all methods; this program
665is used to log in to the remote site. Then, there are two ways to
666actually transfer the files between the local and the remote side.
667One way is using an additional rcp-like program. If you want to do
668this, set `tramp-rcp-program' in the method.
669
670Another possibility for file transfer is inline transfer, i.e. the
671file is passed through the same buffer used by `tramp-rsh-program'. In
672this case, the file contents need to be protected since the
673`tramp-rsh-program' might use escape codes or the connection might not
674be eight-bit clean. Therefore, file contents are encoded for transit.
675
676Two possibilities for encoding are uuencode/uudecode and mimencode.
677For uuencode/uudecode you want to set `tramp-encoding-command' to
678something like \"uuencode\" and `tramp-decoding-command' to \"uudecode
679-p\". For mimencode you want to set `tramp-encoding-command' to
680something like \"mimencode -b\" and `tramp-decoding-command' to
681\"mimencode -b -u\".
682
683When using inline transfer, you can use a program or a Lisp function
684on the local side to encode or decode the file contents. Set the
685`tramp-encoding-function' and `tramp-decoding-function' parameters to nil
686in order to use the commands or to the function to use. It is
687possible to specify one function and the other parameter as nil.
688
689So, to summarize: if the method is an inline method, you must specify
690`tramp-encoding-command' and `tramp-decoding-command', and
691`tramp-rcp-program' must be nil. If the method is out of band, then
692you must specify `tramp-rcp-program' and `tramp-rcp-args' and
693`tramp-encoding-command' and `tramp-decoding-command' must be nil.
694Every method, inline or out of band, must specify
695`tramp-connection-function' plus the associated arguments (for
696example, the telnet program if you chose
697`tramp-open-connection-telnet').
698
699Notes:
700
701When using `tramp-open-connection-su' the phrase `open connection to a
702remote host' sounds strange, but it is used nevertheless, for
703consistency. No connection is opened to a remote host, but `su' is
704started on the local host. You are not allowed to specify a remote
705host other than `localhost' or the name of the local host.
706
707Using a uuencode/uudecode inline method is discouraged, please use one
708of the base64 methods instead since base64 encoding is much more
709reliable and the commands are more standardized between the different
710Unix versions. But if you can't use base64 for some reason, please
711note that the default uudecode command does not work well for some
712Unices, in particular AIX and Irix. For AIX, you might want to use
713the following command for uudecode:
714
715 sed '/^begin/d;/^[` ]$/d;/^end/d' | iconv -f uucode -t ISO8859-1
716
717For Irix, no solution is known yet."
718 :group 'tramp
719 :type '(repeat
720 (cons string
721 (set (list (const tramp-connection-function) function)
722 (list (const tramp-rsh-program)
723 (choice (const nil) string))
724 (list (const tramp-rcp-program)
725 (choice (const nil) string))
726 (list (const tramp-remote-sh)
727 (choice (const nil) string))
728 (list (const tramp-rsh-args) (repeat string))
729 (list (const tramp-rcp-args) (repeat string))
730 (list (const tramp-rcp-keep-date-arg)
731 (choice (const nil) string))
732 (list (const tramp-su-program)
733 (choice (const nil) string))
734 (list (const tramp-su-args) (repeat string))
735 (list (const tramp-encoding-command)
736 (choice (const nil) string))
737 (list (const tramp-decoding-command)
738 (choice (const nil) string))
739 (list (const tramp-encoding-function)
740 (choice (const nil) function))
741 (list (const tramp-decoding-function)
742 (choice (const nil) function))
743 (list (const tramp-telnet-program)
744 (choice (const nil) string))
745 (list (const tramp-telnet-args) (repeat string))))))
746
747(defcustom tramp-multi-methods '("multi" "multiu")
748 "*List of multi-hop methods.
749Each entry in this list should be a method name as mentioned in the
750variable `tramp-methods'."
751 :group 'tramp
752 :type '(repeat string))
753
754(defcustom tramp-multi-connection-function-alist
755 '(("telnet" tramp-multi-connect-telnet "telnet %h%n")
756 ("rsh" tramp-multi-connect-rlogin "rsh %h -l %u%n")
757 ("ssh" tramp-multi-connect-rlogin "ssh %h -l %u%n")
758 ("su" tramp-multi-connect-su "su - %u%n")
759 ("sudo" tramp-multi-connect-su "sudo -u %u -s%n"))
760 "*List of connection functions for multi-hop methods.
761Each list item is a list of three items (METHOD FUNCTION COMMAND),
762where METHOD is the name as used in the file name, FUNCTION is the
763function to be executed, and COMMAND is the shell command used for
764connecting.
765
766COMMAND may contain percent escapes. `%u' will be replaced with the
767user name, `%h' will be replaced with the host name, and `%n' will be
768replaced with an end-of-line character, as specified in the variable
769`tramp-rsh-end-of-line'. Use `%%' for a literal percent character.
770Note that the interpretation of the percent escapes also depends on
771the FUNCTION. For example, the `%u' escape is forbidden with the
772function `tramp-multi-connect-telnet'. See the documentation of the
773various functions for details."
774 :group 'tramp
775 :type '(repeat (list string function string)))
776
777(defcustom tramp-default-method "rcp"
778 "*Default method to use for transferring files.
779See `tramp-methods' for possibilities."
780 :group 'tramp
781 :type 'string)
782
783(defcustom tramp-rsh-end-of-line "\n"
784 "*String used for end of line in rsh connections.
785I don't think this ever needs to be changed, so please tell me about it
786if you need to change this."
787 :group 'tramp
788 :type 'string)
789
790(defcustom tramp-remote-path
791 '("/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin" "/usr/ccs/bin"
792 "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
793 "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
794 "*List of directories to search for executables on remote host.
795Please notify me about other semi-standard directories to include here.
796
797You can use `~' in this list, but when searching for a shell which groks
798tilde expansion, all directory names starting with `~' will be ignored."
799 :group 'tramp
800 :type '(repeat string))
801
802(defcustom tramp-login-prompt-regexp
803 ".*ogin: *$"
804 "*Regexp matching login-like prompts.
805The regexp should match the whole line."
806 :group 'tramp
807 :type 'regexp)
808
809(defcustom tramp-password-prompt-regexp
810 "^.*\\([pP]assword\\|passphrase.*\\):\^@? *$"
811 "*Regexp matching password-like prompts.
812The regexp should match the whole line.
813
814The `sudo' program appears to insert a `^@' character into the prompt."
815 :group 'tramp
816 :type 'regexp)
817
818(defcustom tramp-wrong-passwd-regexp
819 (concat "^.*\\(Permission denied.\\|Login [Ii]ncorrect\\|"
820 "Received signal [0-9]+\\|Connection \\(refused\\|closed\\)\\|"
821 "Sorry, try again.\\|Name or service not known\\).*$")
822 "*Regexp matching a `login failed' message.
823The regexp should match the whole line."
824 :group 'tramp
825 :type 'regexp)
826
827(defcustom tramp-temp-name-prefix "tramp."
828 "*Prefix to use for temporary files.
829If this is a relative file name (such as \"tramp.\"), it is considered
830relative to the directory name returned by the function
831`tramp-temporary-file-directory' (which see). It may also be an
832absolute file name; don't forget to include a prefix for the filename
833part, though."
834 :group 'tramp
835 :type 'string)
836
837(defcustom tramp-discard-garbage nil
838 "*If non-nil, try to discard garbage sent by remote shell.
839Some shells send such garbage upon connection setup."
840 :group 'tramp
841 :type 'boolean)
842
843;; File name format.
844
845(defcustom tramp-file-name-structure
846 (list "\\`/\\[\\(\\([a-zA-Z0-9]+\\)/\\)?\\(\\([-a-zA-Z0-9_#/:]+\\)@\\)?\\([-a-zA-Z0-9_#/:@.]+\\)\\]\\(.*\\)\\'"
847 2 4 5 6)
848 "*List of five elements (REGEXP METHOD USER HOST FILE), detailing \
849the tramp file name structure.
850
851The first element REGEXP is a regular expression matching a tramp file
852name. The regex should contain parentheses around the method name,
853the user name, the host name, and the file name parts.
854
855The second element METHOD is a number, saying which pair of
856parentheses matches the method name. The third element USER is
857similar, but for the user name. The fourth element HOST is similar,
858but for the host name. The fifth element FILE is for the file name.
859These numbers are passed directly to `match-string', which see. That
860means the opening parentheses are counted to identify the pair.
861
862See also `tramp-file-name-regexp' and `tramp-make-tramp-file-format'."
863 :group 'tramp
864 :type '(list (regexp :tag "File name regexp")
865 (integer :tag "Paren pair for method name")
866 (integer :tag "Paren pair for user name ")
867 (integer :tag "Paren pair for host name ")
868 (integer :tag "Paren pair for file name ")))
869
870;;;###autoload
871(defcustom tramp-file-name-regexp "\\`/\\[.*\\]"
872 "*Regular expression matching file names handled by tramp.
873This regexp should match tramp file names but no other file names.
874\(When tramp.el is loaded, this regular expression is prepended to
875`file-name-handler-alist', and that is searched sequentially. Thus,
876if the tramp entry appears rather early in the `file-name-handler-alist'
877and is a bit too general, then some files might be considered tramp
878files which are not really tramp files.
879
880Please note that the entry in `file-name-handler-alist' is made when
881this file (tramp.el) is loaded. This means that this variable must be set
882before loading tramp.el. Alternatively, `file-name-handler-alist' can be
883updated after changing this variable.
884
885Also see `tramp-file-name-structure' and `tramp-make-tramp-file-format'."
886 :group 'tramp
887 :type 'regexp)
888
889(defcustom tramp-make-tramp-file-format "/[%m/%u@%h]%p"
890 "*Format string saying how to construct tramp file name.
891`%m' is replaced by the method name.
892`%u' is replaced by the user name.
893`%h' is replaced by the host name.
894`%p' is replaced by the file name.
895`%%' is replaced by %.
896
897Also see `tramp-file-name-structure' and `tramp-file-name-regexp'."
898 :group 'tramp
899 :type 'string)
900
901;; HHH: New. This format spec is made to handle the cases where the
902;; user does not provide a user name for the connection.
903(defcustom tramp-make-tramp-file-user-nil-format "/[%m/%h]%p"
904 "*Format string saying how to construct tramp file name when the user name is not known.
905`%m' is replaced by the method name.
906`%h' is replaced by the host name.
907`%p' is replaced by the file name.
908`%%' is replaced by %.
909
910Also see `tramp-make-tramp-file-format', `tramp-file-name-structure', and `tramp-file-name-regexp'."
911 :group 'tramp
912 :type 'string)
913
914(defcustom tramp-multi-file-name-structure
915 (list (concat
916 ;; prefix
917 "\\`/\\[\\(\\([a-z0-9]+\\)\\)?"
918 ;; regexp specifying a hop
919 "\\(\\(%s\\)+\\)"
920 ;; path name
921 "\\]\\(.*\\)\\'")
922 2 ;number of pair to match method
923 3 ;number of pair to match hops
924 -1) ;number of pair to match path
925
926 "*Describes the file name structure of `multi' files.
927Multi files allow you to contact a remote host in several hops.
928This is a list of four elements (REGEXP METHOD HOP PATH).
929
930The first element, REGEXP, gives a regular expression to match against
931the file name. In this regular expression, `%s' is replaced with the
932value of `tramp-multi-file-name-hop-structure'. (Note: in order to
933allow multiple hops, you normally want to use something like
934\"\\\\(\\\\(%s\\\\)+\\\\)\" in the regular expression. The outer pair
935of parentheses is used for the HOP element, see below.)
936
937All remaining elements are numbers. METHOD gives the number of the
938paren pair which matches the method name. HOP gives the number of the
939paren pair which matches the hop sequence. PATH gives the number of
940the paren pair which matches the path name on the remote host.
941
942PATH can also be negative, which means to count from the end. Ie, a
943value of -1 means the last paren pair.
944
945I think it would be good if the regexp matches the whole of the
946string, but I haven't actually tried what happens if it doesn't..."
947 :group 'tramp
948 :type '(list (regexp :tag "File name regexp")
949 (integer :tag "Paren pair for method name")
950 (integer :tag "Paren pair for hops")
951 (integer :tag "Paren pair to match path")))
952
953(defcustom tramp-multi-file-name-hop-structure
954 (list "/\\([a-z0-9_]+\\):\\([a-z0-9_]+\\)@\\([a-z0-9.-]+\\)"
955 1 2 3)
956 "*Describes the structure of a hop in multi files.
957This is a list of four elements (REGEXP METHOD USER HOST). First
958element REGEXP is used to match against the hop. Pair number METHOD
959matches the method of one hop, pair number USER matches the user of
960one hop, pair number HOST matches the host of one hop.
961
962This regular expression should match exactly all of one hop."
963 :group 'tramp
964 :type '(list (regexp :tag "Hop regexp")
965 (integer :tag "Paren pair for method name")
966 (integer :tag "Paren pair for user name")
967 (integer :tag "Paren pair for host name")))
968
969(defcustom tramp-make-multi-tramp-file-format
970 (list "/[%m" "/%m:%u@%h" "]%p")
971 "*Describes how to construct a `multi' file name.
972This is a list of three elements PREFIX, HOP and PATH.
973
974The first element PREFIX says how to construct the prefix, the second
975element HOP specifies what each hop looks like, and the final element
976PATH says how to construct the path name.
977
978In PREFIX, `%%' means `%' and `%m' means the method name.
979
980In HOP, `%%' means `%' and `%m', `%u', `%h' mean the hop method, hop
981user and hop host, respectively.
982
983In PATH, `%%' means `%' and `%p' means the path name.
984
985The resulting file name always contains one copy of PREFIX and one
986copy of PATH, but there is one copy of HOP for each hop in the file
987name.
988
989Note: the current implementation requires the prefix to contain the
990method name, followed by all the hops, and the path name must come
991last."
992 :group 'tramp
993 :type '(list string string string))
994
995(defcustom tramp-terminal-type "dumb"
996 "*Value of TERM environment variable for logging in to remote host.
997Because Tramp wants to parse the output of the remote shell, it is easily
998confused by ANSI color escape sequences and suchlike. Often, shell init
999files conditionalize this setup based on the TERM environment variable."
1000 :group 'tramp
1001 :type 'string)
1002
1003(defcustom tramp-completion-without-shell-p nil
1004 "*If nil, use shell wildcards for completion, else rely on Lisp only.
1005Using shell wildcards for completions has the advantage that it can be
1006fast even in large directories, but completion is always
1007case-sensitive. Relying on Lisp only means that case-insensitive
1008completion is possible (subject to the variable `completion-ignore-case'),
1009but it might be slow on large directories."
1010 :group 'tramp
1011 :type 'boolean)
1012
1013;;; Internal Variables:
1014
1015(defvar tramp-buffer-file-attributes nil
1016 "Holds the `ls -ild' output for the current buffer.
1017This variable is local to each buffer. It is not used if the remote
1018machine groks Perl. If it is used, it's used as an emulation for
1019the visited file modtime.")
1020(make-variable-buffer-local 'tramp-buffer-file-attributes)
1021
1022(defvar tramp-end-of-output "/////"
1023 "String used to recognize end of output.")
1024
1025(defvar tramp-connection-function nil
1026 "This internal variable holds a parameter for `tramp-methods'.
1027In the connection buffer, this variable has the value of the like-named
1028method parameter, as specified in `tramp-methods' (which see).")
1029
1030(defvar tramp-remote-sh nil
1031 "This internal variable holds a parameter for `tramp-methods'.
1032In the connection buffer, this variable has the value of the like-named
1033method parameter, as specified in `tramp-methods' (which see).")
1034
1035(defvar tramp-rsh-program nil
1036 "This internal variable holds a parameter for `tramp-methods'.
1037In the connection buffer, this variable has the value of the like-named
1038method parameter, as specified in `tramp-methods' (which see).")
1039
1040(defvar tramp-rsh-args nil
1041 "This internal variable holds a parameter for `tramp-methods'.
1042In the connection buffer, this variable has the value of the like-named
1043method parameter, as specified in `tramp-methods' (which see).")
1044
1045(defvar tramp-rcp-program nil
1046 "This internal variable holds a parameter for `tramp-methods'.
1047In the connection buffer, this variable has the value of the like-named
1048method parameter, as specified in `tramp-methods' (which see).")
1049
1050(defvar tramp-rcp-args nil
1051 "This internal variable holds a parameter for `tramp-methods'.
1052In the connection buffer, this variable has the value of the like-named
1053method parameter, as specified in `tramp-methods' (which see).")
1054
1055(defvar tramp-rcp-keep-date-arg nil
1056 "This internal variable holds a parameter for `tramp-methods'.
1057In the connection buffer, this variable has the value of the like-named
1058method parameter, as specified in `tramp-methods' (which see).")
1059
1060(defvar tramp-encoding-command nil
1061 "This internal variable holds a parameter for `tramp-methods'.
1062In the connection buffer, this variable has the value of the like-named
1063method parameter, as specified in `tramp-methods' (which see).")
1064
1065(defvar tramp-decoding-command nil
1066 "This internal variable holds a parameter for `tramp-methods'.
1067In the connection buffer, this variable has the value of the like-named
1068method parameter, as specified in `tramp-methods' (which see).")
1069
1070(defvar tramp-encoding-function nil
1071 "This internal variable holds a parameter for `tramp-methods'.
1072In the connection buffer, this variable has the value of the like-named
1073method parameter, as specified in `tramp-methods' (which see).")
1074
1075(defvar tramp-decoding-function nil
1076 "This internal variable holds a parameter for `tramp-methods'.
1077In the connection buffer, this variable has the value of the like-named
1078method parameter, as specified in `tramp-methods' (which see).")
1079
1080(defvar tramp-telnet-program nil
1081 "This internal variable holds a parameter for `tramp-methods'.
1082In the connection buffer, this variable has the value of the like-named
1083method parameter, as specified in `tramp-methods' (which see).")
1084
1085(defvar tramp-telnet-args nil
1086 "This internal variable holds a parameter for `tramp-methods'.
1087In the connection buffer, this variable has the value of the like-named
1088method parameter, as specified in `tramp-methods' (which see).")
1089
1090;; CCC `local in each buffer'?
1091(defvar tramp-ls-command nil
1092 "This command is used to get a long listing with numeric user and group ids.
1093This variable is automatically made buffer-local to each rsh process buffer
1094upon opening the connection.")
1095
1096(defvar tramp-current-multi-method nil
1097 "Name of `multi' connection method for this *tramp* buffer, or nil if not multi.
1098This variable is automatically made buffer-local to each rsh process buffer
1099upon opening the connection.")
1100
1101(defvar tramp-current-method nil
1102 "Connection method for this *tramp* buffer.
1103This variable is automatically made buffer-local to each rsh process buffer
1104upon opening the connection.")
1105
1106(defvar tramp-current-user nil
1107 "Remote login name for this *tramp* buffer.
1108This variable is automatically made buffer-local to each rsh process buffer
1109upon opening the connection.")
1110
1111(defvar tramp-current-host nil
1112 "Remote host for this *tramp* buffer.
1113This variable is automatically made buffer-local to each rsh process buffer
1114upon opening the connection.")
1115
1116(defvar tramp-test-groks-nt nil
1117 "Whether the `test' command groks the `-nt' switch.
1118\(`test A -nt B' tests if file A is newer than file B.)
1119This variable is automatically made buffer-local to each rsh process buffer
1120upon opening the connection.")
1121
1122(defvar tramp-file-exists-command nil
1123 "Command to use for checking if a file exists.
1124This variable is automatically made buffer-local to each rsh process buffer
1125upon opening the connection.")
1126
1127;; Perl script to implement `file-attributes' in a Lisp `read'able output.
1128;; If you are hacking on this, note that you get *no* output unless this
1129;; spits out a complete line, including the '\n' at the end.
1130(defconst tramp-perl-file-attributes (concat
1131 "$f = $ARGV[0];
1132@s = lstat($f);
1133if (($s[2] & 0170000) == 0120000) { $l = readlink($f); $l = \"\\\"$l\\\"\"; }
1134elsif (($s[2] & 0170000) == 040000) { $l = \"t\"; }
1135else { $l = \"nil\" };
1136printf(\"(%s %u %u %u (%u %u) (%u %u) (%u %u) %u %u t (%u . %u) (%u %u))\\n\",
1137$l, $s[3], $s[4], $s[5], $s[8] >> 16 & 0xffff, $s[8] & 0xffff,
1138$s[9] >> 16 & 0xffff, $s[9] & 0xffff, $s[10] >> 16 & 0xffff, $s[10] & 0xffff,
1139$s[7], $s[2], $s[1] >> 16 & 0xffff, $s[1] & 0xffff, $s[0] >> 16 & 0xffff, $s[0] & 0xffff);"
1140 )
1141 "Perl script to produce output suitable for use with `file-attributes'
1142on the remote file system.")
1143
1144;; Perl script to implement `mime-encode'
1145(defvar tramp-perl-mime-encode (concat
1146 "sub encode_base64 ($);
1147 my $buf;
1148 while(read(STDIN, $buf, 60*57)) { print encode_base64($buf) }
1149 sub encode_base64 ($) {
1150 my $res = \"\";
1151 my $eol = \"\n\";
1152 pos($_[0]) = 0; # ensure start at the beginning
1153 while ($_[0] =~ /(.{1,45})/gs) {
1154 $res .= substr(pack(\"u\", $1), 1);
1155 chop($res);
1156 }
1157 $res =~ tr|` -_|AA-Za-z0-9+/|; # `# help emacs
1158 # fix padding at the end
1159 my $padding = (3 - length($_[0]) % 3) % 3;
1160 $res =~ s/.{$padding}$/\"=\" x $padding/e if $padding;
1161 # break encoded string into lines of no more than 76 characters each
1162 if (length $eol) {
1163 $res =~ s/(.{1,76})/$1$eol/g;
1164 }
1165 $res;}"))
1166
1167;; Perl script to implement `mime-decode'
1168(defvar tramp-perl-mime-decode (concat
1169 "sub decode_base64 ($);
1170 my $buf;
1171 while(read(STDIN, $buf, 60*57)) { print decode_base64($buf) }
1172 sub decode_base64 ($) {
1173 local($^W) = 0; # unpack(\"u\",...) gives bogus warning in 5.00[123]
1174
1175 my $str = shift;
1176 my $res = \"\";
1177
1178 $str =~ tr|A-Za-z0-9+=/||cd; # remove non-base64 chars
1179 if (length($str) % 4) {
1180 warn(\"Length of base64 data not a multiple of 4\")
1181 }
1182 $str =~ s/=+$//; # remove padding
1183 $str =~ tr|A-Za-z0-9+/| -_|; # convert to uuencoded format
1184 while ($str =~ /(.{1,60})/gs) {
1185 my $len = chr(32 + length($1)*3/4); # compute length byte
1186 $res .= unpack(\"u\", $len . $1 ); # uudecode
1187 }
1188 $res;}"))
1189
1190; These values conform to `file-attributes' from XEmacs 21.2.
1191; GNU Emacs and other tools not checked.
1192(defconst tramp-file-mode-type-map '((0 . "-") ; Normal file (SVID-v2 and XPG2)
1193 (1 . "p") ; fifo
1194 (2 . "c") ; character device
1195 (3 . "m") ; multiplexed character device (v7)
1196 (4 . "d") ; directory
1197 (5 . "?") ; Named special file (XENIX)
1198 (6 . "b") ; block device
1199 (7 . "?") ; multiplexed block device (v7)
1200 (8 . "-") ; regular file
1201 (9 . "n") ; network special file (HP-UX)
1202 (10 . "l") ; symlink
1203 (11 . "?") ; ACL shadow inode (Solaris, not userspace)
1204 (12 . "s") ; socket
1205 (13 . "D") ; door special (Solaris)
1206 (14 . "w")) ; whiteout (BSD)
1207 "A list of file types returned from the `stat' system call.
1208This is used to map a mode number to a permission string.")
1209
1210(defvar tramp-dos-coding-system
1211 (if (and (fboundp 'coding-system-p)
1212 (funcall 'coding-system-p '(dos)))
1213 'dos
1214 'undecided-dos)
1215 "Some Emacsen know the `dos' coding system, others need `undecided-dos'.")
1216
1217
1218;; New handlers should be added here. The following operations can be
1219;; handled using the normal primitives: file-name-as-directory,
1220;; file-name-directory, file-name-nondirectory,
1221;; file-name-sans-versions, get-file-buffer.
1222(defconst tramp-file-name-handler-alist
1223 '(
1224 (load . tramp-handle-load)
1225 (make-symbolic-link . tramp-handle-make-symbolic-link)
1226 (file-name-directory . tramp-handle-file-name-directory)
1227 (file-name-nondirectory . tramp-handle-file-name-nondirectory)
1228 (file-truename . tramp-handle-file-truename)
1229 (file-exists-p . tramp-handle-file-exists-p)
1230 (file-directory-p . tramp-handle-file-directory-p)
1231 (file-executable-p . tramp-handle-file-executable-p)
1232 (file-accessible-directory-p . tramp-handle-file-accessible-directory-p)
1233 (file-readable-p . tramp-handle-file-readable-p)
1234 (file-regular-p . tramp-handle-file-regular-p)
1235 (file-symlink-p . tramp-handle-file-symlink-p)
1236 (file-writable-p . tramp-handle-file-writable-p)
1237 (file-ownership-preserved-p . tramp-handle-file-ownership-preserved-p)
1238 (file-newer-than-file-p . tramp-handle-file-newer-than-file-p)
1239 (file-attributes . tramp-handle-file-attributes)
1240 (file-modes . tramp-handle-file-modes)
1241 (file-directory-files . tramp-handle-file-directory-files)
1242 (directory-files . tramp-handle-directory-files)
1243 (file-name-all-completions . tramp-handle-file-name-all-completions)
1244 (file-name-completion . tramp-handle-file-name-completion)
1245 (add-name-to-file . tramp-handle-add-name-to-file)
1246 (copy-file . tramp-handle-copy-file)
1247 (rename-file . tramp-handle-rename-file)
1248 (set-file-modes . tramp-handle-set-file-modes)
1249 (make-directory . tramp-handle-make-directory)
1250 (delete-directory . tramp-handle-delete-directory)
1251 (delete-file . tramp-handle-delete-file)
1252 (directory-file-name . tramp-handle-directory-file-name)
1253 (shell-command . tramp-handle-shell-command)
1254 (insert-directory . tramp-handle-insert-directory)
1255 (expand-file-name . tramp-handle-expand-file-name)
1256 (file-local-copy . tramp-handle-file-local-copy)
1257 (insert-file-contents . tramp-handle-insert-file-contents)
1258 (write-region . tramp-handle-write-region)
1259 (unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
1260 (dired-call-process . tramp-handle-dired-call-process)
1261 (dired-recursive-delete-directory
1262 . tramp-handle-dired-recursive-delete-directory)
1263 (set-visited-file-modtime . tramp-handle-set-visited-file-modtime)
1264 (verify-visited-file-modtime . tramp-handle-verify-visited-file-modtime))
1265 "Alist of handler functions.
1266Operations not mentioned here will be handled by the normal Emacs functions.")
1267
1268;;; For better error reporting.
1269
1270(defun tramp-version (arg)
1271 "Print version number of tramp.el in minibuffer or current buffer."
1272 (interactive "P")
1273 (if arg (insert tramp-version) (message tramp-version)))
1274
1275;;; Internal functions which must come first.
1276
1277(defsubst tramp-message (level fmt-string &rest args)
1278 "Emit a message depending on verbosity level.
1279First arg LEVEL says to be quiet if `tramp-verbose' is less than LEVEL. The
1280message is emitted only if `tramp-verbose' is greater than or equal to LEVEL.
1281Calls function `message' with FMT-STRING as control string and the remaining
1282ARGS to actually emit the message (if applicable).
1283
1284This function expects to be called from the tramp buffer only!"
1285 (when (<= level tramp-verbose)
1286 (apply #'message (concat "tramp: " fmt-string) args)
1287 (when tramp-debug-buffer
1288 (save-excursion
1289 (set-buffer
1290 (tramp-get-debug-buffer
1291 tramp-current-multi-method tramp-current-method
1292 tramp-current-user tramp-current-host))
1293 (goto-char (point-max))
1294 (tramp-insert-with-face
1295 'italic
1296 (concat "# " (apply #'format fmt-string args) "\n"))))))
1297
1298(defun tramp-message-for-buffer
1299 (multi-method method user host level fmt-string &rest args)
1300 "Like `tramp-message' but temporarily switches to the tramp buffer.
1301First three args METHOD, USER, and HOST identify the tramp buffer to use,
1302remaining args passed to `tramp-message'."
1303 (save-excursion
1304 (set-buffer (tramp-get-buffer multi-method method user host))
1305 (apply 'tramp-message level fmt-string args)))
1306
1307(defsubst tramp-line-end-position nil
1308 "Return point at end of line.
1309Calls `line-end-position' or `point-at-eol' if defined, else
1310own implementation."
1311 (cond
1312 ((fboundp 'line-end-position) (funcall 'line-end-position))
1313 ((fboundp 'point-at-eol) (funcall 'point-at-eol))
1314 (t (save-excursion (end-of-line) (point)))))
1315
1316;;; File Name Handler Functions:
1317
1318;; The following file name handler ops are not implemented (yet?).
1319
1320(defun tramp-handle-make-symbolic-link
1321 (filename linkname &optional ok-if-already-exists)
1322 "Like `make-symbolic-link' for tramp files.
1323This function will raise an error if FILENAME and LINKNAME are not
1324on the same remote host."
1325 (unless (or (tramp-tramp-file-p filename)
1326 (tramp-tramp-file-p linkname))
1327 (tramp-run-real-handler 'make-symbolic-link
1328 (list filename linkname ok-if-already-exists)))
1329 (let* ((file (tramp-dissect-file-name filename))
1330 (link (tramp-dissect-file-name linkname))
1331 (multi (tramp-file-name-multi-method file))
1332 (method (tramp-file-name-method file))
1333 (user (tramp-file-name-user file))
1334 (host (tramp-file-name-host file))
1335 (l-multi (tramp-file-name-multi-method link))
1336 (l-meth (tramp-file-name-method link))
1337 (l-user (tramp-file-name-user link))
1338 (l-host (tramp-file-name-host link))
1339 (ln (tramp-get-remote-ln multi method user host))
1340 (cwd (file-name-directory (tramp-file-name-path file))))
1341 (unless ln
1342 (signal 'file-error (list "Making a symbolic link."
1343 "ln(1) does not exist on the remote host.")))
1344
1345 ;; Check that method, user, host are the same.
1346 (unless (equal host l-host)
1347 (signal 'file-error (list "Can't make symlink across hosts" host l-host)))
1348 (unless (equal user l-user)
1349 (signal 'file-error (list "Can't make symlink for different users"
1350 user l-user)))
1351 (unless (and (equal multi l-multi)
1352 (equal method l-meth))
1353 (signal 'file-error (list "Method must be the same for making symlinks"
1354 multi l-multi method l-meth)))
1355
1356 ;; Do the 'confirm if exists' thing.
1357 (when (file-exists-p (tramp-file-name-path link))
1358 ;; What to do?
1359 (if (or (null ok-if-already-exists) ; not allowed to exist
1360 (and (numberp ok-if-already-exists)
1361 (not (yes-or-no-p
1362 (format "File %s already exists; make it a link anyway? "
1363 (tramp-file-name-path link))))))
1364 (signal 'file-already-exists (list "File already exists"
1365 (tramp-file-name-path link)))))
1366
1367 ;; Right, they are on the same host, regardless of user, method, etc.
1368 ;; We now make the link on the remote machine. This will occur as the user
1369 ;; that FILENAME belongs to.
1370 (zerop
1371 (tramp-send-command-and-check
1372 multi method user host
1373 (format "cd %s && %s -sf %s %s"
1374 cwd ln
1375 (tramp-file-name-path file) ; target
1376 (tramp-file-name-path link)) ; link name
1377 t))))
1378
1379
1380(defun tramp-handle-load (file &optional noerror nomessage nosuffix must-suffix)
1381 "Like `load' for tramp files. Not implemented!"
1382 (unless (file-name-absolute-p file)
1383 (error "Tramp cannot `load' files without absolute path name"))
1384 (unless nosuffix
1385 (cond ((file-exists-p (concat file ".elc"))
1386 (setq file (concat file ".elc")))
1387 ((file-exists-p (concat file ".el"))
1388 (setq file (concat file ".el")))))
1389 (when must-suffix
1390 ;; The first condition is always true for absolute file names.
1391 ;; Included for safety's sake.
1392 (unless (or (file-name-directory file)
1393 (string-match "\\.elc?\\'" file))
1394 (error "File `%s' does not include a `.el' or `.elc' suffix"
1395 file)))
1396 (unless noerror
1397 (when (not (file-exists-p file))
1398 (error "Cannot load nonexistant file `%s'" file)))
1399 (if (not (file-exists-p file))
1400 nil
1401 (unless nomessage
1402 (message "Loading %s..." file))
1403 (let ((local-copy (file-local-copy file)))
1404 ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
1405 (load local-copy noerror t t)
1406 (delete-file local-copy))
1407 (unless nomessage
1408 (message "Loading %s...done" file))
1409 t))
1410
1411;; Path manipulation functions that grok TRAMP paths...
1412(defun tramp-handle-file-name-directory (file)
1413 "Like `file-name-directory' but aware of TRAMP files."
1414 ;; everything except the last filename thing is the directory
1415 (let* ((v (tramp-dissect-file-name file))
1416 (multi-method (tramp-file-name-multi-method v))
1417 (method (tramp-file-name-method v))
1418 (user (tramp-file-name-user v))
1419 (host (tramp-file-name-host v))
1420 (path (tramp-file-name-path v)))
1421 (if (or (string= path "") (string= path "/"))
1422 ;; For a filename like "/[foo]", we return "/". The `else'
1423 ;; case would return "/[foo]" unchanged. But if we do that,
1424 ;; then `file-expand-wildcards' ceases to work. It's not
1425 ;; quite clear to me what's the intuition that tells that this
1426 ;; behavior is the right behavior, but oh, well.
1427 "/"
1428 ;; run the command on the path portion only
1429 ;; CCC: This should take into account the remote machine type, no?
1430 ;; --daniel <daniel@danann.net>
1431 (tramp-make-tramp-file-name multi-method method user host
1432 ;; This will not recurse...
1433 (or (file-name-directory path) "")))))
1434
1435(defun tramp-handle-file-name-nondirectory (file)
1436 "Like `file-name-nondirectory' but aware of TRAMP files."
1437 (let ((v (tramp-dissect-file-name file)))
1438 (file-name-nondirectory (tramp-file-name-path v))))
1439
1440(defun tramp-handle-file-truename (filename &optional counter prev-dirs)
1441 "Like `file-truename' for tramp files."
1442 (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))
1443 (multi-method (tramp-file-name-multi-method v))
1444 (method (tramp-file-name-method v))
1445 (user (tramp-file-name-user v))
1446 (host (tramp-file-name-host v))
1447 (path (tramp-file-name-path v))
1448 (steps (tramp-split-string path "/"))
1449 (pathdir (let ((directory-sep-char ?/))
1450 (file-name-as-directory path)))
1451 (is-dir (string= path pathdir))
1452 (thisstep nil)
1453 (numchase 0)
1454 ;; Don't make the following value larger than necessary.
1455 ;; People expect an error message in a timely fashion when
1456 ;; something is wrong; otherwise they might think that Emacs
1457 ;; is hung. Of course, correctness has to come first.
1458 (numchase-limit 20)
1459 (result nil) ;result steps in reverse order
1460 (curstri "")
1461 symlink-target)
1462 (tramp-message-for-buffer
1463 multi-method method user host
1464 10 "Finding true name for `%s'" filename)
1465 (while (and steps (< numchase numchase-limit))
1466 (setq thisstep (pop steps))
1467 (tramp-message-for-buffer
1468 multi-method method user host
1469 10 "Check %s"
1470 (mapconcat 'identity
1471 (append '("") (reverse result) (list thisstep))
1472 "/"))
1473 (setq symlink-target
1474 (nth 0 (tramp-handle-file-attributes
1475 (tramp-make-tramp-file-name
1476 multi-method method user host
1477 (mapconcat 'identity
1478 (append '("") (reverse result) (list thisstep))
1479 "/")))))
1480 (cond ((string= "." thisstep)
1481 (tramp-message-for-buffer multi-method method user host
1482 10 "Ignoring step `.'"))
1483 ((string= ".." thisstep)
1484 (tramp-message-for-buffer multi-method method user host
1485 10 "Processing step `..'")
1486 (pop result))
1487 ((stringp symlink-target)
1488 ;; It's a symlink, follow it.
1489 (tramp-message-for-buffer
1490 multi-method method user host
1491 10 "Follow symlink to %s" symlink-target)
1492 (setq numchase (1+ numchase))
1493 (when (file-name-absolute-p symlink-target)
1494 (setq result nil))
1495 (setq steps
1496 (append (tramp-split-string symlink-target "/") steps)))
1497 (t
1498 ;; It's a file.
1499 (setq result (cons thisstep result)))))
1500 (when (>= numchase numchase-limit)
1501 (error "Maximum number (%d) of symlinks exceeded" numchase-limit))
1502 (setq result (reverse result))
1503 (tramp-message-for-buffer
1504 multi-method method user host
1505 10 "True name of `%s' is `%s'"
1506 filename (mapconcat 'identity (cons "" result) "/"))
1507 (tramp-make-tramp-file-name
1508 multi-method method user host
1509 (concat (mapconcat 'identity (cons "" result) "/")
1510 (if is-dir "/" "")))))
1511
1512;; Basic functions.
1513
1514(defun tramp-handle-file-exists-p (filename)
1515 "Like `file-exists-p' for tramp files."
1516 (let ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))
1517 multi-method method user host path)
1518 (setq multi-method (tramp-file-name-multi-method v))
1519 (setq method (tramp-file-name-method v))
1520 (setq user (tramp-file-name-user v))
1521 (setq host (tramp-file-name-host v))
1522 (setq path (tramp-file-name-path v))
1523 (save-excursion
1524 (zerop (tramp-send-command-and-check
1525 multi-method method user host
1526 (format
1527 (tramp-get-file-exists-command multi-method method user host)
1528 (tramp-shell-quote-argument path)))))))
1529
1530;; CCC: This should check for an error condition and signal failure
1531;; when something goes wrong.
1532;; Daniel Pittman <daniel@danann.net>
1533(defun tramp-handle-file-attributes (filename &optional nonnumeric)
1534 "Like `file-attributes' for tramp files.
1535Optional argument NONNUMERIC means return user and group name
1536rather than as numbers."
1537 (if (tramp-handle-file-exists-p filename)
1538 ;; file exists, find out stuff
1539 (save-excursion
1540 (let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name filename)))
1541 (multi-method (tramp-file-name-multi-method v))
1542 (method (tramp-file-name-method v))
1543 (user (tramp-file-name-user v))
1544 (host (tramp-file-name-host v))
1545 (path (tramp-file-name-path v)))
1546 (if (tramp-get-remote-perl multi-method method user host)
1547 (tramp-handle-file-attributes-with-perl multi-method method user host path nonnumeric)
1548 (tramp-handle-file-attributes-with-ls multi-method method user host path nonnumeric))))
1549 nil)) ; no file
1550
1551
1552(defun tramp-handle-file-attributes-with-ls
1553 (multi-method method user host path &optional nonnumeric)
1554 "Implement `file-attributes' for tramp files using the ls(1) command."
1555 (let (symlinkp dirp
1556 res-inode res-filemodes res-numlinks
1557 res-uid res-gid res-size res-symlink-target)
1558 (tramp-send-command
1559 multi-method method user host
1560 (format "%s %s %s"
1561 (tramp-get-ls-command multi-method method user host)
1562 (if nonnumeric "-ild" "-ildn")
1563 (tramp-shell-quote-argument path)))
1564 (tramp-wait-for-output)
1565 ;; parse `ls -l' output ...
1566 ;; ... inode
1567 (setq res-inode
1568 (condition-case err
1569 (read (current-buffer))
1570 (invalid-read-syntax
1571 (when (and (equal (cadr err)
1572 "Integer constant overflow in reader")
1573 (string-match
1574 "^[0-9]+\\([0-9][0-9][0-9][0-9][0-9]\\)\\'"
1575 (caddr err)))
1576 (let* ((big (read (substring (caddr err) 0
1577 (match-beginning 1))))
1578 (small (read (match-string 1 (caddr err))))
1579 (twiddle (/ small 65536)))
1580 (cons (+ big twiddle)
1581 (- small (* twiddle 65536))))))))
1582 ;; ... file mode flags
1583 (setq res-filemodes (symbol-name (read (current-buffer))))
1584 ;; ... number links
1585 (setq res-numlinks (read (current-buffer)))
1586 ;; ... uid and gid
1587 (setq res-uid (read (current-buffer)))
1588 (setq res-gid (read (current-buffer)))
1589 (unless nonnumeric
1590 (unless (numberp res-uid) (setq res-uid -1))
1591 (unless (numberp res-gid) (setq res-gid -1)))
1592 ;; ... size
1593 (setq res-size (read (current-buffer)))
1594 ;; From the file modes, figure out other stuff.
1595 (setq symlinkp (eq ?l (aref res-filemodes 0)))
1596 (setq dirp (eq ?d (aref res-filemodes 0)))
1597 ;; if symlink, find out file name pointed to
1598 (when symlinkp
1599 (search-forward "-> ")
1600 (setq res-symlink-target
1601 (buffer-substring (point)
1602 (tramp-line-end-position))))
1603 ;; return data gathered
1604 (list
1605 ;; 0. t for directory, string (name linked to) for symbolic
1606 ;; link, or nil.
1607 (or dirp res-symlink-target nil)
1608 ;; 1. Number of links to file.
1609 res-numlinks
1610 ;; 2. File uid.
1611 res-uid
1612 ;; 3. File gid.
1613 res-gid
1614 ;; 4. Last access time, as a list of two integers. First
1615 ;; integer has high-order 16 bits of time, second has low 16
1616 ;; bits.
1617 ;; 5. Last modification time, likewise.
1618 ;; 6. Last status change time, likewise.
1619 '(0 0) '(0 0) '(0 0) ;CCC how to find out?
1620 ;; 7. Size in bytes (-1, if number is out of range).
1621 res-size
1622 ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
1623 res-filemodes
1624 ;; 9. t iff file's gid would change if file were deleted and
1625 ;; recreated.
1626 nil ;hm?
1627 ;; 10. inode number.
1628 res-inode
1629 ;; 11. Device number.
1630 -1 ;hm?
1631 )))
1632
1633(defun tramp-handle-file-attributes-with-perl
1634 (multi-method method user host path &optional nonnumeric)
1635 "Implement `file-attributes' for tramp files using a Perl script.
1636
1637The Perl command is sent to the remote machine when the connection
1638is initially created and is kept cached by the remote shell."
1639 (tramp-send-command
1640 multi-method method user host
1641 (format "tramp_file_attributes %s"
1642 (tramp-shell-quote-argument path)))
1643 (tramp-wait-for-output)
1644 (let ((result (read (current-buffer))))
1645 (setcar (nthcdr 8 result)
1646 (tramp-file-mode-from-int (nth 8 result)))
1647 result))
1648
1649(defun tramp-handle-set-visited-file-modtime (&optional time-list)
1650 "Like `set-visited-file-modtime' for tramp files."
1651 (unless (buffer-file-name)
1652 (error "Can't set-visited-file-modtime: buffer `%s' not visiting a file"
1653 (buffer-name)))
1654 (when time-list
1655 (tramp-run-real-handler 'set-visited-file-modtime (list time-list)))
1656 (let* ((coding-system-used nil)
1657 (f (buffer-file-name))
1658 (v (tramp-dissect-file-name f))
1659 (multi-method (tramp-file-name-multi-method v))
1660 (method (tramp-file-name-method v))
1661 (user (tramp-file-name-user v))
1662 (host (tramp-file-name-host v))
1663 (path (tramp-file-name-path v))
1664 (attr (file-attributes f))
1665 (modtime (nth 5 attr)))
1666 ;; We use '(0 0) as a don't-know value. See also
1667 ;; `tramp-handle-file-attributes-with-ls'.
1668 (when (boundp 'last-coding-system-used)
1669 (setq coding-system-used last-coding-system-used))
1670 (if (not (equal modtime '(0 0)))
1671 (tramp-run-real-handler 'set-visited-file-modtime (list modtime))
1672 (save-excursion
1673 (tramp-send-command
1674 multi-method method user host
1675 (format "%s -ild %s"
1676 (tramp-get-ls-command multi-method method user host)
1677 (tramp-shell-quote-argument path)))
1678 (tramp-wait-for-output)
1679 (setq attr (buffer-substring (point)
1680 (progn (end-of-line) (point)))))
1681 (setq tramp-buffer-file-attributes attr))
1682 (when (boundp 'last-coding-system-used)
1683 (setq last-coding-system-used coding-system-used))
1684 nil))
1685
1686;; This function makes the same assumption as
1687;; `tramp-handle-set-visited-file-modtime'.
1688(defun tramp-handle-verify-visited-file-modtime (buf)
1689 "Like `verify-visited-file-modtime' for tramp files."
1690 (with-current-buffer buf
1691 (let* ((f (buffer-file-name))
1692 (v (tramp-dissect-file-name f))
1693 (multi-method (tramp-file-name-multi-method v))
1694 (method (tramp-file-name-method v))
1695 (user (tramp-file-name-user v))
1696 (host (tramp-file-name-host v))
1697 (path (tramp-file-name-path v))
1698 (attr (file-attributes f))
1699 (modtime (nth 5 attr)))
1700 (if attr
1701 (if (not (equal modtime '(0 0)))
1702 ;; Why does `file-attributes' return a list (HIGH LOW), but
1703 ;; `visited-file-modtime' returns a cons (HIGH . LOW)?
1704 (let ((mt (visited-file-modtime)))
1705 (< (abs (tramp-time-diff modtime (list (car mt) (cdr mt)))) 2))
1706 (save-excursion
1707 (tramp-send-command
1708 multi-method method user host
1709 (format "%s -ild %s"
1710 (tramp-get-ls-command multi-method method user host)
1711 (tramp-shell-quote-argument path)))
1712 (tramp-wait-for-output)
1713 (setq attr (buffer-substring (point)
1714 (progn (end-of-line) (point)))))
1715 (equal tramp-buffer-file-attributes attr))
1716 ;; If file does not exist, say it is not modified.
1717 nil))))
1718
1719(defadvice clear-visited-file-modtime (after tramp activate)
1720 "Set `tramp-buffer-file-attributes' back to nil.
1721Tramp uses this variable as an emulation for the actual modtime of the file,
1722if the remote host can't provide the modtime."
1723 (setq tramp-buffer-file-attributes nil))
1724
1725(defun tramp-handle-set-file-modes (filename mode)
1726 "Like `set-file-modes' for tramp files."
1727 (let ((v (tramp-dissect-file-name filename)))
1728 (save-excursion
1729 (unless (zerop (tramp-send-command-and-check
1730 (tramp-file-name-multi-method v)
1731 (tramp-file-name-method v)
1732 (tramp-file-name-user v)
1733 (tramp-file-name-host v)
1734 (format "chmod %s %s"
1735 (tramp-decimal-to-octal mode)
1736 (tramp-shell-quote-argument
1737 (tramp-file-name-path v)))))
1738 (signal 'file-error
1739 (list "Doing chmod"
1740 ;; FIXME: extract the proper text from chmod's stderr.
1741 "error while changing file's mode"
1742 filename))))))
1743
1744;; Simple functions using the `test' command.
1745
1746(defun tramp-handle-file-executable-p (filename)
1747 "Like `file-executable-p' for tramp files."
1748 (zerop (tramp-run-test "-x" filename)))
1749
1750(defun tramp-handle-file-readable-p (filename)
1751 "Like `file-readable-p' for tramp files."
1752 (zerop (tramp-run-test "-r" filename)))
1753
1754(defun tramp-handle-file-accessible-directory-p (filename)
1755 "Like `file-accessible-directory-p' for tramp files."
1756 (and (zerop (tramp-run-test "-d" filename))
1757 (zerop (tramp-run-test "-r" filename))
1758 (zerop (tramp-run-test "-x" filename))))
1759
1760;; When the remote shell is started, it looks for a shell which groks
1761;; tilde expansion. Here, we assume that all shells which grok tilde
1762;; expansion will also provide a `test' command which groks `-nt' (for
1763;; newer than). If this breaks, tell me about it and I'll try to do
1764;; something smarter about it.
1765(defun tramp-handle-file-newer-than-file-p (file1 file2)
1766 "Like `file-newer-than-file-p' for tramp files."
1767 (cond ((not (file-exists-p file1))
1768 nil)
1769 ((not (file-exists-p file2))
1770 t)
1771 ;; We are sure both files exist at this point.
1772 (t
1773 (save-excursion
1774 (let* ((v1 (tramp-dissect-file-name file1))
1775 (mm1 (tramp-file-name-multi-method v1))
1776 (m1 (tramp-file-name-method v1))
1777 (u1 (tramp-file-name-user v1))
1778 (h1 (tramp-file-name-host v1))
1779 (v2 (tramp-dissect-file-name file2))
1780 (mm2 (tramp-file-name-multi-method v2))
1781 (m2 (tramp-file-name-method v2))
1782 (u2 (tramp-file-name-user v2))
1783 (h2 (tramp-file-name-host v2)))
1784 (unless (and (equal mm1 mm2)
1785 (equal m1 m2)
1786 (equal u1 u2)
1787 (equal h1 h2))
1788 (signal 'file-error
1789 (list "Files must have same method, user, host"
1790 file1 file2)))
1791 (unless (and (tramp-tramp-file-p file1)
1792 (tramp-tramp-file-p file2))
1793 (signal 'file-error
1794 (list "Files must be tramp files on same host"
1795 file1 file2)))
1796 (if (tramp-get-test-groks-nt mm1 m1 u1 h1)
1797 (zerop (tramp-run-test2 "test" file1 file2 "-nt"))
1798 (zerop (tramp-run-test2 "tramp_test_nt" file1 file2))))))))
1799
1800;; Functions implemented using the basic functions above.
1801
1802(defun tramp-handle-file-modes (filename)
1803 "Like `file-modes' for tramp files."
1804 (when (file-exists-p filename)
1805 (tramp-mode-string-to-int
1806 (nth 8 (tramp-handle-file-attributes filename)))))
1807
1808(defun tramp-handle-file-directory-p (filename)
1809 "Like `file-directory-p' for tramp files."
1810 ;; Care must be taken that this function returns `t' for symlinks
1811 ;; pointing to directories. Surely the most obvious implementation
1812 ;; would be `test -d', but that returns false for such symlinks.
1813 ;; CCC: Stefan Monnier says that `test -d' follows symlinks. And
1814 ;; I now think he's right. So we could be using `test -d', couldn't
1815 ;; we?
1816 ;;
1817 ;; Alternatives: `cd %s', `test -d %s'
1818 (save-excursion
1819 (let ((v (tramp-dissect-file-name filename)))
1820 (zerop
1821 (tramp-send-command-and-check
1822 (tramp-file-name-multi-method v) (tramp-file-name-method v)
1823 (tramp-file-name-user v) (tramp-file-name-host v)
1824 (format "test -d %s"
1825 (tramp-shell-quote-argument (tramp-file-name-path v)))
1826 t))))) ;run command in subshell
1827
1828(defun tramp-handle-file-regular-p (filename)
1829 "Like `file-regular-p' for tramp files."
1830 (and (tramp-handle-file-exists-p filename)
1831 (eq ?- (aref (nth 8 (tramp-handle-file-attributes filename)) 0))))
1832
1833(defun tramp-handle-file-symlink-p (filename)
1834 "Like `file-symlink-p' for tramp files."
1835 (let ((x (car (tramp-handle-file-attributes filename))))
1836 (when (stringp x) x)))
1837
1838(defun tramp-handle-file-writable-p (filename)
1839 "Like `file-writable-p' for tramp files."
1840 (if (tramp-handle-file-exists-p filename)
1841 ;; Existing files must be writable.
1842 (zerop (tramp-run-test "-w" filename))
1843 ;; If file doesn't exist, check if directory is writable.
1844 (and (zerop (tramp-run-test "-d" (tramp-handle-file-name-directory filename)))
1845 (zerop (tramp-run-test "-w" (tramp-handle-file-name-directory filename))))))
1846
1847(defun tramp-handle-file-ownership-preserved-p (filename)
1848 "Like `file-ownership-preserved-p' for tramp files."
1849 (or (not (tramp-handle-file-exists-p filename))
1850 ;; Existing files must be writable.
1851 (zerop (tramp-run-test "-O" filename))))
1852
1853;; Other file name ops.
1854
1855