Commit | Line | Data |
---|---|---|
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. | |
115 | The 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. | |
122 | This MUST be a Bourne-like shell. This shell is used to execute | |
123 | the encoding and decoding command on the local host, so if you | |
124 | want to use `~' in those commands, you should choose a shell here | |
125 | which groks tilde expansion. `/bin/sh' normally does not | |
126 | understand tilde expansion. | |
127 | ||
128 | Note that this variable is not used for remote commands. There are | |
129 | mechanisms in tramp.el which automatically determine the right shell to | |
130 | use 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. | |
598 | This is a list of entries of the form (NAME PARAM1 PARAM2 ...). | |
599 | Each NAME stands for a remote access method. Each PARAM is a | |
600 | pair 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 | ||
663 | What does all this mean? Well, you should specify `tramp-rsh-program', | |
664 | `tramp-telnet-program' or `tramp-su-program' for all methods; this program | |
665 | is used to log in to the remote site. Then, there are two ways to | |
666 | actually transfer the files between the local and the remote side. | |
667 | One way is using an additional rcp-like program. If you want to do | |
668 | this, set `tramp-rcp-program' in the method. | |
669 | ||
670 | Another possibility for file transfer is inline transfer, i.e. the | |
671 | file is passed through the same buffer used by `tramp-rsh-program'. In | |
672 | this case, the file contents need to be protected since the | |
673 | `tramp-rsh-program' might use escape codes or the connection might not | |
674 | be eight-bit clean. Therefore, file contents are encoded for transit. | |
675 | ||
676 | Two possibilities for encoding are uuencode/uudecode and mimencode. | |
677 | For uuencode/uudecode you want to set `tramp-encoding-command' to | |
678 | something like \"uuencode\" and `tramp-decoding-command' to \"uudecode | |
679 | -p\". For mimencode you want to set `tramp-encoding-command' to | |
680 | something like \"mimencode -b\" and `tramp-decoding-command' to | |
681 | \"mimencode -b -u\". | |
682 | ||
683 | When using inline transfer, you can use a program or a Lisp function | |
684 | on the local side to encode or decode the file contents. Set the | |
685 | `tramp-encoding-function' and `tramp-decoding-function' parameters to nil | |
686 | in order to use the commands or to the function to use. It is | |
687 | possible to specify one function and the other parameter as nil. | |
688 | ||
689 | So, 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 | |
692 | you must specify `tramp-rcp-program' and `tramp-rcp-args' and | |
693 | `tramp-encoding-command' and `tramp-decoding-command' must be nil. | |
694 | Every method, inline or out of band, must specify | |
695 | `tramp-connection-function' plus the associated arguments (for | |
696 | example, the telnet program if you chose | |
697 | `tramp-open-connection-telnet'). | |
698 | ||
699 | Notes: | |
700 | ||
701 | When using `tramp-open-connection-su' the phrase `open connection to a | |
702 | remote host' sounds strange, but it is used nevertheless, for | |
703 | consistency. No connection is opened to a remote host, but `su' is | |
704 | started on the local host. You are not allowed to specify a remote | |
705 | host other than `localhost' or the name of the local host. | |
706 | ||
707 | Using a uuencode/uudecode inline method is discouraged, please use one | |
708 | of the base64 methods instead since base64 encoding is much more | |
709 | reliable and the commands are more standardized between the different | |
710 | Unix versions. But if you can't use base64 for some reason, please | |
711 | note that the default uudecode command does not work well for some | |
712 | Unices, in particular AIX and Irix. For AIX, you might want to use | |
713 | the following command for uudecode: | |
714 | ||
715 | sed '/^begin/d;/^[` ]$/d;/^end/d' | iconv -f uucode -t ISO8859-1 | |
716 | ||
717 | For 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. | |
749 | Each entry in this list should be a method name as mentioned in the | |
750 | variable `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. | |
761 | Each list item is a list of three items (METHOD FUNCTION COMMAND), | |
762 | where METHOD is the name as used in the file name, FUNCTION is the | |
763 | function to be executed, and COMMAND is the shell command used for | |
764 | connecting. | |
765 | ||
766 | COMMAND may contain percent escapes. `%u' will be replaced with the | |
767 | user name, `%h' will be replaced with the host name, and `%n' will be | |
768 | replaced with an end-of-line character, as specified in the variable | |
769 | `tramp-rsh-end-of-line'. Use `%%' for a literal percent character. | |
770 | Note that the interpretation of the percent escapes also depends on | |
771 | the FUNCTION. For example, the `%u' escape is forbidden with the | |
772 | function `tramp-multi-connect-telnet'. See the documentation of the | |
773 | various 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. | |
779 | See `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. | |
785 | I don't think this ever needs to be changed, so please tell me about it | |
786 | if 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. | |
795 | Please notify me about other semi-standard directories to include here. | |
796 | ||
797 | You can use `~' in this list, but when searching for a shell which groks | |
798 | tilde 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. | |
805 | The 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. | |
812 | The regexp should match the whole line. | |
813 | ||
814 | The `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. | |
823 | The 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. | |
829 | If this is a relative file name (such as \"tramp.\"), it is considered | |
830 | relative to the directory name returned by the function | |
831 | `tramp-temporary-file-directory' (which see). It may also be an | |
832 | absolute file name; don't forget to include a prefix for the filename | |
833 | part, 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. | |
839 | Some 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 \ | |
849 | the tramp file name structure. | |
850 | ||
851 | The first element REGEXP is a regular expression matching a tramp file | |
852 | name. The regex should contain parentheses around the method name, | |
853 | the user name, the host name, and the file name parts. | |
854 | ||
855 | The second element METHOD is a number, saying which pair of | |
856 | parentheses matches the method name. The third element USER is | |
857 | similar, but for the user name. The fourth element HOST is similar, | |
858 | but for the host name. The fifth element FILE is for the file name. | |
859 | These numbers are passed directly to `match-string', which see. That | |
860 | means the opening parentheses are counted to identify the pair. | |
861 | ||
862 | See 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. | |
873 | This 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, | |
876 | if the tramp entry appears rather early in the `file-name-handler-alist' | |
877 | and is a bit too general, then some files might be considered tramp | |
878 | files which are not really tramp files. | |
879 | ||
880 | Please note that the entry in `file-name-handler-alist' is made when | |
881 | this file (tramp.el) is loaded. This means that this variable must be set | |
882 | before loading tramp.el. Alternatively, `file-name-handler-alist' can be | |
883 | updated after changing this variable. | |
884 | ||
885 | Also 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 | ||
897 | Also 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 | ||
910 | Also 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. | |
927 | Multi files allow you to contact a remote host in several hops. | |
928 | This is a list of four elements (REGEXP METHOD HOP PATH). | |
929 | ||
930 | The first element, REGEXP, gives a regular expression to match against | |
931 | the file name. In this regular expression, `%s' is replaced with the | |
932 | value of `tramp-multi-file-name-hop-structure'. (Note: in order to | |
933 | allow multiple hops, you normally want to use something like | |
934 | \"\\\\(\\\\(%s\\\\)+\\\\)\" in the regular expression. The outer pair | |
935 | of parentheses is used for the HOP element, see below.) | |
936 | ||
937 | All remaining elements are numbers. METHOD gives the number of the | |
938 | paren pair which matches the method name. HOP gives the number of the | |
939 | paren pair which matches the hop sequence. PATH gives the number of | |
940 | the paren pair which matches the path name on the remote host. | |
941 | ||
942 | PATH can also be negative, which means to count from the end. Ie, a | |
943 | value of -1 means the last paren pair. | |
944 | ||
945 | I think it would be good if the regexp matches the whole of the | |
946 | string, 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. | |
957 | This is a list of four elements (REGEXP METHOD USER HOST). First | |
958 | element REGEXP is used to match against the hop. Pair number METHOD | |
959 | matches the method of one hop, pair number USER matches the user of | |
960 | one hop, pair number HOST matches the host of one hop. | |
961 | ||
962 | This 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. | |
972 | This is a list of three elements PREFIX, HOP and PATH. | |
973 | ||
974 | The first element PREFIX says how to construct the prefix, the second | |
975 | element HOP specifies what each hop looks like, and the final element | |
976 | PATH says how to construct the path name. | |
977 | ||
978 | In PREFIX, `%%' means `%' and `%m' means the method name. | |
979 | ||
980 | In HOP, `%%' means `%' and `%m', `%u', `%h' mean the hop method, hop | |
981 | user and hop host, respectively. | |
982 | ||
983 | In PATH, `%%' means `%' and `%p' means the path name. | |
984 | ||
985 | The resulting file name always contains one copy of PREFIX and one | |
986 | copy of PATH, but there is one copy of HOP for each hop in the file | |
987 | name. | |
988 | ||
989 | Note: the current implementation requires the prefix to contain the | |
990 | method name, followed by all the hops, and the path name must come | |
991 | last." | |
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. | |
997 | Because Tramp wants to parse the output of the remote shell, it is easily | |
998 | confused by ANSI color escape sequences and suchlike. Often, shell init | |
999 | files 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. | |
1005 | Using shell wildcards for completions has the advantage that it can be | |
1006 | fast even in large directories, but completion is always | |
1007 | case-sensitive. Relying on Lisp only means that case-insensitive | |
1008 | completion is possible (subject to the variable `completion-ignore-case'), | |
1009 | but 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. | |
1017 | This variable is local to each buffer. It is not used if the remote | |
1018 | machine groks Perl. If it is used, it's used as an emulation for | |
1019 | the 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'. | |
1027 | In the connection buffer, this variable has the value of the like-named | |
1028 | method 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'. | |
1032 | In the connection buffer, this variable has the value of the like-named | |
1033 | method 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'. | |
1037 | In the connection buffer, this variable has the value of the like-named | |
1038 | method 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'. | |
1042 | In the connection buffer, this variable has the value of the like-named | |
1043 | method 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'. | |
1047 | In the connection buffer, this variable has the value of the like-named | |
1048 | method 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'. | |
1052 | In the connection buffer, this variable has the value of the like-named | |
1053 | method 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'. | |
1057 | In the connection buffer, this variable has the value of the like-named | |
1058 | method 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'. | |
1062 | In the connection buffer, this variable has the value of the like-named | |
1063 | method 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'. | |
1067 | In the connection buffer, this variable has the value of the like-named | |
1068 | method 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'. | |
1072 | In the connection buffer, this variable has the value of the like-named | |
1073 | method 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'. | |
1077 | In the connection buffer, this variable has the value of the like-named | |
1078 | method 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'. | |
1082 | In the connection buffer, this variable has the value of the like-named | |
1083 | method 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'. | |
1087 | In the connection buffer, this variable has the value of the like-named | |
1088 | method 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. | |
1093 | This variable is automatically made buffer-local to each rsh process buffer | |
1094 | upon 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. | |
1098 | This variable is automatically made buffer-local to each rsh process buffer | |
1099 | upon opening the connection.") | |
1100 | ||
1101 | (defvar tramp-current-method nil | |
1102 | "Connection method for this *tramp* buffer. | |
1103 | This variable is automatically made buffer-local to each rsh process buffer | |
1104 | upon opening the connection.") | |
1105 | ||
1106 | (defvar tramp-current-user nil | |
1107 | "Remote login name for this *tramp* buffer. | |
1108 | This variable is automatically made buffer-local to each rsh process buffer | |
1109 | upon opening the connection.") | |
1110 | ||
1111 | (defvar tramp-current-host nil | |
1112 | "Remote host for this *tramp* buffer. | |
1113 | This variable is automatically made buffer-local to each rsh process buffer | |
1114 | upon 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.) | |
1119 | This variable is automatically made buffer-local to each rsh process buffer | |
1120 | upon opening the connection.") | |
1121 | ||
1122 | (defvar tramp-file-exists-command nil | |
1123 | "Command to use for checking if a file exists. | |
1124 | This variable is automatically made buffer-local to each rsh process buffer | |
1125 | upon 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); | |
1133 | if (($s[2] & 0170000) == 0120000) { $l = readlink($f); $l = \"\\\"$l\\\"\"; } | |
1134 | elsif (($s[2] & 0170000) == 040000) { $l = \"t\"; } | |
1135 | else { $l = \"nil\" }; | |
1136 | printf(\"(%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' | |
1142 | on 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. | |
1208 | This 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. | |
1266 | Operations 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. | |
1279 | First arg LEVEL says to be quiet if `tramp-verbose' is less than LEVEL. The | |
1280 | message is emitted only if `tramp-verbose' is greater than or equal to LEVEL. | |
1281 | Calls function `message' with FMT-STRING as control string and the remaining | |
1282 | ARGS to actually emit the message (if applicable). | |
1283 | ||
1284 | This 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. | |
1301 | First three args METHOD, USER, and HOST identify the tramp buffer to use, | |
1302 | remaining 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. | |
1309 | Calls `line-end-position' or `point-at-eol' if defined, else | |
1310 | own 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. | |
1323 | This function will raise an error if FILENAME and LINKNAME are not | |
1324 | on 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. | |
1535 | Optional argument NONNUMERIC means return user and group name | |
1536 | rather 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 | ||
1637 | The Perl command is sent to the remote machine when the connection | |
1638 | is 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. | |
1721 | Tramp uses this variable as an emulation for the actual modtime of the file, | |
1722 | if 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 |