* lisp/net/tramp-container.el (tramp-methods) <docker, dockercp, podman>
<podmancp, apptainer, nspawn>:
* lisp/net/tramp-sh.el (tramp-methods) <scp, scpx, rsync>
<ssh, sshx, sudo>:
* lisp/net/tramp-sshfs.el (tramp-methods) <sshfs>: Set TERM environment.
(Bug#78508)
* lisp/net/tramp-sh.el (tramp-find-executable): Handle superlong PATH.
(tramp-set-remote-path): Simplify command.
(tramp-timeout-session): Add ;;;###tramp-autoload cookie.
* lisp/net/tramp-smb.el (tramp-smb-errors): Add string.
(tramp-smb-winexe-program): Adapt docstring.
(tramp-smb-handle-copy-directory, tramp-smb-handle-file-acl)
(tramp-smb-handle-set-file-acl, tramp-smb-maybe-open-connection):
Simplify argument handling.
(tramp-smb-handle-process-file): Flush " process-exit-status" property.
(tramp-smb-call-winexe): Set $winsize.Width to 102 only.
* lisp/net/tramp.el (tramp-process-sentinel): Adapt docstring.
Set " process-exit-status" property.
* test/lisp/net/tramp-tests.el (tramp--test-enabled):
Make it more robust.
(tramp-test18-file-attributes)
(tramp-test26-interactive-file-name-completion)
(tramp-test26-file-name-completion-boundaries)
(tramp-test35-remote-path): Adapt tests.
(cherry picked from commit
5ce0e1372bb41ac83c513a632a57b3ffb643971e)
;;; TODO:
;;
;; * Use multisession.el, starting with Emacs 29.1.
+;;
+;; Use `with-memoization', starting with Emacs 29.1.
;;; tramp-cache.el ends here
(tramp-login-args (("exec")
("-it")
("-u" "%u")
+ ("-e" ,(format "TERM=%s" tramp-terminal-type))
("%h")
("%l")))
(tramp-direct-async (,tramp-default-remote-shell "-c"))
(tramp-login-args (("exec")
("-it")
("-u" "%u")
+ ("-e" ,(format "TERM=%s" tramp-terminal-type))
("%h")
("%l")))
(tramp-direct-async (,tramp-default-remote-shell "-c"))
(tramp-login-args (("exec")
("-it")
("-u" "%u")
+ ("-e" ,(format "TERM=%s" tramp-terminal-type))
("%h")
("%l")))
(tramp-direct-async (,tramp-default-remote-shell "-c"))
(tramp-login-args (("exec")
("-it")
("-u" "%u")
+ ("-e" ,(format "TERM=%s" tramp-terminal-type))
("%h")
("%l")))
(tramp-direct-async (,tramp-default-remote-shell "-c"))
`(,tramp-apptainer-method
(tramp-login-program ,tramp-apptainer-program)
(tramp-login-args (("shell")
+ ("--env"
+ ,(format "TERM=%s" tramp-terminal-type))
("instance://%h")
("%h"))) ; Needed for multi-hop check.
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-login-args (("shell")
("-q")
("--uid" "%u")
+ ("-E"
+ ,(format "TERM=%s" tramp-terminal-type))
("%h")))
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-remote-shell-login ("-l"))
`("scp"
(tramp-login-program "ssh")
(tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
- ("-e" "none") ("%h")))
+ ("-e" "none")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
+ ("%h")))
(tramp-async-args (("-q")))
(tramp-direct-async ("-t" "-t"))
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
("-e" "none") ("-t" "-t")
("-o" "RemoteCommand=\"%l\"")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
("%h")))
(tramp-async-args (("-q")))
(tramp-remote-shell ,tramp-default-remote-shell)
`("rsync"
(tramp-login-program "ssh")
(tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
- ("-e" "none") ("%h")))
+ ("-e" "none")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
+ ("%h")))
(tramp-async-args (("-q")))
(tramp-direct-async t)
(tramp-remote-shell ,tramp-default-remote-shell)
`("ssh"
(tramp-login-program "ssh")
(tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
- ("-e" "none") ("%h")))
+ ("-e" "none")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
+ ("%h")))
(tramp-async-args (("-q")))
(tramp-direct-async ("-t" "-t"))
(tramp-remote-shell ,tramp-default-remote-shell)
(tramp-login-program "ssh")
(tramp-login-args (("-l" "%u") ("-p" "%p") ("%c")
("-e" "none") ("-t" "-t")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
("-o" "RemoteCommand=\"%l\"")
("%h")))
(tramp-async-args (("-q")))
;; remote host echoes the command.
;; The "-p" argument doesn't work reliably, see Bug#50594.
(tramp-login-args (("SUDO_PROMPT=P\"\"a\"\"s\"\"s\"\"w\"\"o\"\"r\"\"d\"\":")
+ (,(format "TERM=%s" tramp-terminal-type))
("sudo") ("-u" "%u") ("-s") ("-H")
("%l")))
(tramp-remote-shell ,tramp-default-remote-shell)
(unless (char-equal ?~ (aref d 0))
(setq newdl (cons d newdl))))
(setq dirlist (nreverse newdl))))
- (when (tramp-send-command-and-check
- vec (format "(unalias %s; %s command -v %s)"
- progname
- (if dirlist (concat "PATH=" (string-join dirlist ":")) "")
- progname))
- (string-trim (tramp-get-buffer-string (tramp-get-connection-buffer vec)))))
+ (let ((command
+ (concat
+ (when dirlist (format "PATH=%s " (string-join dirlist ":")))
+ "command -v " progname))
+ (pipe-buf (tramp-get-remote-pipe-buf vec))
+ tmpfile chunk chunksize)
+ (when (if (length< command pipe-buf)
+ (tramp-send-command-and-check vec command)
+ ;; Use a temporary file. We cannot use `write-region'
+ ;; because setting the remote path happens in the early
+ ;; connection handshake, and not all external tools are
+ ;; determined yet.
+ (setq command (concat command "\n")
+ tmpfile (tramp-make-tramp-temp-file vec))
+ (while (not (string-empty-p command))
+ (setq chunksize (min (length command) (/ pipe-buf 2))
+ chunk (substring command 0 chunksize)
+ command (substring command chunksize))
+ (tramp-send-command
+ vec (format "printf \"%%b\" \"$*\" %s >>%s"
+ (tramp-shell-quote-argument chunk)
+ (tramp-shell-quote-argument tmpfile))))
+ (tramp-send-command-and-check
+ vec (format ". %s && rm -f %s" tmpfile tmpfile)))
+
+ (string-trim
+ (tramp-get-buffer-string (tramp-get-connection-buffer vec))))))
;; On hydra.nixos.org, the $PATH environment variable is too long to
;; send it. This is likely not due to PATH_MAX, but PIPE_BUF. We
(setq chunksize (min (length command) (/ pipe-buf 2))
chunk (substring command 0 chunksize)
command (substring command chunksize))
- (tramp-send-command vec (format
- "printf \"%%b\" \"$*\" %s >>%s"
- (tramp-shell-quote-argument chunk)
- (tramp-shell-quote-argument tmpfile))))
- (tramp-send-command vec (format ". %s" tmpfile))
- (tramp-send-command vec (format "rm -f %s" tmpfile))))))
+ (tramp-send-command
+ vec (format "printf \"%%b\" \"$*\" %s >>%s"
+ (tramp-shell-quote-argument chunk)
+ (tramp-shell-quote-argument tmpfile))))
+ (tramp-send-command vec (format ". %s && rm -f %s" tmpfile tmpfile))))))
;; ------------------------------------------------------------
;; -- Communication with external shell --
(t "-3")))
+;;;###tramp-autoload
(defun tramp-timeout-session (vec)
"Close the connection VEC after a session timeout.
If there is just some editing, retry it after 5 seconds."
"NT_STATUS_PASSWORD_MUST_CHANGE"
"NT_STATUS_RESOURCE_NAME_NOT_FOUND"
"NT_STATUS_REVISION_MISMATCH"
+ "NT_STATUS_RPC_SS_CONTEXT_MISMATCH"
"NT_STATUS_SHARING_VIOLATION"
"NT_STATUS_TRUSTED_RELATIONSHIP_FAILURE"
"NT_STATUS_UNSUCCESSFUL"
;; Options for remote processes via winexe.
(defcustom tramp-smb-winexe-program "winexe"
"Name of winexe client to run.
-If it isn't found in the local $PATH, the absolute path of winexe
+If it isn't found in the local $PATH, the absolute path of \"winexe\"
shall be given. This is needed for remote processes."
:group 'tramp
:version "24.3"
(args (list (concat "//" host "/" share) "-E"))
(options tramp-smb-options))
- (if (tramp-string-empty-or-nil-p user)
- (setq args (append args (list "-N")))
- (setq args (append args (list "-U" user))))
+ (setq args
+ (append args
+ (if (tramp-string-empty-or-nil-p user)
+ (list "-N")
+ (list "-U" (if domain (concat domain "/" user) user)))
+ (when port (list "-p" port))))
- (when domain (setq args (append args (list "-W" domain))))
- (when port (setq args (append args (list "-p" port))))
(when tramp-smb-conf
(setq args (append args (list "-s" tramp-smb-conf))))
(while options
(args (list (concat "//" host "/" share) "-E"))
(options tramp-smb-options))
- (if (tramp-string-empty-or-nil-p user)
- (setq args (append args (list "-N")))
- (setq args (append args (list "-U" user))))
+ (setq args
+ (append args
+ (if (tramp-string-empty-or-nil-p user)
+ (list "-N")
+ (list "-U" (if domain (concat domain "/" user) user)))
+ (when port (list "-p" port))))
- (when domain (setq args (append args (list "-W" domain))))
- (when port (setq args (append args (list "-p" port))))
(when tramp-smb-conf
(setq args (append args (list "-s" tramp-smb-conf))))
(while options
(tramp-set-connection-property
v " process-buffer"
(or outbuf (generate-new-buffer tramp-temp-buffer-name)))
+ (tramp-flush-connection-property v " process-exit-status")
(with-current-buffer (tramp-get-connection-buffer v)
;; Preserve buffer contents.
(narrow-to-region (point-max) (point-max))
(string-replace "\n" "," acl-string)))
(options tramp-smb-options))
- (if (tramp-string-empty-or-nil-p user)
- (setq args (append args (list "-N")))
- (setq args (append args (list "-U" user))))
+ (setq args
+ (append args
+ (if (tramp-string-empty-or-nil-p user)
+ (list "-N")
+ (list "-U" (if domain (concat domain "/" user) user)))
+ (when port (list "-p" port))))
- (when domain (setq args (append args (list "-W" domain))))
- (when port (setq args (append args (list "-p" port))))
(when tramp-smb-conf
(setq args (append args (list "-s" tramp-smb-conf))))
(while options
(share (setq args (list (concat "//" host "/" share))))
(t (setq args (list "-g" "-L" host ))))
- (if (tramp-string-empty-or-nil-p user)
- (setq args (append args (list "-N")))
- (setq args (append args (list "-U" user))))
+ (setq args
+ (append args
+ (if (tramp-string-empty-or-nil-p user)
+ (list "-N")
+ (list "-U" (if domain (concat domain "/" user) user)))
+ (when port (list "-p" port))))
- (when domain (setq args (append args (list "-W" domain))))
- (when port (setq args (append args (list "-p" port))))
(when tramp-smb-conf
(setq args (append args (list "-s" tramp-smb-conf))))
(dolist (option options)
(setq args (append args (list "--option" option))))
+ ;; For debugging.
+ (setq args (append args (list "-d" "1")))
(when argument
(setq args (append args (list argument))))
(when (tramp-file-name-port vec)
(tramp-error vec 'file-error "Port not supported for remote processes"))
+ ;; In case of "NT_STATUS_RPC_SS_CONTEXT_MISMATCH", the remote server
+ ;; is a Samba server. winexe cannot install the respective service there.
(tramp-smb-maybe-open-connection
vec
(format
;; Suppress "^M". Shouldn't we specify utf8?
(set-process-coding-system (tramp-get-connection-process vec) 'raw-text-dos)
- ;; Set width to 128. This avoids mixing prompt and long error messages.
+ ;; Set width to 128 ($bufsize.Width) or 102 ($winsize.Width),
+ ;; respectively. $winsize.Width cannot be larger. This avoids
+ ;; mixing prompt and long error messages.
(tramp-smb-send-command vec "$rawui = (Get-Host).UI.RawUI")
(tramp-smb-send-command vec "$bufsize = $rawui.BufferSize")
(tramp-smb-send-command vec "$winsize = $rawui.WindowSize")
(tramp-smb-send-command vec "$bufsize.Width = 128")
- (tramp-smb-send-command vec "$winsize.Width = 128")
+ (tramp-smb-send-command vec "$winsize.Width = 102")
(tramp-smb-send-command vec "$rawui.BufferSize = $bufsize")
(tramp-smb-send-command vec "$rawui.WindowSize = $winsize"))
;; several places, especially in `tramp-smb-handle-insert-directory'.
;;
;; * Keep a separate connection process per share.
+;;
+;; * Keep a permanent connection process for `process-file'.
;;; tramp-smb.el ends here
(tramp-login-program "ssh")
(tramp-login-args (("-q") ("-l" "%u") ("-p" "%p")
("-e" "none") ("%a" "%a")
+ ("-o" ,(format "SetEnv=\"TERM=%s\""
+ tramp-terminal-type))
("%h") ("%l")))
(tramp-direct-async t)
(tramp-remote-shell ,tramp-default-remote-shell)
(process-send-string p string)))))))
(defun tramp-process-sentinel (proc event)
- "Flush file caches and remove shell prompt."
+ "Flush file caches and remove shell prompt.
+Set exit status of PROC as connection property \" process-exit-status\"."
(unless (process-live-p proc)
(let ((vec (process-get proc 'tramp-vector))
(buf (process-buffer proc))
(prompt (tramp-get-connection-property proc "prompt")))
(when vec
- (tramp-message vec 5 "Sentinel called: `%S' `%s'" proc event)
+ (tramp-message
+ vec 5 "Sentinel called: `%S' event: `%s' status: %s"
+ proc event (process-exit-status proc))
(tramp-flush-connection-properties proc)
- (tramp-flush-directory-properties vec "/"))
+ (tramp-flush-directory-properties vec "/")
+ ;; Sometimes, the process has been deleted already before we
+ ;; can retrieve the exit status.
+ (tramp-set-connection-property
+ vec " process-exit-status" (process-exit-status proc)))
(when (buffer-live-p buf)
(with-current-buffer buf
(when (and prompt (tramp-search-regexp (rx (literal prompt))))