From 809790a1d23ab98e76531c5ff77375c2c7c2f00c Mon Sep 17 00:00:00 2001 From: Michael Albinus Date: Wed, 23 Jul 2025 16:22:26 +0200 Subject: [PATCH] Add consistent environment for local process calls in Tramp * lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection): * lisp/net/tramp-androidsu.el (tramp-androidsu-maybe-open-connection): * lisp/net/tramp-gvfs.el (tramp-gvfs-handle-file-notify-add-watch): * lisp/net/tramp-sh.el (tramp-do-copy-or-rename-file-out-of-band) (tramp-maybe-open-connection): * lisp/net/tramp-smb.el (tramp-smb-handle-copy-directory) (tramp-smb-handle-file-acl) (tramp-smb-handle-file-notify-add-watch) (tramp-smb-handle-set-file-acl, tramp-smb-maybe-open-connection): * lisp/net/tramp-sudoedit.el (tramp-sudoedit-send-command): Use `tramp-start-process'. Do not call `tramp-post-process-creation'. * lisp/net/tramp.el (with-tramp-local-environment): New defmacro. (tramp-start-process): New defun. (tramp-call-process, tramp-call-process-region) (tramp-process-lines): Use `with-tramp-local-environment'. (cherry picked from commit c142f0d246095b75bdb3a7d8bc3079a55e48f2b3) --- lisp/net/tramp-adb.el | 11 +++---- lisp/net/tramp-androidsu.el | 19 ++++++------ lisp/net/tramp-gvfs.el | 3 +- lisp/net/tramp-sh.el | 36 ++++++++++------------ lisp/net/tramp-smb.el | 42 ++++++++------------------ lisp/net/tramp-sudoedit.el | 18 +++++------ lisp/net/tramp.el | 60 +++++++++++++++++++++++++------------ 7 files changed, 92 insertions(+), 97 deletions(-) diff --git a/lisp/net/tramp-adb.el b/lisp/net/tramp-adb.el index 883345506a1..21e6a93570a 100644 --- a/lisp/net/tramp-adb.el +++ b/lisp/net/tramp-adb.el @@ -1117,17 +1117,14 @@ connection if a previous connection has died for some reason." (process-connection-type tramp-process-connection-type) (args (tramp-expand-args vec 'tramp-login-args nil ?d (or device ""))) - (p (let ((default-directory - tramp-compat-temporary-file-directory)) - (apply - #'start-process (tramp-get-connection-name vec) buf - tramp-adb-program args))) + (p (apply + #'tramp-start-process vec (tramp-get-connection-name vec) + buf tramp-adb-program args)) (prompt (md5 (concat (prin1-to-string process-environment) (current-time-string))))) - ;; Set sentinel. Initialize variables. + ;; Set sentinel. (set-process-sentinel p #'tramp-process-sentinel) - (tramp-post-process-creation p vec) ;; Wait for initial prompt. On some devices, it needs ;; an initial RET, in order to get it. diff --git a/lisp/net/tramp-androidsu.el b/lisp/net/tramp-androidsu.el index 9fd2ee61803..3969d7475cf 100644 --- a/lisp/net/tramp-androidsu.el +++ b/lisp/net/tramp-androidsu.el @@ -131,19 +131,18 @@ multibyte mode and waits for the shell prompt to appear." ;; The executable loader cannot execute setuid ;; binaries, such as su. (android-use-exec-loader nil) - (p (start-process (tramp-get-connection-name vec) - (tramp-get-connection-buffer vec) - ;; Disregard - ;; `tramp-encoding-shell', as - ;; there's no guarantee that it's - ;; possible to execute it with - ;; `android-use-exec-loader' off. - tramp-androidsu-local-shell-name "-i")) + (p (tramp-start-process + vec (tramp-get-connection-name vec) + (tramp-get-connection-buffer vec) + ;; Disregard `tramp-encoding-shell', as + ;; there's no guarantee that it's possible to + ;; execute it with `android-use-exec-loader' + ;; off. + tramp-androidsu-local-shell-name "-i")) (user (tramp-file-name-user vec)) su-binary path command) - ;; Set sentinel. Initialize variables. + ;; Set sentinel. (set-process-sentinel p #'tramp-process-sentinel) - (tramp-post-process-creation p vec) ;; Replace `login-args' place holders. `PATH' must be ;; set to `tramp-androidsu-remote-path', as some `su' ;; implementations propagate their callers' environments diff --git a/lisp/net/tramp-gvfs.el b/lisp/net/tramp-gvfs.el index 7bc8f7ccfbd..424dfbc96a7 100644 --- a/lisp/net/tramp-gvfs.el +++ b/lisp/net/tramp-gvfs.el @@ -1510,7 +1510,7 @@ If FILE-SYSTEM is non-nil, return file system attributes." '(created changed changes-done-hint moved deleted unmounted)) ((memq 'attribute-change flags) '(attribute-changed unmounted)))) (p (apply - #'start-process + #'tramp-start-process v "gvfs-monitor" (generate-new-buffer " *gvfs-monitor*") `("gio" "monitor" ,(tramp-gvfs-url-file-name file-name))))) (if (not (processp p)) @@ -1521,7 +1521,6 @@ If FILE-SYSTEM is non-nil, return file system attributes." (process-put p 'tramp-watch-name localname) (set-process-filter p #'tramp-gvfs-monitor-process-filter) (set-process-sentinel p #'tramp-file-notify-process-sentinel) - (tramp-post-process-creation p v) ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (while (tramp-accept-process-output p)) diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el index 649f3e7bd37..1d1879fb4d2 100644 --- a/lisp/net/tramp-sh.el +++ b/lisp/net/tramp-sh.el @@ -2627,14 +2627,11 @@ The method used must be an out-of-band method." ;; can be handled. We don't set a timeout, because ;; the copying of large files can last longer than 60 ;; secs. - p (let ((default-directory - tramp-compat-temporary-file-directory)) - (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - copy-program copy-args))) - (tramp-post-process-creation p v) + p (apply + #'tramp-start-process v + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + copy-program copy-args)) ;; We must adapt `tramp-local-end-of-line' for sending ;; the password. Also, we indicate that perhaps @@ -3923,7 +3920,7 @@ Fall back to normal file name handler if no Tramp handler exists." bol (+ (not ":")) ":" blank (group (+ (not ":"))) ":" blank (group (regexp (regexp-opt tramp-gio-events))) - (? blank (group (+ (not ":")))) eol) + (? blank (group (+ (not (any "\r\n:"))))) eol) string) (let* ((file (match-string 1 string)) @@ -5249,21 +5246,18 @@ connection if a previous connection has died for some reason." (extra-args (tramp-get-sh-extra-args tramp-encoding-shell)) ;; This must be done in order to avoid our file ;; name handler. - (p (let ((default-directory - tramp-compat-temporary-file-directory)) - (apply - #'start-process - (tramp-get-connection-name vec) - (tramp-get-connection-buffer vec) - (append - `(,tramp-encoding-shell) - (and extra-args (split-string extra-args)) - (and tramp-encoding-command-interactive - `(,tramp-encoding-command-interactive))))))) + (p (apply + #'tramp-start-process vec + (tramp-get-connection-name vec) + (tramp-get-connection-buffer vec) + (append + `(,tramp-encoding-shell) + (and extra-args (split-string extra-args)) + (and tramp-encoding-command-interactive + `(,tramp-encoding-command-interactive)))))) ;; Set sentinel. Initialize variables. (set-process-sentinel p #'tramp-process-sentinel) - (tramp-post-process-creation p vec) (setq tramp-current-connection (cons vec (current-time))) ;; Set connection-local variables. diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index b8c6dfd4482..011017039f5 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -552,13 +552,11 @@ arguments to pass to the OPERATION." ;; Use an asynchronous processes. By this, ;; password can be handled. - (let* ((default-directory tmpdir) - (p (apply - #'start-process - (tramp-get-connection-name v) - (tramp-get-connection-buffer v) - tramp-smb-program args))) - (tramp-post-process-creation p v) + (let ((p (apply + #'tramp-start-process v + (tramp-get-connection-name v) + (tramp-get-connection-buffer v) + tramp-smb-program args))) (tramp-process-actions p v nil tramp-smb-actions-with-tar) @@ -813,11 +811,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; Use an asynchronous process. By this, password ;; can be handled. (let ((p (apply - #'start-process + #'tramp-start-process v (tramp-get-connection-name v) (tramp-get-connection-buffer v) tramp-smb-acl-program args))) - (tramp-post-process-creation p v) (tramp-process-actions p v nil tramp-smb-actions-get-acl) (when (> (point-max) (point-min)) (substring-no-properties (buffer-string)))))))))))) @@ -1000,7 +997,6 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." (process-put p 'tramp-watch-name localname) (set-process-filter p #'tramp-smb-notify-process-filter) (set-process-sentinel p #'tramp-file-notify-process-sentinel) - (tramp-post-process-creation p v) ;; There might be an error if the monitor is not supported. ;; Give the filter a chance to read the output. (while (tramp-accept-process-output p)) @@ -1505,11 +1501,10 @@ PRESERVE-UID-GID and PRESERVE-EXTENDED-ATTRIBUTES are completely ignored." ;; Use an asynchronous process. By this, password ;; can be handled. (let ((p (apply - #'start-process + #'tramp-start-process v (tramp-get-connection-name v) (tramp-get-connection-buffer v) tramp-smb-acl-program args))) - (tramp-post-process-creation p v) (tramp-process-actions p v nil tramp-smb-actions-set-acl) ;; This is meant for traces, and returning from ;; the function. No error is propagated outside, @@ -2042,23 +2037,12 @@ If ARGUMENT is non-nil, use it as argument for (let* (coding-system-for-read (process-connection-type tramp-process-connection-type) - (p (let ((default-directory - tramp-compat-temporary-file-directory) - (process-environment - (cons (concat "TERM=" tramp-terminal-type) - process-environment)) - ;; There might be some unfortune values of - ;; `tramp-smb-connection-local-default-system-variables'. - (path-separator (default-value 'path-separator)) - (null-device (default-value 'null-device)) - (exec-suffixes (default-value 'exec-suffixes))) - (apply #'start-process - (tramp-get-connection-name vec) - (tramp-get-connection-buffer vec) - (if argument - tramp-smb-winexe-program tramp-smb-program) - args)))) - (tramp-post-process-creation p vec) + (p (apply #'tramp-start-process vec + (tramp-get-connection-name vec) + (tramp-get-connection-buffer vec) + (if argument + tramp-smb-winexe-program tramp-smb-program) + args))) ;; Set connection-local variables. (tramp-set-connection-local-variables vec) diff --git a/lisp/net/tramp-sudoedit.el b/lisp/net/tramp-sudoedit.el index d21970e21ad..e3e69cb1b65 100644 --- a/lisp/net/tramp-sudoedit.el +++ b/lisp/net/tramp-sudoedit.el @@ -771,14 +771,15 @@ in case of error, t otherwise." (erase-buffer) (let* ((delete-exited-processes t) (process-connection-type tramp-process-connection-type) - (p (apply #'start-process - (tramp-get-connection-name vec) (current-buffer) - (append - (tramp-expand-args - vec 'tramp-sudo-login nil - ?h (or (tramp-file-name-host vec) "") - ?u (or (tramp-file-name-user vec) "")) - (flatten-tree args)))) + (p (apply + #'tramp-start-process vec + (tramp-get-connection-name vec) (current-buffer) + (append + (tramp-expand-args + vec 'tramp-sudo-login nil + ?h (or (tramp-file-name-host vec) "") + ?u (or (tramp-file-name-user vec) "")) + (flatten-tree args)))) ;; We suppress the messages `Waiting for prompts from remote shell'. (tramp-verbose (if (= tramp-verbose 3) 2 tramp-verbose)) ;; The password shall be cached also in case of "emacs -Q". @@ -788,7 +789,6 @@ in case of error, t otherwise." auth-source-save-behavior) ;; Avoid process status message in output buffer. (set-process-sentinel p #'ignore) - (tramp-post-process-creation p vec) (tramp-set-connection-property p "pw-vector" tramp-sudoedit-null-hop) (tramp-process-actions p vec nil tramp-sudoedit-sudo-actions) (tramp-message vec 6 "%s\n%s" (process-exit-status p) (buffer-string)) diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index 5a19e4be1ae..6c501a3ebe4 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -6867,16 +6867,41 @@ ALIST is of the form ((FROM . TO) ...)." ;;; Compatibility functions section: +(defmacro with-tramp-local-environment (&rest body) + "Set environment for local processes and run BODY. +Beside some global variables, it let-binds also the connection-local +variables defined in `tramp-connection-local-default-system-variables'. +If the current buffer is a remote one, these connection-local variables +might have improper values." + (declare (debug t)) + (let ((bindings + (mapcar + (lambda (elem) `(,elem (default-value ',elem))) + (mapcar #'car tramp-connection-local-default-system-variables)))) + `(let* ((default-directory tramp-compat-temporary-file-directory) + (temporary-file-directory tramp-compat-temporary-file-directory) + (process-environment + (cons "TERM=dumb" (default-toplevel-value 'process-environment))) + ,@bindings) + ,@body))) + +(defun tramp-start-process (vec name buffer program &rest args) + "Call `start-process' on the local host. +Run post process creation actions. Traces are written with verbosity of 6." + (let ((vec (or vec (car tramp-current-connection))) + (p (with-tramp-local-environment + (apply #'start-process name buffer program args)))) + ;; Initialize variables. + (tramp-post-process-creation p vec) + p)) + (defun tramp-call-process (vec program &optional infile destination display &rest args) "Call `call-process' on the local host. 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 ((default-directory tramp-compat-temporary-file-directory) - (temporary-file-directory tramp-compat-temporary-file-directory) - (process-environment (default-toplevel-value 'process-environment)) - (destination (if (eq destination t) (current-buffer) destination)) + (let ((destination (if (eq destination t) (current-buffer) destination)) (vec (or vec (car tramp-current-connection))) output error result) (tramp-message @@ -6885,8 +6910,9 @@ are written with verbosity of 6." (condition-case err (with-temp-buffer (setq result - (apply - #'call-process program infile (or destination t) display args) + (with-tramp-local-environment + (apply + #'call-process program infile (or destination t) display args)) output (tramp-get-buffer-string destination)) ;; `result' could also be an error string. (when (stringp result) @@ -6906,10 +6932,7 @@ are written with verbosity of 6." 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 ((default-directory tramp-compat-temporary-file-directory) - (temporary-file-directory tramp-compat-temporary-file-directory) - (process-environment (default-toplevel-value 'process-environment)) - (buffer (if (eq buffer t) (current-buffer) buffer)) + (let ((buffer (if (eq buffer t) (current-buffer) buffer)) (vec (or vec (car tramp-current-connection))) result) (tramp-message @@ -6918,9 +6941,10 @@ are written with verbosity of 6." (condition-case err (progn (setq result - (apply - #'call-process-region - start end program delete buffer display args)) + (with-tramp-local-environment + (apply + #'call-process-region + start end program delete buffer display args))) ;; `result' could also be an error string. (when (stringp result) (signal 'file-error (list result))) @@ -6933,21 +6957,19 @@ are written with verbosity of 6." (tramp-message vec 6 "%d\n%s" result (error-message-string err)))) result)) -(defun tramp-process-lines - (vec program &rest args) +(defun tramp-process-lines (vec program &rest args) "Call `process-lines' on the local host. If an error occurs, it returns nil. Traces are written with verbosity of 6." - (let ((default-directory tramp-compat-temporary-file-directory) - (process-environment (default-toplevel-value 'process-environment)) - (vec (or vec (car tramp-current-connection))) + (let ((vec (or vec (car tramp-current-connection))) result) (if args (tramp-message vec 6 "%s %s" program (string-join args " ")) (tramp-message vec 6 "%s" program)) (setq result (condition-case err - (apply #'process-lines program args) + (with-tramp-local-environment + (apply #'process-lines program args)) (error (tramp-error vec (car err) (cdr err))))) (tramp-message vec 6 "\n%s" (string-join result "\n")) -- 2.39.5