:type '(choice (const nil) integer))
(defcustom tramp-copy-size-limit 10240
- "The maximum file size where inline copying is preferred over an out-of-the-band copy.
-If it is nil, inline out-of-the-band copy will be used without a check."
+ "The maximum file size where inline copying is preferred over an \
+out-of-the-band copy.
+If it is nil, out-of-the-band copy will be used without a check."
:group 'tramp
:type '(choice (const nil) integer))
(tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
- (tramp-password-end-of-line "xy") ;see docstring for "xy"
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
(tramp-login-args (("-l" "%u") ("-P" "%p") ("-1" "-ssh") ("%h")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
- (tramp-password-end-of-line "xy") ;see docstring for "xy"
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
("-q") ("-r")))
(tramp-copy-keep-date t)
(tramp-copy-recursive t)
- (tramp-password-end-of-line "xy") ;see docstring for "xy"
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
(tramp-copy-args (("-l" "%u") ("-P" "%p") ("-sftp") ("-p" "%k")
("-q") ("-r")))
(tramp-copy-keep-date t)
- (tramp-copy-recursive t)
- (tramp-password-end-of-line "xy"))) ;see docstring for "xy"
+ (tramp-copy-recursive t)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
'("fcp"
;;;###tramp-autoload
(defconst tramp-completion-function-alist-putty
- '((tramp-parse-putty
- "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"))
- "Default list of (FUNCTION REGISTRY) pairs to be examined for putty methods.")
+ `((tramp-parse-putty
+ ,(if (memq system-type '(windows-nt))
+ "HKEY_CURRENT_USER\\Software\\SimonTatham\\PuTTY\\Sessions"
+ "~/.putty/sessions")))
+ "Default list of (FUNCTION REGISTRY) pairs to be examined for putty sessions.")
;;;###tramp-autoload
(eval-after-load 'tramp
;; IRIX64: /usr/bin
;;;###tramp-autoload
(defcustom tramp-remote-path
- '(tramp-default-remote-path "/bin" "/usr/bin" "/usr/sbin" "/usr/local/bin"
- "/local/bin" "/local/freeware/bin" "/local/gnu/bin"
- "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin")
+ '(tramp-default-remote-path "/bin" "/usr/bin" "/sbin" "/usr/sbin"
+ "/usr/local/bin" "/usr/local/sbin" "/local/bin" "/local/freeware/bin"
+ "/local/gnu/bin" "/usr/freeware/bin" "/usr/pkg/bin" "/usr/contrib/bin"
+ "/opt/bin" "/opt/sbin" "/opt/local/bin")
"List of directories to search for executables on remote host.
For every remote host, this variable will be set buffer local,
keeping the list of existing directories on that host.
,(format "INSIDE_EMACS='%s,tramp:%s'" emacs-version tramp-version)
"CDPATH=" "HISTORY=" "MAIL=" "MAILCHECK=" "MAILPATH=" "PAGER=\"\""
"autocorrect=" "correct=")
-
"List of environment variables to be set on the remote host.
Each element should be a string of the form ENVVARNAME=VALUE. An
(tramp-get-file-exists-command v)
(tramp-shell-quote-argument localname)))))))
-;; CCC: This should check for an error condition and signal failure
-;; when something goes wrong.
-;; Daniel Pittman <daniel@danann.net>
(defun tramp-sh-handle-file-attributes (filename &optional id-format)
"Like `file-attributes' for Tramp files."
(unless id-format (setq id-format 'integer))
(tramp-get-test-command vec)
(tramp-shell-quote-argument localname)
(tramp-get-remote-stat vec)
- (if (eq id-format 'integer) "%u" "\"%U\"")
- (if (eq id-format 'integer) "%g" "\"%G\"")
+ (if (eq id-format 'integer) "%ue0" "\"%U\"")
+ (if (eq id-format 'integer) "%ge0" "\"%G\"")
(tramp-shell-quote-argument localname))))
(defun tramp-sh-handle-set-visited-file-modtime (&optional time-list)
;; "-"; this would confuse xargs. "ls -aQ" might be a solution,
;; but it does not work on all remote systems. Therefore, we
;; quote the filenames via sed.
- "cd %s; echo \"(\"; (%s -a | sed -e s/\\$/\\\"/g -e s/^/\\\"/g | xargs "
- "%s -c '(\"%%n\" (\"%%N\") %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 \"%%A\" t %%ie0 -1)'); "
- "echo \")\"")
+ "cd %s; echo \"(\"; (%s -a | sed -e s/\\$/\\\"/g -e s/^/\\\"/g | "
+ "xargs %s -c "
+ "'(\"%%n\" (\"%%N\") %%h %s %s %%Xe0 %%Ye0 %%Ze0 %%se0 \"%%A\" t %%ie0 -1)'"
+ " 2>/dev/null); echo \")\"")
(tramp-shell-quote-argument localname)
(tramp-get-ls-command vec)
(tramp-get-remote-stat vec)
- (if (eq id-format 'integer) "%u" "\"%U\"")
- (if (eq id-format 'integer) "%g" "\"%G\""))))
+ (if (eq id-format 'integer) "%ue0" "\"%U\"")
+ (if (eq id-format 'integer) "%ge0" "\"%G\""))))
;; This function should return "foo/" for directories and "bar" for
;; files.
p v nil tramp-actions-copy-out-of-band)))
;; Reset the transfer process properties.
- (tramp-message orig-vec 6 "%s" (buffer-string))
+ (tramp-message orig-vec 6 "\n%s" (buffer-string))
(tramp-set-connection-property v "process-name" nil)
(tramp-set-connection-property v "process-buffer" nil)))
"Recursively delete the directory given.
This is like `dired-recursive-delete-directory' for Tramp files."
(with-parsed-tramp-file-name filename nil
- ;; Run a shell command 'rm -r <localname>'
+ ;; Run a shell command 'rm -r <localname>'.
;; Code shamelessly stolen from the dired implementation and, um, hacked :)
(unless (file-exists-p filename)
(tramp-error v 'file-error "No such directory: %s" filename))
- ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>)
+ ;; Which is better, -r or -R? (-r works for me <daniel@danann.net>).
(tramp-send-command
v
(format "rm -rf %s" (tramp-shell-quote-argument localname))
method user host
(tramp-drop-volume-letter
(tramp-run-real-handler
- 'expand-file-name (list localname))))))))
+ 'expand-file-name (list localname)))
+ hop)))))
;;; Remote commands:
(bmp (and (buffer-live-p buffer) (buffer-modified-p buffer)))
(name1 name)
(i 0))
- (unwind-protect
- (save-excursion
- (save-restriction
- (unless buffer
- ;; BUFFER can be nil. We use a temporary buffer.
- (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
- (while (get-process name1)
- ;; NAME must be unique as process name.
- (setq i (1+ i)
- name1 (format "%s<%d>" name i)))
- (setq name name1)
- ;; Set the new process properties.
- (tramp-set-connection-property v "process-name" name)
- (tramp-set-connection-property v "process-buffer" buffer)
- ;; Activate narrowing in order to save BUFFER contents.
- ;; Clear also the modification time; otherwise we might
- ;; be interrupted by `verify-visited-file-modtime'.
- (with-current-buffer (tramp-get-connection-buffer v)
- (let ((buffer-undo-list t))
+
+ (unless buffer
+ ;; BUFFER can be nil. We use a temporary buffer.
+ (setq buffer (generate-new-buffer tramp-temp-buffer-name)))
+ (while (get-process name1)
+ ;; NAME must be unique as process name.
+ (setq i (1+ i)
+ name1 (format "%s<%d>" name i)))
+ (setq name name1)
+ ;; Set the new process properties.
+ (tramp-set-connection-property v "process-name" name)
+ (tramp-set-connection-property v "process-buffer" buffer)
+
+ (with-current-buffer (tramp-get-connection-buffer v)
+ (unwind-protect
+ (save-excursion
+ (save-restriction
+ ;; Activate narrowing in order to save BUFFER
+ ;; contents. Clear also the modification time;
+ ;; otherwise we might be interrupted by
+ ;; `verify-visited-file-modtime'.
+ (let ((buffer-undo-list t)
+ (buffer-read-only nil)
+ (mark (point)))
(clear-visited-file-modtime)
(narrow-to-region (point-max) (point-max))
+ ;; We call `tramp-maybe-open-connection', in order
+ ;; to cleanup the prompt afterwards.
+ (tramp-maybe-open-connection v)
+ (widen)
+ (delete-region mark (point))
+ (narrow-to-region (point-max) (point-max))
+ ;; Now do it.
(if command
;; Send the command.
(tramp-send-command v command nil t) ; nooutput
;; Check, whether a pty is associated.
- (tramp-maybe-open-connection v)
(unless (tramp-compat-process-get
(tramp-get-connection-process v) 'remote-tty)
(tramp-error
v 'file-error
- "pty association is not supported for `%s'" name)))))
- (let ((p (tramp-get-connection-process v)))
- ;; Set query flag for this process.
- (tramp-compat-set-process-query-on-exit-flag p t)
- ;; Return process.
- p)))
- ;; Save exit.
- (with-current-buffer (tramp-get-connection-buffer v)
+ "pty association is not supported for `%s'" name))))
+ (let ((p (tramp-get-connection-process v)))
+ ;; Set query flag for this process. We ignore errors,
+ ;; because the process could have finished already.
+ (ignore-errors
+ (tramp-compat-set-process-query-on-exit-flag p t))
+ ;; Return process.
+ p)))
+
+ ;; Save exit.
(if (string-match tramp-temp-buffer-name (buffer-name))
(progn
(set-process-buffer (tramp-get-connection-process v) nil)
(kill-buffer (current-buffer)))
- (set-buffer-modified-p bmp)))
- (tramp-set-connection-property v "process-name" nil)
- (tramp-set-connection-property v "process-buffer" nil)))))
+ (set-buffer-modified-p bmp))
+ (tramp-set-connection-property v "process-name" nil)
+ (tramp-set-connection-property v "process-buffer" nil))))))
(defun tramp-sh-handle-process-file
(program &optional infile destination display &rest args)
(let (last-coding-system-used (need-chown t))
;; Set file modification time.
(when (or (eq visit t) (stringp visit))
- (let ((file-attr (file-attributes filename)))
+ (let ((file-attr (tramp-compat-file-attributes filename 'integer)))
(set-visited-file-modtime
;; We must pass modtime explicitly, because filename can
;; be different from (buffer-file-name), f.e. if
;; `file-precious-flag' is set.
(nth 5 file-attr))
- (when (and (eq (nth 2 file-attr) uid)
- (eq (nth 3 file-attr) gid))
+ (when (and (= (nth 2 file-attr) uid)
+ (= (nth 3 file-attr) gid))
(setq need-chown nil))))
;; Set the ownership.
`((,tramp-file-name-regexp . tramp-vc-file-name-handler))))
;; Here we collect only file names, which need an operation.
- (tramp-run-real-handler 'vc-registered (list file))
+ (ignore-errors (tramp-run-real-handler 'vc-registered (list file)))
(tramp-message v 10 "\n%s" tramp-vc-registered-file-names)
;; Send just one command, in order to fill the cache.
((and fn (memq operation '(file-exists-p file-readable-p)))
(add-to-list 'tramp-vc-registered-file-names localname 'append)
nil)
+ ;; `process-file' and `start-file-process' shall be ignored.
+ ((and fn (eq operation 'process-file) 0))
+ ((and fn (eq operation 'start-file-process) nil))
;; Tramp file name handlers like `expand-file-name'. They
;; must still work.
- (fn
- (save-match-data (apply (cdr fn) args)))
+ (fn (save-match-data (apply (cdr fn) args)))
;; Default file name handlers, we don't care.
(t (tramp-run-real-handler operation args)))))))
;; `/usr/bin/test'.
;; `/usr/bin/test -e' In case `/bin/test' does not exist.
(unless (or
- (and (setq result (format "%s -e" (tramp-get-test-command vec)))
- (tramp-send-command-and-check
- vec (format "%s %s" result existing))
- (not (tramp-send-command-and-check
- vec (format "%s %s" result nonexistent))))
- (and (setq result "/bin/test -e")
- (tramp-send-command-and-check
- vec (format "%s %s" result existing))
- (not (tramp-send-command-and-check
- vec (format "%s %s" result nonexistent))))
- (and (setq result "/usr/bin/test -e")
- (tramp-send-command-and-check
- vec (format "%s %s" result existing))
- (not (tramp-send-command-and-check
- vec (format "%s %s" result nonexistent))))
- (and (setq result (format "%s -d" (tramp-get-ls-command vec)))
- (tramp-send-command-and-check
- vec (format "%s %s" result existing))
- (not (tramp-send-command-and-check
- vec (format "%s %s" result nonexistent)))))
+ (ignore-errors
+ (and (setq result (format "%s -e" (tramp-get-test-command vec)))
+ (tramp-send-command-and-check
+ vec (format "%s %s" result existing))
+ (not (tramp-send-command-and-check
+ vec (format "%s %s" result nonexistent)))))
+ (ignore-errors
+ (and (setq result "/bin/test -e")
+ (tramp-send-command-and-check
+ vec (format "%s %s" result existing))
+ (not (tramp-send-command-and-check
+ vec (format "%s %s" result nonexistent)))))
+ (ignore-errors
+ (and (setq result "/usr/bin/test -e")
+ (tramp-send-command-and-check
+ vec (format "%s %s" result existing))
+ (not (tramp-send-command-and-check
+ vec (format "%s %s" result nonexistent)))))
+ (ignore-errors
+ (and (setq result (format "%s -d" (tramp-get-ls-command vec)))
+ (tramp-send-command-and-check
+ vec (format "%s %s" result existing))
+ (not (tramp-send-command-and-check
+ vec (format "%s %s" result nonexistent))))))
(tramp-error
vec 'file-error "Couldn't find command to check if file exists"))
result))
(setq item (pop alist))
(when (string-match (car item) shell)
(setq extra-args (cdr item))))
- (when extra-args (setq shell (concat shell " " extra-args)))
(tramp-send-command
- vec (format "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s"
- (tramp-shell-quote-argument tramp-end-of-output) shell)
+ vec (format
+ "exec env ENV='' PROMPT_COMMAND='' PS1=%s PS2='' PS3='' %s %s"
+ (tramp-shell-quote-argument tramp-end-of-output)
+ shell (or extra-args ""))
t))
+ (tramp-set-connection-property
+ (tramp-get-connection-process vec) "remote-shell" shell)
;; Setting prompts.
(tramp-send-command
vec (format "PS1=%s" (tramp-shell-quote-argument tramp-end-of-output)) t)
(defun tramp-find-shell (vec)
"Opens a shell on the remote host which groks tilde expansion."
- (unless (tramp-get-connection-property vec "remote-shell" nil)
- (let (shell)
- (with-current-buffer (tramp-get-buffer vec)
- (tramp-send-command vec "echo ~root" t)
- (cond
- ((or (string-match "^~root$" (buffer-string))
- ;; The default shell (ksh93) of OpenSolaris and Solaris
- ;; is buggy. We've got reports for "SunOS 5.10" and
- ;; "SunOS 5.11" so far.
- (string-match (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
- (tramp-get-connection-property vec "uname" "")))
- (setq shell
- (or (tramp-find-executable
- vec "bash" (tramp-get-remote-path vec) t t)
- (tramp-find-executable
- vec "ksh" (tramp-get-remote-path vec) t t)))
- (unless shell
- (tramp-error
- vec 'file-error
- "Couldn't find a shell which groks tilde expansion"))
- (tramp-message
- vec 5 "Starting remote shell `%s' for tilde expansion"
- (tramp-set-connection-property vec "remote-shell" shell))
- (tramp-open-shell vec shell))
-
- (t (tramp-message
- vec 5 "Remote `%s' groks tilde expansion, good"
- (tramp-set-connection-property
- vec "remote-shell"
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell)))))))))
+ (with-current-buffer (tramp-get-buffer vec)
+ (let ((default-shell
+ (or
+ (tramp-get-connection-property
+ (tramp-get-connection-process vec) "remote-shell" nil)
+ (tramp-get-method-parameter
+ (tramp-file-name-method vec) 'tramp-remote-shell)))
+ shell)
+ (setq shell
+ (with-connection-property vec "remote-shell"
+ ;; CCC: "root" does not exist always, see QNAP 459.
+ ;; Which check could we apply instead?
+ (tramp-send-command vec "echo ~root" t)
+ (if (or (string-match "^~root$" (buffer-string))
+ ;; The default shell (ksh93) of OpenSolaris and
+ ;; Solaris is buggy. We've got reports for
+ ;; "SunOS 5.10" and "SunOS 5.11" so far.
+ (string-match (regexp-opt '("SunOS 5.10" "SunOS 5.11"))
+ (tramp-get-connection-property
+ vec "uname" "")))
+
+ (or (tramp-find-executable
+ vec "bash" (tramp-get-remote-path vec) t t)
+ (tramp-find-executable
+ vec "ksh" (tramp-get-remote-path vec) t t)
+ ;; Maybe it works at least for some other commands.
+ (prog1
+ default-shell
+ (tramp-message
+ vec 2
+ (concat
+ "Couldn't find a remote shell which groks tilde "
+ "expansion, using `%s'")
+ default-shell)))
+
+ default-shell)))
+
+ ;; Open a new shell if needed.
+ (unless (string-equal shell default-shell)
+ (tramp-message
+ vec 5 "Starting remote shell `%s' for tilde expansion" shell)
+ (tramp-open-shell vec shell))
+
+ ;; Busyboxes tend to behave strange. We check for the existence.
+ (with-connection-property vec "busybox"
+ (tramp-send-command vec (format "%s --version" shell) t)
+ (let ((case-fold-search t))
+ (and (string-match "busybox" (buffer-string)) t))))))
;; Utility functions.
;; discarded as well.
(tramp-open-shell
vec
- (tramp-get-method-parameter
- (tramp-file-name-method vec) 'tramp-remote-shell))
+ (or (tramp-get-connection-property vec "remote-shell" nil)
+ (tramp-get-method-parameter
+ (tramp-file-name-method vec) 'tramp-remote-shell)))
;; Disable echo.
(tramp-message vec 5 "Setting up remote shell environment")
vec "uname"
(tramp-send-command-and-read vec "echo \\\"`uname -sr`\\\""))))
(when (and (stringp old-uname) (not (string-equal old-uname new-uname)))
- (with-current-buffer (tramp-get-debug-buffer vec)
- ;; Keep the debug buffer.
- (rename-buffer
- (generate-new-buffer-name tramp-temp-buffer-name) 'unique)
- (tramp-cleanup-connection vec)
- (if (= (point-min) (point-max))
- (kill-buffer nil)
- (rename-buffer (tramp-debug-buffer-name vec) 'unique))
- ;; We call `tramp-get-buffer' in order to keep the debug buffer.
- (tramp-get-buffer vec)
- (tramp-message
- vec 3
- "Connection reset, because remote host changed from `%s' to `%s'"
- old-uname new-uname)
- (throw 'uname-changed (tramp-maybe-open-connection vec)))))
+ (tramp-cleanup vec)
+ (tramp-message
+ vec 3
+ "Connection reset, because remote host changed from `%s' to `%s'"
+ old-uname new-uname)
+ (throw 'uname-changed (tramp-maybe-open-connection vec))))
;; Check whether the remote host suffers from buggy
;; `send-process-string'. This is known for FreeBSD (see comment in
(tramp-set-remote-path vec)
;; Search for a good shell before searching for a command which
- ;; checks if a file exists. This is done because Tramp wants to use
+ ;; checks if a file exists. This is done because Tramp wants to use
;; "test foo; echo $?" to check if various conditions hold, and
;; there are buggy /bin/sh implementations which don't execute the
;; "echo $?" part if the "test" part has an error. In particular,
;; Disable unexpected output.
(tramp-send-command vec "mesg n; biff n" t)
- ;; Busyboxes tend to behave strange. We check for the existence.
- (with-connection-property vec "busybox"
- (tramp-send-command
- vec
- (format
- "%s --version" (tramp-get-connection-property vec "remote-shell" "echo"))
- t)
- (with-current-buffer (process-buffer proc)
- (let ((case-fold-search t))
- (and (string-match "busybox" (buffer-string)) t))))
-
;; IRIX64 bash expands "!" even when in single quotes. This
;; destroys our shell functions, we must disable it. See
;; <http://stackoverflow.com/questions/3291692/irix-bash-shell-expands-expression-in-single-quotes-yet-shouldnt>.
(b64 "recode data..base64" "recode base64..data")
(b64 tramp-perl-encode-with-module tramp-perl-decode-with-module)
(b64 tramp-perl-encode tramp-perl-decode)
- (uu "uuencode xxx" "uudecode -o /dev/stdout")
+ (uu "uuencode xxx" "uudecode -o /dev/stdout" "test -c /dev/stdout")
(uu "uuencode xxx" "uudecode -o -")
(uu "uuencode xxx" "uudecode -p")
(uu "uuencode xxx" tramp-uudecode)
"List of remote coding commands for inline transfer.
Each item is a list that looks like this:
-\(FORMAT ENCODING DECODING\)
+\(FORMAT ENCODING DECODING [TEST]\)
FORMAT is symbol describing the encoding/decoding format. It can be
`b64' for base64 encoding, `uu' for uu encoding, or `pack' for simple packing.
If they are variables, this variable is a string containing a Perl
implementation for this functionality. This Perl program will be transferred
-to the remote host, and it is available as shell function with the same name.")
+to the remote host, and it is available as shell function with the same name.
+
+The optional TEST command can be used for further tests, whether
+ENCODING and DECODING are applicable.")
(defun tramp-find-inline-encoding (vec)
"Find an inline transfer encoding that works.
(save-excursion
(let ((local-commands tramp-local-coding-commands)
(magic "xyzzy")
- loc-enc loc-dec rem-enc rem-dec litem ritem found)
+ (p (tramp-get-connection-process vec))
+ loc-enc loc-dec rem-enc rem-dec rem-test litem ritem found)
(while (and local-commands (not found))
(setq litem (pop local-commands))
(catch 'wont-work-local
(when (equal format (nth 0 ritem))
(setq rem-enc (nth 1 ritem))
(setq rem-dec (nth 2 ritem))
+ (setq rem-test (nth 3 ritem))
+ ;; Check the remote test command if exists.
+ (when (stringp rem-test)
+ (tramp-message
+ vec 5 "Checking remote test command `%s'" rem-test)
+ (unless (tramp-send-command-and-check vec rem-test t)
+ (throw 'wont-work-remote nil)))
;; Check if remote encoding and decoding commands can be
;; called remotely with null input and output. This makes
;; sure there are no syntax errors and the command is really
(tramp-error
vec 'file-error "Couldn't find an inline transfer encoding"))
- ;; Set connection properties.
+ ;; Set connection properties. Since the commands are risky (due
+ ;; to output direction), we cache them in the process cache.
(tramp-message vec 5 "Using local encoding `%s'" loc-enc)
- (tramp-set-connection-property vec "local-encoding" loc-enc)
+ (tramp-set-connection-property p "local-encoding" loc-enc)
(tramp-message vec 5 "Using local decoding `%s'" loc-dec)
- (tramp-set-connection-property vec "local-decoding" loc-dec)
+ (tramp-set-connection-property p "local-decoding" loc-dec)
(tramp-message vec 5 "Using remote encoding `%s'" rem-enc)
- (tramp-set-connection-property vec "remote-encoding" rem-enc)
+ (tramp-set-connection-property p "remote-encoding" rem-enc)
(tramp-message vec 5 "Using remote decoding `%s'" rem-dec)
- (tramp-set-connection-property vec "remote-decoding" rem-dec))))
+ (tramp-set-connection-property p "remote-decoding" rem-dec))))
(defun tramp-call-local-coding-command (cmd input output)
"Call the local encoding or decoding command.
(save-excursion
(let ((commands tramp-inline-compress-commands)
(magic "xyzzy")
- item compress decompress
- found)
+ (p (tramp-get-connection-process vec))
+ item compress decompress found)
(while (and commands (not found))
(catch 'next
(setq item (pop commands)
;; Did we find something?
(if found
(progn
- ;; Set connection properties.
+ ;; Set connection properties. Since the commands are
+ ;; risky (due to output direction), we cache them in the
+ ;; process cache.
(tramp-message
vec 5 "Using inline transfer compress command `%s'" compress)
- (tramp-set-connection-property vec "inline-compress" compress)
+ (tramp-set-connection-property p "inline-compress" compress)
(tramp-message
vec 5 "Using inline transfer decompress command `%s'" decompress)
- (tramp-set-connection-property vec "inline-decompress" decompress))
+ (tramp-set-connection-property p "inline-decompress" decompress))
- (tramp-set-connection-property vec "inline-compress" nil)
- (tramp-set-connection-property vec "inline-decompress" nil)
+ (tramp-set-connection-property p "inline-compress" nil)
+ (tramp-set-connection-property p "inline-decompress" nil)
(tramp-message
vec 2 "Couldn't find an inline transfer compress command")))))
"Expands VEC according to `tramp-default-proxies-alist'.
Gateway hops are already opened."
(let ((target-alist `(,vec))
- (choices tramp-default-proxies-alist)
- item proxy)
+ (hops (or (tramp-file-name-hop vec) ""))
+ (item vec)
+ choices proxy)
+
+ ;; Ad-hoc proxy definitions.
+ (dolist (proxy (reverse (split-string hops tramp-postfix-hop-regexp 'omit)))
+ (let ((user (tramp-file-name-user item))
+ (host (tramp-file-name-host item))
+ (proxy (concat
+ tramp-prefix-format proxy tramp-postfix-host-format)))
+ (tramp-message
+ vec 5 "Add proxy (\"%s\" \"%s\" \"%s\")"
+ (and (stringp host) (regexp-quote host))
+ (and (stringp user) (regexp-quote user))
+ proxy)
+ ;; Add the hop.
+ (add-to-list
+ 'tramp-default-proxies-alist
+ (list (and (stringp host) (regexp-quote host))
+ (and (stringp user) (regexp-quote user))
+ proxy))
+ (setq item (tramp-dissect-file-name proxy))))
+ ;; Save the new value.
+ (when (and hops tramp-save-ad-hoc-proxies)
+ (customize-save-variable
+ 'tramp-default-proxies-alist tramp-default-proxies-alist))
;; Look for proxy hosts to be passed.
+ (setq choices tramp-default-proxies-alist)
(while choices
(setq item (pop choices)
proxy (eval (nth 2 item)))
(when (and
- ;; host
+ ;; Host.
(string-match (or (eval (nth 0 item)) "")
(or (tramp-file-name-host (car target-alist)) ""))
- ;; user
+ ;; User.
(string-match (or (eval (nth 1 item)) "")
(or (tramp-file-name-user (car target-alist)) "")))
(if (null proxy)
'target-alist
(vector
(tramp-file-name-method hop) (tramp-file-name-user hop)
- (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil))
+ (tramp-compat-funcall 'tramp-gw-open-connection vec gw hop) nil nil))
;; For the password prompt, we need the correct values.
;; Therefore, we must remember the gateway vector. But we
;; cannot do it as connection property, because it shouldn't
;; 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
(process-environment (copy-sequence process-environment))
(pos (with-current-buffer (tramp-get-connection-buffer vec) (point))))
+ ;; If Tramp opens the same connection within a short time frame,
+ ;; there is a problem. We shall signal this.
+ (unless (or (and p (processp p) (memq (process-status p) '(run open)))
+ (not (equal (butlast (append vec nil))
+ (car tramp-current-connection)))
+ (> (tramp-time-diff
+ (current-time) (cdr tramp-current-connection))
+ 5))
+ (throw 'suppress 'suppress))
+
;; If too much time has passed since last command was sent, look
;; whether process is still alive. If it isn't, kill it. When
;; using ssh, it can sometimes happen that the remote end has
;; The error will be caught locally.
(tramp-error vec 'file-error "Awake did fail")))
(file-error
- (tramp-flush-connection-property vec)
- (tramp-flush-connection-property p)
- (delete-process p)
+ (tramp-cleanup vec)
(setq p nil)))
;; New connection must be opened.
;; We call `tramp-get-buffer' in order to get a debug
;; buffer for messages from the beginning.
(tramp-get-buffer vec)
+
+ ;; If `non-essential' is non-nil, don't reopen a new connection.
+ (when (and (boundp 'non-essential) (symbol-value 'non-essential))
+ (throw 'non-essential 'non-essential))
+
(tramp-with-progress-reporter
vec 3
(if (zerop (length (tramp-file-name-user vec)))
(tramp-set-connection-property p "vector" vec)
(set-process-sentinel p 'tramp-process-sentinel)
(tramp-compat-set-process-query-on-exit-flag p nil)
+ (setq tramp-current-connection
+ (cons (butlast (append vec nil)) (current-time))
+ tramp-current-host (system-name))
(tramp-message
vec 6 "%s" (mapconcat 'identity (process-command p) " "))
(expand-file-name
tramp-temp-name-prefix
(tramp-compat-temporary-file-directory)))))
- spec)
+ spec r-shell)
;; Add arguments for asynchronous processes.
(when (and process-name async-args)
(setq l-port (match-string 2 l-host)
l-host (match-string 1 l-host)))
+ ;; Check, whether there is a restricted shell.
+ (dolist (elt tramp-restricted-shell-hosts-alist)
+ (when (string-match elt tramp-current-host)
+ (setq r-shell t)))
+
;; Set variables for computing the prompt for
;; reading password. They can also be derived
;; from a gateway.
(concat
;; We do not want to see the trailing local
;; prompt in `start-file-process'.
- (unless (memq system-type '(windows-nt)) "exec ")
+ (unless r-shell "exec ")
command " "
(mapconcat
(lambda (x)
login-args " ")
;; Local shell could be a Windows COMSPEC. It
;; doesn't know the ";" syntax, but we must exit
- ;; always for `start-file-process'. "exec" does
- ;; not work either.
- (if (memq system-type '(windows-nt)) " && exit || exit")))
+ ;; always for `start-file-process'. It could
+ ;; also be a restricted shell, which does not
+ ;; allow "exec".
+ (when r-shell " && exit || exit")))
;; Send the command.
(tramp-message vec 3 "Sending command `%s'" command)
;; When the user did interrupt, we must cleanup.
(quit
- (let ((p (tramp-get-connection-process vec)))
- (when (and p (processp p))
- (tramp-flush-connection-property vec)
- (tramp-flush-connection-property p)
- (delete-process p)))
+ (tramp-cleanup vec)
;; Propagate the quit signal.
(signal (car err) (cdr err)))))))
If no corresponding command is found, nil is returned."
(when (and (integerp tramp-inline-compress-start-size)
(> size tramp-inline-compress-start-size))
- (with-connection-property vec prop
+ (with-connection-property (tramp-get-connection-process vec) prop
(tramp-find-inline-compress vec)
- (tramp-get-connection-property vec prop nil))))
+ (tramp-get-connection-property
+ (tramp-get-connection-process vec) prop nil))))
(defun tramp-get-inline-coding (vec prop size)
"Return the coding command related to PROP.
;; no inline coding is found.
(ignore-errors
(let ((coding
- (with-connection-property vec prop
+ (with-connection-property (tramp-get-connection-process vec) prop
(tramp-find-inline-encoding vec)
- (tramp-get-connection-property vec prop nil)))
+ (tramp-get-connection-property
+ (tramp-get-connection-process vec) prop nil)))
(prop1 (if (string-match "encoding" prop)
"inline-compress" "inline-decompress"))
compress)