;; this would load dbus.el.
(when (and (featurep 'dbusbind)
(condition-case nil
- (funcall 'dbus-get-unique-name :session)
+ (tramp-compat-funcall 'dbus-get-unique-name :session)
(error nil))
(tramp-compat-process-running-p "gvfs-fuse-daemon"))
'tramp-gvfs)
(tramp-copy-recursive t)
(tramp-password-end-of-line nil))
("scp" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k")
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("scp1" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-1" "-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
(tramp-copy-args (("-1") ("-P" "%p") ("-p" "%k")
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("scp2" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-2" "-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
(tramp-copy-args (("-2") ("-P" "%p") ("-p" "%k")
("sftp" (tramp-login-program "ssh")
(tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "sftp")
(tramp-copy-args nil)
("rsync" (tramp-login-program "ssh")
(tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rsync")
(tramp-copy-args (("-e" "ssh") ("-t" "%k") ("-r")))
("-o" "ControlPath=%t.%%r@%%h:%%p")
("-o" "ControlMaster=yes")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "rsync")
(tramp-copy-args (("-t" "%k") ("-r")))
(tramp-copy-keep-date nil)
(tramp-password-end-of-line nil))
("ssh" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program nil)
(tramp-copy-args nil)
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("ssh1" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-1" "-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program nil)
(tramp-copy-args nil)
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("ssh2" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-2" "-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program nil)
(tramp-copy-args nil)
(tramp-login-program "ssh1")
(tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program nil)
(tramp-copy-args nil)
(tramp-copy-keep-date nil)
(tramp-password-end-of-line nil))
("scpc" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-o" "ControlPath=%t.%%r@%%h:%%p")
("-o" "ControlMaster=yes")
("-e" "none")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
(tramp-copy-args (("-P" "%p") ("-p" "%k") ("-q")
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("scpx" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none" "-t" "-t" "/bin/sh")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program "scp")
(tramp-copy-args (("-p" "%k")))
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22))
("sshx" (tramp-login-program "ssh")
- (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p") ("-q")
+ (tramp-login-args (("%h") ("-l" "%u") ("-p" "%p")
("-e" "none" "-t" "-t" "/bin/sh")))
+ (tramp-async-args (("-q")))
(tramp-remote-sh "/bin/sh")
(tramp-copy-program nil)
(tramp-copy-args nil)
\"%t\" is replaced by the temporary file name produced with
`tramp-make-tramp-temp-file'. \"%k\" indicates the keep-date
parameter of a program, if exists.
+ * `tramp-async-args'
+ When an asynchronous process is started, we know already that
+ the connection works. Therefore, we can pass additional
+ parameters to suppress diagnostic messages, in order not to
+ tamper the process output.
* `tramp-copy-program'
This specifies the name of the program to use for remotely copying
the file; this might be the absolute filename of rcp or the name of
;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
;; GNU/Linux (Debian, Suse): /bin:/usr/bin
;; FreeBSD: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
+;; IRIX64: /usr/bin
(defcustom tramp-remote-path
'(tramp-default-remote-path "/usr/sbin" "/usr/local/bin"
"/local/bin" "/local/freeware/bin" "/local/gnu/bin"
`("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_ALL=C"
,(format "TERM=%s" tramp-terminal-type)
"EMACS=t" ;; Deprecated.
- ,(format "INSIDE_EMACS=%s,tramp:%s" emacs-version tramp-version)
+ ,(format "INSIDE_EMACS='%s,tramp:%s'" emacs-version tramp-version)
"CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH="
"autocorrect=" "correct=")
(defcustom tramp-shell-prompt-pattern
;; Allow a prompt to start right after a ^M since it indeed would be
- ;; displayed at the beginning of the line (and Zsh uses it).
- "\\(?:^\\|\r\\)[^#$%>\n]*#?[#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*"
+ ;; displayed at the beginning of the line (and Zsh uses it). This
+ ;; regexp works only for GNU Emacs.
+ (concat (if (featurep 'xemacs) "" "\\(?:^\\|\r\\)")
+ "[^#$%>\n]*#?[#$%>] *\\(\e\\[[0-9;]*[a-zA-Z] *\\)*")
"Regexp to match prompts from remote shell.
Normally, Tramp expects you to configure `shell-prompt-pattern'
correctly, but sometimes it happens that you are connecting to a
$stat[2],
$stat[1] >> 16 & 0xffff,
$stat[1] & 0xffff
-);' \"$1\" \"$2\" \"$3\" 2>/dev/null"
+);' \"$1\" \"$2\" 2>/dev/null"
"Perl script to produce output suitable for use with `file-attributes'
on the remote file system.
Escape sequence %s is replaced with name of Perl binary.
$stat[0] >> 16 & 0xffff,
$stat[0] & 0xffff);
}
-printf(\")\\n\");' \"$1\" \"$2\" \"$3\" 2>/dev/null"
+printf(\")\\n\");' \"$1\" \"$2\" 2>/dev/null"
"Perl script implementing `directory-files-attributes' as Lisp `read'able
output.
Escape sequence %s is replaced with name of Perl binary.
(setq fn (symbol-name btf))
(unless (and (string-match "^tramp" fn)
(not (string-match
- "^tramp\\(-debug\\)?\\(-message\\|-error\\)$"
+ "^tramp\\(-debug\\)?\\(-message\\|-error\\|-compat-funcall\\)$"
fn)))
(setq fn nil)))
(setq btn (1+ btn))))
(put 'with-connection-property 'edebug-form-spec t)
(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-connection-property\\>"))
+(defun tramp-progress-reporter-update (reporter &optional value)
+ (let* ((parameters (cdr reporter))
+ (message (aref parameters 3)))
+ (when (string-match message (or (current-message) ""))
+ (funcall 'progress-reporter-update reporter value))))
+
(defmacro with-progress-reporter (vec level message &rest body)
- "Executes BODY, spinning a progress reporter with MESSAGE."
+ "Executes BODY, spinning a progress reporter with MESSAGE.
+If LEVEL does not fit for visible messages, or if this is a
+nested call of the macro, there are only traces without a visible
+progress reporter."
`(let (pr tm)
(tramp-message ,vec ,level "%s..." ,message)
;; We start a pulsing progress reporter after 3 seconds. Feature
;; introduced in Emacs 24.1.
- (when (<= ,level tramp-verbose)
+ (when (and tramp-message-show-message
+ ;; Display only when there is a minimum level.
+ (<= ,level (min tramp-verbose 3)))
(condition-case nil
- (setq pr (funcall 'make-progress-reporter ,message)
- tm (run-at-time 3 0.1 'progress-reporter-update pr))
+ (setq pr (tramp-compat-funcall 'make-progress-reporter ,message)
+ tm (when pr
+ (run-at-time 3 0.1 'tramp-progress-reporter-update pr)))
(error nil)))
(unwind-protect
- ;; Execute the body.
- (progn ,@body)
+ ;; Execute the body. Unset `tramp-message-show-message' when
+ ;; the timer object is created, in order to suppress
+ ;; concurrent timers.
+ (let ((tramp-message-show-message
+ (and tramp-message-show-message (not tm))))
+ ,@body)
;; Stop progress reporter.
- (if tm (cancel-timer tm))
+ (if tm (tramp-compat-funcall 'cancel-timer tm))
(tramp-message ,vec ,level "%s...done" ,message))))
(put 'with-progress-reporter 'lisp-indent-function 3)
special handling of `substitute-in-file-name'."
(when (symbol-value 'minibuffer-completing-file-name)
(setq tramp-rfn-eshadow-overlay
- (funcall (symbol-function 'make-overlay)
- (funcall (symbol-function 'minibuffer-prompt-end))
- (funcall (symbol-function 'minibuffer-prompt-end))))
+ (tramp-compat-funcall
+ 'make-overlay
+ (tramp-compat-funcall 'minibuffer-prompt-end)
+ (tramp-compat-funcall 'minibuffer-prompt-end)))
;; Copy rfn-eshadow-overlay properties.
- (let ((props (funcall (symbol-function 'overlay-properties)
- (symbol-value 'rfn-eshadow-overlay))))
+ (let ((props (tramp-compat-funcall
+ 'overlay-properties (symbol-value 'rfn-eshadow-overlay))))
(while props
- (funcall (symbol-function 'overlay-put)
- tramp-rfn-eshadow-overlay (pop props) (pop props))))))
+ (tramp-compat-funcall
+ 'overlay-put tramp-rfn-eshadow-overlay (pop props) (pop props))))))
(when (boundp 'rfn-eshadow-setup-minibuffer-hook)
(add-hook 'rfn-eshadow-setup-minibuffer-hook
`file-name-shadow-mode'; the minibuffer should have already
been set up by `rfn-eshadow-setup-minibuffer'."
;; In remote files name, there is a shadowing just for the local part.
- (let ((end (or (funcall (symbol-function 'overlay-end)
- (symbol-value 'rfn-eshadow-overlay))
- (funcall (symbol-function 'minibuffer-prompt-end)))))
- (when (file-remote-p (buffer-substring-no-properties end (point-max)))
+ (let ((end (or (tramp-compat-funcall
+ 'overlay-end (symbol-value 'rfn-eshadow-overlay))
+ (tramp-compat-funcall 'minibuffer-prompt-end))))
+ (when
+ (file-remote-p
+ (tramp-compat-funcall 'buffer-substring-no-properties end (point-max)))
(save-excursion
(save-restriction
(narrow-to-region
(point-max))
(let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
(rfn-eshadow-update-overlay-hook nil))
- (move-overlay rfn-eshadow-overlay (point-max) (point-max))
- (funcall (symbol-function 'rfn-eshadow-update-overlay))))))))
+ (tramp-compat-funcall
+ 'move-overlay rfn-eshadow-overlay (point-max) (point-max))
+ (tramp-compat-funcall 'rfn-eshadow-update-overlay)))))))
(when (boundp 'rfn-eshadow-update-overlay-hook)
(add-hook 'rfn-eshadow-update-overlay-hook
(tramp-error v 'file-error "Cannot load nonexistent file `%s'" file)))
(if (not (file-exists-p file))
nil
- (unless nomessage (tramp-message v 0 "Loading %s..." file))
- (let ((local-copy (file-local-copy file)))
- ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
- (unwind-protect
- (load local-copy noerror t t)
- (delete-file local-copy)))
- (unless nomessage (tramp-message v 0 "Loading %s...done" file))
+ (let ((tramp-message-show-message (not nomessage)))
+ (with-progress-reporter v 0 (format "Loading %s" file)
+ (let ((local-copy (file-local-copy file)))
+ ;; MUST-SUFFIX doesn't exist on XEmacs, so let it default to nil.
+ (unwind-protect
+ (load local-copy noerror t t)
+ (delete-file local-copy)))))
t)))
;; Localname manipulation functions that grok Tramp localnames...
(tramp-send-command-and-read
vec
(format
- "((%s %s || %s -h %s) && %s -c '((\"%%N\") %%h %s %s %%X.0 %%Y.0 %%Z.0 %%s.0 \"%%A\" t %%i.0 -1)' %s || echo nil)"
+ ;; On Opsware, pdksh (which is the true name of ksh there) doesn't
+ ;; parse correctly the sequence "((". Therefore, we add a space.
+ "( (%s %s || %s -h %s) && %s -c '( (\"%%N\") %%h %s %s %%X.0 %%Y.0 %%Z.0 %%s.0 \"%%A\" t %%i.0 -1)' %s || echo nil)"
(tramp-get-file-exists-command vec)
(tramp-shell-quote-argument localname)
(tramp-get-test-command vec)
function directly, unless those two cases are already taken care
of."
(with-current-buffer buf
- ;; There is no file visiting the buffer, or the buffer has no
- ;; recorded last modification time.
- (if (or (not (buffer-file-name))
- (eq (visited-file-modtime) 0))
- t
- (let ((f (buffer-file-name)))
+ (let ((f (buffer-file-name)))
+ ;; There is no file visiting the buffer, or the buffer has no
+ ;; recorded last modification time, or there is no established
+ ;; connection.
+ (if (or (not f)
+ (eq (visited-file-modtime) 0)
+ (not (tramp-file-name-handler 'file-remote-p f nil 'connected)))
+ t
(with-parsed-tramp-file-name f nil
(tramp-flush-file-property v localname)
(let* ((attr (file-attributes f))
(let ((time (if (or (null time) (equal time '(0 0)))
(current-time)
time))
- (utc
- ;; With GNU Emacs, `format-time-string' has an
- ;; optional parameter UNIVERSAL. This is preferred,
- ;; because we could handle the case when the remote
- ;; host is located in a different time zone as the
- ;; local host.
- (and (functionp 'subr-arity)
- (subrp (symbol-function 'format-time-string))
- (= 3 (cdr (funcall (symbol-function 'subr-arity)
- (symbol-function
- 'format-time-string)))))))
+ ;; With GNU Emacs, `format-time-string' has an optional
+ ;; parameter UNIVERSAL. This is preferred, because we
+ ;; could handle the case when the remote host is
+ ;; located in a different time zone as the local host.
+ (utc (not (featurep 'xemacs))))
(tramp-send-command-and-check
v (format "%s touch -t %s %s"
(if utc "TZ=UTC; export TZ;" "")
(apply 'file-selinux-context (list filename))))
pr tm)
- (when (and (not ok-if-already-exists) (file-exists-p newname))
- (with-parsed-tramp-file-name (if t1 filename newname) nil
+ (with-parsed-tramp-file-name (if t1 filename newname) nil
+ (when (and (not ok-if-already-exists) (file-exists-p newname))
(tramp-error
- v 'file-already-exists "File %s already exists" newname)))
+ v 'file-already-exists "File %s already exists" newname))
- (with-parsed-tramp-file-name (if t1 filename newname) nil
(with-progress-reporter
- v 0 (format "Transferring %s to %s" filename newname)
+ v 0 (format "%s %s to %s"
+ (if (eq op 'copy) "Copying" "Renaming")
+ filename newname)
- (cond
- ;; Both are Tramp files.
- ((and t1 t2)
- (with-parsed-tramp-file-name filename v1
- (with-parsed-tramp-file-name newname v2
- (cond
- ;; Shortcut: if method, host, user are the same for both
- ;; files, we invoke `cp' or `mv' on the remote host
- ;; directly.
- ((tramp-equal-remote filename newname)
- (tramp-do-copy-or-rename-file-directly
- op filename newname
- ok-if-already-exists keep-date preserve-uid-gid))
-
- ;; Try out-of-band operation.
- ((tramp-method-out-of-band-p
- v1 (nth 7 (file-attributes filename)))
- (tramp-do-copy-or-rename-file-out-of-band
- op filename newname keep-date))
-
- ;; No shortcut was possible. So we copy the
- ;; file first. If the operation was `rename', we go
- ;; back and delete the original file (if the copy was
- ;; successful). The approach is simple-minded: we
- ;; create a new buffer, insert the contents of the
- ;; source file into it, then write out the buffer to
- ;; the target file. The advantage is that it doesn't
- ;; matter which filename handlers are used for the
- ;; source and target file.
- (t
- (tramp-do-copy-or-rename-file-via-buffer
- op filename newname keep-date))))))
+ (cond
+ ;; Both are Tramp files.
+ ((and t1 t2)
+ (with-parsed-tramp-file-name filename v1
+ (with-parsed-tramp-file-name newname v2
+ (cond
+ ;; Shortcut: if method, host, user are the same for
+ ;; both files, we invoke `cp' or `mv' on the remote
+ ;; host directly.
+ ((tramp-equal-remote filename newname)
+ (tramp-do-copy-or-rename-file-directly
+ op filename newname
+ ok-if-already-exists keep-date preserve-uid-gid))
+
+ ;; Try out-of-band operation.
+ ((tramp-method-out-of-band-p
+ v1 (nth 7 (file-attributes filename)))
+ (tramp-do-copy-or-rename-file-out-of-band
+ op filename newname keep-date))
+
+ ;; No shortcut was possible. So we copy the file
+ ;; first. If the operation was `rename', we go back
+ ;; and delete the original file (if the copy was
+ ;; successful). The approach is simple-minded: we
+ ;; create a new buffer, insert the contents of the
+ ;; source file into it, then write out the buffer to
+ ;; the target file. The advantage is that it doesn't
+ ;; matter which filename handlers are used for the
+ ;; source and target file.
+ (t
+ (tramp-do-copy-or-rename-file-via-buffer
+ op filename newname keep-date))))))
+
+ ;; One file is a Tramp file, the other one is local.
+ ((or t1 t2)
+ (cond
+ ;; Fast track on local machine.
+ ((tramp-local-host-p v)
+ (tramp-do-copy-or-rename-file-directly
+ op filename newname
+ ok-if-already-exists keep-date preserve-uid-gid))
- ;; One file is a Tramp file, the other one is local.
- ((or t1 t2)
- (cond
- ;; Fast track on local machine.
- ((tramp-local-host-p v)
- (tramp-do-copy-or-rename-file-directly
- op filename newname
- ok-if-already-exists keep-date preserve-uid-gid))
-
- ;; If the Tramp file has an out-of-band method, the corresponding
- ;; copy-program can be invoked.
- ((tramp-method-out-of-band-p v (nth 7 (file-attributes filename)))
- (tramp-do-copy-or-rename-file-out-of-band
- op filename newname keep-date))
-
- ;; Use the inline method via a Tramp buffer.
- (t (tramp-do-copy-or-rename-file-via-buffer
- op filename newname keep-date))))
-
- (t
- ;; One of them must be a Tramp file.
- (error "Tramp implementation says this cannot happen")))
-
- ;; Handle `preserve-selinux-context'.
- (when context (apply 'set-file-selinux-context (list newname context)))
-
- ;; In case of `rename', we must flush the cache of the source file.
- (when (and t1 (eq op 'rename))
- (with-parsed-tramp-file-name filename v1
- (tramp-flush-file-property v1 (file-name-directory localname))
- (tramp-flush-file-property v1 localname)))
-
- ;; When newname did exist, we have wrong cached values.
- (when t2
- (with-parsed-tramp-file-name newname v2
- (tramp-flush-file-property v2 (file-name-directory localname))
- (tramp-flush-file-property v2 localname)))))))
+ ;; If the Tramp file has an out-of-band method, the
+ ;; corresponding copy-program can be invoked.
+ ((tramp-method-out-of-band-p v (nth 7 (file-attributes filename)))
+ (tramp-do-copy-or-rename-file-out-of-band
+ op filename newname keep-date))
+
+ ;; Use the inline method via a Tramp buffer.
+ (t (tramp-do-copy-or-rename-file-via-buffer
+ op filename newname keep-date))))
+
+ (t
+ ;; One of them must be a Tramp file.
+ (error "Tramp implementation says this cannot happen")))
+
+ ;; Handle `preserve-selinux-context'.
+ (when context (apply 'set-file-selinux-context (list newname context)))
+
+ ;; In case of `rename', we must flush the cache of the source file.
+ (when (and t1 (eq op 'rename))
+ (with-parsed-tramp-file-name filename v1
+ (tramp-flush-file-property v1 (file-name-directory localname))
+ (tramp-flush-file-property v1 localname)))
+
+ ;; When newname did exist, we have wrong cached values.
+ (when t2
+ (with-parsed-tramp-file-name newname v2
+ (tramp-flush-file-property v2 (file-name-directory localname))
+ (tramp-flush-file-property v2 localname)))))))
(defun tramp-do-copy-or-rename-file-via-buffer (op filename newname keep-date)
"Use an Emacs buffer to copy or rename a file.
(tramp-shell-quote-argument localname))))
(tramp-error v 'file-error "Couldn't delete %s" directory))))
-(defun tramp-handle-delete-file (filename)
+(defun tramp-handle-delete-file (filename &optional trash)
"Like `delete-file' for Tramp files."
(setq filename (expand-file-name filename))
(with-parsed-tramp-file-name filename nil
(tramp-flush-file-property v (file-name-directory localname))
(tramp-flush-file-property v localname)
- (unless (zerop (tramp-send-command-and-check
- v
- (format "rm -f %s"
- (tramp-shell-quote-argument localname))))
+ (unless
+ (zerop
+ (tramp-send-command-and-check
+ v (format "%s %s"
+ (or (and trash (tramp-get-remote-trash v)) "rm -f")
+ (tramp-shell-quote-argument localname))))
(tramp-error v 'file-error "Couldn't delete %s" filename))))
;; Dired.
nil)
((and suffix (nth 2 suffix))
;; We found an uncompression rule.
- (with-progress-reporter v 0 (format "Uncompressing %s..." file)
+ (with-progress-reporter v 0 (format "Uncompressing %s" file)
(when (zerop
(tramp-send-command-and-check
v (concat (nth 2 suffix) " "
(tramp-shell-quote-argument localname))))
- ;; `dired-remove-file' is not defined in XEmacs
- (funcall (symbol-function 'dired-remove-file) file)
+ ;; `dired-remove-file' is not defined in XEmacs.
+ (tramp-compat-funcall 'dired-remove-file file)
(string-match (car suffix) file)
(concat (substring file 0 (match-beginning 0))))))
(t
;; We don't recognize the file as compressed, so compress it.
;; Try gzip.
- (with-progress-reporter v 0 (format "Compressing %s..." file)
+ (with-progress-reporter v 0 (format "Compressing %s" file)
(when (zerop
(tramp-send-command-and-check
v (concat "gzip -f "
(tramp-shell-quote-argument localname))))
- ;; `dired-remove-file' is not defined in XEmacs
- (funcall (symbol-function 'dired-remove-file) file)
+ ;; `dired-remove-file' is not defined in XEmacs.
+ (tramp-compat-funcall 'dired-remove-file file)
(cond ((file-exists-p (concat file ".gz"))
(concat file ".gz"))
((file-exists-p (concat file ".z"))
(forward-line -2)
(when (looking-at "//SUBDIRED//")
(forward-line -1))
- (when (looking-at "//DIRED//")
- (let ((end (tramp-compat-line-end-position))
- (linebeg (point)))
+ (when (looking-at "//DIRED//\\s-+")
+ (let ((databeg (match-end 0))
+ (end (tramp-compat-line-end-position)))
;; Now read the numeric positions of file names.
- (goto-char linebeg)
- (forward-word 1)
- (forward-char 3)
+ (goto-char databeg)
(while (< (point) end)
(let ((start (+ beg (read (current-buffer))))
(end (+ beg (read (current-buffer)))))
(let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
;; We cannot use `shell-file-name' and `shell-command-switch',
;; they are variables of the local host.
- (args (list "/bin/sh" "-c" (substring command 0 asynchronous)))
+ (args (list
+ (tramp-get-method-parameter
+ (tramp-file-name-method
+ (tramp-dissect-file-name default-directory))
+ 'tramp-remote-sh)
+ "-c" (substring command 0 asynchronous)))
current-buffer-p
(output-buffer
(cond
;; There's some output, display it.
(when (with-current-buffer output-buffer (> (point-max) (point-min)))
(if (functionp 'display-message-or-buffer)
- (funcall (symbol-function 'display-message-or-buffer)
- output-buffer)
+ (tramp-compat-funcall 'display-message-or-buffer output-buffer)
(pop-to-buffer output-buffer))))))))
;; File Editing.
;; Use inline encoding for file transfer.
(rem-enc
(save-excursion
- (tramp-message v 5 "Encoding remote file %s..." filename)
- (tramp-barf-unless-okay
- v (format rem-enc (tramp-shell-quote-argument localname))
- "Encoding remote file failed")
- (tramp-message v 5 "Encoding remote file %s...done" filename)
+ (with-progress-reporter
+ v 3 (format "Encoding remote file %s" filename)
+ (tramp-barf-unless-okay
+ v (format rem-enc (tramp-shell-quote-argument localname))
+ "Encoding remote file failed"))
(if (functionp loc-dec)
;; If local decoding is a function, we call it. We
(with-temp-buffer
(set-buffer-multibyte nil)
(insert-buffer-substring (tramp-get-buffer v))
- (tramp-message
- v 5 "Decoding remote file %s with function %s..."
- filename loc-dec)
- (funcall loc-dec (point-min) (point-max))
- ;; Unset `file-name-handler-alist'. Otherwise,
- ;; epa-file gets confused.
- (let (file-name-handler-alist
- (coding-system-for-write 'binary))
- (write-region (point-min) (point-max) tmpfile)))
+ (with-progress-reporter
+ v 3 (format "Decoding remote file %s with function %s"
+ filename loc-dec)
+ (funcall loc-dec (point-min) (point-max))
+ ;; Unset `file-name-handler-alist'. Otherwise,
+ ;; epa-file gets confused.
+ (let (file-name-handler-alist
+ (coding-system-for-write 'binary))
+ (write-region (point-min) (point-max) tmpfile))))
;; If tramp-decoding-function is not defined for this
;; method, we invoke tramp-decoding-command instead.
(let (file-name-handler-alist
(coding-system-for-write 'binary))
(write-region (point-min) (point-max) tmpfile2))
- (tramp-message
- v 5 "Decoding remote file %s with command %s..."
- filename loc-dec)
- (unwind-protect
- (tramp-call-local-coding-command loc-dec tmpfile2 tmpfile)
- (delete-file tmpfile2))))
+ (with-progress-reporter
+ v 3 (format "Decoding remote file %s with command %s"
+ filename loc-dec)
+ (unwind-protect
+ (tramp-call-local-coding-command
+ loc-dec tmpfile2 tmpfile)
+ (delete-file tmpfile2)))))
- (tramp-message v 5 "Decoding remote file %s...done" filename)
;; Set proper permissions.
(set-file-modes tmpfile (tramp-default-file-modes filename))
;; Set local user ownership.
"Like `insert-file-contents' for Tramp files."
(barf-if-buffer-read-only)
(setq filename (expand-file-name filename))
- (let (coding-system-used result local-copy remote-copy)
+ (let (result local-copy remote-copy)
(with-parsed-tramp-file-name filename nil
(unwind-protect
(if (not (file-exists-p filename))
(setq tramp-temp-buffer-file-name local-copy)
(put 'tramp-temp-buffer-file-name 'permanent-local t))
- (tramp-message
- v 4 "Inserting local temp file `%s'..." local-copy)
-
- ;; We must ensure that `file-coding-system-alist'
- ;; matches `local-copy'.
- (let ((file-coding-system-alist
- (tramp-find-file-name-coding-system-alist
- filename local-copy)))
- (setq result
- (insert-file-contents
- local-copy nil nil nil replace))
- ;; Now `last-coding-system-used' has right value.
- ;; Remember it.
- (when (boundp 'last-coding-system-used)
- (setq coding-system-used
- (symbol-value 'last-coding-system-used))))
-
- (tramp-message
- v 4 "Inserting local temp file `%s'...done" local-copy)
- (when (boundp 'last-coding-system-used)
- (set 'last-coding-system-used coding-system-used))))
+ (with-progress-reporter
+ v 3 (format "Inserting local temp file `%s'" local-copy)
+ ;; We must ensure that `file-coding-system-alist'
+ ;; matches `local-copy'.
+ (let ((file-coding-system-alist
+ (tramp-find-file-name-coding-system-alist
+ filename local-copy)))
+ (setq result
+ (insert-file-contents
+ local-copy nil nil nil replace))))))
;; Save exit.
(progn
;; Use inline file transfer.
(rem-dec
;; Encode tmpfile.
- (tramp-message v 5 "Encoding region...")
(unwind-protect
(with-temp-buffer
(set-buffer-multibyte nil)
;; Use encoding function or command.
(if (functionp loc-enc)
- (progn
- (tramp-message
- v 5 "Encoding region using function `%s'..." loc-enc)
+ (with-progress-reporter
+ v 3 (format "Encoding region using function `%s'"
+ loc-enc)
(let ((coding-system-for-read 'binary))
(insert-file-contents-literally tmpfile))
;; The following `let' is a workaround for the
(tramp-compat-temporary-file-directory)))
(funcall loc-enc (point-min) (point-max))))
- (tramp-message
- v 5 "Encoding region using command `%s'..." loc-enc)
- (unless (zerop (tramp-call-local-coding-command
- loc-enc tmpfile t))
- (tramp-error
- v 'file-error
- "Cannot write to `%s', local encoding command `%s' failed"
- filename loc-enc)))
+ (with-progress-reporter
+ v 3 (format "Encoding region using command `%s'"
+ loc-enc)
+ (unless (zerop (tramp-call-local-coding-command
+ loc-enc tmpfile t))
+ (tramp-error
+ v 'file-error
+ (concat "Cannot write to `%s', "
+ "local encoding command `%s' failed")
+ filename loc-enc))))
;; Send buffer into remote decoding command which
;; writes to remote file. Because this happens on
;; the remote host, we cannot use the function.
- (goto-char (point-max))
- (unless (bolp) (newline))
- (tramp-message
- v 5 "Decoding region into remote file %s..." filename)
- (tramp-send-command
- v
- (format
- (concat rem-dec " <<'EOF'\n%sEOF")
- (tramp-shell-quote-argument localname)
- (buffer-string)))
- (tramp-barf-unless-okay
- v nil
- "Couldn't write region to `%s', decode using `%s' failed"
- filename rem-dec)
- ;; When `file-precious-flag' is set, the region is
- ;; written to a temporary file. Check that the
- ;; checksum is equal to that from the local tmpfile.
- (when file-precious-flag
- (erase-buffer)
- (and
- ;; cksum runs locally, if possible.
- (zerop (tramp-local-call-process "cksum" tmpfile t))
- ;; cksum runs remotely.
- (zerop
- (tramp-send-command-and-check
- v
- (format
- "cksum <%s" (tramp-shell-quote-argument localname))))
- ;; ... they are different.
- (not
- (string-equal
- (buffer-string)
- (with-current-buffer (tramp-get-buffer v)
- (buffer-string))))
- (tramp-error
- v 'file-error
- (concat "Couldn't write region to `%s',"
- " decode using `%s' failed")
- filename rem-dec)))
- (tramp-message
- v 5 "Decoding region into remote file %s...done" filename))
+ (with-progress-reporter
+ v 3
+ (format "Decoding region into remote file %s" filename)
+ (goto-char (point-max))
+ (unless (bolp) (newline))
+ (tramp-send-command
+ v
+ (format
+ (concat rem-dec " <<'EOF'\n%sEOF")
+ (tramp-shell-quote-argument localname)
+ (buffer-string)))
+ (tramp-barf-unless-okay
+ v nil
+ "Couldn't write region to `%s', decode using `%s' failed"
+ filename rem-dec)
+ ;; When `file-precious-flag' is set, the region is
+ ;; written to a temporary file. Check that the
+ ;; checksum is equal to that from the local tmpfile.
+ (when file-precious-flag
+ (erase-buffer)
+ (and
+ ;; cksum runs locally, if possible.
+ (zerop (tramp-local-call-process "cksum" tmpfile t))
+ ;; cksum runs remotely.
+ (zerop
+ (tramp-send-command-and-check
+ v
+ (format
+ "cksum <%s"
+ (tramp-shell-quote-argument localname))))
+ ;; ... they are different.
+ (not
+ (string-equal
+ (buffer-string)
+ (with-current-buffer (tramp-get-buffer v)
+ (buffer-string))))
+ (tramp-error
+ v 'file-error
+ (concat "Couldn't write region to `%s',"
+ " decode using `%s' failed")
+ filename rem-dec)))))
;; Save exit.
(delete-file tmpfile)))
;; any other remote command.
(defun tramp-handle-vc-registered (file)
"Like `vc-registered' for Tramp files."
- (with-parsed-tramp-file-name file nil
-
- ;; There could be new files, created by the vc backend. We cannot
- ;; reuse the old cache entries, therefore.
- (let (tramp-vc-registered-file-names
- (tramp-cache-inhibit-cache (current-time))
- (file-name-handler-alist
- `((,tramp-file-name-regexp . tramp-vc-file-name-handler))))
-
- ;; Here we collect only file names, which need an operation.
- (tramp-run-real-handler 'vc-registered (list file))
- (tramp-message v 10 "\n%s" tramp-vc-registered-file-names)
-
- ;; Send just one command, in order to fill the cache.
- (when tramp-vc-registered-file-names
- (tramp-maybe-send-script
- v
- (format tramp-vc-registered-read-file-names
- (tramp-get-file-exists-command v)
- (format "%s -r" (tramp-get-test-command v)))
- "tramp_vc_registered_read_file_names")
-
- (dolist
- (elt
- (tramp-send-command-and-read
- v
- (format
- "tramp_vc_registered_read_file_names %s"
- (mapconcat 'tramp-shell-quote-argument
- tramp-vc-registered-file-names
- " "))))
-
- (tramp-set-file-property v (car elt) (cadr elt) (cadr (cdr elt))))))
-
- ;; Second run. Now all `file-exists-p' or `file-readable-p' calls
- ;; shall be answered from the file cache.
- ;; We unset `process-file-side-effects' in order to keep the cache
- ;; when `process-file' calls appear.
- (let (process-file-side-effects)
- (tramp-run-real-handler 'vc-registered (list file)))))
+ (with-temp-message ""
+ (with-parsed-tramp-file-name file nil
+ (with-progress-reporter
+ v 3 (format "Checking `vc-registered' for %s" file)
+
+ ;; There could be new files, created by the vc backend. We
+ ;; cannot reuse the old cache entries, therefore.
+ (let (tramp-vc-registered-file-names
+ (tramp-cache-inhibit-cache (current-time))
+ (file-name-handler-alist
+ `((,tramp-file-name-regexp . tramp-vc-file-name-handler))))
+
+ ;; Here we collect only file names, which need an operation.
+ (tramp-run-real-handler 'vc-registered (list file))
+ (tramp-message v 10 "\n%s" tramp-vc-registered-file-names)
+
+ ;; Send just one command, in order to fill the cache.
+ (when tramp-vc-registered-file-names
+ (tramp-maybe-send-script
+ v
+ (format tramp-vc-registered-read-file-names
+ (tramp-get-file-exists-command v)
+ (format "%s -r" (tramp-get-test-command v)))
+ "tramp_vc_registered_read_file_names")
+
+ (dolist
+ (elt
+ (tramp-send-command-and-read
+ v
+ (format
+ "tramp_vc_registered_read_file_names %s"
+ (mapconcat 'tramp-shell-quote-argument
+ tramp-vc-registered-file-names
+ " "))))
+
+ (tramp-set-file-property
+ v (car elt) (cadr elt) (cadr (cdr elt))))))
+
+ ;; Second run. Now all `file-exists-p' or `file-readable-p'
+ ;; calls shall be answered from the file cache. We unset
+ ;; `process-file-side-effects' in order to keep the cache when
+ ;; `process-file' calls appear.
+ (let (process-file-side-effects)
+ (tramp-run-real-handler 'vc-registered (list file)))))))
;;;###autoload
(progn (defun tramp-run-real-handler (operation args)
;; XEmacs only.
'dired-print-file 'dired-shell-call-process
;; nowhere yet.
- 'executable-find 'start-process 'call-process))
+ 'executable-find 'start-process
+ 'call-process 'call-process-region))
default-directory)
;; Unknown file primitive.
(t (error "unknown file I/O primitive: %s" operation))))
(if foreign
(condition-case err
(apply foreign operation args)
+
+ ;; Trace that somebody has interrupted the
+ ;; operation.
+ (quit
+ (let (tramp-message-show-message)
+ (tramp-message
+ v 1 "Interrupt received in operation %s"
+ (append (list operation) args)))
+ ;; Propagate the quit signal.
+ (signal (car err) (cdr err)))
+
+ ;; When we are in completion mode, some failed
+ ;; operations shall return at least a default value
+ ;; in order to give the user a chance to correct the
+ ;; file name in the minibuffer.
(error
(cond
- ;; When we are in completion mode, some failed
- ;; operations shall return at least a default
- ;; value in order to give the user a chance to
- ;; correct the file name in the minibuffer.
((and completion (zerop (length localname))
(memq operation '(file-exists-p file-directory-p)))
t)
filename)
;; Propagate the error.
(t (signal (car err) (cdr err))))))
+
;; Nothing to do for us.
(tramp-run-real-handler operation args)))))
(featurep 'tramp) ;; If it's loaded, we may as well use it.
;; `partial-completion-mode' does not exist in XEmacs.
;; It is obsoleted with Emacs 24.1.
- (and (boundp 'partial-completion-mode) partial-completion-mode)
+ (and (boundp 'partial-completion-mode)
+ (symbol-value 'partial-completion-mode))
;; FIXME: These may have been loaded even if the user never
;; intended to use them.
(featurep 'ido)
;; `last-input-event' might be nil.
(not (null last-input-event))
;; `last-input-event' may have no character approximation.
- (funcall (symbol-function 'event-to-character) last-input-event)
+ (tramp-compat-funcall 'event-to-character last-input-event)
(or
;; ?\t has event-modifier 'control.
(equal
- (funcall (symbol-function 'event-to-character)
- last-input-event) ?\t)
+ (tramp-compat-funcall 'event-to-character last-input-event) ?\t)
(and (not (event-modifiers last-input-event))
(or (equal
- (funcall (symbol-function 'event-to-character)
- last-input-event) ?\?)
+ (tramp-compat-funcall 'event-to-character last-input-event)
+ ?\?)
(equal
- (funcall (symbol-function 'event-to-character)
- last-input-event) ?\ )))))))
+ (tramp-compat-funcall 'event-to-character last-input-event)
+ ?\ )))))))
(defun tramp-connectable-p (filename)
"Check, whether it is possible to connect the remote host w/o side-effects.
(let* ((p (tramp-get-connection-process vec))
(scripts (tramp-get-connection-property p "scripts" nil)))
(unless (member name scripts)
- (tramp-message vec 5 "Sending script `%s'..." name)
- ;; The script could contain a call of Perl. This is masked with `%s'.
- (tramp-send-command-and-check
- vec
- (format "%s () {\n%s\n}" name
- (format script (tramp-get-remote-perl vec))))
- (tramp-set-connection-property p "scripts" (cons name scripts))
- (tramp-message vec 5 "Sending script `%s'...done." name))))
+ (with-progress-reporter vec 5 (format "Sending script `%s'" name)
+ ;; The script could contain a call of Perl. This is masked with `%s'.
+ (tramp-send-command-and-check
+ vec
+ (format "%s () {\n%s\n}" name
+ (format script (tramp-get-remote-perl vec))))
+ (tramp-set-connection-property p "scripts" (cons name scripts))))))
(defun tramp-set-auto-save ()
(when (and ;; ange-ftp has its own auto-save mechanism
(setq extra-args (cdr item))))
(when extra-args (setq shell (concat shell " " extra-args))))
(tramp-message
- vec 5 "Starting remote shell `%s' for tilde expansion..." shell)
+ vec 5 "Starting remote shell `%s' for tilde expansion" shell)
(let ((tramp-end-of-output tramp-initial-end-of-output))
(tramp-send-command
vec
(shell-quote-argument tramp-end-of-output) shell)
t))
;; Setting prompts.
- (tramp-message vec 5 "Setting remote shell prompt...")
- (tramp-send-command
- vec (format "PS1=%s" (shell-quote-argument tramp-end-of-output)) t)
- (tramp-send-command vec "PS2=''" t)
- (tramp-send-command vec "PS3=''" t)
- (tramp-send-command vec "PROMPT_COMMAND=''" t)
- (tramp-message vec 5 "Setting remote shell prompt...done"))
+ (with-progress-reporter vec 5 (format "Setting remote shell prompt")
+ (tramp-send-command
+ vec (format "PS1=%s" (shell-quote-argument tramp-end-of-output)) t)
+ (tramp-send-command vec "PS2=''" t)
+ (tramp-send-command vec "PS3=''" t)
+ (tramp-send-command vec "PROMPT_COMMAND=''" t)))
(t (tramp-message
vec 5 "Remote `%s' groks tilde expansion, good"
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-sh))
- (tramp-set-connection-property
- vec "remote-shell"
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-sh))))))))
+ (tramp-set-connection-property
+ vec "remote-shell"
+ (tramp-get-method-parameter
+ (tramp-file-name-method vec) 'tramp-remote-sh)))))))))
;; ------------------------------------------------------------
;; -- Functions for establishing connection --
(defun tramp-process-actions (proc vec actions &optional timeout)
"Perform actions until success or TIMEOUT."
- ;; Enable auth-source and password-cache.
- (tramp-set-connection-property vec "first-password-request" t)
- (let (exit)
- (while (not exit)
- (tramp-message proc 3 "Waiting for prompts from remote shell")
- (setq exit
- (catch 'tramp-action
- (if timeout
- (with-timeout (timeout)
- (tramp-process-one-action proc vec actions))
- (tramp-process-one-action proc vec actions)))))
- (with-current-buffer (tramp-get-connection-buffer vec)
- (tramp-message vec 6 "\n%s" (buffer-string)))
- (unless (eq exit 'ok)
- (tramp-clear-passwd vec)
- (tramp-error-with-buffer
- nil vec 'file-error
- (cond
- ((eq exit 'permission-denied) "Permission denied")
- ((eq exit 'process-died) "Process died")
- (t "Login failed"))))))
+ ;; Preserve message for `progress-reporter'.
+ (with-temp-message ""
+ ;; Enable auth-source and password-cache.
+ (tramp-set-connection-property vec "first-password-request" t)
+ (let (exit)
+ (while (not exit)
+ (tramp-message proc 3 "Waiting for prompts from remote shell")
+ (setq exit
+ (catch 'tramp-action
+ (if timeout
+ (with-timeout (timeout)
+ (tramp-process-one-action proc vec actions))
+ (tramp-process-one-action proc vec actions)))))
+ (with-current-buffer (tramp-get-connection-buffer vec)
+ (tramp-message vec 6 "\n%s" (buffer-string)))
+ (unless (eq exit 'ok)
+ (tramp-clear-passwd vec)
+ (tramp-error-with-buffer
+ nil vec 'file-error
+ (cond
+ ((eq exit 'permission-denied) "Permission denied")
+ ((eq exit 'process-died) "Process died")
+ (t "Login failed")))))))
;; Utility functions.
(when (or (not (tramp-get-connection-property proc "check-remote-echo" nil))
;; Sometimes, the echo string is suppressed on the remote side.
(not (string-equal
- (substring-no-properties
- tramp-echo-mark-marker
+ (tramp-compat-funcall
+ 'substring-no-properties tramp-echo-mark-marker
0 (min tramp-echo-mark-marker-length (1- (point-max))))
- (buffer-substring-no-properties
+ (tramp-compat-funcall
+ 'buffer-substring-no-properties
1 (min (1+ tramp-echo-mark-marker-length) (point-max))))))
;; No echo to be handled, now we can look for the regexp.
(goto-char (point-min))
(if (featurep 'mule)
;; Use MULE to select the right EOL convention for communicating
;; with the process.
- (let* ((cs (or (funcall (symbol-function 'process-coding-system) proc)
+ (let* ((cs (or (tramp-compat-funcall 'process-coding-system proc)
(cons 'undecided 'undecided)))
cs-decode cs-encode)
(when (symbolp cs) (setq cs (cons cs cs)))
(when (search-forward "\r" nil t)
(setq cs-decode (tramp-coding-system-change-eol-conversion
cs-decode 'dos)))
- (funcall (symbol-function 'set-buffer-process-coding-system)
- cs-decode cs-encode)
+ (tramp-compat-funcall
+ 'set-buffer-process-coding-system cs-decode cs-encode)
(tramp-message
vec 5 "Setting coding system to `%s' and `%s'" cs-decode cs-encode))
;; Look for ^M and do something useful if found.
;; Keep the debug buffer.
(rename-buffer
(generate-new-buffer-name tramp-temp-buffer-name) 'unique)
- (funcall (symbol-function 'tramp-cleanup-connection) vec)
+ (tramp-compat-funcall 'tramp-cleanup-connection vec)
(if (= (point-min) (point-max))
(kill-buffer nil)
(rename-buffer (tramp-debug-buffer-name vec) 'unique))
;; Disable unexpected output.
(tramp-send-command vec "mesg n; biff n" t)
+ ;; IRIX64 bash expands "!" even when in single quotes. This
+ ;; destroys our shell functions, we must disable it. See
+ ;; <http://stackoverflow.com/questions/3291692/irix-bash-shell-expands-expression-in-single-quotes-yet-shouldnt>.
+ (when (string-match "^IRIX64" (tramp-get-connection-property vec "uname" ""))
+ (tramp-send-command vec "set +H" t))
+
;; Set the environment.
(tramp-message vec 5 "Setting default environment")
(setq env (cdr env)))
(when unset
(tramp-send-command
- vec (format "unset %s" (mapconcat 'identity unset " "))))) t)
+ vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
;; CCC: We should either implement a Perl version of base64 encoding
;; and decoding. Then we just use that in the last item. The other
'target-alist
(vector
(tramp-file-name-method hop) (tramp-file-name-user hop)
- (funcall (symbol-function 'tramp-gw-open-connection) vec gw hop) nil))
+ (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil))
;; For the password prompt, we need the correct values.
;; Therefore, we must remember the gateway vector. But we
;; cannot do it as connection property, because it shouldn't
connection if a previous connection has died for some reason."
(catch 'uname-changed
(let ((p (tramp-get-connection-process vec))
+ (process-name (tramp-get-connection-property vec "process-name" nil))
(process-environment (copy-sequence process-environment)))
;; If too much time has passed since last command was sent, look
;; We call `tramp-get-buffer' in order to get a debug buffer for
;; messages from the beginning.
(tramp-get-buffer vec)
- (if (zerop (length (tramp-file-name-user vec)))
- (tramp-message
- vec 3 "Opening connection for %s using %s..."
- (tramp-file-name-host vec)
- (tramp-file-name-method vec))
- (tramp-message
- vec 3 "Opening connection for %s@%s using %s..."
- (tramp-file-name-user vec)
- (tramp-file-name-host vec)
- (tramp-file-name-method vec)))
-
- ;; Start new process.
- (when (and p (processp p))
- (delete-process p))
- (setenv "TERM" tramp-terminal-type)
- (setenv "LC_ALL" "C")
- (setenv "PROMPT_COMMAND")
- (setenv "PS1" tramp-initial-end-of-output)
- (let* ((target-alist (tramp-compute-multi-hops vec))
- (process-connection-type tramp-process-connection-type)
- (process-adaptive-read-buffering nil)
- (coding-system-for-read nil)
- ;; This must be done in order to avoid our file name handler.
- (p (let ((default-directory
- (tramp-compat-temporary-file-directory)))
- (start-process
- (or (tramp-get-connection-property vec "process-name" nil)
- (tramp-buffer-name vec))
- (tramp-get-connection-buffer vec)
- tramp-encoding-shell))))
+ (with-progress-reporter
+ vec 3
+ (if (zerop (length (tramp-file-name-user vec)))
+ (format "Opening connection for %s using %s"
+ (tramp-file-name-host vec)
+ (tramp-file-name-method vec))
+ (format "Opening connection for %s@%s using %s"
+ (tramp-file-name-user vec)
+ (tramp-file-name-host vec)
+ (tramp-file-name-method vec)))
+
+ ;; Start new process.
+ (when (and p (processp p))
+ (delete-process p))
+ (setenv "TERM" tramp-terminal-type)
+ (setenv "LC_ALL" "C")
+ (setenv "PROMPT_COMMAND")
+ (setenv "PS1" tramp-initial-end-of-output)
+ (let* ((target-alist (tramp-compute-multi-hops vec))
+ (process-connection-type tramp-process-connection-type)
+ (process-adaptive-read-buffering nil)
+ (coding-system-for-read nil)
+ ;; This must be done in order to avoid our file name handler.
+ (p (let ((default-directory
+ (tramp-compat-temporary-file-directory)))
+ (start-process
+ (or process-name (tramp-buffer-name vec))
+ (tramp-get-connection-buffer vec)
+ tramp-encoding-shell))))
- (tramp-message
- vec 6 "%s" (mapconcat 'identity (process-command p) " "))
+ (tramp-message
+ vec 6 "%s" (mapconcat 'identity (process-command p) " "))
- ;; Check whether process is alive.
- (tramp-set-process-query-on-exit-flag p nil)
- (with-progress-reporter vec 3 "Waiting 60s for local shell to come up"
+ ;; Check whether process is alive.
+ (tramp-set-process-query-on-exit-flag p nil)
(tramp-barf-if-no-shell-prompt
- p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell))
-
- ;; Now do all the connections as specified.
- (while target-alist
- (let* ((hop (car target-alist))
- (l-method (tramp-file-name-method hop))
- (l-user (tramp-file-name-user hop))
- (l-host (tramp-file-name-host hop))
- (l-port nil)
- (login-program
- (tramp-get-method-parameter l-method 'tramp-login-program))
- (login-args
- (tramp-get-method-parameter l-method 'tramp-login-args))
- (gw-args
- (tramp-get-method-parameter l-method 'tramp-gw-args))
- (gw (tramp-get-file-property hop "" "gateway" nil))
- (g-method (and gw (tramp-file-name-method gw)))
- (g-user (and gw (tramp-file-name-user gw)))
- (g-host (and gw (tramp-file-name-host gw)))
- (command login-program)
- ;; We don't create the temporary file. In fact, it
- ;; is just a prefix for the ControlPath option of
- ;; ssh; the real temporary file has another name, and
- ;; it is created and protected by ssh. It is also
- ;; removed by ssh, when the connection is closed.
- (tmpfile
- (tramp-set-connection-property
- p "temp-file"
- (make-temp-name
- (expand-file-name
- tramp-temp-name-prefix
- (tramp-compat-temporary-file-directory)))))
- spec)
-
- ;; Add gateway arguments if necessary.
- (when (and gw gw-args)
- (setq login-args (append login-args gw-args)))
-
- ;; Check for port number. Until now, there's no need
- ;; for handling like method, user, host.
- (when (string-match tramp-host-with-port-regexp l-host)
+ p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell)
+
+ ;; Now do all the connections as specified.
+ (while target-alist
+ (let* ((hop (car target-alist))
+ (l-method (tramp-file-name-method hop))
+ (l-user (tramp-file-name-user hop))
+ (l-host (tramp-file-name-host hop))
+ (l-port nil)
+ (login-program
+ (tramp-get-method-parameter
+ l-method 'tramp-login-program))
+ (login-args
+ (tramp-get-method-parameter l-method 'tramp-login-args))
+ (async-args
+ (tramp-get-method-parameter l-method 'tramp-async-args))
+ (gw-args
+ (tramp-get-method-parameter l-method 'tramp-gw-args))
+ (gw (tramp-get-file-property hop "" "gateway" nil))
+ (g-method (and gw (tramp-file-name-method gw)))
+ (g-user (and gw (tramp-file-name-user gw)))
+ (g-host (and gw (tramp-file-name-host gw)))
+ (command login-program)
+ ;; We don't create the temporary file. In fact,
+ ;; it is just a prefix for the ControlPath option
+ ;; of ssh; the real temporary file has another
+ ;; name, and it is created and protected by ssh.
+ ;; It is also removed by ssh, when the connection
+ ;; is closed.
+ (tmpfile
+ (tramp-set-connection-property
+ p "temp-file"
+ (make-temp-name
+ (expand-file-name
+ tramp-temp-name-prefix
+ (tramp-compat-temporary-file-directory)))))
+ spec)
+
+ ;; Add arguments for asynchrononous processes.
+ (when (and process-name async-args)
+ (setq login-args (append async-args login-args)))
+
+ ;; Add gateway arguments if necessary.
+ (when (and gw gw-args)
+ (setq login-args (append gw-args login-args)))
+
+ ;; Check for port number. Until now, there's no need
+ ;; for handling like method, user, host.
+ (when (string-match tramp-host-with-port-regexp l-host)
(setq l-port (match-string 2 l-host)
l-host (match-string 1 l-host)))
- ;; Set variables for computing the prompt for reading
- ;; password. They can also be derived from a gateway.
- (setq tramp-current-method (or g-method l-method)
- tramp-current-user (or g-user l-user)
- tramp-current-host (or g-host l-host))
-
- ;; Replace login-args place holders.
- (setq
- l-host (or l-host "")
- l-user (or l-user "")
- l-port (or l-port "")
- spec (format-spec-make ?h l-host ?u l-user ?p l-port ?t tmpfile)
- command
- (concat
- ;; We do not want to see the trailing local prompt in
- ;; `start-file-process'.
- (unless (memq system-type '(windows-nt)) "exec ")
- command " "
- (mapconcat
- (lambda (x)
- (setq x (mapcar (lambda (y) (format-spec y spec)) x))
- (unless (member "" x) (mapconcat 'identity x " ")))
- login-args " ")
- ;; Local shell could be a Windows COMSPEC. It doesn't
- ;; know the ";" syntax, but we must exit always for
- ;; `start-file-process'. "exec" does not work either.
- (if (memq system-type '(windows-nt)) " && exit || exit")))
-
- ;; Send the command.
- (tramp-message vec 3 "Sending command `%s'" command)
- (tramp-send-command vec command t t)
- (tramp-process-actions p vec tramp-actions-before-shell 60)
- (tramp-message vec 3 "Found remote shell prompt on `%s'" l-host))
- ;; Next hop.
- (setq target-alist (cdr target-alist)))
-
- ;; Make initial shell settings.
- (tramp-open-connection-setup-interactive-shell p vec))))))
+ ;; Set variables for computing the prompt for reading
+ ;; password. They can also be derived from a gateway.
+ (setq tramp-current-method (or g-method l-method)
+ tramp-current-user (or g-user l-user)
+ tramp-current-host (or g-host l-host))
+
+ ;; Replace login-args place holders.
+ (setq
+ l-host (or l-host "")
+ l-user (or l-user "")
+ l-port (or l-port "")
+ spec (format-spec-make
+ ?h l-host ?u l-user ?p l-port ?t tmpfile)
+ command
+ (concat
+ ;; We do not want to see the trailing local prompt in
+ ;; `start-file-process'.
+ (unless (memq system-type '(windows-nt)) "exec ")
+ command " "
+ (mapconcat
+ (lambda (x)
+ (setq x (mapcar (lambda (y) (format-spec y spec)) x))
+ (unless (member "" x) (mapconcat 'identity x " ")))
+ login-args " ")
+ ;; Local shell could be a Windows COMSPEC. It
+ ;; doesn't know the ";" syntax, but we must exit
+ ;; always for `start-file-process'. "exec" does not
+ ;; work either.
+ (if (memq system-type '(windows-nt)) " && exit || exit")))
+
+ ;; Send the command.
+ (tramp-message vec 3 "Sending command `%s'" command)
+ (tramp-send-command vec command t t)
+ (tramp-process-actions p vec tramp-actions-before-shell 60)
+ (tramp-message
+ vec 3 "Found remote shell prompt on `%s'" l-host))
+ ;; Next hop.
+ (setq target-alist (cdr target-alist)))
+
+ ;; Make initial shell settings.
+ (tramp-open-connection-setup-interactive-shell p vec)))))))
(defun tramp-send-command (vec command &optional neveropen nooutput)
"Send the COMMAND to connection VEC.
;; Check parameters. On busybox, "ls" output coloring is
;; enabled by default sometimes. So we try to disable it
;; when possible. $LS_COLORING is not supported there.
+ ;; Some "ls" versions are sensible wrt the order of
+ ;; arguments, they fail when "-al" is after the
+ ;; "--color=never" argument (for example on FreeBSD).
(when (zerop (tramp-send-command-and-check
vec (format "%s -lnd /" result)))
(when (zerop (tramp-send-command-and-check
- vec (format "%s --color=never /" result)))
+ vec (format "%s --color=never -al /" result)))
(setq result (concat result " --color=never")))
(throw 'ls-found result))
(setq dl (cdr dl))))))
(save-match-data
(with-connection-property vec "ls-dired"
(tramp-message vec 5 "Checking, whether `ls --dired' works")
+ ;; Some "ls" versions are sensible wrt the order of arguments,
+ ;; they fail when "-al" is after the "--dired" argument (for
+ ;; example on FreeBSD).
(zerop (tramp-send-command-and-check
- vec (format "%s --dired /" (tramp-get-ls-command vec)))))))
+ vec (format "%s --dired -al /" (tramp-get-ls-command vec)))))))
(defun tramp-get-test-command (vec)
(with-connection-property vec "test"
(error nil))))
result))))
+(defun tramp-get-remote-trash (vec)
+ (with-connection-property vec "trash"
+ (tramp-message vec 5 "Finding a suitable `trash' command")
+ (tramp-find-executable vec "trash" (tramp-get-remote-path vec))))
+
(defun tramp-get-remote-id (vec)
(with-connection-property vec "id"
(tramp-message vec 5 "Finding POSIX `id' command")
(and (boundp 'auth-sources)
(tramp-get-connection-property v "first-password-request" nil)
;; Try with Tramp's current method.
- (funcall (symbol-function 'auth-source-user-or-password)
- "password" tramp-current-host tramp-current-method))
+ (tramp-compat-funcall
+ 'auth-source-user-or-password
+ "password" tramp-current-host tramp-current-method))
;; Try the password cache.
(when (functionp 'password-read)
(unless (tramp-get-connection-property
v "first-password-request" nil)
- (funcall (symbol-function 'password-cache-remove) key))
+ (tramp-compat-funcall 'password-cache-remove key))
(let ((password
- (funcall (symbol-function 'password-read) pw-prompt key)))
- (funcall (symbol-function 'password-cache-add) key password)
+ (tramp-compat-funcall 'password-read pw-prompt key)))
+ (tramp-compat-funcall 'password-cache-add key password)
password))
;; Else, get the password interactively.
(read-passwd pw-prompt))
(defun tramp-clear-passwd (vec)
"Clear password cache for connection related to VEC."
- (when (functionp 'password-cache-remove)
- (funcall
- (symbol-function 'password-cache-remove)
- (tramp-make-tramp-file-name
- (tramp-file-name-method vec)
- (tramp-file-name-user vec)
- (tramp-file-name-host vec)
- ""))))
+ (tramp-compat-funcall
+ 'password-cache-remove
+ (tramp-make-tramp-file-name
+ (tramp-file-name-method vec)
+ (tramp-file-name-user vec)
+ (tramp-file-name-host vec)
+ "")))
;; Snarfed code from time-date.el and parse-time.el
;; Pacify byte-compiler with `symbol-function'.
(cond ((and (fboundp 'subtract-time)
(fboundp 'float-time))
- (funcall (symbol-function 'float-time)
- (funcall (symbol-function 'subtract-time) t1 t2)))
+ (tramp-compat-funcall
+ 'float-time (tramp-compat-funcall 'subtract-time t1 t2)))
((and (fboundp 'subtract-time)
(fboundp 'time-to-seconds))
- (funcall (symbol-function 'time-to-seconds)
- (funcall (symbol-function 'subtract-time) t1 t2)))
+ (tramp-compat-funcall
+ 'time-to-seconds (tramp-compat-funcall 'subtract-time t1 t2)))
((fboundp 'itimer-time-difference)
- (funcall (symbol-function 'itimer-time-difference)
- (if (< (length t1) 3) (append t1 '(0)) t1)
- (if (< (length t2) 3) (append t2 '(0)) t2)))
+ (tramp-compat-funcall
+ 'itimer-time-difference
+ (if (< (length t1) 3) (append t1 '(0)) t1)
+ (if (< (length t2) 3) (append t2 '(0)) t2)))
(t
(let ((time (tramp-time-subtract t1 t2)))
(+ (* (car time) 65536.0)
"Return a coding system like CODING-SYSTEM but with given EOL-TYPE.
EOL-TYPE can be one of `dos', `unix', or `mac'."
(cond ((fboundp 'coding-system-change-eol-conversion)
- (funcall (symbol-function 'coding-system-change-eol-conversion)
- coding-system eol-type))
+ (tramp-compat-funcall
+ 'coding-system-change-eol-conversion coding-system eol-type))
((fboundp 'subsidiary-coding-system)
- (funcall (symbol-function 'subsidiary-coding-system)
- coding-system
- (cond ((eq eol-type 'dos) 'crlf)
- ((eq eol-type 'unix) 'lf)
- ((eq eol-type 'mac) 'cr)
- (t
- (error "Unknown EOL-TYPE `%s', must be %s"
- eol-type
- "`dos', `unix', or `mac'")))))
+ (tramp-compat-funcall
+ 'subsidiary-coding-system coding-system
+ (cond ((eq eol-type 'dos) 'crlf)
+ ((eq eol-type 'unix) 'lf)
+ ((eq eol-type 'mac) 'cr)
+ (t
+ (error "Unknown EOL-TYPE `%s', must be %s"
+ eol-type
+ "`dos', `unix', or `mac'")))))
(t (error "Can't change EOL conversion -- is MULE missing?"))))
(defun tramp-set-process-query-on-exit-flag (process flag)
If the second argument flag is non-nil, Emacs will query the user before
exiting if process is running."
(if (fboundp 'set-process-query-on-exit-flag)
- (funcall (symbol-function 'set-process-query-on-exit-flag) process flag)
- (funcall (symbol-function 'process-kill-without-query) process flag)))
+ (tramp-compat-funcall 'set-process-query-on-exit-flag process flag)
+ (tramp-compat-funcall 'process-kill-without-query process flag)))
;; ------------------------------------------------------------
;; When Tramp is not loaded yet, its autoloads are still active.
(tramp-unload-file-name-handlers)
;; ange-ftp settings must be enabled.
- (when (functionp 'tramp-ftp-enable-ange-ftp)
- (funcall (symbol-function 'tramp-ftp-enable-ange-ftp)))
+ (tramp-compat-funcall 'tramp-ftp-enable-ange-ftp)
;; Maybe its not loaded yet.
(condition-case nil
(unload-feature 'tramp 'force)
;; by the files in that directory. Add this here.
;; * Avoid screen blanking when hitting `g' in dired. (Eli Tziperman)
;; * Make ffap.el grok Tramp filenames. (Eli Tziperman)
-;; * Case-insensitive filename completion. (Norbert Goevert.)
;; * Don't use globbing for directories with many files, as this is
;; likely to produce long command lines, and some shells choke on
;; long command lines.
;; rsync).
;; * Keep a second connection open for out-of-band methods like scp or
;; rsync.
-;; * Support ptys in `tramp-handle-start-file-process'. (Bug#4604)
+;; * Support ptys in `tramp-handle-start-file-process'. (Bug#4604, Bug#6360)
;; * IMHO, it's a drawback that currently Tramp doesn't support
;; Unicode in Dired file names by default. Is it possible to
;; improve Tramp to set LC_ALL to "C" only for commands where Tramp
;; without built-in uuencode/uudecode.
;; * Let `shell-dynamic-complete-*' and `comint-dynamic-complete' work
;; on remote hosts.
-;; * Use secrets.el for password handling.
;; * Load ~/.emacs_SHELLNAME on the remote host for `shell'.
;; Functions for file-name-handler-alist: