summaryrefslogtreecommitdiff
path: root/lisp/net
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/net')
-rw-r--r--lisp/net/ange-ftp.el31
-rw-r--r--lisp/net/browse-url.el51
-rw-r--r--lisp/net/eudc-bob.el1
-rw-r--r--lisp/net/eudc-export.el1
-rw-r--r--lisp/net/eudc-hotlist.el1
-rw-r--r--lisp/net/eudc-vars.el1
-rw-r--r--lisp/net/eudc.el1
-rw-r--r--lisp/net/eudcb-bbdb.el1
-rw-r--r--lisp/net/eudcb-ldap.el1
-rw-r--r--lisp/net/eudcb-ph.el1
-rw-r--r--lisp/net/goto-addr.el1
-rw-r--r--lisp/net/ldap.el26
-rw-r--r--lisp/net/net-utils.el1
-rw-r--r--lisp/net/netrc.el1
-rw-r--r--lisp/net/quickurl.el1
-rw-r--r--lisp/net/rcompile.el1
-rw-r--r--lisp/net/rlogin.el3
-rw-r--r--lisp/net/snmp-mode.el1
-rw-r--r--lisp/net/telnet.el3
-rw-r--r--lisp/net/tls.el1
-rw-r--r--lisp/net/tramp-ftp.el20
-rw-r--r--lisp/net/tramp-smb.el162
-rw-r--r--lisp/net/tramp-util.el2
-rw-r--r--lisp/net/tramp-uu.el2
-rw-r--r--lisp/net/tramp-vc.el12
-rw-r--r--lisp/net/tramp.el925
-rw-r--r--lisp/net/trampver.el3
-rw-r--r--lisp/net/webjump.el6
-rw-r--r--lisp/net/zone-mode.el3
29 files changed, 794 insertions, 470 deletions
diff --git a/lisp/net/ange-ftp.el b/lisp/net/ange-ftp.el
index a315482fd1e..8e1068a5bed 100644
--- a/lisp/net/ange-ftp.el
+++ b/lisp/net/ange-ftp.el
@@ -686,7 +686,7 @@
:prefix "ange-ftp-")
(defcustom ange-ftp-name-format
- '("^/\\(\\([^@/:]*\\)@\\)?\\([^@/:]*[^@/:.]\\):\\(.*\\)" . (3 2 4))
+ '("^/\\(\\([^/:]*\\)@\\)?\\([^@/:]*[^@/:.]\\):\\(.*\\)" . (3 2 4))
"*Format of a fully expanded remote file name.
This is a list of the form \(REGEXP HOST USER NAME\),
@@ -694,7 +694,7 @@ where REGEXP is a regular expression matching
the full remote name, and HOST, USER, and NAME are the numbers of
parenthesized expressions in REGEXP for the components (in that order)."
:group 'ange-ftp
- :type '(list regexp
+ :type '(list (regexp :tag "Name regexp")
(integer :tag "Host group")
(integer :tag "User group")
(integer :tag "Name group")))
@@ -1469,14 +1469,15 @@ only return the directory part of FILE."
;; Display the last chunk of output from the ftp process for the given HOST
;; USER pair, and signal an error including MSG in the text.
(defun ange-ftp-error (host user msg)
- (let ((cur (selected-window))
- (pop-up-windows t))
- (pop-to-buffer
- (get-buffer-create
- (ange-ftp-ftp-process-buffer host user)))
- (goto-char (point-max))
- (select-window cur))
- (signal 'ftp-error (list (format "FTP Error: %s" msg))))
+ (save-excursion ;; Prevent pop-to-buffer from changing current buffer.
+ (let ((cur (selected-window))
+ (pop-up-windows t))
+ (pop-to-buffer
+ (get-buffer-create
+ (ange-ftp-ftp-process-buffer host user)))
+ (goto-char (point-max))
+ (select-window cur))
+ (signal 'ftp-error (list (format "FTP Error: %s" msg)))))
(defun ange-ftp-set-buffer-mode ()
"Set correct modes for the current buffer if visiting a remote file."
@@ -1917,7 +1918,8 @@ on the gateway machine to do the ftp instead."
;; but that doesn't work: ftp never responds.
;; Can anyone find a fix for that?
(let ((process-connection-type t)
- (process-environment process-environment)
+ ;; Copy this so we don't alter it permanently.
+ (process-environment (copy-tree process-environment))
(buffer (get-buffer-create name)))
(save-excursion
(set-buffer buffer)
@@ -3433,7 +3435,7 @@ system TYPE.")
(nreverse files)))
(apply 'ange-ftp-real-directory-files directory full match v19-args)))
-(defun ange-ftp-file-attributes (file)
+(defun ange-ftp-file-attributes (file &optional id-format)
(setq file (expand-file-name file))
(let ((parsed (ange-ftp-ftp-name file)))
(if parsed
@@ -3466,7 +3468,9 @@ system TYPE.")
inode ;10 "inode number".
-1 ;11 device number [v19 only]
))))
- (ange-ftp-real-file-attributes file))))
+ (if id-format
+ (ange-ftp-real-file-attributes file id-format)
+ (ange-ftp-real-file-attributes file)))))
(defun ange-ftp-file-newer-than-file-p (f1 f2)
(let ((f1-parsed (ange-ftp-ftp-name f1))
@@ -6048,4 +6052,5 @@ be recognized automatically (they are all valid BS2000 hosts too)."
(provide 'ange-ftp)
+;;; arch-tag: 2987ef88-cb56-4ec1-87a9-79132572e316
;;; ange-ftp.el ends here
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el
index b97eda6472b..a70e08028d2 100644
--- a/lisp/net/browse-url.el
+++ b/lisp/net/browse-url.el
@@ -1,6 +1,6 @@
;;; browse-url.el --- pass a URL to a WWW browser
-;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001
+;; Copyright (C) 1995, 96, 97, 98, 99, 2000, 2001, 2004
;; Free Software Foundation, Inc.
;; Author: Denis Howe <dbh@doc.ic.ac.uk>
@@ -818,8 +818,8 @@ When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
(interactive (browse-url-interactive-arg "URL: "))
;; URL encode any `confusing' characters in the URL. This needs to
- ;; include at least commas; presumably also close parens.
- (while (string-match "[,)]" url)
+ ;; include at least commas; presumably also close parens and dollars.
+ (while (string-match "[,)$]" url)
(setq url (replace-match
(format "%%%x" (string-to-char (match-string 0 url))) t t url)))
(let* ((process-environment (browse-url-process-environment))
@@ -889,8 +889,8 @@ When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
(interactive (browse-url-interactive-arg "URL: "))
;; URL encode any `confusing' characters in the URL. This needs to
- ;; include at least commas; presumably also close parens.
- (while (string-match "[,)]" url)
+ ;; include at least commas; presumably also close parens and dollars.
+ (while (string-match "[,)$]" url)
(setq url (replace-match
(format "%%%x" (string-to-char (match-string 0 url))) t t url)))
(let* ((process-environment (browse-url-process-environment))
@@ -942,8 +942,8 @@ When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
(interactive (browse-url-interactive-arg "URL: "))
;; URL encode any `confusing' characters in the URL. This needs to
- ;; include at least commas; presumably also close parens.
- (while (string-match "[,)]" url)
+ ;; include at least commas; presumably also close parens and dollars.
+ (while (string-match "[,)$]" url)
(setq url (replace-match
(format "%%%x" (string-to-char (match-string 0 url))) t t url)))
(let* ((process-environment (browse-url-process-environment))
@@ -991,8 +991,8 @@ When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
(interactive (browse-url-interactive-arg "URL: "))
;; URL encode any `confusing' characters in the URL. This needs to
- ;; include at least commas; presumably also close parens.
- (while (string-match "[,)]" url)
+ ;; include at least commas; presumably also close parens and dollars.
+ (while (string-match "[,)$]" url)
(setq url (replace-match
(format "%%%x" (string-to-char (match-string 0 url))) t t url)))
(let* ((process-environment (browse-url-process-environment))
@@ -1301,9 +1301,11 @@ Default to the URL around or before point."
;; --- mailto ---
+(autoload 'rfc2368-parse-mailto-url "rfc2368")
+
;;;###autoload
(defun browse-url-mail (url &optional new-window)
- "Open a new mail message buffer within Emacs.
+ "Open a new mail message buffer within Emacs for the RFC 2368 URL.
Default to using the mailto: URL around or before point as the
recipient's address. Supplying a non-nil interactive prefix argument
will cause the mail to be composed in another window rather than the
@@ -1318,14 +1320,24 @@ When called non-interactively, optional second argument NEW-WINDOW is
used instead of `browse-url-new-window-flag'."
(interactive (browse-url-interactive-arg "Mailto URL: "))
(save-excursion
- (let ((to (if (string-match "^mailto:" url)
- (substring url 7)
- url)))
+ (let* ((alist (rfc2368-parse-mailto-url url))
+ (to (assoc "To" alist))
+ (subject (assoc "Subject" alist))
+ (body (assoc "Body" alist))
+ (rest (delete to (delete subject (delete body alist))))
+ (to (cdr to))
+ (subject (cdr subject))
+ (body (cdr body))
+ (mail-citation-hook (unless body mail-citation-hook)))
(if (browse-url-maybe-new-window new-window)
- (compose-mail-other-window to nil nil nil
- (list 'insert-buffer (current-buffer)))
- (compose-mail to nil nil nil nil
- (list 'insert-buffer (current-buffer)))))))
+ (compose-mail-other-window to subject rest nil
+ (if body
+ (list 'insert body)
+ (list 'insert-buffer (current-buffer))))
+ (compose-mail to subject rest nil nil
+ (if body
+ (list 'insert body)
+ (list 'insert-buffer (current-buffer))))))))
;; --- Random browser ---
@@ -1340,8 +1352,8 @@ don't offer a form of remote control."
(interactive (browse-url-interactive-arg "URL: "))
(if (not browse-url-generic-program)
(error "No browser defined (`browse-url-generic-program')"))
- (apply 'start-process (concat browse-url-generic-program url) nil
- browse-url-generic-program
+ (apply 'call-process browse-url-generic-program nil
+ 0 nil
(append browse-url-generic-args (list url))))
;;;###autoload
@@ -1355,4 +1367,5 @@ Default to the URL around or before point."
(provide 'browse-url)
+;;; arch-tag: d2079573-5c06-4097-9598-f550fba19430
;;; browse-url.el ends here
diff --git a/lisp/net/eudc-bob.el b/lisp/net/eudc-bob.el
index 78593fe5c19..df20007cfb7 100644
--- a/lisp/net/eudc-bob.el
+++ b/lisp/net/eudc-bob.el
@@ -365,4 +365,5 @@ display a button."
"Display a button for the JPEG DATA."
(eudc-bob-display-jpeg data nil))
+;;; arch-tag: 8f1853df-c9b6-4c5a-bdb1-d94dbd651fb3
;;; eudc-bob.el ends here
diff --git a/lisp/net/eudc-export.el b/lisp/net/eudc-export.el
index 9bd3ad7ca7e..704792f6b68 100644
--- a/lisp/net/eudc-export.el
+++ b/lisp/net/eudc-export.el
@@ -215,4 +215,5 @@ This function can only be called from a directory query result buffer."
(overlay-get (car (overlays-at (point))) 'eudc-record)
(eudc-insert-record-at-point-into-bbdb)))
+;;; arch-tag: 8cbda7dc-3163-47e6-921c-6ec5083df2d7
;;; eudc-export.el ends here
diff --git a/lisp/net/eudc-hotlist.el b/lisp/net/eudc-hotlist.el
index c03cf0219f8..9dc81ce2bc9 100644
--- a/lisp/net/eudc-hotlist.el
+++ b/lisp/net/eudc-hotlist.el
@@ -194,4 +194,5 @@ These are the special commands of this mode:
""
eudc-hotlist-menu))
+;;; arch-tag: 9b633ab3-6a6e-4b46-b12e-d96739a7e0e8
;;; eudc-hotlist.el ends here
diff --git a/lisp/net/eudc-vars.el b/lisp/net/eudc-vars.el
index b44f7f74607..1b9da92da67 100644
--- a/lisp/net/eudc-vars.el
+++ b/lisp/net/eudc-vars.el
@@ -406,4 +406,5 @@ Otherwise records must match queries exactly."
(provide 'eudc-vars)
+;;; arch-tag: 80050575-b838-4246-8ebc-b2d7c5a2e482
;;; eudc-vars.el ends here
diff --git a/lisp/net/eudc.el b/lisp/net/eudc.el
index 9d3e4aa9d34..6d12d5e6364 100644
--- a/lisp/net/eudc.el
+++ b/lisp/net/eudc.el
@@ -1284,4 +1284,5 @@ This does nothing except loading eudc by autoload side-effect."
(provide 'eudc)
+;;; arch-tag: e18872b6-db83-400b-869d-be54e9a4160c
;;; eudc.el ends here
diff --git a/lisp/net/eudcb-bbdb.el b/lisp/net/eudcb-bbdb.el
index 1c20c7cc185..745d6e289a1 100644
--- a/lisp/net/eudcb-bbdb.el
+++ b/lisp/net/eudcb-bbdb.el
@@ -231,4 +231,5 @@ RETURN-ATTRS is a list of attributes to return, defaulting to
(provide 'eudcb-bbdb)
+;;; arch-tag: 38276208-75de-4dbc-ba6f-8db684c32e0a
;;; eudcb-bbdb.el ends here
diff --git a/lisp/net/eudcb-ldap.el b/lisp/net/eudcb-ldap.el
index fb97bc754e7..a206578b774 100644
--- a/lisp/net/eudcb-ldap.el
+++ b/lisp/net/eudcb-ldap.el
@@ -208,4 +208,5 @@ attribute names are returned. Default to `person'"
(provide 'eudcb-ldap)
+;;; arch-tag: 0f254dc0-7378-4fd4-ae26-18666184e96b
;;; eudcb-ldap.el ends here
diff --git a/lisp/net/eudcb-ph.el b/lisp/net/eudcb-ph.el
index 68d03979f48..efd89beaaa9 100644
--- a/lisp/net/eudcb-ph.el
+++ b/lisp/net/eudcb-ph.el
@@ -244,4 +244,5 @@ depending on RETURN-RESPONSE."
(provide 'eudcb-ph)
+;;; arch-tag: 4365bbf5-af20-453e-b5b6-2e7118ebfcdb
;;; eudcb-ph.el ends here
diff --git a/lisp/net/goto-addr.el b/lisp/net/goto-addr.el
index 1449c9bcc38..b77be84deb3 100644
--- a/lisp/net/goto-addr.el
+++ b/lisp/net/goto-addr.el
@@ -248,4 +248,5 @@ Also fontifies the buffer appropriately (see `goto-address-fontify-p' and
(provide 'goto-addr)
+;;; arch-tag: ca47c505-5661-425d-a471-62bc6e75cf0a
;;; goto-addr.el ends here
diff --git a/lisp/net/ldap.el b/lisp/net/ldap.el
index d539164e9f9..55af47e6a87 100644
--- a/lisp/net/ldap.el
+++ b/lisp/net/ldap.el
@@ -1,6 +1,6 @@
;;; ldap.el --- client interface to LDAP for Emacs
-;; Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 02, 2004 Free Software Foundation, Inc.
;; Author: Oscar Figueiredo <oscar@cpe.fr>
;; Maintainer: Pavel Janík <Pavel@Janik.cz>
@@ -36,6 +36,7 @@
;;; Code:
(require 'custom)
+(eval-when-compile (require 'cl))
(defgroup ldap nil
"Lightweight Directory Access Protocol."
@@ -464,17 +465,16 @@ Additional search parameters can be specified through
(error "No LDAP host specified"))
(let ((host-plist (cdr (assoc host ldap-host-parameters-alist)))
result)
- (setq result (ldap-search-internal (append host-plist
- (list 'host host
- 'filter filter
- 'attributes attributes
- 'attrsonly attrsonly
- 'withdn withdn))))
+ (setq result (ldap-search-internal (list* 'host host
+ 'filter filter
+ 'attributes attributes
+ 'attrsonly attrsonly
+ 'withdn withdn
+ host-plist)))
(if ldap-ignore-attribute-codings
result
- (mapcar (function
- (lambda (record)
- (mapcar 'ldap-decode-attribute record)))
+ (mapcar (lambda (record)
+ (mapcar 'ldap-decode-attribute record))
result))))
@@ -582,6 +582,11 @@ an alist of attribute/value pairs."
(while (looking-at "^\\(\\w*\\)[=:\t ]+\\(<[\t ]*file://\\)?\\(.*\\)$")
(setq name (match-string 1)
value (match-string 3))
+ ;; Need to handle file:///D:/... as generated by OpenLDAP
+ ;; on DOS/Windows as local files.
+ (if (and (memq system-type '(windows-nt ms-dos))
+ (eq (string-match "/\\(.:.*\\)$" value) 0))
+ (setq value (match-string 1 value)))
;; Do not try to open non-existent files
(if (equal value "")
(setq value " ")
@@ -607,4 +612,5 @@ an alist of attribute/value pairs."
(provide 'ldap)
+;;; arch-tag: 47913a76-6155-42e6-ac58-6d28b5d50eb0
;;; ldap.el ends here
diff --git a/lisp/net/net-utils.el b/lisp/net/net-utils.el
index 982923ed559..202dac361e7 100644
--- a/lisp/net/net-utils.el
+++ b/lisp/net/net-utils.el
@@ -828,4 +828,5 @@ from SEARCH-STRING. With argument, prompt for whois server."
(provide 'net-utils)
+;;; arch-tag: 97119e91-9edb-4376-838b-bf7058fa1314
;;; net-utils.el ends here
diff --git a/lisp/net/netrc.el b/lisp/net/netrc.el
index 8062b4292dc..713c036ce7b 100644
--- a/lisp/net/netrc.el
+++ b/lisp/net/netrc.el
@@ -125,4 +125,5 @@ Entries without port tokens default to DEFAULTPORT."
(provide 'netrc)
+;;; arch-tag: af9929cc-2d12-482f-936e-eb4366f9fa55
;;; netrc.el ends here
diff --git a/lisp/net/quickurl.el b/lisp/net/quickurl.el
index 22794a41078..fd13b3a0f51 100644
--- a/lisp/net/quickurl.el
+++ b/lisp/net/quickurl.el
@@ -549,4 +549,5 @@ TYPE dictates what will be inserted, options are:
(provide 'quickurl)
+;;; arch-tag: a8183ea5-80c2-4082-a7d1-b0fdf2da467e
;;; quickurl.el ends here
diff --git a/lisp/net/rcompile.el b/lisp/net/rcompile.el
index 8105593c758..c9078ac2d76 100644
--- a/lisp/net/rcompile.el
+++ b/lisp/net/rcompile.el
@@ -175,4 +175,5 @@ See \\[compile]."
(set (make-local-variable 'comint-file-name-prefix)
(concat "/" host ":")))))
+;;; arch-tag: 2866a132-ece4-4ce9-9f91-ec147f803f73
;;; rcompile.el ends here
diff --git a/lisp/net/rlogin.el b/lisp/net/rlogin.el
index cc2defdf166..fa7e0d1950e 100644
--- a/lisp/net/rlogin.el
+++ b/lisp/net/rlogin.el
@@ -6,8 +6,6 @@
;; Maintainer: Noah Friedman <friedman@splode.com>
;; Keywords: unix, comm
-;; $Id: rlogin.el,v 1.3 2002/03/14 11:51:47 miles Exp $
-
;; This file is part of GNU Emacs.
;; GNU Emacs is free software; you can redistribute it and/or modify
@@ -329,4 +327,5 @@ Delete ARG characters forward, or send a C-d to process if at end of buffer."
(provide 'rlogin)
+;;; arch-tag: 6e20eabf-feda-40fa-ab40-0d156db447e4
;;; rlogin.el ends here
diff --git a/lisp/net/snmp-mode.el b/lisp/net/snmp-mode.el
index cde6fb7c60d..7fed47f6bf8 100644
--- a/lisp/net/snmp-mode.el
+++ b/lisp/net/snmp-mode.el
@@ -720,4 +720,5 @@ controls whether case is significant."
(provide 'snmp-mode)
+;;; arch-tag: eb6cc0f9-1e47-4023-8625-bc9aae6c3527
;;; snmp-mode.el ends here
diff --git a/lisp/net/telnet.el b/lisp/net/telnet.el
index b75ff47220d..dac6f228cd6 100644
--- a/lisp/net/telnet.el
+++ b/lisp/net/telnet.el
@@ -89,8 +89,8 @@ Should be set to the number of terminal writes telnet will make
rejecting one login and prompting again for a username and password.")
(defun telnet-interrupt-subjob ()
- (interactive)
"Interrupt the program running through telnet on the remote host."
+ (interactive)
(send-string nil telnet-interrupt-string))
(defun telnet-c-z ()
@@ -262,4 +262,5 @@ Normally input is edited in Emacs and sent a line at a time."
(provide 'telnet)
+;;; arch-tag: 98218821-d04a-48b6-9058-57d0d4677a56
;;; telnet.el ends here
diff --git a/lisp/net/tls.el b/lisp/net/tls.el
index 70270773a3c..dd161032d9a 100644
--- a/lisp/net/tls.el
+++ b/lisp/net/tls.el
@@ -124,4 +124,5 @@ specifying a port number to connect to."
(provide 'tls)
+;;; arch-tag: 5596d1c4-facc-4bc4-94a9-9863b928d7ac
;;; tls.el ends here
diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el
index 07a756c3523..3be891a49f8 100644
--- a/lisp/net/tramp-ftp.el
+++ b/lisp/net/tramp-ftp.el
@@ -1,6 +1,6 @@
;;; tramp-ftp.el --- Tramp convenience functions for Ange-FTP and EFS -*- coding: iso-8859-1; -*-
-;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Michael Albinus <Michael.Albinus@alcatel.de>
;; Keywords: comm, processes
@@ -24,8 +24,8 @@
;;; Commentary:
-;; Convenience functions for calling Ange-FTP (and maybe EFS, later on)
-;; from Tramp. Most of them are displaced from tramp.el.
+;; Convenience functions for calling Ange-FTP from Tramp.
+;; Most of them are displaced from tramp.el.
;;; Code:
@@ -98,9 +98,16 @@ pass to the OPERATION."
(list (nth 0 tramp-file-name-structure)
(nth 3 tramp-file-name-structure)
(nth 2 tramp-file-name-structure)
- (nth 4 tramp-file-name-structure))))
+ (nth 4 tramp-file-name-structure)))
+ ;; ange-ftp uses `ange-ftp-ftp-name-arg' and `ange-ftp-ftp-name-res'
+ ;; for optimization in `ange-ftp-ftp-name'. If Tramp wasn't active,
+ ;; there could be incorrect values from previous calls in case the
+ ;; "ftp" method is used in the Tramp file name. So we unset
+ ;; those values.
+ (ange-ftp-ftp-name-arg "")
+ (ange-ftp-ftp-name-res nil))
(cond
- ;; If argument is a symlink, 'file-directory-p` and 'file-exists-p`
+ ;; If argument is a symlink, `file-directory-p' and `file-exists-p'
;; call the traversed file recursively. So we cannot disable the
;; file-name-handler this case.
((memq operation '(file-directory-p file-exists-p))
@@ -137,5 +144,8 @@ pass to the OPERATION."
;; pretended in `tramp-file-name-handler' otherwise.
;; Furthermore, there are no backup files on FTP hosts.
;; Worth further investigations.
+;; * Map /multi:ssh:out@gate:ftp:kai@real.host:/path/to.file
+;; on Ange-FTP gateways.
+;;; arch-tag: 759fb338-5c63-4b99-bd36-b4d59db91cff
;;; tramp-ftp.el ends here
diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el
index 8474b7a88a3..ab6ad3310c1 100644
--- a/lisp/net/tramp-smb.el
+++ b/lisp/net/tramp-smb.el
@@ -1,6 +1,6 @@
;;; tramp-smb.el --- Tramp access functions for SMB servers -*- coding: iso-8859-1; -*-
-;; Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: Michael Albinus <Michael.Albinus@alcatel.de>
;; Keywords: comm, processes
@@ -50,7 +50,7 @@
;; Add a default for `tramp-default-method-alist'. Rule: If there is
;; a domain in USER, it must be the SMB method.
(add-to-list 'tramp-default-method-alist
- (list "%" "" tramp-smb-method))
+ (list "" "%" tramp-smb-method))
;; Add completion function for SMB method.
(tramp-set-completion-function
@@ -62,7 +62,7 @@
:group 'tramp
:type 'string)
-(defconst tramp-smb-prompt "^smb: \\S-+> "
+(defconst tramp-smb-prompt "^smb: \\S-+> \\|^\\s-+Server\\s-+Comment$"
"Regexp used as prompt in smbclient.")
(defconst tramp-smb-errors
@@ -71,8 +71,8 @@
'(; Connection error
"Connection to \\S-+ failed"
; Samba
- "ERRSRV"
"ERRDOS"
+ "ERRSRV"
"ERRbadfile"
"ERRbadpw"
"ERRfilexists"
@@ -81,13 +81,16 @@
"ERRnosuchshare"
; Windows NT 4.0, Windows 5.0 (Windows 2000), Windows 5.1 (Windows XP)
"NT_STATUS_ACCESS_DENIED"
+ "NT_STATUS_ACCOUNT_LOCKED_OUT"
"NT_STATUS_BAD_NETWORK_NAME"
"NT_STATUS_CANNOT_DELETE"
"NT_STATUS_LOGON_FAILURE"
+ "NT_STATUS_NETWORK_ACCESS_DENIED"
"NT_STATUS_NO_SUCH_FILE"
"NT_STATUS_OBJECT_NAME_INVALID"
"NT_STATUS_OBJECT_NAME_NOT_FOUND"
- "NT_STATUS_SHARING_VIOLATION")
+ "NT_STATUS_SHARING_VIOLATION"
+ "NT_STATUS_WRONG_PASSWORD")
"\\|")
"Regexp for possible error strings of SMB servers.
Used instead of analyzing error codes of commands.")
@@ -102,12 +105,6 @@ This variable is local to each buffer.")
This variable is local to each buffer.")
(make-variable-buffer-local 'tramp-smb-share-cache)
-(defvar tramp-smb-process-running nil
- "Flag whether a corresponding process is still running.
-Will be changed by corresponding `process-sentinel'.
-This variable is local to each buffer.")
-(make-variable-buffer-local 'tramp-smb-process-running)
-
(defvar tramp-smb-inodes nil
"Keeps virtual inodes numbers for SMB files.")
@@ -290,7 +287,7 @@ KEEP-DATE is not handled in case NEWNAME resides on an SMB server."
(tramp-smb-send-command user host (format "cd \\"))
;; Error
(tramp-smb-send-command user host (format "cd \\"))
- (error "Cannot delete file `%s'" directory))))))
+ (error "Cannot delete file `%s'" filename))))))
(defun tramp-smb-handle-directory-files
(directory &optional full match nosort)
@@ -324,18 +321,18 @@ KEEP-DATE is not handled in case NEWNAME resides on an SMB server."
entries))))
(defun tramp-smb-handle-directory-files-and-attributes
- (directory &optional full match nosort)
+ (directory &optional full match nosort id-format)
"Like `directory-files-and-attributes' for tramp files."
(mapcar
(lambda (x)
- (cons x (file-attributes
- (if full x (concat (file-name-as-directory directory) x)))))
+ ;; We cannot call `file-attributes' for backward compatibility reasons.
+ ;; Its optional parameter ID-FORMAT is introduced with Emacs 21.4.
+ (cons x (tramp-smb-handle-file-attributes
+ (if full x (concat (file-name-as-directory directory) x)) id-format)))
(directory-files directory full match nosort)))
-(defun tramp-smb-handle-file-attributes (filename &optional nonnumeric)
- "Like `file-attributes' for tramp files.
-Optional argument NONNUMERIC means return user and group name
-rather than as numbers."
+(defun tramp-smb-handle-file-attributes (filename &optional id-format)
+ "Like `file-attributes' for tramp files."
; (with-parsed-tramp-file-name filename nil
(let (user host localname)
(with-parsed-tramp-file-name filename l
@@ -346,6 +343,8 @@ rather than as numbers."
(entries (tramp-smb-get-file-entries user host share file))
(entry (and entries
(assoc (file-name-nondirectory file) entries)))
+ (uid (if (and id-format (equal id-format 'string)) "nobody" -1))
+ (gid (if (and id-format (equal id-format 'string)) "nogroup" -1))
(inode (tramp-smb-get-inode share file))
(device (tramp-get-device nil tramp-smb-method user host)))
@@ -354,8 +353,8 @@ rather than as numbers."
(list (and (string-match "d" (nth 1 entry))
t) ;0 file type
-1 ;1 link count
- -1 ;2 uid
- -1 ;3 gid
+ uid ;2 uid
+ gid ;3 gid
'(0 0) ;4 atime
(nth 3 entry) ;5 mtime
'(0 0) ;6 ctime
@@ -450,19 +449,23 @@ rather than as numbers."
(defun tramp-smb-handle-file-writable-p (filename)
"Like `file-writable-p' for tramp files."
-; (with-parsed-tramp-file-name filename nil
- (let (user host localname)
- (with-parsed-tramp-file-name filename l
- (setq user l-user host l-host localname l-localname))
- (save-excursion
- (let* ((share (tramp-smb-get-share localname))
- (file (tramp-smb-get-localname localname nil))
- (entries (tramp-smb-get-file-entries user host share file))
- (entry (and entries
- (assoc (file-name-nondirectory file) entries))))
- (and entry
- (string-match "w" (nth 1 entry))
- t)))))
+ (if (not (file-exists-p filename))
+ (let ((dir (file-name-directory filename)))
+ (and (file-exists-p dir)
+ (file-writable-p dir)))
+; (with-parsed-tramp-file-name filename nil
+ (let (user host localname)
+ (with-parsed-tramp-file-name filename l
+ (setq user l-user host l-host localname l-localname))
+ (save-excursion
+ (let* ((share (tramp-smb-get-share localname))
+ (file (tramp-smb-get-localname localname nil))
+ (entries (tramp-smb-get-file-entries user host share file))
+ (entry (and entries
+ (assoc (file-name-nondirectory file) entries))))
+ (and share entry
+ (string-match "w" (nth 1 entry))
+ t))))))
(defun tramp-smb-handle-insert-directory
(filename switches &optional wildcard full-directory-p)
@@ -546,7 +549,7 @@ WILDCARD and FULL-DIRECTORY-P are not handled."
"Like `make-directory-internal' for tramp files."
(setq directory (directory-file-name (expand-file-name directory)))
(unless (file-name-absolute-p directory)
- (setq ldir (concat default-directory directory)))
+ (setq directory (concat default-directory directory)))
; (with-parsed-tramp-file-name directory nil
(let (user host localname)
(with-parsed-tramp-file-name directory l
@@ -731,9 +734,12 @@ Result is a list of (LOCALNAME MODE SIZE MONTH DAY TIME YEAR)."
;; Cache share entries
(setq tramp-smb-share-cache res)))
-
;; Add directory itself
- (add-to-list 'res '("" "dr-xr-xr-x" 0 (0 0)))
+ (add-to-list 'res '("" "drwxrwxrwx" 0 (0 0)))
+
+ ;; There's a very strange error (debugged with XEmacs 21.4.14)
+ ;; If there's no short delay, it returns nil. No idea about
+ (when (featurep 'xemacs) (sleep-for 0.01))
;; Check for matching entries
(delq nil (mapcar
@@ -911,7 +917,8 @@ there has been an error message from smbclient."
"Maybe open a connection to HOST, logging in as USER, using `tramp-smb-program'.
Does not do anything if a connection is already open, but re-opens the
connection if a previous connection has died for some reason."
- (let ((p (get-buffer-process
+ (let ((process-connection-type tramp-process-connection-type)
+ (p (get-buffer-process
(tramp-get-buffer nil tramp-smb-method user host))))
(save-excursion
(set-buffer (tramp-get-buffer nil tramp-smb-method user host))
@@ -985,11 +992,7 @@ Domain names in USER and port numbers in HOST are acknowledged."
(tramp-message 9 "Started process %s" (process-command p))
(process-kill-without-query p)
(set-buffer buffer)
- (set-process-sentinel
- p (lambda (proc str) (setq tramp-smb-process-running nil)))
- ; If no share is given, the process will terminate
- (setq tramp-smb-process-running share
- tramp-smb-share share)
+ (setq tramp-smb-share share)
; send password
(when real-user
@@ -998,54 +1001,44 @@ Domain names in USER and port numbers in HOST are acknowledged."
(tramp-enter-password p pw-prompt)))
(unless (tramp-smb-wait-for-output user host)
+ (tramp-clear-passwd user host)
(error "Cannot open connection //%s@%s/%s"
user host (or share "")))))))
;; We don't use timeouts. If needed, the caller shall wrap around.
(defun tramp-smb-wait-for-output (user host)
"Wait for output from smbclient command.
-Sets position to begin of buffer.
Returns nil if an error message has appeared."
- (save-excursion
- (let ((proc (get-buffer-process (current-buffer)))
- (found (progn (goto-char (point-max))
- (beginning-of-line)
- (looking-at tramp-smb-prompt)))
- err)
- (save-match-data
- ;; Algorithm: get waiting output. See if last line contains
- ;; tramp-smb-prompt sentinel, or process has exited.
- ;; If not, wait a bit and again get waiting output.
- (while (and (not found) tramp-smb-process-running)
- (accept-process-output proc)
- (goto-char (point-max))
- (beginning-of-line)
- (setq found (looking-at tramp-smb-prompt)))
-
- ;; There might be pending output. If tramp-smb-prompt sentinel
- ;; hasn't been found, the process has died already. We should
- ;; give it a chance.
- (when (not found) (accept-process-output nil 1))
-
- ;; Search for errors.
- (goto-char (point-min))
- (setq err (re-search-forward tramp-smb-errors nil t)))
-
- ;; Add output to debug buffer if appropriate.
- (when tramp-debug-buffer
- (append-to-buffer
- (tramp-get-debug-buffer nil tramp-smb-method user host)
- (point-min) (point-max))
- (when (and (not found) tramp-smb-process-running)
- (save-excursion
- (set-buffer
- (tramp-get-debug-buffer nil tramp-smb-method user host))
- (goto-char (point-max))
- (insert (format "[[Remote prompt `%s' not found]]\n"
- tramp-smb-prompt)))))
+ (let ((proc (get-buffer-process (current-buffer)))
+ (found (progn (goto-char (point-min))
+ (re-search-forward tramp-smb-prompt nil t)))
+ (err (progn (goto-char (point-min))
+ (re-search-forward tramp-smb-errors nil t))))
+
+ ;; Algorithm: get waiting output. See if last line contains
+ ;; tramp-smb-prompt sentinel or tramp-smb-errors strings.
+ ;; If not, wait a bit and again get waiting output.
+ (while (and (not found) (not err))
+
+ ;; Accept pending output.
+ (accept-process-output proc)
+
+ ;; Search for prompt.
(goto-char (point-min))
- ;; Return value is whether no error message has appeared.
- (not err))))
+ (setq found (re-search-forward tramp-smb-prompt nil t))
+
+ ;; Search for errors.
+ (goto-char (point-min))
+ (setq err (re-search-forward tramp-smb-errors nil t)))
+
+ ;; Add output to debug buffer if appropriate.
+ (when tramp-debug-buffer
+ (append-to-buffer
+ (tramp-get-debug-buffer nil tramp-smb-method user host)
+ (point-min) (point-max)))
+
+ ;; Return value is whether no error message has appeared.
+ (not err)))
;; Snarfed code from time-date.el and parse-time.el
@@ -1123,8 +1116,6 @@ Return the difference in the format of a time value."
;; * Provide a local smb.conf. The default one might not be readable.
;; * Error handling in case password is wrong.
;; * Read password from "~/.netrc".
-;; * Use different buffers for different shares. By this, the password
-;; won't be requested again when changing shares on the same host.
;; * Return more comprehensive file permission string. Think whether it is
;; possible to implement `set-file-modes'.
;; * Handle WILDCARD and FULL-DIRECTORY-P in
@@ -1139,4 +1130,5 @@ Return the difference in the format of a time value."
;; * (RMS) Use unwind-protect to clean up the state so as to make the state
;; regular again.
+;;; arch-tag: fcc9dbec-7503-4d73-b638-3c8aa59575f5
;;; tramp-smb.el ends here
diff --git a/lisp/net/tramp-util.el b/lisp/net/tramp-util.el
index 44a24ca3ab7..2d828d27c51 100644
--- a/lisp/net/tramp-util.el
+++ b/lisp/net/tramp-util.el
@@ -52,4 +52,6 @@
(compilation-minor-mode 1))
(provide 'tramp-util)
+
+;;; arch-tag: 500f9992-a44e-46d0-83a7-980799251808
;;; tramp-util.el ends here
diff --git a/lisp/net/tramp-uu.el b/lisp/net/tramp-uu.el
index e307febc6fc..1047e62a3cb 100644
--- a/lisp/net/tramp-uu.el
+++ b/lisp/net/tramp-uu.el
@@ -87,4 +87,6 @@
(insert "begin 600 xxx\n"))))
(provide 'tramp-uu)
+
+;;; arch-tag: 7153f2c6-8be5-4cd2-8c06-0fbcf5190ef6
;;; tramp-uu.el ends here
diff --git a/lisp/net/tramp-vc.el b/lisp/net/tramp-vc.el
index cee13308d38..ded30f4b09c 100644
--- a/lisp/net/tramp-vc.el
+++ b/lisp/net/tramp-vc.el
@@ -391,8 +391,15 @@ filename we are thinking about..."
;; Pacify byte-compiler; this symbol is bound in the calling
;; function. CCC: Maybe it would be better to move the
;; boundness-checking into this function?
- (let ((file (symbol-value 'file)))
- (if (and uid (/= uid (nth 2 (file-attributes file))))
+ (let ((file (symbol-value 'file))
+ (remote-uid
+ ;; With Emacs 21.4, `file-attributes' has got an optional parameter
+ ;; ID-FORMAT. Handle this case backwards compatible.
+ (if (and (functionp 'subr-arity)
+ (= 2 (cdr (subr-arity (symbol-function 'file-attributes)))))
+ (nth 2 (file-attributes file 'integer))
+ (nth 2 (file-attributes file)))))
+ (if (and uid (/= uid remote-uid))
(error "tramp-handle-vc-user-login-name cannot map a uid to a name")
(let* ((v (tramp-dissect-file-name (tramp-handle-expand-file-name file)))
(u (tramp-file-name-user v)))
@@ -486,4 +493,5 @@ This makes remote VC work correctly at the cost of some processing time."
;; No need to load this again if anyone asks.
(provide 'tramp-vc)
+;;; arch-tag: 27cc42ce-da19-468d-ad5c-a2690558db60
;;; tramp-vc.el ends here
diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el
index 966d93b719c..cd6ed337927 100644
--- a/lisp/net/tramp.el
+++ b/lisp/net/tramp.el
@@ -1,7 +1,7 @@
;;; -*- mode: Emacs-Lisp; coding: iso-2022-7bit; -*-
;;; tramp.el --- Transparent Remote Access, Multiple Protocol
-;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
;; Author: kai.grossjohann@gmx.net
;; Keywords: comm, processes
@@ -72,6 +72,12 @@
(require 'timer)
(require 'format-spec) ;from Gnus 5.8, also in tar ball
+;; As long as password.el is not part of (X)Emacs, it shouldn't
+;; be mandatory
+(if (featurep 'xemacs)
+ (load "password" 'noerror)
+ (require 'password nil 'noerror)) ;from No Gnus, also in tar ball
+
;; The explicit check is not necessary in Emacs, which provides the
;; feature even if implemented in C, but it appears to be necessary
;; in XEmacs.
@@ -569,6 +575,7 @@ variable `tramp-methods'."
("rsh" tramp-multi-connect-rlogin "rsh %h -l %u%n")
("remsh" tramp-multi-connect-rlogin "remsh %h -l %u%n")
("ssh" tramp-multi-connect-rlogin "ssh %h -l %u%n")
+ ("ssht" tramp-multi-connect-rlogin "ssh %h -e none -t -t -l %u%n")
("su" tramp-multi-connect-su "su - %u%n")
("sudo" tramp-multi-connect-su "sudo -u %u -s -p Password:%n"))
"*List of connection functions for multi-hop methods.
@@ -627,14 +634,18 @@ See `tramp-methods' for a list of possibilities for METHOD."
;; Default values for non-Unices seeked
(defconst tramp-completion-function-alist-ssh
(unless (memq system-type '(windows-nt))
- '((tramp-parse-rhosts "/etc/hosts.equiv")
- (tramp-parse-rhosts "/etc/shosts.equiv")
- (tramp-parse-shosts "/etc/ssh_known_hosts")
- (tramp-parse-sconfig "/etc/ssh_config")
- (tramp-parse-rhosts "~/.rhosts")
- (tramp-parse-rhosts "~/.shosts")
- (tramp-parse-shosts "~/.ssh/known_hosts")
- (tramp-parse-sconfig "~/.ssh/config")))
+ '((tramp-parse-rhosts "/etc/hosts.equiv")
+ (tramp-parse-rhosts "/etc/shosts.equiv")
+ (tramp-parse-shosts "/etc/ssh_known_hosts")
+ (tramp-parse-sconfig "/etc/ssh_config")
+ (tramp-parse-shostkeys "/etc/ssh2/hostkeys")
+ (tramp-parse-sknownhosts "/etc/ssh2/knownhosts")
+ (tramp-parse-rhosts "~/.rhosts")
+ (tramp-parse-rhosts "~/.shosts")
+ (tramp-parse-shosts "~/.ssh/known_hosts")
+ (tramp-parse-sconfig "~/.ssh/config")
+ (tramp-parse-shostkeys "~/.ssh2/hostkeys")
+ (tramp-parse-sknownhosts "~/.ssh2/knownhosts")))
"Default list of (FUNCTION FILE) pairs to be examined for ssh methods.")
;; Default values for non-Unices seeked
@@ -649,53 +660,79 @@ See `tramp-methods' for a list of possibilities for METHOD."
'((tramp-parse-passwd "/etc/passwd")))
"Default list of (FUNCTION FILE) pairs to be examined for su methods.")
-(defcustom tramp-completion-function-alist
- (list (cons "rcp" tramp-completion-function-alist-rsh)
- (cons "scp" tramp-completion-function-alist-ssh)
- (cons "scp1" tramp-completion-function-alist-ssh)
- (cons "scp2" tramp-completion-function-alist-ssh)
- (cons "scp1_old" tramp-completion-function-alist-ssh)
- (cons "scp2_old" tramp-completion-function-alist-ssh)
- (cons "rsync" tramp-completion-function-alist-rsh)
- (cons "remcp" tramp-completion-function-alist-rsh)
- (cons "rsh" tramp-completion-function-alist-rsh)
- (cons "ssh" tramp-completion-function-alist-ssh)
- (cons "ssh1" tramp-completion-function-alist-ssh)
- (cons "ssh2" tramp-completion-function-alist-ssh)
- (cons "ssh1_old" tramp-completion-function-alist-ssh)
- (cons "ssh2_old" tramp-completion-function-alist-ssh)
- (cons "remsh" tramp-completion-function-alist-rsh)
- (cons "telnet" tramp-completion-function-alist-telnet)
- (cons "su" tramp-completion-function-alist-su)
- (cons "sudo" tramp-completion-function-alist-su)
- (cons "multi" nil)
- (cons "scpx" tramp-completion-function-alist-ssh)
- (cons "sshx" tramp-completion-function-alist-ssh)
- (cons "krlogin" tramp-completion-function-alist-rsh)
- (cons "plink" tramp-completion-function-alist-ssh)
- (cons "plink1" tramp-completion-function-alist-ssh)
- (cons "pscp" tramp-completion-function-alist-ssh)
- (cons "fcp" tramp-completion-function-alist-ssh)
- )
+(defvar tramp-completion-function-alist nil
"*Alist of methods for remote files.
This is a list of entries of the form (NAME PAIR1 PAIR2 ...).
Each NAME stands for a remote access method. Each PAIR is of the form
\(FUNCTION FILE). FUNCTION is responsible to extract user names and host
names from FILE for completion. The following predefined FUNCTIONs exists:
- * `tramp-parse-rhosts' for \"~/.rhosts\" like files,
- * `tramp-parse-shosts' for \"~/.ssh/known_hosts\" like files,
- * `tramp-parse-sconfig' for \"~/.ssh/config\" like files,
- * `tramp-parse-hosts' for \"/etc/hosts\" like files, and
- * `tramp-parse-passwd' for \"/etc/passwd\" like files.
- * `tramp-parse-netrc' for \"~/.netrc\" like files.
-
-FUNCTION can also see a customer defined function. For more details see
-the info pages."
- :group 'tramp
- :type '(repeat
- (cons string
- (choice (const nil) (repeat (list function file))))))
+ * `tramp-parse-rhosts' for \"~/.rhosts\" like files,
+ * `tramp-parse-shosts' for \"~/.ssh/known_hosts\" like files,
+ * `tramp-parse-sconfig' for \"~/.ssh/config\" like files,
+ * `tramp-parse-shostkeys' for \"~/.ssh2/hostkeys/*\" like files,
+ * `tramp-parse-sknownhosts' for \"~/.ssh2/knownhosts/*\" like files,
+ * `tramp-parse-hosts' for \"/etc/hosts\" like files,
+ * `tramp-parse-passwd' for \"/etc/passwd\" like files.
+ * `tramp-parse-netrc' for \"~/.netrc\" like files.
+
+FUNCTION can also be a customer defined function. For more details see
+the info pages.")
+
+(eval-after-load "tramp"
+ '(progn
+ (tramp-set-completion-function
+ "rcp" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "scp" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "scp1" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "scp2" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "scp1_old" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "scp2_old" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "rsync" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "remcp" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "rsh" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "ssh" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "ssh1" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "ssh2" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "ssh1_old" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "ssh2_old" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "remsh" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "telnet" 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
+ "multi" nil)
+ (tramp-set-completion-function
+ "scpx" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "sshx" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "krlogin" tramp-completion-function-alist-rsh)
+ (tramp-set-completion-function
+ "plink" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "plink1" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "pscp" tramp-completion-function-alist-ssh)
+ (tramp-set-completion-function
+ "fcp" tramp-completion-function-alist-ssh)))
(defcustom tramp-rsh-end-of-line "\n"
"*String used for end of line in rsh connections.
@@ -1250,11 +1287,33 @@ checked via the following code:
(re-search-forward \"\\\\w+\")
(message \"Bytes sent: %s\\tBytes received: %s\" bytes (match-string 0))))
+In the Emacs normally running Tramp, evaluate the above code.
+You can do this, for example, by pasting it into the `*scratch*'
+buffer and then hitting C-j with the cursor after the last
+closing parenthesis.
+
+If your Emacs is buggy, the sent and received numbers will be
+different. In that case, you'll want to set this variable to
+some number. For those people who have needed it, the value 500
+seems to have worked well. There is no way to predict what value
+you need; maybe you could just experiment a bit.
+
Please raise a bug report via \"M-x tramp-bug\" if your system needs
this variable to be set as well."
:group 'tramp
:type '(choice (const nil) integer))
+;; Logging in to a remote host normally requires obtaining a pty. But
+;; Emacs on MacOS X has process-connection-type set to nil by default,
+;; so on those systems Tramp doesn't obtain a pty. Here, we allow
+;; for an override of the system default.
+(defcustom tramp-process-connection-type t
+ "Overrides `process-connection-type' for connections from Tramp.
+Tramp binds process-connection-type to the value given here before
+opening a connection to a remote host."
+ :group 'tramp
+ :type '(choice (const nil) (const t) (const pty)))
+
;;; Internal Variables:
(defvar tramp-buffer-file-attributes nil
@@ -1405,13 +1464,15 @@ some systems don't, and for them we have this shell function.")
;; The device number is returned as "-1", because there will be a virtual
;; device number set in `tramp-handle-file-attributes'
(defconst tramp-perl-file-attributes "\
-$f = $ARGV[0];
+($f, $n) = @ARGV;
@s = lstat($f);
if (($s[2] & 0170000) == 0120000) { $l = readlink($f); $l = \"\\\"$l\\\"\"; }
elsif (($s[2] & 0170000) == 040000) { $l = \"t\"; }
else { $l = \"nil\" };
-printf(\"(%s %u %d %d (%u %u) (%u %u) (%u %u) %u %u t (%u . %u) -1)\\n\",
-$l, $s[3], $s[4], $s[5], $s[8] >> 16 & 0xffff, $s[8] & 0xffff,
+$u = ($n eq \"nil\") ? $s[4] : getpwuid($s[4]);
+$g = ($n eq \"nil\") ? $s[5] : getgrgid($s[5]);
+printf(\"(%s %u %s %s (%u %u) (%u %u) (%u %u) %u %u t (%u . %u) -1)\\n\",
+$l, $s[3], $u, $g, $s[8] >> 16 & 0xffff, $s[8] & 0xffff,
$s[9] >> 16 & 0xffff, $s[9] & 0xffff, $s[10] >> 16 & 0xffff, $s[10] & 0xffff,
$s[7], $s[2], $s[1] >> 16 & 0xffff, $s[1] & 0xffff);"
"Perl script to produce output suitable for use with `file-attributes'
@@ -1624,6 +1685,7 @@ on the FILENAME argument, even if VISIT was a string.")
(insert-file-contents . tramp-handle-insert-file-contents)
(write-region . tramp-handle-write-region)
(unhandled-file-name-directory . tramp-handle-unhandled-file-name-directory)
+ (dired-compress-file . tramp-handle-dired-compress-file)
(dired-call-process . tramp-handle-dired-call-process)
(dired-recursive-delete-directory
. tramp-handle-dired-recursive-delete-directory)
@@ -1747,15 +1809,30 @@ Example:
'((tramp-parse-sconfig \"/etc/ssh_config\")
(tramp-parse-sconfig \"~/.ssh/config\")))"
- (let ((v (cdr (assoc method tramp-completion-function-alist))))
- (if v (setcdr v function-list)
+ (let ((r function-list)
+ (v function-list))
+ (setq tramp-completion-function-alist
+ (delete (assoc method tramp-completion-function-alist)
+ tramp-completion-function-alist))
+
+ (while v
+ ;; Remove double entries
+ (when (member (car v) (cdr v))
+ (setcdr v (delete (car v) (cdr v))))
+ ;; Check for function and file
+ (unless (and (functionp (nth 0 (car v)))
+ (file-exists-p (nth 1 (car v))))
+ (setq r (delete (car v) r)))
+ (setq v (cdr v)))
+
+ (when r
(add-to-list 'tramp-completion-function-alist
- (cons method function-list)))))
+ (cons method r)))))
(defun tramp-get-completion-function (method)
"Returns list of completion functions for METHOD.
For definition of that list see `tramp-set-completion-function'."
- (cdr (assoc method tramp-completion-function-alist)))
+ (cdr (assoc method tramp-completion-function-alist)))
;;; File Name Handler Functions:
@@ -1900,7 +1977,7 @@ target of the symlink differ."
(append '("") (reverse result) (list thisstep))
"/"))
(setq symlink-target
- (nth 0 (tramp-handle-file-attributes
+ (nth 0 (file-attributes
(tramp-make-tramp-file-name
multi-method method user host
(mapconcat 'identity
@@ -1979,11 +2056,10 @@ target of the symlink differ."
;; CCC: This should check for an error condition and signal failure
;; when something goes wrong.
;; Daniel Pittman <daniel@danann.net>
-(defun tramp-handle-file-attributes (filename &optional nonnumeric)
- "Like `file-attributes' for tramp files.
-Optional argument NONNUMERIC means return user and group name
-rather than as numbers."
- (let (result)
+(defun tramp-handle-file-attributes (filename &optional id-format)
+ "Like `file-attributes' for tramp files."
+ (let ((nonnumeric (and id-format (equal id-format 'string)))
+ result)
(with-parsed-tramp-file-name filename nil
(when (tramp-handle-file-exists-p filename)
;; file exists, find out stuff
@@ -2097,8 +2173,8 @@ is initially created and is kept cached by the remote shell."
multi-method method user host localname))
(tramp-send-command
multi-method method user host
- (format "tramp_file_attributes %s"
- (tramp-shell-quote-argument localname)))
+ (format "tramp_file_attributes %s %s"
+ (tramp-shell-quote-argument localname) nonnumeric))
(tramp-wait-for-output)
(let ((result (read (current-buffer))))
(setcar (nthcdr 8 result)
@@ -2310,7 +2386,7 @@ if the remote host can't provide the modtime."
(defun tramp-handle-file-symlink-p (filename)
"Like `file-symlink-p' for tramp files."
(with-parsed-tramp-file-name filename nil
- (let ((x (car (tramp-handle-file-attributes filename))))
+ (let ((x (car (file-attributes filename))))
(when (stringp x)
;; When Tramp is running on VMS, then `file-name-absolute-p'
;; might do weird things.
@@ -2573,44 +2649,86 @@ and `rename'. FILENAME and NEWNAME must be absolute file names."
(signal 'file-already-exists
(list newname))))
(let ((t1 (tramp-tramp-file-p filename))
- (t2 (tramp-tramp-file-p newname)))
+ (t2 (tramp-tramp-file-p newname))
+ v1-multi-method v1-method v1-user v1-host v1-localname
+ v2-multi-method v2-method v2-user v2-host v2-localname)
+
;; Check which ones of source and target are Tramp files.
+ ;; We cannot invoke `with-parsed-tramp-file-name';
+ ;; it fails if the file isn't a Tramp file name.
+ (if t1
+ (with-parsed-tramp-file-name filename l
+ (setq v1-multi-method l-multi-method
+ v1-method l-method
+ v1-user l-user
+ v1-host l-host
+ v1-localname l-localname))
+ (setq v1-localname filename))
+ (if t2
+ (with-parsed-tramp-file-name newname l
+ (setq v2-multi-method l-multi-method
+ v2-method l-method
+ v2-user l-user
+ v2-host l-host
+ v2-localname l-localname))
+ (setq v2-localname newname))
+
(cond
+ ;; Both are Tramp files.
((and t1 t2)
- ;; Both are Tramp files.
- (with-parsed-tramp-file-name filename v1
- (with-parsed-tramp-file-name newname v2
- ;; Check if we can use a shortcut.
- (if (and (equal v1-multi-method v2-multi-method)
- (equal v1-method v2-method)
- (equal v1-host v2-host)
- (equal v1-user v2-user))
- ;; Shortcut: if method, host, user are the same for both
- ;; files, we invoke `cp' or `mv' on the remote host
- ;; directly.
- (tramp-do-copy-or-rename-file-directly
- op v1-multi-method v1-method v1-user v1-host
- v1-localname v2-localname keep-date)
- ;; The shortcut was not possible. So we copy the
- ;; file first. If the operation was `rename', we go
- ;; back and delete the original file (if the copy was
- ;; successful). The approach is simple-minded: we
- ;; 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
- ;; source and target file.
-
- ;; CCC: If both source and target are Tramp files,
- ;; and both are using the same copy-program, then we
- ;; can invoke rcp directly. Note that
- ;; default-directory should point to a local
- ;; directory if we want to invoke rcp.
- (tramp-do-copy-or-rename-via-buffer
- op filename newname keep-date)))))
+ (cond
+ ;; Shortcut: if method, host, user are the same for both
+ ;; files, we invoke `cp' or `mv' on the remote host
+ ;; directly.
+ ((and (equal v1-multi-method v2-multi-method)
+ (equal v1-method v2-method)
+ (equal v1-user v2-user)
+ (equal v1-host v2-host))
+ (tramp-do-copy-or-rename-file-directly
+ op v1-multi-method v1-method v1-user v1-host
+ v1-localname v2-localname keep-date))
+ ;; If both source and target are Tramp files,
+ ;; both are using the same copy-program, then we
+ ;; can invoke rcp directly. Note that
+ ;; default-directory should point to a local
+ ;; directory if we want to invoke rcp.
+ ((and (not v1-multi-method)
+ (not v2-multi-method)
+ (equal v1-method v2-method)
+ (tramp-method-out-of-band-p
+ v1-multi-method v1-method v1-user v1-host)
+ (not (string-match "\\([^#]*\\)#\\(.*\\)" v1-host))
+ (not (string-match "\\([^#]*\\)#\\(.*\\)" v2-host)))
+ (tramp-do-copy-or-rename-file-out-of-band
+ op filename newname keep-date))
+ ;; No shortcut was possible. So we copy the
+ ;; file first. If the operation was `rename', we go
+ ;; back and delete the original file (if the copy was
+ ;; successful). The approach is simple-minded: we
+ ;; 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
+ ;; source and target file.
+ (t
+ (tramp-do-copy-or-rename-via-buffer
+ op filename newname keep-date))))
+
+ ;; One file is a Tramp file, the other one is local.
((or t1 t2)
- ;; Use the generic method via a Tramp buffer.
- (tramp-do-copy-or-rename-via-buffer op filename newname keep-date))
+ ;; If the Tramp file has an out-of-band method, the corresponding
+ ;; copy-program can be invoked.
+ (if (and (not v1-multi-method)
+ (not v2-multi-method)
+ (or (tramp-method-out-of-band-p
+ v1-multi-method v1-method v1-user v1-host)
+ (tramp-method-out-of-band-p
+ v2-multi-method v2-method v2-user v2-host)))
+ (tramp-do-copy-or-rename-file-out-of-band
+ op filename newname keep-date)
+ ;; Use the generic method via a Tramp buffer.
+ (tramp-do-copy-or-rename-via-buffer op filename newname keep-date)))
+
(t
;; One of them must be a Tramp file.
(error "Tramp implementation says this cannot happen")))))
@@ -2621,8 +2739,9 @@ and `rename'. FILENAME and NEWNAME must be absolute file names."
First arg OP is either `copy' or `rename' and indicates the operation.
FILENAME is the source file, NEWNAME the target file.
KEEP-DATE is non-nil if NEWNAME should have the same timestamp as FILENAME."
- (let ((trampbuf (get-buffer-create "*tramp output*")))
- (when keep-date
+ (let ((trampbuf (get-buffer-create "*tramp output*"))
+ (modtime (nth 5 (file-attributes filename))))
+ (when (and keep-date (or (null modtime) (equal modtime '(0 0))))
(tramp-message
1 (concat "Warning: cannot preserve file time stamp"
" with inline copying across machines")))
@@ -2633,7 +2752,12 @@ KEEP-DATE is non-nil if NEWNAME should have the same timestamp as FILENAME."
;; `jka-compr-inhibit' to t.
(let ((coding-system-for-write 'binary)
(jka-compr-inhibit t))
- (write-region (point-min) (point-max) newname)))
+ (write-region (point-min) (point-max) newname))
+ ;; KEEP-DATE handling.
+ (when (and keep-date
+ (not (null modtime))
+ (not (equal modtime '(0 0))))
+ (tramp-touch newname modtime)))
;; If the operation was `rename', delete the original file.
(unless (eq op 'copy)
(delete-file filename))))
@@ -2663,13 +2787,112 @@ If KEEP-DATE is non-nil, preserve the time stamp when copying."
"Copying directly failed, see buffer `%s' for details."
(buffer-name)))))
-(defun tramp-do-copy-or-rename-file-one-local
- (op filename newname keep-date)
+(defun tramp-do-copy-or-rename-file-out-of-band (op filename newname keep-date)
"Invoke rcp program to copy.
One of FILENAME and NEWNAME must be a Tramp name, the other must
be a local filename. The method used must be an out-of-band method."
- ;; CCC
- )
+ (let ((trampbuf (get-buffer-create "*tramp output*"))
+ (t1 (tramp-tramp-file-p filename))
+ (t2 (tramp-tramp-file-p newname))
+ v1-multi-method v1-method v1-user v1-host v1-localname
+ v2-multi-method v2-method v2-user v2-host v2-localname
+ method copy-program copy-args source target)
+
+ ;; Check which ones of source and target are Tramp files.
+ ;; We cannot invoke `with-parsed-tramp-file-name';
+ ;; it fails if the file isn't a Tramp file name.
+ (if t1
+ (with-parsed-tramp-file-name filename l
+ (setq v1-multi-method l-multi-method
+ v1-method l-method
+ v1-user l-user
+ v1-host l-host
+ v1-localname l-localname
+ method (tramp-find-method
+ v1-multi-method v1-method v1-user v1-host)
+ copy-program (tramp-get-method-parameter
+ v1-multi-method method
+ v1-user v1-host 'tramp-copy-program)
+ copy-args (tramp-get-method-parameter
+ v1-multi-method method
+ v1-user v1-host 'tramp-copy-args)))
+ (setq v1-localname filename))
+
+ (if t2
+ (with-parsed-tramp-file-name newname l
+ (setq v2-multi-method l-multi-method
+ v2-method l-method
+ v2-user l-user
+ v2-host l-host
+ v2-localname l-localname
+ method (tramp-find-method
+ v2-multi-method v2-method v2-user v2-host)
+ copy-program (tramp-get-method-parameter
+ v2-multi-method method
+ v2-user v2-host 'tramp-copy-program)
+ copy-args (tramp-get-method-parameter
+ v2-multi-method method
+ v2-user v2-host 'tramp-copy-args)))
+ (setq v2-localname newname))
+
+ ;; The following should be changed. We need a more general
+ ;; mechanism to parse extra host args.
+ (if (not t1)
+ (setq source v1-localname)
+ (when (string-match "\\([^#]*\\)#\\(.*\\)" v1-host)
+ (setq copy-args (cons "-P" (cons (match-string 2 v1-host) copy-args)))
+ (setq v1-host (match-string 1 v1-host)))
+ (setq source
+ (tramp-make-copy-program-file-name
+ v1-user v1-host
+ (tramp-shell-quote-argument v1-localname))))
+
+ (if (not t2)
+ (setq target v2-localname)
+ (when (string-match "\\([^#]*\\)#\\(.*\\)" v2-host)
+ (setq copy-args (cons "-P" (cons (match-string 2 v2-host) copy-args)))
+ (setq v2-host (match-string 1 v2-host)))
+ (setq target
+ (tramp-make-copy-program-file-name
+ v2-user v2-host
+ (tramp-shell-quote-argument v2-localname))))
+
+ ;; Handle keep-date argument
+ (when keep-date
+ (if t1
+ (setq copy-args
+ (cons (tramp-get-method-parameter
+ v1-multi-method method
+ v1-user v1-host 'tramp-copy-keep-date-arg)
+ copy-args))
+ (setq copy-args
+ (cons (tramp-get-method-parameter
+ v2-multi-method method
+ v2-user v2-host 'tramp-copy-keep-date-arg)
+ copy-args))))
+
+ (setq copy-args (append copy-args (list source target)))
+
+ ;; Use rcp-like program for file transfer.
+ (tramp-message
+ 5 "Transferring %s to file %s..." filename newname)
+ (save-excursion (set-buffer trampbuf) (erase-buffer))
+ (unless (equal
+ 0
+ (apply #'call-process copy-program
+ nil trampbuf nil copy-args))
+ (pop-to-buffer trampbuf)
+ (error
+ (concat
+ "tramp-do-copy-or-rename-file-out-of-band: `%s' didn't work, "
+ "see buffer `%s' for details")
+ copy-program trampbuf))
+ (tramp-message
+ 5 "Transferring %s to file %s...done" filename newname)
+
+ ;; If the operation was `rename', delete the original file.
+ (unless (eq op 'copy)
+ (delete-file filename))))
;; mkdir
(defun tramp-handle-make-directory (dir &optional parents)
@@ -2732,7 +2955,6 @@ This is like `dired-recursive-delete-directory' for tramp files."
(and (tramp-handle-file-exists-p filename)
(error "Failed to recusively delete %s" filename))))
-
(defun tramp-handle-dired-call-process (program discard &rest arguments)
"Like `dired-call-process' for tramp files."
(with-parsed-tramp-file-name default-directory nil
@@ -2754,6 +2976,59 @@ This is like `dired-recursive-delete-directory' for tramp files."
(tramp-send-command-and-check multi-method method user host nil)
(tramp-send-command multi-method method user host "cd")
(tramp-wait-for-output)))))
+
+(defun tramp-handle-dired-compress-file (file &rest ok-flag)
+ "Like `dired-compress-file' for tramp files."
+ ;; OK-FLAG is valid for XEmacs only, but not implemented.
+ ;; Code stolen mainly from dired-aux.el.
+ (with-parsed-tramp-file-name file nil
+ (save-excursion
+ (let ((suffixes
+ (if (not (featurep 'xemacs))
+ ;; Emacs case
+ (symbol-value 'dired-compress-file-suffixes)
+ ;; XEmacs has `dired-compression-method-alist', which is
+ ;; transformed into `dired-compress-file-suffixes' structure.
+ (mapcar
+ '(lambda (x)
+ (list (concat (regexp-quote (nth 1 x)) "\\'")
+ nil
+ (mapconcat 'identity (nth 3 x) " ")))
+ (symbol-value 'dired-compression-method-alist))))
+ suffix)
+ ;; See if any suffix rule matches this file name.
+ (while suffixes
+ (let (case-fold-search)
+ (if (string-match (car (car suffixes)) localname)
+ (setq suffix (car suffixes) suffixes nil))
+ (setq suffixes (cdr suffixes))))
+
+ (cond ((file-symlink-p file)
+ nil)
+ ((and suffix (nth 2 suffix))
+ ;; We found an uncompression rule.
+ (message "Uncompressing %s..." file)
+ (when (zerop (tramp-send-command-and-check
+ multi-method method user host
+ (concat (nth 2 suffix) " " localname)))
+ (message "Uncompressing %s...done" file)
+ (dired-remove-file file)
+ (string-match (car suffix) file)
+ (concat (substring file 0 (match-beginning 0)))))
+ (t
+ ;; We don't recognize the file as compressed, so compress it.
+ ;; Try gzip.
+ (message "Compressing %s..." file)
+ (when (zerop (tramp-send-command-and-check
+ multi-method method user host
+ (concat "gzip -f " localname)))
+ (message "Compressing %s...done" file)
+ (dired-remove-file file)
+ (cond ((file-exists-p (concat file ".gz"))
+ (concat file ".gz"))
+ ((file-exists-p (concat file ".z"))
+ (concat file ".z"))
+ (t nil)))))))))
;; Pacify byte-compiler. The function is needed on XEmacs only. I'm
;; not sure at all that this is the right way to do it, but let's hope
@@ -2948,17 +3223,40 @@ the result will be a local, non-Tramp, filename."
;; Remote commands.
+(defvar tramp-async-proc nil
+ "Global variable keeping asyncronous process object.
+Used in `tramp-handle-shell-command'")
+
(defun tramp-handle-shell-command (command &optional output-buffer error-buffer)
"Like `shell-command' for tramp files.
This will break if COMMAND prints a newline, followed by the value of
`tramp-end-of-output', followed by another newline."
+ ;; Asynchronous processes are far from being perfect. But it works at least
+ ;; for `find-grep-dired' and `find-name-dired' in Emacs 21.4.
(if (tramp-tramp-file-p default-directory)
(with-parsed-tramp-file-name default-directory nil
- (let (status)
- (when (string-match "&[ \t]*\\'" command)
- (error "Tramp doesn't grok asynchronous shell commands, yet"))
-;; (when error-buffer
-;; (error "Tramp doesn't grok optional third arg ERROR-BUFFER, yet"))
+ (let ((asynchronous (string-match "[ \t]*&[ \t]*\\'" command))
+ status)
+ (unless output-buffer
+ (setq output-buffer
+ (get-buffer-create
+ (if asynchronous
+ "*Async Shell Command*"
+ "*Shell Command Output*")))
+ (set-buffer output-buffer)
+ (erase-buffer))
+ (unless (bufferp output-buffer)
+ (setq output-buffer (current-buffer)))
+ (set-buffer output-buffer)
+ ;; Tramp doesn't handle the asynchronous case by an asynchronous
+ ;; process. Instead of, another asynchronous process is opened
+ ;; which gets the output of the (synchronous) Tramp process
+ ;; via process-filter. ERROR-BUFFER is disabled.
+ (when asynchronous
+ (setq command (substring command 0 (match-beginning 0))
+ error-buffer nil
+ tramp-async-proc (start-process (buffer-name output-buffer)
+ output-buffer "cat")))
(save-excursion
(tramp-barf-unless-okay
multi-method method user host
@@ -2966,23 +3264,39 @@ This will break if COMMAND prints a newline, followed by the value of
nil 'file-error
"tramp-handle-shell-command: Couldn't `cd %s'"
(tramp-shell-quote-argument localname))
+ ;; Define the process filter
+ (when asynchronous
+ (set-process-filter
+ (get-buffer-process
+ (tramp-get-buffer multi-method method user host))
+ '(lambda (process string)
+ ;; Write the output into the Tramp Process
+ (save-current-buffer
+ (set-buffer (process-buffer process))
+ (goto-char (point-max))
+ (insert string))
+ ;; Hand-over output to asynchronous process.
+ (let ((end
+ (string-match
+ (regexp-quote tramp-end-of-output) string)))
+ (when end
+ (setq string
+ (substring string 0 (1- (match-beginning 0)))))
+ (process-send-string tramp-async-proc string)
+ (when end
+ (set-process-filter process nil)
+ (process-send-eof tramp-async-proc))))))
+ ;; Send the command
(tramp-send-command
multi-method method user host
(if error-buffer
(format "( %s ) 2>/tmp/tramp.$$.err; tramp_old_status=$?"
command)
- (format "%s ;tramp_old_status=$?" command)))
- ;; This will break if the shell command prints "/////"
- ;; somewhere. Let's just hope for the best...
- (tramp-wait-for-output))
- (unless output-buffer
- (setq output-buffer (get-buffer-create "*Shell Command Output*"))
- (set-buffer output-buffer)
- (erase-buffer))
- (unless (bufferp output-buffer)
- (setq output-buffer (current-buffer)))
- (set-buffer output-buffer)
- (insert-buffer (tramp-get-buffer multi-method method user host))
+ (format "%s; tramp_old_status=$?" command)))
+ (unless asynchronous
+ (tramp-wait-for-output)))
+ (unless asynchronous
+ (insert-buffer (tramp-get-buffer multi-method method user host)))
(when error-buffer
(save-excursion
(unless (bufferp error-buffer)
@@ -2997,17 +3311,19 @@ This will break if COMMAND prints a newline, followed by the value of
multi-method method user host "rm -f /tmp/tramp.$$.err")))
(save-excursion
(tramp-send-command multi-method method user host "cd")
- (tramp-wait-for-output)
+ (unless asynchronous
+ (tramp-wait-for-output))
(tramp-send-command
multi-method method user host
(concat "tramp_set_exit_status $tramp_old_status;"
" echo tramp_exit_status $?"))
- (tramp-wait-for-output)
- (goto-char (point-max))
- (unless (search-backward "tramp_exit_status " nil t)
- (error "Couldn't find exit status of `%s'" command))
- (skip-chars-forward "^ ")
- (setq status (read (current-buffer))))
+ (unless asynchronous
+ (tramp-wait-for-output)
+ (goto-char (point-max))
+ (unless (search-backward "tramp_exit_status " nil t)
+ (error "Couldn't find exit status of `%s'" command))
+ (skip-chars-forward "^ ")
+ (setq status (read (current-buffer)))))
(unless (zerop (buffer-size))
(display-buffer output-buffer))
status))
@@ -3028,16 +3344,7 @@ This will break if COMMAND prints a newline, followed by the value of
(defun tramp-handle-file-local-copy (filename)
"Like `file-local-copy' for tramp files."
(with-parsed-tramp-file-name filename nil
- (let ((output-buf (get-buffer-create "*tramp output*"))
- (tramp-buf (tramp-get-buffer multi-method method user host))
- (copy-program (tramp-get-copy-program
- multi-method
- (tramp-find-method multi-method method user host)
- user host))
- (copy-args (tramp-get-copy-args
- multi-method
- (tramp-find-method multi-method method user host)
- user host))
+ (let ((tramp-buf (tramp-get-buffer multi-method method user host))
;; We used to bind the following as late as possible.
;; loc-enc and loc-dec were bound directly before the if
;; statement that checks them. But the functions
@@ -3053,37 +3360,12 @@ This will break if COMMAND prints a newline, followed by the value of
(error "Cannot make local copy of non-existing file `%s'"
filename))
(setq tmpfil (tramp-make-temp-file))
- (cond (copy-program
- ;; The following should be changed. We need a more general
- ;; mechanism to parse extra host args.
- (when (string-match "\\([^#]*\\)#\\(.*\\)" host)
- (setq copy-args (cons "-p" (cons (match-string 2 host)
- rsh-args)))
- (setq host (match-string 1 host)))
- ;; Use rcp-like program for file transfer.
- (tramp-message-for-buffer
- multi-method method user host
- 5 "Fetching %s to tmp file %s..." filename tmpfil)
- (save-excursion (set-buffer output-buf) (erase-buffer))
- (unless (equal
- 0
- (apply #'call-process
- copy-program
- nil output-buf nil
- (append copy-args
- (list
- (tramp-make-copy-program-file-name
- user host
- (tramp-shell-quote-argument localname))
- tmpfil))))
- (pop-to-buffer output-buf)
- (error
- (concat "tramp-handle-file-local-copy: `%s' didn't work, "
- "see buffer `%s' for details")
- copy-program output-buf))
- (tramp-message-for-buffer
- multi-method method user host
- 5 "Fetching %s to tmp file %s...done" filename tmpfil))
+
+
+ (cond ((tramp-method-out-of-band-p multi-method method user host)
+ ;; `copy-file' handles out-of-band methods
+ (copy-file filename tmpfil t t))
+
((and rem-enc rem-dec)
;; Use inline encoding for file transfer.
(save-excursion
@@ -3212,14 +3494,6 @@ This will break if COMMAND prints a newline, followed by the value of
(error "File not overwritten")))
(with-parsed-tramp-file-name filename nil
(let ((curbuf (current-buffer))
- (copy-program (tramp-get-copy-program
- multi-method
- (tramp-find-method multi-method method user host)
- user host))
- (copy-args (tramp-get-copy-args
- multi-method
- (tramp-find-method multi-method method user host)
- user host))
(rem-enc (tramp-get-remote-encoding multi-method method user host))
(rem-dec (tramp-get-remote-decoding multi-method method user host))
(loc-enc (tramp-get-local-encoding multi-method method user host))
@@ -3254,44 +3528,10 @@ This will break if COMMAND prints a newline, followed by the value of
;; decoding command must be specified. However, if the method
;; _also_ specifies an encoding function, then that is used for
;; encoding the contents of the tmp file.
- (cond (copy-program
- ;; The following should be changed. We need a more general
- ;; mechanism to parse extra host args.
- (when (string-match "\\([^#]*\\)#\\(.*\\)" host)
- (setq copy-args (cons "-p" (cons (match-string 2 host)
- rsh-args)))
- (setq host (match-string 1 host)))
-
- ;; use rcp-like program for file transfer
- (let ((argl (append copy-args
- (list
- tmpfil
- (tramp-make-copy-program-file-name
- user host
- (tramp-shell-quote-argument localname))))))
- (tramp-message-for-buffer
- multi-method method user host
- 6 "Writing tmp file using `%s'..." copy-program)
- (save-excursion (set-buffer trampbuf) (erase-buffer))
- (when tramp-debug-buffer
- (save-excursion
- (set-buffer (tramp-get-debug-buffer multi-method
- method user host))
- (goto-char (point-max))
- (tramp-insert-with-face
- 'bold (format "$ %s %s\n" copy-program
- (mapconcat 'identity argl " ")))))
- (unless (equal 0
- (apply #'call-process
- copy-program nil trampbuf nil argl))
- (pop-to-buffer trampbuf)
- (error
- "Cannot write region to file `%s', command `%s' failed"
- filename copy-program))
- (tramp-message-for-buffer
- multi-method method user host
- 6 "Transferring file using `%s'...done"
- copy-program)))
+ (cond ((tramp-method-out-of-band-p multi-method method user host)
+ ;; `copy-file' handles out-of-band methods
+ (copy-file tmpfil filename t t))
+
((and rem-enc rem-dec)
;; Use inline file transfer
(let ((tmpbuf (get-buffer-create " *tramp file transfer*")))
@@ -3306,7 +3546,8 @@ This will break if COMMAND prints a newline, followed by the value of
(progn
(tramp-message-for-buffer
multi-method method user host
- 6 "Encoding region using function...")
+ 6 "Encoding region using function `%s'..."
+ (symbol-name loc-enc))
(insert-file-contents-literally tmpfil)
;; CCC. The following `let' is a workaround for
;; the base64.el that comes with pgnus-0.84. If
@@ -3672,11 +3913,12 @@ necessary anymore."
;; shouldn't have partial tramp file name syntax. Maybe another variable should
;; be introduced overwriting this check in such cases. Or we change tramp
;; file name syntax in order to avoid ambiguities, like in XEmacs ...
-;; In case of XEmacs it can be always true (and wouldn't be necessary).
+;; In case of non unified file names it can be always true (and wouldn't be
+;; necessary, because there are different regexp).
(defun tramp-completion-mode (file)
"Checks whether method / user name / host name completion is active."
(cond
- ((featurep 'xemacs) t)
+ ((not tramp-unified-filenames) t)
((string-match "^/.*:.*:$" file) nil)
((string-match
(concat tramp-prefix-regexp
@@ -3684,11 +3926,21 @@ necessary anymore."
file)
(member (match-string 1 file) (mapcar 'car tramp-methods)))
((or (equal last-input-event 'tab)
+ ;; Emacs
(and (integerp last-input-event)
(not (event-modifiers last-input-event))
(or (char-equal last-input-event ?\?)
(char-equal last-input-event ?\t) ; handled by 'tab already?
- (char-equal last-input-event ?\ ))))
+ (char-equal last-input-event ?\ )))
+ ;; XEmacs
+ (and (featurep 'xemacs)
+ (not (event-modifiers last-input-event))
+ (or (char-equal
+ (funcall 'event-to-character last-input-event) ?\?)
+ (char-equal
+ (funcall 'event-to-character last-input-event) ?\t)
+ (char-equal
+ (funcall 'event-to-character last-input-event) ?\ ))))
t)))
(defun tramp-completion-handle-file-exists-p (filename)
@@ -4037,6 +4289,35 @@ User is always nil."
(forward-line 1))
result))
+(defun tramp-parse-shostkeys (dirname)
+ "Return a list of (user host) tuples allowed to access.
+User is always nil."
+
+ (let ((regexp (concat "^key_[0-9]+_\\(" tramp-host-regexp "\\)\\.pub$"))
+ (files (when (file-directory-p dirname) (directory-files dirname)))
+ result)
+
+ (while files
+ (when (string-match regexp (car files))
+ (push (list nil (match-string 1 (car files))) result))
+ (setq files (cdr files)))
+ result))
+
+(defun tramp-parse-sknownhosts (dirname)
+ "Return a list of (user host) tuples allowed to access.
+User is always nil."
+
+ (let ((regexp (concat "^\\(" tramp-host-regexp
+ "\\)\\.ssh-\\(dss\\|rsa\\)\\.pub$"))
+ (files (when (file-directory-p dirname) (directory-files dirname)))
+ result)
+
+ (while files
+ (when (string-match regexp (car files))
+ (push (list nil (match-string 1 (car files))) result))
+ (setq files (cdr files)))
+ result))
+
(defun tramp-parse-hosts (filename)
"Return a list of (user host) tuples allowed to access.
User is always nil."
@@ -4193,14 +4474,29 @@ hosts, or files, disagree."
(or switch "")
(tramp-shell-quote-argument localname2))))))
+(defun tramp-touch (file time)
+ "Set the last-modified timestamp of the given file.
+TIME is an Emacs internal time value as returned by `current-time'."
+ (let ((touch-time (format-time-string "%Y%m%d%H%M.%S" time)))
+ (with-parsed-tramp-file-name file nil
+ (let ((buf (tramp-get-buffer multi-method method user host)))
+ (unless (zerop (tramp-send-command-and-check
+ multi-method method user host
+ (format "touch -t %s %s"
+ touch-time
+ localname)))
+ (pop-to-buffer buf)
+ (error "tramp-touch: touch failed, see buffer `%s' for details"
+ buf))))))
+
(defun tramp-buffer-name (multi-method method user host)
"A name for the connection buffer for USER at HOST using METHOD."
(if multi-method
(tramp-buffer-name-multi-method "tramp" multi-method method user host)
(let ((method (tramp-find-method multi-method method user host)))
(if user
- (format "*tramp/%s %s@%s*" method user host))
- (format "*tramp/%s %s*" method host))))
+ (format "*tramp/%s %s@%s*" method user host)
+ (format "*tramp/%s %s*" method host)))))
(defun tramp-buffer-name-multi-method (prefix multi-method method user host)
"A name for the multi method connection buffer.
@@ -4402,7 +4698,8 @@ file exists and nonzero exit status otherwise."
9 "Setting remote shell prompt...done")
)
(t (tramp-message 5 "Remote `%s' groks tilde expansion, good"
- (tramp-get-remote-sh multi-method method user host))))))
+ (tramp-get-method-parameter
+ multi-method method user host 'tramp-remote-sh))))))
(defun tramp-check-ls-command (multi-method method user host cmd)
"Checks whether the given `ls' executable groks `-n'.
@@ -4468,11 +4765,6 @@ Returns nil if none was found, else the command is returned."
(defun tramp-action-password (p multi-method method user host)
"Query the user for a password."
(let ((pw-prompt (match-string 0)))
- (when (tramp-method-out-of-band-p multi-method method user host)
- (kill-process (get-buffer-process (current-buffer)))
- (error (concat "Out of band method `%s' not applicable "
- "for remote shell asking for a password")
- method))
(tramp-message 9 "Sending password")
(tramp-enter-password p pw-prompt)))
@@ -4583,6 +4875,7 @@ The terminal type can be configured with `tramp-terminal-type'."
p multi-method method user host actions)
nil)))
(unless (eq exit 'ok)
+ (tramp-clear-passwd user host)
(error "Login failed"))))
;; For multi-actions.
@@ -4618,6 +4911,7 @@ The terminal type can be configured with `tramp-terminal-type'."
(tramp-process-one-multi-action p method user host actions)
nil)))
(unless (eq exit 'ok)
+ (tramp-clear-passwd user host)
(error "Login failed"))))
;; Functions to execute when we have seen the remote shell prompt but
@@ -4686,15 +4980,15 @@ Maybe the different regular expressions need to be tuned.
(p (apply 'start-process
(tramp-buffer-name multi-method method user host)
(tramp-get-buffer multi-method method user host)
- (tramp-get-login-program
+ (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host)
+ user host 'tramp-login-program)
host
- (tramp-get-login-args
+ (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host)))
+ user host 'tramp-login-args)))
(found nil)
(pw nil))
(process-kill-without-query p)
@@ -4743,18 +5037,18 @@ arguments, and xx will be used as the host name to connect to.
(let ((process-environment (copy-sequence process-environment))
(bufnam (tramp-buffer-name multi-method method user host))
(buf (tramp-get-buffer multi-method method user host))
- (login-program (tramp-get-login-program
+ (login-program (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host))
- (login-args (tramp-get-login-args
+ user host 'tramp-login-program))
+ (login-args (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host)))
+ user host 'tramp-login-args)))
;; The following should be changed. We need a more general
;; mechanism to parse extra host args.
(when (string-match "\\([^#]*\\)#\\(.*\\)" host)
- (setq login-args (cons "-p" (cons (match-string 2 host) rsh-args)))
+ (setq login-args (cons "-p" (cons (match-string 2 host) login-args)))
(setq host (match-string 1 host)))
(setenv "TERM" tramp-terminal-type)
(let* ((default-directory (tramp-temporary-file-directory))
@@ -4818,17 +5112,17 @@ prompt than you do, so it is not at all unlikely that the variable
(p (apply 'start-process
(tramp-buffer-name multi-method method user host)
(tramp-get-buffer multi-method method user host)
- (tramp-get-login-program
+ (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host)
+ user host 'tramp-login-program)
(mapcar
(lambda (x)
(format-spec x `((?u . ,(or user "root")))))
- (tramp-get-login-args
+ (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host))))
+ user host 'tramp-login-args))))
(found nil)
(pw nil))
(process-kill-without-query p)
@@ -5054,11 +5348,13 @@ Uses PROMPT as a prompt and sends the password to process P."
(erase-buffer)
(process-send-string
p (concat pw
- (tramp-get-password-end-of-line
- tramp-current-multi-method
- tramp-current-method
- tramp-current-user
- tramp-current-host)))))
+ (or (tramp-get-method-parameter
+ tramp-current-multi-method
+ tramp-current-method
+ tramp-current-user
+ tramp-current-host
+ 'tramp-password-end-of-line)
+ tramp-default-password-end-of-line)))))
;; HHH: Not Changed. This might handle the case where USER is not
;; given in the "File name" very poorly. Then, the local
@@ -5101,13 +5397,15 @@ to set up. METHOD, USER and HOST specify the connection."
(tramp-send-command-internal
multi-method method user host
(format "exec env 'ENV=' 'PS1=$ ' %s"
- (tramp-get-remote-sh multi-method method user host))
+ (tramp-get-method-parameter
+ multi-method method user host 'tramp-remote-sh))
(format "remote `%s' to come up"
- (tramp-get-remote-sh multi-method method user host)))
+ (tramp-get-method-parameter
+ multi-method method user host 'tramp-remote-sh)))
(tramp-barf-if-no-shell-prompt
p 30
"Remote `%s' didn't come up. See buffer `%s' for details"
- (tramp-get-remote-sh multi-method method user host)
+ (tramp-get-method-parameter multi-method method user host 'tramp-remote-sh)
(buffer-name))
(tramp-message 8 "Setting up remote shell environment")
(tramp-discard-garbage-erase-buffer p multi-method method user host)
@@ -5287,13 +5585,10 @@ locale to C and sets up the remote shell search path."
multi-method method user host
(concat "tramp_file_attributes () {\n"
tramp-remote-perl
- " -e '" tramp-perl-file-attributes "' $1 2>/dev/null\n"
+ " -e '" tramp-perl-file-attributes "' $1 $2 2>/dev/null\n"
"}"))
(tramp-wait-for-output)
- (unless (tramp-get-copy-program
- multi-method
- (tramp-find-method multi-method method user host)
- user host)
+ (unless (tramp-method-out-of-band-p multi-method method user host)
(tramp-message 5 "Sending the Perl `mime-encode' implementations.")
(tramp-send-string
multi-method method user host
@@ -5332,10 +5627,7 @@ locale to C and sets up the remote shell search path."
(tramp-set-connection-property "ln" ln multi-method method user host)))
(erase-buffer)
;; Find the right encoding/decoding commands to use.
- (unless (tramp-get-copy-program
- multi-method
- (tramp-find-method multi-method method user host)
- user host)
+ (unless (tramp-method-out-of-band-p multi-method method user host)
(tramp-find-inline-encoding multi-method method user host))
;; If encoding/decoding command are given, test to see if they work.
;; CCC: Maybe it would be useful to run the encoder both locally and
@@ -5548,11 +5840,12 @@ connection if a previous connection has died for some reason."
(unless (and p (processp p) (memq (process-status p) '(run open)))
(when (and p (processp p))
(delete-process p))
- (funcall (tramp-get-connection-function
- multi-method
- (tramp-find-method multi-method method user host)
- user host)
- multi-method method user host))))
+ (let ((process-connection-type tramp-process-connection-type))
+ (funcall (tramp-get-method-parameter
+ multi-method
+ (tramp-find-method multi-method method user host)
+ user host 'tramp-connection-function)
+ multi-method method user host)))))
(defun tramp-send-command
(multi-method method user host command &optional noerase neveropen)
@@ -6035,10 +6328,10 @@ If both MULTI-METHOD and METHOD are nil, do a lookup in
"Return t if this is an out-of-band method, nil otherwise.
It is important to check for this condition, since it is not possible
to enter a password for the `tramp-copy-program'."
- (tramp-get-copy-program
+ (tramp-get-method-parameter
multi-method
(tramp-find-method multi-method method user host)
- user host))
+ user host 'tramp-copy-program))
;; Variables local to connection.
@@ -6117,65 +6410,19 @@ If the value is not set for the connection, return `default'"
(tramp-get-connection-property "local-decoding" nil
multi-method method user host))
-
-
-(defun tramp-get-connection-function (multi-method method user host)
- (second (or (assoc 'tramp-connection-function
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify a connection function"
- (or multi-method method)))))
-
-(defun tramp-get-remote-sh (multi-method method user host)
- (second (or (assoc 'tramp-remote-sh
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify a remote shell"
- (or multi-method method)))))
-
-(defun tramp-get-login-program (multi-method method user host)
- (second (or (assoc 'tramp-login-program
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify a login program"
- (or multi-method method)))))
-
-(defun tramp-get-login-args (multi-method method user host)
- (second (or (assoc 'tramp-login-args
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify login args"
- (or multi-method method)))))
-
-(defun tramp-get-copy-program (multi-method method user host)
- (second (or (assoc 'tramp-copy-program
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify a copy program"
- (or multi-method method)))))
-
-(defun tramp-get-copy-args (multi-method method user host)
- (second (or (assoc 'tramp-copy-args
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify copy args"
- (or multi-method method)))))
-
-(defun tramp-get-copy-keep-date-arg (multi-method method user host)
- (second (or (assoc 'tramp-copy-keep-date-arg
- (assoc (tramp-find-method multi-method method user host)
- tramp-methods))
- (error "Method `%s' didn't specify `keep-date' arg for tramp"
- (or multi-method method)))))
-
-(defun tramp-get-password-end-of-line (multi-method method user host)
- (let ((entry (assoc 'tramp-password-end-of-line
+(defun tramp-get-method-parameter (multi-method method user host param)
+ "Return the method parameter PARAM.
+If the `tramp-methods' entry does not exist, use the variable PARAM
+as default."
+ (unless (boundp param)
+ (error "Non-existing method parameter `%s'" param))
+ (let ((entry (assoc param
(assoc (tramp-find-method multi-method method user host)
tramp-methods))))
- (unless entry
- (error "Method `%s' didn't specify `password-end-of-line' arg for tramp"
- (or multi-method method)))
- (or (second entry) tramp-default-password-end-of-line)))
+ (if entry
+ (second entry)
+ (symbol-value param))))
+
;; Auto saving to a special directory.
@@ -6251,10 +6498,28 @@ this is the function `temp-directory'."
(defun tramp-read-passwd (prompt)
"Read a password from user (compat function).
-Invokes `read-passwd' if that is defined, else `ange-ftp-read-passwd'."
- (apply
- (if (fboundp 'read-passwd) #'read-passwd #'ange-ftp-read-passwd)
- (list prompt)))
+Invokes `password-read' if available, `read-passwd' else."
+ (if (functionp 'password-read)
+ (let* ((user (or tramp-current-user (user-login-name)))
+ (host (or tramp-current-host (system-name)))
+ (key (concat user "@" host))
+ (password (apply #'password-read (list prompt key))))
+ (apply #'password-cache-add (list key password))
+ password)
+ (read-passwd prompt)))
+
+(defun tramp-clear-passwd (&optional user host)
+ "Clear password cache for connection related to current-buffer."
+ (interactive)
+ (let ((filename (or buffer-file-name list-buffers-directory "")))
+ (when (and (functionp 'password-cache-remove)
+ (or (and user host) (tramp-tramp-file-p filename)))
+ (let* ((v (when (tramp-tramp-file-p filename)
+ (tramp-dissect-file-name filename)))
+ (luser (or user (tramp-file-name-user v) (user-login-name)))
+ (lhost (or host (tramp-file-name-host v) (system-name)))
+ (key (concat luser "@" lhost)))
+ (apply #'password-cache-remove (list key))))))
(defun tramp-time-diff (t1 t2)
"Return the difference between the two times, in seconds.
@@ -6626,6 +6891,7 @@ report.
;; ** Enhance variables for debug.
;; ** Implement "/multi:" completion.
;; ** Add a learning mode for completion. Make results persistent.
+;; * Allow out-of-band methods as _last_ multi-hop.
;; Functions for file-name-handler-alist:
;; diff-latest-backup-file -- in diff.el
@@ -6642,4 +6908,5 @@ report.
;; unhandled-file-name-directory
;; vc-registered
+;;; arch-tag: 3a21a994-182b-48fa-b0cd-c1d9fede424a
;;; tramp.el ends here
diff --git a/lisp/net/trampver.el b/lisp/net/trampver.el
index f741da82757..b3223d7a46e 100644
--- a/lisp/net/trampver.el
+++ b/lisp/net/trampver.el
@@ -30,7 +30,7 @@
;; are auto-frobbed from configure.ac, so you should edit that file and run
;; "autoconf && ./configure" to change them.
-(defconst tramp-version "2.0.36"
+(defconst tramp-version "2.0.39"
"This version of Tramp.")
(defconst tramp-bug-report-address "tramp-devel@mail.freesoftware.fsf.org"
@@ -38,4 +38,5 @@
(provide 'trampver)
+;;; arch-tag: 443576ca-f8f1-4bb1-addc-5c70861e93b1
;;; trampver.el ends here
diff --git a/lisp/net/webjump.el b/lisp/net/webjump.el
index 4c701b48ac5..3f004b8864e 100644
--- a/lisp/net/webjump.el
+++ b/lisp/net/webjump.el
@@ -1,6 +1,6 @@
;;; webjump.el --- programmable Web hotlist
-;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
+;; Copyright (C) 1996, 1997, 2004 Free Software Foundation, Inc.
;; Author: Neil W. Van Dyke <nwv@acm.org>
;; Created: 09-Aug-1996
@@ -300,7 +300,8 @@ Please submit bug reports and other feedback to the author, Neil W. Van Dyke
((eq builtin 'mirrors)
(if (= (length expr) 1)
(error
- "WebJump URL builtin \"mirrors\" for \"%s\" needs at least 1 arg"))
+ "WebJump URL builtin \"mirrors\" for \"%s\" needs at least 1 arg"
+ name))
(webjump-choose-mirror name (cdr (append expr nil))))
((eq builtin 'name)
name)
@@ -400,4 +401,5 @@ Please submit bug reports and other feedback to the author, Neil W. Van Dyke
(provide 'webjump)
+;;; arch-tag: f1d20156-0a6f-488b-bd91-f69ee8b6d5cc
;;; webjump.el ends here
diff --git a/lisp/net/zone-mode.el b/lisp/net/zone-mode.el
index a58bc2dd54a..6b4d22f9b13 100644
--- a/lisp/net/zone-mode.el
+++ b/lisp/net/zone-mode.el
@@ -92,7 +92,7 @@ Zone-mode does two things:
- fontification"
- (add-hook 'write-file-hooks 'zone-mode-update-serial-hook nil t)
+ (add-hook 'write-file-functions 'zone-mode-update-serial-hook nil t)
(if (null zone-mode-syntax-table)
(zone-mode-load-time-setup)) ;; should have been run at load-time
@@ -115,4 +115,5 @@ Zone-mode does two things:
(provide 'zone-mode)
+;;; arch-tag: 6a2940ef-fd4f-4de7-b979-b027b09821fe
;;; zone-mode.el ends here