Mercurial > emacs
comparison lisp/net/tramp.el @ 95967:13aa0133c5af
(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.
author | Michael Albinus <michael.albinus@gmx.de> |
---|---|
date | Sun, 15 Jun 2008 16:57:03 +0000 |
parents | a20bb74ebe03 |
children | a99299e4d2de |
comparison
equal
deleted
inserted
replaced
95966:054335cbee3d | 95967:13aa0133c5af |
---|---|
5844 (tramp-send-command vec "stty -onlcr" t)))) | 5844 (tramp-send-command vec "stty -onlcr" t)))) |
5845 (tramp-send-command vec "set +o vi +o emacs" t) | 5845 (tramp-send-command vec "set +o vi +o emacs" t) |
5846 | 5846 |
5847 ;; Check whether the output of "uname -sr" has been changed. If | 5847 ;; Check whether the output of "uname -sr" has been changed. If |
5848 ;; yes, this is a strong indication that we must expire all | 5848 ;; yes, this is a strong indication that we must expire all |
5849 ;; connection properties. | 5849 ;; connection properties. We start again with |
5850 ;; `tramp-maybe-open-connection', it will be catched there. | |
5850 (tramp-message vec 5 "Checking system information") | 5851 (tramp-message vec 5 "Checking system information") |
5851 (let ((old-uname (tramp-get-connection-property vec "uname" nil)) | 5852 (let ((old-uname (tramp-get-connection-property vec "uname" nil)) |
5852 (new-uname | 5853 (new-uname |
5853 (tramp-set-connection-property | 5854 (tramp-set-connection-property |
5854 vec "uname" | 5855 vec "uname" |
5855 (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\"")))) | 5856 (tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\"")))) |
5856 (when (and (stringp old-uname) (not (string-equal old-uname new-uname))) | 5857 (when (and (stringp old-uname) (not (string-equal old-uname new-uname))) |
5857 (funcall (symbol-function 'tramp-cleanup-connection) vec) | 5858 (with-current-buffer (tramp-get-debug-buffer vec) |
5858 (signal | 5859 ;; Keep the debug buffer |
5859 'quit | 5860 (rename-buffer " *temp*" 'unique) |
5860 (list (format | 5861 (funcall (symbol-function 'tramp-cleanup-connection) vec) |
5861 "Connection reset, because remote host changed from `%s' to `%s'" | 5862 (if (= (point-min) (point-max)) |
5862 old-uname new-uname))))) | 5863 (kill-buffer nil) |
5864 (rename-buffer (tramp-debug-buffer-name vec) 'unique)) | |
5865 ;; We call `tramp-get-buffer' in order to keep the debug buffer. | |
5866 (tramp-get-buffer vec) | |
5867 (tramp-message | |
5868 vec 3 | |
5869 "Connection reset, because remote host changed from `%s' to `%s'" | |
5870 old-uname new-uname) | |
5871 (throw 'uname-changed (tramp-maybe-open-connection vec))))) | |
5863 | 5872 |
5864 ;; Check whether the remote host suffers from buggy | 5873 ;; Check whether the remote host suffers from buggy |
5865 ;; `send-process-string'. This is known for FreeBSD (see comment in | 5874 ;; `send-process-string'. This is known for FreeBSD (see comment in |
5866 ;; `send_process', file process.c). I've tested sending 624 bytes | 5875 ;; `send_process', file process.c). I've tested sending 624 bytes |
5867 ;; successfully, sending 625 bytes failed. Emacs makes a hack when | 5876 ;; successfully, sending 625 bytes failed. Emacs makes a hack when |
6220 | 6229 |
6221 (defun tramp-maybe-open-connection (vec) | 6230 (defun tramp-maybe-open-connection (vec) |
6222 "Maybe open a connection VEC. | 6231 "Maybe open a connection VEC. |
6223 Does not do anything if a connection is already open, but re-opens the | 6232 Does not do anything if a connection is already open, but re-opens the |
6224 connection if a previous connection has died for some reason." | 6233 connection if a previous connection has died for some reason." |
6225 (let ((p (tramp-get-connection-process vec)) | 6234 (catch 'uname-changed |
6226 (process-environment (copy-sequence process-environment))) | 6235 (let ((p (tramp-get-connection-process vec)) |
6227 | 6236 (process-environment (copy-sequence process-environment))) |
6228 ;; If too much time has passed since last command was sent, look | 6237 |
6229 ;; whether process is still alive. If it isn't, kill it. When | 6238 ;; If too much time has passed since last command was sent, look |
6230 ;; using ssh, it can sometimes happen that the remote end has hung | 6239 ;; whether process is still alive. If it isn't, kill it. When |
6231 ;; up but the local ssh client doesn't recognize this until it | 6240 ;; using ssh, it can sometimes happen that the remote end has |
6232 ;; tries to send some data to the remote end. So that's why we | 6241 ;; hung up but the local ssh client doesn't recognize this until |
6233 ;; try to send a command from time to time, then look again | 6242 ;; it tries to send some data to the remote end. So that's why |
6234 ;; whether the process is really alive. | 6243 ;; we try to send a command from time to time, then look again |
6235 (condition-case nil | 6244 ;; whether the process is really alive. |
6236 (when (and (> (tramp-time-diff | 6245 (condition-case nil |
6237 (current-time) | 6246 (when (and (> (tramp-time-diff |
6238 (tramp-get-connection-property | 6247 (current-time) |
6239 p "last-cmd-time" '(0 0 0))) | 6248 (tramp-get-connection-property |
6240 60) | 6249 p "last-cmd-time" '(0 0 0))) |
6241 p (processp p) (memq (process-status p) '(run open))) | 6250 60) |
6242 (tramp-send-command vec "echo are you awake" t t) | 6251 p (processp p) (memq (process-status p) '(run open))) |
6243 (unless (and (memq (process-status p) '(run open)) | 6252 (tramp-send-command vec "echo are you awake" t t) |
6244 (tramp-wait-for-output p 10)) | 6253 (unless (and (memq (process-status p) '(run open)) |
6245 ;; The error will be catched locally. | 6254 (tramp-wait-for-output p 10)) |
6246 (tramp-error vec 'file-error "Awake did fail"))) | 6255 ;; The error will be catched locally. |
6247 (file-error | 6256 (tramp-error vec 'file-error "Awake did fail"))) |
6248 (tramp-flush-connection-property vec) | 6257 (file-error |
6249 (tramp-flush-connection-property p) | 6258 (tramp-flush-connection-property vec) |
6250 (delete-process p) | 6259 (tramp-flush-connection-property p) |
6251 (setq p nil))) | 6260 (delete-process p) |
6252 | 6261 (setq p nil))) |
6253 ;; New connection must be opened. | 6262 |
6254 (unless (and p (processp p) (memq (process-status p) '(run open))) | 6263 ;; New connection must be opened. |
6255 | 6264 (unless (and p (processp p) (memq (process-status p) '(run open))) |
6256 ;; We call `tramp-get-buffer' in order to get a debug buffer for | 6265 |
6257 ;; messages from the beginning. | 6266 ;; We call `tramp-get-buffer' in order to get a debug buffer for |
6258 (tramp-get-buffer vec) | 6267 ;; messages from the beginning. |
6259 (if (zerop (length (tramp-file-name-user vec))) | 6268 (tramp-get-buffer vec) |
6269 (if (zerop (length (tramp-file-name-user vec))) | |
6270 (tramp-message | |
6271 vec 3 "Opening connection for %s using %s..." | |
6272 (tramp-file-name-host vec) | |
6273 (tramp-file-name-method vec)) | |
6260 (tramp-message | 6274 (tramp-message |
6261 vec 3 "Opening connection for %s using %s..." | 6275 vec 3 "Opening connection for %s@%s using %s..." |
6276 (tramp-file-name-user vec) | |
6262 (tramp-file-name-host vec) | 6277 (tramp-file-name-host vec) |
6263 (tramp-file-name-method vec)) | 6278 (tramp-file-name-method vec))) |
6264 (tramp-message | 6279 |
6265 vec 3 "Opening connection for %s@%s using %s..." | 6280 ;; Start new process. |
6266 (tramp-file-name-user vec) | 6281 (when (and p (processp p)) |
6267 (tramp-file-name-host vec) | 6282 (delete-process p)) |
6268 (tramp-file-name-method vec))) | 6283 (setenv "TERM" tramp-terminal-type) |
6269 | 6284 (setenv "LC_ALL" "C") |
6270 ;; Start new process. | 6285 (setenv "PROMPT_COMMAND") |
6271 (when (and p (processp p)) | 6286 (setenv "PS1" "$ ") |
6272 (delete-process p)) | 6287 (let* ((target-alist (tramp-compute-multi-hops vec)) |
6273 (setenv "TERM" tramp-terminal-type) | 6288 (process-connection-type tramp-process-connection-type) |
6274 (setenv "LC_ALL" "C") | 6289 (process-adaptive-read-buffering nil) |
6275 (setenv "PROMPT_COMMAND") | 6290 (coding-system-for-read nil) |
6276 (setenv "PS1" "$ ") | 6291 ;; This must be done in order to avoid our file name handler. |
6277 (let* ((target-alist (tramp-compute-multi-hops vec)) | 6292 (p (let ((default-directory |
6278 (process-connection-type tramp-process-connection-type) | 6293 (tramp-compat-temporary-file-directory))) |
6279 (process-adaptive-read-buffering nil) | 6294 (start-process |
6280 (coding-system-for-read nil) | 6295 (or (tramp-get-connection-property vec "process-name" nil) |
6281 ;; This must be done in order to avoid our file name handler. | 6296 (tramp-buffer-name vec)) |
6282 (p (let ((default-directory | 6297 (tramp-get-connection-buffer vec) |
6283 (tramp-compat-temporary-file-directory))) | 6298 tramp-encoding-shell))) |
6284 (start-process | 6299 (first-hop t)) |
6285 (or (tramp-get-connection-property vec "process-name" nil) | 6300 |
6286 (tramp-buffer-name vec)) | 6301 (tramp-message |
6287 (tramp-get-connection-buffer vec) | 6302 vec 6 "%s" (mapconcat 'identity (process-command p) " ")) |
6288 tramp-encoding-shell))) | 6303 |
6289 (first-hop t)) | 6304 ;; Check whether process is alive. |
6290 | 6305 (set-process-sentinel p 'tramp-process-sentinel) |
6291 (tramp-message | 6306 (tramp-set-process-query-on-exit-flag p nil) |
6292 vec 6 "%s" (mapconcat 'identity (process-command p) " ")) | 6307 (tramp-message vec 3 "Waiting 60s for local shell to come up...") |
6293 | 6308 (tramp-barf-if-no-shell-prompt |
6294 ;; Check whether process is alive. | 6309 p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell) |
6295 (set-process-sentinel p 'tramp-process-sentinel) | 6310 |
6296 (tramp-set-process-query-on-exit-flag p nil) | 6311 ;; Now do all the connections as specified. |
6297 (tramp-message vec 3 "Waiting 60s for local shell to come up...") | 6312 (while target-alist |
6298 (tramp-barf-if-no-shell-prompt | 6313 (let* ((hop (car target-alist)) |
6299 p 60 "Couldn't find local shell prompt %s" tramp-encoding-shell) | 6314 (l-method (tramp-file-name-method hop)) |
6300 | 6315 (l-user (tramp-file-name-user hop)) |
6301 ;; Now do all the connections as specified. | 6316 (l-host (tramp-file-name-host hop)) |
6302 (while target-alist | 6317 (l-port nil) |
6303 (let* ((hop (car target-alist)) | 6318 (login-program |
6304 (l-method (tramp-file-name-method hop)) | 6319 (tramp-get-method-parameter l-method 'tramp-login-program)) |
6305 (l-user (tramp-file-name-user hop)) | 6320 (login-args |
6306 (l-host (tramp-file-name-host hop)) | 6321 (tramp-get-method-parameter l-method 'tramp-login-args)) |
6307 (l-port nil) | 6322 (gw-args |
6308 (login-program | 6323 (tramp-get-method-parameter l-method 'tramp-gw-args)) |
6309 (tramp-get-method-parameter l-method 'tramp-login-program)) | 6324 (gw (tramp-get-file-property hop "" "gateway" nil)) |
6310 (login-args | 6325 (g-method (and gw (tramp-file-name-method gw))) |
6311 (tramp-get-method-parameter l-method 'tramp-login-args)) | 6326 (g-user (and gw (tramp-file-name-user gw))) |
6312 (gw-args | 6327 (g-host (and gw (tramp-file-name-host gw))) |
6313 (tramp-get-method-parameter l-method 'tramp-gw-args)) | 6328 (command login-program) |
6314 (gw (tramp-get-file-property hop "" "gateway" nil)) | 6329 ;; We don't create the temporary file. In fact, it |
6315 (g-method (and gw (tramp-file-name-method gw))) | 6330 ;; is just a prefix for the ControlPath option of |
6316 (g-user (and gw (tramp-file-name-user gw))) | 6331 ;; ssh; the real temporary file has another name, and |
6317 (g-host (and gw (tramp-file-name-host gw))) | 6332 ;; it is created and protected by ssh. It is also |
6318 (command login-program) | 6333 ;; removed by ssh, when the connection is closed. |
6319 ;; We don't create the temporary file. In fact, it | 6334 (tmpfile |
6320 ;; is just a prefix for the ControlPath option of | 6335 (tramp-set-connection-property |
6321 ;; ssh; the real temporary file has another name, and | 6336 p "temp-file" |
6322 ;; it is created and protected by ssh. It is also | 6337 (make-temp-name |
6323 ;; removed by ssh, when the connection is closed. | 6338 (expand-file-name |
6324 (tmpfile | 6339 tramp-temp-name-prefix |
6325 (tramp-set-connection-property | 6340 (tramp-compat-temporary-file-directory))))) |
6326 p "temp-file" | 6341 spec) |
6327 (make-temp-name | 6342 |
6328 (expand-file-name | 6343 ;; Add gateway arguments if necessary. |
6329 tramp-temp-name-prefix | 6344 (when (and gw gw-args) |
6330 (tramp-compat-temporary-file-directory))))) | 6345 (setq login-args (append login-args gw-args))) |
6331 spec) | 6346 |
6332 | 6347 ;; Check for port number. Until now, there's no need |
6333 ;; Add gateway arguments if necessary. | 6348 ;; for handling like method, user, host. |
6334 (when (and gw gw-args) | 6349 (when (string-match tramp-host-with-port-regexp l-host) |
6335 (setq login-args (append login-args gw-args))) | 6350 (setq l-port (match-string 2 l-host) |
6336 | 6351 l-host (match-string 1 l-host))) |
6337 ;; Check for port number. Until now, there's no need for handling | 6352 |
6338 ;; like method, user, host. | 6353 ;; Set variables for computing the prompt for reading |
6339 (when (string-match tramp-host-with-port-regexp l-host) | 6354 ;; password. They can also be derived from a gatewy. |
6340 (setq l-port (match-string 2 l-host) | 6355 (setq tramp-current-method (or g-method l-method) |
6341 l-host (match-string 1 l-host))) | 6356 tramp-current-user (or g-user l-user) |
6342 | 6357 tramp-current-host (or g-host l-host)) |
6343 ;; Set variables for computing the prompt for reading password. | 6358 |
6344 ;; They can also be derived from a gatewy. | 6359 ;; Replace login-args place holders. |
6345 (setq tramp-current-method (or g-method l-method) | 6360 (setq |
6346 tramp-current-user (or g-user l-user) | 6361 l-host (or l-host "") |
6347 tramp-current-host (or g-host l-host)) | 6362 l-user (or l-user "") |
6348 | 6363 l-port (or l-port "") |
6349 ;; Replace login-args place holders. | 6364 spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port) |
6350 (setq | 6365 (?t . ,tmpfile)) |
6351 l-host (or l-host "") | 6366 command |
6352 l-user (or l-user "") | 6367 (concat |
6353 l-port (or l-port "") | 6368 command " " |
6354 spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port) | 6369 (mapconcat |
6355 (?t . ,tmpfile)) | 6370 '(lambda (x) |
6356 command | 6371 (setq x (mapcar '(lambda (y) (format-spec y spec)) x)) |
6357 (concat | 6372 (unless (member "" x) (mapconcat 'identity x " "))) |
6358 command " " | 6373 login-args " ") |
6359 (mapconcat | 6374 ;; String to detect failed connection. Every single |
6360 '(lambda (x) | 6375 ;; word must be enclosed with '\"'; otherwise it is |
6361 (setq x (mapcar '(lambda (y) (format-spec y spec)) x)) | 6376 ;; detected during connection setup. |
6362 (unless (member "" x) (mapconcat 'identity x " "))) | 6377 ;; Local shell could be a Windows COMSPEC. It doesn't |
6363 login-args " ") | 6378 ;; know the ";" syntax, but we must exit always for |
6364 ;; String to detect failed connection. Every single word must | 6379 ;; `start-process'. "exec" does not work either. |
6365 ;; be enclosed with '\"'; otherwise it is detected | 6380 (if first-hop |
6366 ;; during connection setup. | 6381 " && exit || exit" |
6367 ;; Local shell could be a Windows COMSPEC. It doesn't know | 6382 "; echo \"Tramp\" \"connection\" \"closed\"; sleep 1")) |
6368 ;; the ";" syntax, but we must exit always for `start-process'. | 6383 ;; We don't reach a Windows shell. Could be initial only. |
6369 ;; "exec" does not work either. | 6384 first-hop nil) |
6370 (if first-hop | 6385 |
6371 " && exit || exit" | 6386 ;; Send the command. |
6372 "; echo \"Tramp\" \"connection\" \"closed\"; sleep 1")) | 6387 (tramp-message vec 3 "Sending command `%s'" command) |
6373 ;; We don't reach a Windows shell. Could be initial only. | 6388 (tramp-send-command vec command t t) |
6374 first-hop nil) | 6389 (tramp-process-actions p vec tramp-actions-before-shell 60) |
6375 | 6390 (tramp-message vec 3 "Found remote shell prompt on `%s'" l-host)) |
6376 ;; Send the command. | 6391 ;; Next hop. |
6377 (tramp-message vec 3 "Sending command `%s'" command) | 6392 (setq target-alist (cdr target-alist))) |
6378 (tramp-send-command vec command t t) | 6393 |
6379 (tramp-process-actions p vec tramp-actions-before-shell 60) | 6394 ;; Make initial shell settings. |
6380 (tramp-message vec 3 "Found remote shell prompt on `%s'" l-host)) | 6395 (tramp-open-connection-setup-interactive-shell p vec)))))) |
6381 ;; Next hop. | |
6382 (setq target-alist (cdr target-alist))) | |
6383 | |
6384 ;; Make initial shell settings. | |
6385 (tramp-open-connection-setup-interactive-shell p vec))))) | |
6386 | 6396 |
6387 (defun tramp-send-command (vec command &optional neveropen nooutput) | 6397 (defun tramp-send-command (vec command &optional neveropen nooutput) |
6388 "Send the COMMAND to connection VEC. | 6398 "Send the COMMAND to connection VEC. |
6389 Erases temporary buffer before sending the command. If optional | 6399 Erases temporary buffer before sending the command. If optional |
6390 arg NEVEROPEN is non-nil, never try to open the connection. This | 6400 arg NEVEROPEN is non-nil, never try to open the connection. This |