]> code.delx.au - gnu-emacs/blobdiff - lisp/net/tramp-sh.el
merge trunk
[gnu-emacs] / lisp / net / tramp-sh.el
index 1fa358e92778beeeb76d86c444f8facfe774a8f3..ec321d0050639342be52e2c0089b31444273a7dc 100644 (file)
@@ -1,6 +1,6 @@
 ;;; tramp-sh.el --- Tramp access functions for (s)sh-like connections
 
-;; Copyright (C) 1998-2011 Free Software Foundation, Inc.
+;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
 
 ;; (copyright statements below in code to be updated with the above notice)
 
 ;; `dired-insert-set-properties'.
 
 (defcustom tramp-inline-compress-start-size 4096
-  "*The minimum size of compressing where inline transfer.
-When inline transfer, compress transfered data of file
+  "The minimum size of compressing where inline transfer.
+When inline transfer, compress transferred data of file
 whose size is this value or above (up to `tramp-copy-size-limit').
 If it is nil, no compression at all will be applied."
   :group 'tramp
   :type '(choice (const nil) integer))
 
 (defcustom tramp-copy-size-limit 10240
-  "*The maximum file size where inline copying is preferred over an out-of-the-band copy.
-If it is nil, inline out-of-the-band copy will be used without a check."
+  "The maximum file size where inline copying is preferred over an \
+out-of-the-band copy.
+If it is nil, out-of-the-band copy will be used without a check."
   :group 'tramp
   :type '(choice (const nil) integer))
 
 ;;;###tramp-autoload
 (defcustom tramp-terminal-type "dumb"
-  "*Value of TERM environment variable for logging in to remote host.
+  "Value of TERM environment variable for logging in to remote host.
 Because Tramp wants to parse the output of the remote shell, it is easily
 confused by ANSI color escape sequences and suchlike.  Often, shell init
 files conditionalize this setup based on the TERM environment variable."
@@ -347,7 +348,6 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
     (tramp-remote-shell         "/bin/sh")
     (tramp-remote-shell-args    ("-c"))
-    (tramp-password-end-of-line "xy") ;see docstring for "xy"
     (tramp-default-port         22)))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
@@ -356,7 +356,6 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-login-args           (("-l" "%u") ("-P" "%p") ("-1" "-ssh") ("%h")))
     (tramp-remote-shell         "/bin/sh")
     (tramp-remote-shell-args    ("-c"))
-    (tramp-password-end-of-line "xy") ;see docstring for "xy"
     (tramp-default-port         22)))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
@@ -380,11 +379,10 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-remote-shell         "/bin/sh")
     (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "pscp")
-    (tramp-copy-args            (("-P" "%p") ("-scp") ("-p" "%k")
+    (tramp-copy-args            (("-l" "%u") ("-P" "%p") ("-scp") ("-p" "%k")
                                 ("-q") ("-r")))
     (tramp-copy-keep-date       t)
     (tramp-copy-recursive       t)
-    (tramp-password-end-of-line "xy") ;see docstring for "xy"
     (tramp-default-port         22)))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
@@ -394,11 +392,10 @@ detected as prompt when being sent on echoing hosts, therefore.")
     (tramp-remote-shell         "/bin/sh")
     (tramp-remote-shell-args    ("-c"))
     (tramp-copy-program         "pscp")
-    (tramp-copy-args            (("-P" "%p") ("-sftp") ("-p" "%k")
+    (tramp-copy-args            (("-l" "%u") ("-P" "%p") ("-sftp") ("-p" "%k")
                                 ("-q") ("-r")))
     (tramp-copy-keep-date       t)
-    (tramp-copy-recursive       t)
-    (tramp-password-end-of-line "xy"))) ;see docstring for "xy"
+    (tramp-copy-recursive       t)))
 ;;;###tramp-autoload
 (add-to-list 'tramp-methods
   '("fcp"
@@ -419,13 +416,12 @@ detected as prompt when being sent on echoing hosts, therefore.")
             `(,(concat "\\`" (regexp-opt '("su" "sudo" "ksu")) "\\'")
               nil "root"))
 ;; Do not add "ssh" based methods, otherwise ~/.ssh/config would be ignored.
+;; Do not add "plink" based methods, they ask interactively for the user.
 ;;;###tramp-autoload
 (add-to-list 'tramp-default-user-alist
             `(,(concat
                 "\\`"
-                (regexp-opt
-                 '("rcp" "remcp" "rsh" "telnet" "krlogin"
-                   "plink" "plink1" "pscp" "psftp" "fcp"))
+                (regexp-opt '("rcp" "remcp" "rsh" "telnet" "krlogin" "fcp"))
                 "\\'")
               nil ,(user-login-name)))
 
@@ -463,9 +459,11 @@ detected as prompt when being sent on echoing hosts, therefore.")
 
 ;;;###tramp-autoload
 (defconst tramp-completion-function-alist-putty
-  '((tramp-parse-putty
-     "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"))
-  "Default list of (FUNCTION REGISTRY) pairs to be examined for putty methods.")
+  `((tramp-parse-putty
+     ,(if (memq system-type '(windows-nt))
+         "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"
+       "~/.putty/sessions")))
+  "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.")
 
 ;;;###tramp-autoload
 (eval-after-load 'tramp
@@ -512,11 +510,13 @@ detected as prompt when being sent on echoing hosts, therefore.")
 ;; GNU/Linux (Debian, Suse): /bin:/usr/bin
 ;; FreeBSD: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
 ;; IRIX64: /usr/bin
+;;;###tramp-autoload
 (defcustom tramp-remote-path
-  '(tramp-default-remote-path "/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin"
-    "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
-    "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
-  "*List of directories to search for executables on remote host.
+  '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
+    "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
+    "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
+    "/opt/bin" "/opt/sbin" "/opt/local/bin")
+  "List of directories to search for executables on remote host.
 For every remote host, this variable will be set buffer local,
 keeping the list of existing directories on that host.
 
@@ -543,13 +543,12 @@ as given in your `~/.profile'."
     ,(format "TERM=%s" tramp-terminal-type)
     "EMACS=t" ;; Deprecated.
     ,(format "INSIDE_EMACS='%s,tramp:%s'" emacs-version tramp-version)
-    "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH="
+    "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=\"\""
     "autocorrect=" "correct=")
-
-  "*List of environment variables to be set on the remote host.
+  "List of environment variables to be set on the remote host.
 
 Each element should be a string of the form ENVVARNAME=VALUE.  An
-entry ENVVARNAME= diables the corresponding environment variable,
+entry ENVVARNAME= disables the corresponding environment variable,
 which might have been set in the init files like ~/.profile.
 
 Special handling is applied to the PATH environment, which should
@@ -558,7 +557,7 @@ not be set here. Instead, it should be set via `tramp-remote-path'."
   :type '(repeat string))
 
 (defcustom tramp-sh-extra-args '(("/bash\\'" . "-norc -noprofile"))
-  "*Alist specifying extra arguments to pass to the remote shell.
+  "Alist specifying extra arguments to pass to the remote shell.
 Entries are (REGEXP . ARGS) where REGEXP is a regular expression
 matching the shell file name and ARGS is a string specifying the
 arguments.
@@ -806,7 +805,7 @@ on the remote host.")
 (defconst tramp-perl-encode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002-2011 Free Software Foundation, Inc.
+# Copyright (C) 2002-2012 Free Software Foundation, Inc.
 use strict;
 
 my %%trans = do {
@@ -847,7 +846,7 @@ This string is passed to `format', so percent characters need to be doubled.")
 (defconst tramp-perl-decode
   "%s -e '
 # This script contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002-2011 Free Software Foundation, Inc.
+# Copyright (C) 2002-2012 Free Software Foundation, Inc.
 use strict;
 
 my %%trans = do {
@@ -1042,9 +1041,9 @@ target of the symlink differ."
       (tramp-flush-file-property l (file-name-directory l-localname))
       (tramp-flush-file-property l l-localname)
 
-      ;; Right, they are on the same host, regardless of user, method, etc.
-      ;; We now make the link on the remote machine. This will occur as the user
-      ;; that FILENAME belongs to.
+      ;; Right, they are on the same host, regardless of user, method,
+      ;; etc.  We now make the link on the remote machine. This will
+      ;; occur as the user that FILENAME belongs to.
       (tramp-send-command-and-check
        l
        (format
@@ -1058,113 +1057,117 @@ target of the symlink differ."
 (defun tramp-sh-handle-file-truename (filename &optional counter prev-dirs)
   "Like `file-truename' for Tramp files."
   (with-parsed-tramp-file-name (expand-file-name filename) nil
-    (with-file-property v localname "file-truename"
-      (let ((result nil))                      ; result steps in reverse order
-       (tramp-message v 4 "Finding true name for `%s'" filename)
-       (cond
-        ;; Use GNU readlink --canonicalize-missing where available.
-        ((tramp-get-remote-readlink v)
-         (setq result
-               (tramp-send-command-and-read
-                v
-                (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\""
-                        (tramp-get-remote-readlink v)
-                        (tramp-shell-quote-argument localname)))))
-
-        ;; Use Perl implementation.
-        ((and (tramp-get-remote-perl v)
-              (tramp-get-connection-property v "perl-file-spec" nil)
-              (tramp-get-connection-property v "perl-cwd-realpath" nil))
-         (tramp-maybe-send-script
-          v tramp-perl-file-truename "tramp_perl_file_truename")
-         (setq result
-               (tramp-send-command-and-read
-                v
-                (format "tramp_perl_file_truename %s"
-                        (tramp-shell-quote-argument localname)))))
-
-        ;; Do it yourself.  We bind `directory-sep-char' here for
-        ;; XEmacs on Windows, which would otherwise use backslash.
-        (t (let* ((directory-sep-char ?/)
-                  (steps (tramp-compat-split-string localname "/"))
-                  (localnamedir (tramp-run-real-handler
-                                 'file-name-as-directory (list localname)))
-                  (is-dir (string= localname localnamedir))
-                  (thisstep nil)
-                  (numchase 0)
-                  ;; Don't make the following value larger than
-                  ;; necessary.  People expect an error message in a
-                  ;; timely fashion when something is wrong;
-                  ;; otherwise they might think that Emacs is hung.
-                  ;; Of course, correctness has to come first.
-                  (numchase-limit 20)
-                  symlink-target)
-             (while (and steps (< numchase numchase-limit))
-               (setq thisstep (pop steps))
-               (tramp-message
-                v 5 "Check %s"
-                (mapconcat 'identity
-                           (append '("") (reverse result) (list thisstep))
-                           "/"))
-               (setq symlink-target
-                     (nth 0 (file-attributes
-                             (tramp-make-tramp-file-name
-                              method user host
-                              (mapconcat 'identity
-                                         (append '("")
-                                                 (reverse result)
-                                                 (list thisstep))
-                                         "/")))))
-               (cond ((string= "." thisstep)
-                      (tramp-message v 5 "Ignoring step `.'"))
-                     ((string= ".." thisstep)
-                      (tramp-message v 5 "Processing step `..'")
-                      (pop result))
-                     ((stringp symlink-target)
-                      ;; It's a symlink, follow it.
-                      (tramp-message v 5 "Follow symlink to %s" symlink-target)
-                      (setq numchase (1+ numchase))
-                      (when (file-name-absolute-p symlink-target)
-                        (setq result nil))
-                      ;; If the symlink was absolute, we'll get a string like
-                      ;; "/user@host:/some/target"; extract the
-                      ;; "/some/target" part from it.
-                      (when (tramp-tramp-file-p symlink-target)
-                        (unless (tramp-equal-remote filename symlink-target)
-                          (tramp-error
-                           v 'file-error
-                           "Symlink target `%s' on wrong host" symlink-target))
-                        (setq symlink-target localname))
-                      (setq steps
-                            (append (tramp-compat-split-string
-                                     symlink-target "/")
-                                    steps)))
-                     (t
-                      ;; It's a file.
-                      (setq result (cons thisstep result)))))
-             (when (>= numchase numchase-limit)
-               (tramp-error
-                v 'file-error
-                "Maximum number (%d) of symlinks exceeded" numchase-limit))
-             (setq result (reverse result))
-             ;; Combine list to form string.
-             (setq result
-                   (if result
-                       (mapconcat 'identity (cons "" result) "/")
-                     "/"))
-             (when (and is-dir (or (string= "" result)
-                                   (not (string= (substring result -1) "/"))))
-               (setq result (concat result "/"))))))
-
-        (tramp-message v 4 "True name of `%s' is `%s'" filename result)
-        (tramp-make-tramp-file-name method user host result)))))
+    (tramp-make-tramp-file-name method user host
+      (with-tramp-file-property v localname "file-truename"
+       (let ((result nil))                     ; result steps in reverse order
+         (tramp-message v 4 "Finding true name for `%s'" filename)
+         (cond
+          ;; Use GNU readlink --canonicalize-missing where available.
+          ((tramp-get-remote-readlink v)
+           (setq result
+                 (tramp-send-command-and-read
+                  v
+                  (format "echo \"\\\"`%s --canonicalize-missing %s`\\\"\""
+                          (tramp-get-remote-readlink v)
+                          (tramp-shell-quote-argument localname)))))
+
+          ;; Use Perl implementation.
+          ((and (tramp-get-remote-perl v)
+                (tramp-get-connection-property v "perl-file-spec" nil)
+                (tramp-get-connection-property v "perl-cwd-realpath" nil))
+           (tramp-maybe-send-script
+            v tramp-perl-file-truename "tramp_perl_file_truename")
+           (setq result
+                 (tramp-send-command-and-read
+                  v
+                  (format "tramp_perl_file_truename %s"
+                          (tramp-shell-quote-argument localname)))))
+
+          ;; Do it yourself.  We bind `directory-sep-char' here for
+          ;; XEmacs on Windows, which would otherwise use backslash.
+          (t (let* ((directory-sep-char ?/)
+                    (steps (tramp-compat-split-string localname "/"))
+                    (localnamedir (tramp-run-real-handler
+                                   'file-name-as-directory (list localname)))
+                    (is-dir (string= localname localnamedir))
+                    (thisstep nil)
+                    (numchase 0)
+                    ;; Don't make the following value larger than
+                    ;; necessary.  People expect an error message in
+                    ;; a timely fashion when something is wrong;
+                    ;; otherwise they might think that Emacs is hung.
+                    ;; Of course, correctness has to come first.
+                    (numchase-limit 20)
+                    symlink-target)
+               (while (and steps (< numchase numchase-limit))
+                 (setq thisstep (pop steps))
+                 (tramp-message
+                  v 5 "Check %s"
+                  (mapconcat 'identity
+                             (append '("") (reverse result) (list thisstep))
+                             "/"))
+                 (setq symlink-target
+                       (nth 0 (file-attributes
+                               (tramp-make-tramp-file-name
+                                method user host
+                                (mapconcat 'identity
+                                           (append '("")
+                                                   (reverse result)
+                                                   (list thisstep))
+                                           "/")))))
+                 (cond ((string= "." thisstep)
+                        (tramp-message v 5 "Ignoring step `.'"))
+                       ((string= ".." thisstep)
+                        (tramp-message v 5 "Processing step `..'")
+                        (pop result))
+                       ((stringp symlink-target)
+                        ;; It's a symlink, follow it.
+                        (tramp-message
+                         v 5 "Follow symlink to %s" symlink-target)
+                        (setq numchase (1+ numchase))
+                        (when (file-name-absolute-p symlink-target)
+                          (setq result nil))
+                        ;; If the symlink was absolute, we'll get a
+                        ;; string like "/user@host:/some/target";
+                        ;; extract the "/some/target" part from it.
+                        (when (tramp-tramp-file-p symlink-target)
+                          (unless (tramp-equal-remote filename symlink-target)
+                            (tramp-error
+                             v 'file-error
+                             "Symlink target `%s' on wrong host"
+                             symlink-target))
+                          (setq symlink-target localname))
+                        (setq steps
+                              (append (tramp-compat-split-string
+                                       symlink-target "/")
+                                      steps)))
+                       (t
+                        ;; It's a file.
+                        (setq result (cons thisstep result)))))
+               (when (>= numchase numchase-limit)
+                 (tramp-error
+                  v 'file-error
+                  "Maximum number (%d) of symlinks exceeded" numchase-limit))
+               (setq result (reverse result))
+               ;; Combine list to form string.
+               (setq result
+                     (if result
+                         (mapconcat 'identity (cons "" result) "/")
+                       "/"))
+               (when (and is-dir
+                          (or (string= "" result)
+                              (not (string= (substring result -1) "/"))))
+                 (setq result (concat result "/"))))))
+
+         (tramp-message v 4 "True name of `%s' is `%s'" localname result)
+         result)))))
 
 ;; Basic functions.
 
 (defun tramp-sh-handle-file-exists-p (filename)
   "Like `file-exists-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-exists-p"
+    (with-tramp-file-property v localname "file-exists-p"
       (or (not (null (tramp-get-file-property
                       v localname "file-attributes-integer" nil)))
           (not (null (tramp-get-file-property
@@ -1176,16 +1179,14 @@ target of the symlink differ."
            (tramp-get-file-exists-command v)
            (tramp-shell-quote-argument localname)))))))
 
-;; CCC: This should check for an error condition and signal failure
-;;      when something goes wrong.
-;; Daniel Pittman <daniel@danann.net>
 (defun tramp-sh-handle-file-attributes (filename &optional id-format)
   "Like `file-attributes' for Tramp files."
   (unless id-format (setq id-format 'integer))
   ;; Don't modify `last-coding-system-used' by accident.
   (let ((last-coding-system-used last-coding-system-used))
     (with-parsed-tramp-file-name (expand-file-name filename) nil
-      (with-file-property v localname (format "file-attributes-%s" id-format)
+      (with-tramp-file-property
+         v localname (format "file-attributes-%s" id-format)
        (save-excursion
          (tramp-convert-file-attributes
           v
@@ -1314,8 +1315,8 @@ target of the symlink differ."
     (tramp-get-test-command vec)
     (tramp-shell-quote-argument localname)
     (tramp-get-remote-stat vec)
-    (if (eq id-format 'integer) "%u" "\"%U\"")
-    (if (eq id-format 'integer) "%g" "\"%G\"")
+    (if (eq id-format 'integer) "%ue0" "\"%U\"")
+    (if (eq id-format 'integer) "%ge0" "\"%G\"")
     (tramp-shell-quote-argument localname))))
 
 (defun tramp-sh-handle-set-visited-file-modtime (&optional time-list)
@@ -1481,7 +1482,8 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 
 (defun tramp-remote-selinux-p (vec)
   "Check, whether SELINUX is enabled on the remote host."
-  (with-connection-property (tramp-get-connection-process vec) "selinux-p"
+  (with-tramp-connection-property
+      (tramp-get-connection-process vec) "selinux-p"
     (let ((result (tramp-find-executable
                   vec "getenforce" (tramp-get-remote-path vec) t t)))
       (and result
@@ -1493,7 +1495,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 (defun tramp-sh-handle-file-selinux-context (filename)
   "Like `file-selinux-context' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-selinux-context"
+    (with-tramp-file-property v localname "file-selinux-context"
       (let ((context '(nil nil nil nil))
            (regexp (concat "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\):"
                            "\\([a-z0-9_]+\\):" "\\([a-z0-9_]+\\)")))
@@ -1537,7 +1539,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 (defun tramp-sh-handle-file-executable-p (filename)
   "Like `file-executable-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-executable-p"
+    (with-tramp-file-property v localname "file-executable-p"
       ;; Examine `file-attributes' cache to see if request can be
       ;; satisfied without remote operation.
       (or (tramp-check-cached-permissions v ?x)
@@ -1546,7 +1548,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 (defun tramp-sh-handle-file-readable-p (filename)
   "Like `file-readable-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-readable-p"
+    (with-tramp-file-property v localname "file-readable-p"
       ;; Examine `file-attributes' cache to see if request can be
       ;; satisfied without remote operation.
       (or (tramp-check-cached-permissions v ?r)
@@ -1594,22 +1596,19 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 
 (defun tramp-sh-handle-file-directory-p (filename)
   "Like `file-directory-p' for Tramp files."
-  ;; Care must be taken that this function returns `t' for symlinks
-  ;; pointing to directories.  Surely the most obvious implementation
-  ;; would be `test -d', but that returns false for such symlinks.
-  ;; CCC: Stefan Monnier says that `test -d' follows symlinks.  And
-  ;; I now think he's right.  So we could be using `test -d', couldn't
-  ;; we?
-  ;;
-  ;; Alternatives: `cd %s', `test -d %s'
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-directory-p"
-      (tramp-run-test "-d" filename))))
+    ;; `file-directory-p' is used as predicate for filename completion.
+    ;; Sometimes, when a connection is not established yet, it is
+    ;; desirable to return t immediately for "/method:foo:".  It can
+    ;; be expected that this is always a directory.
+    (or (zerop (length localname))
+       (with-tramp-file-property v localname "file-directory-p"
+         (tramp-run-test "-d" filename)))))
 
 (defun tramp-sh-handle-file-writable-p (filename)
   "Like `file-writable-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-writable-p"
+    (with-tramp-file-property v localname "file-writable-p"
       (if (file-exists-p filename)
          ;; Examine `file-attributes' cache to see if request can be
          ;; satisfied without remote operation.
@@ -1622,7 +1621,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
 (defun tramp-sh-handle-file-ownership-preserved-p (filename)
   "Like `file-ownership-preserved-p' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    (with-file-property v localname "file-ownership-preserved-p"
+    (with-tramp-file-property v localname "file-ownership-preserved-p"
       (let ((attributes (file-attributes filename)))
        ;; Return t if the file doesn't exist, since it's true that no
        ;; information would be lost by an (attempted) delete and create.
@@ -1640,7 +1639,7 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
     (let* ((temp
            (copy-tree
             (with-parsed-tramp-file-name directory nil
-              (with-file-property
+              (with-tramp-file-property
                   v localname
                   (format "directory-files-and-attributes-%s" id-format)
                 (save-excursion
@@ -1695,14 +1694,15 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
      ;; "-"; this would confuse xargs.  "ls -aQ" might be a solution,
      ;; but it does not work on all remote systems.  Therefore, we
      ;; quote the filenames via sed.
-     "cd %s; echo \"(\"; (%s -a | sed -e s/\\$/\\\"/g -e s/^/\\\"/g | xargs "
-     "%s -c '(\"%%n\" (\"%%N\") %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 \"%%A\" t %%ie0 -1)'); "
-     "echo \")\"")
+     "cd %s; echo \"(\"; (%s -a | sed -e s/\\$/\\\"/g -e s/^/\\\"/g | "
+     "xargs %s -c "
+     "'(\"%%n\" (\"%%N\") %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 \"%%A\" t %%ie0 -1)'"
+     " 2>/dev/null); echo \")\"")
     (tramp-shell-quote-argument localname)
     (tramp-get-ls-command vec)
     (tramp-get-remote-stat vec)
-    (if (eq id-format 'integer) "%u" "\"%U\"")
-    (if (eq id-format 'integer) "%g" "\"%G\""))))
+    (if (eq id-format 'integer) "%ue0" "\"%U\"")
+    (if (eq id-format 'integer) "%ge0" "\"%G\""))))
 
 ;; This function should return "foo/" for directories and "bar" for
 ;; files.
@@ -1738,7 +1738,9 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
                        "file-name-all-completions"
                        nil)))
                  (when cache-hit (list cache-hit))))
-             (tramp-compat-number-sequence (length filename) 0 -1)))))
+             ;; We cannot use a length of 0, because file properties
+             ;; for "foo" and "foo/" are identical.
+             (tramp-compat-number-sequence (length filename) 1 -1)))))
 
          ;; Cache expired or no matching cache entry found so we need
          ;; to perform a remote operation.
@@ -1803,12 +1805,12 @@ and gid of the corresponding user is taken.  Both parameters must be integers."
            (with-current-buffer (tramp-get-buffer v)
              (goto-char (point-max))
 
-             ;; Check result code, found in last line of output
+             ;; Check result code, found in last line of output.
              (forward-line -1)
              (if (looking-at "^fail$")
                  (progn
                    ;; Grab error message from line before last line
-                   ;; (it was put there by `cd 2>&1')
+                   ;; (it was put there by `cd 2>&1').
                    (forward-line -1)
                    (tramp-error
                     v 'file-error
@@ -1829,9 +1831,8 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'"
                (push (buffer-substring (point) (point-at-eol)) result)))
 
            ;; Because the remote op went through OK we know the
-           ;; directory we `cd'-ed to exists
-           (tramp-set-file-property
-            v localname "file-exists-p" t)
+           ;; directory we `cd'-ed to exists.
+           (tramp-set-file-property v localname "file-exists-p" t)
 
            ;; Because the remote op went through OK we know every
            ;; file listed by `ls' exists.
@@ -1840,11 +1841,10 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'"
                    v (concat localname entry) "file-exists-p" t))
                 result)
 
-           ;; Store result in the cache
+           ;; Store result in the cache.
            (tramp-set-file-property
             v (concat localname filename)
-            "file-name-all-completions"
-            result))))))))
+           "file-name-all-completions" result))))))))
 
 ;; cp, mv and ln
 
@@ -1908,7 +1908,7 @@ tramp-sh-handle-file-name-all-completions: internal error accessing `%s': `%s'"
      'copy-file (list filename newname ok-if-already-exists keep-date)))))
 
 (defun tramp-sh-handle-copy-directory
-  (dirname newname &optional keep-date parents)
+  (dirname newname &optional keep-date parents copy-contents)
   "Like `copy-directory' for Tramp files."
   (let ((t1 (tramp-tramp-file-p dirname))
        (t2 (tramp-tramp-file-p newname)))
@@ -1989,7 +1989,7 @@ file names."
        (tramp-error
         v 'file-already-exists "File %s already exists" newname))
 
-      (tramp-with-progress-reporter
+      (with-tramp-progress-reporter
          v 0 (format "%s %s to %s"
                      (if (eq op 'copy) "Copying" "Renaming")
                      filename newname)
@@ -2279,8 +2279,10 @@ The method used must be an out-of-band method."
        ;; Set variables for computing the prompt for reading
        ;; password.
        (setq tramp-current-method (tramp-file-name-method v)
-             tramp-current-user   (tramp-file-name-user v)
-             tramp-current-host   (tramp-file-name-host v))
+             tramp-current-user (or (tramp-file-name-user v)
+                                    (tramp-get-connection-property
+                                     v "login-as" nil))
+             tramp-current-host (tramp-file-name-real-host v))
 
        ;; Expand hops.  Might be necessary for gateway methods.
        (setq v (car (tramp-compute-multi-hops v)))
@@ -2307,8 +2309,15 @@ The method used must be an out-of-band method."
          (setq port (string-to-number (match-string 2 host))
                host (string-to-number (match-string 1 host))))
 
+       ;; Check for user.  There might be an interactive setting.
+       (setq user (or (tramp-file-name-user v)
+                      (tramp-get-connection-property v "login-as" nil)))
+
        ;; Compose copy command.
-       (setq spec (format-spec-make
+       (setq host (or host "")
+             user (or user "")
+             port (or port "")
+             spec (format-spec-make
                    ?h host ?u user ?p port
                    ?t (tramp-get-connection-property
                        (tramp-get-connection-process v) "temp-file" "")
@@ -2384,7 +2393,7 @@ The method used must be an out-of-band method."
                   p v nil tramp-actions-copy-out-of-band)))
 
            ;; Reset the transfer process properties.
-           (tramp-message orig-vec 6 "%s" (buffer-string))
+           (tramp-message orig-vec 6 "\n%s" (buffer-string))
            (tramp-set-connection-property v "process-name" nil)
            (tramp-set-connection-property v "process-buffer" nil)))
 
@@ -2447,11 +2456,11 @@ The method used must be an out-of-band method."
   "Recursively delete the directory given.
 This is like `dired-recursive-delete-directory' for Tramp files."
   (with-parsed-tramp-file-name filename nil
-    ;; Run a shell command 'rm -r <localname>'
+    ;; Run a shell command 'rm -r <localname>'.
     ;; Code shamelessly stolen from the dired implementation and, um, hacked :)
     (unless (file-exists-p filename)
       (tramp-error v 'file-error "No such directory: %s" filename))
-    ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>)
+    ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>).
     (tramp-send-command
      v
      (format "rm -rf %s" (tramp-shell-quote-argument localname))
@@ -2498,7 +2507,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
               nil)
              ((and suffix (nth 2 suffix))
               ;; We found an uncompression rule.
-              (tramp-with-progress-reporter
+              (with-tramp-progress-reporter
                    v 0 (format "Uncompressing %s" file)
                 (when (tramp-send-command-and-check
                        v (concat (nth 2 suffix) " "
@@ -2510,7 +2519,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
              (t
               ;; We don't recognize the file as compressed, so compress it.
               ;; Try gzip.
-              (tramp-with-progress-reporter v 0 (format "Compressing %s" file)
+              (with-tramp-progress-reporter v 0 (format "Compressing %s" file)
                 (when (tramp-send-command-and-check
                        v (concat "gzip -f "
                                  (tramp-shell-quote-argument localname)))
@@ -2666,7 +2675,7 @@ the result will be a local, non-Tramp, filename."
                     (string-match "\\`su\\(do\\)?\\'" method))
            (setq uname (concat uname user)))
          (setq uname
-               (with-connection-property v uname
+               (with-tramp-connection-property v uname
                  (tramp-send-command
                   v (format "cd %s; pwd" (tramp-shell-quote-argument uname)))
                  (with-current-buffer (tramp-get-buffer v)
@@ -2689,7 +2698,8 @@ the result will be a local, non-Tramp, filename."
         method user host
         (tramp-drop-volume-letter
          (tramp-run-real-handler
-          'expand-file-name (list localname))))))))
+          'expand-file-name (list localname)))
+        hop)))))
 
 ;;; Remote commands:
 
@@ -2730,51 +2740,64 @@ the result will be a local, non-Tramp, filename."
          (bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
          (name1 name)
          (i 0))
-      (unwind-protect
-         (save-excursion
-           (save-restriction
-             (unless buffer
-               ;; BUFFER can be nil.  We use a temporary buffer.
-               (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
-             (while (get-process name1)
-               ;; NAME must be unique as process name.
-               (setq i (1+ i)
-                     name1 (format "%s<%d>" name i)))
-             (setq name name1)
-             ;; Set the new process properties.
-             (tramp-set-connection-property v "process-name" name)
-             (tramp-set-connection-property v "process-buffer" buffer)
-             ;; Activate narrowing in order to save BUFFER contents.
-             ;; Clear also the modification time; otherwise we might
-             ;; be interrupted by `verify-visited-file-modtime'.
-             (with-current-buffer (tramp-get-connection-buffer v)
-               (let ((buffer-undo-list t))
+
+      (unless buffer
+       ;; BUFFER can be nil.  We use a temporary buffer.
+       (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
+      (while (get-process name1)
+       ;; NAME must be unique as process name.
+       (setq i (1+ i)
+             name1 (format "%s<%d>" name i)))
+      (setq name name1)
+      ;; Set the new process properties.
+      (tramp-set-connection-property v "process-name" name)
+      (tramp-set-connection-property v "process-buffer" buffer)
+
+      (with-current-buffer (tramp-get-connection-buffer v)
+       (unwind-protect
+           (save-excursion
+             (save-restriction
+               ;; Activate narrowing in order to save BUFFER
+               ;; contents.  Clear also the modification time;
+               ;; otherwise we might be interrupted by
+               ;; `verify-visited-file-modtime'.
+               (let ((buffer-undo-list t)
+                     (buffer-read-only nil)
+                     (mark (point)))
                  (clear-visited-file-modtime)
                  (narrow-to-region (point-max) (point-max))
+                 ;; We call `tramp-maybe-open-connection', in order
+                 ;; to cleanup the prompt afterwards.
+                 (tramp-maybe-open-connection v)
+                 (widen)
+                 (delete-region mark (point))
+                 (narrow-to-region (point-max) (point-max))
+                 ;; Now do it.
                  (if command
                      ;; Send the command.
                      (tramp-send-command v command nil t) ; nooutput
                    ;; Check, whether a pty is associated.
-                   (tramp-maybe-open-connection v)
                    (unless (tramp-compat-process-get
                             (tramp-get-connection-process v) 'remote-tty)
                      (tramp-error
                       v 'file-error
-                      "pty association is not supported for `%s'" name)))))
-             (let ((p (tramp-get-connection-process v)))
-               ;; Set query flag for this process.
-               (tramp-compat-set-process-query-on-exit-flag p t)
-               ;; Return process.
-               p)))
-       ;; Save exit.
-       (with-current-buffer (tramp-get-connection-buffer v)
+                      "pty association is not supported for `%s'" name))))
+               (let ((p (tramp-get-connection-process v)))
+                 ;; Set query flag for this process.  We ignore errors,
+                 ;; because the process could have finished already.
+                 (ignore-errors
+                   (tramp-compat-set-process-query-on-exit-flag p t))
+                 ;; Return process.
+                 p)))
+
+         ;; Save exit.
          (if (string-match tramp-temp-buffer-name (buffer-name))
              (progn
                (set-process-buffer (tramp-get-connection-process v) nil)
                (kill-buffer (current-buffer)))
-           (set-buffer-modified-p bmp)))
-       (tramp-set-connection-property v "process-name" nil)
-       (tramp-set-connection-property v "process-buffer" nil)))))
+           (set-buffer-modified-p bmp))
+         (tramp-set-connection-property v "process-name" nil)
+         (tramp-set-connection-property v "process-buffer" nil))))))
 
 (defun tramp-sh-handle-process-file
   (program &optional infile destination display &rest args)
@@ -2922,7 +2945,7 @@ the result will be a local, non-Tramp, filename."
           ;; Use inline encoding for file transfer.
           (rem-enc
            (save-excursion
-             (tramp-with-progress-reporter
+             (with-tramp-progress-reporter
               v 3 (format "Encoding remote file %s" filename)
               (tramp-barf-unless-okay
                v (format rem-enc (tramp-shell-quote-argument localname))
@@ -2936,7 +2959,7 @@ the result will be a local, non-Tramp, filename."
                  (with-temp-buffer
                    (set-buffer-multibyte nil)
                    (insert-buffer-substring (tramp-get-buffer v))
-                   (tramp-with-progress-reporter
+                   (with-tramp-progress-reporter
                        v 3 (format "Decoding remote file %s with function %s"
                                    filename loc-dec)
                      (funcall loc-dec (point-min) (point-max))
@@ -2954,7 +2977,7 @@ the result will be a local, non-Tramp, filename."
                  (let (file-name-handler-alist
                        (coding-system-for-write 'binary))
                    (write-region (point-min) (point-max) tmpfile2))
-                 (tramp-with-progress-reporter
+                 (with-tramp-progress-reporter
                      v 3 (format "Decoding remote file %s with command %s"
                                  filename loc-dec)
                    (unwind-protect
@@ -3083,22 +3106,25 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
           'write-region
           (list start end localname append 'no-message lockname confirm))
 
-       (let ((modes (save-excursion (tramp-default-file-modes filename)))
-             ;; We use this to save the value of
-             ;; `last-coding-system-used' after writing the tmp
-             ;; file.  At the end of the function, we set
-             ;; `last-coding-system-used' to this saved value.  This
-             ;; way, any intermediary coding systems used while
-             ;; talking to the remote shell or suchlike won't hose
-             ;; this variable.  This approach was snarfed from
-             ;; ange-ftp.el.
-             coding-system-used
-             ;; Write region into a tmp file.  This isn't really
-             ;; needed if we use an encoding function, but currently
-             ;; we use it always because this makes the logic
-             ;; simpler.
-             (tmpfile (or tramp-temp-buffer-file-name
-                          (tramp-compat-make-temp-file filename))))
+       (let* ((modes (save-excursion (tramp-default-file-modes filename)))
+              ;; We use this to save the value of
+              ;; `last-coding-system-used' after writing the tmp
+              ;; file.  At the end of the function, we set
+              ;; `last-coding-system-used' to this saved value.  This
+              ;; way, any intermediary coding systems used while
+              ;; talking to the remote shell or suchlike won't hose
+              ;; this variable.  This approach was snarfed from
+              ;; ange-ftp.el.
+              coding-system-used
+              ;; Write region into a tmp file.  This isn't really
+              ;; needed if we use an encoding function, but currently
+              ;; we use it always because this makes the logic
+              ;; simpler.  We must also set `temporary-file-directory',
+              ;; because it could point to a remote directory.
+              (temporary-file-directory
+               (tramp-compat-temporary-file-directory))
+              (tmpfile (or tramp-temp-buffer-file-name
+                           (tramp-compat-make-temp-file filename))))
 
          ;; If `append' is non-nil, we copy the file locally, and let
          ;; the native `write-region' implementation do the job.
@@ -3179,7 +3205,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                    (set-buffer-multibyte nil)
                    ;; Use encoding function or command.
                    (if (functionp loc-enc)
-                       (tramp-with-progress-reporter
+                       (with-tramp-progress-reporter
                            v 3 (format "Encoding region using function `%s'"
                                        loc-enc)
                          (let ((coding-system-for-read 'binary))
@@ -3197,7 +3223,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                                  (tramp-compat-temporary-file-directory)))
                            (funcall loc-enc (point-min) (point-max))))
 
-                     (tramp-with-progress-reporter
+                     (with-tramp-progress-reporter
                          v 3 (format "Encoding region using command `%s'"
                                      loc-enc)
                        (unless (zerop (tramp-call-local-coding-command
@@ -3211,7 +3237,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
                    ;; Send buffer into remote decoding command which
                    ;; writes to remote file.  Because this happens on
                    ;; the remote host, we cannot use the function.
-                   (tramp-with-progress-reporter
+                   (with-tramp-progress-reporter
                        v 3
                        (format "Decoding region into remote file %s" filename)
                      (goto-char (point-max))
@@ -3274,14 +3300,14 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
       (let (last-coding-system-used (need-chown t))
        ;; Set file modification time.
        (when (or (eq visit t) (stringp visit))
-          (let ((file-attr (file-attributes filename)))
+          (let ((file-attr (tramp-compat-file-attributes filename 'integer)))
             (set-visited-file-modtime
              ;; We must pass modtime explicitly, because filename can
              ;; be different from (buffer-file-name), f.e. if
              ;; `file-precious-flag' is set.
              (nth 5 file-attr))
-            (when (and (eq (nth 2 file-attr) uid)
-                       (eq (nth 3 file-attr) gid))
+            (when (and (= (nth 2 file-attr) uid)
+                       (= (nth 3 file-attr) gid))
               (setq need-chown nil))))
 
        ;; Set the ownership.
@@ -3311,7 +3337,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
   "Like `vc-registered' for Tramp files."
   (tramp-compat-with-temp-message ""
     (with-parsed-tramp-file-name file nil
-      (tramp-with-progress-reporter
+      (with-tramp-progress-reporter
          v 3 (format "Checking `vc-registered' for %s" file)
 
        ;; There could be new files, created by the vc backend.  We
@@ -3322,7 +3348,7 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
               `((,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))
+         (ignore-errors (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.
@@ -3390,10 +3416,12 @@ Fall back to normal file name handler if no Tramp handler exists."
         ((and fn (memq operation '(file-exists-p file-readable-p)))
          (add-to-list 'tramp-vc-registered-file-names localname 'append)
          nil)
+        ;; `process-file' and `start-file-process' shall be ignored.
+        ((and fn (eq operation 'process-file) 0))
+        ((and fn (eq operation 'start-file-process) nil))
         ;; Tramp file name handlers like `expand-file-name'.  They
         ;; must still work.
-        (fn
-         (save-match-data (apply (cdr fn) args)))
+        (fn (save-match-data (apply (cdr fn) args)))
         ;; Default file name handlers, we don't care.
         (t (tramp-run-real-handler operation args)))))))
 
@@ -3407,7 +3435,7 @@ Only send the definition if it has not already been done."
   (let ((scripts (tramp-get-connection-property
                  (tramp-get-connection-process vec) "scripts" nil)))
     (unless (member name scripts)
-      (tramp-with-progress-reporter vec 5 (format "Sending script `%s'" name)
+      (with-tramp-progress-reporter vec 5 (format "Sending script `%s'" name)
        ;; The script could contain a call of Perl.  This is masked with `%s'.
        (tramp-barf-unless-okay
         vec
@@ -3525,7 +3553,7 @@ variable PATH."
 Here, we are looking for a command which has zero exit status if the
 file exists and nonzero exit status otherwise."
   (let ((existing "/")
-        (nonexisting
+        (nonexistent
         (tramp-shell-quote-argument "/ this file does not exist "))
        result)
     ;; The algorithm is as follows: we try a list of several commands.
@@ -3546,33 +3574,37 @@ file exists and nonzero exit status otherwise."
     ;;                    `/usr/bin/test'.
     ;; `/usr/bin/test -e' In case `/bin/test' does not exist.
     (unless (or
-             (and (setq result (format "%s -e" (tramp-get-test-command vec)))
-                 (tramp-send-command-and-check
-                  vec (format "%s %s" result existing))
-                  (not (tramp-send-command-and-check
-                       vec (format "%s %s" result nonexisting))))
-             (and (setq result "/bin/test -e")
-                 (tramp-send-command-and-check
-                  vec (format "%s %s" result existing))
-                  (not (tramp-send-command-and-check
-                       vec (format "%s %s" result nonexisting))))
-             (and (setq result "/usr/bin/test -e")
-                 (tramp-send-command-and-check
-                  vec (format "%s %s" result existing))
-                  (not (tramp-send-command-and-check
-                       vec (format "%s %s" result nonexisting))))
-             (and (setq result (format "%s -d" (tramp-get-ls-command vec)))
-                 (tramp-send-command-and-check
-                  vec (format "%s %s" result existing))
-                  (not (tramp-send-command-and-check
-                       vec (format "%s %s" result nonexisting)))))
+            (ignore-errors
+              (and (setq result (format "%s -e" (tramp-get-test-command vec)))
+                   (tramp-send-command-and-check
+                    vec (format "%s %s" result existing))
+                   (not (tramp-send-command-and-check
+                         vec (format "%s %s" result nonexistent)))))
+            (ignore-errors
+              (and (setq result "/bin/test -e")
+                   (tramp-send-command-and-check
+                    vec (format "%s %s" result existing))
+                   (not (tramp-send-command-and-check
+                         vec (format "%s %s" result nonexistent)))))
+            (ignore-errors
+              (and (setq result "/usr/bin/test -e")
+                   (tramp-send-command-and-check
+                    vec (format "%s %s" result existing))
+                   (not (tramp-send-command-and-check
+                         vec (format "%s %s" result nonexistent)))))
+            (ignore-errors
+              (and (setq result (format "%s -d" (tramp-get-ls-command vec)))
+                   (tramp-send-command-and-check
+                    vec (format "%s %s" result existing))
+                   (not (tramp-send-command-and-check
+                         vec (format "%s %s" result nonexistent))))))
       (tramp-error
        vec 'file-error "Couldn't find command to check if file exists"))
     result))
 
 (defun tramp-open-shell (vec shell)
   "Opens shell SHELL."
-  (tramp-with-progress-reporter
+  (with-tramp-progress-reporter
       vec 5 (format "Opening remote shell `%s'" shell)
     ;; Find arguments for this shell.
     (let ((tramp-end-of-output tramp-initial-end-of-output)
@@ -3582,11 +3614,14 @@ file exists and nonzero exit status otherwise."
        (setq item (pop alist))
        (when (string-match (car item) shell)
          (setq extra-args (cdr item))))
-      (when extra-args (setq shell (concat shell " " extra-args)))
       (tramp-send-command
-       vec (format "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s"
-                  (tramp-shell-quote-argument tramp-end-of-output) shell)
+       vec (format
+           "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s %s"
+           (tramp-shell-quote-argument tramp-end-of-output)
+           shell (or extra-args ""))
        t))
+    (tramp-set-connection-property
+     (tramp-get-connection-process vec) "remote-shell" shell)
     ;; Setting prompts.
     (tramp-send-command
      vec (format "PS1=%s" (tramp-shell-quote-argument tramp-end-of-output)) t)
@@ -3596,36 +3631,54 @@ file exists and nonzero exit status otherwise."
 
 (defun tramp-find-shell (vec)
   "Opens a shell on the remote host which groks tilde expansion."
-  (unless (tramp-get-connection-property vec "remote-shell" nil)
-    (let (shell)
-      (with-current-buffer (tramp-get-buffer vec)
-       (tramp-send-command vec "echo ~root" t)
-       (cond
-        ((or (string-match "^~root$" (buffer-string))
-             ;; The default shell (ksh93) of OpenSolaris and Solaris
-             ;; is buggy.  We've got reports for "SunOS 5.10" and
-             ;; "SunOS 5.11" so far.
-             (string-match (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
-                           (tramp-get-connection-property vec "uname" "")))
-         (setq shell
-               (or (tramp-find-executable
-                    vec "bash" (tramp-get-remote-path vec) t t)
-                   (tramp-find-executable
-                    vec "ksh" (tramp-get-remote-path vec) t t)))
-         (unless shell
-           (tramp-error
-            vec 'file-error
-            "Couldn't find a shell which groks tilde expansion"))
-         (tramp-message
-          vec 5 "Starting remote shell `%s' for tilde expansion" shell)
-         (tramp-open-shell vec shell))
+  (with-current-buffer (tramp-get-buffer vec)
+    (let ((default-shell
+           (or
+            (tramp-get-connection-property
+             (tramp-get-connection-process vec) "remote-shell" nil)
+            (tramp-get-method-parameter
+             (tramp-file-name-method vec) 'tramp-remote-shell)))
+         shell)
+      (setq shell
+           (with-tramp-connection-property vec "remote-shell"
+             ;; CCC: "root" does not exist always, see QNAP 459.
+             ;; Which check could we apply instead?
+             (tramp-send-command vec "echo ~root" t)
+             (if (or (string-match "^~root$" (buffer-string))
+                     ;; The default shell (ksh93) of OpenSolaris and
+                     ;; Solaris is buggy.  We've got reports for
+                     ;; "SunOS 5.10" and "SunOS 5.11" so far.
+                     (string-match (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
+                                   (tramp-get-connection-property
+                                    vec "uname" "")))
+
+                 (or (tramp-find-executable
+                      vec "bash" (tramp-get-remote-path vec) t t)
+                     (tramp-find-executable
+                      vec "ksh" (tramp-get-remote-path vec) t t)
+                     ;; Maybe it works at least for some other commands.
+                     (prog1
+                         default-shell
+                       (tramp-message
+                        vec 2
+                        (concat
+                         "Couldn't find a remote shell which groks tilde "
+                         "expansion, using `%s'")
+                        default-shell)))
+
+               default-shell)))
+
+      ;; Open a new shell if needed.
+      (unless (string-equal shell default-shell)
+       (tramp-message
+        vec 5 "Starting remote shell `%s' for tilde expansion" shell)
+       (tramp-open-shell vec shell))
 
-        (t (tramp-message
-            vec 5 "Remote `%s' groks tilde expansion, good"
-            (tramp-set-connection-property
-             vec "remote-shell"
-             (tramp-get-method-parameter
-              (tramp-file-name-method vec) 'tramp-remote-shell)))))))))
+      ;; Busyboxes tend to behave strange.  We check for the existence.
+      (with-tramp-connection-property vec "busybox"
+       (tramp-send-command vec (format "%s --version" shell) t)
+       (let ((case-fold-search t))
+         (and (string-match "busybox" (buffer-string)) t))))))
 
 ;; Utility functions.
 
@@ -3661,8 +3714,9 @@ process to set up.  VEC specifies the connection."
     ;; discarded as well.
     (tramp-open-shell
      vec
-     (tramp-get-method-parameter
-      (tramp-file-name-method vec) 'tramp-remote-shell))
+     (or (tramp-get-connection-property vec "remote-shell" nil)
+        (tramp-get-method-parameter
+         (tramp-file-name-method vec) 'tramp-remote-shell)))
 
     ;; Disable echo.
     (tramp-message vec 5 "Setting up remote shell environment")
@@ -3725,7 +3779,7 @@ process to set up.  VEC specifies the connection."
   ;; Check whether the output of "uname -sr" has been changed.  If
   ;; yes, this is a strong indication that we must expire all
   ;; connection properties.  We start again with
-  ;; `tramp-maybe-open-connection', it will be catched there.
+  ;; `tramp-maybe-open-connection', it will be caught there.
   (tramp-message vec 5 "Checking system information")
   (let ((old-uname (tramp-get-connection-property vec "uname" nil))
        (new-uname
@@ -3733,21 +3787,12 @@ process to set up.  VEC specifies the connection."
          vec "uname"
          (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\""))))
     (when (and (stringp old-uname) (not (string-equal old-uname new-uname)))
-      (with-current-buffer (tramp-get-debug-buffer vec)
-       ;; Keep the debug buffer.
-       (rename-buffer
-        (generate-new-buffer-name tramp-temp-buffer-name) 'unique)
-       (tramp-cleanup-connection vec)
-       (if (= (point-min) (point-max))
-           (kill-buffer nil)
-         (rename-buffer (tramp-debug-buffer-name vec) 'unique))
-       ;; We call `tramp-get-buffer' in order to keep the debug buffer.
-       (tramp-get-buffer vec)
-       (tramp-message
-        vec 3
-        "Connection reset, because remote host changed from `%s' to `%s'"
-        old-uname new-uname)
-       (throw 'uname-changed (tramp-maybe-open-connection vec)))))
+      (tramp-cleanup vec)
+      (tramp-message
+       vec 3
+       "Connection reset, because remote host changed from `%s' to `%s'"
+       old-uname new-uname)
+      (throw 'uname-changed (tramp-maybe-open-connection vec))))
 
   ;; Check whether the remote host suffers from buggy
   ;; `send-process-string'.  This is known for FreeBSD (see comment in
@@ -3755,7 +3800,7 @@ process to set up.  VEC specifies the connection."
   ;; successfully, sending 625 bytes failed.  Emacs makes a hack when
   ;; this host type is detected locally.  It cannot handle remote
   ;; hosts, though.
-  (with-connection-property proc "chunksize"
+  (with-tramp-connection-property proc "chunksize"
     (cond
      ((and (integerp tramp-chunksize) (> tramp-chunksize 0))
       tramp-chunksize)
@@ -3770,7 +3815,7 @@ process to set up.  VEC specifies the connection."
   (tramp-set-remote-path vec)
 
   ;; Search for a good shell before searching for a command which
-  ;; checks if a file exists. This is done because Tramp wants to use
+  ;; checks if a file exists.  This is done because Tramp wants to use
   ;; "test foo; echo $?" to check if various conditions hold, and
   ;; there are buggy /bin/sh implementations which don't execute the
   ;; "echo $?"  part if the "test" part has an error.  In particular,
@@ -3877,7 +3922,7 @@ with the encoded or decoded results, respectively.")
     (b64 "recode data..base64" "recode base64..data")
     (b64 tramp-perl-encode-with-module tramp-perl-decode-with-module)
     (b64 tramp-perl-encode tramp-perl-decode)
-    (uu  "uuencode xxx" "uudecode -o /dev/stdout")
+    (uu  "uuencode xxx" "uudecode -o /dev/stdout" "test -c /dev/stdout")
     (uu  "uuencode xxx" "uudecode -o -")
     (uu  "uuencode xxx" "uudecode -p")
     (uu  "uuencode xxx" tramp-uudecode)
@@ -3887,7 +3932,7 @@ with the encoded or decoded results, respectively.")
   "List of remote coding commands for inline transfer.
 Each item is a list that looks like this:
 
-\(FORMAT ENCODING DECODING\)
+\(FORMAT ENCODING DECODING [TEST]\)
 
 FORMAT is  symbol describing the encoding/decoding format.  It can be
 `b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
@@ -3901,7 +3946,10 @@ input.
 
 If they are variables, this variable is a string containing a Perl
 implementation for this functionality.  This Perl program will be transferred
-to the remote host, and it is available as shell function with the same name.")
+to the remote host, and it is available as shell function with the same name.
+
+The optional TEST command can be used for further tests, whether
+ENCODING and DECODING are applicable.")
 
 (defun tramp-find-inline-encoding (vec)
   "Find an inline transfer encoding that works.
@@ -3910,7 +3958,8 @@ Goes through the list `tramp-local-coding-commands' and
   (save-excursion
     (let ((local-commands tramp-local-coding-commands)
          (magic "xyzzy")
-         loc-enc loc-dec rem-enc rem-dec litem ritem found)
+         (p (tramp-get-connection-process vec))
+         loc-enc loc-dec rem-enc rem-dec rem-test litem ritem found)
       (while (and local-commands (not found))
        (setq litem (pop local-commands))
        (catch 'wont-work-local
@@ -3943,6 +3992,13 @@ Goes through the list `tramp-local-coding-commands' and
                (when (equal format (nth 0 ritem))
                  (setq rem-enc (nth 1 ritem))
                  (setq rem-dec (nth 2 ritem))
+                 (setq rem-test (nth 3 ritem))
+                 ;; Check the remote test command if exists.
+                 (when (stringp rem-test)
+                   (tramp-message
+                    vec 5 "Checking remote test command `%s'" rem-test)
+                   (unless (tramp-send-command-and-check vec rem-test t)
+                     (throw 'wont-work-remote nil)))
                  ;; Check if remote encoding and decoding commands can be
                  ;; called remotely with null input and output.  This makes
                  ;; sure there are no syntax errors and the command is really
@@ -3994,15 +4050,16 @@ Goes through the list `tramp-local-coding-commands' and
        (tramp-error
         vec 'file-error "Couldn't find an inline transfer encoding"))
 
-      ;; Set connection properties.
+      ;; Set connection properties.  Since the commands are risky (due
+      ;; to output direction), we cache them in the process cache.
       (tramp-message vec 5 "Using local encoding `%s'" loc-enc)
-      (tramp-set-connection-property vec "local-encoding" loc-enc)
+      (tramp-set-connection-property p "local-encoding" loc-enc)
       (tramp-message vec 5 "Using local decoding `%s'" loc-dec)
-      (tramp-set-connection-property vec "local-decoding" loc-dec)
+      (tramp-set-connection-property p "local-decoding" loc-dec)
       (tramp-message vec 5 "Using remote encoding `%s'" rem-enc)
-      (tramp-set-connection-property vec "remote-encoding" rem-enc)
+      (tramp-set-connection-property p "remote-encoding" rem-enc)
       (tramp-message vec 5 "Using remote decoding `%s'" rem-dec)
-      (tramp-set-connection-property vec "remote-decoding" rem-dec))))
+      (tramp-set-connection-property p "remote-decoding" rem-dec))))
 
 (defun tramp-call-local-coding-command (cmd input output)
   "Call the local encoding or decoding command.
@@ -4025,6 +4082,7 @@ means discard it)."
 (defconst tramp-inline-compress-commands
   '(("gzip" "gzip -d")
     ("bzip2" "bzip2 -d")
+    ("xz" "xz -d")
     ("compress" "compress -d"))
   "List of compress and decompress commands for inline transfer.
 Each item is a list that looks like this:
@@ -4039,8 +4097,8 @@ Goes through the list `tramp-inline-compress-commands'."
   (save-excursion
     (let ((commands tramp-inline-compress-commands)
          (magic "xyzzy")
-         item compress decompress
-         found)
+         (p (tramp-get-connection-process vec))
+         item compress decompress found)
       (while (and commands (not found))
        (catch 'next
          (setq item (pop commands)
@@ -4074,16 +4132,18 @@ Goes through the list `tramp-inline-compress-commands'."
       ;; Did we find something?
       (if found
          (progn
-           ;; Set connection properties.
+           ;; Set connection properties.  Since the commands are
+           ;; risky (due to output direction), we cache them in the
+           ;; process cache.
            (tramp-message
             vec 5 "Using inline transfer compress command `%s'" compress)
-           (tramp-set-connection-property vec "inline-compress" compress)
+           (tramp-set-connection-property p "inline-compress" compress)
            (tramp-message
             vec 5 "Using inline transfer decompress command `%s'" decompress)
-           (tramp-set-connection-property vec "inline-decompress" decompress))
+           (tramp-set-connection-property p "inline-decompress" decompress))
 
-       (tramp-set-connection-property vec "inline-compress" nil)
-       (tramp-set-connection-property vec "inline-decompress" nil)
+       (tramp-set-connection-property p "inline-compress" nil)
+       (tramp-set-connection-property p "inline-decompress" nil)
        (tramp-message
         vec 2 "Couldn't find an inline transfer compress command")))))
 
@@ -4091,18 +4151,43 @@ Goes through the list `tramp-inline-compress-commands'."
   "Expands VEC according to `tramp-default-proxies-alist'.
 Gateway hops are already opened."
   (let ((target-alist `(,vec))
-       (choices tramp-default-proxies-alist)
-       item proxy)
+       (hops (or (tramp-file-name-hop vec) ""))
+       (item vec)
+       choices proxy)
+
+    ;; Ad-hoc proxy definitions.
+    (dolist (proxy (reverse (split-string hops tramp-postfix-hop-regexp 'omit)))
+      (let ((user (tramp-file-name-user item))
+           (host (tramp-file-name-host item))
+           (proxy (concat
+                   tramp-prefix-format proxy tramp-postfix-host-format)))
+       (tramp-message
+        vec 5 "Add proxy (\"%s\" \"%s\" \"%s\")"
+        (and (stringp host) (regexp-quote host))
+        (and (stringp user) (regexp-quote user))
+        proxy)
+       ;; Add the hop.
+       (add-to-list
+        'tramp-default-proxies-alist
+        (list (and (stringp host) (regexp-quote host))
+              (and (stringp user) (regexp-quote user))
+              proxy))
+       (setq item (tramp-dissect-file-name proxy))))
+    ;; Save the new value.
+    (when (and hops tramp-save-ad-hoc-proxies)
+      (customize-save-variable
+       'tramp-default-proxies-alist tramp-default-proxies-alist))
 
     ;; Look for proxy hosts to be passed.
+    (setq choices tramp-default-proxies-alist)
     (while choices
       (setq item (pop choices)
            proxy (eval (nth 2 item)))
       (when (and
-            ;; host
+            ;; Host.
             (string-match (or (eval (nth 0 item)) "")
                           (or (tramp-file-name-host (car target-alist)) ""))
-            ;; user
+            ;; User.
             (string-match (or (eval (nth 1 item)) "")
                           (or (tramp-file-name-user (car target-alist)) "")))
        (if (null proxy)
@@ -4138,7 +4223,7 @@ Gateway hops are already opened."
         'target-alist
         (vector
          (tramp-file-name-method hop) (tramp-file-name-user hop)
-         (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil))
+         (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil 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
@@ -4186,6 +4271,9 @@ Gateway hops are already opened."
     ;; Result.
     target-alist))
 
+(defvar tramp-current-connection nil
+  "Last connection timestamp.")
+
 (defun tramp-maybe-open-connection (vec)
   "Maybe open a connection VEC.
 Does not do anything if a connection is already open, but re-opens the
@@ -4196,6 +4284,16 @@ connection if a previous connection has died for some reason."
          (process-environment (copy-sequence process-environment))
          (pos (with-current-buffer (tramp-get-connection-buffer vec) (point))))
 
+      ;; If Tramp opens the same connection within a short time frame,
+      ;; there is a problem.  We shall signal this.
+      (unless (or (and p (processp p) (memq (process-status p) '(run open)))
+                 (not (equal (butlast (append vec nil))
+                             (car tramp-current-connection)))
+                 (> (tramp-time-diff
+                     (current-time) (cdr tramp-current-connection))
+                    5))
+       (throw 'suppress 'suppress))
+
       ;; If too much time has passed since last command was sent, look
       ;; whether process is still alive.  If it isn't, kill it.  When
       ;; using ssh, it can sometimes happen that the remote end has
@@ -4213,157 +4311,183 @@ connection if a previous connection has died for some reason."
            (tramp-send-command vec "echo are you awake" t t)
            (unless (and (memq (process-status p) '(run open))
                         (tramp-wait-for-output p 10))
-             ;; The error will be catched locally.
+             ;; The error will be caught locally.
              (tramp-error vec 'file-error "Awake did fail")))
        (file-error
-        (tramp-flush-connection-property vec)
-        (tramp-flush-connection-property p)
-        (delete-process p)
+        (tramp-cleanup vec)
         (setq p nil)))
 
       ;; New connection must be opened.
-      (unless (and p (processp p) (memq (process-status p) '(run open)))
-
-       ;; We call `tramp-get-buffer' in order to get a debug buffer for
-       ;; messages from the beginning.
-       (tramp-get-buffer vec)
-       (tramp-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)))
-                     (apply
-                      'start-process
-                      (tramp-get-connection-name vec)
-                      (tramp-get-connection-buffer vec)
-                      (if tramp-encoding-command-interactive
-                          (list tramp-encoding-shell
-                                tramp-encoding-command-interactive)
-                        (list tramp-encoding-shell))))))
-
-           ;; Set sentinel and query flag.
-           (tramp-set-connection-property p "vector" vec)
-           (set-process-sentinel p 'tramp-process-sentinel)
-           (tramp-compat-set-process-query-on-exit-flag p nil)
+      (condition-case err
+         (unless (and p (processp p) (memq (process-status p) '(run open)))
+
+           ;; We call `tramp-get-buffer' in order to get a debug
+           ;; buffer for messages from the beginning.
+           (tramp-get-buffer vec)
+
+           ;; If `non-essential' is non-nil, don't reopen a new connection.
+           (when (and (boundp 'non-essential) (symbol-value 'non-essential))
+             (throw 'non-essential 'non-essential))
+
+           (with-tramp-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)))
+                         (apply
+                          'start-process
+                          (tramp-get-connection-name vec)
+                          (tramp-get-connection-buffer vec)
+                          (if tramp-encoding-command-interactive
+                              (list tramp-encoding-shell
+                                    tramp-encoding-command-interactive)
+                            (list tramp-encoding-shell))))))
+
+               ;; Set sentinel and query flag.
+               (tramp-set-connection-property p "vector" vec)
+               (set-process-sentinel p 'tramp-process-sentinel)
+               (tramp-compat-set-process-query-on-exit-flag p nil)
+               (setq tramp-current-connection
+                     (cons (butlast (append vec nil)) (current-time))
+                     tramp-current-host (system-name))
 
-           (tramp-message
-            vec 6 "%s" (mapconcat 'identity (process-command p) " "))
-
-           ;; Check whether process is alive.
-           (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))
-                    (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 pos 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)))))))
+                vec 6 "%s" (mapconcat 'identity (process-command p) " "))
+
+               ;; Check whether process is alive.
+               (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))
+                        (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-real-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 r-shell)
+
+                   ;; Add arguments for asynchronous 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)))
+
+                   ;; Check, whether there is a restricted shell.
+                   (dolist (elt tramp-restricted-shell-hosts-alist)
+                     (when (string-match elt tramp-current-host)
+                       (setq r-shell t)))
+
+                   ;; 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 r-shell "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'.  It could
+                     ;; also be a restricted shell, which does not
+                     ;; allow "exec".
+                     (when r-shell " && 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 pos 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))))
+
+       ;; When the user did interrupt, we must cleanup.
+       (quit
+        (tramp-cleanup vec)
+        ;; Propagate the quit signal.
+        (signal (car err) (cdr err)))))))
 
 (defun tramp-send-command (vec command &optional neveropen nooutput)
   "Send the COMMAND to connection VEC.
@@ -4377,7 +4501,8 @@ function waits for output unless NOOUTPUT is set."
       ;; We mark the command string that it can be erased in the output buffer.
       (tramp-set-connection-property p "check-remote-echo" t)
       (setq command (format "%s%s%s" tramp-echo-mark command tramp-echo-mark)))
-    (when (string-match "<<'EOF'" command)
+    (when (and (string-match "<<'EOF'" command)
+              (not (tramp-get-connection-property vec "busybox" nil)))
       ;; Unset $PS1 when using here documents, in order to avoid
       ;; multiple prompts.
       (setq command (concat "(PS1= ; " command "\n)")))
@@ -4650,7 +4775,7 @@ This is used internally by `tramp-file-mode-from-int'."
 ;; Variables local to connection.
 
 (defun tramp-get-remote-path (vec)
-  (with-connection-property
+  (with-tramp-connection-property
       ;; When `tramp-own-remote-path' is in `tramp-remote-path', we
       ;; cache the result for the session only.  Otherwise, the result
       ;; is cached persistently.
@@ -4721,18 +4846,8 @@ This is used internally by `tramp-file-mode-from-int'."
           x))
        remote-path)))))
 
-(defun tramp-get-remote-tmpdir (vec)
-  (with-connection-property vec "tmp-directory"
-    (let ((dir (tramp-shell-quote-argument "/tmp")))
-      (if (and (tramp-send-command-and-check
-               vec (format "%s -d %s" (tramp-get-test-command vec) dir))
-              (tramp-send-command-and-check
-               vec (format "%s -w %s" (tramp-get-test-command vec) dir)))
-         dir
-       (tramp-error vec 'file-error "Directory %s not accessible" dir)))))
-
 (defun tramp-get-ls-command (vec)
-  (with-connection-property vec "ls"
+  (with-tramp-connection-property vec "ls"
     (tramp-message vec 5 "Finding a suitable `ls' command")
     (or
      (catch 'ls-found
@@ -4758,7 +4873,7 @@ This is used internally by `tramp-file-mode-from-int'."
 
 (defun tramp-get-ls-command-with-dired (vec)
   (save-match-data
-    (with-connection-property vec "ls-dired"
+    (with-tramp-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
@@ -4767,7 +4882,7 @@ This is used internally by `tramp-file-mode-from-int'."
        vec (format "%s --dired -al /dev/null" (tramp-get-ls-command vec))))))
 
 (defun tramp-get-test-command (vec)
-  (with-connection-property vec "test"
+  (with-tramp-connection-property vec "test"
     (tramp-message vec 5 "Finding a suitable `test' command")
     (if (tramp-send-command-and-check vec "test 0")
        "test"
@@ -4777,7 +4892,7 @@ This is used internally by `tramp-file-mode-from-int'."
   ;; Does `test A -nt B' work?  Use abominable `find' construct if it
   ;; doesn't.  BSD/OS 4.0 wants the parentheses around the command,
   ;; for otherwise the shell crashes.
-  (with-connection-property vec "test-nt"
+  (with-tramp-connection-property vec "test-nt"
     (or
      (progn
        (tramp-send-command
@@ -4795,17 +4910,17 @@ This is used internally by `tramp-file-mode-from-int'."
        "tramp_test_nt %s %s"))))
 
 (defun tramp-get-file-exists-command (vec)
-  (with-connection-property vec "file-exists"
+  (with-tramp-connection-property vec "file-exists"
     (tramp-message vec 5 "Finding command to check if file exists")
     (tramp-find-file-exists-command vec)))
 
 (defun tramp-get-remote-ln (vec)
-  (with-connection-property vec "ln"
+  (with-tramp-connection-property vec "ln"
     (tramp-message vec 5 "Finding a suitable `ln' command")
     (tramp-find-executable vec "ln" (tramp-get-remote-path vec))))
 
 (defun tramp-get-remote-perl (vec)
-  (with-connection-property vec "perl"
+  (with-tramp-connection-property vec "perl"
     (tramp-message vec 5 "Finding a suitable `perl' command")
     (let ((result
           (or (tramp-find-executable vec "perl5" (tramp-get-remote-path vec))
@@ -4813,16 +4928,16 @@ This is used internally by `tramp-file-mode-from-int'."
                vec "perl" (tramp-get-remote-path vec)))))
       ;; We must check also for some Perl modules.
       (when result
-       (with-connection-property vec "perl-file-spec"
+       (with-tramp-connection-property vec "perl-file-spec"
           (tramp-send-command-and-check
            vec (format "%s -e 'use File::Spec;'" result)))
-       (with-connection-property vec "perl-cwd-realpath"
+       (with-tramp-connection-property vec "perl-cwd-realpath"
           (tramp-send-command-and-check
            vec (format "%s -e 'use Cwd \"realpath\";'" result))))
       result)))
 
 (defun tramp-get-remote-stat (vec)
-  (with-connection-property vec "stat"
+  (with-tramp-connection-property vec "stat"
     (tramp-message vec 5 "Finding a suitable `stat' command")
     (let ((result (tramp-find-executable
                   vec "stat" (tramp-get-remote-path vec)))
@@ -4840,7 +4955,7 @@ This is used internally by `tramp-file-mode-from-int'."
       result)))
 
 (defun tramp-get-remote-readlink (vec)
-  (with-connection-property vec "readlink"
+  (with-tramp-connection-property vec "readlink"
     (tramp-message vec 5 "Finding a suitable `readlink' command")
     (let ((result (tramp-find-executable
                   vec "readlink" (tramp-get-remote-path vec))))
@@ -4850,12 +4965,12 @@ This is used internally by `tramp-file-mode-from-int'."
        result))))
 
 (defun tramp-get-remote-trash (vec)
-  (with-connection-property vec "trash"
+  (with-tramp-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"
+  (with-tramp-connection-property vec "id"
     (tramp-message vec 5 "Finding POSIX `id' command")
     (or
      (catch 'id-found
@@ -4869,7 +4984,7 @@ This is used internally by `tramp-file-mode-from-int'."
      (tramp-error vec 'file-error "Couldn't find a POSIX `id' command"))))
 
 (defun tramp-get-remote-uid (vec id-format)
-  (with-connection-property vec (format "uid-%s" id-format)
+  (with-tramp-connection-property vec (format "uid-%s" id-format)
     (let ((res (tramp-send-command-and-read
                vec
                (format "%s -u%s %s"
@@ -4881,7 +4996,7 @@ This is used internally by `tramp-file-mode-from-int'."
       (if (and (equal id-format 'integer) (not (integerp res))) -1 res))))
 
 (defun tramp-get-remote-gid (vec id-format)
-  (with-connection-property vec (format "gid-%s" id-format)
+  (with-tramp-connection-property vec (format "gid-%s" id-format)
     (let ((res (tramp-send-command-and-read
                vec
                (format "%s -g%s %s"
@@ -4907,13 +5022,14 @@ the length of the file to be compressed.
 If no corresponding command is found, nil is returned."
   (when (and (integerp tramp-inline-compress-start-size)
             (> size tramp-inline-compress-start-size))
-    (with-connection-property vec prop
+    (with-tramp-connection-property (tramp-get-connection-process vec) prop
       (tramp-find-inline-compress vec)
-      (tramp-get-connection-property vec prop nil))))
+      (tramp-get-connection-property
+       (tramp-get-connection-process vec) prop nil))))
 
 (defun tramp-get-inline-coding (vec prop size)
   "Return the coding command related to PROP.
-PROP is either `remote-encoding', `remode-decoding',
+PROP is either `remote-encoding', `remote-decoding',
 `local-encoding' or `local-decoding'.
 
 SIZE is the length of the file to be coded.  Depending on SIZE,
@@ -4927,9 +5043,11 @@ function cell is returned to be applied on a buffer."
   ;; no inline coding is found.
   (ignore-errors
     (let ((coding
-          (with-connection-property vec prop
+          (with-tramp-connection-property
+              (tramp-get-connection-process vec) prop
             (tramp-find-inline-encoding vec)
-            (tramp-get-connection-property vec prop nil)))
+            (tramp-get-connection-property
+             (tramp-get-connection-process vec) prop nil)))
          (prop1 (if (string-match "encoding" prop)
                     "inline-compress" "inline-decompress"))
          compress)
@@ -5041,11 +5159,11 @@ function cell is returned to be applied on a buffer."
 ;;   until the last but one hop via `start-file-process'.  Apply it
 ;;   also for ftp and smb.
 ;; * WIBNI if we had a command "trampclient"?  If I was editing in
-;;   some shell with root priviledges, it would be nice if I could
+;;   some shell with root privileges, it would be nice if I could
 ;;   just call
 ;;     trampclient filename.c
 ;;   as an editor, and the _current_ shell would connect to an Emacs
-;;   server and would be used in an existing non-priviledged Emacs
+;;   server and would be used in an existing non-privileged Emacs
 ;;   session for doing the editing in question.
 ;;   That way, I need not tell Emacs my password again and be afraid
 ;;   that it makes it into core dumps or other ugly stuff (I had Emacs