* vc-git.el (vc-git--call): Apply `process-file' instead of
[bpt/emacs.git] / lisp / net / tramp.el
index aa7456a..899cefc 100644 (file)
@@ -1,12 +1,12 @@
-;;; -*- mode: Emacs-Lisp; coding: iso-2022-7bit; -*-
 ;;; tramp.el --- Transparent Remote Access, Multiple Protocol
+;;; -*- mode: Emacs-Lisp; coding: utf-8; -*-
 
 ;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-;;   2005, 2006, 2007 Free Software Foundation, Inc.
+;;   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 ;; (copyright statements below in code to be updated with the above notice)
 
-;; Author: Kai Gro\e,A_\e(Bjohann <kai.grossjohann@gmx.net>
+;; Author: Kai Großjohann <kai.grossjohann@gmx.net>
 ;;         Michael Albinus <michael.albinus@gmx.de>
 ;; Keywords: comm, processes
 
@@ -14,8 +14,8 @@
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 3 of the License, or
-;; (at your option) any later version.
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
             (when (featurep 'trampver)
               (unload-feature 'trampver 'force))))
 
-(require 'custom)
-
-(if (featurep 'xemacs)
-    (require 'timer-funcs)
-  (require 'timer))
+(require 'tramp-compat)
+(add-hook 'tramp-unload-hook
+         '(lambda ()
+            (when (featurep 'tramp-compat)
+              (unload-feature 'tramp-compat 'force))))
 
-(require 'format-spec)                  ;from Gnus 5.8, also in tar ball
+(require 'format-spec)                  ; from Gnus 5.8, also in tar ball
 ;; As long as password.el is not part of (X)Emacs, it shouldn't
 ;; be mandatory
 (if (featurep 'xemacs)
     (load "password" 'noerror)
-  (require 'password nil 'noerror))     ;from No Gnus, also in tar ball
+  (or (require 'password-cache nil 'noerror)
+      (require 'password nil 'noerror))) ; from No Gnus, also in tar ball
 
 (require 'shell)
 (require 'advice)
@@ -93,7 +94,6 @@
 (autoload 'tramp-set-file-property "tramp-cache")
 (autoload 'tramp-flush-file-property "tramp-cache")
 (autoload 'tramp-flush-directory-property "tramp-cache")
-(autoload 'tramp-cache-print "tramp-cache")
 (autoload 'tramp-get-connection-property "tramp-cache")
 (autoload 'tramp-set-connection-property "tramp-cache")
 (autoload 'tramp-flush-connection-property "tramp-cache")
 
 (autoload 'uudecode-decode-region "uudecode")
 
-;; The following Tramp packages must be loaded after Tramp, because
-;; they require Tramp as well.
+;; The following Tramp packages must be loaded after tramp.el, because
+;; they require it as well.
 (eval-after-load "tramp"
-  '(progn
+  '(dolist
+       (feature
+       (list
+
+        ;; Tramp interactive commands.
+        'tramp-cmds
+
+        ;; Load foreign FTP method.
+        (if (featurep 'xemacs) 'tramp-efs 'tramp-ftp)
 
-     ;; Load foreign FTP method.
-     (let ((feature (if (featurep 'xemacs) 'tramp-efs 'tramp-ftp)))
+        ;; tramp-smb uses "smbclient" from Samba.  Not available
+        ;; under Cygwin and Windows, because they don't offer
+        ;; "smbclient".  And even not necessary there, because Emacs
+        ;; supports UNC file names like "//host/share/localname".
+        (unless (memq system-type '(cygwin windows-nt)) 'tramp-smb)
+
+        ;; Load foreign FISH method.
+        'tramp-fish
+
+        ;; Load gateways.  It needs `make-network-process' from Emacs 22.
+        (when (functionp 'make-network-process) 'tramp-gw)))
+
+     (when feature
        (require feature)
        (add-hook 'tramp-unload-hook
                 `(lambda ()
                    (when (featurep ,feature)
-                     (unload-feature ,feature 'force)))))
-
-     ;; tramp-smb uses "smbclient" from Samba.  Not available under
-     ;; Cygwin and Windows, because they don't offer "smbclient".  And
-     ;; even not necessary there, because Emacs supports UNC file names
-     ;; like "//host/share/localname".
-     (unless (memq system-type '(cygwin windows-nt))
-       (require 'tramp-smb)
-       (add-hook 'tramp-unload-hook
-                '(lambda ()
-                   (when (featurep 'tramp-smb)
-                     (unload-feature 'tramp-smb 'force)))))
-
-     ;; Load foreign FISH method.
-     (require 'tramp-fish)
-     (add-hook 'tramp-unload-hook
-              '(lambda ()
-                 (when (featurep 'tramp-fish)
-                   (unload-feature 'tramp-fish 'force))))
-
-     ;; Load gateways.  It needs `make-network-process' from Emacs 22.
-     (if (functionp 'make-network-process)
-        (progn
-          (require 'tramp-gw)
-          (add-hook 'tramp-unload-hook
-                    '(lambda ()
-                       (when (featurep 'tramp-gw)
-                         (unload-feature 'tramp-gw 'force)))))
-       ;; We need to declare used tramp-gw-* symbols at least.
-       (setq tramp-gw-tunnel-method ""
-            tramp-gw-socks-method "")
-       (defalias 'tramp-gw-open-connection 'ignore))
-
-     ;; tramp-util offers integration into other (X)Emacs packages like
-     ;; compile.el, gud.el etc.  Not necessary in Emacs 23.
-     (unless (functionp 'start-file-process)
-       (require 'tramp-util)
-       (add-hook 'tramp-unload-hook
-                '(lambda ()
-                   (when (featurep 'tramp-util)
-                     (unload-feature 'tramp-util 'force)))))))
-
-;; Avoid byte-compiler warnings if the byte-compiler supports this.
-;; Currently, XEmacs supports this.
-(eval-when-compile
-  (when (featurep 'xemacs)
-    (byte-compiler-options (warnings (- unused-vars)))))
-
-;; `last-coding-system-used' is unknown in XEmacs.
-(eval-when-compile
-  (unless (boundp 'last-coding-system-used)
-    (defvar last-coding-system-used nil)))
-
-;; `directory-sep-char' is an obsolete variable in Emacs.  But it is
-;; used in XEmacs, so we set it here and there.  The following is needed
-;; to pacify Emacs byte-compiler.
-(eval-when-compile
-  (unless (boundp 'byte-compile-not-obsolete-var)
-    (defvar byte-compile-not-obsolete-var nil))
-  (setq byte-compile-not-obsolete-var 'directory-sep-char))
-
-;; `with-temp-message' does not exists in XEmacs.
-(eval-and-compile
-  (condition-case nil
-      (with-temp-message (current-message) nil)
-    (error (defmacro with-temp-message (message &rest body) `(progn ,@body)))))
-
-;; `set-buffer-multibyte' comes from Emacs Leim.
-(eval-and-compile
-  (unless (fboundp 'set-buffer-multibyte)
-    (defalias 'set-buffer-multibyte 'ignore)))
+                     (unload-feature ,feature 'force)))))))
 
 ;;; User Customizable Internal Variables:
 
   :version "22.1")
 
 (defcustom tramp-verbose 3
-  "*Verbosity level for tramp.
+  "*Verbosity level for Tramp.
 Any level x includes messages for all levels 1 .. x-1.  The levels are
 
  0  silent (no tramp messages at all)
@@ -611,7 +560,7 @@ pair of the form (KEY VALUE).  The following KEYs are defined:
   * `tramp-remote-sh'
     This specifies the Bourne shell to use on the remote host.  This
     MUST be a Bourne-like shell.  It is normally not necessary to set
-    this to any value other than \"/bin/sh\": tramp wants to use a shell
+    this to any value other than \"/bin/sh\": Tramp wants to use a shell
     which groks tilde expansion, but it can search for it.  Also note
     that \"/bin/sh\" exists on all Unixen, this might not be true for
     the value that you decide to use.  You Have Been Warned.
@@ -942,7 +891,7 @@ The default value is to use the same value as `tramp-rsh-end-of-line'."
 ;; "getconf PATH" yields:
 ;; HP-UX: /usr/bin:/usr/ccs/bin:/opt/ansic/bin:/opt/langtools/bin:/opt/fortran/bin
 ;; Solaris: /usr/xpg4/bin:/usr/ccs/bin:/usr/bin:/opt/SUNWspro/bin
-;; Linux (Debian, Suse): /bin:/usr/bin
+;; GNU/Linux (Debian, Suse): /bin:/usr/bin
 ;; FreeBSD: /usr/bin:/bin:/usr/sbin:/sbin: - beware trailing ":"!
 (defcustom tramp-remote-path
   '(tramp-default-remote-path "/usr/sbin" "/usr/local/bin"
@@ -964,16 +913,8 @@ directories for POSIX compatible commands."
                  (const :tag "Default Directories" tramp-default-remote-path)
                  (string :tag "Directory"))))
 
-(defcustom tramp-terminal-type "dumb"
-  "*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."
-  :group 'tramp
-  :type 'string)
-
 (defcustom tramp-remote-process-environment
-  `("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_TIME=C"
+  `("HISTFILE=$HOME/.tramp_history" "HISTSIZE=1" "LC_CTYPE=C" "LC_TIME=C"
     ,(concat "TERM=" tramp-terminal-type)
     "CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH="
     "autocorrect=" "correct=")
@@ -1023,11 +964,11 @@ The `sudo' program appears to insert a `^@' character into the prompt."
 (defcustom tramp-wrong-passwd-regexp
   (concat "^.*"
          ;; These strings should be on the last line
-         (regexp-opt '("Permission denied."
+         (regexp-opt '("Permission denied"
                        "Login incorrect"
                        "Login Incorrect"
                        "Connection refused"
-                       "Connection closed by foreign host."
+                       "Connection closed"
                        "Sorry, try again."
                        "Name or service not known"
                        "Host key verification failed."
@@ -1113,7 +1054,7 @@ The answer will be provided by `tramp-action-process-alive',
   "*Prefix to use for temporary files.
 If this is a relative file name (such as \"tramp.\"), it is considered
 relative to the directory name returned by the function
-`tramp-temporary-file-directory' (which see).  It may also be an
+`tramp-compat-temporary-file-directory' (which see).  It may also be an
 absolute file name; don't forget to include a prefix for the filename
 part, though."
   :group 'tramp
@@ -1168,12 +1109,12 @@ It can have the following values:
        ((equal tramp-syntax 'sep) "/[")
        ((equal tramp-syntax 'url) "/")
        (t (error "Wrong `tramp-syntax' defined")))
-  "*String matching the very beginning of tramp file names.
+  "*String matching the very beginning of Tramp file names.
 Used in `tramp-make-tramp-file-name'.")
 
 (defconst tramp-prefix-regexp
   (concat "^" (regexp-quote tramp-prefix-format))
-  "*Regexp matching the very beginning of tramp file names.
+  "*Regexp matching the very beginning of Tramp file names.
 Should always start with \"^\". Derived from `tramp-prefix-format'.")
 
 (defconst tramp-method-regexp
@@ -1265,9 +1206,9 @@ Derived from `tramp-postfix-host-format'.")
    2 4 5 7)
 
   "*List of five elements (REGEXP METHOD USER HOST FILE), detailing \
-the tramp file name structure.
+the Tramp file name structure.
 
-The first element REGEXP is a regular expression matching a tramp file
+The first element REGEXP is a regular expression matching a Tramp file
 name.  The regex should contain parentheses around the method name,
 the user name, the host name, and the file name parts.
 
@@ -1306,12 +1247,12 @@ See `tramp-file-name-structure' for more explanations.")
        ((equal tramp-syntax 'sep) tramp-file-name-regexp-separate)
        ((equal tramp-syntax 'url) tramp-file-name-regexp-url)
        (t (error "Wrong `tramp-syntax' defined")))
-  "*Regular expression matching file names handled by tramp.
-This regexp should match tramp file names but no other file names.
+  "*Regular expression matching file names handled by Tramp.
+This regexp should match Tramp file names but no other file names.
 \(When tramp.el is loaded, this regular expression is prepended to
 `file-name-handler-alist', and that is searched sequentially.  Thus,
-if the tramp entry appears rather early in the `file-name-handler-alist'
-and is a bit too general, then some files might be considered tramp
+if the Tramp entry appears rather early in the `file-name-handler-alist'
+and is a bit too general, then some files might be considered Tramp
 files which are not really Tramp files.
 
 Please note that the entry in `file-name-handler-alist' is made when
@@ -1353,8 +1294,8 @@ See `tramp-file-name-structure' for more explanations.")
        ((equal tramp-syntax 'sep) tramp-completion-file-name-regexp-separate)
        ((equal tramp-syntax 'url) tramp-completion-file-name-regexp-url)
        (t (error "Wrong `tramp-syntax' defined")))
-  "*Regular expression matching file names handled by tramp completion.
-This regexp should match partial tramp file names only.
+  "*Regular expression matching file names handled by Tramp completion.
+This regexp should match partial Tramp file names only.
 
 Please note that the entry in `file-name-handler-alist' is made when
 this file (tramp.el) is loaded.  This means that this variable must be set
@@ -1477,6 +1418,18 @@ opening a connection to a remote host."
   :group 'tramp
   :type '(choice (const nil) (const t) (const pty)))
 
+(defcustom tramp-completion-reread-directory-timeout 10
+  "Defines seconds since last remote command before rereading a directory.
+A remote directory might have changed its contents.  In order to
+make it visible during file name completion in the minibuffer,
+Tramp flushes its cache and rereads the directory contents when
+more than `tramp-completion-reread-directory-timeout' seconds
+have been gone since last remote command execution.  A value of 0
+would require an immediate reread during filename completion, nil
+means to use always cached values for the directory contents."
+  :group 'tramp
+  :type '(choice (const nil) integer))
+
 ;;; Internal Variables:
 
 (defvar tramp-end-of-output
@@ -1642,7 +1595,7 @@ on the remote host.")
 (defconst tramp-perl-encode
   "%s -e '
 # This script is contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
 #   Free Software Foundation, Inc.
 use strict;
 
@@ -1684,7 +1637,7 @@ This string is passed to `format', so percent characters need to be doubled.")
 (defconst tramp-perl-decode
   "%s -e '
 # This script is contributed by Juanma Barranquero <lektu@terra.es>.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008
 #   Free Software Foundation, Inc.
 use strict;
 
@@ -1726,27 +1679,27 @@ while (my $data = <STDIN>) {
 Escape sequence %s is replaced with name of Perl binary.
 This string is passed to `format', so percent characters need to be doubled.")
 
-(defconst tramp-file-mode-type-map '((0  . "-")  ; Normal file (SVID-v2 and XPG2)
-                                    (1  . "p")  ; fifo
-                                    (2  . "c")  ; character device
-                                    (3  . "m")  ; multiplexed character device (v7)
-                                    (4  . "d")  ; directory
-                                    (5  . "?")  ; Named special file (XENIX)
-                                    (6  . "b")  ; block device
-                                    (7  . "?")  ; multiplexed block device (v7)
-                                    (8  . "-")  ; regular file
-                                    (9  . "n")  ; network special file (HP-UX)
-                                    (10 . "l")  ; symlink
-                                    (11 . "?")  ; ACL shadow inode (Solaris, not userspace)
-                                    (12 . "s")  ; socket
-                                    (13 . "D")  ; door special (Solaris)
-                                    (14 . "w")) ; whiteout (BSD)
+(defconst tramp-file-mode-type-map
+  '((0  . "-")  ; Normal file (SVID-v2 and XPG2)
+    (1  . "p")  ; fifo
+    (2  . "c")  ; character device
+    (3  . "m")  ; multiplexed character device (v7)
+    (4  . "d")  ; directory
+    (5  . "?")  ; Named special file (XENIX)
+    (6  . "b")  ; block device
+    (7  . "?")  ; multiplexed block device (v7)
+    (8  . "-")  ; regular file
+    (9  . "n")  ; network special file (HP-UX)
+    (10 . "l")  ; symlink
+    (11 . "?")  ; ACL shadow inode (Solaris, not userspace)
+    (12 . "s")  ; socket
+    (13 . "D")  ; door special (Solaris)
+    (14 . "w")) ; whiteout (BSD)
   "A list of file types returned from the `stat' system call.
 This is used to map a mode number to a permission string.")
 
 ;; New handlers should be added here.  The following operations can be
 ;; handled using the normal primitives: file-name-as-directory,
-;; file-name-directory, file-name-nondirectory,
 ;; file-name-sans-versions, get-file-buffer.
 (defconst tramp-file-name-handler-alist
   '((load . tramp-handle-load)
@@ -1789,6 +1742,8 @@ This is used to map a mode number to a permission string.")
     (file-local-copy . tramp-handle-file-local-copy)
     (file-remote-p . tramp-handle-file-remote-p)
     (insert-file-contents . tramp-handle-insert-file-contents)
+    (insert-file-contents-literally
+     . tramp-handle-insert-file-contents-literally)
     (write-region . tramp-handle-write-region)
     (find-backup-file-name . tramp-handle-find-backup-file-name)
     (make-auto-save-file-name . tramp-handle-make-auto-save-file-name)
@@ -1801,7 +1756,7 @@ This is used to map a mode number to a permission string.")
   "Alist of handler functions.
 Operations not mentioned here will be handled by the normal Emacs functions.")
 
-;; Handlers for partial tramp file names.  For Emacs just
+;; Handlers for partial Tramp file names.  For Emacs just
 ;; `file-name-all-completions' is needed.
 ;;;###autoload
 (defconst tramp-completion-file-name-handler-alist
@@ -1821,7 +1776,7 @@ normal Emacs functions.")
 If (FUNCTION FILENAME) returns non-nil, then all I/O on that file is done by
 calling HANDLER.")
 
-;;; Internal functions which must come first.
+;;; Internal functions which must come first:
 
 (defsubst tramp-debug-message (vec fmt-string &rest args)
   "Append message to debug buffer.
@@ -1864,7 +1819,7 @@ ARGS to actually emit the message (if applicable)."
 
 (defsubst tramp-message (vec-or-proc level fmt-string &rest args)
   "Emit a message depending on verbosity level.
-VEC-OR-PROC identifies the tramp buffer to use.  It can be either a
+VEC-OR-PROC identifies the Tramp buffer to use.  It can be either a
 vector or a process.  LEVEL says to be quiet if `tramp-verbose' is
 less than LEVEL.  The message is emitted only if `tramp-verbose' is
 greater than or equal to LEVEL.
@@ -1933,15 +1888,6 @@ an input event arrives.  The other arguments are passed to `tramp-error'."
               (tramp-get-buffer vec-or-proc)))
          (sit-for 30))))))
 
-(defsubst tramp-line-end-position nil
-  "Return point at end of line.
-Calls `line-end-position' or `point-at-eol' if defined, else
-own implementation."
-  (cond
-   ((fboundp 'line-end-position) (funcall (symbol-function 'line-end-position)))
-   ((fboundp 'point-at-eol)     (funcall (symbol-function 'point-at-eol)))
-   (t (save-excursion (end-of-line) (point)))))
-
 (defmacro with-parsed-tramp-file-name (filename var &rest body)
   "Parse a Tramp filename and make components available in the body.
 
@@ -1970,14 +1916,7 @@ If VAR is nil, then we bind `v' to the structure and `method', `user',
 
 (put 'with-parsed-tramp-file-name 'lisp-indent-function 2)
 (put 'with-parsed-tramp-file-name 'edebug-form-spec '(form symbolp body))
-;; Enable debugging.
-;(eval-and-compile
-;  (when (featurep 'edebug)
-;    (def-edebug-spec with-parsed-tramp-file-name (form symbolp body))))
-;; Highlight as keyword.
-(when (functionp 'font-lock-add-keywords)
-  (funcall 'font-lock-add-keywords
-          'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>")))
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-parsed-tramp-file-name\\>"))
 
 (defmacro with-file-property (vec file property &rest body)
   "Check in Tramp cache for PROPERTY, otherwise execute BODY and set cache.
@@ -1992,8 +1931,10 @@ FILE must be a local file name on a connection identified via VEC."
          (tramp-set-file-property ,vec ,file ,property value))
        value)
      ,@body))
+
 (put 'with-file-property 'lisp-indent-function 3)
 (put 'with-file-property 'edebug-form-spec t)
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-file-property\\>"))
 
 (defmacro with-connection-property (key property &rest body)
   "Checks in Tramp for property PROPERTY, otherwise executes BODY and set."
@@ -2005,8 +1946,10 @@ FILE must be a local file name on a connection identified via VEC."
       (setq value (progn ,@body))
       (tramp-set-connection-property ,key ,property value))
     value))
+
 (put 'with-connection-property 'lisp-indent-function 2)
 (put 'with-connection-property 'edebug-form-spec t)
+(font-lock-add-keywords 'emacs-lisp-mode '("\\<with-connection-property\\>"))
 
 (defmacro tramp-let-maybe (variable value &rest body)
   "Let-bind VARIABLE to VALUE in BODY, but only if VARIABLE is not obsolete.
@@ -2019,6 +1962,33 @@ The intent is to protect against `obsolete variable' warnings."
 (put 'tramp-let-maybe 'lisp-indent-function 2)
 (put 'tramp-let-maybe 'edebug-form-spec t)
 
+(defsubst tramp-make-tramp-temp-file (vec)
+  "Create a temporary file on the remote host identified by VEC.
+Return the local name of the temporary file."
+  (let ((prefix
+        (tramp-make-tramp-file-name
+         (tramp-file-name-method vec)
+         (tramp-file-name-user vec)
+         (tramp-file-name-host vec)
+         (expand-file-name
+          tramp-temp-name-prefix (tramp-get-remote-tmpdir vec))))
+       result)
+    (while (not result)
+      ;; `make-temp-file' would be the natural choice for
+      ;; implementation.  But it calls `write-region' internally,
+      ;; which also needs a temporary file - we would end in an
+      ;; infinite loop.
+      (setq result (make-temp-name prefix))
+      (if (file-exists-p result)
+         (setq result nil)
+       ;; This creates the file by side effect.
+       (set-file-times result)
+       (set-file-modes result (tramp-octal-to-decimal "0700"))))
+
+    ;; Return the local part.
+    (with-parsed-tramp-file-name result nil localname)))
+
+
 ;;; Config Manipulation Functions:
 
 (defun tramp-set-completion-function (method function-list)
@@ -2052,7 +2022,9 @@ Example:
                   (if (string-match "^HKEY_CURRENT_USER" (nth 1 (car v)))
                       ;; Windows registry.
                       (and (memq system-type '(cygwin windows-nt))
-                           (zerop (call-process "reg" nil nil nil "query" (nth 1 (car v)))))
+                           (zerop
+                            (tramp-local-call-process
+                             "reg" nil nil nil "query" (nth 1 (car v)))))
                     ;; Configuration file.
                     (file-exists-p (nth 1 (car v)))))
        (setq r (delete (car v) r)))
@@ -2071,6 +2043,56 @@ For definition of that list see `tramp-set-completion-function'."
    ;; The method related defaults.
    (cdr (assoc method tramp-completion-function-alist))))
 
+
+;;; Fontification of `read-file-name':
+
+;; rfn-eshadow.el is part of Emacs 22.  It is autoloaded.
+(defvar tramp-rfn-eshadow-overlay)
+(make-variable-buffer-local 'tramp-rfn-eshadow-overlay)
+
+(defun tramp-rfn-eshadow-setup-minibuffer ()
+  "Set up a minibuffer for `file-name-shadow-mode'.
+Adds another overlay hiding filename parts according to Tramp's
+special handling of `substitute-in-file-name'."
+  (when (symbol-value 'minibuffer-completing-file-name)
+    (setq tramp-rfn-eshadow-overlay
+         (funcall (symbol-function 'make-overlay)
+                  (funcall (symbol-function 'minibuffer-prompt-end))
+                  (funcall (symbol-function 'minibuffer-prompt-end))))
+    ;; Copy rfn-eshadow-overlay properties.
+    (let ((props (funcall (symbol-function 'overlay-properties)
+                         (symbol-value 'rfn-eshadow-overlay))))
+      (while props
+       (funcall (symbol-function 'overlay-put)
+                tramp-rfn-eshadow-overlay (pop props) (pop props))))))
+
+(when (boundp 'rfn-eshadow-setup-minibuffer-hook)
+  (add-hook 'rfn-eshadow-setup-minibuffer-hook
+           'tramp-rfn-eshadow-setup-minibuffer))
+
+(defun tramp-rfn-eshadow-update-overlay ()
+  "Update `rfn-eshadow-overlay' to cover shadowed part of minibuffer input.
+This is intended to be used as a minibuffer `post-command-hook' for
+`file-name-shadow-mode'; the minibuffer should have already
+been set up by `rfn-eshadow-setup-minibuffer'."
+  ;; In remote files name, there is a shadowing just for the local part.
+  (let ((end (or (funcall (symbol-function 'overlay-end)
+                         (symbol-value 'rfn-eshadow-overlay))
+                (funcall (symbol-function 'minibuffer-prompt-end)))))
+    (when (file-remote-p (buffer-substring-no-properties end (point-max)))
+      (save-excursion
+       (save-restriction
+         (narrow-to-region
+          (1+ (or (string-match "/" (buffer-string) end) end)) (point-max))
+         (let ((rfn-eshadow-overlay tramp-rfn-eshadow-overlay)
+               (rfn-eshadow-update-overlay-hook nil))
+           (funcall (symbol-function 'rfn-eshadow-update-overlay))))))))
+
+(when (boundp 'rfn-eshadow-update-overlay-hook)
+  (add-hook 'rfn-eshadow-update-overlay-hook
+           'tramp-rfn-eshadow-update-overlay))
+
+
 ;;; File Name Handler Functions:
 
 (defun tramp-handle-make-symbolic-link
@@ -2107,9 +2129,9 @@ target of the symlink differ."
 
       ;; If FILENAME is a Tramp name, use just the localname component.
       (when (tramp-tramp-file-p filename)
-       (setq filename (tramp-file-name-localname
-                       (tramp-dissect-file-name
-                        (expand-file-name filename)))))
+       (setq filename
+             (tramp-file-name-localname
+              (tramp-dissect-file-name (expand-file-name filename)))))
 
       ;; 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
@@ -2148,14 +2170,20 @@ target of the symlink differ."
       (unless nomessage (tramp-message v 0 "Loading %s...done" file))
       t)))
 
-;; Localname manipulation functions that grok TRAMP localnames...
+;; Localname manipulation functions that grok Tramp localnames...
 (defun tramp-handle-file-name-directory (file)
   "Like `file-name-directory' but aware of Tramp files."
-  ;; Everything except the last filename thing is the directory.
-  (with-parsed-tramp-file-name file nil
+  ;; Everything except the last filename thing is the directory.  We
+  ;; cannot apply `with-parsed-tramp-file-name', because this expands
+  ;; the remote file name parts.  This is a problem when we are in
+  ;; file name completion.
+  (let ((v (tramp-dissect-file-name file t)))
     ;; Run the command on the localname portion only.
     (tramp-make-tramp-file-name
-     method user host (file-name-directory (or localname "")))))
+     (tramp-file-name-method v)
+     (tramp-file-name-user v)
+     (tramp-file-name-host v)
+     (file-name-directory (or (tramp-file-name-localname v) "")))))
 
 (defun tramp-handle-file-name-nondirectory (file)
   "Like `file-name-nondirectory' but aware of Tramp files."
@@ -2341,7 +2369,7 @@ target of the symlink differ."
       (when symlinkp
        (search-forward "-> ")
        (setq res-symlink-target
-             (buffer-substring (point) (tramp-line-end-position))))
+             (buffer-substring (point) (tramp-compat-line-end-position))))
       ;; return data gathered
       (list
        ;; 0. t for directory, string (name linked to) for symbolic
@@ -2363,7 +2391,7 @@ target of the symlink differ."
        res-size
        ;; 8. File modes, as a string of ten letters or dashes as in ls -l.
        res-filemodes
-       ;; 9. t iff file's gid would change if file were deleted and
+       ;; 9. t if file's gid would change if file were deleted and
        ;; recreated.  Will be set in `tramp-convert-file-attributes'
        t
        ;; 10. inode number.
@@ -2448,6 +2476,7 @@ of."
        t
       (let ((f (buffer-file-name)))
        (with-parsed-tramp-file-name f nil
+         (tramp-flush-file-property v localname)
          (let* ((attr (file-attributes f))
                 (modtime (nth 5 attr))
                 (mt (visited-file-modtime)))
@@ -2500,6 +2529,7 @@ of."
   (zerop
    (if (file-remote-p filename)
        (with-parsed-tramp-file-name filename nil
+        (tramp-flush-file-property v localname)
         (let ((time (if (or (null time) (equal time '(0 0)))
                         (current-time)
                       time))
@@ -2521,14 +2551,42 @@ of."
                          (format-time-string "%Y%m%d%H%M.%S" time t)
                        (format-time-string "%Y%m%d%H%M.%S" time))
                      (tramp-shell-quote-argument localname)))))
+
      ;; We handle also the local part, because in older Emacsen,
      ;; without `set-file-times', this function is an alias for this.
      ;; We are local, so we don't need the UTC settings.
-     (call-process
+     (tramp-local-call-process
       "touch" nil nil nil "-t"
       (format-time-string "%Y%m%d%H%M.%S" time)
       (tramp-shell-quote-argument filename)))))
 
+(defun tramp-set-file-uid-gid (filename &optional uid gid)
+  "Set the ownership for FILENAME.
+If UID and GID are provided, these values are used; otherwise uid
+and gid of the corresponding user is taken.  Both parameters must be integers."
+  ;; CCC: Modern Unices allow chown only for root.  So we might need
+  ;;      another implementation, see `dired-do-chown'.  OTOH, it is
+  ;;      mostly working with su(do)? when it is needed, so it shall
+  ;;      succeed in the majority of cases.
+  (if (file-remote-p filename)
+      (with-parsed-tramp-file-name filename nil
+       (let ((uid (or (and (integerp uid) uid)
+                      (tramp-get-remote-uid v 'integer)))
+             (gid (or (and (integerp gid) gid)
+                      (tramp-get-remote-gid v 'integer))))
+         (tramp-send-command
+          v (format
+             "chown %d:%d %s" uid gid
+             (tramp-shell-quote-argument localname)))))
+
+    ;; We handle also the local part, because there doesn't exist
+    ;; `set-file-uid-gid'.  On Win32 "chown" might not work.
+    (let ((uid (or (and (integerp uid) uid) (tramp-get-local-uid 'integer)))
+         (gid (or (and (integerp gid) gid) (tramp-get-local-gid 'integer))))
+      (tramp-local-call-process
+       "chown" nil nil nil
+       (format "%d:%d" uid gid) (tramp-shell-quote-argument filename)))))
+
 ;; Simple functions using the `test' command.
 
 (defun tramp-handle-file-executable-p (filename)
@@ -2687,7 +2745,7 @@ of."
   (when (file-directory-p directory)
     (setq directory (expand-file-name directory))
     (let* ((temp
-           (copy-tree
+           (tramp-compat-copy-tree
             (with-parsed-tramp-file-name directory nil
               (with-file-property
                   v localname
@@ -2753,7 +2811,17 @@ of."
 (defun tramp-handle-file-name-all-completions (filename directory)
   "Like `file-name-all-completions' for Tramp files."
   (unless (save-match-data (string-match "/" filename))
-    (with-parsed-tramp-file-name directory nil
+    (with-parsed-tramp-file-name (expand-file-name directory) nil
+      ;; Flush the directory cache.  There could be changed directory
+      ;; contents.
+      (when (and (integerp tramp-completion-reread-directory-timeout)
+                (> (tramp-time-diff
+                    (current-time)
+                    (tramp-get-file-property
+                     v localname "last-completion" '(0 0 0)))
+                   tramp-completion-reread-directory-timeout))
+       (tramp-flush-file-property v localname))
+
       (all-completions
        filename
        (mapcar
@@ -2781,9 +2849,12 @@ of."
           (with-current-buffer (tramp-get-buffer v)
             (goto-char (point-max))
             (while (zerop (forward-line -1))
-              (push (buffer-substring (point)  (tramp-line-end-position))
+              (push (buffer-substring
+                     (point) (tramp-compat-line-end-position))
                     result)))
 
+          (tramp-set-file-property
+           v localname "last-completion" (current-time))
           result)))))))
 
 ;; The following isn't needed for Emacs 20 but for 19.34?
@@ -2834,44 +2905,52 @@ of."
         (buffer-name))))))
 
 (defun tramp-handle-copy-file
-  (filename newname &optional ok-if-already-exists keep-date)
+  (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
   "Like `copy-file' for Tramp files."
   ;; Check if both files are local -- invoke normal copy-file.
-  ;; Otherwise, use tramp from local system.
+  ;; Otherwise, use Tramp from local system.
   (setq filename (expand-file-name filename))
   (setq newname (expand-file-name newname))
-  ;; At least one file a tramp file?
-  (if (or (tramp-tramp-file-p filename)
-          (tramp-tramp-file-p newname))
-      (tramp-do-copy-or-rename-file
-       'copy filename newname ok-if-already-exists keep-date)
+  (cond
+   ;; At least one file a Tramp file?
+   ((or (tramp-tramp-file-p filename)
+       (tramp-tramp-file-p newname))
+    (tramp-do-copy-or-rename-file
+     'copy filename newname ok-if-already-exists keep-date preserve-uid-gid))
+   ;; Compat section.
+   (preserve-uid-gid
+    (tramp-run-real-handler
+     'copy-file
+     (list filename newname ok-if-already-exists keep-date preserve-uid-gid)))
+   (t
     (tramp-run-real-handler
-     'copy-file (list filename newname ok-if-already-exists keep-date))))
+     'copy-file (list filename newname ok-if-already-exists keep-date)))))
 
 (defun tramp-handle-rename-file
   (filename newname &optional ok-if-already-exists)
   "Like `rename-file' for Tramp files."
   ;; Check if both files are local -- invoke normal rename-file.
-  ;; Otherwise, use tramp from local system.
+  ;; Otherwise, use Tramp from local system.
   (setq filename (expand-file-name filename))
   (setq newname (expand-file-name newname))
-  ;; At least one file a tramp file?
+  ;; At least one file a Tramp file?
   (if (or (tramp-tramp-file-p filename)
           (tramp-tramp-file-p newname))
       (tramp-do-copy-or-rename-file
-       'rename filename newname ok-if-already-exists t)
+       'rename filename newname ok-if-already-exists t t)
     (tramp-run-real-handler
      'rename-file (list filename newname ok-if-already-exists))))
 
 (defun tramp-do-copy-or-rename-file
-  (op filename newname &optional ok-if-already-exists keep-date)
+  (op filename newname &optional ok-if-already-exists keep-date preserve-uid-gid)
   "Copy or rename a remote file.
 OP must be `copy' or `rename' and indicates the operation to perform.
 FILENAME specifies the file to copy or rename, NEWNAME is the name of
 the new file (for copy) or the new name of the file (for rename).
 OK-IF-ALREADY-EXISTS means don't barf if NEWNAME exists already.
 KEEP-DATE means to make sure that NEWNAME has the same timestamp
-as FILENAME.
+as FILENAME.  PRESERVE-UID-GID, when non-nil, instructs to keep
+the uid and gid if both files are on the same host.
 
 This function is invoked by `tramp-handle-copy-file' and
 `tramp-handle-rename-file'.  It is an error if OP is neither of `copy'
@@ -2899,7 +2978,9 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
               ;; directly.
               ((tramp-equal-remote filename newname)
                (tramp-do-copy-or-rename-file-directly
-                op v1 v1-localname v2-localname keep-date))
+                op filename newname
+                ok-if-already-exists keep-date preserve-uid-gid))
+
               ;; If both source and target are Tramp files,
               ;; both are using the same copy-program, then we
               ;; can invoke rcp directly.  Note that
@@ -2911,6 +2992,7 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
                        tramp-copy-size-limit))
                (tramp-do-copy-or-rename-file-out-of-band
                 op filename newname keep-date))
+
               ;; No shortcut was possible.  So we copy the
               ;; file first.  If the operation was `rename', we go
               ;; back and delete the original file (if the copy was
@@ -2927,20 +3009,29 @@ and `rename'.  FILENAME and NEWNAME must be absolute file names."
         ;; One file is a Tramp file, the other one is local.
         ((or t1 t2)
          (with-parsed-tramp-file-name (if t1 filename newname) nil
-           ;; If the Tramp file has an out-of-band method, the corresponding
-           ;; copy-program can be invoked.
-           (if (and (tramp-method-out-of-band-p v)
-                    (> (nth 7 (file-attributes filename))
-                       tramp-copy-size-limit))
-               (tramp-do-copy-or-rename-file-out-of-band
-                op filename newname keep-date)
-             ;; Use the generic method via a Tramp buffer.
-             (tramp-do-copy-or-rename-file-via-buffer
-              op filename newname keep-date))))
+           (cond
+            ;; Fast track on local machine.
+            ((tramp-local-host-p v)
+             (tramp-do-copy-or-rename-file-directly
+              op filename newname
+              ok-if-already-exists keep-date preserve-uid-gid))
+
+            ;; If the Tramp file has an out-of-band method, the corresponding
+            ;; copy-program can be invoked.
+            ((and (tramp-method-out-of-band-p v)
+                  (> (nth 7 (file-attributes filename))
+                     tramp-copy-size-limit))
+             (tramp-do-copy-or-rename-file-out-of-band
+              op filename newname keep-date))
+
+            ;; Use the inline method via a Tramp buffer.
+            (t (tramp-do-copy-or-rename-file-via-buffer
+                op filename newname keep-date)))))
 
         (t
          ;; One of them must be a Tramp file.
          (error "Tramp implementation says this cannot happen")))
+
       ;; When newname did exist, we have wrong cached values.
       (when t2
        (with-parsed-tramp-file-name newname nil
@@ -2962,8 +3053,7 @@ KEEP-DATE is non-nil if NEWNAME should have the same timestamp as FILENAME."
                (jka-compr-inhibit t))
            (write-region (point-min) (point-max) newname))))
     ;; KEEP-DATE handling.
-    (when (and keep-date (functionp 'set-file-times))
-      (apply 'set-file-times (list newname modtime)))
+    (when keep-date (set-file-times newname modtime))
     ;; Set the mode.
     (set-file-modes newname (file-modes filename))
     ;; If the operation was `rename', delete the original file.
@@ -2971,53 +3061,127 @@ KEEP-DATE is non-nil if NEWNAME should have the same timestamp as FILENAME."
       (delete-file filename))))
 
 (defun tramp-do-copy-or-rename-file-directly
 (op vec localname1 localname2 keep-date)
(op filename newname ok-if-already-exists keep-date preserve-uid-gid)
   "Invokes `cp' or `mv' on the remote system.
 OP must be one of `copy' or `rename', indicating `cp' or `mv',
-respectively.  VEC specifies the connection.  LOCALNAME1 and
-LOCALNAME2 specify the two arguments of `cp' or `mv'.  If
-KEEP-DATE is non-nil, preserve the time stamp when copying."
-  ;; CCC: What happens to the timestamp when renaming?
-  (let ((cmd (cond ((and (eq op 'copy) keep-date) "cp -f -p")
-                   ((eq op 'copy) "cp -f")
-                   ((eq op 'rename) "mv -f")
-                   (t (tramp-error
-                      vec 'file-error
-                       "Unknown operation `%s', must be `copy' or `rename'"
-                       op)))))
-    (tramp-send-command
-     vec
-     (format "%s %s %s"
-            cmd
-            (tramp-shell-quote-argument localname1)
-            (tramp-shell-quote-argument localname2)))
-    (with-current-buffer (tramp-get-buffer vec)
-      (goto-char (point-min))
-      (unless
-         (or
-          (and (eq op 'copy) keep-date
-               ;; Mask cp -f error.
-               (re-search-forward tramp-operation-not-permitted-regexp nil t))
-          (zerop (tramp-send-command-and-check vec nil)))
-       (tramp-error-with-buffer
-        nil vec 'file-error
-        "Copying directly failed, see buffer `%s' for details."
-        (buffer-name))))
-    ;; Set the mode.
-    ;; CCC: Maybe `chmod --reference=localname1 localname2' could be used
-    ;;      where available?
-    (unless (or (eq op 'rename) keep-date)
-      (set-file-modes
-       (tramp-make-tramp-file-name
-       (tramp-file-name-method vec)
-       (tramp-file-name-user vec)
-       (tramp-file-name-host vec)
-       localname2)
-       (file-modes (tramp-make-tramp-file-name
-                   (tramp-file-name-method vec)
-                   (tramp-file-name-user vec)
-                   (tramp-file-name-host vec)
-                   localname1))))))
+respectively.  FILENAME specifies the file to copy or rename,
+NEWNAME is the name of the new file (for copy) or the new name of
+the file (for rename).  Both files must reside on the same host.
+KEEP-DATE means to make sure that NEWNAME has the same timestamp
+as FILENAME.  PRESERVE-UID-GID, when non-nil, instructs to keep
+the uid and gid from FILENAME."
+  (let ((t1 (tramp-tramp-file-p filename))
+       (t2 (tramp-tramp-file-p newname)))
+    (with-parsed-tramp-file-name (if t1 filename newname) nil
+      (let* ((cmd (cond ((and (eq op 'copy) preserve-uid-gid) "cp -f -p")
+                       ((eq op 'copy) "cp -f")
+                       ((eq op 'rename) "mv -f")
+                       (t (tramp-error
+                           v 'file-error
+                           "Unknown operation `%s', must be `copy' or `rename'"
+                           op))))
+            (localname1
+             (if t1 (tramp-handle-file-remote-p filename 'localname) filename))
+            (localname2
+             (if t2 (tramp-handle-file-remote-p newname 'localname) newname))
+            (prefix (file-remote-p (if t1 filename newname))))
+
+       (cond
+        ;; Both files are on a remote host, with same user.
+        ((and t1 t2)
+         (tramp-send-command
+          v
+          (format "%s %s %s" cmd
+                  (tramp-shell-quote-argument localname1)
+                  (tramp-shell-quote-argument localname2)))
+         (with-current-buffer (tramp-get-buffer v)
+           (goto-char (point-min))
+           (unless
+               (or
+                (and keep-date
+                     ;; Mask cp -f error.
+                     (re-search-forward
+                      tramp-operation-not-permitted-regexp nil t))
+                (zerop (tramp-send-command-and-check v nil)))
+             (tramp-error-with-buffer
+              nil v 'file-error
+              "Copying directly failed, see buffer `%s' for details."
+              (buffer-name)))))
+
+        ;; We are on the local host.
+        ((or t1 t2)
+         (cond
+          ;; We can do it directly.
+          ((and (file-readable-p localname1)
+                (file-writable-p (file-name-directory localname2))
+                (or (file-directory-p localname2)
+                    (file-writable-p localname2)))
+           (if (eq op 'copy)
+               (tramp-compat-copy-file
+                localname1 localname2 ok-if-already-exists
+                keep-date preserve-uid-gid)
+             (rename-file localname1 localname2 ok-if-already-exists)))
+
+          ;; We can do it directly with `tramp-send-command'
+          ((and (file-readable-p (concat prefix localname1))
+                (file-writable-p
+                 (file-name-directory (concat prefix localname2))))
+           (tramp-do-copy-or-rename-file-directly
+            op (concat prefix localname1) (concat prefix localname2)
+            ok-if-already-exists keep-date t)
+           ;; We must change the ownership to the local user.
+           (tramp-set-file-uid-gid
+            (concat prefix localname2)
+            (tramp-get-local-uid 'integer)
+            (tramp-get-local-gid 'integer)))
+
+          ;; We need a temporary file in between.
+          (t
+           ;; Create the temporary file.
+           (let ((tmpfile (tramp-compat-make-temp-file localname1)))
+             (cond
+              (t1
+               (tramp-send-command
+                v (format
+                   "%s %s %s" cmd
+                   (tramp-shell-quote-argument localname1)
+                   (tramp-shell-quote-argument tmpfile)))
+               ;; We must change the ownership as remote user.
+               (tramp-set-file-uid-gid
+                (concat prefix tmpfile)
+                (tramp-get-local-uid 'integer)
+                (tramp-get-local-gid 'integer)))
+              (t2
+               (if (eq op 'copy)
+                   (tramp-compat-copy-file
+                    localname1 tmpfile ok-if-already-exists
+                    keep-date preserve-uid-gid)
+                 (rename-file localname1 tmpfile ok-if-already-exists))
+               ;; We must change the ownership as local user.
+               (tramp-set-file-uid-gid
+                tmpfile
+                (tramp-get-remote-uid v 'integer)
+                (tramp-get-remote-gid v 'integer))))
+
+             ;; Move the temporary file to its destination.
+             (cond
+              (t2
+               (tramp-send-command
+                v (format
+                   "mv -f %s %s"
+                   (tramp-shell-quote-argument tmpfile)
+                   (tramp-shell-quote-argument localname2))))
+              (t1
+               (rename-file tmpfile localname2 ok-if-already-exists)))))))))
+
+      ;; Set the time and mode. Mask possible errors.
+      ;; Won't be applied for 'rename.
+      (condition-case nil
+         (when (and keep-date (not preserve-uid-gid))
+           (set-file-times newname (nth 5 (file-attributes filename)))
+           (set-file-modes newname (file-modes filename)))
+       (error)))))
+
 
 (defun tramp-do-copy-or-rename-file-out-of-band (op filename newname keep-date)
   "Invoke rcp program to copy.
@@ -3046,7 +3210,8 @@ be a local filename.  The method used must be an out-of-band method."
 
       ;; Compose copy command.
       (setq spec `((?h . ,host) (?u . ,user) (?p . ,port)
-                  (?t . ,(tramp-make-tramp-temp-file v))
+                  (?t . ,(tramp-get-connection-property
+                          (tramp-get-connection-process v) "temp-file" ""))
                   (?k . ,(if keep-date " " "")))
            copy-program (tramp-get-method-parameter
                          method 'tramp-copy-program)
@@ -3061,13 +3226,12 @@ be a local filename.  The method used must be an out-of-band method."
                  ;; " " is indication for keep-date argument.
                  x (delete " " (mapcar '(lambda (y) (format-spec y spec)) x)))
                 (unless (member "" x) (mapconcat 'identity x " ")))
-             (tramp-get-method-parameter
-              method 'tramp-copy-args))))
+             (tramp-get-method-parameter method 'tramp-copy-args))))
 
       ;; Check for program.
       (when (and (fboundp 'executable-find)
                 (not (let ((default-directory
-                             (tramp-temporary-file-directory)))
+                             (tramp-compat-temporary-file-directory)))
                        (executable-find copy-program))))
        (tramp-error
         v 'file-error "Cannot find copy program: %s" copy-program))
@@ -3091,7 +3255,7 @@ be a local filename.  The method used must be an out-of-band method."
              ;; set a timeout, because the copying of large files can
              ;; last longer than 60 secs.
              (let ((p (let ((default-directory
-                              (tramp-temporary-file-directory)))
+                              (tramp-compat-temporary-file-directory)))
                         (apply 'start-process
                                (tramp-get-connection-property
                                 v "process-name" nil)
@@ -3112,9 +3276,8 @@ be a local filename.  The method used must be an out-of-band method."
       (tramp-message v 0 "Transferring %s to %s...done" filename newname)
 
       ;; Handle KEEP-DATE argument.
-      (when (and keep-date (not copy-keep-date) (functionp 'set-file-times))
-       (apply 'set-file-times
-              (list newname (nth 5 (file-attributes filename)))))
+      (when (and keep-date (not copy-keep-date))
+       (set-file-times newname (nth 5 (file-attributes filename))))
 
       ;; Set the mode.
       (unless (and keep-date copy-keep-date)
@@ -3131,7 +3294,7 @@ be a local filename.  The method used must be an out-of-band method."
     (save-excursion
       (tramp-barf-unless-okay
        v
-       (format " %s %s"
+       (format "%s %s"
               (if parents "mkdir -p" "mkdir")
               (tramp-shell-quote-argument localname))
        "Couldn't make directory %s" dir))))
@@ -3143,7 +3306,7 @@ be a local filename.  The method used must be an out-of-band method."
     (tramp-flush-directory-property v localname)
     (unless (zerop (tramp-send-command-and-check
                    v
-                   (format "rmdir %s"
+                   (format "rmdir -f %s"
                            (tramp-shell-quote-argument localname))))
       (tramp-error v 'file-error "Couldn't delete %s" directory))))
 
@@ -3161,7 +3324,7 @@ be a local filename.  The method used must be an out-of-band method."
 ;; Dired.
 
 ;; CCC: This does not seem to be enough. Something dies when
-;;      we try and delete two directories under TRAMP :/
+;;      we try and delete two directories under Tramp :/
 (defun tramp-handle-dired-recursive-delete-directory (filename)
   "Recursively delete the directory given.
 This is like `dired-recursive-delete-directory' for Tramp files."
@@ -3174,7 +3337,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
     ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>)
     (tramp-send-command
      v
-     (format "rm -r %s" (tramp-shell-quote-argument localname))
+     (format "rm -rf %s" (tramp-shell-quote-argument localname))
      ;; Don't read the output, do it explicitely.
      nil t)
     ;; Wait for the remote system to return to us...
@@ -3307,7 +3470,7 @@ This is like `dired-recursive-delete-directory' for Tramp files."
                     ""
                   (tramp-shell-quote-argument
                    (file-name-nondirectory localname))))))
-      ;; We cannot use `insert-buffer-substring' because the tramp buffer
+      ;; We cannot use `insert-buffer-substring' because the Tramp buffer
       ;; changes its contents before insertion due to calling
       ;; `expand-file' and alike.
       (insert
@@ -3374,7 +3537,7 @@ the result will be a local, non-Tramp, filename."
              (tramp-send-command v (format "cd %s; pwd" uname))
              (with-current-buffer (tramp-get-buffer v)
                (goto-char (point-min))
-               (buffer-substring (point) (tramp-line-end-position)))))
+               (buffer-substring (point) (tramp-compat-line-end-position)))))
          (setq localname (concat uname fname))))
       ;; There might be a double slash, for example when "~/"
       ;; expands to "/". Remove this.
@@ -3387,7 +3550,7 @@ the result will be a local, non-Tramp, filename."
       ;; bound, because on Windows there would be problems with UNC
       ;; shares or Cygwin mounts.
       (tramp-let-maybe directory-sep-char ?/
-       (let ((default-directory (tramp-temporary-file-directory)))
+       (let ((default-directory (tramp-compat-temporary-file-directory)))
          (tramp-make-tramp-file-name
           method user host
           (tramp-drop-volume-letter
@@ -3415,8 +3578,8 @@ beginning of local filename are not substituted."
       ;; Ignore in LOCALNAME everything before "//" or "/~".
       (when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname))
        (setq filename
-             (tramp-make-tramp-file-name
-              method user host (replace-match "\\1" nil nil localname)))
+             (concat (file-remote-p filename)
+                     (replace-match "\\1" nil nil localname)))
        ;; "/m:h:~" does not work for completion.  We use "/m:h:~/".
        (when (string-match "~$" filename)
          (setq filename (concat filename "/"))))
@@ -3425,7 +3588,7 @@ beginning of local filename are not substituted."
 ;; In XEmacs, electricity is implemented via a key map for ?/ and ?~,
 ;; which calls corresponding functions (see minibuf.el).
 (when (fboundp 'minibuffer-electric-separator)
-  (mapcar
+  (mapc
    '(lambda (x)
       (eval
        `(defadvice ,x
@@ -3446,27 +3609,12 @@ beginning of local filename are not substituted."
      minibuffer-electric-tilde)))
 
 
-;;; Remote commands.
-
-(defsubst tramp-make-temp-file (filename)
-  (concat
-   (funcall (if (fboundp 'make-temp-file) 'make-temp-file 'make-temp-name)
-           (expand-file-name tramp-temp-name-prefix
-                             (tramp-temporary-file-directory)))
-   (file-name-extension filename t)))
-
-(defsubst tramp-make-tramp-temp-file (vec)
-  (format
-   "/tmp/%s%s"
-   tramp-temp-name-prefix
-   (if (get-buffer-process (tramp-get-connection-buffer vec))
-       (process-id (get-buffer-process (tramp-get-connection-buffer vec)))
-     (emacs-pid))))
+;;; Remote commands:
 
 (defun tramp-handle-executable-find (command)
   "Like `executable-find' for Tramp files."
   (with-parsed-tramp-file-name default-directory nil
-    (tramp-find-executable v command tramp-remote-path t)))
+    (tramp-find-executable v command (tramp-get-remote-path v) t)))
 
 ;; We use BUFFER also as connection buffer during setup. Because of
 ;; this, its original contents must be saved, and restored once
@@ -3513,8 +3661,7 @@ beginning of local filename are not substituted."
     (error "Implementation does not handle immediate return"))
 
   (with-parsed-tramp-file-name default-directory nil
-    (let ((temp-name-prefix (tramp-make-tramp-temp-file v))
-         command input stderr outbuf ret)
+    (let (command input tmpinput stderr tmpstderr outbuf ret)
       ;; Compute command.
       (setq command (mapconcat 'tramp-shell-quote-argument
                               (cons program args) " "))
@@ -3526,11 +3673,9 @@ beginning of local filename are not substituted."
            ;; INFILE is on the same remote host.
            (setq input (with-parsed-tramp-file-name infile nil localname))
          ;; INFILE must be copied to remote host.
-         (setq input (concat temp-name-prefix ".in"))
-         (copy-file
-          infile
-          (tramp-make-tramp-file-name method user host input)
-          t)))
+         (setq input (tramp-make-tramp-temp-file v)
+               tmpinput (tramp-make-tramp-file-name method user host input))
+         (copy-file infile tmpinput t)))
       (when input (setq command (format "%s <%s" command input)))
 
       ;; Determine output.
@@ -3548,7 +3693,9 @@ beginning of local filename are not substituted."
         ((bufferp (car destination))
          (setq outbuf (car destination)))
         ((stringp (car destination))
-         (setq outbuf (get-buffer-create (car destination)))))
+         (setq outbuf (get-buffer-create (car destination))))
+        ((car destination)
+         (setq outbuf (current-buffer))))
        ;; stderr
        (cond
         ((stringp (cadr destination))
@@ -3559,7 +3706,9 @@ beginning of local filename are not substituted."
                               (cadr destination) nil localname))
            ;; stderr must be copied to remote host.  The temporary
            ;; file must be deleted after execution.
-           (setq stderr (concat temp-name-prefix ".err"))))
+           (setq stderr (tramp-make-tramp-temp-file v)
+                 tmpstderr (tramp-make-tramp-file-name
+                            method user host stderr))))
         ;; stderr to be discarded
         ((null (cadr destination))
          (setq stderr "/dev/null"))))
@@ -3568,9 +3717,6 @@ beginning of local filename are not substituted."
        (setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; If we have a temporary file, it must be removed after operation.
-      (when (and input (string-match temp-name-prefix input))
-       (setq command (format "%s; rm %s" command input)))
       ;; Goto working directory.
       (tramp-send-command
        v (format "cd %s" (tramp-shell-quote-argument localname)))
@@ -3580,27 +3726,44 @@ beginning of local filename are not substituted."
              (tramp-send-command v command)
            ;; We should show the output anyway.
            (when outbuf
-             (with-current-buffer outbuf
-               (insert-buffer-substring (tramp-get-connection-buffer v)))
+             (let ((output-string
+                    (with-current-buffer (tramp-get-connection-buffer v)
+                      (buffer-substring (point-min) (point-max)))))
+               (with-current-buffer outbuf
+                 (insert output-string)))
              (when display (display-buffer outbuf))))
        ;; When the user did interrupt, we should do it also.
        (error
         (kill-buffer (tramp-get-connection-buffer v))
         (setq ret 1)))
-      (unless ret
-       ;; Check return code.
-       (setq ret (tramp-send-command-and-check v nil))
-       ;; Provide error file.
-       (when (and stderr (string-match temp-name-prefix stderr))
-         (rename-file (tramp-make-tramp-file-name method user host stderr)
-                      (cadr destination) t)))
+
+      ;; Check return code.
+      (unless ret (setq ret (tramp-send-command-and-check v nil)))
+      ;; Provide error file.
+      (when tmpstderr (rename-file tmpstderr (cadr destination) t))
+      ;; Cleanup.
+      (when tmpinput (delete-file tmpinput))
       ;; Return exit status.
       ret)))
 
+(defun tramp-local-call-process
+  (program &optional infile destination display &rest args)
+  "Calls `call-process' on the local host.
+This is needed because for some Emacs flavors Tramp has
+defadviced `call-process' to behave like `process-file'.  The
+Lisp error raised when PROGRAM is nil is trapped also, returning 1."
+  (let ((default-directory
+         (if (file-remote-p default-directory)
+             (tramp-compat-temporary-file-directory)
+           default-directory)))
+    (if (executable-find program)
+       (apply 'call-process program infile destination display args)
+      1)))
+
 (defun tramp-handle-call-process-region
   (start end program &optional delete buffer display &rest args)
   "Like `call-process-region' for Tramp files."
-  (let ((tmpfile (tramp-make-temp-file "")))
+  (let ((tmpfile (tramp-compat-make-temp-file "")))
     (write-region start end tmpfile)
     (when delete (delete-region start end))
     (unwind-protect
@@ -3613,30 +3776,38 @@ beginning of local filename are not substituted."
   (let* ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
         (args (split-string (substring command 0 asynchronous) " "))
         (output-buffer
-         (or output-buffer
-             (if asynchronous
-                 "*Async Shell Command*"
-               "*Shell Command Output*")))
+         (cond
+          ((bufferp output-buffer) output-buffer)
+          ((stringp output-buffer) (get-buffer-create output-buffer))
+          (output-buffer (current-buffer))
+          (t (generate-new-buffer
+              (if asynchronous
+                  "*Async Shell Command*"
+                "*Shell Command Output*")))))
+        (error-buffer
+         (cond
+          ((bufferp error-buffer) error-buffer)
+          ((stringp error-buffer) (get-buffer-create error-buffer))))
         (buffer
-         (if (and (not asynchronous) (bufferp error-buffer))
+         (if (and (not asynchronous) error-buffer)
              (with-parsed-tramp-file-name default-directory nil
                (list output-buffer (tramp-make-tramp-temp-file v)))
            output-buffer)))
 
     (prog1
-       ;; Run the process.  We cannot use `process-file' and
-       ;; `start-file-process', because these functions might not
-       ;; exist in older Emacsen.
+       ;; Run the process.
        (if (integerp asynchronous)
-           (apply 'tramp-handle-start-file-process
-                  "*Async Shell*" buffer args)
-         (apply 'tramp-handle-process-file
-                (car args) nil buffer nil (cdr args)))
+           (apply 'start-file-process "*Async Shell*" buffer args)
+         (apply 'process-file (car args) nil buffer nil (cdr args)))
       ;; Insert error messages if they were separated.
       (when (listp buffer)
-       (with-current-buffer error-buffer
-         (insert-file-contents (cadr buffer)))
-       (delete-file (cadr buffer))))))
+       (with-current-buffer error-buffer (insert-file-contents (cadr buffer)))
+       (delete-file (cadr buffer)))
+      ;; There's some output, display it.
+      (when (with-current-buffer output-buffer (> (point-max) (point-min)))
+       (if (functionp 'display-message-or-buffer)
+           (funcall (symbol-function 'display-message-or-buffer) output-buffer)
+         (pop-to-buffer output-buffer))))))
 
 ;; File Editing.
 
@@ -3645,75 +3816,71 @@ beginning of local filename are not substituted."
 
 (defun tramp-handle-file-local-copy (filename)
   "Like `file-local-copy' for Tramp files."
+
   (with-parsed-tramp-file-name filename nil
-    (let (;; We used to bind the following as late as possible.
-         ;; loc-dec was bound directly before the if statement that
-         ;; checks them.  But the functions tramp-get-* might invoke
-         ;; the "are you awake" check in `tramp-maybe-open-connection',
-         ;; which is an unfortunate time since we rely on the buffer
-         ;; contents at that spot.
-         (rem-enc (tramp-get-remote-coding v "remote-encoding"))
+    (let ((rem-enc (tramp-get-remote-coding v "remote-encoding"))
          (loc-dec (tramp-get-local-coding v "local-decoding"))
-         tmpfil)
+         (tmpfile (tramp-compat-make-temp-file filename)))
       (unless (file-exists-p filename)
        (tramp-error
         v 'file-error
         "Cannot make local copy of non-existing file `%s'" filename))
-      (setq tmpfil (tramp-make-temp-file filename))
-
-      (cond ((and (tramp-method-out-of-band-p v)
-                 (> (nth 7 (file-attributes filename))
-                    tramp-copy-size-limit))
-            ;; `copy-file' handles out-of-band methods
-            (copy-file filename tmpfil t t))
-
-           (rem-enc
-            ;; Use inline encoding for file transfer.
-            (save-excursion
-              (tramp-message v 5 "Encoding remote file %s..." filename)
-              (tramp-barf-unless-okay
-               v
-               (concat rem-enc " < " (tramp-shell-quote-argument localname))
-               "Encoding remote file failed")
-
-              (tramp-message v 5 "Decoding remote file %s..." filename)
-              ;; Here is where loc-dec used to be let-bound.
-              (if (and (symbolp loc-dec) (fboundp loc-dec))
-                  ;; If local decoding is a function, we call it.  We
-                  ;; must disable multibyte, because
-                  ;; `uudecode-decode-region' doesn't handle it
-                  ;; correctly.
-                  (unwind-protect
-                      (with-temp-buffer
-                        (set-buffer-multibyte nil)
-                        (insert-buffer-substring (tramp-get-buffer v))
-                        (tramp-message
-                         v 5 "Decoding remote file %s with function %s..."
-                         filename loc-dec)
-                        (funcall loc-dec (point-min) (point-max))
-                        (let ((coding-system-for-write 'binary))
-                          (write-region (point-min) (point-max) tmpfil))))
-                ;; If tramp-decoding-function is not defined for this
-                ;; method, we invoke tramp-decoding-command instead.
-                (let ((tmpfil2 (tramp-make-temp-file filename)))
-                  (let ((coding-system-for-write 'binary))
-                    (write-region (point-min) (point-max) tmpfil2))
-                  (tramp-message
-                   v 5 "Decoding remote file %s with command %s..."
-                   filename loc-dec)
-                  (tramp-call-local-coding-command
-                   loc-dec tmpfil2 tmpfil)
-                  (delete-file tmpfil2)))
-              (tramp-message v 5 "Decoding remote file %s...done" filename)
-              ;; Set proper permissions.
-              (set-file-modes tmpfil (file-modes filename))))
-
-           (t (tramp-error
-               v 'file-error "Wrong method specification for `%s'" method)))
+
+      (cond
+       ;; `copy-file' handles direct copy and out-of-band methods.
+       ((or (tramp-local-host-p v)
+           (and (tramp-method-out-of-band-p v)
+                (> (nth 7 (file-attributes filename)) tramp-copy-size-limit)))
+       (copy-file filename tmpfile t t))
+
+       ;; Use inline encoding for file transfer.
+       (rem-enc
+       (save-excursion
+         (tramp-message v 5 "Encoding remote file %s..." filename)
+         (tramp-barf-unless-okay
+          v (format "%s < %s" rem-enc (tramp-shell-quote-argument localname))
+          "Encoding remote file failed")
+         (tramp-message v 5 "Encoding remote file %s...done" filename)
+
+         (tramp-message v 5 "Decoding remote file %s..." filename)
+         (if (and (symbolp loc-dec) (fboundp loc-dec))
+             ;; If local decoding is a function, we call it.  We must
+             ;; disable multibyte, because `uudecode-decode-region'
+             ;; doesn't handle it correctly.
+             (unwind-protect
+                 (with-temp-buffer
+                   (set-buffer-multibyte nil)
+                   (insert-buffer-substring (tramp-get-buffer v))
+                   (tramp-message
+                    v 5 "Decoding remote file %s with function %s..."
+                    filename loc-dec)
+                   (funcall loc-dec (point-min) (point-max))
+                   (let ((coding-system-for-write 'binary))
+                     (write-region (point-min) (point-max) tmpfile))))
+           ;; If tramp-decoding-function is not defined for this
+           ;; method, we invoke tramp-decoding-command instead.
+           (let ((tmpfile2 (tramp-compat-make-temp-file filename)))
+             (let ((coding-system-for-write 'binary))
+               (write-region (point-min) (point-max) tmpfile2))
+             (tramp-message
+              v 5 "Decoding remote file %s with command %s..."
+              filename loc-dec)
+             (tramp-call-local-coding-command loc-dec tmpfile2 tmpfile)
+             (delete-file tmpfile2)))
+         (tramp-message v 5 "Decoding remote file %s...done" filename)
+         ;; Set proper permissions.
+         (set-file-modes tmpfile (file-modes filename))
+         ;; Set local user ownership.
+         (tramp-set-file-uid-gid tmpfile)))
+
+       ;; Oops, I don't know what to do.
+       (t (tramp-error
+          v 'file-error "Wrong method specification for `%s'" method)))
+
       (run-hooks 'tramp-handle-file-local-copy-hook)
-      tmpfil)))
+      tmpfile)))
 
-(defun tramp-handle-file-remote-p (file &optional identification connected)
+(defun tramp-handle-file-remote-p (filename &optional identification connected)
   "Like `file-remote-p' for Tramp files."
   (when (tramp-tramp-file-p filename)
     (with-parsed-tramp-file-name filename nil
@@ -3724,6 +3891,7 @@ beginning of local filename are not substituted."
            ((eq identification 'method) method)
            ((eq identification 'user) user)
            ((eq identification 'host) host)
+           ((eq identification 'localname) localname)
            (t (tramp-make-tramp-file-name method user host "")))))))
 
 (defun tramp-handle-insert-file-contents
@@ -3731,42 +3899,73 @@ beginning of local filename are not substituted."
   "Like `insert-file-contents' for Tramp files."
   (barf-if-buffer-read-only)
   (setq filename (expand-file-name filename))
-  (with-parsed-tramp-file-name filename nil
-    (if (not (file-exists-p filename))
-       (progn
-         (when visit
-           (setq buffer-file-name filename)
-           (set-visited-file-modtime)
-           (set-buffer-modified-p nil))
-         (tramp-error
-          v 'file-error "File %s not found on remote host" filename)
-         (list (expand-file-name filename) 0))
-      ;; `insert-file-contents-literally' takes care to avoid calling
-      ;; jka-compr.  By let-binding inhibit-file-name-operation, we
-      ;; propagate that care to the file-local-copy operation.
-      (let ((local-copy
-            (let ((inhibit-file-name-operation
-                   (when (eq inhibit-file-name-operation
-                             'insert-file-contents)
-                     'file-local-copy)))
-              (file-local-copy filename)))
-           coding-system-used result)
-       (tramp-message v 4 "Inserting local temp file `%s'..." local-copy)
-       (setq result (insert-file-contents local-copy nil beg end replace))
+  (let (coding-system-used result)
+    (with-parsed-tramp-file-name filename nil
+
+      (if (not (file-exists-p filename))
+         (progn
+           (when visit
+             (setq buffer-file-name filename)
+             (set-visited-file-modtime)
+             (set-buffer-modified-p nil))
+           ;; We don't raise a Tramp error, because it might be
+           ;; suppressed, like in `find-file-noselect-1'.
+           (signal 'file-error (list "File not found on remote host" filename))
+           (list (expand-file-name filename) 0))
+
+       (if (and (tramp-local-host-p v)
+                (file-readable-p localname))
+           ;; Short track: if we are on the local host, we can run directly.
+           (setq result (insert-file-contents localname visit beg end replace))
+
+         ;; `insert-file-contents-literally' takes care to avoid calling
+         ;; jka-compr.  By let-binding inhibit-file-name-operation, we
+         ;; propagate that care to the file-local-copy operation.
+         (let ((local-copy
+                (let ((inhibit-file-name-operation
+                       (when (eq inhibit-file-name-operation
+                                 'insert-file-contents)
+                         'file-local-copy)))
+                  (file-local-copy filename))))
+           (tramp-message v 4 "Inserting local temp file `%s'..." local-copy)
+           (setq result (insert-file-contents local-copy nil beg end replace))
+           ;; Now `last-coding-system-used' has right value.  Remember it.
+           (when (boundp 'last-coding-system-used)
+             (setq coding-system-used (symbol-value 'last-coding-system-used)))
+           (tramp-message v 4 "Inserting local temp file `%s'...done" local-copy)
+           (delete-file local-copy)
+           (when (boundp 'last-coding-system-used)
+             (set 'last-coding-system-used coding-system-used))))
+
        (when visit
+         (setq buffer-read-only (file-writable-p filename))
          (setq buffer-file-name filename)
          (set-visited-file-modtime)
          (set-buffer-modified-p nil))
-       ;; Now `last-coding-system-used' has right value.  Remember it.
-       (when (boundp 'last-coding-system-used)
-         (setq coding-system-used (symbol-value 'last-coding-system-used)))
-       (tramp-message v 4 "Inserting local temp file `%s'...done" local-copy)
-       (delete-file local-copy)
-       (when (boundp 'last-coding-system-used)
-         (set 'last-coding-system-used coding-system-used))
        (list (expand-file-name filename)
              (cadr result))))))
 
+;; This is needed for XEmacs only.  Code stolen from files.el.
+(defun tramp-handle-insert-file-contents-literally
+  (filename &optional visit beg end replace)
+  "Like `insert-file-contents-literally' for Tramp files."
+  (let ((format-alist nil)
+       (after-insert-file-functions nil)
+       (coding-system-for-read 'no-conversion)
+       (coding-system-for-write 'no-conversion)
+       (find-buffer-file-type-function
+        (if (fboundp 'find-buffer-file-type)
+            (symbol-function 'find-buffer-file-type)
+          nil))
+       (inhibit-file-name-handlers '(jka-compr-handler image-file-handler))
+       (inhibit-file-name-operation 'insert-file-contents))
+    (unwind-protect
+       (progn
+         (fset 'find-buffer-file-type (lambda (filename) t))
+         (insert-file-contents filename visit beg end replace))
+      (if find-buffer-file-type-function
+         (fset 'find-buffer-file-type find-buffer-file-type-function)
+       (fmakunbound 'find-buffer-file-type)))))
 
 (defun tramp-handle-find-backup-file-name (filename)
   "Like `find-backup-file-name' for Tramp files."
@@ -3827,13 +4026,13 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
     ;; UNIQUIFY element of `auto-save-file-name-transforms'); but for
     ;; all other cases we must do it ourselves.
     (when (boundp 'auto-save-file-name-transforms)
-      (mapcar
+      (mapc
        '(lambda (x)
          (when (and (string-match (car x) buffer-file-name)
                     (not (car (cddr x))))
            (setq tramp-auto-save-directory
                  (or tramp-auto-save-directory
-                     (tramp-temporary-file-directory)))))
+                     (tramp-compat-temporary-file-directory)))))
        (symbol-value 'auto-save-file-name-transforms)))
     ;; Create directory.
     (when tramp-auto-save-directory
@@ -3873,154 +4072,181 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file."
     ;;              (string= lockname filename))
     ;;    (error
     ;;     "tramp-handle-write-region: LOCKNAME must be nil or equal FILENAME"))
-    ;; XEmacs takes a coding system as the seventh argument, not `confirm'
+
+    ;; XEmacs takes a coding system as the seventh argument, not `confirm'.
     (when (and (not (featurep 'xemacs)) confirm (file-exists-p filename))
       (unless (y-or-n-p (format "File %s exists; overwrite anyway? " filename))
        (tramp-error v 'file-error "File not overwritten")))
-    (let ((rem-dec (tramp-get-remote-coding v "remote-decoding"))
-         (loc-enc (tramp-get-local-coding v "local-encoding"))
-         (modes (save-excursion (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.
-         (tmpfil (tramp-make-temp-file filename)))
-      ;; We say `no-message' here because we don't want the visited file
-      ;; modtime data to be clobbered from the temp file.  We call
-      ;; `set-visited-file-modtime' ourselves later on.
-      (tramp-run-real-handler
-       'write-region
-       (if confirm ; don't pass this arg unless defined for backward compat.
-          (list start end tmpfil append 'no-message lockname confirm)
-        (list start end tmpfil append 'no-message lockname)))
-      ;; Now, `last-coding-system-used' has the right value.  Remember it.
-      (when (boundp 'last-coding-system-used)
-       (setq coding-system-used (symbol-value 'last-coding-system-used)))
-      ;; The permissions of the temporary file should be set.  If
-      ;; filename does not exist (eq modes nil) it has been renamed to
-      ;; the backup file.  This case `save-buffer' handles
-      ;; permissions.
-      (when modes (set-file-modes tmpfil modes))
-      ;; This is a bit lengthy due to the different methods possible for
-      ;; file transfer.  First, we check whether the method uses an rcp
-      ;; program.  If so, we call it.  Otherwise, both encoding and
-      ;; decoding command must be specified.  However, if the method
-      ;; _also_ specifies an encoding function, then that is used for
-      ;; encoding the contents of the tmp file.
-      (cond ((and (tramp-method-out-of-band-p v)
-                 (integerp start)
-                 (> (- end start) tramp-copy-size-limit))
-            ;; `copy-file' handles out-of-band methods
-            (copy-file tmpfil filename t t))
-
-           (rem-dec
-            ;; Use inline file transfer
-            ;; Encode tmpfil
-            (tramp-message v 5 "Encoding region...")
-            (unwind-protect
-                (with-temp-buffer
-                  ;; Use encoding function or command.
-                  (if (and (symbolp loc-enc) (fboundp loc-enc))
-                      (progn
-                        (tramp-message
-                         v 5 "Encoding region using function `%s'..."
-                         (symbol-name loc-enc))
-                        (let ((coding-system-for-read 'binary))
-                          (insert-file-contents-literally tmpfil))
-                        ;; CCC.  The following `let' is a workaround for
-                        ;; the base64.el that comes with pgnus-0.84.  If
-                        ;; both of the following conditions are
-                        ;; satisfied, it tries to write to a local file
-                        ;; in default-directory, but at this point,
-                        ;; default-directory is remote.
-                        ;; (CALL-PROCESS-REGION can't write to remote
-                        ;; files, it seems.)  The file in question is a
-                        ;; tmp file anyway.
-                        (let ((default-directory
-                                (tramp-temporary-file-directory)))
-                          (funcall loc-enc (point-min) (point-max))))
-
-                    (tramp-message
-                     v 5 "Encoding region using command `%s'..." loc-enc)
-                    (unless (equal 0 (tramp-call-local-coding-command
-                                      loc-enc tmpfil t))
-                      (tramp-error
-                       v 'file-error
-                       (concat "Cannot write to `%s', local encoding"
-                               " command `%s' failed")
-                       filename loc-enc)))
-
-                  ;; Send buffer into remote decoding command which
-                  ;; writes to remote file.  Because this happens on the
-                  ;; remote host, we cannot use the function.
-                  (goto-char (point-max))
-                  (unless (bolp) (newline))
-                  (tramp-message
-                   v 5 "Decoding region into remote file %s..." filename)
-                  (tramp-send-command
-                   v
-                   (format
-                    "%s >%s <<'EOF'\n%sEOF"
-                    rem-dec
-                    (tramp-shell-quote-argument localname)
-                    (buffer-string)))
-                  (tramp-barf-unless-okay
-                   v nil
-                   (concat "Couldn't write region to `%s',"
-                           " decode using `%s' failed")
-                   filename rem-dec)
-                  ;; When `file-precious-flag' is set, the region is
-                  ;; written to a temporary file.  Check that the
-                  ;; checksum is equal to that from the local tmpfil.
-                  (when file-precious-flag
-                    (erase-buffer)
-                    (and
-                     ;; cksum runs locally
-                     (let ((default-directory
-                             (tramp-temporary-file-directory)))
-                       (zerop (call-process "cksum" tmpfil t)))
-                     ;; cksum runs remotely
-                     (zerop
-                      (tramp-send-command-and-check
-                       v
-                       (format
-                        "cksum <%s"
-                        (tramp-shell-quote-argument localname))))
-                     ;; ... they are different
-                     (not
-                      (string-equal
-                       (buffer-string)
-                       (with-current-buffer (tramp-get-buffer v)
-                         (buffer-string))))
+
+    (let ((uid (or (nth 2 (tramp-compat-file-attributes filename 'integer))
+                  (tramp-get-remote-uid v 'integer)))
+         (gid (or (nth 3 (tramp-compat-file-attributes filename 'integer))
+                  (tramp-get-remote-gid v 'integer))))
+
+      (if (and (tramp-local-host-p v)
+              (file-writable-p (file-name-directory localname))
+              (or (file-directory-p localname)
+                  (file-writable-p localname)))
+         ;; Short track: if we are on the local host, we can run directly.
+         (write-region start end localname append 'no-message lockname confirm)
+
+       (let ((rem-dec (tramp-get-remote-coding v "remote-decoding"))
+             (loc-enc (tramp-get-local-coding v "local-encoding"))
+             (modes (save-excursion (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 (tramp-compat-make-temp-file filename)))
+
+         ;; We say `no-message' here because we don't want the
+         ;; visited file modtime data to be clobbered from the temp
+         ;; file.  We call `set-visited-file-modtime' ourselves later
+         ;; on.
+         (tramp-run-real-handler
+          'write-region
+          (list start end tmpfile append 'no-message lockname confirm))
+         ;; Now, `last-coding-system-used' has the right value.  Remember it.
+         (when (boundp 'last-coding-system-used)
+           (setq coding-system-used (symbol-value 'last-coding-system-used)))
+         ;; The permissions of the temporary file should be set.  If
+         ;; filename does not exist (eq modes nil) it has been
+         ;; renamed to the backup file.  This case `save-buffer'
+         ;; handles permissions.
+         (when modes (set-file-modes tmpfile modes))
+
+         ;; This is a bit lengthy due to the different methods
+         ;; possible for file transfer.  First, we check whether the
+         ;; method uses an rcp program.  If so, we call it.
+         ;; Otherwise, both encoding and decoding command must be
+         ;; specified.  However, if the method _also_ specifies an
+         ;; encoding function, then that is used for encoding the
+         ;; contents of the tmp file.
+         (cond
+          ;; `rename-file' handles direct copy and out-of-band methods.
+          ((or (tramp-local-host-p v)
+               (and (tramp-method-out-of-band-p v)
+                    (integerp start)
+                    (> (- end start) tramp-copy-size-limit)))
+           (rename-file tmpfile filename t))
+
+          ;; Use inline file transfer
+          (rem-dec
+           ;; Encode tmpfile
+           (tramp-message v 5 "Encoding region...")
+           (unwind-protect
+               (with-temp-buffer
+                 ;; Use encoding function or command.
+                 (if (and (symbolp loc-enc) (fboundp loc-enc))
+                     (progn
+                       (tramp-message
+                        v 5 "Encoding region using function `%s'..."
+                        (symbol-name loc-enc))
+                       (let ((coding-system-for-read 'binary))
+                         (insert-file-contents-literally tmpfile))
+                       ;; CCC.  The following `let' is a workaround
+                       ;; for the base64.el that comes with
+                       ;; pgnus-0.84.  If both of the following
+                       ;; conditions are satisfied, it tries to write
+                       ;; to a local file in default-directory, but
+                       ;; at this point, default-directory is remote.
+                       ;; (CALL-PROCESS-REGION can't write to remote
+                       ;; files, it seems.)  The file in question is
+                       ;; a tmp file anyway.
+                       (let ((default-directory
+                               (tramp-compat-temporary-file-directory)))
+                         (funcall loc-enc (point-min) (point-max))))
+
+                   (tramp-message
+                    v 5 "Encoding region using command `%s'..." loc-enc)
+                   (unless (equal 0 (tramp-call-local-coding-command
+                                     loc-enc tmpfile t))
                      (tramp-error
                       v 'file-error
-                      (concat "Couldn't write region to `%s',"
-                              " decode using `%s' failed")
-                      filename rem-dec)))
-                  (tramp-message
-                   v 5 "Decoding region into remote file %s...done" filename)
-                  (tramp-flush-file-property v localname))))
-           (t
-            (tramp-error
-             v 'file-error
-             (concat "Method `%s' should specify both encoding and "
-                     "decoding command or an rcp program")
-             method)))
-      (delete-file tmpfil)
+                      "Cannot write to `%s', local encoding command `%s' failed"
+                      filename loc-enc)))
+
+                 ;; Send buffer into remote decoding command which
+                 ;; writes to remote file.  Because this happens on
+                 ;; the remote host, we cannot use the function.
+                 (goto-char (point-max))
+                 (unless (bolp) (newline))
+                 (tramp-message
+                  v 5 "Decoding region into remote file %s..." filename)
+                 (tramp-send-command
+                  v
+                  (format
+                   "%s >%s <<'EOF'\n%sEOF"
+                   rem-dec
+                   (tramp-shell-quote-argument localname)
+                   (buffer-string)))
+                 (tramp-barf-unless-okay
+                  v nil
+                  "Couldn't write region to `%s', decode using `%s' failed"
+                  filename rem-dec)
+                 ;; When `file-precious-flag' is set, the region is
+                 ;; written to a temporary file.  Check that the
+                 ;; checksum is equal to that from the local tmpfile.
+                 (when file-precious-flag
+                   (erase-buffer)
+                   (and
+                    ;; cksum runs locally, if possible.
+                    (zerop (tramp-local-call-process "cksum" tmpfile t))
+                    ;; cksum runs remotely.
+                    (zerop
+                     (tramp-send-command-and-check
+                      v
+                      (format
+                       "cksum <%s" (tramp-shell-quote-argument localname))))
+                    ;; ... they are different.
+                    (not
+                     (string-equal
+                      (buffer-string)
+                      (with-current-buffer (tramp-get-buffer v)
+                        (buffer-string))))
+                    (tramp-error
+                     v 'file-error
+                     (concat "Couldn't write region to `%s',"
+                             " decode using `%s' failed")
+                     filename rem-dec)))
+                 (tramp-message
+                  v 5 "Decoding region into remote file %s...done" filename)
+                 (tramp-flush-file-property v localname))
+
+             ;; Save exit.
+             (delete-file tmpfile)))
+
+          ;; That's not expected.
+          (t
+           (tramp-error
+            v 'file-error
+            (concat "Method `%s' should specify both encoding and "
+                    "decoding command or an rcp program")
+            method)))
+
+         ;; Make `last-coding-system-used' have the right value.
+         (when coding-system-used
+           (set 'last-coding-system-used coding-system-used))))
+
+      ;; Set file modification time.
       (when (or (eq visit t) (stringp visit))
        (set-visited-file-modtime
-        ;; We must pass modtime explicitely, because filename can be different
-        ;; from (buffer-file-name), f.e. if `file-precious-flag' is set.
+        ;; We must pass modtime explicitely, because filename can
+        ;; be different from (buffer-file-name), f.e. if
+        ;; `file-precious-flag' is set.
         (nth 5 (file-attributes filename))))
-      ;; Make `last-coding-system-used' have the right value.
-      (when (boundp 'last-coding-system-used)
-       (set 'last-coding-system-used coding-system-used))
+
+      ;; Set the ownership.
+      (tramp-set-file-uid-gid filename uid gid)
       (when (or (eq visit t) (null visit) (stringp visit))
        (tramp-message v 0 "Wrote %s" filename))
       (run-hooks 'tramp-handle-write-region-hook))))
@@ -4116,7 +4342,7 @@ ARGS are the arguments OPERATION has been called with."
    ; BUF
    ((member operation
            (list 'set-visited-file-modtime 'verify-visited-file-modtime
-                  ; Emacs 22 only
+                  ; since Emacs 22 only
                  'make-auto-save-file-name
                  ; XEmacs only
                  'backup-buffer))
@@ -4142,29 +4368,33 @@ ARGS are the arguments OPERATION has been called with."
 
 (defun tramp-find-foreign-file-name-handler (filename)
   "Return foreign file name handler if exists."
-  (when (and (stringp filename) (tramp-tramp-file-p filename)
-            (or (not (tramp-completion-mode))
-                (not (string-match
-                      tramp-completion-file-name-regexp filename))))
-    (let (elt
-         res
-         (handler-alist tramp-foreign-file-name-handler-alist))
-      (while handler-alist
-       (setq elt (car handler-alist)
-             handler-alist (cdr handler-alist))
-       (when (funcall (car elt) filename)
-         (setq handler-alist nil)
-         (setq res (cdr elt))))
-      res)))
+  (when (and (stringp filename) (tramp-tramp-file-p filename))
+    (let ((v (tramp-dissect-file-name filename t))
+         (handler tramp-foreign-file-name-handler-alist)
+         elt res)
+      ;; When we are not fully sure that filename completion is safe,
+      ;; we should not return a handler.
+      (when (or (tramp-file-name-method v) (tramp-file-name-user v)
+               (and (tramp-file-name-host v)
+                    (not (member (tramp-file-name-host v)
+                                 (mapcar 'car tramp-methods))))
+               (not (tramp-completion-mode-p)))
+       (while handler
+         (setq elt (car handler)
+               handler (cdr handler))
+         (when (funcall (car elt) filename)
+           (setq handler nil
+                 res (cdr elt))))
+       res))))
 
 ;; Main function.
 ;;;###autoload
 (defun tramp-file-name-handler (operation &rest args)
   "Invoke Tramp file name handler.
-Falls back to normal file name handler if no tramp file name handler exists."
+Falls back to normal file name handler if no Tramp file name handler exists."
   (save-match-data
     (let* ((filename (apply 'tramp-file-name-for-operation operation args))
-          (completion (tramp-completion-mode))
+          (completion (tramp-completion-mode-p))
           (foreign (tramp-find-foreign-file-name-handler filename)))
       (with-parsed-tramp-file-name filename nil
        (cond
@@ -4227,8 +4457,8 @@ Fall back to normal file name handler if no Tramp handler exists."
 
 ;;;###autoload
 (progn (defun tramp-completion-file-name-handler (operation &rest args)
-  "Invoke tramp file name completion handler.
-Falls back to normal file name handler if no tramp file name handler exists."
+  "Invoke Tramp file name completion handler.
+Falls back to normal file name handler if no Tramp file name handler exists."
 ;;  (setq edebug-trace t)
 ;;  (edebug-trace "%s" (with-output-to-string (backtrace)))
 
@@ -4243,7 +4473,7 @@ Falls back to normal file name handler if no tramp file name handler exists."
 
 ;;;###autoload
 (defsubst tramp-register-file-name-handler ()
-  "Add tramp file name handler to `file-name-handler-alist'."
+  "Add Tramp file name handler to `file-name-handler-alist'."
   ;; Remove autoloaded handler from file name handler alist.  Useful,
   ;; if `tramp-syntax' has been changed.
   (let ((a1 (rassq 'tramp-file-name-handler file-name-handler-alist)))
@@ -4266,7 +4496,7 @@ Falls back to normal file name handler if no tramp file name handler exists."
 
 ;;;###autoload
 (defsubst tramp-register-completion-file-name-handler ()
-  "Add tramp completion file name handler to `file-name-handler-alist'."
+  "Add Tramp completion file name handler to `file-name-handler-alist'."
   ;; Remove autoloaded handler from file name handler alist.  Useful,
   ;; if `tramp-syntax' has been changed.
   (let ((a1 (rassq
@@ -4275,9 +4505,12 @@ Falls back to normal file name handler if no tramp file name handler exists."
   ;; `partial-completion-mode' is unknown in XEmacs.  So we should
   ;; load it unconditionally there.  In the GNU Emacs case, method/
   ;; user/host name completion shall be bound to `partial-completion-mode'.
+  ;; `ido-mode' and `icy-mode' are other packages which extend file
+  ;; name completion.
   (when (or (not (boundp 'partial-completion-mode))
            (symbol-value 'partial-completion-mode)
-           (featurep 'ido))
+           (featurep 'ido)
+           (featurep 'icicles))
     (add-to-list 'file-name-handler-alist
                 (cons tramp-completion-file-name-regexp
                       'tramp-completion-file-name-handler))
@@ -4308,63 +4541,15 @@ Falls back to normal file name handler if no tramp file name handler exists."
 
 (add-hook 'tramp-unload-hook 'tramp-unload-file-name-handlers)
 
-;;; Interactions with other packages:
-
-;; -- complete.el --
+;;; File name handler functions for completion mode:
 
-;; This function contributed by Ed Sabol
-(defun tramp-handle-expand-many-files (name)
-  "Like `PC-expand-many-files' for Tramp files."
-  (with-parsed-tramp-file-name name nil
-    (save-match-data
-      (if (or (string-match "\\*" name)
-             (string-match "\\?" name)
-             (string-match "\\[.*\\]" name))
-         (progn
-           (let (bufstr)
-             ;; CCC: To do it right, we should quote certain characters
-             ;; in the file name, but since the echo command is going to
-             ;; break anyway when there are spaces in the file names, we
-             ;; don't bother.
-             ;;-(let ((comint-file-name-quote-list
-             ;;-       (set-difference tramp-file-name-quote-list
-             ;;-                       '(?\* ?\? ?[ ?]))))
-             ;;-  (tramp-send-command
-             ;;-   method user host
-             ;;-   (format "echo %s" (comint-quote-filename localname))))
-             (tramp-send-command v (format "echo %s" localname))
-             (setq bufstr (buffer-substring (point-min)
-                                            (tramp-line-end-position)))
-             (with-current-buffer (tramp-get-buffer v)
-               (goto-char (point-min))
-               (if (string-equal localname bufstr)
-                   nil
-                 (insert "(\"")
-                 (while (search-forward " " nil t)
-                   (delete-backward-char 1)
-                   (insert "\" \""))
-                 (goto-char (point-max))
-                 (delete-backward-char 1)
-                 (insert "\")")
-                 (goto-char (point-min))
-                 (mapcar
-                  (function (lambda (x)
-                              (tramp-make-tramp-file-name method user host x)))
-                  (read (current-buffer)))))))
-       (list (expand-file-name name))))))
-
-(eval-after-load "complete"
-  '(progn
-     (defadvice PC-expand-many-files
-       (around tramp-advice-PC-expand-many-files (name) activate)
-       "Invoke `tramp-handle-expand-many-files' for Tramp files."
-       (if (tramp-tramp-file-p name)
-          (setq ad-return-value (tramp-handle-expand-many-files name))
-        ad-do-it))
-     (add-hook 'tramp-unload-hook
-              '(lambda () (ad-unadvise 'PC-expand-many-files)))))
+(defvar tramp-completion-mode nil
+  "If non-nil, external packages signal that they are in file name completion.
 
-;;; File name handler functions for completion mode
+This is necessary, because Tramp uses a heuristic depending on last
+input event.  This fails when external packages use other characters
+but <TAB>, <SPACE> or ?\\? for file name completion.  This variable
+should never be set globally, the intention is to let-bind it.")
 
 ;; Necessary because `tramp-file-name-regexp-unified' and
 ;; `tramp-completion-file-name-regexp-unified' aren't different.  If
@@ -4374,38 +4559,41 @@ Falls back to normal file name handler if no tramp file name handler exists."
 ;; risky, because completing a file might require loading other files,
 ;; like "~/.netrc", and for them it shouldn't be decided based on that
 ;; variable. On the other hand, those files shouldn't have partial
-;; tramp file name syntax. Maybe another variable should be introduced
-;; overwriting this check in such cases. Or we change tramp file name
+;; Tramp file name syntax. Maybe another variable should be introduced
+;; overwriting this check in such cases. Or we change Tramp file name
 ;; syntax in order to avoid ambiguities, like in XEmacs ...
-(defun tramp-completion-mode ()
+(defun tramp-completion-mode-p ()
   "Checks whether method / user name / host name completion is active."
-  (or (equal last-input-event 'tab)
-      ;; Emacs
-      (and (natnump last-input-event)
-          (or
-           ;; ?\t has event-modifier 'control
-           (char-equal last-input-event ?\t)
-           (and (not (event-modifiers last-input-event))
-                (or (char-equal last-input-event ?\?)
-                    (char-equal last-input-event ?\ )))))
-      ;; XEmacs
-      (and (featurep 'xemacs)
-          ;; `last-input-event' might be nil.
-          (not (null last-input-event))
-          ;; `last-input-event' may have no character approximation.
-          (funcall (symbol-function 'event-to-character) last-input-event)
-          (or
-           ;; ?\t has event-modifier 'control
-           (char-equal
-            (funcall (symbol-function 'event-to-character)
-                     last-input-event) ?\t)
-           (and (not (event-modifiers last-input-event))
-                (or (char-equal
-                     (funcall (symbol-function 'event-to-character)
-                              last-input-event) ?\?)
-                    (char-equal
-                     (funcall (symbol-function 'event-to-character)
-                              last-input-event) ?\ )))))))
+  (or
+   ;; Signal from outside.
+   tramp-completion-mode
+   ;; Emacs.
+   (equal last-input-event 'tab)
+   (and (natnump last-input-event)
+       (or
+        ;; ?\t has event-modifier 'control.
+        (char-equal last-input-event ?\t)
+        (and (not (event-modifiers last-input-event))
+             (or (char-equal last-input-event ?\?)
+                 (char-equal last-input-event ?\ )))))
+   ;; XEmacs.
+   (and (featurep 'xemacs)
+       ;; `last-input-event' might be nil.
+       (not (null last-input-event))
+       ;; `last-input-event' may have no character approximation.
+       (funcall (symbol-function 'event-to-character) last-input-event)
+       (or
+        ;; ?\t has event-modifier 'control.
+        (char-equal
+         (funcall (symbol-function 'event-to-character)
+                  last-input-event) ?\t)
+        (and (not (event-modifiers last-input-event))
+             (or (char-equal
+                  (funcall (symbol-function 'event-to-character)
+                           last-input-event) ?\?)
+                 (char-equal
+                  (funcall (symbol-function 'event-to-character)
+                           last-input-event) ?\ )))))))
 
 ;; Method, host name and user name completion.
 ;; `tramp-completion-dissect-file-name' returns a list of
@@ -4436,19 +4624,20 @@ Falls back to normal file name handler if no tramp file name handler exists."
 
              ;; Method dependent user / host combinations.
              (progn
-               (mapcar
+               (mapc
                 (lambda (x)
                   (setq all-user-hosts
                         (append all-user-hosts
                                 (funcall (nth 0 x) (nth 1 x)))))
                 (tramp-get-completion-function m))
 
-               (setq result (append result
-                 (mapcar
-                  (lambda (x)
-                    (tramp-get-completion-user-host
-                     method user host (nth 0 x) (nth 1 x)))
-                  (delq nil all-user-hosts)))))
+               (setq result
+                     (append result
+                             (mapcar
+                              (lambda (x)
+                                (tramp-get-completion-user-host
+                                 method user host (nth 0 x) (nth 1 x)))
+                              (delq nil all-user-hosts)))))
 
            ;; Possible methods.
            (setq result
@@ -4575,7 +4764,7 @@ They are collected by `tramp-completion-dissect-file-name1'."
             (concat tramp-prefix-regexp "/$"))
           1 nil 3 nil)))
 
-    (mapcar (lambda (regexp)
+    (mapc (lambda (regexp)
       (add-to-list 'result
        (tramp-completion-dissect-file-name1 regexp name)))
       (list
@@ -4657,7 +4846,7 @@ PARTIAL-USER must match USER, PARTIAL-HOST must match HOST."
 Either user or host may be nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (when (file-readable-p filename)
       (with-temp-buffer
@@ -4675,7 +4864,7 @@ Either user or host may be nil."
          (concat
           "^\\(" tramp-host-regexp "\\)"
           "\\([ \t]+" "\\(" tramp-user-regexp "\\)" "\\)?")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (append (list (match-string 3) (match-string 1)))))
      (widen)
@@ -4687,7 +4876,7 @@ Either user or host may be nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (when (file-readable-p filename)
       (with-temp-buffer
@@ -4702,7 +4891,7 @@ User is always nil."
 User is always nil."
    (let ((result)
         (regexp (concat "^\\(" tramp-host-regexp "\\)")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (list nil (match-string 1))))
      (widen)
@@ -4716,7 +4905,7 @@ User is always nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (when (file-readable-p filename)
       (with-temp-buffer
@@ -4731,7 +4920,7 @@ User is always nil."
 User is always nil."
    (let ((result)
         (regexp (concat "^[ \t]*Host[ \t]+" "\\(" tramp-host-regexp "\\)")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (list nil (match-string 1))))
      (widen)
@@ -4745,7 +4934,7 @@ User is always nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let* ((default-directory (tramp-temporary-file-directory))
+  (let* ((default-directory (tramp-compat-temporary-file-directory))
         (regexp (concat "^key_[0-9]+_\\(" tramp-host-regexp "\\)\\.pub$"))
         (files (when (file-directory-p dirname) (directory-files dirname)))
         result)
@@ -4760,7 +4949,7 @@ User is always nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let* ((default-directory (tramp-temporary-file-directory))
+  (let* ((default-directory (tramp-compat-temporary-file-directory))
         (regexp (concat "^\\(" tramp-host-regexp
                         "\\)\\.ssh-\\(dss\\|rsa\\)\\.pub$"))
         (files (when (file-directory-p dirname) (directory-files dirname)))
@@ -4776,7 +4965,7 @@ User is always nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (when (file-readable-p filename)
       (with-temp-buffer
@@ -4791,7 +4980,7 @@ User is always nil."
 User is always nil."
    (let ((result)
         (regexp (concat "^\\(" tramp-host-regexp "\\)")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (unless (char-equal (or (char-after) ?\n) ?:) ; no IPv6
         (setq result (list nil (match-string 1)))))
@@ -4810,7 +4999,7 @@ User is always nil."
 Host is always \"localhost\"."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (if (zerop (length tramp-current-user))
        '(("root" nil))
@@ -4827,7 +5016,7 @@ Host is always \"localhost\"."
 Host is always \"localhost\"."
    (let ((result)
         (regexp (concat "^\\(" tramp-user-regexp "\\):")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (list (match-string 1) "localhost")))
      (widen)
@@ -4839,7 +5028,7 @@ Host is always \"localhost\"."
 User may be nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (when (file-readable-p filename)
       (with-temp-buffer
@@ -4857,7 +5046,7 @@ User may be nil."
          (concat
           "^[ \t]*machine[ \t]+" "\\(" tramp-host-regexp "\\)"
           "\\([ \t]+login[ \t]+" "\\(" tramp-user-regexp "\\)" "\\)?")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (list (match-string 3) (match-string 1))))
      (widen)
@@ -4869,10 +5058,10 @@ User may be nil."
 User is always nil."
   ;; On Windows, there are problems in completion when
   ;; `default-directory' is remote.
-  (let ((default-directory (tramp-temporary-file-directory))
+  (let ((default-directory (tramp-compat-temporary-file-directory))
        res)
     (with-temp-buffer
-      (when (zerop (call-process "reg" nil t nil "query" registry))
+      (when (zerop (tramp-local-call-process "reg" nil t nil "query" registry))
        (goto-char (point-min))
        (while (not (eobp))
          (push (tramp-parse-putty-group registry) res))))
@@ -4883,7 +5072,7 @@ User is always nil."
 User is always nil."
    (let ((result)
         (regexp (concat (regexp-quote registry) "\\\\\\(.+\\)")))
-     (narrow-to-region (point) (tramp-line-end-position))
+     (narrow-to-region (point) (tramp-compat-line-end-position))
      (when (re-search-forward regexp nil t)
        (setq result (list nil (match-string 1))))
      (widen)
@@ -4897,7 +5086,7 @@ User is always nil."
 Only send the definition if it has not already been done."
   (let* ((p (tramp-get-connection-process vec))
         (scripts (tramp-get-connection-property p "scripts" nil)))
-    (unless (memq name scripts)
+    (unless (member name scripts)
       (tramp-message vec 5 "Sending script `%s'..." name)
       ;; The script could contain a call of Perl.  This is masked with `%s'.
       (tramp-send-command-and-check
@@ -5006,17 +5195,17 @@ from the default one."
       (get-buffer-create (tramp-debug-buffer-name vec))
     (when (bobp)
       (setq buffer-undo-list t)
-      ;; Activate outline-mode
-      (make-local-variable 'outline-regexp)
-      (make-local-variable 'outline-level)
-      ;; This runs `text-mode-hook' and `outline-mode-hook'.  We must
-      ;; prevent that local processes die.  Yes: I've seen
-      ;; `flyspell-mode', which starts "ispell" ...
-      (let ((default-directory (tramp-temporary-file-directory)))
+      ;; Activate outline-mode.  This runs `text-mode-hook' and
+      ;; `outline-mode-hook'.  We must prevent that local processes
+      ;; die.  Yes: I've seen `flyspell-mode', which starts "ispell"
+      ;; ...
+      (let ((default-directory (tramp-compat-temporary-file-directory)))
        (outline-mode))
-      (setq outline-regexp "[0-9]+:[0-9]+:[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
-;      (setq outline-regexp "[a-z.-]+:[0-9]+: [a-z0-9-]+ (\\([0-9]+\\)) #")
-      (setq outline-level 'tramp-outline-level))
+      (set (make-local-variable 'outline-regexp)
+          "[0-9]+:[0-9]+:[0-9]+ [a-z0-9-]+ (\\([0-9]+\\)) #")
+;      (set (make-local-variable 'outline-regexp)
+;         "[a-z.-]+:[0-9]+: [a-z0-9-]+ (\\([0-9]+\\)) #")
+      (set (make-local-variable 'outline-level) 'tramp-outline-level))
     (current-buffer)))
 
 (defun tramp-outline-level ()
@@ -5071,7 +5260,8 @@ This function expects to be in the right *tramp* buffer."
        (when (search-backward "tramp_executable " nil t)
          (skip-chars-forward "^ ")
          (skip-chars-forward " ")
-         (setq result (buffer-substring (point) (tramp-line-end-position)))))
+         (setq result (buffer-substring
+                       (point) (tramp-compat-line-end-position)))))
     result)))
 
 (defun tramp-set-remote-path (vec)
@@ -5080,53 +5270,9 @@ I.e., for each directory in `tramp-remote-path', it is tested
 whether it exists and if so, it is added to the environment
 variable PATH."
   (tramp-message vec 5 (format "Setting $PATH environment variable"))
-
-  (with-current-buffer (tramp-get-connection-buffer vec)
-    (set (make-local-variable 'tramp-remote-path)
-        (copy-tree tramp-remote-path))
-    (let* ((elt (memq 'tramp-default-remote-path tramp-remote-path))
-          (tramp-default-remote-path
-           (with-connection-property vec "default-remote-path"
-             (when elt
-               (condition-case nil
-                   (symbol-name
-                    (tramp-send-command-and-read vec "getconf PATH"))
-                 ;; Default if "getconf" is not available.
-                 (error
-                  (tramp-message
-                   vec 3
-                   "`getconf PATH' not successful, using default value \"%s\"."
-                   "/bin:/usr/bin")
-                  "/bin:/usr/bin"))))))
-      (when elt
-       ;; Replace place holder `tramp-default-remote-path'.
-       (setcdr elt
-               (append
-                (tramp-split-string tramp-default-remote-path ":")
-                (cdr elt)))
-       (setq tramp-remote-path
-             (delq 'tramp-default-remote-path tramp-remote-path))))
-
-    ;; Check for existence of directories.
-    (setq tramp-remote-path
-         (delq
-          nil
-          (mapcar
-           (lambda (x)
-             (and
-              (with-connection-property vec x
-                (file-directory-p
-                 (tramp-make-tramp-file-name
-                  (tramp-file-name-method vec)
-                  (tramp-file-name-user vec)
-                  (tramp-file-name-host vec)
-                  x)))
-              x))
-           tramp-remote-path)))
-    (tramp-send-command
-     vec
-     (format "PATH=%s; export PATH"
-            (mapconcat 'identity tramp-remote-path ":")))))
+  (tramp-send-command
+   vec (format "PATH=%s; export PATH"
+              (mapconcat 'identity (tramp-get-remote-path vec) ":"))))
 
 ;; -- communication with external shell --
 
@@ -5187,12 +5333,14 @@ file exists and nonzero exit status otherwise."
   (unless (tramp-get-connection-property vec "remote-shell" nil)
     (let (shell)
       (with-current-buffer (tramp-get-buffer vec)
-       (tramp-send-command vec "echo ~root")
+       (tramp-send-command vec "echo ~root" t)
        (cond
         ((string-match "^~root$" (buffer-string))
          (setq shell
-               (or (tramp-find-executable vec "bash" tramp-remote-path t)
-                   (tramp-find-executable vec "ksh" tramp-remote-path t)))
+               (or (tramp-find-executable
+                    vec "bash" (tramp-get-remote-path vec) t)
+                   (tramp-find-executable
+                    vec "ksh" (tramp-get-remote-path vec) t)))
          (unless shell
            (tramp-error
             vec 'file-error
@@ -5207,8 +5355,11 @@ file exists and nonzero exit status otherwise."
            (when extra-args (setq shell (concat shell " " extra-args))))
          (tramp-message
           vec 5 "Starting remote shell `%s' for tilde expansion..." shell)
-         (tramp-send-command-internal
-          vec (concat "PROMPT_COMMAND='' PS1='$ ' exec " shell))
+         (let ((tramp-end-of-output "$ "))
+           (tramp-send-command
+            vec
+            (format "PROMPT_COMMAND='' PS1='$ ' PS2='' PS3='' exec %s" shell)
+            t))
          (tramp-message vec 5 "Setting remote shell prompt...")
          ;; Douglas Gray Stephens <DGrayStephens@slb.com> says that we
          ;; must use "\n" here, not tramp-rsh-end-of-line.  Kai left the
@@ -5216,10 +5367,14 @@ file exists and nonzero exit status otherwise."
          ;; as well.
          (tramp-send-command
           vec
-          (format "PROMPT_COMMAND=''; PS1='%s%s%s'; PS2=''; PS3=''"
+          (format "PS1='%s%s%s'"
                   tramp-rsh-end-of-line
                   tramp-end-of-output
-                  tramp-rsh-end-of-line))
+                  tramp-rsh-end-of-line)
+          t)
+         (tramp-send-command vec "PS2=''" t)
+         (tramp-send-command vec "PS3=''" t)
+         (tramp-send-command vec "PROMPT_COMMAND=''" t)
          (tramp-message vec 5 "Setting remote shell prompt...done"))
         (t (tramp-message
             vec 5 "Remote `%s' groks tilde expansion, good"
@@ -5296,6 +5451,8 @@ See also `tramp-action-yesno'."
   "Tell the remote host which terminal type to use.
 The terminal type can be configured with `tramp-terminal-type'."
   (tramp-message vec 5 "Setting `%s' as terminal type." tramp-terminal-type)
+  (with-current-buffer (tramp-get-connection-buffer vec)
+    (tramp-message vec 6 "\n%s" (buffer-string)))
   (tramp-send-string vec tramp-terminal-type))
 
 (defun tramp-action-process-alive (proc vec)
@@ -5360,7 +5517,7 @@ The terminal type can be configured with `tramp-terminal-type'."
     (with-current-buffer (tramp-get-connection-buffer vec)
       (tramp-message vec 6 "\n%s" (buffer-string)))
     (unless (eq exit 'ok)
-      (tramp-clear-passwd)
+      (tramp-clear-passwd vec)
       (tramp-error-with-buffer
        nil vec 'file-error
        (cond
@@ -5441,80 +5598,97 @@ nil."
          (tramp-error proc 'file-error "[[Regexp `%s' not found]]" regexp)))
       found)))
 
-(defun tramp-wait-for-shell-prompt (proc timeout)
-  "Wait for the shell prompt to appear from process PROC within TIMEOUT seconds.
-See `tramp-wait-for-regexp' for more details.
-Shell prompt pattern is determined by variables `shell-prompt-pattern'
-and `tramp-shell-prompt-pattern'."
-  (tramp-wait-for-regexp
-   proc timeout
-   (format "\\(%s\\|%s\\)\\'"
-          shell-prompt-pattern tramp-shell-prompt-pattern)))
-
 (defun tramp-barf-if-no-shell-prompt (proc timeout &rest error-args)
   "Wait for shell prompt and barf if none appears.
 Looks at process PROC to see if a shell prompt appears in TIMEOUT
 seconds.  If not, it produces an error message with the given ERROR-ARGS."
-  (unless (tramp-wait-for-shell-prompt proc timeout)
+  (unless
+      (tramp-wait-for-regexp
+       proc timeout
+       (format
+       "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
     (apply 'tramp-error-with-buffer nil proc 'file-error error-args)))
 
-;; We don't call `tramp-send-string' in order to hide the password from the
-;; debug buffer, and because end-of-line handling of the string.
-(defun tramp-enter-password (p)
+;; We don't call `tramp-send-string' in order to hide the password
+;; from the debug buffer, and because end-of-line handling of the
+;; string.
+(defun tramp-enter-password (proc)
   "Prompt for a password and send it to the remote end."
   (process-send-string
-   p (concat (tramp-read-passwd p)
-            (or (tramp-get-method-parameter
-                 tramp-current-method
-                 'tramp-password-end-of-line)
-                tramp-default-password-end-of-line))))
+   proc (concat (tramp-read-passwd proc)
+               (or (tramp-get-method-parameter
+                    tramp-current-method
+                    'tramp-password-end-of-line)
+                   tramp-default-password-end-of-line))))
 
 (defun tramp-open-connection-setup-interactive-shell (proc vec)
   "Set up an interactive shell.
 Mainly sets the prompt and the echo correctly.  PROC is the shell
 process to set up.  VEC specifies the connection."
-  ;; It is useful to set the prompt in the following command because
-  ;; some people have a setting for $PS1 which /bin/sh doesn't know
-  ;; about and thus /bin/sh will display a strange prompt.  For
-  ;; example, if $PS1 has "${CWD}" in the value, then ksh will display
-  ;; the current working directory but /bin/sh will display a dollar
-  ;; sign.  The following command line sets $PS1 to a sane value, and
-  ;; works under Bourne-ish shells as well as csh-like shells.  Daniel
-  ;; Pittman reports that the unusual positioning of the single quotes
-  ;; makes it work under `rc', too.  We also unset the variable $ENV
-  ;; because that is read by some sh implementations (eg, bash when
-  ;; called as sh) on startup; this way, we avoid the startup file
-  ;; clobbering $PS1.  $PROMP_COMMAND is another way to set the prompt
-  ;; in /bin/bash, it must be discarded as well.
-  (tramp-send-command-internal
+  (let ((tramp-end-of-output "$ "))
+    ;; It is useful to set the prompt in the following command because
+    ;; some people have a setting for $PS1 which /bin/sh doesn't know
+    ;; about and thus /bin/sh will display a strange prompt.  For
+    ;; example, if $PS1 has "${CWD}" in the value, then ksh will
+    ;; display the current working directory but /bin/sh will display
+    ;; a dollar sign.  The following command line sets $PS1 to a sane
+    ;; value, and works under Bourne-ish shells as well as csh-like
+    ;; shells.  Daniel Pittman reports that the unusual positioning of
+    ;; the single quotes makes it work under `rc', too.  We also unset
+    ;; the variable $ENV because that is read by some sh
+    ;; implementations (eg, bash when called as sh) on startup; this
+    ;; way, we avoid the startup file clobbering $PS1.  $PROMP_COMMAND
+    ;; is another way to set the prompt in /bin/bash, it must be
+    ;; discarded as well.
+    (tramp-send-command
+     vec
+     (format
+      "exec env ENV='' PROMPT_COMMAND='' PS1='$ ' PS2='' PS3='' %s"
+      (tramp-get-method-parameter
+       (tramp-file-name-method vec) 'tramp-remote-sh))
+     t)
+
+    ;; Disable echo.
+    (tramp-message vec 5 "Setting up remote shell environment")
+    (tramp-send-command vec "stty -inlcr -echo kill '^U' erase '^H'" t)
+    ;; Check whether the echo has really been disabled.  Some
+    ;; implementations, like busybox of embedded GNU/Linux, don't
+    ;; support disabling.
+    (tramp-send-command vec "echo foo" t)
+    (with-current-buffer (process-buffer proc)
+      (goto-char (point-min))
+      (when (looking-at "echo foo")
+       (tramp-set-connection-property proc "remote-echo" t)
+       (tramp-message vec 5 "Remote echo still on. Ok.")
+       ;; Make sure backspaces and their echo are enabled and no line
+       ;; width magic interferes with them.
+       (tramp-send-command vec "stty icanon erase ^H cols 32767" t))))
+
+  (tramp-message vec 5 "Setting shell prompt")
+  ;; We can set $PS1 to `tramp-end-of-output' only when the echo has
+  ;; been disabled.  Otherwise, the echo of the command would be
+  ;; regarded as prompt already.
+  (tramp-send-command
    vec
-   (format "exec env 'ENV=' 'PROMPT_COMMAND=' 'PS1=$ ' %s"
-          (tramp-get-method-parameter
-           (tramp-file-name-method vec) 'tramp-remote-sh)))
-  (tramp-message vec 5 "Setting up remote shell environment")
-  (tramp-send-command-internal vec "stty -inlcr -echo kill '^U' erase '^H'")
-  ;; Check whether the echo has really been disabled.  Some
-  ;; implementations, like busybox of embedded GNU/Linux, don't
-  ;; support disabling.
-  (tramp-send-command-internal vec "echo foo")
-  (with-current-buffer (process-buffer proc)
-    (goto-char (point-min))
-    (when (looking-at "echo foo")
-      (tramp-set-connection-property vec "remote-echo" t)
-      (tramp-message vec 5 "Remote echo still on. Ok.")
-      ;; Make sure backspaces and their echo are enabled and no line
-      ;; width magic interferes with them.
-      (tramp-send-command-internal vec "stty icanon erase ^H cols 32767")))
+   (format "PS1='%s%s%s'"
+          tramp-rsh-end-of-line
+           tramp-end-of-output
+          tramp-rsh-end-of-line)
+   t)
+  (tramp-send-command vec "PS2=''" t)
+  (tramp-send-command vec "PS3=''" t)
+  (tramp-send-command vec "PROMPT_COMMAND=''" t)
+
   ;; Try to set up the coding system correctly.
   ;; CCC this can't be the right way to do it.  Hm.
   (tramp-message vec 5 "Determining coding system")
-  (tramp-send-command-internal vec "echo foo ; echo bar")
+  (tramp-send-command vec "echo foo ; echo bar" t)
   (with-current-buffer (process-buffer proc)
     (goto-char (point-min))
     (if (featurep 'mule)
        ;; Use MULE to select the right EOL convention for communicating
        ;; with the process.
-       (let* ((cs (or (process-coding-system proc)
+       (let* ((cs (or (funcall (symbol-function 'process-coding-system) proc)
                       (cons 'undecided 'undecided)))
               cs-decode cs-encode)
          (when (symbolp cs) (setq cs (cons cs cs)))
@@ -5527,30 +5701,39 @@ process to set up.  VEC specifies the connection."
          (when (search-forward "\r" nil t)
            (setq cs-decode (tramp-coding-system-change-eol-conversion
                             cs-decode 'dos)))
-         (set-buffer-process-coding-system cs-decode cs-encode))
+         (funcall (symbol-function 'set-buffer-process-coding-system)
+                  cs-decode cs-encode))
       ;; Look for ^M and do something useful if found.
       (when (search-forward "\r" nil t)
        ;; We have found a ^M but cannot frob the process coding system
        ;; because we're running on a non-MULE Emacs.  Let's try
        ;; stty, instead.
-       (tramp-send-command-internal vec "stty -onlcr"))))
-  (tramp-send-command-internal vec "set +o vi +o emacs")
-  (tramp-message vec 5 "Setting shell prompt")
-  ;; Douglas Gray Stephens <DGrayStephens@slb.com> says that we must
-  ;; use "\n" here, not tramp-rsh-end-of-line.  We also manually frob
-  ;; the last time we sent a command, to avoid `tramp-send-command' to
-  ;; send "echo are you awake".
-  (tramp-send-command
-   vec
-   (format "PROMPT_COMMAND=''; PS1='%s%s%s'; PS2=''; PS3=''"
-          tramp-rsh-end-of-line
-           tramp-end-of-output
-          tramp-rsh-end-of-line))
-  ;; Check whether the remote host suffers from buggy `send-process-string'.
-  ;; This is known for FreeBSD (see comment in `send_process', file process.c).
-  ;; I've tested sending 624 bytes successfully, sending 625 bytes failed.
-  ;; Emacs makes a hack when this host type is detected locally.  It cannot
-  ;; handle remote hosts, though.
+       (tramp-send-command vec "stty -onlcr" t))))
+  (tramp-send-command vec "set +o vi +o emacs" t)
+
+  ;; Check whether the output of "uname -sr" has been changed.  If
+  ;; yes, this is a strong indication that we must expire all
+  ;; connection properties.
+  (tramp-message vec 5 "Checking system information")
+  (let ((old-uname (tramp-get-connection-property vec "uname" nil))
+       (new-uname
+        (tramp-set-connection-property
+         vec "uname"
+         (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\""))))
+    (when (and (stringp old-uname) (not (string-equal old-uname new-uname)))
+      (funcall (symbol-function 'tramp-cleanup-connection) vec)
+      (signal
+       'quit
+       (list (format
+             "Connection reset, because remote host changed from `%s' to `%s'"
+             old-uname new-uname)))))
+
+  ;; Check whether the remote host suffers from buggy
+  ;; `send-process-string'.  This is known for FreeBSD (see comment in
+  ;; `send_process', file process.c).  I've tested sending 624 bytes
+  ;; 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"
     (cond
      ((and (integerp tramp-chunksize) (> tramp-chunksize 0))
@@ -5559,12 +5742,12 @@ process to set up.  VEC specifies the connection."
       (tramp-message
        vec 5 "Checking remote host type for `send-process-string' bug")
       (if (string-match
-          "^FreeBSD"
-          (with-connection-property vec "uname"
-            (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\"")))
+          "^FreeBSD" (tramp-get-connection-property vec "uname" ""))
          500 0))))
+
   ;; Set remote PATH variable.
   (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
   ;; "test foo; echo $?" to check if various conditions hold, and
@@ -5574,8 +5757,10 @@ process to set up.  VEC specifies the connection."
   ;; with buggy /bin/sh implementations will have a working bash or
   ;; ksh.  Whee...
   (tramp-find-shell vec)
+
   ;; Disable unexpected output.
-  (tramp-send-command vec "mesg n; biff n")
+  (tramp-send-command vec "mesg n; biff n" t)
+
   ;; Set the environment.
   (tramp-message vec 5 "Setting default environment")
   (let ((env (copy-sequence tramp-remote-process-environment))
@@ -5584,12 +5769,12 @@ process to set up.  VEC specifies the connection."
       (setq item (split-string (car env) "="))
       (if (and (stringp (cadr item)) (not (string-equal (cadr item) "")))
          (tramp-send-command
-          vec (format "%s=%s; export %s" (car item) (cadr item) (car item)))
+          vec (format "%s=%s; export %s" (car item) (cadr item) (car item)) t)
        (push (car item) unset))
       (setq env (cdr env)))
     (when unset
       (tramp-send-command
-       vec (format "unset %s" (mapconcat 'identity unset " "))))))
+       vec (format "unset %s" (mapconcat 'identity unset " "))))) t)
 
 ;; CCC: We should either implement a Perl version of base64 encoding
 ;; and decoding.  Then we just use that in the last item.  The other
@@ -5776,18 +5961,15 @@ INPUT can also be nil which means `/dev/null'.
 OUTPUT can be a string (which specifies a filename), or t (which
 means standard output and thus the current buffer), or nil (which
 means discard it)."
-  (let ((default-directory (tramp-temporary-file-directory)))
-    (call-process
-     tramp-encoding-shell              ;program
-     (when (and input (not (string-match "%s" cmd)))
-       input)                          ;input
-     (if (eq output t) t nil)          ;output
-     nil                               ;redisplay
-     tramp-encoding-command-switch
-     ;; actual shell command
-     (concat
-      (if (string-match "%s" cmd) (format cmd input) cmd)
-      (if (stringp output) (concat "> " output) "")))))
+  (tramp-local-call-process
+   tramp-encoding-shell
+   (when (and input (not (string-match "%s" cmd))) input)
+   (if (eq output t) t nil)
+   nil
+   tramp-encoding-command-switch
+   (concat
+    (if (string-match "%s" cmd) (format cmd input) cmd)
+    (if (stringp output) (concat "> " output) ""))))
 
 (defun tramp-compute-multi-hops (vec)
   "Expands VEC according to `tramp-default-proxies-alist'.
@@ -5823,10 +6005,12 @@ Gateway hops are already opened."
            (setq choices tramp-default-proxies-alist)))))
 
     ;; Handle gateways.
-    (when (string-match (format
-                        "^\\(%s\\|%s\\)$"
-                        tramp-gw-tunnel-method tramp-gw-socks-method)
-                       (tramp-file-name-method (car target-alist)))
+    (when (and (boundp 'tramp-gw-tunnel-method)
+              (string-match (format
+                             "^\\(%s\\|%s\\)$"
+                             (symbol-value 'tramp-gw-tunnel-method)
+                             (symbol-value 'tramp-gw-socks-method))
+                            (tramp-file-name-method (car target-alist))))
       (let ((gw (pop target-alist))
            (hop (pop target-alist)))
        ;; Is the method prepared for gateways?
@@ -5851,7 +6035,7 @@ Gateway hops are already opened."
         'target-alist
         (vector
          (tramp-file-name-method hop) (tramp-file-name-user hop)
-         (tramp-gw-open-connection vec gw hop) nil))
+         (funcall (symbol-function 'tramp-gw-open-connection) vec gw hop) nil))
        ;; For the password prompt, we need the correct values.
        ;; Therefore, we must remember the gateway vector.  But we
        ;; cannot do it as connection property, because it shouldn't
@@ -5882,7 +6066,8 @@ Gateway hops are already opened."
   "Maybe open a connection VEC.
 Does not do anything if a connection is already open, but re-opens the
 connection if a previous connection has died for some reason."
-  (let ((p (tramp-get-connection-process vec)))
+  (let ((p (tramp-get-connection-process vec))
+       (process-environment (copy-sequence process-environment)))
 
     ;; If too much time has passed since last command was sent, look
     ;; whether process is still alive.  If it isn't, kill it.  When
@@ -5891,16 +6076,23 @@ connection if a previous connection has died for some reason."
     ;; tries to send some data to the remote end.  So that's why we
     ;; try to send a command from time to time, then look again
     ;; whether the process is really alive.
-    (when (and (> (tramp-time-diff
-                  (current-time)
-                  (tramp-get-connection-property p "last-cmd-time" '(0 0 0)))
-                 60)
-              p (processp p) (memq (process-status p) '(run open)))
-      (tramp-send-command vec "echo are you awake" t t)
-      (unless (and (memq (process-status p) '(run open))
-                  (tramp-wait-for-output p 10))
-       (delete-process p)
-       (setq p nil)))
+    (condition-case nil
+       (when (and (> (tramp-time-diff
+                      (current-time)
+                      (tramp-get-connection-property
+                       p "last-cmd-time" '(0 0 0)))
+                     60)
+                  p (processp p) (memq (process-status p) '(run open)))
+         (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.
+           (tramp-error vec 'file-error "Awake did fail")))
+      (file-error
+       (tramp-flush-connection-property vec nil)
+       (tramp-flush-connection-property p nil)
+       (delete-process p)
+       (setq p nil)))
 
     ;; New connection must be opened.
     (unless (and p (processp p) (memq (process-status p) '(run open)))
@@ -5923,14 +6115,16 @@ connection if a previous connection has died for some reason."
       (when (and p (processp p))
        (delete-process p))
       (setenv "TERM" tramp-terminal-type)
+      (setenv "LC_ALL" "C")
       (setenv "PROMPT_COMMAND")
       (setenv "PS1" "$ ")
       (let* ((target-alist (tramp-compute-multi-hops vec))
-            (process-environment (copy-sequence process-environment))
             (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-temporary-file-directory)))
+            (p (let ((default-directory
+                       (tramp-compat-temporary-file-directory)))
                  (start-process
                   (or (tramp-get-connection-property vec "process-name" nil)
                       (tramp-buffer-name vec))
@@ -5966,6 +6160,18 @@ connection if a previous connection has died for some reason."
                 (g-user (and gw (tramp-file-name-user gw)))
                 (g-host (and gw (tramp-file-name-host gw)))
                 (command login-program)
+                ;; We don't create the temporary file.  In fact, it
+                ;; is just a prefix for the ControlPath option of
+                ;; ssh; the real temporary file has another name, and
+                ;; it is created and protected by ssh.  It is also
+                ;; removed by ssh, when the connection is closed.
+                (tmpfile
+                 (tramp-set-connection-property
+                  p "temp-file"
+                  (make-temp-name
+                   (expand-file-name
+                    tramp-temp-name-prefix
+                    (tramp-compat-temporary-file-directory)))))
                 spec)
 
            ;; Add gateway arguments if necessary.
@@ -5990,7 +6196,7 @@ connection if a previous connection has died for some reason."
             l-user (or l-user "")
             l-port (or l-port "")
             spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
-                   (?t . ,(tramp-make-tramp-temp-file vec)))
+                   (?t . ,tmpfile))
             command
             (concat
              command " "
@@ -6030,7 +6236,7 @@ is meant to be used from `tramp-maybe-open-connection' only.  The
 function waits for output unless NOOUTPUT is set."
   (unless neveropen (tramp-maybe-open-connection vec))
   (let ((p (tramp-get-connection-process vec)))
-    (when (tramp-get-connection-property vec "remote-echo" nil)
+    (when (tramp-get-connection-property p "remote-echo" nil)
       ;; 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)))
@@ -6038,30 +6244,17 @@ function waits for output unless NOOUTPUT is set."
     (tramp-send-string vec command)
     (unless nooutput (tramp-wait-for-output p))))
 
-(defun tramp-send-command-internal (vec command)
-  "Send command to remote host and wait for success.
-Sends COMMAND, then waits 30 seconds for shell prompt."
-  (let ((p (tramp-get-connection-process vec)))
-    (when (tramp-get-connection-property vec "remote-echo" nil)
-      ;; 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)))
-    (tramp-message vec 6 "%s" command)
-    (tramp-send-string vec command)
-    (tramp-barf-if-no-shell-prompt
-     p 30 "Couldn't `%s', see buffer `%s'" command (buffer-name))))
-
 (defun tramp-wait-for-output (proc &optional timeout)
   "Wait for output from remote rsh command."
   (with-current-buffer (process-buffer proc)
-    (let ((found
-          (tramp-wait-for-regexp
-           proc timeout
-           (format "^%s\r?$" (regexp-quote tramp-end-of-output)))))
+    ;; Initially, `tramp-end-of-output' is "$ ".  There might be
+    ;; leading escape sequences, which must be ignored.
+    (let* ((regexp (format "^[^$\n]*%s\r?$" (regexp-quote tramp-end-of-output)))
+          (found (tramp-wait-for-regexp proc timeout regexp)))
       (if found
          (let (buffer-read-only)
            (goto-char (point-max))
-           (forward-line -2)
+           (re-search-backward regexp nil t)
            (delete-region (point) (point-max)))
        (if timeout
            (tramp-error
@@ -6115,7 +6308,8 @@ In case there is no valid Lisp expression, it raises an error"
     (condition-case nil
        (prog1 (read (current-buffer))
          ;; Error handling.
-         (when (re-search-forward "\\S-" nil t) (error)))
+         (when (re-search-forward "\\S-" (tramp-compat-line-end-position) t)
+           (error nil)))
       (error (tramp-error
              vec 'file-error
              "`%s' does not return a valid Lisp expression: `%s'"
@@ -6124,7 +6318,7 @@ In case there is no valid Lisp expression, it raises an error"
 ;; It seems that Tru64 Unix does not like it if long strings are sent
 ;; to it in one go.  (This happens when sending the Perl
 ;; `file-attributes' implementation, for instance.)  Therefore, we
-;; have this function which waits a bit at each line.
+;; have this function which sends the string in chunks.
 (defun tramp-send-string (vec string)
   "Send the STRING via connection VEC.
 
@@ -6142,7 +6336,7 @@ the remote host use line-endings as defined in the variable
       ;; Clean up the buffer.  We cannot call `erase-buffer' because
       ;; narrowing might be in effect.
       (let (buffer-read-only) (delete-region (point-min) (point-max)))
-      ;; replace "\n" by `tramp-rsh-end-of-line'
+      ;; Replace "\n" by `tramp-rsh-end-of-line'.
       (setq string
            (mapconcat 'identity
                       (split-string string "\n")
@@ -6150,7 +6344,7 @@ the remote host use line-endings as defined in the variable
       (unless (or (string= string "")
                  (string-equal (substring string -1) tramp-rsh-end-of-line))
        (setq string (concat string tramp-rsh-end-of-line)))
-      ;; send the string
+      ;; Send the string.
       (if (and chunksize (not (zerop chunksize)))
          (let ((pos 0)
                (end (length string)))
@@ -6256,7 +6450,8 @@ Return ATTR."
   ;; Convert file size.
   (when (< (nth 7 attr) 0)
     (setcar (nthcdr 7 attr) -1))
-  (when (and (floatp (nth 7 attr)) (<= (nth 7 attr) most-positive-fixnum))
+  (when (and (floatp (nth 7 attr))
+            (<= (nth 7 attr) (tramp-compat-most-positive-fixnum)))
     (setcar (nthcdr 7 attr) (round (nth 7 attr))))
   ;; Convert file mode bits to string.
   (unless (stringp (nth 8 attr))
@@ -6372,7 +6567,7 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
 
 
 ;; ------------------------------------------------------------
-;; -- TRAMP file names --
+;; -- Tramp file names --
 ;; ------------------------------------------------------------
 ;; Conversion functions between external representation and
 ;; internal data structure.  Convenience functions for internal
@@ -6400,7 +6595,7 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
 
 ;; The host part of a Tramp file name vector can be of kind
 ;; "host#port".  Sometimes, we must extract these parts.
-(defsubst tramp-file-name-real-host (vec)
+(defun tramp-file-name-real-host (vec)
   "Return the host name of VEC without port."
   (let ((host (tramp-file-name-host vec)))
     (if (and (stringp host)
@@ -6408,7 +6603,7 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
        (match-string 1 host)
       host)))
 
-(defsubst tramp-file-name-port (vec)
+(defun tramp-file-name-port (vec)
   "Return the port number of VEC."
   (let ((host (tramp-file-name-host vec)))
     (and (stringp host)
@@ -6416,11 +6611,11 @@ Not actually used.  Use `(format \"%o\" i)' instead?"
         (string-to-number (match-string 2 host)))))
 
 (defun tramp-tramp-file-p (name)
-  "Return t iff NAME is a tramp file."
+  "Return t if NAME is a Tramp file."
   (save-match-data
     (string-match tramp-file-name-regexp name)))
 
-(defsubst tramp-find-method (method user host)
+(defun tramp-find-method (method user host)
   "Return the right method string to use.
 This is METHOD, if non-nil. Otherwise, do a lookup in
 `tramp-default-method-alist'."
@@ -6436,7 +6631,7 @@ This is METHOD, if non-nil. Otherwise, do a lookup in
        lmethod)
       tramp-default-method))
 
-(defsubst tramp-find-user (method user host)
+(defun tramp-find-user (method user host)
   "Return the right user string to use.
 This is USER, if non-nil. Otherwise, do a lookup in
 `tramp-default-user-alist'."
@@ -6452,28 +6647,32 @@ This is USER, if non-nil. Otherwise, do a lookup in
        luser)
       tramp-default-user))
 
-(defsubst tramp-find-host (method user host)
+(defun tramp-find-host (method user host)
   "Return the right host string to use.
 This is HOST, if non-nil. Otherwise, it is `tramp-default-host'."
   (or (and (> (length host) 0) host)
       tramp-default-host))
 
-(defun tramp-dissect-file-name (name)
+(defun tramp-dissect-file-name (name &optional nodefault)
   "Return a `tramp-file-name' structure.
-The structure consists of remote method, remote user, remote host and
-localname (file name on remote host)."
+The structure consists of remote method, remote user, remote host
+and localname (file name on remote host).  If NODEFAULT is
+non-nil, the file name parts are not expanded to their default
+values."
   (save-match-data
     (let ((match (string-match (nth 0 tramp-file-name-structure) name)))
-      (unless match (error "Not a tramp file name: %s" name))
+      (unless match (error "Not a Tramp file name: %s" name))
       (let ((method    (match-string (nth 1 tramp-file-name-structure) name))
            (user      (match-string (nth 2 tramp-file-name-structure) name))
            (host      (match-string (nth 3 tramp-file-name-structure) name))
            (localname (match-string (nth 4 tramp-file-name-structure) name)))
-       (vector
-        (tramp-find-method method user host)
-        (tramp-find-user   method user host)
-        (tramp-find-host   method user host)
-        localname)))))
+       (if nodefault
+           (vector method user host localname)
+         (vector
+          (tramp-find-method method user host)
+          (tramp-find-user   method user host)
+          (tramp-find-host   method user host)
+          localname))))))
 
 (defun tramp-equal-remote (file1 file2)
   "Checks, whether the remote parts of FILE1 and FILE2 are identical.
@@ -6519,8 +6718,7 @@ necessary only.  This function will be used in file name completion."
 (defun tramp-make-copy-program-file-name (vec)
   "Create a file name suitable to be passed to `rcp' and workalikes."
   (let ((user (tramp-file-name-user vec))
-       (host (car (split-string
-                   (tramp-file-name-host vec) tramp-prefix-port-regexp)))
+       (host (tramp-file-name-real-host vec))
        (localname (tramp-shell-quote-argument
                    (tramp-file-name-localname vec))))
     (if (not (zerop (length user)))
@@ -6531,8 +6729,68 @@ necessary only.  This function will be used in file name completion."
   "Return t if this is an out-of-band method, nil otherwise."
   (tramp-get-method-parameter (tramp-file-name-method vec) 'tramp-copy-program))
 
+(defun tramp-local-host-p (vec)
+  "Return t if this points to the local host, nil otherwise."
+  (let ((host (tramp-file-name-real-host vec)))
+    (and
+     (stringp host)
+     (string-match
+      (concat "^" (regexp-opt (list "localhost" (system-name)) t) "$") host))))
+
 ;; Variables local to connection.
 
+(defun tramp-get-remote-path (vec)
+  (with-connection-property vec "remote-path"
+    (let* ((remote-path (tramp-compat-copy-tree tramp-remote-path))
+          (elt (memq 'tramp-default-remote-path remote-path))
+          (default-remote-path
+            (when elt
+              (condition-case nil
+                  (symbol-name
+                   (tramp-send-command-and-read vec "getconf PATH"))
+                ;; Default if "getconf" is not available.
+                (error
+                 (tramp-message
+                  vec 3
+                  "`getconf PATH' not successful, using default value \"%s\"."
+                  "/bin:/usr/bin")
+                 "/bin:/usr/bin")))))
+      (when elt
+       ;; Replace place holder `tramp-default-remote-path'.
+       (setcdr elt
+               (append
+                (tramp-split-string default-remote-path ":")
+                (cdr elt)))
+       (setq remote-path (delq 'tramp-default-remote-path remote-path)))
+
+      ;; Remove non-existing directories.
+      (delq
+       nil
+       (mapcar
+       (lambda (x)
+         (and
+          (with-connection-property vec x
+            (file-directory-p
+             (tramp-make-tramp-file-name
+              (tramp-file-name-method vec)
+              (tramp-file-name-user vec)
+              (tramp-file-name-host vec)
+              x)))
+          x))
+       remote-path)))))
+
+(defun tramp-get-remote-tmpdir (vec)
+  (with-connection-property vec "tmp-directory"
+    (let ((dir (tramp-shell-quote-argument "/tmp")))
+      (if (and (zerop
+               (tramp-send-command-and-check
+                vec (format "%s -d %s" (tramp-get-test-command vec) dir)))
+              (zerop
+               (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-current-buffer (tramp-get-buffer vec)
@@ -6540,7 +6798,7 @@ necessary only.  This function will be used in file name completion."
       (or
        (catch 'ls-found
         (dolist (cmd '("ls" "gnuls" "gls"))
-          (let ((dl tramp-remote-path)
+          (let ((dl (tramp-get-remote-path vec))
                 result)
             (while
                 (and
@@ -6551,13 +6809,6 @@ necessary only.  This function will be used in file name completion."
               (when (zerop (tramp-send-command-and-check
                             vec (format "%s -lnd /" result)))
                 (throw 'ls-found result))
-              ;; Remove unneeded directories from path.
-              (while
-                  (and
-                   dl
-                   (not
-                    (string-equal result (expand-file-name cmd (car dl)))))
-                (setq dl (cdr dl)))
               (setq dl (cdr dl))))))
        (tramp-error vec 'file-error "Couldn't find a proper `ls' command")))))
 
@@ -6567,7 +6818,7 @@ necessary only.  This function will be used in file name completion."
       (tramp-message vec 5 "Finding a suitable `test' command")
       (if (zerop (tramp-send-command-and-check vec "test 0"))
          "test"
-       (tramp-find-executable vec "test" tramp-remote-path)))))
+       (tramp-find-executable vec "test" (tramp-get-remote-path vec))))))
 
 (defun tramp-get-test-nt-command (vec)
   ;; Does `test A -nt B' work?  Use abominable `find' construct if it
@@ -6601,20 +6852,21 @@ necessary only.  This function will be used in file name completion."
   (with-connection-property vec "ln"
     (with-current-buffer (tramp-get-buffer vec)
       (tramp-message vec 5 "Finding a suitable `ln' command")
-      (tramp-find-executable vec "ln" tramp-remote-path))))
+      (tramp-find-executable vec "ln" (tramp-get-remote-path vec)))))
 
 (defun tramp-get-remote-perl (vec)
   (with-connection-property vec "perl"
     (with-current-buffer (tramp-get-buffer vec)
       (tramp-message vec 5 "Finding a suitable `perl' command")
-      (or (tramp-find-executable vec "perl5" tramp-remote-path)
-         (tramp-find-executable vec "perl" tramp-remote-path)))))
+      (or (tramp-find-executable vec "perl5" (tramp-get-remote-path vec))
+         (tramp-find-executable vec "perl" (tramp-get-remote-path vec))))))
 
 (defun tramp-get-remote-stat (vec)
   (with-connection-property vec "stat"
     (with-current-buffer (tramp-get-buffer vec)
       (tramp-message vec 5 "Finding a suitable `stat' command")
-      (let ((result (tramp-find-executable vec "stat" tramp-remote-path))
+      (let ((result (tramp-find-executable
+                    vec "stat" (tramp-get-remote-path vec)))
            tmp)
        ;; Check whether stat(1) returns usable syntax.
        (when result
@@ -6636,7 +6888,7 @@ necessary only.  This function will be used in file name completion."
       (tramp-message vec 5 "Finding POSIX `id' command")
       (or
        (catch 'id-found
-        (let ((dl tramp-remote-path)
+        (let ((dl (tramp-get-remote-path vec))
               result)
           (while
               (and
@@ -6647,15 +6899,6 @@ necessary only.  This function will be used in file name completion."
             (when (zerop (tramp-send-command-and-check
                           vec (format "%s -u" result)))
               (throw 'id-found result))
-            ;; Remove unneeded directories from path.
-            (while
-                (and
-                 dl
-                 (not
-                  (string-equal
-                   result
-                   (concat (file-name-as-directory (car dl)) "id"))))
-              (setq dl (cdr dl)))
             (setq dl (cdr dl)))))
        (tramp-error vec 'file-error "Couldn't find a POSIX `id' command")))))
 
@@ -6683,6 +6926,12 @@ necessary only.  This function will be used in file name completion."
       ;; The command might not always return a number.
       (if (and (equal id-format 'integer) (not (integerp res))) -1 res))))
 
+(defun tramp-get-local-uid (id-format)
+  (if (equal id-format 'integer) (user-uid) (user-login-name)))
+
+(defun tramp-get-local-gid (id-format)
+  (nth 3 (tramp-compat-file-attributes "~/" id-format)))
+
 ;; Some predefined connection properties.
 (defun tramp-get-remote-coding (vec prop)
   ;; Local coding handles properties like remote coding.  So we could
@@ -6753,6 +7002,7 @@ If the `tramp-methods' entry does not exist, return NIL."
   (let ((bfn (buffer-file-name)))
     (when (and (stringp bfn)
               (tramp-tramp-file-p bfn)
+              (buffer-modified-p)
               (stringp buffer-auto-save-file-name)
               (not (equal bfn buffer-auto-save-file-name)))
       (unless (file-exists-p buffer-auto-save-file-name)
@@ -6789,25 +7039,6 @@ ALIST is of the form ((FROM . TO) ...)."
 ;; -- Compatibility functions section --
 ;; ------------------------------------------------------------
 
-(defun tramp-temporary-file-directory ()
-  "Return name of directory for temporary files (compat function).
-For Emacs, this is the variable `temporary-file-directory', for XEmacs
-this is the function `temp-directory'."
-  (cond ((boundp 'temporary-file-directory)
-         (symbol-value 'temporary-file-directory))
-        ((fboundp 'temp-directory)
-         (funcall (symbol-function 'temp-directory))) ;pacify byte-compiler
-        ((let ((d (getenv "TEMP"))) (and d (file-directory-p d)))
-         (file-name-as-directory (getenv "TEMP")))
-        ((let ((d (getenv "TMP"))) (and d (file-directory-p d)))
-         (file-name-as-directory (getenv "TMP")))
-        ((let ((d (getenv "TMPDIR"))) (and d (file-directory-p d)))
-         (file-name-as-directory (getenv "TMPDIR")))
-        ((file-exists-p "c:/temp") (file-name-as-directory "c:/temp"))
-        (t (message (concat "Neither `temporary-file-directory' nor "
-                            "`temp-directory' is defined -- using /tmp."))
-           (file-name-as-directory "/tmp"))))
-
 (defun tramp-read-passwd (proc &optional prompt)
   "Read a password from user (compat function).
 Invokes `password-read' if available, `read-passwd' else."
@@ -6820,22 +7051,22 @@ Invokes `password-read' if available, `read-passwd' else."
                (tramp-check-for-regexp proc tramp-password-prompt-regexp)
                (format "%s for %s " (capitalize (match-string 1)) key)))))
     (if (functionp 'password-read)
-       (let ((password (apply #'password-read  (list pw-prompt key))))
-         (apply #'password-cache-add (list key password))
+       (let ((password (funcall (symbol-function 'password-read)
+                                pw-prompt key)))
+         (funcall (symbol-function 'password-cache-add) key password)
          password)
       (read-passwd pw-prompt))))
 
-(defun tramp-clear-passwd ()
-  "Clear password cache for connection related to current-buffer.
-If METHOD, USER or HOST is given, take then for computing the key."
-  (interactive)
+(defun tramp-clear-passwd (vec)
+  "Clear password cache for connection related to VEC."
   (when (functionp 'password-cache-remove)
-    (apply #'password-cache-remove
-          (list (tramp-make-tramp-file-name
-                 tramp-current-method
-                 tramp-current-user
-                 tramp-current-host
-                 "")))))
+    (funcall
+     (symbol-function 'password-cache-remove)
+     (tramp-make-tramp-file-name
+      (tramp-file-name-method vec)
+      (tramp-file-name-user vec)
+      (tramp-file-name-host vec)
+      ""))))
 
 ;; Snarfed code from time-date.el and parse-time.el
 
@@ -6892,19 +7123,18 @@ T1 and T2 are time values (as returned by `current-time' for example)."
   "Return a coding system like CODING-SYSTEM but with given EOL-TYPE.
 EOL-TYPE can be one of `dos', `unix', or `mac'."
   (cond ((fboundp 'coding-system-change-eol-conversion)
-         (apply #'coding-system-change-eol-conversion
-                (list coding-system eol-type)))
+         (funcall (symbol-function 'coding-system-change-eol-conversion)
+                 coding-system eol-type))
         ((fboundp 'subsidiary-coding-system)
-         (apply
-          #'subsidiary-coding-system
-          (list coding-system
-                (cond ((eq eol-type 'dos) 'crlf)
-                      ((eq eol-type 'unix) 'lf)
-                      ((eq eol-type 'mac) 'cr)
-                      (t
-                       (error "Unknown EOL-TYPE `%s', must be %s"
-                              eol-type
-                              "`dos', `unix', or `mac'"))))))
+         (funcall (symbol-function 'subsidiary-coding-system)
+                 coding-system
+                 (cond ((eq eol-type 'dos) 'crlf)
+                       ((eq eol-type 'unix) 'lf)
+                       ((eq eol-type 'mac) 'cr)
+                       (t
+                        (error "Unknown EOL-TYPE `%s', must be %s"
+                               eol-type
+                               "`dos', `unix', or `mac'")))))
         (t (error "Can't change EOL conversion -- is MULE missing?"))))
 
 (defun tramp-split-string (string pattern)
@@ -6981,285 +7211,22 @@ Only works for Bourne-like shells."
 ;; CCC: This check is now also really awful; we should search all
 ;; of the filename format, not just the prefix.
 (when (string-match "\\[" tramp-prefix-format)
-  (defadvice file-expand-wildcards (around tramp-fix activate)
+  (defadvice file-expand-wildcards
+    (around tramp-advice-file-expand-wildcards activate)
     (let ((name (ad-get-arg 0)))
       (if (tramp-tramp-file-p name)
          ;; If it's a Tramp file, dissect it and look if wildcards
          ;; need to be expanded at all.
-         (let ((v (tramp-dissect-file-name name)))
-           (if (string-match "[[*?]" (tramp-file-name-localname v))
-               (let ((res ad-do-it))
-                 (setq ad-return-value (or res (list name))))
-             (setq ad-return-value (list name))))
+         (if (string-match
+              "[[*?]"
+              (tramp-file-name-localname (tramp-dissect-file-name name)))
+             (setq ad-return-value (or ad-do-it (list name)))
+           (setq ad-return-value (list name)))
        ;; If it is not a Tramp file, just run the original function.
-       (let ((res ad-do-it))
-         (setq ad-return-value (or res (list name)))))))
+       (setq ad-return-value (or ad-do-it (list name))))))
   (add-hook 'tramp-unload-hook
            '(lambda () (ad-unadvise 'file-expand-wildcards))))
 
-;; Tramp version is useful in a number of situations.
-
-(defun tramp-version (arg)
-  "Print version number of tramp.el in minibuffer or current buffer."
-  (interactive "P")
-  (if arg (insert tramp-version) (message tramp-version)))
-
-;; Make the `reporter` functionality available for making bug reports about
-;; the package. A most useful piece of code.
-
-(unless (fboundp 'reporter-submit-bug-report)
-  (autoload 'reporter-submit-bug-report "reporter"))
-
-(defun tramp-bug ()
-  "Submit a bug report to the TRAMP developers."
-  (interactive)
-  (require 'reporter)
-  (catch 'dont-send
-    (let ((reporter-prompt-for-summary-p t))
-      (reporter-submit-bug-report
-       tramp-bug-report-address                ; to-address
-       (format "tramp (%s)" tramp-version) ; package name and version
-       (delq nil
-            `(;; Current state
-              tramp-current-method
-              tramp-current-user
-              tramp-current-host
-
-              ;; System defaults
-              tramp-auto-save-directory        ; vars to dump
-              tramp-default-method
-              tramp-default-method-alist
-              tramp-default-host
-              tramp-default-proxies-alist
-              tramp-default-user
-              tramp-default-user-alist
-              tramp-rsh-end-of-line
-              tramp-default-password-end-of-line
-              tramp-remote-path
-              tramp-login-prompt-regexp
-              ;; Mask non-7bit characters
-              (tramp-password-prompt-regexp . tramp-reporter-dump-variable)
-              tramp-wrong-passwd-regexp
-              tramp-yesno-prompt-regexp
-              tramp-yn-prompt-regexp
-              tramp-terminal-prompt-regexp
-              tramp-temp-name-prefix
-              tramp-file-name-structure
-              tramp-file-name-regexp
-              tramp-methods
-              tramp-end-of-output
-              tramp-local-coding-commands
-              tramp-remote-coding-commands
-              tramp-actions-before-shell
-              tramp-actions-copy-out-of-band
-              tramp-terminal-type
-              ;; Mask non-7bit characters
-              (tramp-shell-prompt-pattern . tramp-reporter-dump-variable)
-              ,(when (boundp 'tramp-backup-directory-alist)
-                 'tramp-backup-directory-alist)
-              ,(when (boundp 'tramp-bkup-backup-directory-info)
-                 'tramp-bkup-backup-directory-info)
-              ;; Dump cache.
-              (tramp-cache-data . tramp-reporter-dump-variable)
-
-              ;; Non-tramp variables of interest
-              ;; Mask non-7bit characters
-              (shell-prompt-pattern . tramp-reporter-dump-variable)
-              backup-by-copying
-              backup-by-copying-when-linked
-              backup-by-copying-when-mismatch
-              ,(when (boundp 'backup-by-copying-when-privileged-mismatch)
-                 'backup-by-copying-when-privileged-mismatch)
-              ,(when (boundp 'password-cache)
-                 'password-cache)
-              ,(when (boundp 'password-cache-expiry)
-                 'password-cache-expiry)
-              ,(when (boundp 'backup-directory-alist)
-                 'backup-directory-alist)
-              ,(when (boundp 'bkup-backup-directory-info)
-                 'bkup-backup-directory-info)
-              file-name-handler-alist))
-
-       'tramp-load-report-modules      ; pre-hook
-       'tramp-append-tramp-buffers     ; post-hook
-       "\
-Enter your bug report in this message, including as much detail
-as you possibly can about the problem, what you did to cause it
-and what the local and remote machines are.
-
-If you can give a simple set of instructions to make this bug
-happen reliably, please include those.  Thank you for helping
-kill bugs in TRAMP.
-
-Another useful thing to do is to put
-
-  (setq tramp-verbose 8)
-
-in the ~/.emacs file and to repeat the bug.  Then, include the
-contents of the *tramp/foo* buffer and the *debug tramp/foo*
-buffer in your bug report.
-
---bug report follows this line--
-"))))
-
-(defun tramp-reporter-dump-variable (varsym mailbuf)
-  "Pretty-print the value of the variable in symbol VARSYM.
-Used for non-7bit chars in strings."
-  (let* ((reporter-eval-buffer (symbol-value 'reporter-eval-buffer))
-        (val (with-current-buffer reporter-eval-buffer
-               (symbol-value varsym))))
-
-    (if (hash-table-p val)
-       ;; Pretty print the cache.
-       (set varsym (read (format "(%s)" (tramp-cache-print val))))
-      ;; There are characters to be masked.
-      (when (and (boundp 'mm-7bit-chars)
-                (string-match
-                 (concat "[^" (symbol-value 'mm-7bit-chars) "]") val))
-       (with-current-buffer reporter-eval-buffer
-         (set varsym (format "(base64-decode-string \"%s\""
-                             (base64-encode-string val))))))
-
-    ;; Dump variable.
-    (funcall (symbol-function 'reporter-dump-variable) varsym mailbuf)
-
-    (unless (hash-table-p val)
-      ;; Remove string quotation.
-      (forward-line -1)
-      (when (looking-at
-            (concat "\\(^.*\\)" "\""                       ;; \1 "
-                    "\\((base64-decode-string \\)" "\\\\"  ;; \2 \
-                    "\\(\".*\\)" "\\\\"                    ;; \3 \
-                    "\\(\")\\)" "\"$"))                    ;; \4 "
-       (replace-match "\\1\\2\\3\\4")
-       (beginning-of-line)
-       (insert " ;; variable encoded due to non-printable characters\n"))
-      (forward-line 1))
-
-    ;; Reset VARSYM to old value.
-    (with-current-buffer reporter-eval-buffer
-      (set varsym val))))
-
-(defun tramp-load-report-modules ()
-  "Load needed modules for reporting."
-
-  ;; We load message.el and mml.el from Gnus.
-  (if (featurep 'xemacs)
-      (progn
-       (load "message" 'noerror)
-       (load "mml" 'noerror))
-    (require 'message nil 'noerror)
-    (require 'mml nil 'noerror))
-  (when (functionp 'message-mode)
-    (funcall (symbol-function 'message-mode)))
-  (when (functionp 'mml-mode)
-    (funcall (symbol-function 'mml-mode) t)))
-
-(defun tramp-append-tramp-buffers ()
-  "Append Tramp buffers and buffer local variables into the bug report."
-
-  (goto-char (point-max))
-
-  ;; Dump buffer local variables.
-  (dolist (buffer
-          (delq nil
-                (mapcar
-                 '(lambda (b)
-                    (when (string-match "\\*tramp/" (buffer-name b)) b))
-                 (buffer-list))))
-    (let ((reporter-eval-buffer buffer)
-         (buffer-name (buffer-name buffer))
-         (elbuf (get-buffer-create " *tmp-reporter-buffer*")))
-      (with-current-buffer elbuf
-       (emacs-lisp-mode)
-       (erase-buffer)
-       (insert "\n(setq\n")
-       (lisp-indent-line)
-       (funcall (symbol-function 'reporter-dump-variable)
-                'buffer-name (current-buffer))
-       (dolist (varsym-or-cons-cell (buffer-local-variables buffer))
-         (let ((varsym (or (car-safe varsym-or-cons-cell)
-                           varsym-or-cons-cell)))
-           (when (string-match "tramp" (symbol-name varsym))
-             (funcall
-              (symbol-function 'reporter-dump-variable)
-              varsym (current-buffer)))))
-       (lisp-indent-line)
-       (insert ")\n"))
-      (insert-buffer-substring elbuf)))
-
-  ;; Append buffers only when we are in message mode.
-  (when (and
-        (eq major-mode 'message-mode)
-        (boundp 'mml-mode)
-        (symbol-value 'mml-mode))
-
-    (let* ((tramp-buf-regexp "\\*\\(debug \\)?tramp/")
-          (buffer-list
-           (delq nil
-                 (mapcar '(lambda (b)
-                    (when (string-match tramp-buf-regexp (buffer-name b)) b))
-                         (buffer-list))))
-          (curbuf (current-buffer)))
-
-      ;; There is at least one Tramp buffer.
-      (when buffer-list
-       (switch-to-buffer (list-buffers-noselect nil))
-       (delete-other-windows)
-       (setq buffer-read-only nil)
-       (goto-char (point-min))
-       (while (not (eobp))
-         (if (re-search-forward tramp-buf-regexp (tramp-line-end-position) t)
-             (forward-line 1)
-           (forward-line 0)
-           (let ((start (point)))
-             (forward-line 1)
-             (kill-region start (point)))))
-       (insert "
-The buffer(s) above will be appended to this message.  If you
-don't want to append a buffer because it contains sensitive data,
-or because the buffer is too large, you should delete the
-respective buffer.  The buffer(s) will contain user and host
-names.  Passwords will never be included there.")
-
-       (when (>= tramp-verbose 6)
-         (insert "\n\n")
-         (let ((start (point)))
-           (insert "\
-Please note that you have set `tramp-verbose' to a value of at
-least 6.  Therefore, the contents of files might be included in
-the debug buffer(s).")
-           (add-text-properties start (point) (list 'face 'italic))))
-
-       (set-buffer-modified-p nil)
-       (setq buffer-read-only t)
-       (goto-char (point-min))
-
-       (if (y-or-n-p "Do you want to append the buffer(s)? ")
-           ;; OK, let's send.  First we delete the buffer list.
-           (progn
-             (kill-buffer nil)
-             (switch-to-buffer curbuf)
-             (goto-char (point-max))
-             (insert "\n\
-This is a special notion of the `gnus/message' package.  If you
-use another mail agent (by copying the contents of this buffer)
-please ensure that the buffers are attached to your email.\n\n")
-             (dolist (buffer buffer-list)
-               (funcall (symbol-function 'mml-insert-empty-tag)
-                        'part 'type "text/plain" 'encoding "base64"
-                        'disposition "attachment" 'buffer (buffer-name buffer)
-                        'description (buffer-name buffer)))
-             (set-buffer-modified-p nil))
-
-         ;; Don't send.  Delete the message buffer.
-         (set-buffer curbuf)
-         (set-buffer-modified-p nil)
-         (kill-buffer nil)
-         (throw 'dont-send nil))))))
-
-(defalias 'tramp-submit-bug 'tramp-bug)
-
 ;; Checklist for `tramp-unload-hook'
 ;; - Unload all `tramp-*' packages
 ;; - Reset `file-name-handler-alist'
@@ -7282,18 +7249,6 @@ please ensure that the buffers are attached to your email.\n\n")
 
 (provide 'tramp)
 
-;; Make sure that we get integration with the VC package.
-;; When it is loaded, we need to pull in the integration module.
-;; This must come after (provide 'tramp) because tramp-vc.el
-;; requires tramp.  Not necessary in Emacs 23.
-(eval-after-load "vc"
-  '(unless (functionp 'start-file-process)
-     (require 'tramp-vc)
-     (add-hook 'tramp-unload-hook
-              '(lambda ()
-                 (when (featurep 'tramp-vc)
-                   (unload-feature 'tramp-vc 'force))))))
-
 ;;; TODO:
 
 ;; * Allow putting passwords in the filename.
@@ -7309,22 +7264,8 @@ please ensure that the buffers are attached to your email.\n\n")
 ;;   indefinitely blocking piece of code.  In this case it would be
 ;;   within Tramp around one of its calls to accept-process-output (or
 ;;   around one of the loops that calls accept-process-output)
-;;   (Stefann Monnier).
+;;   (Stefan Monnier).
 ;; * Autodetect if remote `ls' groks the "--dired" switch.
-;; * Add fallback for inline encodings.  This should be used
-;;   if the remote end doesn't support mimencode or a similar program.
-;;   For reading files from the remote host, we can just parse the output
-;;   of `od -b'.  For writing files to the remote host, we construct
-;;   a shell program which contains only "safe" ascii characters
-;;   and which writes the right bytes to the file.  We can use printf(1)
-;;   or "echo -e" or the printf function in awk and use octal escapes
-;;   for the "dangerous" characters.  The null byte might be a problem.
-;;   On some systems, the octal escape doesn't work.  So we try the following
-;;   two commands to write a null byte:
-;;   dd if=/dev/zero bs=1 count=1
-;;   echo | tr '\n' '\000'
-;; * Cooperate with PCL-CVS.  It uses start-process, which doesn't
-;;   work for remote files.
 ;; * Rewrite `tramp-shell-quote-argument' to abstain from using
 ;;   `shell-quote-argument'.
 ;; * Completion gets confused when you leave out the method name.
@@ -7350,7 +7291,6 @@ please ensure that the buffers are attached to your email.\n\n")
 ;; * Grok `append' parameter for `write-region'.
 ;; * Test remote ksh or bash for tilde expansion in `tramp-find-shell'?
 ;; * abbreviate-file-name
-;; * grok ~ in tramp-remote-path  (Henrik Holm <henrikh@tele.ntnu.no>)
 ;; * better error checking.  At least whenever we see something
 ;;   strange when doing zerop, we should kill the process and start
 ;;   again.  (Greg Stark)
@@ -7358,24 +7298,17 @@ please ensure that the buffers are attached to your email.\n\n")
 ;;   transfer method to use.  (Greg Stark)
 ;; * Remove unneeded parameters from methods.
 ;; * Invoke rsync once for copying a whole directory hierarchy.
-;;   (Francesco Potort\e,Al\e(B)
+;;   (Francesco Potortì)
 ;; * Make it work for different encodings, and for different file name
 ;;   encodings, too.  (Daniel Pittman)
-;; * Clean up unused *tramp/foo* buffers after a while.  (Pete Forman)
 ;; * Progress reports while copying files.  (Michael Kifer)
 ;; * Don't search for perl5 and perl.  Instead, only search for perl and
 ;;   then look if it's the right version (with `perl -v').
 ;; * When editing a remote CVS controlled file as a different user, VC
 ;;   gets confused about the file locking status.  Try to find out why
 ;;   the workaround doesn't work.
-;; * Change `copy-file' to grok the case where the filename handler
-;;   for the source and the target file are different.  Right now,
-;;   it looks at the source file and then calls that handler, if
-;;   there is one.  But since ange-ftp, for instance, does not know
-;;   about Tramp, it does not do the right thing if the target file
-;;   name is a Tramp name.
 ;; * Username and hostname completion.
-;; ** Try to avoid usage of `last-input-event' in `tramp-completion-mode'.
+;; ** Try to avoid usage of `last-input-event' in `tramp-completion-mode-p'.
 ;; ** Unify `tramp-parse-{rhosts,shosts,sconfig,hosts,passwd,netrc}'.
 ;;    Code is nearly identical.
 ;; * Allow out-of-band methods as _last_ multi-hop.
@@ -7395,29 +7328,18 @@ please ensure that the buffers are attached to your email.\n\n")
 ;;   having the possibility of passing a local file there to a local
 ;;   Emacs session (in case I can arrange for a connection back) would
 ;;   be nice.
-;;   Likely the corresponding tramp server should not allow the
+;;   Likely the corresponding Tramp server should not allow the
 ;;   equivalent of the emacsclient -eval option in order to make this
 ;;   reasonably unproblematic.  And maybe trampclient should have some
 ;;   way of passing credentials, like by using an SSL socket or
 ;;   something. (David Kastrup)
 ;; * Could Tramp reasonably look for a prompt after ^M rather than
 ;;   only after ^J ? (Stefan Monnier)
-;; * WIBNI there was an interactive command prompting for tramp
-;;   method, hostname, username and filename and translates the user
-;;   input into the correct filename syntax (depending on the Emacs
-;;   flavor) (Reiner Steib)
-;; * Let the user edit the connection properties interactively.
-;;   Something like `gnus-server-edit-server' in Gnus' *Server* buffer.
 ;; * Reconnect directly to a compliant shell without first going
 ;;   through the user's default shell. (Pete Forman)
-;; * It's just that when I come to Customize `tramp-default-user-alist'
-;;   I'm presented with a mismatch and raw lisp for a value.  It is my
-;;   understanding that a variable declared with defcustom is a User
-;;   Option and should not be modified by the code.  add-to-list is
-;;   called in several places. One way to handle that is to have a new
-;;   ordinary variable that gets its initial value from
-;;   tramp-default-user-alist and then is added to. (Pete Forman)
 ;; * Make `tramp-default-user' obsolete.
+;; * Tramp shall reconnect automatically to its ssh connection when it
+;;   detects that the process "has died". (David Reitter)
 
 ;; Functions for file-name-handler-alist:
 ;; diff-latest-backup-file -- in diff.el