]> code.delx.au - gnu-emacs/commitdiff
(tramp-open-connection-setup-interactive-shell): Flush cache, and
authorMichael Albinus <michael.albinus@gmx.de>
Sun, 15 Jun 2008 16:59:25 +0000 (16:59 +0000)
committerMichael Albinus <michael.albinus@gmx.de>
Sun, 15 Jun 2008 16:59:25 +0000 (16:59 +0000)
restart `tramp-maybe-open-connection' when the remote system has
been changed. Throw 'uname-changed event.
(tramp-maybe-open-connection): Catch it.

lisp/ChangeLog
lisp/net/tramp.el

index 0d3d3a40638e1f1712e2b4ce2bef6aa6f000fc04..6f7b1ce01b253c3008c9e3bd096974e26647facf 100644 (file)
        modification time of the connection buffer.
        (tramp-sh-file-name-handler): Reset `tramp-locked' in case of
        error.
+       (tramp-open-connection-setup-interactive-shell): Flush cache, and
+       restart `tramp-maybe-open-connection' when the remote system has
+       been changed. Throw 'uname-changed event.
+       (tramp-maybe-open-connection): Catch it.
 
        * net/tramp-cmds.el (tramp-cleanup-all-connections): Reset
        `tramp-locked'.
index 943a7a66b5505641309139e3333a5baef8837898..5918db6df4a1baa598916aba32c2bcaf4a4746b4 100644 (file)
@@ -5846,7 +5846,8 @@ process to set up.  VEC specifies the connection."
 
   ;; Check whether the output of "uname -sr" has been changed.  If
   ;; yes, this is a strong indication that we must expire all
-  ;; connection properties.
+  ;; connection properties.  We start again with
+  ;; `tramp-maybe-open-connection', it will be catched there.
   (tramp-message vec 5 "Checking system information")
   (let ((old-uname (tramp-get-connection-property vec "uname" nil))
        (new-uname
@@ -5854,12 +5855,20 @@ process to set up.  VEC specifies the connection."
          vec "uname"
          (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\""))))
     (when (and (stringp old-uname) (not (string-equal old-uname new-uname)))
-      (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)))))
+      (with-current-buffer (tramp-get-debug-buffer vec)
+       ;; Keep the debug buffer
+       (rename-buffer " *temp*" 'unique)
+       (funcall (symbol-function 'tramp-cleanup-connection) vec)
+       (if (= (point-min) (point-max))
+           (kill-buffer nil)
+         (rename-buffer (tramp-debug-buffer-name vec) 'unique))
+       ;; We call `tramp-get-buffer' in order to keep the debug buffer.
+       (tramp-get-buffer vec)
+       (tramp-message
+        vec 3
+        "Connection reset, because remote host changed from `%s' to `%s'"
+        old-uname new-uname)
+       (throw 'uname-changed (tramp-maybe-open-connection vec)))))
 
   ;; Check whether the remote host suffers from buggy
   ;; `send-process-string'.  This is known for FreeBSD (see comment in
@@ -6222,167 +6231,168 @@ 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))
-       (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
-    ;; using ssh, it can sometimes happen that the remote end has hung
-    ;; up but the local ssh client doesn't recognize this until it
-    ;; 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.
-    (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)
-       (tramp-flush-connection-property p)
-       (delete-process p)
-       (setq p nil)))
-
-    ;; New connection must be opened.
-    (unless (and p (processp p) (memq (process-status p) '(run open)))
-
-      ;; We call `tramp-get-buffer' in order to get a debug buffer for
-      ;; messages from the beginning.
-      (tramp-get-buffer vec)
-      (if (zerop (length (tramp-file-name-user vec)))
+  (catch 'uname-changed
+    (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
+      ;; using ssh, it can sometimes happen that the remote end has
+      ;; hung up but the local ssh client doesn't recognize this until
+      ;; it 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.
+      (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)
+        (tramp-flush-connection-property p)
+        (delete-process p)
+        (setq p nil)))
+
+      ;; New connection must be opened.
+      (unless (and p (processp p) (memq (process-status p) '(run open)))
+
+       ;; We call `tramp-get-buffer' in order to get a debug buffer for
+       ;; messages from the beginning.
+       (tramp-get-buffer vec)
+       (if (zerop (length (tramp-file-name-user vec)))
+           (tramp-message
+            vec 3 "Opening connection for %s using %s..."
+            (tramp-file-name-host vec)
+            (tramp-file-name-method vec))
          (tramp-message
-          vec 3 "Opening connection for %s using %s..."
+          vec 3 "Opening connection for %s@%s using %s..."
+          (tramp-file-name-user vec)
           (tramp-file-name-host vec)
-          (tramp-file-name-method vec))
-       (tramp-message
-        vec 3 "Opening connection for %s@%s using %s..."
-        (tramp-file-name-user vec)
-        (tramp-file-name-host vec)
-        (tramp-file-name-method vec)))
-
-      ;; Start new process.
-      (when (and p (processp p))
-       (delete-process p))
-      (setenv "TERM" tramp-terminal-type)
-      (setenv "LC_ALL" "C")
-      (setenv "PROMPT_COMMAND")
-      (setenv "PS1" "$ ")
-      (let* ((target-alist (tramp-compute-multi-hops vec))
-            (process-connection-type tramp-process-connection-type)
-            (process-adaptive-read-buffering nil)
-            (coding-system-for-read nil)
-            ;; This must be done in order to avoid our file name handler.
-            (p (let ((default-directory
-                       (tramp-compat-temporary-file-directory)))
-                 (start-process
-                  (or (tramp-get-connection-property vec "process-name" nil)
-                      (tramp-buffer-name vec))
-                  (tramp-get-connection-buffer vec)
-                  tramp-encoding-shell)))
-            (first-hop t))
+          (tramp-file-name-method vec)))
+
+       ;; Start new process.
+       (when (and p (processp p))
+         (delete-process p))
+       (setenv "TERM" tramp-terminal-type)
+       (setenv "LC_ALL" "C")
+       (setenv "PROMPT_COMMAND")
+       (setenv "PS1" "$ ")
+       (let* ((target-alist (tramp-compute-multi-hops vec))
+              (process-connection-type tramp-process-connection-type)
+              (process-adaptive-read-buffering nil)
+              (coding-system-for-read nil)
+              ;; This must be done in order to avoid our file name handler.
+              (p (let ((default-directory
+                         (tramp-compat-temporary-file-directory)))
+                   (start-process
+                    (or (tramp-get-connection-property vec "process-name" nil)
+                        (tramp-buffer-name vec))
+                    (tramp-get-connection-buffer vec)
+                    tramp-encoding-shell)))
+              (first-hop t))
 
-       (tramp-message
-        vec 6 "%s" (mapconcat 'identity (process-command p) " "))
-
-       ;; Check whether process is alive.
-       (set-process-sentinel p 'tramp-process-sentinel)
-       (tramp-set-process-query-on-exit-flag p nil)
-       (tramp-message vec 3 "Waiting 60s for local shell to come up...")
-       (tramp-barf-if-no-shell-prompt
-        p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell)
-
-       ;; Now do all the connections as specified.
-       (while target-alist
-         (let* ((hop (car target-alist))
-                (l-method (tramp-file-name-method hop))
-                (l-user (tramp-file-name-user hop))
-                (l-host (tramp-file-name-host hop))
-                (l-port nil)
-                (login-program
-                 (tramp-get-method-parameter l-method 'tramp-login-program))
-                (login-args
-                 (tramp-get-method-parameter l-method 'tramp-login-args))
-                (gw-args
-                 (tramp-get-method-parameter l-method 'tramp-gw-args))
-                (gw (tramp-get-file-property hop "" "gateway" nil))
-                (g-method (and gw (tramp-file-name-method gw)))
-                (g-user (and gw (tramp-file-name-user gw)))
-                (g-host (and gw (tramp-file-name-host gw)))
-                (command login-program)
-                ;; We don't create the temporary file.  In fact, it
-                ;; is just a prefix for the ControlPath option of
-                ;; ssh; the real temporary file has another name, and
-                ;; it is created and protected by ssh.  It is also
-                ;; removed by ssh, when the connection is closed.
-                (tmpfile
-                 (tramp-set-connection-property
-                  p "temp-file"
-                  (make-temp-name
-                   (expand-file-name
-                    tramp-temp-name-prefix
-                    (tramp-compat-temporary-file-directory)))))
-                spec)
-
-           ;; Add gateway arguments if necessary.
-           (when (and gw gw-args)
-             (setq login-args (append login-args gw-args)))
-
-           ;; Check for port number.  Until now, there's no need for handling
-           ;; like method, user, host.
-           (when (string-match tramp-host-with-port-regexp l-host)
-             (setq l-port (match-string 2 l-host)
-                   l-host (match-string 1 l-host)))
-
-           ;; Set variables for computing the prompt for reading password.
-           ;; They can also be derived from a gatewy.
-           (setq tramp-current-method (or g-method l-method)
-                 tramp-current-user   (or g-user   l-user)
-                 tramp-current-host   (or g-host   l-host))
-
-           ;; Replace login-args place holders.
-           (setq
-            l-host (or l-host "")
-            l-user (or l-user "")
-            l-port (or l-port "")
-            spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
-                   (?t . ,tmpfile))
-            command
-            (concat
-             command " "
-             (mapconcat
-              '(lambda (x)
-                 (setq x (mapcar '(lambda (y) (format-spec y spec)) x))
-                 (unless (member "" x) (mapconcat 'identity x " ")))
-              login-args " ")
-             ;; String to detect failed connection.  Every single word must
-             ;; be enclosed with '\"'; otherwise it is detected
-             ;; during connection setup.
-             ;; Local shell could be a Windows COMSPEC.  It doesn't know
-             ;; the ";" syntax, but we must exit always for `start-process'.
-             ;; "exec" does not work either.
-             (if first-hop
-                 " && exit || exit"
-               "; echo \"Tramp\" \"connection\" \"closed\"; sleep 1"))
-            ;; We don't reach a Windows shell.  Could be initial only.
-            first-hop nil)
-
-           ;; Send the command.
-           (tramp-message vec 3 "Sending command `%s'" command)
-           (tramp-send-command vec command t t)
-           (tramp-process-actions p vec tramp-actions-before-shell 60)
-           (tramp-message vec 3 "Found remote shell prompt on `%s'" l-host))
-         ;; Next hop.
-         (setq target-alist (cdr target-alist)))
-
-       ;; Make initial shell settings.
-       (tramp-open-connection-setup-interactive-shell p vec)))))
+         (tramp-message
+          vec 6 "%s" (mapconcat 'identity (process-command p) " "))
+
+         ;; Check whether process is alive.
+         (set-process-sentinel p 'tramp-process-sentinel)
+         (tramp-set-process-query-on-exit-flag p nil)
+         (tramp-message vec 3 "Waiting 60s for local shell to come up...")
+         (tramp-barf-if-no-shell-prompt
+          p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell)
+
+         ;; Now do all the connections as specified.
+         (while target-alist
+           (let* ((hop (car target-alist))
+                  (l-method (tramp-file-name-method hop))
+                  (l-user (tramp-file-name-user hop))
+                  (l-host (tramp-file-name-host hop))
+                  (l-port nil)
+                  (login-program
+                   (tramp-get-method-parameter l-method 'tramp-login-program))
+                  (login-args
+                   (tramp-get-method-parameter l-method 'tramp-login-args))
+                  (gw-args
+                   (tramp-get-method-parameter l-method 'tramp-gw-args))
+                  (gw (tramp-get-file-property hop "" "gateway" nil))
+                  (g-method (and gw (tramp-file-name-method gw)))
+                  (g-user (and gw (tramp-file-name-user gw)))
+                  (g-host (and gw (tramp-file-name-host gw)))
+                  (command login-program)
+                  ;; We don't create the temporary file.  In fact, it
+                  ;; is just a prefix for the ControlPath option of
+                  ;; ssh; the real temporary file has another name, and
+                  ;; it is created and protected by ssh.  It is also
+                  ;; removed by ssh, when the connection is closed.
+                  (tmpfile
+                   (tramp-set-connection-property
+                    p "temp-file"
+                    (make-temp-name
+                     (expand-file-name
+                      tramp-temp-name-prefix
+                      (tramp-compat-temporary-file-directory)))))
+                  spec)
+
+             ;; Add gateway arguments if necessary.
+             (when (and gw gw-args)
+               (setq login-args (append login-args gw-args)))
+
+             ;; Check for port number.  Until now, there's no need
+             ;; for handling like method, user, host.
+             (when (string-match tramp-host-with-port-regexp l-host)
+               (setq l-port (match-string 2 l-host)
+                     l-host (match-string 1 l-host)))
+
+             ;; Set variables for computing the prompt for reading
+             ;; password.  They can also be derived from a gatewy.
+             (setq tramp-current-method (or g-method l-method)
+                   tramp-current-user   (or g-user   l-user)
+                   tramp-current-host   (or g-host   l-host))
+
+             ;; Replace login-args place holders.
+             (setq
+              l-host (or l-host "")
+              l-user (or l-user "")
+              l-port (or l-port "")
+              spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
+                     (?t . ,tmpfile))
+              command
+              (concat
+               command " "
+               (mapconcat
+                '(lambda (x)
+                   (setq x (mapcar '(lambda (y) (format-spec y spec)) x))
+                   (unless (member "" x) (mapconcat 'identity x " ")))
+                login-args " ")
+               ;; String to detect failed connection.  Every single
+               ;; word must be enclosed with '\"'; otherwise it is
+               ;; detected during connection setup.
+               ;; Local shell could be a Windows COMSPEC.  It doesn't
+               ;; know the ";" syntax, but we must exit always for
+               ;; `start-process'.  "exec" does not work either.
+               (if first-hop
+                   " && exit || exit"
+                 "; echo \"Tramp\" \"connection\" \"closed\"; sleep 1"))
+              ;; We don't reach a Windows shell.  Could be initial only.
+              first-hop nil)
+
+             ;; Send the command.
+             (tramp-message vec 3 "Sending command `%s'" command)
+             (tramp-send-command vec command t t)
+             (tramp-process-actions p vec tramp-actions-before-shell 60)
+             (tramp-message vec 3 "Found remote shell prompt on `%s'" l-host))
+           ;; Next hop.
+           (setq target-alist (cdr target-alist)))
+
+         ;; Make initial shell settings.
+         (tramp-open-connection-setup-interactive-shell p vec))))))
 
 (defun tramp-send-command (vec command &optional neveropen nooutput)
   "Send the COMMAND to connection VEC.