(defvar directory-sep-char)
(defvar tramp-gw-tunnel-method)
(defvar tramp-gw-socks-method)
+(defvar vc-handled-backends)
+(defvar vc-bzr-program)
+(defvar vc-git-program)
+(defvar vc-hg-program)
(defcustom tramp-inline-compress-start-size 4096
"The minimum size of compressing where inline transfer.
("-o" "StrictHostKeyChecking=no")))
(tramp-default-port 22)))
;;;###tramp-autoload
-(add-to-list 'tramp-methods
- '("sftp"
- (tramp-login-program "ssh")
- (tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
- ("-e" "none") ("%h")))
- (tramp-async-args (("-q")))
- (tramp-remote-shell "/bin/sh")
- (tramp-remote-shell-args ("-c"))
- (tramp-copy-program "sftp")
- (tramp-copy-args ("%c"))))
- ;;;###tramp-autoload
(add-to-list 'tramp-methods
'("rsync"
(tramp-login-program "ssh")
(add-to-list 'tramp-methods
'("telnet"
(tramp-login-program "telnet")
- (tramp-login-args (("%h") ("%p")))
+ (tramp-login-args (("%h") ("%p") ("2>/dev/null")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-default-port 23)))
;;;###tramp-autoload
+(add-to-list 'tramp-methods
+ '("nc"
+ (tramp-login-program "telnet")
+ (tramp-login-args (("%h") ("%p") ("2>/dev/null")))
+ (tramp-remote-shell "/bin/sh")
+ (tramp-remote-shell-args ("-c"))
+ (tramp-copy-program "nc")
+ ;; We use "-v" for better error tracking.
+ (tramp-copy-args (("-w" "1") ("-v") ("%h") ("%r")))
+ (tramp-remote-copy-program "nc")
+ ;; We use "-p" as required for newer busyboxes. For older
+ ;; busybox/nc versions, the value must be (("-l") ("%r")). This
+ ;; can be achieved by tweaking `tramp-connection-properties'.
+ (tramp-remote-copy-args (("-l") ("-p" "%r")))
+ (tramp-default-port 23)))
+;;;###tramp-autoload
(add-to-list 'tramp-methods
'("su"
(tramp-login-program "su")
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("plink"
+ `("plink"
(tramp-login-program "plink")
- (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
+ ;; ("%h") must be a single element, see `tramp-compute-multi-hops'.
+ (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("-t")
+ ("%h") ("\"")
+ (,(format
+ "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
+ tramp-terminal-type
+ tramp-initial-end-of-output))
+ ("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-default-port 22)))
(add-to-list 'tramp-methods
`("plinkx"
(tramp-login-program "plink")
- ;; ("%h") must be a single element, see
- ;; `tramp-compute-multi-hops'.
- (tramp-login-args (("-load") ("%h") ("-t")
+ (tramp-login-args (("-load") ("%h") ("-t") ("\"")
(,(format
"env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
tramp-terminal-type
tramp-initial-end-of-output))
- ("/bin/sh")))
+ ("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("pscp"
+ `("pscp"
(tramp-login-program "plink")
- (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("-t")
+ ("%h") ("\"")
+ (,(format
+ "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
+ tramp-terminal-type
+ tramp-initial-end-of-output))
+ ("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "pscp")
(tramp-default-port 22)))
;;;###tramp-autoload
(add-to-list 'tramp-methods
- '("psftp"
+ `("psftp"
(tramp-login-program "plink")
- (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("%h")))
+ (tramp-login-args (("-l" "%u") ("-P" "%p") ("-ssh") ("-t")
+ ("%h") ("\"")
+ (,(format
+ "env 'TERM=%s' 'PROMPT_COMMAND=' 'PS1=%s'"
+ tramp-terminal-type
+ tramp-initial-end-of-output))
+ ("/bin/sh") ("\"")))
(tramp-remote-shell "/bin/sh")
(tramp-remote-shell-args ("-c"))
(tramp-copy-program "pscp")
(add-to-list 'tramp-default-user-alist
`(,(concat
"\\`"
- (regexp-opt '("rcp" "remcp" "rsh" "telnet" "krlogin" "fcp"))
+ (regexp-opt
+ '("rcp" "remcp" "rsh" "telnet" "nc" "krlogin" "fcp"))
"\\'")
nil ,(user-login-name)))
(tramp-set-completion-function "remcp" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "scp" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "scpx" tramp-completion-function-alist-ssh)
- (tramp-set-completion-function "sftp" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "rsync" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "rsh" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "remsh" tramp-completion-function-alist-rsh)
(tramp-set-completion-function "sshx" tramp-completion-function-alist-ssh)
(tramp-set-completion-function
"telnet" tramp-completion-function-alist-telnet)
+ (tramp-set-completion-function "nc" tramp-completion-function-alist-telnet)
(tramp-set-completion-function "su" tramp-completion-function-alist-su)
(tramp-set-completion-function "sudo" tramp-completion-function-alist-su)
(tramp-set-completion-function "ksu" tramp-completion-function-alist-su)
(tramp-set-completion-function
"plinkx" tramp-completion-function-alist-putty)
(tramp-set-completion-function "pscp" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function "psftp" tramp-completion-function-alist-ssh)
(tramp-set-completion-function "fcp" tramp-completion-function-alist-ssh)))
;; "getconf PATH" yields:
(format "%s -ild %s"
(tramp-get-ls-command v)
(tramp-shell-quote-argument localname)))
- (setq attr (buffer-substring (point)
- (progn (end-of-line) (point)))))
+ (setq attr (buffer-substring (point) (point-at-eol))))
(tramp-set-file-property
v localname "visited-file-modtime-ild" attr))
(when (boundp 'last-coding-system-used)
(tramp-get-ls-command v)
(tramp-shell-quote-argument localname)))
(with-current-buffer (tramp-get-buffer v)
- (setq attr (buffer-substring
- (point) (progn (end-of-line) (point)))))
+ (setq attr (buffer-substring (point) (point-at-eol))))
(equal
attr
(tramp-get-file-property
;; We are local, so we don't need the UTC settings.
(zerop
(tramp-call-process
- "touch" nil nil nil "-t"
+ nil "touch" nil nil nil "-t"
(format-time-string "%Y%m%d%H%M.%S" time)
(tramp-shell-quote-argument filename)))))
(let ((uid (or (and (natnump uid) uid) (tramp-get-local-uid 'integer)))
(gid (or (and (natnump gid) gid) (tramp-get-local-gid 'integer))))
(tramp-call-process
- "chown" nil nil nil
+ nil "chown" nil nil nil
(format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))))
(defun tramp-remote-selinux-p (vec)
(defun tramp-sh-handle-file-directory-p (filename)
"Like `file-directory-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
- ;; `file-directory-p' is used as predicate for filename completion.
+ ;; `file-directory-p' is used as predicate for file name completion.
;; Sometimes, when a connection is not established yet, it is
;; desirable to return t immediately for "/method:foo:". It can
;; be expected that this is always a directory.
vec
(format
(concat
- ;; We must care about filenames with spaces, or starting with
+ ;; We must care about file names with spaces, or starting with
;; "-"; 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.
+ ;; quote the file names 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)'"
(mapcar
'list
(or
- ;; Try cache entries for filename, filename with last
- ;; character removed, filename with last two characters
+ ;; Try cache entries for `filename', `filename' with last
+ ;; character removed, `filename' with last two characters
;; removed, ..., and finally the empty string - all
;; concatenated to the local directory name.
(let ((remote-file-name-inhibit-cache
(or remote-file-name-inhibit-cache
tramp-completion-reread-directory-timeout)))
- ;; This is inefficient for very long filenames, pity
+ ;; This is inefficient for very long file names, pity
;; `reduce' is not available...
(car
(apply
(tramp-shell-quote-argument localname)
(tramp-get-ls-command v)
;; When `filename' is empty, just `ls' without
- ;; filename argument is more efficient than `ls *'
+ ;; `filename' argument is more efficient than `ls *'
;; for very large directories and might avoid the
;; `Argument list too long' error.
;;
;; create a new buffer, insert the contents of the
;; source file into it, then write out the buffer to
;; the target file. The advantage is that it doesn't
- ;; matter which filename handlers are used for the
+ ;; matter which file name handlers are used for the
;; source and target file.
(t
(tramp-do-copy-or-rename-file-via-buffer
(set-file-modes newname file-modes))))))
(defun tramp-do-copy-or-rename-file-out-of-band (op filename newname keep-date)
- "Invoke rcp program to copy.
+ "Invoke `scp' program to copy.
The method used must be an out-of-band method."
(let* ((t1 (tramp-tramp-file-p filename))
(t2 (tramp-tramp-file-p newname))
(orig-vec (tramp-dissect-file-name (if t1 filename newname)))
- copy-program copy-args copy-env copy-keep-date port spec
- options source target)
+ copy-program copy-args copy-env copy-keep-date port listener spec
+ options source target remote-copy-program remote-copy-args)
(with-parsed-tramp-file-name (if t1 filename newname) nil
(if (and t1 t2)
;; Both are Tramp files. We shall optimize it when the
- ;; methods for filename and newname are the same.
+ ;; methods for FILENAME and NEWNAME are the same.
(let* ((dir-flag (file-directory-p filename))
(tmpfile (tramp-compat-make-temp-file localname dir-flag)))
(if dir-flag
(setq user (or (tramp-file-name-user v)
(tramp-get-connection-property v "login-as" nil)))
+ ;; Check for listener port.
+ (when (tramp-get-method-parameter method 'tramp-remote-copy-args)
+ (setq listener (number-to-string (+ 50000 (random 10000))))
+ (while
+ (zerop (tramp-call-process v "nc" nil nil nil "-z" host listener))
+ (setq listener (number-to-string (+ 50000 (random 10000))))))
+
;; Compose copy command.
(setq host (or host "")
user (or user "")
tramp-ssh-controlmaster-options "")
spec)
spec (format-spec-make
- ?h host ?u user ?p port ?c options
+ ?h host ?u user ?p port ?r listener ?c options
?k (if keep-date " " ""))
copy-program (tramp-get-method-parameter
method 'tramp-copy-program)
copy-keep-date (tramp-get-method-parameter
method 'tramp-copy-keep-date)
+
copy-args
(delete
;; " " has either been a replacement of "%k" (when
copy-args
(let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
(if (member "" y) '(" ") y))))))
+
copy-env
(delq
nil
(lambda (x)
(setq x (mapcar (lambda (y) (format-spec y spec)) x))
(unless (member "" x) (mapconcat 'identity x " ")))
- (tramp-get-method-parameter method 'tramp-copy-env))))
+ (tramp-get-method-parameter method 'tramp-copy-env)))
+
+ remote-copy-program
+ (tramp-get-method-parameter method 'tramp-remote-copy-program))
- ;; Check for program.
+ (dolist
+ (x
+ (or
+ (tramp-get-connection-property v "remote-copy-args" nil)
+ (tramp-get-method-parameter method 'tramp-remote-copy-args)))
+ (setq remote-copy-args
+ (append
+ remote-copy-args
+ (let ((y (mapcar (lambda (z) (format-spec z spec)) x)))
+ (if (member "" y) '(" ") y)))))
+
+ ;; Check for local copy program.
(unless (executable-find copy-program)
(tramp-error
- v 'file-error "Cannot find copy program: %s" copy-program))
+ v 'file-error "Cannot find local copy program: %s" copy-program))
+
+ ;; Install listener on the remote side. The prompt must be
+ ;; consumed later on, when the process does not listen anymore.
+ (when remote-copy-program
+ (unless (with-tramp-connection-property
+ v (concat "remote-copy-program-" remote-copy-program)
+ (tramp-find-executable
+ v remote-copy-program (tramp-get-remote-path v)))
+ (tramp-error
+ v 'file-error
+ "Cannot find remote listener: %s" remote-copy-program))
+ (setq remote-copy-program
+ (mapconcat
+ 'identity
+ (append
+ (list remote-copy-program) remote-copy-args
+ (list (if t1 (concat "<" source) (concat ">" target)) "&"))
+ " "))
+ (tramp-send-command v remote-copy-program)
+ (with-timeout
+ (1 (tramp-error
+ v 'file-error
+ "Listener process not running on remote host: `%s'"
+ remote-copy-program))
+ (tramp-send-command v (format "netstat -l | grep -q :%s" listener))
+ (while (not (tramp-send-command-and-check v nil))
+ (tramp-send-command
+ v (format "netstat -l | grep -q :%s" listener)))))
(with-temp-buffer
(unwind-protect
(tramp-message
orig-vec 6 "%s=\"%s\"" (car copy-env) (cadr copy-env))
(setenv (pop copy-env) (pop copy-env)))
+ (setq
+ copy-args
+ (append
+ copy-args
+ (if remote-copy-program
+ (list (if t1 (concat ">" target) (concat "<" source)))
+ (list source target))))
;; Use an asynchronous process. By this, password can
- ;; be handled. The default directory must be local, in
- ;; order to apply the correct `copy-program'. We don't
- ;; set a timeout, because the copying of large files can
- ;; last longer than 60 secs.
- (let ((p (let ((default-directory
- (tramp-compat-temporary-file-directory)))
- (apply 'start-process-shell-command
- (tramp-get-connection-name v)
- (tramp-get-connection-buffer v)
- copy-program
- (append
- copy-args
- (list
- source target
- "&&" "echo" "tramp_exit_status" "0"
- "||" "echo" "tramp_exit_status" "1"))))))
+ ;; be handled. We don't set a timeout, because the
+ ;; copying of large files can last longer than 60
+ ;; secs.
+ (let ((p (apply 'start-process-shell-command
+ (tramp-get-connection-name v)
+ (tramp-get-connection-buffer v)
+ copy-program
+ (append
+ copy-args
+ (list "&&" "echo" "tramp_exit_status" "0"
+ "||" "echo" "tramp_exit_status" "1")))))
(tramp-message
orig-vec 6 "%s"
(mapconcat 'identity (process-command p) " "))
;; Reset the transfer process properties.
(tramp-set-connection-property v "process-name" nil)
- (tramp-set-connection-property v "process-buffer" nil)))
+ (tramp-set-connection-property v "process-buffer" nil)
+ ;; Clear the remote prompt.
+ (when (and remote-copy-program
+ (not (tramp-send-command-and-check v nil)))
+ ;; Houston, we have a problem! Likely, the listener is
+ ;; still running, so let's clear everything (but the
+ ;; cached password).
+ (tramp-cleanup-connection v 'keep-debug 'keep-password))))
;; Handle KEEP-DATE argument.
(when (and keep-date (not copy-keep-date))
(delete-region (match-beginning 0) (point)))
;; Some busyboxes are reluctant to discard colors.
- (unless (string-match "color" (tramp-get-connection-property v "ls" ""))
+ (unless
+ (string-match "color" (tramp-get-connection-property v "ls" ""))
(goto-char beg)
(while (re-search-forward tramp-color-escape-sequence-regexp nil t)
(replace-match "")))
(defun tramp-sh-handle-expand-file-name (name &optional dir)
"Like `expand-file-name' for Tramp files.
-If the localname part of the given filename starts with \"/../\" then
-the result will be a local, non-Tramp, filename."
- ;; If DIR is not given, use DEFAULT-DIRECTORY or "/".
+If the localname part of the given file name starts with \"/../\" then
+the result will be a local, non-Tramp, file name."
+ ;; If DIR is not given, use `default-directory' or "/".
(setq dir (or dir default-directory "/"))
;; Unless NAME is absolute, concat DIR and NAME.
(unless (file-name-absolute-p name)
;; connection has been setup.
(defun tramp-sh-handle-start-file-process (name buffer program &rest args)
"Like `start-file-process' for Tramp files."
- (with-parsed-tramp-file-name default-directory nil
+ (with-parsed-tramp-file-name (expand-file-name default-directory) nil
(let* (;; When PROGRAM matches "*sh", and the first arg is "-c",
;; it might be that the arguments exceed the command line
;; length. Therefore, we modify the command.
(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
+ ;; FILENAME does not exist (eq modes nil) it has been
;; renamed to the backup file. This case `save-buffer'
;; handles permissions.
;; Ensure that it is still readable.
;; 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.
+ ;; method uses an scp 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
(erase-buffer)
(and
;; cksum runs locally, if possible.
- (zerop (tramp-call-process "cksum" tmpfile t))
+ (zerop (tramp-call-process v "cksum" tmpfile t))
;; cksum runs remotely.
(tramp-send-command-and-check
v
(tramp-error
v 'file-error
(concat "Method `%s' should specify both encoding and "
- "decoding command or an rcp program")
+ "decoding command or an scp program")
method))))
;; Make `last-coding-system-used' have the right value.
(when (or (eq visit t) (stringp visit))
(let ((file-attr (tramp-compat-file-attributes filename 'integer)))
(set-visited-file-modtime
- ;; We must pass modtime explicitly, because filename can
+ ;; 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))
;; calls shall be answered from the file cache. We unset
;; `process-file-side-effects' and `remote-file-name-inhibit-cache'
;; in order to keep the cache.
- (let (remote-file-name-inhibit-cache process-file-side-effects)
+ (let ((vc-handled-backends vc-handled-backends)
+ remote-file-name-inhibit-cache process-file-side-effects)
+ ;; Reduce `vc-handled-backends' in order to minimize process calls.
+ (when (and (memq 'Bzr vc-handled-backends)
+ (boundp 'vc-bzr-program)
+ (not (with-tramp-connection-property v vc-bzr-program
+ (tramp-find-executable
+ v vc-bzr-program (tramp-get-remote-path v)))))
+ (setq vc-handled-backends (remq 'Bzr vc-handled-backends)))
+ (when (and (memq 'Git vc-handled-backends)
+ (boundp 'vc-git-program)
+ (not (with-tramp-connection-property v vc-git-program
+ (tramp-find-executable
+ v vc-git-program (tramp-get-remote-path v)))))
+ (setq vc-handled-backends (remq 'Git vc-handled-backends)))
+ (when (and (memq 'Hg vc-handled-backends)
+ (boundp 'vc-hg-program)
+ (not (with-tramp-connection-property v vc-hg-program
+ (tramp-find-executable
+ v vc-hg-program (tramp-get-remote-path v)))))
+ (setq vc-handled-backends (remq 'Hg vc-handled-backends)))
+ ;; Run.
(ignore-errors
(tramp-run-real-handler 'vc-registered (list file))))))))
(tramp-message vec 5 "Setting shell prompt")
(tramp-send-command
- vec (format "PS1=%s" (tramp-shell-quote-argument tramp-end-of-output)) t)
- (tramp-send-command vec "PS2=''" t)
- (tramp-send-command vec "PS3=''" t)
- (tramp-send-command vec "PROMPT_COMMAND=''" t)
+ vec (format "PS1=%s PS2='' PS3='' PROMPT_COMMAND=''"
+ (tramp-shell-quote-argument tramp-end-of-output)) 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 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 (tramp-compat-funcall 'process-coding-system proc)
- (cons 'undecided 'undecided)))
- cs-decode cs-encode)
+ (let ((cs (or (when (string-match
+ "utf8" (or (tramp-get-remote-locale vec) ""))
+ (cons 'utf-8 'utf-8))
+ (tramp-compat-funcall 'process-coding-system proc)
+ (cons 'undecided 'undecided)))
+ cs-decode cs-encode)
(when (symbolp cs) (setq cs (cons cs cs)))
(setq cs-decode (car cs))
(setq cs-encode (cdr cs))
(unless cs-encode (setq cs-encode 'undecided))
(setq cs-encode (tramp-compat-coding-system-change-eol-conversion
cs-encode 'unix))
+ (tramp-send-command vec "echo foo ; echo bar" t)
+ (goto-char (point-min))
(when (search-forward "\r" nil t)
(setq cs-decode (tramp-compat-coding-system-change-eol-conversion
cs-decode 'dos)))
(let ((env (append (when (tramp-get-remote-locale vec) ; Discard `(nil)'.
`(,(tramp-get-remote-locale vec)))
(copy-sequence tramp-remote-process-environment)))
- unset item)
+ unset vars item)
(while env
(setq item (tramp-compat-split-string (car env) "="))
(setcdr item (mapconcat 'identity (cdr item) "="))
(if (and (stringp (cdr item)) (not (string-equal (cdr item) "")))
- (tramp-send-command
- vec (format "%s=%s; export %s" (car item) (cdr item) (car item)) t)
+ (push (format "%s %s" (car item) (cdr item)) vars)
(push (car item) unset))
(setq env (cdr env)))
+ (when vars
+ (tramp-send-command
+ vec
+ (format "while read var val; do export $var=$val; done <<'%s'\n%s\n%s"
+ tramp-end-of-heredoc
+ (mapconcat 'identity vars "\n")
+ tramp-end-of-heredoc)
+ t))
(when unset
(tramp-send-command
vec (format "unset %s" (mapconcat 'identity unset " ")) t))))
ENCODING and DECODING can be strings, giving commands, or symbols,
giving functions. If they are strings, then they can contain
the \"%s\" format specifier. If that specifier is present, the input
-filename will be put into the command line at that spot. If the
+file name will be put into the command line at that spot. If the
specifier is not present, the input should be read from standard
input.
ENCODING and DECODING can be strings, giving commands, or symbols,
giving variables. If they are strings, then they can contain
the \"%s\" format specifier. If that specifier is present, the input
-filename will be put into the command line at that spot. If the
+file name will be put into the command line at that spot. If the
specifier is not present, the input should be read from standard
input.
(setq rem-dec (nth 2 ritem))
(setq found t)))))))
- ;; Did we find something?
- (unless found
- (tramp-error
- vec 'file-error "Couldn't find an inline transfer encoding"))
-
- ;; 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 p "local-encoding" loc-enc)
- (tramp-message vec 5 "Using local decoding `%s'" 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 p "remote-encoding" rem-enc)
- (tramp-message vec 5 "Using remote decoding `%s'" rem-dec)
- (tramp-set-connection-property p "remote-decoding" rem-dec))))
+ (when found
+ ;; 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 p "local-encoding" loc-enc)
+ (tramp-message vec 5 "Using local decoding `%s'" 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 p "remote-encoding" rem-enc)
+ (tramp-message vec 5 "Using remote decoding `%s'" 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.
If CMD contains \"%s\", provide input file INPUT there in command.
Otherwise, INPUT is passed via standard input.
INPUT can also be nil which means `/dev/null'.
-OUTPUT can be a string (which specifies a filename), or t (which
+OUTPUT can be a string (which specifies a file name), or t (which
means standard output and thus the current buffer), or nil (which
means discard it)."
(tramp-call-process
- tramp-encoding-shell
+ nil tramp-encoding-shell
(when (and input (not (string-match "%s" cmd))) input)
(if (eq output t) t nil)
nil
""))
(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))
+ "Create a file name suitable to be passed to `scp' or `nc' and workalikes."
+ (let ((method (tramp-file-name-method vec))
+ (user (tramp-file-name-user vec))
(host (tramp-file-name-real-host vec))
(localname (tramp-shell-quote-argument
(tramp-file-name-localname vec))))
- (shell-quote-argument
- (if (not (zerop (length user)))
- (format "%s@%s:%s" user host localname)
- (format "%s:%s" host localname)))))
+ (cond
+ ((tramp-get-method-parameter method 'tramp-remote-copy-program)
+ localname)
+ ((not (zerop (length user)))
+ (shell-quote-argument (format "%s@%s:%s" user host localname)))
+ (t (shell-quote-argument (format "%s:%s" host localname))))))
(defun tramp-method-out-of-band-p (vec size)
"Return t if this is an out-of-band method, nil otherwise."
(format
"%s -t %s %s"
result
- (format-time-string "%Y%m%d%H%M.%S" (current-time))
+ (format-time-string "%Y%m%d%H%M.%S")
(tramp-file-name-handler 'file-remote-p tmpfile 'localname))))
(delete-file tmpfile))
result)))
(with-tramp-connection-property vec "id"
(tramp-message vec 5 "Finding POSIX `id' command")
(catch 'id-found
- (let ((dl (tramp-get-remote-path vec))
- result)
- (while (and dl (setq result (tramp-find-executable vec "id" dl t t)))
- ;; Check POSIX parameter.
- (when (tramp-send-command-and-check vec (format "%s -u" result))
- (throw 'id-found result))
- (setq dl (cdr dl)))))))
+ (dolist (cmd '("id" "gid"))
+ (let ((dl (tramp-get-remote-path vec))
+ result)
+ (while (and dl (setq result (tramp-find-executable vec cmd dl t t)))
+ ;; Check POSIX parameter.
+ (when (tramp-send-command-and-check vec (format "%s -u" result))
+ (throw 'id-found result))
+ (setq dl (cdr dl))))))))
(defun tramp-get-remote-uid-with-id (vec id-format)
(tramp-send-command-and-read
(defun tramp-get-remote-python (vec)
(with-tramp-connection-property vec "python"
(tramp-message vec 5 "Finding a suitable `python' command")
- (tramp-find-executable vec "python" (tramp-get-remote-path vec))))
+ (or (tramp-find-executable vec "python" (tramp-get-remote-path vec))
+ (tramp-find-executable vec "python2" (tramp-get-remote-path vec))
+ (tramp-find-executable vec "python3" (tramp-get-remote-path vec)))))
(defun tramp-get-remote-uid-with-python (vec id-format)
(tramp-send-command-and-read
(format "%s -c \"%s\""
(tramp-get-remote-python vec)
(if (equal id-format 'integer)
- "import os; print os.getuid()"
- "import os, pwd; print '\\\"' + pwd.getpwuid(os.getuid())[0] + '\\\"'"))))
+ "import os; print (os.getuid())"
+ "import os, pwd; print ('\\\"' + pwd.getpwuid(os.getuid())[0] + '\\\"')"))))
(defun tramp-get-remote-uid (vec id-format)
(with-tramp-connection-property vec (format "uid-%s" id-format)
(format "%s -c \"%s\""
(tramp-get-remote-python vec)
(if (equal id-format 'integer)
- "import os; print os.getgid()"
- "import os, grp; print '\\\"' + grp.getgrgid(os.getgid())[0] + '\\\"'"))))
+ "import os; print (os.getgid())"
+ "import os, grp; print ('\\\"' + grp.getgrgid(os.getgid())[0] + '\\\"')"))))
(defun tramp-get-remote-gid (vec id-format)
(with-tramp-connection-property vec (format "gid-%s" id-format)
;; rsync).
;; * Keep a second connection open for out-of-band methods like scp or
;; rsync.
-;; * Try telnet+curl as new method. It might be useful for busybox,
-;; without built-in uuencode/uudecode.
-;; * Try telnet+nc as new method. It might be useful for busybox,
-;; without built-in uuencode/uudecode.
;;; tramp-sh.el ends here
(expand-file-name
tramp-temp-name-prefix
(tramp-compat-temporary-file-directory))))
- (args (list tramp-smb-program
- (concat "//" real-host "/" share) "-E")))
+ (args (list (concat "//" real-host "/" share) "-E")))
(if (not (zerop (length real-user)))
(setq args (append args (list "-U" real-user)))
;; Use an asynchronous processes. By this,
;; password can be handled.
(let* ((default-directory tmpdir)
- (p (start-process-shell-command
+ (p (apply
+ 'start-process
(tramp-get-connection-name v)
(tramp-get-connection-buffer v)
- (mapconcat 'identity args " "))))
+ tramp-smb-program args)))
(tramp-message
v 6 "%s" (mapconcat 'identity (process-command p) " "))
(setq filename (file-name-as-directory filename))
(setq filename (directory-file-name filename)))
(with-parsed-tramp-file-name filename nil
- (save-match-data
- (let ((base (file-name-nondirectory filename))
- ;; We should not destroy the cache entry.
- (entries (copy-sequence
- (tramp-smb-get-file-entries
- (file-name-directory filename)))))
-
- (when wildcard
- (string-match "\\." base)
- (setq base (replace-match "\\\\." nil nil base))
- (string-match "\\*" base)
- (setq base (replace-match ".*" nil nil base))
- (string-match "\\?" base)
- (setq base (replace-match ".?" nil nil base)))
-
- ;; Filter entries.
- (setq entries
- (delq
- nil
- (if (or wildcard (zerop (length base)))
- ;; Check for matching entries.
- (mapcar
- (lambda (x)
- (when (string-match
- (format "^%s" base) (nth 0 x))
- x))
- entries)
- ;; We just need the only and only entry FILENAME.
- (list (assoc base entries)))))
-
- ;; Sort entries.
- (setq entries
- (sort
- entries
- (lambda (x y)
- (if (string-match "t" switches)
- ;; Sort by date.
- (tramp-time-less-p (nth 3 y) (nth 3 x))
- ;; Sort by name.
- (string-lessp (nth 0 x) (nth 0 y))))))
-
- ;; Handle "-F" switch.
- (when (string-match "F" switches)
+ (with-tramp-progress-reporter v 0 (format "Opening directory %s" filename)
+ (save-match-data
+ (let ((base (file-name-nondirectory filename))
+ ;; We should not destroy the cache entry.
+ (entries (copy-sequence
+ (tramp-smb-get-file-entries
+ (file-name-directory filename)))))
+
+ (when wildcard
+ (string-match "\\." base)
+ (setq base (replace-match "\\\\." nil nil base))
+ (string-match "\\*" base)
+ (setq base (replace-match ".*" nil nil base))
+ (string-match "\\?" base)
+ (setq base (replace-match ".?" nil nil base)))
+
+ ;; Filter entries.
+ (setq entries
+ (delq
+ nil
+ (if (or wildcard (zerop (length base)))
+ ;; Check for matching entries.
+ (mapcar
+ (lambda (x)
+ (when (string-match
+ (format "^%s" base) (nth 0 x))
+ x))
+ entries)
+ ;; We just need the only and only entry FILENAME.
+ (list (assoc base entries)))))
+
+ ;; Sort entries.
+ (setq entries
+ (sort
+ entries
+ (lambda (x y)
+ (if (string-match "t" switches)
+ ;; Sort by date.
+ (tramp-time-less-p (nth 3 y) (nth 3 x))
+ ;; Sort by name.
+ (string-lessp (nth 0 x) (nth 0 y))))))
+
+ ;; Handle "-F" switch.
+ (when (string-match "F" switches)
+ (mapc
+ (lambda (x)
+ (when (not (zerop (length (car x))))
+ (cond
+ ((char-equal ?d (string-to-char (nth 1 x)))
+ (setcar x (concat (car x) "/")))
+ ((char-equal ?x (string-to-char (nth 1 x)))
+ (setcar x (concat (car x) "*"))))))
+ entries))
+
+ ;; Print entries.
(mapc
(lambda (x)
- (when (not (zerop (length (car x))))
- (cond
- ((char-equal ?d (string-to-char (nth 1 x)))
- (setcar x (concat (car x) "/")))
- ((char-equal ?x (string-to-char (nth 1 x)))
- (setcar x (concat (car x) "*"))))))
- entries))
-
- ;; Print entries.
- (mapc
- (lambda (x)
- (when (not (zerop (length (nth 0 x))))
- (when (string-match "l" switches)
- (let ((attr
- (when (tramp-smb-get-stat-capability v)
- (ignore-errors
- (file-attributes filename 'string)))))
+ (when (not (zerop (length (nth 0 x))))
+ (when (string-match "l" switches)
+ (let ((attr
+ (when (tramp-smb-get-stat-capability v)
+ (ignore-errors
+ (file-attributes filename 'string)))))
+ (insert
+ (format
+ "%10s %3d %-8s %-8s %8s %s "
+ (or (nth 8 attr) (nth 1 x)) ; mode
+ (or (nth 1 attr) 1) ; inode
+ (or (nth 2 attr) "nobody") ; uid
+ (or (nth 3 attr) "nogroup") ; gid
+ (or (nth 7 attr) (nth 2 x)) ; size
+ (format-time-string
+ (if (tramp-time-less-p
+ (tramp-time-subtract (current-time) (nth 3 x))
+ tramp-half-a-year)
+ "%b %e %R"
+ "%b %e %Y")
+ (nth 3 x)))))) ; date
+
+ ;; We mark the file name. The inserted name could be
+ ;; from somewhere else, so we use the relative file name
+ ;; of `default-directory'.
+ (let ((start (point)))
(insert
(format
- "%10s %3d %-8s %-8s %8s %s "
- (or (nth 8 attr) (nth 1 x)) ; mode
- (or (nth 1 attr) 1) ; inode
- (or (nth 2 attr) "nobody") ; uid
- (or (nth 3 attr) "nogroup") ; gid
- (or (nth 7 attr) (nth 2 x)) ; size
- (format-time-string
- (if (tramp-time-less-p
- (tramp-time-subtract (current-time) (nth 3 x))
- tramp-half-a-year)
- "%b %e %R"
- "%b %e %Y")
- (nth 3 x)))))) ; date
-
- ;; We mark the file name. The inserted name could be
- ;; from somewhere else, so we use the relative file name
- ;; of `default-directory'.
- (let ((start (point)))
- (insert
- (format
- "%s\n"
- (file-relative-name
- (expand-file-name
- (nth 0 x) (file-name-directory filename))
- (when full-directory-p (file-name-directory filename)))))
- (put-text-property start (1- (point)) 'dired-filename t))
- (forward-line)
- (beginning-of-line)))
- entries)))))
+ "%s\n"
+ (file-relative-name
+ (expand-file-name
+ (nth 0 x) (file-name-directory filename))
+ (when full-directory-p (file-name-directory filename)))))
+ (put-text-property start (1- (point)) 'dired-filename t))
+ (forward-line)
+ (beginning-of-line)))
+ entries))))))
(defun tramp-smb-handle-make-directory (dir &optional parents)
"Like `make-directory' for Tramp files."
;; We must also flush the cache of the directory, because
;; `file-attributes' reads the values from there.
+ (tramp-flush-file-property v1 (file-name-directory v1-localname))
+ (tramp-flush-file-property v1 v1-localname)
(tramp-flush-file-property v2 (file-name-directory v2-localname))
(tramp-flush-file-property v2 v2-localname)
(unless (tramp-smb-get-share v2)
;; Use an asynchronous processes. By this, password can
;; be handled.
(let ((p (apply
- 'start-process-shell-command
+ 'start-process
(tramp-get-connection-name v)
(tramp-get-connection-buffer v)
tramp-smb-acl-program args)))
tamper the process output.
* `tramp-copy-program'
This specifies the name of the program to use for remotely copying
- the file; this might be the absolute filename of rcp or the name of
+ the file; this might be the absolute filename of scp or the name of
a workalike program. It is always applied on the local host.
* `tramp-copy-args'
This specifies the list of parameters to pass to the above mentioned
* `tramp-copy-env'
A list of environment variables and their values, which will
be set when calling `tramp-copy-program'.
+ * `tramp-remote-copy-program'
+ The listener program to be applied on remote side, if needed.
+ * `tramp-remote-copy-args'
+ The list of parameters to pass to the listener program, the hints
+ for `tramp-login-args' also apply here. Additionally, \"%r\" could
+ be used here and in `tramp-copy-args'. It denotes a randomly
+ chosen port for the remote listener.
* `tramp-copy-keep-date'
This specifies whether the copying program when the preserves the
timestamp of the original file.
What does all this mean? Well, you should specify `tramp-login-program'
for all methods; this program is used to log in to the remote site. Then,
there are two ways to actually transfer the files between the local and the
-remote side. One way is using an additional rcp-like program. If you want
+remote side. One way is using an additional scp-like program. If you want
to do this, set `tramp-copy-program' in the method.
Another possibility for file transfer is inline transfer, i.e. the
(and (memq system-type '(cygwin windows-nt))
(zerop
(tramp-call-process
- "reg" nil nil nil "query" (nth 1 (car v)))))
+ v "reg" nil nil nil "query" (nth 1 (car v)))))
;; Configuration file.
(file-exists-p (nth 1 (car v)))))
(setq r (delete (car v) r)))
((eq result 'non-essential)
(tramp-message
v 5 "Non-essential received in operation %s"
- (append (list operation) args))
+ (cons operation args))
(tramp-run-real-handler operation args))
((eq result 'suppress)
(let (tramp-message-show-message)
(tramp-message
v 1 "Suppress received in operation %s"
- (append (list operation) args))
+ (cons operation args))
(tramp-cleanup-connection v t)
(tramp-run-real-handler operation args)))
(t result)))
(let (tramp-message-show-message)
(tramp-message
v 1 "Interrupt received in operation %s"
- (append (list operation) args)))
+ (cons operation args)))
;; Propagate the quit signal.
(signal (car err) (cdr err)))
(if (memq system-type '(windows-nt))
(with-temp-buffer
(when (zerop (tramp-call-process
- "reg" nil t nil "query" registry-or-dirname))
+ nil "reg" nil t nil "query" registry-or-dirname))
(goto-char (point-min))
(loop while (not (eobp)) collect
(tramp-parse-putty-group registry-or-dirname))))
(defun tramp-handle-file-accessible-directory-p (filename)
"Like `file-accessible-directory-p' for Tramp files."
(and (file-directory-p filename)
- (file-executable-p filename)))
+ (file-readable-p filename)))
(defun tramp-handle-file-exists-p (filename)
"Like `file-exists-p' for Tramp files."
(with-parsed-tramp-file-name filename nil
(let ((x (car (file-attributes filename))))
(when (stringp x)
- ;; When Tramp is running on VMS, then `file-name-absolute-p'
- ;; might do weird things.
(if (file-name-absolute-p x)
(tramp-make-tramp-file-name method user host x)
x)))))
;; Run the process.
(setq p (apply 'start-file-process "*Async Shell*" buffer args))
;; Display output.
- (pop-to-buffer output-buffer)
- (setq mode-line-process '(":%s"))
- (shell-mode)
- (set-process-sentinel p 'shell-command-sentinel)
- (set-process-filter p 'comint-output-filter))
+ (with-current-buffer output-buffer
+ (display-buffer output-buffer '(nil (allow-no-window . t)))
+ (setq mode-line-process '(":%s"))
+ (shell-mode)
+ (set-process-sentinel p 'shell-command-sentinel)
+ (set-process-filter p 'comint-output-filter)))
(prog1
;; Run the process.
(defun tramp-handle-unhandled-file-name-directory (_filename)
"Like `unhandled-file-name-directory' for Tramp files."
;; With Emacs 23, we could simply return `nil'. But we must keep it
- ;; for backward compatibility.
- (expand-file-name "~/"))
+ ;; for backward compatibility. "~/" cannot be returned, because
+ ;; there might be machines without a HOME directory (like hydra).
+ "/")
(defun tramp-handle-set-visited-file-modtime (&optional time-list)
"Like `set-visited-file-modtime' for Tramp files."
(tramp-get-file-property
vec (tramp-file-name-localname vec)
(concat "file-attributes-" suffix) nil)
- (file-attributes
+ (tramp-compat-file-attributes
(tramp-make-tramp-file-name
(tramp-file-name-method vec)
(tramp-file-name-user vec)
;;; Compatibility functions section:
(defun tramp-call-process
- (program &optional infile destination display &rest args)
+ (vec program &optional infile destination display &rest args)
"Calls `call-process' on the local host.
-This is needed because for some Emacs flavors Tramp has
-defadvised `call-process' to behave like `process-file'. The
-Lisp error raised when PROGRAM is nil is trapped also, returning 1.
-Furthermore, traces are written with verbosity of 6."
- (tramp-message
- (vector tramp-current-method tramp-current-user tramp-current-host nil nil)
- 6 "`%s %s' %s %s" program (mapconcat 'identity args " ") infile destination)
- (if (executable-find program)
- (apply 'call-process program infile destination display args)
- 1))
+It always returns a return code. The Lisp error raised when
+PROGRAM is nil is trapped also, returning 1. Furthermore, traces
+are written with verbosity of 6."
+ (let ((v (or vec
+ (vector tramp-current-method tramp-current-user
+ tramp-current-host nil nil)))
+ (destination (if (eq destination t) (current-buffer) destination))
+ result)
+ (tramp-message
+ v 6 "`%s %s' %s %s"
+ program (mapconcat 'identity args " ") infile destination)
+ (condition-case err
+ (with-temp-buffer
+ (setq result
+ (apply
+ 'call-process program infile (or destination t) display args))
+ ;; `result' could also be an error string.
+ (when (stringp result)
+ (signal 'file-error (list result)))
+ (with-current-buffer
+ (if (bufferp destination) destination (current-buffer))
+ (tramp-message v 6 "%d\n%s" result (buffer-string))))
+ (error
+ (setq result 1)
+ (tramp-message v 6 "%d\n%s" result (error-message-string err))))
+ result))
;;;###tramp-autoload
(defun tramp-read-passwd (proc &optional prompt)