"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-regexp
- proc timeout
- (format
- "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
- (apply 'tramp-error-with-buffer nil proc 'file-error error-args)))
+ (let ((vec (tramp-get-connection-property proc "vector" nil)))
+ (condition-case err
+ (tramp-wait-for-regexp
+ proc timeout
+ (format
+ "\\(%s\\|%s\\)\\'" shell-prompt-pattern tramp-shell-prompt-pattern))
+ (error
+ (delete-process proc)
+ (apply 'tramp-error-with-buffer
+ (tramp-get-connection-buffer vec) vec 'file-error error-args)))))
(defun tramp-open-connection-setup-interactive-shell (proc vec)
"Set up an interactive shell.
;; Result.
target-alist))
-(defvar tramp-current-connection nil
- "Last connection timestamp.")
-
(defun tramp-maybe-open-connection (vec)
"Maybe open a connection VEC.
Does not do anything if a connection is already open, but re-opens the
;; If Tramp opens the same connection within a short time frame,
;; there is a problem. We shall signal this.
(unless (or (and p (processp p) (memq (process-status p) '(run open)))
- (not (equal (butlast (append vec nil))
+ (not (equal (butlast (append vec nil) 2)
(car tramp-current-connection)))
(> (tramp-time-diff
(current-time) (cdr tramp-current-connection))
(set-process-sentinel p 'tramp-process-sentinel)
(tramp-compat-set-process-query-on-exit-flag p nil)
(setq tramp-current-connection
- (cons (butlast (append vec nil)) (current-time))
+ (cons (butlast (append vec nil) 2) (current-time))
tramp-current-host (system-name))
(tramp-message
;; Check whether process is alive.
(tramp-barf-if-no-shell-prompt
p 60
- "Couldn't find local shell prompt %s" tramp-encoding-shell)
+ "Couldn't find local shell prompt for %s" tramp-encoding-shell)
;; Now do all the connections as specified.
(while target-alist
(defvar tramp-current-host nil
"Remote host for this *tramp* buffer.")
+(defvar tramp-current-connection nil
+ "Last connection timestamp.")
+
;;;###autoload
(defconst tramp-completion-file-name-handler-alist
'((file-name-all-completions . tramp-completion-handle-file-name-all-completions)
This variable is used to disable messages from `tramp-error'.
The messages are visible anyway, because an error is raised.")
-(defvar tramp-message-show-progress-reporter-message t
- "Show Tramp progress reporter message in the minibuffer.
-This variable is used to disable recursive progress reporter messages.")
-
(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
(or (and (bufferp buffer) buffer)
(and (processp vec-or-proc) (process-buffer vec-or-proc))
(tramp-get-connection-buffer vec-or-proc)))
- (when (string-equal fmt-string "Process died")
- (message
- "%s\n %s"
- "Tramp failed to connect. If this happens repeatedly, try"
- "`M-x tramp-cleanup-this-connection'"))
- (sit-for 30))))))
+ ;; `tramp-error' does not show messages. So we must do it ourselves.
+ (message fmt-string args)
+ (discard-input)
+ (sit-for 30)))
+ ;; Reset timestamp. It would be wrong after waiting for a while.
+ (when tramp-current-connection
+ (setcdr tramp-current-connection (current-time))))))
(defmacro with-parsed-tramp-file-name (filename var &rest body)
"Parse a Tramp filename and make components available in the body.
(tramp-message ,vec ,level "%s..." ,message)
;; We start a pulsing progress reporter after 3 seconds. Feature
;; introduced in Emacs 24.1.
- (when (and tramp-message-show-progress-reporter-message
- tramp-message-show-message
+ (when (and tramp-message-show-message
;; Display only when there is a minimum level.
(<= ,level (min tramp-verbose 3)))
(ignore-errors
(setq pr (tramp-compat-funcall 'make-progress-reporter ,message)
tm (when pr
(run-at-time 3 0.1 'tramp-progress-reporter-update pr)))))
- (unwind-protect
- ;; Execute the body. Suppress concurrent progress reporter
- ;; messages.
- (let ((tramp-message-show-progress-reporter-message
- (and tramp-message-show-progress-reporter-message (not tm))))
- ,@body)
- ;; Stop progress reporter.
- (if tm (tramp-compat-funcall 'cancel-timer tm))
- (tramp-message ,vec ,level "%s...done" ,message))))
+ (condition-case err
+ (unwind-protect
+ ;; Execute the body.
+ (progn ,@body)
+ ;; Stop progress reporter.
+ (if tm (tramp-compat-funcall 'cancel-timer tm)))
+
+ ;; Error handling.
+ ((error quit)
+ (tramp-message ,vec ,level "%s...failed" ,message)
+ (signal (car err) (cdr err))))
+
+ ;; Exit.
+ (tramp-message ,vec ,level "%s...done" ,message)))
(tramp-compat-font-lock-add-keywords
'emacs-lisp-mode '("\\<with-tramp-progress-reporter\\>"))
PROC and VEC indicate the remote connection to be used. POS, if
set, is the starting point of the region to be deleted in the
connection buffer."
- ;; Preserve message for `progress-reporter'.
- (tramp-compat-with-temp-message ""
- ;; Enable `auth-source' and `password-cache'. We must use
- ;; tramp-current-* variables in case we have several hops.
- (tramp-set-connection-property
- (tramp-dissect-file-name
- (tramp-make-tramp-file-name
- tramp-current-method tramp-current-user tramp-current-host ""))
- "first-password-request" t)
- (save-restriction
+ ;; Enable `auth-source' and `password-cache'. We must use
+ ;; tramp-current-* variables in case we have several hops.
+ (tramp-set-connection-property
+ (tramp-dissect-file-name
+ (tramp-make-tramp-file-name
+ tramp-current-method tramp-current-user tramp-current-host ""))
+ "first-password-request" t)
+ (save-restriction
+ (with-tramp-progress-reporter
+ proc 3 "Waiting for prompts from remote shell"
(let (exit)
- (while (not exit)
- (tramp-message proc 3 "Waiting for prompts from remote shell")
- (setq exit
- (catch 'tramp-action
- (if timeout
- (with-timeout (timeout)
- (tramp-process-one-action proc vec actions))
+ (if timeout
+ (with-timeout (timeout (setq exit 'timeout))
+ (while (not exit)
+ (setq exit
+ (catch 'tramp-action
+ (tramp-process-one-action proc vec actions)))))
+ (while (not exit)
+ (setq exit
+ (catch 'tramp-action
(tramp-process-one-action proc vec actions)))))
(with-current-buffer (tramp-get-connection-buffer vec)
(widen)
(tramp-message vec 6 "\n%s" (buffer-string)))
(unless (eq exit 'ok)
(tramp-clear-passwd vec)
+ (delete-process proc)
(tramp-error-with-buffer
- nil vec 'file-error
+ (tramp-get-connection-buffer vec) vec 'file-error
(cond
((eq exit 'permission-denied) "Permission denied")
- ((eq exit 'process-died) "Process died")
- (t "Login failed"))))
- (when (numberp pos)
- (with-current-buffer (tramp-get-connection-buffer vec)
- (let (buffer-read-only) (delete-region pos (point)))))))))
+ ((eq exit 'process-died)
+ (concat
+ "Tramp failed to connect. If this happens repeatedly, try\n"
+ " `M-x tramp-cleanup-this-connection'"))
+ ((eq exit 'timeout)
+ "Timeout reached. Check the buffer for the error reason")
+ (t "Login failed")))))
+ (when (numberp pos)
+ (with-current-buffer (tramp-get-connection-buffer vec)
+ (let (buffer-read-only) (delete-region pos (point))))))))
:;; Utility functions: