changeset 85067:4636000015c5

* net/tramp.el (top): Move loading of tramp-util.el and tramp-vc.el to tramp-compat.el. (tramp-make-tramp-temp-file): Complete rewrite. Create remote temporary file if possible, in order to avoid a security hole. (tramp-do-copy-or-rename-file-out-of-band) (tramp-maybe-open-connection): Call `tramp-make-tramp-temp-file' with DONT-CREATE, because the connection is not setup yet. (tramp-handle-process-file): Rewrite temporary file handling. (tramp-completion-mode): New defvar. (tramp-completion-mode-p): Use it. * net/tramp-compat.el (top): Load tramp-util.el and tramp-vc.el. * net/tramp-fish.el (tramp-fish-handle-process-file): Rewrite temporary file handling.
author Michael Albinus <michael.albinus@gmx.de>
date Sat, 06 Oct 2007 12:00:42 +0000
parents 875aa6bd4755
children 6d4dbcc19e80
files lisp/ChangeLog lisp/net/tramp-compat.el lisp/net/tramp-fish.el lisp/net/tramp.el
diffstat 4 files changed, 129 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Sat Oct 06 11:55:36 2007 +0000
+++ b/lisp/ChangeLog	Sat Oct 06 12:00:42 2007 +0000
@@ -1,3 +1,21 @@
+2007-10-06  Michael Albinus  <michael.albinus@gmx.de>
+
+	* net/tramp.el (top): Move loading of tramp-util.el and
+	tramp-vc.el to tramp-compat.el.
+	(tramp-make-tramp-temp-file): Complete rewrite.  Create remote
+	temporary file if possible, in order to avoid a security hole.
+	(tramp-do-copy-or-rename-file-out-of-band)
+	(tramp-maybe-open-connection): Call `tramp-make-tramp-temp-file'
+	with DONT-CREATE, because the connection is not setup yet.
+	(tramp-handle-process-file): Rewrite temporary file handling.
+	(tramp-completion-mode): New defvar.
+	(tramp-completion-mode-p): Use it.
+
+	* net/tramp-compat.el (top):  Load tramp-util.el and tramp-vc.el.
+
+	* net/tramp-fish.el (tramp-fish-handle-process-file): Rewrite
+	temporary file handling.
+
 2007-10-06  Eric S. Raymond  <esr@snark.thyrsus.com>
 
 	* vc.el: workfile version -> focus version change. Port various
--- a/lisp/net/tramp-compat.el	Sat Oct 06 11:55:36 2007 +0000
+++ b/lisp/net/tramp-compat.el	Sat Oct 06 12:00:42 2007 +0000
@@ -40,6 +40,32 @@
       (require 'timer-funcs)
     (require 'timer))
 
+  ;; tramp-util offers integration into other (X)Emacs packages like
+  ;; compile.el, gud.el etc.  Not necessary in Emacs 23.
+  (eval-after-load "tramp"
+    ;; We check whether `start-file-process' is an alias.
+    '(when (or (not (fboundp 'start-file-process))
+	       (symbolp (symbol-function 'start-file-process)))
+       (require 'tramp-util)
+       (add-hook 'tramp-unload-hook
+		 '(lambda ()
+		    (when (featurep 'tramp-util)
+		      (unload-feature 'tramp-util 'force))))))
+
+  ;; Make sure that we get integration with the VC package.  When it
+  ;; is loaded, we need to pull in the integration module.  Not
+  ;; necessary in Emacs 23.
+  (eval-after-load "vc"
+    (eval-after-load "tramp"
+      ;; We check whether `start-file-process' is an alias.
+      '(when (or (not (fboundp 'start-file-process))
+		 (symbolp (symbol-function 'start-file-process)))
+	 (require 'tramp-vc)
+	 (add-hook 'tramp-unload-hook
+		   '(lambda ()
+		      (when (featurep 'tramp-vc)
+			(unload-feature 'tramp-vc 'force)))))))
+
   ;; Avoid byte-compiler warnings if the byte-compiler supports this.
   ;; Currently, XEmacs supports this.
   (when (featurep 'xemacs)
--- a/lisp/net/tramp-fish.el	Sat Oct 06 11:55:36 2007 +0000
+++ b/lisp/net/tramp-fish.el	Sat Oct 06 12:00:42 2007 +0000
@@ -734,8 +734,8 @@
     (error "Implementation does not handle immediate return"))
 
   (with-parsed-tramp-file-name default-directory nil
-    (let ((temp-name-prefix (tramp-make-tramp-temp-file v))
-	  command input output stderr outbuf tmpfile ret)
+    (let (command input tmpinput output tmpoutput stderr tmpstderr
+		  outbuf tmpfile ret)
       ;; Compute command.
       (setq command (mapconcat 'tramp-shell-quote-argument
 			       (cons program args) " "))
@@ -747,15 +747,14 @@
 	    ;; INFILE is on the same remote host.
 	    (setq input (with-parsed-tramp-file-name infile nil localname))
 	  ;; INFILE must be copied to remote host.
-	  (setq input (concat temp-name-prefix ".in"))
-	  (copy-file
-	   infile
-	   (tramp-make-tramp-file-name method user host input)
-	   t)))
+	  (setq input (tramp-make-tramp-temp-file v)
+		tmpinput (tramp-make-tramp-file-name method user host input))
+	  (copy-file infile tmpinput t)))
       (when input (setq command (format "%s <%s" command input)))
 
       ;; Determine output.
-      (setq output (concat temp-name-prefix ".out"))
+      (setq output (tramp-make-tramp-temp-file v)
+	    tmpoutput (tramp-make-tramp-file-name method user host output))
       (cond
        ;; Just a buffer
        ((bufferp destination)
@@ -781,7 +780,9 @@
 			       (cadr destination) nil localname))
 	    ;; stderr must be copied to remote host.  The temporary
 	    ;; file must be deleted after execution.
-	    (setq stderr (concat temp-name-prefix ".err"))))
+	    (setq stderr (tramp-make-tramp-temp-file v)
+		  tmpstderr (tramp-make-tramp-file-name
+			     method user host stderr))))
 	 ;; stderr to be discarded
 	 ((null (cadr destination))
 	  (setq stderr "/dev/null"))))
@@ -790,9 +791,6 @@
 	(setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; If we have a temporary file, it must be removed after operation.
-      (when (and input (string-match temp-name-prefix input))
-	(setq command (format "%s; rm %s" command input)))
       ;; Goto working directory.
       (unless
 	  (tramp-fish-send-command-and-check
@@ -821,16 +819,15 @@
 	    ;; We should show the output anyway.
 	    (when outbuf
 	      (with-current-buffer outbuf (insert-file-contents tmpfile))
-	      (when display (display-buffer outbuf)))
-	    ;; Remove output file.
-	    (delete-file (tramp-make-tramp-file-name method user host output)))
+	      (when display (display-buffer outbuf))))
 	;; When the user did interrupt, we should do it also.
 	(error (setq ret 1)))
-      (unless ret
-	;; Provide error file.
-	(when (and stderr (string-match temp-name-prefix stderr))
-	  (rename-file (tramp-make-tramp-file-name method user host stderr)
-		       (cadr destination) t)))
+
+      ;; Provide error file.
+      (when tmpstderr (rename-file tmpstderr (cadr destination) t))
+      ;; Cleanup.
+      (when tmpinput (delete-file tmpinput))
+      (when tmpoutput (delete-file tmpoutput))
       ;; Return exit status.
       ret)))
 
--- a/lisp/net/tramp.el	Sat Oct 06 11:55:36 2007 +0000
+++ b/lisp/net/tramp.el	Sat Oct 06 12:00:42 2007 +0000
@@ -149,16 +149,7 @@
        (add-hook 'tramp-unload-hook
 		 '(lambda ()
 		    (when (featurep 'tramp-gw)
-		      (unload-feature 'tramp-gw 'force)))))
-
-     ;; tramp-util offers integration into other (X)Emacs packages like
-     ;; compile.el, gud.el etc.  Not necessary in Emacs 23.
-     (unless (functionp 'start-file-process)
-       (require 'tramp-util)
-       (add-hook 'tramp-unload-hook
-		 '(lambda ()
-		    (when (featurep 'tramp-util)
-		      (unload-feature 'tramp-util 'force)))))))
+		      (unload-feature 'tramp-gw 'force)))))))
 
 ;;; User Customizable Internal Variables:
 
@@ -1974,13 +1965,42 @@
 (put 'tramp-let-maybe 'lisp-indent-function 2)
 (put 'tramp-let-maybe 'edebug-form-spec t)
 
-(defsubst tramp-make-tramp-temp-file (vec)
-  (format
-   "/tmp/%s%s"
-   tramp-temp-name-prefix
-   (if (get-buffer-process (tramp-get-connection-buffer vec))
-       (process-id (get-buffer-process (tramp-get-connection-buffer vec)))
-     (emacs-pid))))
+(defsubst tramp-make-tramp-temp-file (vec &optional dont-create)
+  "Create a temporary file on the remote host identified by VEC.
+Return the local name of the temporary file.
+If DONT-CREATE is non-nil, just the file name is returned without
+creation of the temporary file.  This is not the preferred way to run,
+but it is necessary during connection setup, because we cannot create
+a remote file at this time.  This parameter shall NOT be set to
+non-nil else."
+  (if dont-create
+      ;; It sounds a little bit stupid to create a LOCAL file name.
+      ;; But we intend to use the remote directory "/tmp", and we have
+      ;; no chance to check whether a temporary file exists already
+      ;; remotely, because we have no working connection yet.
+      (make-temp-name (expand-file-name tramp-temp-name-prefix "/tmp"))
+
+    (let ((prefix
+	   (tramp-make-tramp-file-name
+	    (tramp-file-name-method vec)
+	    (tramp-file-name-user vec)
+	    (tramp-file-name-host vec)
+	    (expand-file-name tramp-temp-name-prefix "/tmp")))
+	  result)
+      (while (not result)
+	;; `make-temp-file' would be the first choice for
+	;; implementation.  But it calls `write-region' internally,
+	;; which also needs a temporary file - we would end in an
+	;; infinite loop.
+	(setq result (make-temp-name prefix))
+	(if (file-exists-p result)
+	    (setq result nil)
+	  ;; This creates the file by side effect.
+	  (set-file-times result)
+	  (set-file-modes result (tramp-octal-to-decimal "0700"))))
+
+      ;; Return the local part.
+      (with-parsed-tramp-file-name result nil localname))))
 
 
 ;;; Config Manipulation Functions:
@@ -3188,7 +3208,7 @@
 
       ;; Compose copy command.
       (setq spec `((?h . ,host) (?u . ,user) (?p . ,port)
-		   (?t . ,(tramp-make-tramp-temp-file v))
+		   (?t . ,(tramp-make-tramp-temp-file v 'dont-create))
 		   (?k . ,(if keep-date " " "")))
 	    copy-program (tramp-get-method-parameter
 			  method 'tramp-copy-program)
@@ -3639,8 +3659,7 @@
     (error "Implementation does not handle immediate return"))
 
   (with-parsed-tramp-file-name default-directory nil
-    (let ((temp-name-prefix (tramp-make-tramp-temp-file v))
-	  command input stderr outbuf ret)
+    (let (command input tmpinput stderr tmpstderr outbuf ret)
       ;; Compute command.
       (setq command (mapconcat 'tramp-shell-quote-argument
 			       (cons program args) " "))
@@ -3652,11 +3671,9 @@
 	    ;; INFILE is on the same remote host.
 	    (setq input (with-parsed-tramp-file-name infile nil localname))
 	  ;; INFILE must be copied to remote host.
-	  (setq input (concat temp-name-prefix ".in"))
-	  (copy-file
-	   infile
-	   (tramp-make-tramp-file-name method user host input)
-	   t)))
+	  (setq input (tramp-make-tramp-temp-file v)
+		tmpinput (tramp-make-tramp-file-name method user host input))
+	  (copy-file infile tmpinput t)))
       (when input (setq command (format "%s <%s" command input)))
 
       ;; Determine output.
@@ -3685,7 +3702,9 @@
 			       (cadr destination) nil localname))
 	    ;; stderr must be copied to remote host.  The temporary
 	    ;; file must be deleted after execution.
-	    (setq stderr (concat temp-name-prefix ".err"))))
+	    (setq stderr (tramp-make-tramp-temp-file v)
+		  tmpstderr (tramp-make-tramp-file-name
+			     method user host stderr))))
 	 ;; stderr to be discarded
 	 ((null (cadr destination))
 	  (setq stderr "/dev/null"))))
@@ -3694,9 +3713,6 @@
 	(setq outbuf (current-buffer))))
       (when stderr (setq command (format "%s 2>%s" command stderr)))
 
-      ;; If we have a temporary file, it must be removed after operation.
-      (when (and input (string-match temp-name-prefix input))
-	(setq command (format "%s; rm %s" command input)))
       ;; Goto working directory.
       (tramp-send-command
        v (format "cd %s" (tramp-shell-quote-argument localname)))
@@ -3716,13 +3732,13 @@
 	(error
 	 (kill-buffer (tramp-get-connection-buffer v))
 	 (setq ret 1)))
-      (unless ret
-	;; Check return code.
-	(setq ret (tramp-send-command-and-check v nil))
-	;; Provide error file.
-	(when (and stderr (string-match temp-name-prefix stderr))
-	  (rename-file (tramp-make-tramp-file-name method user host stderr)
-		       (cadr destination) t)))
+
+      ;; Check return code.
+      (unless ret (setq ret (tramp-send-command-and-check v nil)))
+      ;; Provide error file.
+      (when tmpstderr (rename-file tmpstderr (cadr destination) t))
+      ;; Cleanup.
+      (when tmpinput (delete-file tmpinput))
       ;; Return exit status.
       ret)))
 
@@ -4555,7 +4571,15 @@
      (add-hook 'tramp-unload-hook
 	       '(lambda () (ad-unadvise 'PC-expand-many-files)))))
 
-;;; File name handler functions for completion mode
+;;; File name handler functions for completion mode.
+
+(defvar tramp-completion-mode nil
+  "If non-nil, external packages signal that they are in file name completion.
+
+This is necessary, because Tramp uses a heuristic depending on last
+input event.  This fails when external packages use other characters
+but <TAB>, <SPACE> or ?\\? for file name completion.  This variable
+should never be set globally, the intention is to let-bind it.")
 
 ;; Necessary because `tramp-file-name-regexp-unified' and
 ;; `tramp-completion-file-name-regexp-unified' aren't different.  If
@@ -4571,23 +4595,25 @@
 (defun tramp-completion-mode-p ()
   "Checks whether method / user name / host name completion is active."
   (or
-   ;; Emacs
+   ;; Signal from outside.
+   tramp-completion-mode
+   ;; Emacs.
    (equal last-input-event 'tab)
    (and (natnump last-input-event)
 	(or
-	 ;; ?\t has event-modifier 'control
+	 ;; ?\t has event-modifier 'control.
 	 (char-equal last-input-event ?\t)
 	 (and (not (event-modifiers last-input-event))
 	      (or (char-equal last-input-event ?\?)
 		  (char-equal last-input-event ?\ )))))
-   ;; XEmacs
+   ;; XEmacs.
    (and (featurep 'xemacs)
 	;; `last-input-event' might be nil.
 	(not (null last-input-event))
 	;; `last-input-event' may have no character approximation.
 	(funcall (symbol-function 'event-to-character) last-input-event)
 	(or
-	 ;; ?\t has event-modifier 'control
+	 ;; ?\t has event-modifier 'control.
 	 (char-equal
 	  (funcall (symbol-function 'event-to-character)
 		   last-input-event) ?\t)
@@ -6151,7 +6177,7 @@
 	     l-user (or l-user "")
 	     l-port (or l-port "")
 	     spec `((?h . ,l-host) (?u . ,l-user) (?p . ,l-port)
-		    (?t . ,(tramp-make-tramp-temp-file vec)))
+		    (?t . ,(tramp-make-tramp-temp-file vec 'dont-create)))
 	     command
 	     (concat
 	      command " "
@@ -7468,18 +7494,6 @@
 
 (provide 'tramp)
 
-;; Make sure that we get integration with the VC package.
-;; When it is loaded, we need to pull in the integration module.
-;; This must come after (provide 'tramp) because tramp-vc.el
-;; requires tramp.  Not necessary in Emacs 23.
-(eval-after-load "vc"
-  '(unless (functionp 'start-file-process)
-     (require 'tramp-vc)
-     (add-hook 'tramp-unload-hook
-	       '(lambda ()
-		  (when (featurep 'tramp-vc)
-		    (unload-feature 'tramp-vc 'force))))))
-
 ;;; TODO:
 
 ;; * Allow putting passwords in the filename.