diff options
Diffstat (limited to 'lisp/net')
-rw-r--r-- | lisp/net/browse-url.el | 113 | ||||
-rw-r--r-- | lisp/net/netrc.el | 95 | ||||
-rw-r--r-- | lisp/net/newsticker.el | 9 | ||||
-rw-r--r-- | lisp/net/rcirc.el | 218 | ||||
-rw-r--r-- | lisp/net/tls.el | 97 | ||||
-rw-r--r-- | lisp/net/tramp-cache.el | 66 | ||||
-rw-r--r-- | lisp/net/tramp-cmds.el | 272 | ||||
-rw-r--r-- | lisp/net/tramp-fish.el | 15 | ||||
-rw-r--r-- | lisp/net/tramp-ftp.el | 7 | ||||
-rw-r--r-- | lisp/net/tramp-smb.el | 20 | ||||
-rw-r--r-- | lisp/net/tramp.el | 468 |
11 files changed, 826 insertions, 554 deletions
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index c2a0442478c..523588ec7c2 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el @@ -46,7 +46,7 @@ ;; browse-url-cci XMosaic 2.5 ;; browse-url-w3 w3 0 ;; browse-url-w3-gnudoit w3 remotely -;; browse-url-lynx-* Lynx 0 +;; browse-url-text-* Any text browser 0 ;; browse-url-generic arbitrary ;; browse-url-default-windows-browser MS-Windows browser ;; browse-url-default-macosx-browser Mac OS X browser @@ -246,10 +246,10 @@ regexp should probably be \".\" to specify a default browser." (function-item :tag "Netscape" :value browse-url-netscape) (function-item :tag "Mosaic" :value browse-url-mosaic) (function-item :tag "Mosaic using CCI" :value browse-url-cci) - (function-item :tag "Lynx in an xterm window" - :value browse-url-lynx-xterm) - (function-item :tag "Lynx in an Emacs window" - :value browse-url-lynx-emacs) + (function-item :tag "Text browser in an xterm window" + :value browse-url-text-xterm) + (function-item :tag "Text browser in an Emacs window" + :value browse-url-text-emacs) (function-item :tag "KDE" :value browse-url-kde) (function-item :tag "Elinks" :value browse-url-elinks) (function-item :tag "Specified by `Browse Url Generic Program'" @@ -502,9 +502,9 @@ enabled. The port number should be set in `browse-url-CCI-port'." (defvar browse-url-temp-file-name nil) (make-variable-buffer-local 'browse-url-temp-file-name) - + (defcustom browse-url-xterm-program "xterm" - "The name of the terminal emulator used by `browse-url-lynx-xterm'. + "The name of the terminal emulator used by `browse-url-text-xterm'. This might, for instance, be a separate color version of xterm." :type 'string :group 'browse-url) @@ -515,17 +515,6 @@ These might set its size, for instance." :type '(repeat (string :tag "Argument")) :group 'browse-url) -(defcustom browse-url-lynx-emacs-args (and (not window-system) - '("-show_cursor")) - "A list of strings defining options for Lynx in an Emacs buffer. - -The default is none in a window system, otherwise `-show_cursor' to -indicate the position of the current link in the absence of -highlighting, assuming the normal default for showing the cursor." - :type '(repeat (string :tag "Argument")) - :version "20.3" - :group 'browse-url) - (defcustom browse-url-gnudoit-program "gnudoit" "The name of the `gnudoit' program used by `browse-url-w3-gnudoit'." :type 'string @@ -562,28 +551,47 @@ incompatibly at version 4." :type 'number :group 'browse-url) -(defcustom browse-url-lynx-input-field 'avoid - "Action on selecting an existing Lynx buffer at an input field. -What to do when sending a new URL to an existing Lynx buffer in Emacs -if the Lynx cursor is on an input field (in which case the `g' command +(defcustom browse-url-text-browser "lynx" + "The name of the text browser to invoke." + :type 'string + :group 'browse-url + :version "23.1") + +(defcustom browse-url-text-emacs-args (and (not window-system) + '("-show_cursor")) + "A list of strings defining options for a text browser in an Emacs buffer. + +The default is none in a window system, otherwise `-show_cursor' to +indicate the position of the current link in the absence of +highlighting, assuming the normal default for showing the cursor." + :type '(repeat (string :tag "Argument")) + :version "23.1" + :group 'browse-url) + +(defcustom browse-url-text-input-field 'avoid + "Action on selecting an existing text browser buffer at an input field. +What to do when sending a new URL to an existing text browser buffer in Emacs +if the browser cursor is on an input field (in which case the `g' command would be entered as data). Such fields are recognized by the -underlines ____. Allowed values: nil: disregard it, 'warn: warn the -user and don't emit the URL, 'avoid: try to avoid the field by moving +underlines ____. Allowed values: nil: disregard it, `warn': warn the +user and don't emit the URL, `avoid': try to avoid the field by moving down (this *won't* always work)." :type '(choice (const :tag "Move to try to avoid field" :value avoid) (const :tag "Disregard" :value nil) (const :tag "Warn, don't emit URL" :value warn)) - :version "20.3" + :version "23.1" :group 'browse-url) -(defcustom browse-url-lynx-input-attempts 10 - "How many times to try to move down from a series of lynx input fields." +(defcustom browse-url-text-input-attempts 10 + "How many times to try to move down from a series of text browser input fields." :type 'integer + :version "23.1" :group 'browse-url) -(defcustom browse-url-lynx-input-delay 0.2 - "How many seconds to wait for lynx between moves down from an input field." +(defcustom browse-url-text-input-delay 0.2 + "Seconds to wait for a text browser between moves down from an input field." :type 'number + :version "23.1" :group 'browse-url) (defcustom browse-url-kde-program "kfmclient" @@ -876,7 +884,7 @@ Galeon, Konqueror, Netscape, Mosaic, Lynx in an xterm, and then W3." ((executable-find browse-url-kde-program) 'browse-url-kde) ((executable-find browse-url-netscape-program) 'browse-url-netscape) ((executable-find browse-url-mosaic-program) 'browse-url-mosaic) - ((executable-find browse-url-xterm-program) 'browse-url-lynx-xterm) + ((executable-find browse-url-xterm-program) 'browse-url-text-xterm) ((locate-library "w3") 'browse-url-w3) (t (lambda (&ignore args) (error "No usable browser found")))) @@ -1308,38 +1316,41 @@ The `browse-url-gnudoit-program' program is used with options given by ;; --- Lynx in an xterm --- ;;;###autoload -(defun browse-url-lynx-xterm (url &optional new-window) +(defun browse-url-text-xterm (url &optional new-window) ;; new-window ignored - "Ask the Lynx WWW browser to load URL. -Default to the URL around or before point. A new Lynx process is run + "Ask a text browser to load URL. +URL defaults to the URL around or before point. +This runs the text browser specified by `browse-url-text-browser'. in an Xterm window using the Xterm program named by `browse-url-xterm-program' with possible additional arguments `browse-url-xterm-args'." - (interactive (browse-url-interactive-arg "Lynx URL: ")) - (apply #'start-process `(,(concat "lynx" url) nil ,browse-url-xterm-program - ,@browse-url-xterm-args "-e" "lynx" + (interactive (browse-url-interactive-arg "Text browser URL: ")) + (apply #'start-process `(,(concat browse-url-text-browser url) + nil ,browse-url-xterm-program + ,@browse-url-xterm-args "-e" browse-url-text-browser ,url))) ;; --- Lynx in an Emacs "term" window --- ;;;###autoload -(defun browse-url-lynx-emacs (url &optional new-buffer) - "Ask the Lynx WWW browser to load URL. -Default to the URL around or before point. With a prefix argument, run -a new Lynx process in a new buffer. +(defun browse-url-text-emacs (url &optional new-buffer) + "Ask a text browser to load URL. +URL defaults to the URL around or before point. +This runs the text browser specified by `browse-url-text-browser'. +With a prefix argument, it runs a new browser process in a new buffer. When called interactively, if variable `browse-url-new-window-flag' is -non-nil, load the document in a new lynx in a new term window, +non-nil, load the document in a new browser process in a new term window, otherwise use any existing one. A non-nil interactive prefix argument reverses the effect of `browse-url-new-window-flag'. When called non-interactively, optional second argument NEW-WINDOW is used instead of `browse-url-new-window-flag'." - (interactive (browse-url-interactive-arg "Lynx URL: ")) + (interactive (browse-url-interactive-arg "Text browser URL: ")) (let* ((system-uses-terminfo t) ; Lynx uses terminfo ;; (term-term-name "vt100") ; ?? - (buf (get-buffer "*lynx*")) + (buf (get-buffer "*text browser*")) (proc (and buf (get-buffer-process buf))) - (n browse-url-lynx-input-attempts)) + (n browse-url-text-input-attempts)) (if (and (browse-url-maybe-new-window new-buffer) buf) ;; Rename away the OLD buffer. This isn't very polite, but ;; term insists on working in a buffer named *lynx* and would @@ -1350,11 +1361,13 @@ used instead of `browse-url-new-window-flag'." (not buf) (not proc) (not (memq (process-status proc) '(run stop)))) - ;; start a new lynx + ;; start a new text browser (progn (setq buf (apply #'make-term - `("lynx" "lynx" nil ,@browse-url-lynx-emacs-args + `(,browse-url-text-browser + ,browse-url-text-browser + nil ,@browse-url-text-emacs-args ,url))) (switch-to-buffer buf) (term-char-mode) @@ -1366,18 +1379,18 @@ used instead of `browse-url-new-window-flag'." (if (not (memq (process-status process) '(run stop))) (let ((buf (process-buffer process))) (if buf (kill-buffer buf))))))) - ;; send the url to lynx in the old buffer + ;; Send the url to the text browser in the old buffer (let ((win (get-buffer-window buf t))) (if win (select-window win) (switch-to-buffer buf))) (if (eq (following-char) ?_) - (cond ((eq browse-url-lynx-input-field 'warn) + (cond ((eq browse-url-text-input-field 'warn) (error "Please move out of the input field first")) - ((eq browse-url-lynx-input-field 'avoid) + ((eq browse-url-text-input-field 'avoid) (while (and (eq (following-char) ?_) (> n 0)) (term-send-down) ; down arrow - (sit-for browse-url-lynx-input-delay)) + (sit-for browse-url-text-input-delay)) (if (eq (following-char) ?_) (error "Cannot move out of the input field, sorry"))))) (term-send-string proc (concat "g" ; goto diff --git a/lisp/net/netrc.el b/lisp/net/netrc.el index 1b52090abf6..8c4b0a08f51 100644 --- a/lisp/net/netrc.el +++ b/lisp/net/netrc.el @@ -32,27 +32,45 @@ ;;; Code: ;;; -;;; .netrc and .authinforc parsing +;;; .netrc and .authinfo rc parsing ;;; (defalias 'netrc-point-at-eol (if (fboundp 'point-at-eol) 'point-at-eol 'line-end-position)) +;; autoload encrypt + +(eval-and-compile + (autoload 'encrypt-find-model "encrypt") + (autoload 'encrypt-insert-file-contents "encrypt")) + +(defgroup netrc nil + "Netrc configuration." + :group 'comm) + +(defvar netrc-services-file "/etc/services" + "The name of the services file.") (defun netrc-parse (file) - "Parse FILE and return a list of all entries in the file." + (interactive "fFile to Parse: ") + "Parse FILE and return an list of all entries in the file." (when (file-exists-p file) (with-temp-buffer (let ((tokens '("machine" "default" "login" "password" "account" "macdef" "force" "port")) + (encryption-model (encrypt-find-model file)) alist elem result pair) - (insert-file-contents file) + + (if encryption-model + (encrypt-insert-file-contents file encryption-model) + (insert-file-contents file)) + (goto-char (point-min)) ;; Go through the file, line by line. (while (not (eobp)) - (narrow-to-region (point) (netrc-point-at-eol)) + (narrow-to-region (point) (point-at-eol)) ;; For each line, get the tokens and values. (while (not (eobp)) (skip-chars-forward "\t ") @@ -113,16 +131,79 @@ Entries without port tokens default to DEFAULTPORT." (when result (setq result (nreverse result)) (while (and result - (not (equal (or port defaultport "nntp") - (or (netrc-get (car result) "port") - defaultport "nntp")))) + (not (netrc-port-equal + (or port defaultport "nntp") + (or (netrc-get (car result) "port") + defaultport "nntp")))) (pop result)) (car result)))) +(defun netrc-machine-user-or-password (mode authinfo-file-or-list machines ports defaults) + "Get the user name or password according to MODE from AUTHINFO-FILE-OR-LIST. +Matches a machine from MACHINES and a port from PORTS, giving +default ports DEFAULTS to `netrc-machine'. + +MODE can be \"login\" or \"password\", suitable for passing to +`netrc-get'." + (let ((authinfo-list (if (stringp authinfo-file-or-list) + (netrc-parse authinfo-file-or-list) + authinfo-file-or-list)) + (ports (or ports '(nil))) + (defaults (or defaults '(nil))) + info) + (dolist (machine machines) + (dolist (default defaults) + (dolist (port ports) + (let ((alist (netrc-machine authinfo-list machine port default))) + (setq info (or (netrc-get alist mode) info)))))) + info)) + (defun netrc-get (alist type) "Return the value of token TYPE from ALIST." (cdr (assoc type alist))) +(defun netrc-port-equal (port1 port2) + (when (numberp port1) + (setq port1 (or (netrc-find-service-name port1) port1))) + (when (numberp port2) + (setq port2 (or (netrc-find-service-name port2) port2))) + (equal port1 port2)) + +(defun netrc-parse-services () + (when (file-exists-p netrc-services-file) + (let ((services nil)) + (with-temp-buffer + (insert-file-contents netrc-services-file) + (while (search-forward "#" nil t) + (delete-region (1- (point)) (point-at-eol))) + (goto-char (point-min)) + (while (re-search-forward + "^ *\\([^ \n\t]+\\)[ \t]+\\([0-9]+\\)/\\([^ \t\n]+\\)" nil t) + (push (list (match-string 1) (string-to-number (match-string 2)) + (intern (downcase (match-string 3)))) + services)) + (nreverse services))))) + +(defun netrc-find-service-name (number &optional type) + (let ((services (netrc-parse-services)) + service) + (setq type (or type 'tcp)) + (while (and (setq service (pop services)) + (not (and (= number (cadr service)) + (eq type (caddr service))))) + ) + (car service))) + +(defun netrc-find-service-number (name &optional type) + (let ((services (netrc-parse-services)) + service) + (setq type (or type 'tcp)) + (while (and (setq service (pop services)) + (not (and (string= name (car service)) + (eq type (caddr service))))) + ) + (cadr service))) + (provide 'netrc) ;;; arch-tag: af9929cc-2d12-482f-936e-eb4366f9fa55 diff --git a/lisp/net/newsticker.el b/lisp/net/newsticker.el index eb70a2e2d31..735d946346d 100644 --- a/lisp/net/newsticker.el +++ b/lisp/net/newsticker.el @@ -1199,10 +1199,11 @@ buffers *newsticker-wget-<feed>* will not be closed." (unless (fboundp 'match-string-no-properties) (defalias 'match-string-no-properties 'match-string)) -(unless (fboundp 'replace-regexp-in-string) - (defun replace-regexp-in-string (re rp st) - (save-match-data ;; apparently XEmacs needs save-match-data - (replace-in-string st re rp)))) +(when (featurep 'xemacs) + (unless (fboundp 'replace-regexp-in-string) + (defun replace-regexp-in-string (re rp st) + (save-match-data ;; apparently XEmacs needs save-match-data + (replace-in-string st re rp))))) ;; copied from subr.el (unless (fboundp 'add-to-invisibility-spec) diff --git a/lisp/net/rcirc.el b/lisp/net/rcirc.el index b2ad08d7ccd..ef24de44e50 100644 --- a/lisp/net/rcirc.el +++ b/lisp/net/rcirc.el @@ -93,11 +93,11 @@ VALUE must be a list of strings describing which channels to join when connecting to this server. If absent, no channels will be connected to automatically." :type '(alist :key-type string - :value-type (plist :options ((nick string) - (port integer) - (user-name string) - (full-name string) - (channels (repeat string))))) + :value-type (plist :options ((:nick string) + (:port integer) + (:user-name string) + (:full-name string) + (:channels (repeat string))))) :group 'rcirc) (defcustom rcirc-default-port 6667 @@ -323,6 +323,9 @@ and the cdr part is used for encoding." (defvar rcirc-nick-table nil) +(defvar rcirc-recent-quit-alist nil + "Alist of nicks that have recently quit or parted the channel.") + (defvar rcirc-nick-syntax-table (let ((table (make-syntax-table text-mode-syntax-table))) (mapc (lambda (c) (modify-syntax-entry c "w" table)) @@ -417,8 +420,11 @@ If ARG is non-nil, instead prompt for connection parameters." connected-servers)))))))) (when connected-servers (message "Already connected to %s" - (concat (mapconcat 'identity (butlast connected-servers) ", ") - ", and " (car (last connected-servers)))))))) + (if (cdr connected-servers) + (concat (mapconcat 'identity (butlast connected-servers) ", ") + ", and " + (car (last connected-servers))) + (car connected-servers))))))) ;;;###autoload (defalias 'irc 'rcirc) @@ -763,7 +769,6 @@ If SILENT is non-nil, do not print the message in any irc buffer." rcirc-target)))))) (let ((completion (car rcirc-nick-completions))) (when completion - (rcirc-put-nick-channel (rcirc-buffer-process) completion rcirc-target) (delete-region (+ rcirc-prompt-end-marker rcirc-nick-completion-start-offset) (point)) @@ -799,6 +804,7 @@ If SILENT is non-nil, do not print the message in any irc buffer." (define-key rcirc-mode-map (kbd "C-c C-m") 'rcirc-cmd-msg) (define-key rcirc-mode-map (kbd "C-c C-r") 'rcirc-cmd-nick) ; rename (define-key rcirc-mode-map (kbd "C-c C-o") 'rcirc-omit-mode) +(define-key rcirc-mode-map (kbd "M-o") 'rcirc-omit-mode) (define-key rcirc-mode-map (kbd "C-c C-p") 'rcirc-cmd-part) (define-key rcirc-mode-map (kbd "C-c C-q") 'rcirc-cmd-query) (define-key rcirc-mode-map (kbd "C-c C-t") 'rcirc-cmd-topic) @@ -828,6 +834,10 @@ If SILENT is non-nil, do not print the message in any irc buffer." "Alist of lines to log to disk when `rcirc-log-flag' is non-nil. Each element looks like (FILENAME . TEXT).") +(defvar rcirc-current-line 0 + "The current number of responses printed in this channel. +This number is independent of the number of lines in the buffer.") + (defun rcirc-mode (process target) "Major mode for IRC channel buffers. @@ -850,12 +860,24 @@ Each element looks like (FILENAME . TEXT).") (setq rcirc-last-post-time (current-time)) (make-local-variable 'fill-paragraph-function) (setq fill-paragraph-function 'rcirc-fill-paragraph) + (make-local-variable 'rcirc-recent-quit-alist) + (setq rcirc-recent-quit-alist nil) + (make-local-variable 'rcirc-current-line) + (setq rcirc-current-line 0) (make-local-variable 'rcirc-short-buffer-name) (setq rcirc-short-buffer-name nil) (make-local-variable 'rcirc-urls) (setq use-hard-newlines t) + ;; setup for omitting responses + (setq buffer-invisibility-spec '()) + (setq buffer-display-table (make-display-table)) + (set-display-table-slot buffer-display-table 4 + (let ((glyph (make-glyph-code + ?. 'font-lock-keyword-face))) + (make-vector 3 glyph))) + (make-local-variable 'rcirc-decode-coding-system) (make-local-variable 'rcirc-encode-coding-system) (dolist (i rcirc-coding-system-alist) @@ -879,8 +901,6 @@ Each element looks like (FILENAME . TEXT).") (setq overlay-arrow-position (make-marker)) (set-marker overlay-arrow-position nil) - (setq buffer-invisibility-spec '(rcirc-ignored-user)) - ;; if the user changes the major mode or kills the buffer, there is ;; cleanup work to do (add-hook 'change-major-mode-hook 'rcirc-change-major-mode-hook nil t) @@ -1005,8 +1025,9 @@ Create the buffer if it doesn't exist." (let ((new-buffer (get-buffer-create (rcirc-generate-new-buffer-name process target)))) (with-current-buffer new-buffer - (rcirc-mode process target)) - (rcirc-put-nick-channel process (rcirc-nick process) target) + (rcirc-mode process target) + (rcirc-put-nick-channel process (rcirc-nick process) target + rcirc-current-line)) new-buffer))))) (defun rcirc-send-input () @@ -1090,7 +1111,8 @@ Create the buffer if it doesn't exist." (interactive) (let ((pos (1+ (- (point) rcirc-prompt-end-marker)))) (goto-char (point-max)) - (let ((text (buffer-substring rcirc-prompt-end-marker (point))) + (let ((text (buffer-substring-no-properties rcirc-prompt-end-marker + (point))) (parent (buffer-name))) (delete-region rcirc-prompt-end-marker (point)) (setq rcirc-window-configuration (current-window-configuration)) @@ -1187,7 +1209,7 @@ the of the following escape sequences replaced by the described values: :group 'rcirc) (defcustom rcirc-omit-responses - '("JOIN" "PART" "QUIT") + '("JOIN" "PART" "QUIT" "NICK") "Responses which will be hidden when `rcirc-omit-mode' is enabled." :type '(repeat string) :group 'rcirc) @@ -1281,19 +1303,50 @@ Logfiles are kept in `rcirc-log-directory'." :type 'boolean :group 'rcirc) +(defcustom rcirc-omit-threshold 100 + "Number of lines since last activity from a nick before `rcirc-omit-responses' are omitted." + :type 'integer + :group 'rcirc) + +(defun rcirc-last-quit-line (process nick target) + "Return the line number where NICK left TARGET. +Returns nil if the information is not recorded." + (let ((chanbuf (rcirc-get-buffer process target))) + (when chanbuf + (cdr (assoc-string nick (with-current-buffer chanbuf + rcirc-recent-quit-alist)))))) + +(defun rcirc-last-line (process nick target) + "Return the line from the last activity from NICK in TARGET." + (let* ((chanbuf (rcirc-get-buffer process target)) + (line (or (cdr (assoc-string target + (gethash nick (with-rcirc-server-buffer + rcirc-nick-table)) t)) + (rcirc-last-quit-line process nick target)))) + (if line + line + ;;(message "line is nil for %s in %s" nick target) + nil))) + +(defun rcirc-elapsed-lines (process nick target) + "Return the number of lines since activity from NICK in TARGET." + (let ((last-activity-line (rcirc-last-line process nick target))) + (when (and last-activity-line + (> last-activity-line 0)) + (- rcirc-current-line last-activity-line)))) + (defvar rcirc-markup-text-functions '(rcirc-markup-attributes rcirc-markup-my-nick rcirc-markup-urls rcirc-markup-keywords - rcirc-markup-bright-nicks - rcirc-markup-fill) + rcirc-markup-bright-nicks) "List of functions used to manipulate text before it is printed. -Each function takes two arguments, SENDER, RESPONSE. The buffer -is narrowed with the text to be printed and the point is at the -beginning of the `rcirc-text' propertized text.") +Each function takes two arguments, SENDER, and RESPONSE. The +buffer is narrowed with the text to be printed and the point is +at the beginning of the `rcirc-text' propertized text.") (defun rcirc-print (process sender response target text &optional activity) "Print TEXT in the buffer associated with TARGET. @@ -1305,7 +1358,8 @@ record activity." (when (string-match "^\\([^/]\\w*\\)[:,]" text) (match-string 1 text))) rcirc-ignore-list)) - (not (string= sender (rcirc-nick process)))) + ;; do not ignore if we sent the message + (not (string= sender (rcirc-nick process)))) (let* ((buffer (rcirc-target-buffer process sender response target text)) (inhibit-read-only t)) (with-current-buffer buffer @@ -1350,16 +1404,22 @@ record activity." (save-excursion (rcirc-markup-timestamp sender response)) (dolist (fn rcirc-markup-text-functions) (save-excursion (funcall fn sender response))) - (save-excursion (rcirc-markup-fill sender response))) + (when rcirc-fill-flag + (save-excursion (rcirc-markup-fill sender response)))) (when rcirc-read-only-flag (add-text-properties (point-min) (point-max) '(read-only t front-sticky t)))) ;; make text omittable - (when (and (member response rcirc-omit-responses) - (> start (point-min))) - (put-text-property (1- start) (1- rcirc-prompt-start-marker) - 'invisible 'rcirc-omit)))) + (let ((last-activity-lines (rcirc-elapsed-lines process sender target))) + (if (and (not (string= (rcirc-nick process) sender)) + (member response rcirc-omit-responses) + (or (not last-activity-lines) + (< rcirc-omit-threshold last-activity-lines))) + (put-text-property (1- start) (1- rcirc-prompt-start-marker) + 'invisible 'rcirc-omit) + ;; otherwise increment the line count + (setq rcirc-current-line (1+ rcirc-current-line)))))) (set-marker-insertion-type rcirc-prompt-start-marker nil) (set-marker-insertion-type rcirc-prompt-end-marker nil) @@ -1442,9 +1502,10 @@ Log data is written to `rcirc-log-directory'." (dolist (cell rcirc-log-alist) (with-temp-buffer (insert (cdr cell)) - (write-region (point-min) (point-max) - (concat rcirc-log-directory "/" (car cell)) - t 'quiet))) + (let ((coding-system-for-write 'utf-8)) + (write-region (point-min) (point-max) + (concat rcirc-log-directory "/" (car cell)) + t 'quiet)))) (setq rcirc-log-alist nil)) (defun rcirc-join-channels (process channels) @@ -1470,15 +1531,19 @@ Log data is written to `rcirc-log-directory'." (mapcar (lambda (x) (car x)) (gethash nick rcirc-nick-table)))) -(defun rcirc-put-nick-channel (process nick channel) - "Add CHANNEL to list associated with NICK." +(defun rcirc-put-nick-channel (process nick channel &optional line) + "Add CHANNEL to list associated with NICK. +Update the associated linestamp if LINE is non-nil. + +If the record doesn't exist, and LINE is nil, set the linestamp +to zero." (let ((nick (rcirc-user-nick nick))) (with-rcirc-process-buffer process (let* ((chans (gethash nick rcirc-nick-table)) (record (assoc-string channel chans t))) (if record - (setcdr record (current-time)) - (puthash nick (cons (cons channel (current-time)) + (when line (setcdr record line)) + (puthash nick (cons (cons channel (or line 0)) chans) rcirc-nick-table)))))) @@ -1514,7 +1579,10 @@ Log data is written to `rcirc-log-directory'." (setq nicks (cons (cons k (cdr record)) nicks))))) rcirc-nick-table) (mapcar (lambda (x) (car x)) - (sort nicks (lambda (x y) (time-less-p (cdr y) (cdr x))))))) + (sort nicks (lambda (x y) + (let ((lx (or (cdr x) 0)) + (ly (or (cdr y) 0))) + (< ly lx))))))) (list target)))) (defun rcirc-ignore-update-automatic (nick) @@ -1593,15 +1661,13 @@ Uninteresting lines are those whose responses are listed in `rcirc-omit-responses'." (interactive) (setq rcirc-omit-mode (not rcirc-omit-mode)) - (let ((line (1- (count-screen-lines (point) (window-start))))) - (if rcirc-omit-mode - (progn - (add-to-invisibility-spec 'rcirc-omit) - (message "Rcirc-Omit mode enabled")) - (remove-from-invisibility-spec 'rcirc-omit) - (message "Rcirc-Omit mode disabled")) - (recenter line)) - (force-mode-line-update)) + (if rcirc-omit-mode + (progn + (add-to-invisibility-spec '(rcirc-omit . t)) + (message "Rcirc-Omit mode enabled")) + (remove-from-invisibility-spec '(rcirc-omit . t)) + (message "Rcirc-Omit mode disabled")) + (recenter (when (> (point) rcirc-prompt-start-marker) -1))) (defun rcirc-switch-to-server-buffer () "Switch to the server buffer associated with current channel buffer." @@ -1636,7 +1702,10 @@ With prefix ARG, go to the next low priority buffer with activity." (hipri (cdr pair))) (if (or (and (not arg) hipri) (and arg lopri)) - (switch-to-buffer (car (if arg lopri hipri)) t) + (progn + (switch-to-buffer (car (if arg lopri hipri))) + (when (> (point) rcirc-prompt-start-marker) + (recenter -1))) (if (eq major-mode 'rcirc-mode) (switch-to-buffer (rcirc-non-irc-buffer)) (message (concat @@ -2169,11 +2238,13 @@ keywords when no KEYWORD is given." (let ((fill-prefix (or rcirc-fill-prefix (make-string (- (point) (line-beginning-position)) ?\s))) - (fill-column (cond ((eq rcirc-fill-column 'frame-width) - (1- (frame-width))) - (rcirc-fill-column - rcirc-fill-column) - (t fill-column)))) + (fill-column (- (cond ((eq rcirc-fill-column 'frame-width) + (1- (frame-width))) + (rcirc-fill-column + rcirc-fill-column) + (t fill-column)) + ;; make sure ... doesn't cause line wrapping + 3))) (fill-region (point) (point-max) nil t)))) ;;; handlers @@ -2183,7 +2254,6 @@ keywords when no KEYWORD is given." ;; verbatim (defun rcirc-handler-001 (process sender args text) (rcirc-handler-generic process "001" sender args text) - ;; set the real server name (with-rcirc-process-buffer process (setq rcirc-connecting nil) (rcirc-reschedule-timeout process) @@ -2201,9 +2271,9 @@ keywords when no KEYWORD is given." (if (string-match "^\C-a\\(.*\\)\C-a$" message) (rcirc-handler-CTCP process target sender (match-string 1 message)) (rcirc-print process sender "PRIVMSG" target message t)) - ;; update nick timestamp - (if (member target (rcirc-nick-channels process sender)) - (rcirc-put-nick-channel process sender target)))) + ;; update nick linestamp + (with-current-buffer (rcirc-get-buffer process target t) + (rcirc-put-nick-channel process sender target rcirc-current-line)))) (defun rcirc-handler-NOTICE (process sender args text) (let ((target (car args)) @@ -2228,21 +2298,29 @@ keywords when no KEYWORD is given." (defun rcirc-handler-JOIN (process sender args text) (let ((channel (car args))) - (rcirc-get-buffer-create process channel) + (with-current-buffer (rcirc-get-buffer-create process channel) + ;; when recently rejoining, restore the linestamp + (rcirc-put-nick-channel process sender channel + (let ((last-activity-lines + (rcirc-elapsed-lines process sender channel))) + (when (and last-activity-lines + (< last-activity-lines rcirc-omit-threshold)) + (rcirc-last-line process sender channel))))) + (rcirc-print process sender "JOIN" channel "") ;; print in private chat buffer if it exists (when (rcirc-get-buffer (rcirc-buffer-process) sender) - (rcirc-print process sender "JOIN" sender channel)) - - (rcirc-put-nick-channel process sender channel))) + (rcirc-print process sender "JOIN" sender channel)))) ;; PART and KICK are handled the same way (defun rcirc-handler-PART-or-KICK (process response channel sender nick args) (rcirc-ignore-update-automatic nick) (if (not (string= nick (rcirc-nick process))) ;; this is someone else leaving - (rcirc-remove-nick-channel process nick channel) + (progn + (rcirc-maybe-remember-nick-quit process nick channel) + (rcirc-remove-nick-channel process nick channel)) ;; this is us leaving (mapc (lambda (n) (rcirc-remove-nick-channel process n channel)) @@ -2276,16 +2354,30 @@ keywords when no KEYWORD is given." (rcirc-handler-PART-or-KICK process "KICK" channel sender nick reason))) +(defun rcirc-maybe-remember-nick-quit (process nick channel) + "Remember NICK as leaving CHANNEL if they recently spoke." + (let ((elapsed-lines (rcirc-elapsed-lines process nick channel))) + (when (and elapsed-lines + (< elapsed-lines rcirc-omit-threshold)) + (let ((buffer (rcirc-get-buffer process channel))) + (when buffer + (with-current-buffer buffer + (let ((record (assoc-string nick rcirc-recent-quit-alist t)) + (line (rcirc-last-line process nick channel))) + (if record + (setcdr record line) + (setq rcirc-recent-quit-alist + (cons (cons nick line) + rcirc-recent-quit-alist)))))))))) + (defun rcirc-handler-QUIT (process sender args text) (rcirc-ignore-update-automatic sender) (mapc (lambda (channel) - (rcirc-print process sender "QUIT" channel (apply 'concat args))) + ;; broadcast quit message each channel + (rcirc-print process sender "QUIT" channel (apply 'concat args)) + ;; record nick in quit table if they recently spoke + (rcirc-maybe-remember-nick-quit process sender channel)) (rcirc-nick-channels process sender)) - - ;; print in private chat buffer if it exists - (when (rcirc-get-buffer (rcirc-buffer-process) sender) - (rcirc-print process sender "QUIT" sender (apply 'concat args))) - (rcirc-nick-remove process sender)) (defun rcirc-handler-NICK (process sender args text) diff --git a/lisp/net/tls.el b/lisp/net/tls.el index 2e890a4a476..104cb991254 100644 --- a/lisp/net/tls.el +++ b/lisp/net/tls.el @@ -55,6 +55,29 @@ "Transport Layer Security (TLS) parameters." :group 'comm) +(defcustom tls-end-of-info + (concat + "\\(" + ;; `openssl s_client' regexp. See ssl/ssl_txt.c lines 219-220. + ;; According to apps/s_client.c line 1515 `---' is always the last + ;; line that is printed by s_client before the real data. + "^ Verify return code: .+\n---\n\\|" + ;; `gnutls' regexp. See src/cli.c lines 721-. + "^- Simple Client Mode:\n" + "\\(\n\\|" ; ignore blank lines + ;; According to GnuTLS v2.1.5 src/cli.c lines 640-650 and 705-715 + ;; in `main' the handshake will start after this message. If the + ;; handshake fails, the programs will abort. + "^\\*\\*\\* Starting TLS handshake\n\\)*" + "\\)") + "Regexp matching end of TLS client informational messages. +Client data stream begins after the last character matched by +this. The default matches `openssl s_client' (version 0.9.8c) +and `gnutls-cli' (version 2.0.1) output." + :version "22.2" + :type 'regexp + :group 'tls) + (defcustom tls-program '("gnutls-cli -p %p %h" "gnutls-cli -p %p %h --protocols ssl3" "openssl s_client -connect %h:%p -no_ssl2") @@ -130,35 +153,51 @@ Fourth arg PORT is an integer specifying a port to connect to." process cmd done) (if use-temp-buffer (setq buffer (generate-new-buffer " TLS"))) - (message "Opening TLS connection to `%s'..." host) - (while (and (not done) (setq cmd (pop cmds))) - (message "Opening TLS connection with `%s'..." cmd) - (let ((process-connection-type tls-process-connection-type) - response) - (setq process (start-process - name buffer shell-file-name shell-command-switch - (format-spec - cmd - (format-spec-make - ?h host - ?p (if (integerp port) - (int-to-string port) - port))))) - (while (and process - (memq (process-status process) '(open run)) - (save-excursion - (set-buffer buffer) ;; XXX "blue moon" nntp.el bug - (goto-char (point-min)) - (not (setq done (re-search-forward tls-success nil t))))) - (unless (accept-process-output process 1) - (sit-for 1))) - (message "Opening TLS connection with `%s'...%s" cmd - (if done "done" "failed")) - (if done - (setq done process) - (delete-process process)))) - (message "Opening TLS connection to `%s'...%s" - host (if done "done" "failed")) + (with-current-buffer buffer + (message "Opening TLS connection to `%s'..." host) + (while (and (not done) (setq cmd (pop cmds))) + (message "Opening TLS connection with `%s'..." cmd) + (let ((process-connection-type tls-process-connection-type) + response) + (setq process (start-process + name buffer shell-file-name shell-command-switch + (format-spec + cmd + (format-spec-make + ?h host + ?p (if (integerp port) + (int-to-string port) + port))))) + (while (and process + (memq (process-status process) '(open run)) + (progn + (goto-char (point-min)) + (not (setq done (re-search-forward tls-success nil t))))) + (unless (accept-process-output process 1) + (sit-for 1))) + (message "Opening TLS connection with `%s'...%s" cmd + (if done "done" "failed")) + (if (not done) + (delete-process process) + ;; advance point to after all informational messages that + ;; `openssl s_client' and `gnutls' print + (let ((start-of-data nil)) + (while + (not (setq start-of-data + ;; the string matching `tls-end-of-info' + ;; might come in separate chunks from + ;; `accept-process-output', so start the + ;; search where `tls-success' ended + (save-excursion + (if (re-search-forward tls-end-of-info nil t) + (match-end 0))))) + (accept-process-output process 1)) + (if start-of-data + ;; move point to start of client data + (goto-char start-of-data))) + (setq done process)))) + (message "Opening TLS connection to `%s'...%s" + host (if done "done" "failed"))) (when use-temp-buffer (if done (set-process-buffer process nil)) (kill-buffer buffer)) diff --git a/lisp/net/tramp-cache.el b/lisp/net/tramp-cache.el index 35147e7907c..b28c20263f4 100644 --- a/lisp/net/tramp-cache.el +++ b/lisp/net/tramp-cache.el @@ -138,42 +138,29 @@ Remove also properties of all files in subdirectories." (remhash key tramp-cache-data))) tramp-cache-data))) -(defun tramp-cache-print (table) - "Prints hash table TABLE." - (when (hash-table-p table) - (let (result) - (maphash - '(lambda (key value) - (let ((tmp (format - "(%s %s)" - (if (processp key) - (prin1-to-string (prin1-to-string key)) - (prin1-to-string key)) - (if (hash-table-p value) - (tramp-cache-print value) - (if (bufferp value) - (prin1-to-string (prin1-to-string value)) - (prin1-to-string value)))))) - (setq result (if result (concat result " " tmp) tmp)))) - table) - result))) - ;; Reverting or killing a buffer should also flush file properties. -;; They could have been changed outside Tramp. +;; They could have been changed outside Tramp. In eshell, "ls" would +;; not show proper directory contents when a file has been copied or +;; deleted before. (defun tramp-flush-file-function () "Flush all Tramp cache properties from buffer-file-name." - (let ((bfn (buffer-file-name))) - (when (and (stringp bfn) (tramp-tramp-file-p bfn)) + (let ((bfn (if (stringp (buffer-file-name)) + (buffer-file-name) + default-directory))) + (when (tramp-tramp-file-p bfn) (let* ((v (tramp-dissect-file-name bfn)) (localname (tramp-file-name-localname v))) (tramp-flush-file-property v localname))))) (add-hook 'before-revert-hook 'tramp-flush-file-function) +(add-hook 'eshell-pre-command-hook 'tramp-flush-file-function) (add-hook 'kill-buffer-hook 'tramp-flush-file-function) (add-hook 'tramp-cache-unload-hook '(lambda () (remove-hook 'before-revert-hook 'tramp-flush-file-function) + (remove-hook 'eshell-pre-command-hook + 'tramp-flush-file-function) (remove-hook 'kill-buffer-hook 'tramp-flush-file-function))) @@ -229,9 +216,38 @@ function is intended to run also as process sentinel." ; (tramp-message key 7 "%s" event) (remhash key tramp-cache-data)) +(defun tramp-cache-print (table) + "Print hash table TABLE." + (when (hash-table-p table) + (let (result) + (maphash + '(lambda (key value) + (let ((tmp (format + "(%s %s)" + (if (processp key) + (prin1-to-string (prin1-to-string key)) + (prin1-to-string key)) + (if (hash-table-p value) + (tramp-cache-print value) + (if (bufferp value) + (prin1-to-string (prin1-to-string value)) + (prin1-to-string value)))))) + (setq result (if result (concat result " " tmp) tmp)))) + table) + result))) + +(defun tramp-list-connections () + "Return a list of all known connection vectors according to `tramp-cache'." + (let (result) + (maphash + '(lambda (key value) + (when (and (vectorp key) (null (aref key 3))) + (add-to-list 'result key))) + tramp-cache-data) + result)) + (defun tramp-dump-connection-properties () -"Writes persistent connection properties into file -`tramp-persistency-file-name'." + "Write persistent connection properties into file `tramp-persistency-file-name'." ;; We shouldn't fail, otherwise (X)Emacs might not be able to be closed. (condition-case nil (when (and (hash-table-p tramp-cache-data) diff --git a/lisp/net/tramp-cmds.el b/lisp/net/tramp-cmds.el index 72e57799dc4..7cf2bf3d923 100644 --- a/lisp/net/tramp-cmds.el +++ b/lisp/net/tramp-cmds.el @@ -61,12 +61,12 @@ When called interactively, a Tramp connection has to be selected." (let ((connections (mapcar (lambda (x) - (with-current-buffer x (list (file-remote-p default-directory)))) - ;; We shall not count debug buffers, because their - ;; default-directory is random. It could be even a remote - ;; one from another connection. - (all-completions - "*tramp" (mapcar 'list (tramp-list-tramp-buffers))))) + (tramp-make-tramp-file-name + (tramp-file-name-method x) + (tramp-file-name-user x) + (tramp-file-name-host x) + (tramp-file-name-localname x))) + (tramp-list-connections))) name) (when connections @@ -125,12 +125,270 @@ This includes password cache, file cache, connection cache, buffers." (dolist (name (tramp-list-remote-buffers)) (when (bufferp (get-buffer name)) (kill-buffer name)))) +;; Tramp version is useful in a number of situations. + +(defun tramp-version (arg) + "Print version number of tramp.el in minibuffer or current buffer." + (interactive "P") + (if arg (insert tramp-version) (message tramp-version))) + +;; Make the `reporter` functionality available for making bug reports about +;; the package. A most useful piece of code. + +(autoload 'reporter-submit-bug-report "reporter") + +(defun tramp-bug () + "Submit a bug report to the Tramp developers." + (interactive) + (require 'reporter) + (catch 'dont-send + (let ((reporter-prompt-for-summary-p t)) + (reporter-submit-bug-report + tramp-bug-report-address ; to-address + (format "tramp (%s)" tramp-version) ; package name and version + (delq nil + `(;; Current state + tramp-current-method + tramp-current-user + tramp-current-host + + ;; System defaults + tramp-auto-save-directory ; vars to dump + tramp-default-method + tramp-default-method-alist + tramp-default-host + tramp-default-proxies-alist + tramp-default-user + tramp-default-user-alist + tramp-rsh-end-of-line + tramp-default-password-end-of-line + tramp-login-prompt-regexp + ;; Mask non-7bit characters + (tramp-password-prompt-regexp . tramp-reporter-dump-variable) + tramp-wrong-passwd-regexp + tramp-yesno-prompt-regexp + tramp-yn-prompt-regexp + tramp-terminal-prompt-regexp + tramp-temp-name-prefix + tramp-file-name-structure + tramp-file-name-regexp + tramp-methods + tramp-end-of-output + tramp-local-coding-commands + tramp-remote-coding-commands + tramp-actions-before-shell + tramp-actions-copy-out-of-band + tramp-terminal-type + ;; Mask non-7bit characters + (tramp-shell-prompt-pattern . tramp-reporter-dump-variable) + ,(when (boundp 'tramp-backup-directory-alist) + 'tramp-backup-directory-alist) + ,(when (boundp 'tramp-bkup-backup-directory-info) + 'tramp-bkup-backup-directory-info) + ;; Dump cache. + (tramp-cache-data . tramp-reporter-dump-variable) + + ;; Non-tramp variables of interest + ;; Mask non-7bit characters + (shell-prompt-pattern . tramp-reporter-dump-variable) + backup-by-copying + backup-by-copying-when-linked + backup-by-copying-when-mismatch + ,(when (boundp 'backup-by-copying-when-privileged-mismatch) + 'backup-by-copying-when-privileged-mismatch) + ,(when (boundp 'password-cache) + 'password-cache) + ,(when (boundp 'password-cache-expiry) + 'password-cache-expiry) + ,(when (boundp 'backup-directory-alist) + 'backup-directory-alist) + ,(when (boundp 'bkup-backup-directory-info) + 'bkup-backup-directory-info) + file-name-handler-alist)) + + 'tramp-load-report-modules ; pre-hook + 'tramp-append-tramp-buffers ; post-hook + "\ +Enter your bug report in this message, including as much detail +as you possibly can about the problem, what you did to cause it +and what the local and remote machines are. + +If you can give a simple set of instructions to make this bug +happen reliably, please include those. Thank you for helping +kill bugs in Tramp. + +Another useful thing to do is to put + + (setq tramp-verbose 8) + +in the ~/.emacs file and to repeat the bug. Then, include the +contents of the *tramp/foo* buffer and the *debug tramp/foo* +buffer in your bug report. + +--bug report follows this line-- +")))) + +(defun tramp-reporter-dump-variable (varsym mailbuf) + "Pretty-print the value of the variable in symbol VARSYM. +Used for non-7bit chars in strings." + (let* ((reporter-eval-buffer (symbol-value 'reporter-eval-buffer)) + (val (with-current-buffer reporter-eval-buffer + (symbol-value varsym)))) + + (if (hash-table-p val) + ;; Pretty print the cache. + (set varsym (read (format "(%s)" (tramp-cache-print val)))) + ;; There are characters to be masked. + (when (and (boundp 'mm-7bit-chars) + (string-match + (concat "[^" (symbol-value 'mm-7bit-chars) "]") val)) + (with-current-buffer reporter-eval-buffer + (set varsym (format "(base64-decode-string \"%s\"" + (base64-encode-string val)))))) + + ;; Dump variable. + (funcall (symbol-function 'reporter-dump-variable) varsym mailbuf) + + (unless (hash-table-p val) + ;; Remove string quotation. + (forward-line -1) + (when (looking-at + (concat "\\(^.*\\)" "\"" ;; \1 " + "\\((base64-decode-string \\)" "\\\\" ;; \2 \ + "\\(\".*\\)" "\\\\" ;; \3 \ + "\\(\")\\)" "\"$")) ;; \4 " + (replace-match "\\1\\2\\3\\4") + (beginning-of-line) + (insert " ;; variable encoded due to non-printable characters\n")) + (forward-line 1)) + + ;; Reset VARSYM to old value. + (with-current-buffer reporter-eval-buffer + (set varsym val)))) + +(defun tramp-load-report-modules () + "Load needed modules for reporting." + + ;; We load message.el and mml.el from Gnus. + (if (featurep 'xemacs) + (progn + (load "message" 'noerror) + (load "mml" 'noerror)) + (require 'message nil 'noerror) + (require 'mml nil 'noerror)) + (when (functionp 'message-mode) + (funcall (symbol-function 'message-mode))) + (when (functionp 'mml-mode) + (funcall (symbol-function 'mml-mode) t))) + +(defun tramp-append-tramp-buffers () + "Append Tramp buffers and buffer local variables into the bug report." + + (goto-char (point-max)) + + ;; Dump buffer local variables. + (dolist (buffer + (delq nil + (mapcar + '(lambda (b) + (when (string-match "\\*tramp/" (buffer-name b)) b)) + (buffer-list)))) + (let ((reporter-eval-buffer buffer) + (buffer-name (buffer-name buffer)) + (elbuf (get-buffer-create " *tmp-reporter-buffer*"))) + (with-current-buffer elbuf + (emacs-lisp-mode) + (erase-buffer) + (insert "\n(setq\n") + (lisp-indent-line) + (funcall (symbol-function 'reporter-dump-variable) + 'buffer-name (current-buffer)) + (dolist (varsym-or-cons-cell (buffer-local-variables buffer)) + (let ((varsym (or (car-safe varsym-or-cons-cell) + varsym-or-cons-cell))) + (when (string-match "tramp" (symbol-name varsym)) + (funcall + (symbol-function 'reporter-dump-variable) + varsym (current-buffer))))) + (lisp-indent-line) + (insert ")\n")) + (insert-buffer-substring elbuf))) + + ;; Append buffers only when we are in message mode. + (when (and + (eq major-mode 'message-mode) + (boundp 'mml-mode) + (symbol-value 'mml-mode)) + + (let ((tramp-buf-regexp "\\*\\(debug \\)?tramp/") + (buffer-list (funcall (symbol-function 'tramp-list-tramp-buffers))) + (curbuf (current-buffer))) + + ;; There is at least one Tramp buffer. + (when buffer-list + (switch-to-buffer (list-buffers-noselect nil)) + (delete-other-windows) + (setq buffer-read-only nil) + (goto-char (point-min)) + (while (not (eobp)) + (if (re-search-forward + tramp-buf-regexp (tramp-compat-line-end-position) t) + (forward-line 1) + (forward-line 0) + (let ((start (point))) + (forward-line 1) + (kill-region start (point))))) + (insert " +The buffer(s) above will be appended to this message. If you +don't want to append a buffer because it contains sensitive data, +or because the buffer is too large, you should delete the +respective buffer. The buffer(s) will contain user and host +names. Passwords will never be included there.") + + (when (>= tramp-verbose 6) + (insert "\n\n") + (let ((start (point))) + (insert "\ +Please note that you have set `tramp-verbose' to a value of at +least 6. Therefore, the contents of files might be included in +the debug buffer(s).") + (add-text-properties start (point) (list 'face 'italic)))) + + (set-buffer-modified-p nil) + (setq buffer-read-only t) + (goto-char (point-min)) + + (if (y-or-n-p "Do you want to append the buffer(s)? ") + ;; OK, let's send. First we delete the buffer list. + (progn + (kill-buffer nil) + (switch-to-buffer curbuf) + (goto-char (point-max)) + (insert "\n\ +This is a special notion of the `gnus/message' package. If you +use another mail agent (by copying the contents of this buffer) +please ensure that the buffers are attached to your email.\n\n") + (dolist (buffer buffer-list) + (funcall (symbol-function 'mml-insert-empty-tag) + 'part 'type "text/plain" 'encoding "base64" + 'disposition "attachment" 'buffer buffer + 'description buffer)) + (set-buffer-modified-p nil)) + + ;; Don't send. Delete the message buffer. + (set-buffer curbuf) + (set-buffer-modified-p nil) + (kill-buffer nil) + (throw 'dont-send nil)))))) + +(defalias 'tramp-submit-bug 'tramp-bug) + (provide 'tramp-cmds) ;;; TODO: ;; * Clean up unused *tramp/foo* buffers after a while. (Pete Forman) -;; * WIBNI there was an interactive command prompting for tramp +;; * WIBNI there was an interactive command prompting for Tramp ;; method, hostname, username and filename and translates the user ;; input into the correct filename syntax (depending on the Emacs ;; flavor) (Reiner Steib) diff --git a/lisp/net/tramp-fish.el b/lisp/net/tramp-fish.el index 7116d144061..95091c276bc 100644 --- a/lisp/net/tramp-fish.el +++ b/lisp/net/tramp-fish.el @@ -308,10 +308,10 @@ pass to the OPERATION." v1 'file-error "Error with add-name-to-file %s" newname))))) (defun tramp-fish-handle-copy-file - (filename newname &optional ok-if-already-exists keep-date) + (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid) "Like `copy-file' for Tramp files." (tramp-fish-do-copy-or-rename-file - 'copy filename newname ok-if-already-exists keep-date)) + 'copy filename newname ok-if-already-exists keep-date preserve-uid-gid)) (defun tramp-fish-handle-delete-directory (directory) "Like `delete-directory' for Tramp files." @@ -346,7 +346,7 @@ pass to the OPERATION." ;; Unless NAME is absolute, concat DIR and NAME. (unless (file-name-absolute-p name) (setq name (concat (file-name-as-directory dir) name))) - ;; If NAME is not a tramp file, run the real handler + ;; If NAME is not a Tramp file, run the real handler, (if (or (tramp-completion-mode-p) (not (tramp-tramp-file-p name))) (tramp-drop-volume-letter (tramp-run-real-handler 'expand-file-name (list name nil))) @@ -835,7 +835,7 @@ target of the symlink differ." ;; Internal file name functions (defun tramp-fish-do-copy-or-rename-file - (op filename newname &optional ok-if-already-exists keep-date) + (op filename newname &optional ok-if-already-exists keep-date preserve-uid-gid) "Copy or rename a remote file. OP must be `copy' or `rename' and indicates the operation to perform. FILENAME specifies the file to copy or rename, NEWNAME @@ -869,7 +869,7 @@ file names." ;; directly. ((tramp-equal-remote filename newname) (tramp-fish-do-copy-or-rename-file-directly - op filename newname keep-date)) + op filename newname keep-date preserve-uid-gid)) ;; 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 @@ -899,12 +899,13 @@ file names." (tramp-flush-file-property v (file-name-directory localname))))))) (defun tramp-fish-do-copy-or-rename-file-directly - (op filename newname keep-date) + (op filename newname keep-date preserve-uid-gid) "Invokes `COPY' or `RENAME' on the remote system. OP must be one of `copy' or `rename', indicating `cp' or `mv', respectively. VEC specifies the connection. LOCALNAME1 and LOCALNAME2 specify the two arguments of `cp' or `mv'. If -KEEP-DATE is non-nil, preserve the time stamp when copying." +KEEP-DATE is non-nil, preserve the time stamp when copying. +PRESERVE-UID-GID is completely ignored." (with-parsed-tramp-file-name filename v1 (with-parsed-tramp-file-name newname v2 (tramp-fish-send-command diff --git a/lisp/net/tramp-ftp.el b/lisp/net/tramp-ftp.el index 85416d308d3..a8b6bca44f2 100644 --- a/lisp/net/tramp-ftp.el +++ b/lisp/net/tramp-ftp.el @@ -143,10 +143,13 @@ pass to the OPERATION." ;; cannot disable the file-name-handler this case. We set the ;; connection property "started" in order to put the remote ;; location into the cache, which is helpful for further - ;; completion. + ;; completion. We don't use `with-parsed-tramp-file-name', + ;; because this returns another user but the one declared in + ;; "~/.netrc". ((memq operation '(file-directory-p file-exists-p)) (if (apply 'ange-ftp-hook-function operation args) - (with-parsed-tramp-file-name (car args) nil + (let ((v (tramp-dissect-file-name (car args) t))) + (aset v 0 tramp-ftp-method) (tramp-set-connection-property v "started" t)) nil)) ;; If the second argument of `copy-file' or `rename-file' is a diff --git a/lisp/net/tramp-smb.el b/lisp/net/tramp-smb.el index b4e68c77624..706042060f6 100644 --- a/lisp/net/tramp-smb.el +++ b/lisp/net/tramp-smb.el @@ -205,9 +205,10 @@ pass to the OPERATION." ;; File name primitives (defun tramp-smb-handle-copy-file - (filename newname &optional ok-if-already-exists keep-date) + (filename newname &optional ok-if-already-exists keep-date preserve-uid-gid) "Like `copy-file' for Tramp files. -KEEP-DATE is not handled in case NEWNAME resides on an SMB server." +KEEP-DATE is not handled in case NEWNAME resides on an SMB server. +PRESERVE-UID-GID is completely ignored." (setq filename (expand-file-name filename) newname (expand-file-name newname)) @@ -562,7 +563,14 @@ KEEP-DATE is not handled in case NEWNAME resides on an SMB server." (defun tramp-smb-handle-substitute-in-file-name (filename) "Like `handle-substitute-in-file-name' for Tramp files. -Catches errors for shares like \"C$/\", which are common in Microsoft Windows." +\"//\" substitutes only in the local filename part. Catches +errors for shares like \"C$/\", which are common in Microsoft Windows." + (with-parsed-tramp-file-name filename nil + ;; Ignore in LOCALNAME everything before "//". + (when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname)) + (setq filename + (concat (file-remote-p filename) + (replace-match "\\1" nil nil localname))))) (condition-case nil (tramp-run-real-handler 'substitute-in-file-name (list filename)) (error filename))) @@ -574,7 +582,7 @@ Catches errors for shares like \"C$/\", which are common in Microsoft Windows." (with-parsed-tramp-file-name filename nil (unless (eq append nil) (tramp-error - v 'file-error "Cannot append to file using tramp (`%s')" filename)) + v 'file-error "Cannot append to file using Tramp (`%s')" filename)) ;; XEmacs takes a coding system as the seventh argument, not `confirm'. (when (and (not (featurep 'xemacs)) confirm (file-exists-p filename)) @@ -582,7 +590,7 @@ Catches errors for shares like \"C$/\", which are common in Microsoft Windows." filename)) (tramp-error v 'file-error "File not overwritten"))) ;; We must also flush the cache of the directory, because - ;; file-attributes reads the values from there. + ;; `file-attributes' reads the values from there. (tramp-flush-file-property v (file-name-directory localname)) (tramp-flush-file-property v localname) (let ((file (tramp-smb-get-localname localname t)) @@ -1004,8 +1012,6 @@ Returns nil if an error message has appeared." ;; * Return more comprehensive file permission string. Think whether it is ;; possible to implement `set-file-modes'. ;; * Handle links (FILENAME.LNK). -;; * Maybe local tmp files should have the same extension like the original -;; files. Strange behaviour with jka-compr otherwise? ;; * Try to remove the inclusion of dummy "" directory. Seems to be at ;; several places, especially in `tramp-smb-handle-insert-directory'. ;; * (RMS) Use unwind-protect to clean up the state so as to make the state diff --git a/lisp/net/tramp.el b/lisp/net/tramp.el index b54641b311e..93fdea9ab27 100644 --- a/lisp/net/tramp.el +++ b/lisp/net/tramp.el @@ -93,7 +93,6 @@ (autoload 'tramp-set-file-property "tramp-cache") (autoload 'tramp-flush-file-property "tramp-cache") (autoload 'tramp-flush-directory-property "tramp-cache") -(autoload 'tramp-cache-print "tramp-cache") (autoload 'tramp-get-connection-property "tramp-cache") (autoload 'tramp-set-connection-property "tramp-cache") (autoload 'tramp-flush-connection-property "tramp-cache") @@ -560,7 +559,7 @@ pair of the form (KEY VALUE). The following KEYs are defined: * `tramp-remote-sh' This specifies the Bourne shell to use on the remote host. This MUST be a Bourne-like shell. It is normally not necessary to set - this to any value other than \"/bin/sh\": tramp wants to use a shell + this to any value other than \"/bin/sh\": Tramp wants to use a shell which groks tilde expansion, but it can search for it. Also note that \"/bin/sh\" exists on all Unixen, this might not be true for the value that you decide to use. You Have Been Warned. @@ -972,7 +971,7 @@ The `sudo' program appears to insert a `^@' character into the prompt." (defcustom tramp-wrong-passwd-regexp (concat "^.*" ;; These strings should be on the last line - (regexp-opt '("Permission denied." + (regexp-opt '("Permission denied" "Login incorrect" "Login Incorrect" "Connection refused" @@ -1117,12 +1116,12 @@ It can have the following values: ((equal tramp-syntax 'sep) "/[") ((equal tramp-syntax 'url) "/") (t (error "Wrong `tramp-syntax' defined"))) - "*String matching the very beginning of tramp file names. + "*String matching the very beginning of Tramp file names. Used in `tramp-make-tramp-file-name'.") (defconst tramp-prefix-regexp (concat "^" (regexp-quote tramp-prefix-format)) - "*Regexp matching the very beginning of tramp file names. + "*Regexp matching the very beginning of Tramp file names. Should always start with \"^\". Derived from `tramp-prefix-format'.") (defconst tramp-method-regexp @@ -1214,9 +1213,9 @@ Derived from `tramp-postfix-host-format'.") 2 4 5 7) "*List of five elements (REGEXP METHOD USER HOST FILE), detailing \ -the tramp file name structure. +the Tramp file name structure. -The first element REGEXP is a regular expression matching a tramp file +The first element REGEXP is a regular expression matching a Tramp file name. The regex should contain parentheses around the method name, the user name, the host name, and the file name parts. @@ -1256,11 +1255,11 @@ See `tramp-file-name-structure' for more explanations.") ((equal tramp-syntax 'url) tramp-file-name-regexp-url) (t (error "Wrong `tramp-syntax' defined"))) "*Regular expression matching file names handled by Tramp. -This regexp should match tramp file names but no other file names. +This regexp should match Tramp file names but no other file names. \(When tramp.el is loaded, this regular expression is prepended to `file-name-handler-alist', and that is searched sequentially. Thus, -if the tramp entry appears rather early in the `file-name-handler-alist' -and is a bit too general, then some files might be considered tramp +if the Tramp entry appears rather early in the `file-name-handler-alist' +and is a bit too general, then some files might be considered Tramp files which are not really Tramp files. Please note that the entry in `file-name-handler-alist' is made when @@ -1302,8 +1301,8 @@ See `tramp-file-name-structure' for more explanations.") ((equal tramp-syntax 'sep) tramp-completion-file-name-regexp-separate) ((equal tramp-syntax 'url) tramp-completion-file-name-regexp-url) (t (error "Wrong `tramp-syntax' defined"))) - "*Regular expression matching file names handled by tramp completion. -This regexp should match partial tramp file names only. + "*Regular expression matching file names handled by Tramp completion. +This regexp should match partial Tramp file names only. Please note that the entry in `file-name-handler-alist' is made when this file (tramp.el) is loaded. This means that this variable must be set @@ -1752,7 +1751,7 @@ This is used to map a mode number to a permission string.") "Alist of handler functions. Operations not mentioned here will be handled by the normal Emacs functions.") -;; Handlers for partial tramp file names. For Emacs just +;; Handlers for partial Tramp file names. For Emacs just ;; `file-name-all-completions' is needed. ;;;###autoload (defconst tramp-completion-file-name-handler-alist @@ -1815,7 +1814,7 @@ ARGS to actually emit the message (if applicable)." (defsubst tramp-message (vec-or-proc level fmt-string &rest args) "Emit a message depending on verbosity level. -VEC-OR-PROC identifies the tramp buffer to use. It can be either a +VEC-OR-PROC identifies the Tramp buffer to use. It can be either a vector or a process. LEVEL says to be quiet if `tramp-verbose' is less than LEVEL. The message is emitted only if `tramp-verbose' is greater than or equal to LEVEL. @@ -1966,7 +1965,8 @@ Return the local name of the temporary file." (tramp-file-name-method vec) (tramp-file-name-user vec) (tramp-file-name-host vec) - (expand-file-name tramp-temp-name-prefix "/tmp"))) + (expand-file-name + tramp-temp-name-prefix (tramp-get-remote-tmpdir vec)))) result) (while (not result) ;; `make-temp-file' would be the natural choice for @@ -2017,7 +2017,9 @@ Example: (if (string-match "^HKEY_CURRENT_USER" (nth 1 (car v))) ;; Windows registry. (and (memq system-type '(cygwin windows-nt)) - (zerop (call-process "reg" nil nil nil "query" (nth 1 (car v))))) + (zerop + (tramp-local-call-process + "reg" nil nil nil "query" (nth 1 (car v))))) ;; Configuration file. (file-exists-p (nth 1 (car v))))) (setq r (delete (car v) r))) @@ -2163,7 +2165,7 @@ target of the symlink differ." (unless nomessage (tramp-message v 0 "Loading %s...done" file)) t))) -;; Localname manipulation functions that grok TRAMP localnames... +;; Localname manipulation functions that grok Tramp localnames... (defun tramp-handle-file-name-directory (file) "Like `file-name-directory' but aware of Tramp files." ;; Everything except the last filename thing is the directory. We @@ -2548,7 +2550,7 @@ of." ;; We handle also the local part, because in older Emacsen, ;; without `set-file-times', this function is an alias for this. ;; We are local, so we don't need the UTC settings. - (call-process + (tramp-local-call-process "touch" nil nil nil "-t" (format-time-string "%Y%m%d%H%M.%S" time) (tramp-shell-quote-argument filename))))) @@ -2573,16 +2575,12 @@ and gid of the corresponding user is taken. Both parameters must be integers." (tramp-shell-quote-argument localname))))) ;; We handle also the local part, because there doesn't exist - ;; `set-file-uid-gid'. + ;; `set-file-uid-gid'. On Win32 "chown" might not work. (let ((uid (or (and (integerp uid) uid) (tramp-get-local-uid 'integer))) - (gid (or (and (integerp gid) gid) (tramp-get-local-gid 'integer))) - (default-directory (tramp-compat-temporary-file-directory))) - ;; "chown" might not exist, for example on Win32. - (condition-case nil - (call-process - "chown" nil nil nil - (format "%d:%d" uid gid) (tramp-shell-quote-argument filename)) - (error nil))))) + (gid (or (and (integerp gid) gid) (tramp-get-local-gid 'integer)))) + (tramp-local-call-process + "chown" nil nil nil + (format "%d:%d" uid gid) (tramp-shell-quote-argument filename))))) ;; Simple functions using the `test' command. @@ -2897,7 +2895,7 @@ and gid of the corresponding user is taken. Both parameters must be integers." (setq filename (expand-file-name filename)) (setq newname (expand-file-name newname)) (cond - ;; At least one file a tramp file? + ;; At least one file a Tramp file? ((or (tramp-tramp-file-p filename) (tramp-tramp-file-p newname)) (tramp-do-copy-or-rename-file @@ -2915,10 +2913,10 @@ and gid of the corresponding user is taken. Both parameters must be integers." (filename newname &optional ok-if-already-exists) "Like `rename-file' for Tramp files." ;; Check if both files are local -- invoke normal rename-file. - ;; Otherwise, use tramp from local system. + ;; Otherwise, use Tramp from local system. (setq filename (expand-file-name filename)) (setq newname (expand-file-name newname)) - ;; At least one file a tramp file? + ;; At least one file a Tramp file? (if (or (tramp-tramp-file-p filename) (tramp-tramp-file-p newname)) (tramp-do-copy-or-rename-file @@ -3309,7 +3307,7 @@ be a local filename. The method used must be an out-of-band method." ;; Dired. ;; CCC: This does not seem to be enough. Something dies when -;; we try and delete two directories under TRAMP :/ +;; we try and delete two directories under Tramp :/ (defun tramp-handle-dired-recursive-delete-directory (filename) "Recursively delete the directory given. This is like `dired-recursive-delete-directory' for Tramp files." @@ -3455,7 +3453,7 @@ This is like `dired-recursive-delete-directory' for Tramp files." "" (tramp-shell-quote-argument (file-name-nondirectory localname)))))) - ;; We cannot use `insert-buffer-substring' because the tramp buffer + ;; We cannot use `insert-buffer-substring' because the Tramp buffer ;; changes its contents before insertion due to calling ;; `expand-file' and alike. (insert @@ -3563,8 +3561,8 @@ beginning of local filename are not substituted." ;; Ignore in LOCALNAME everything before "//" or "/~". (when (and (stringp localname) (string-match ".+?/\\(/\\|~\\)" localname)) (setq filename - (tramp-make-tramp-file-name - method user host (replace-match "\\1" nil nil localname))) + (concat (file-remote-p filename) + (replace-match "\\1" nil nil localname))) ;; "/m:h:~" does not work for completion. We use "/m:h:~/". (when (string-match "~$" filename) (setq filename (concat filename "/")))) @@ -3729,6 +3727,20 @@ beginning of local filename are not substituted." ;; Return exit status. ret))) +(defun tramp-local-call-process + (program &optional infile destination display &rest args) + "Calls `call-process' on the local host. +This is needed because for some Emacs flavors Tramp has +defadviced `call-process' to behave like `process-file'. The +Lisp error raised when PROGRAM is nil is trapped also, returning 1." + (let ((default-directory + (if (file-remote-p default-directory) + (tramp-compat-temporary-file-directory) + default-directory))) + (if (executable-find program) + (apply 'call-process program infile destination display args) + 1))) + (defun tramp-handle-call-process-region (start end program &optional delete buffer display &rest args) "Like `call-process-region' for Tramp files." @@ -3764,19 +3776,14 @@ beginning of local filename are not substituted." output-buffer))) (prog1 - ;; Run the process. We cannot use `process-file' and - ;; `start-file-process', because these functions might not - ;; exist in older Emacsen. + ;; Run the process. (if (integerp asynchronous) - (apply 'tramp-handle-start-file-process - "*Async Shell*" buffer args) - (apply 'process-file - (car args) nil buffer nil (cdr args))) + (apply 'start-file-process "*Async Shell*" buffer args) + (apply 'process-file (car args) nil buffer nil (cdr args))) ;; Insert error messages if they were separated. (when (listp buffer) - (with-current-buffer error-buffer - (insert-file-contents (cadr buffer))) - (delete-file (buffer-file-name (cadr buffer)))) + (with-current-buffer error-buffer (insert-file-contents (cadr buffer))) + (delete-file (cadr buffer))) ;; There's some output, display it. (when (with-current-buffer output-buffer (> (point-max) (point-min))) (if (functionp 'display-message-or-buffer) @@ -4052,9 +4059,9 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file." (unless (y-or-n-p (format "File %s exists; overwrite anyway? " filename)) (tramp-error v 'file-error "File not overwritten"))) - (let ((uid (or (nth 2 (file-attributes filename 'integer)) + (let ((uid (or (nth 2 (tramp-compat-file-attributes filename 'integer)) (tramp-get-remote-uid v 'integer))) - (gid (or (nth 3 (file-attributes filename 'integer)) + (gid (or (nth 3 (tramp-compat-file-attributes filename 'integer)) (tramp-get-remote-gid v 'integer)))) (if (and (tramp-local-host-p v) @@ -4173,17 +4180,15 @@ Returns a file name in `tramp-auto-save-directory' for autosaving this file." (when file-precious-flag (erase-buffer) (and - ;; cksum runs locally - (let ((default-directory - (tramp-compat-temporary-file-directory))) - (zerop (call-process "cksum" tmpfile t))) - ;; cksum runs remotely + ;; cksum runs locally, if possible. + (zerop (tramp-local-call-process "cksum" tmpfile t)) + ;; cksum runs remotely. (zerop (tramp-send-command-and-check v (format "cksum <%s" (tramp-shell-quote-argument localname)))) - ;; ... they are different + ;; ... they are different. (not (string-equal (buffer-string) @@ -4367,7 +4372,7 @@ ARGS are the arguments OPERATION has been called with." ;;;###autoload (defun tramp-file-name-handler (operation &rest args) "Invoke Tramp file name handler. -Falls back to normal file name handler if no tramp file name handler exists." +Falls back to normal file name handler if no Tramp file name handler exists." (save-match-data (let* ((filename (apply 'tramp-file-name-for-operation operation args)) (completion (tramp-completion-mode-p)) @@ -4433,8 +4438,8 @@ Fall back to normal file name handler if no Tramp handler exists." ;;;###autoload (progn (defun tramp-completion-file-name-handler (operation &rest args) - "Invoke tramp file name completion handler. -Falls back to normal file name handler if no tramp file name handler exists." + "Invoke Tramp file name completion handler. +Falls back to normal file name handler if no Tramp file name handler exists." ;; (setq edebug-trace t) ;; (edebug-trace "%s" (with-output-to-string (backtrace))) @@ -4449,7 +4454,7 @@ Falls back to normal file name handler if no tramp file name handler exists." ;;;###autoload (defsubst tramp-register-file-name-handler () - "Add tramp file name handler to `file-name-handler-alist'." + "Add Tramp file name handler to `file-name-handler-alist'." ;; Remove autoloaded handler from file name handler alist. Useful, ;; if `tramp-syntax' has been changed. (let ((a1 (rassq 'tramp-file-name-handler file-name-handler-alist))) @@ -4472,7 +4477,7 @@ Falls back to normal file name handler if no tramp file name handler exists." ;;;###autoload (defsubst tramp-register-completion-file-name-handler () - "Add tramp completion file name handler to `file-name-handler-alist'." + "Add Tramp completion file name handler to `file-name-handler-alist'." ;; Remove autoloaded handler from file name handler alist. Useful, ;; if `tramp-syntax' has been changed. (let ((a1 (rassq @@ -4535,8 +4540,8 @@ should never be set globally, the intention is to let-bind it.") ;; risky, because completing a file might require loading other files, ;; like "~/.netrc", and for them it shouldn't be decided based on that ;; variable. On the other hand, those files 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 +;; 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 ... (defun tramp-completion-mode-p () "Checks whether method / user name / host name completion is active." @@ -5037,7 +5042,7 @@ User is always nil." (let ((default-directory (tramp-compat-temporary-file-directory)) res) (with-temp-buffer - (when (zerop (call-process "reg" nil t nil "query" registry)) + (when (zerop (tramp-local-call-process "reg" nil t nil "query" registry)) (goto-char (point-min)) (while (not (eobp)) (push (tramp-parse-putty-group registry) res)))) @@ -5331,11 +5336,11 @@ file exists and nonzero exit status otherwise." (when extra-args (setq shell (concat shell " " extra-args)))) (tramp-message vec 5 "Starting remote shell `%s' for tilde expansion..." shell) - (tramp-message - vec 6 (format "PROMPT_COMMAND='' PS1='$ ' exec %s" shell)) - ;; We just send a string only without checking resulting prompt. - (tramp-send-string - vec (format "PROMPT_COMMAND='' PS1='$ ' exec %s" shell)) + (let ((tramp-end-of-output "$ ")) + (tramp-send-command + vec + (format "PROMPT_COMMAND='' PS1='$ ' PS2='' PS3='' exec %s" shell) + t)) (tramp-message vec 5 "Setting remote shell prompt...") ;; Douglas Gray Stephens <DGrayStephens@slb.com> says that we ;; must use "\n" here, not tramp-rsh-end-of-line. Kai left the @@ -5611,16 +5616,14 @@ process to set up. VEC specifies the connection." ;; called as sh) on startup; this way, we avoid the startup file ;; clobbering $PS1. $PROMP_COMMAND is another way to set the prompt ;; in /bin/bash, it must be discarded as well. - (tramp-message - vec 6 (format "exec env 'ENV=' 'PROMPT_COMMAND=' 'PS1=$ ' %s" - (tramp-get-method-parameter - (tramp-file-name-method vec) 'tramp-remote-sh))) - ;; We just send a string only without checking resulting prompt. - (tramp-send-string - vec - (format "exec env 'ENV=' 'PROMPT_COMMAND=' 'PS1=$ ' %s" - (tramp-get-method-parameter - (tramp-file-name-method vec) 'tramp-remote-sh))) + (let ((tramp-end-of-output "$ ")) + (tramp-send-command + vec + (format + "exec env 'ENV=' 'PROMPT_COMMAND=' 'PS1=$ ' PS2='' PS3='' %s" + (tramp-get-method-parameter + (tramp-file-name-method vec) 'tramp-remote-sh)) + t)) (tramp-message vec 5 "Setting shell prompt") ;; Douglas Gray Stephens <DGrayStephens@slb.com> says that we must ;; use "\n" here, not tramp-rsh-end-of-line. @@ -5631,6 +5634,12 @@ process to set up. VEC specifies the connection." tramp-end-of-output tramp-rsh-end-of-line) t) + ;; If the connection buffer is not empty, the remote shell is + ;; echoing, and the prompt has been detected through the echoed + ;; command. We must reread for the real prompt. + (with-current-buffer (process-buffer proc) + (when (> (point-max) (point-min)) (tramp-wait-for-output proc))) + ;; Disable echo. (tramp-message vec 5 "Setting up remote shell environment") (tramp-send-command vec "stty -inlcr -echo kill '^U' erase '^H'" t) ;; Check whether the echo has really been disabled. Some @@ -5906,18 +5915,15 @@ INPUT can also be nil which means `/dev/null'. OUTPUT can be a string (which specifies a filename), or t (which means standard output and thus the current buffer), or nil (which means discard it)." - (let ((default-directory (tramp-compat-temporary-file-directory))) - (call-process - tramp-encoding-shell ;program - (when (and input (not (string-match "%s" cmd))) - input) ;input - (if (eq output t) t nil) ;output - nil ;redisplay - tramp-encoding-command-switch - ;; actual shell command - (concat - (if (string-match "%s" cmd) (format cmd input) cmd) - (if (stringp output) (concat "> " output) ""))))) + (tramp-local-call-process + tramp-encoding-shell + (when (and input (not (string-match "%s" cmd))) input) + (if (eq output t) t nil) + nil + tramp-encoding-command-switch + (concat + (if (string-match "%s" cmd) (format cmd input) cmd) + (if (stringp output) (concat "> " output) "")))) (defun tramp-compute-multi-hops (vec) "Expands VEC according to `tramp-default-proxies-alist'. @@ -6014,7 +6020,8 @@ Gateway hops are already opened." "Maybe open a connection VEC. 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 (tramp-get-connection-process vec))) + (let ((p (tramp-get-connection-process vec)) + (process-environment (copy-sequence process-environment))) ;; If too much time has passed since last command was sent, look ;; whether process is still alive. If it isn't, kill it. When @@ -6062,10 +6069,10 @@ connection if a previous connection has died for some reason." (when (and p (processp p)) (delete-process p)) (setenv "TERM" tramp-terminal-type) + (setenv "LC_ALL" "C") (setenv "PROMPT_COMMAND") (setenv "PS1" "$ ") (let* ((target-alist (tramp-compute-multi-hops vec)) - (process-environment (copy-sequence process-environment)) (process-connection-type tramp-process-connection-type) (process-adaptive-read-buffering nil) (coding-system-for-read nil) @@ -6197,7 +6204,9 @@ function waits for output unless NOOUTPUT is set." (let ((found (tramp-wait-for-regexp proc timeout - (format "^%s\r?$" (regexp-quote tramp-end-of-output))))) + ;; Initially, `tramp-end-of-output' is "$ ". There might + ;; be leading escape sequences, which must be ignored. + (format "^[^$\n]*%s\r?$" (regexp-quote tramp-end-of-output))))) (if found (let (buffer-read-only) (goto-char (point-max)) @@ -6514,7 +6523,7 @@ Not actually used. Use `(format \"%o\" i)' instead?" ;; ------------------------------------------------------------ -;; -- TRAMP file names -- +;; -- Tramp file names -- ;; ------------------------------------------------------------ ;; Conversion functions between external representation and ;; internal data structure. Convenience functions for internal @@ -6558,7 +6567,7 @@ Not actually used. Use `(format \"%o\" i)' instead?" (string-to-number (match-string 2 host))))) (defun tramp-tramp-file-p (name) - "Return t if NAME is a tramp file." + "Return t if NAME is a Tramp file." (save-match-data (string-match tramp-file-name-regexp name))) @@ -6608,7 +6617,7 @@ non-nil, the file name parts are not expanded to their default values." (save-match-data (let ((match (string-match (nth 0 tramp-file-name-structure) name))) - (unless match (error "Not a tramp file name: %s" name)) + (unless match (error "Not a Tramp file name: %s" name)) (let ((method (match-string (nth 1 tramp-file-name-structure) name)) (user (match-string (nth 2 tramp-file-name-structure) name)) (host (match-string (nth 3 tramp-file-name-structure) name)) @@ -6726,6 +6735,18 @@ necessary only. This function will be used in file name completion." x)) remote-path))))) +(defun tramp-get-remote-tmpdir (vec) + (with-connection-property vec "tmp-directory" + (let ((dir (tramp-shell-quote-argument "/tmp"))) + (if (and (zerop + (tramp-send-command-and-check + vec (format "%s -d %s" (tramp-get-test-command vec) dir))) + (zerop + (tramp-send-command-and-check + vec (format "%s -w %s" (tramp-get-test-command vec) dir)))) + dir + (tramp-error vec 'file-error "Directory %s not accessible" dir))))) + (defun tramp-get-ls-command (vec) (with-connection-property vec "ls" (with-current-buffer (tramp-get-buffer vec) @@ -7161,265 +7182,6 @@ Only works for Bourne-like shells." (add-hook 'tramp-unload-hook '(lambda () (ad-unadvise 'file-expand-wildcards)))) -;; Tramp version is useful in a number of situations. - -(defun tramp-version (arg) - "Print version number of tramp.el in minibuffer or current buffer." - (interactive "P") - (if arg (insert tramp-version) (message tramp-version))) - -;; Make the `reporter` functionality available for making bug reports about -;; the package. A most useful piece of code. - -(unless (fboundp 'reporter-submit-bug-report) - (autoload 'reporter-submit-bug-report "reporter")) - -(defun tramp-bug () - "Submit a bug report to the TRAMP developers." - (interactive) - (require 'reporter) - (catch 'dont-send - (let ((reporter-prompt-for-summary-p t)) - (reporter-submit-bug-report - tramp-bug-report-address ; to-address - (format "tramp (%s)" tramp-version) ; package name and version - (delq nil - `(;; Current state - tramp-current-method - tramp-current-user - tramp-current-host - - ;; System defaults - tramp-auto-save-directory ; vars to dump - tramp-default-method - tramp-default-method-alist - tramp-default-host - tramp-default-proxies-alist - tramp-default-user - tramp-default-user-alist - tramp-rsh-end-of-line - tramp-default-password-end-of-line - tramp-login-prompt-regexp - ;; Mask non-7bit characters - (tramp-password-prompt-regexp . tramp-reporter-dump-variable) - tramp-wrong-passwd-regexp - tramp-yesno-prompt-regexp - tramp-yn-prompt-regexp - tramp-terminal-prompt-regexp - tramp-temp-name-prefix - tramp-file-name-structure - tramp-file-name-regexp - tramp-methods - tramp-end-of-output - tramp-local-coding-commands - tramp-remote-coding-commands - tramp-actions-before-shell - tramp-actions-copy-out-of-band - tramp-terminal-type - ;; Mask non-7bit characters - (tramp-shell-prompt-pattern . tramp-reporter-dump-variable) - ,(when (boundp 'tramp-backup-directory-alist) - 'tramp-backup-directory-alist) - ,(when (boundp 'tramp-bkup-backup-directory-info) - 'tramp-bkup-backup-directory-info) - ;; Dump cache. - (tramp-cache-data . tramp-reporter-dump-variable) - - ;; Non-tramp variables of interest - ;; Mask non-7bit characters - (shell-prompt-pattern . tramp-reporter-dump-variable) - backup-by-copying - backup-by-copying-when-linked - backup-by-copying-when-mismatch - ,(when (boundp 'backup-by-copying-when-privileged-mismatch) - 'backup-by-copying-when-privileged-mismatch) - ,(when (boundp 'password-cache) - 'password-cache) - ,(when (boundp 'password-cache-expiry) - 'password-cache-expiry) - ,(when (boundp 'backup-directory-alist) - 'backup-directory-alist) - ,(when (boundp 'bkup-backup-directory-info) - 'bkup-backup-directory-info) - file-name-handler-alist)) - - 'tramp-load-report-modules ; pre-hook - 'tramp-append-tramp-buffers ; post-hook - "\ -Enter your bug report in this message, including as much detail -as you possibly can about the problem, what you did to cause it -and what the local and remote machines are. - -If you can give a simple set of instructions to make this bug -happen reliably, please include those. Thank you for helping -kill bugs in Tramp. - -Another useful thing to do is to put - - (setq tramp-verbose 8) - -in the ~/.emacs file and to repeat the bug. Then, include the -contents of the *tramp/foo* buffer and the *debug tramp/foo* -buffer in your bug report. - ---bug report follows this line-- -")))) - -(defun tramp-reporter-dump-variable (varsym mailbuf) - "Pretty-print the value of the variable in symbol VARSYM. -Used for non-7bit chars in strings." - (let* ((reporter-eval-buffer (symbol-value 'reporter-eval-buffer)) - (val (with-current-buffer reporter-eval-buffer - (symbol-value varsym)))) - - (if (hash-table-p val) - ;; Pretty print the cache. - (set varsym (read (format "(%s)" (tramp-cache-print val)))) - ;; There are characters to be masked. - (when (and (boundp 'mm-7bit-chars) - (string-match - (concat "[^" (symbol-value 'mm-7bit-chars) "]") val)) - (with-current-buffer reporter-eval-buffer - (set varsym (format "(base64-decode-string \"%s\"" - (base64-encode-string val)))))) - - ;; Dump variable. - (funcall (symbol-function 'reporter-dump-variable) varsym mailbuf) - - (unless (hash-table-p val) - ;; Remove string quotation. - (forward-line -1) - (when (looking-at - (concat "\\(^.*\\)" "\"" ;; \1 " - "\\((base64-decode-string \\)" "\\\\" ;; \2 \ - "\\(\".*\\)" "\\\\" ;; \3 \ - "\\(\")\\)" "\"$")) ;; \4 " - (replace-match "\\1\\2\\3\\4") - (beginning-of-line) - (insert " ;; variable encoded due to non-printable characters\n")) - (forward-line 1)) - - ;; Reset VARSYM to old value. - (with-current-buffer reporter-eval-buffer - (set varsym val)))) - -(defun tramp-load-report-modules () - "Load needed modules for reporting." - - ;; We load message.el and mml.el from Gnus. - (if (featurep 'xemacs) - (progn - (load "message" 'noerror) - (load "mml" 'noerror)) - (require 'message nil 'noerror) - (require 'mml nil 'noerror)) - (when (functionp 'message-mode) - (funcall (symbol-function 'message-mode))) - (when (functionp 'mml-mode) - (funcall (symbol-function 'mml-mode) t))) - -(defun tramp-append-tramp-buffers () - "Append Tramp buffers and buffer local variables into the bug report." - - (goto-char (point-max)) - - ;; Dump buffer local variables. - (dolist (buffer - (delq nil - (mapcar - '(lambda (b) - (when (string-match "\\*tramp/" (buffer-name b)) b)) - (buffer-list)))) - (let ((reporter-eval-buffer buffer) - (buffer-name (buffer-name buffer)) - (elbuf (get-buffer-create " *tmp-reporter-buffer*"))) - (with-current-buffer elbuf - (emacs-lisp-mode) - (erase-buffer) - (insert "\n(setq\n") - (lisp-indent-line) - (funcall (symbol-function 'reporter-dump-variable) - 'buffer-name (current-buffer)) - (dolist (varsym-or-cons-cell (buffer-local-variables buffer)) - (let ((varsym (or (car-safe varsym-or-cons-cell) - varsym-or-cons-cell))) - (when (string-match "tramp" (symbol-name varsym)) - (funcall - (symbol-function 'reporter-dump-variable) - varsym (current-buffer))))) - (lisp-indent-line) - (insert ")\n")) - (insert-buffer-substring elbuf))) - - ;; Append buffers only when we are in message mode. - (when (and - (eq major-mode 'message-mode) - (boundp 'mml-mode) - (symbol-value 'mml-mode)) - - (let ((tramp-buf-regexp "\\*\\(debug \\)?tramp/") - (buffer-list (funcall (symbol-function 'tramp-list-tramp-buffers))) - (curbuf (current-buffer))) - - ;; There is at least one Tramp buffer. - (when buffer-list - (switch-to-buffer (list-buffers-noselect nil)) - (delete-other-windows) - (setq buffer-read-only nil) - (goto-char (point-min)) - (while (not (eobp)) - (if (re-search-forward - tramp-buf-regexp (tramp-compat-line-end-position) t) - (forward-line 1) - (forward-line 0) - (let ((start (point))) - (forward-line 1) - (kill-region start (point))))) - (insert " -The buffer(s) above will be appended to this message. If you -don't want to append a buffer because it contains sensitive data, -or because the buffer is too large, you should delete the -respective buffer. The buffer(s) will contain user and host -names. Passwords will never be included there.") - - (when (>= tramp-verbose 6) - (insert "\n\n") - (let ((start (point))) - (insert "\ -Please note that you have set `tramp-verbose' to a value of at -least 6. Therefore, the contents of files might be included in -the debug buffer(s).") - (add-text-properties start (point) (list 'face 'italic)))) - - (set-buffer-modified-p nil) - (setq buffer-read-only t) - (goto-char (point-min)) - - (if (y-or-n-p "Do you want to append the buffer(s)? ") - ;; OK, let's send. First we delete the buffer list. - (progn - (kill-buffer nil) - (switch-to-buffer curbuf) - (goto-char (point-max)) - (insert "\n\ -This is a special notion of the `gnus/message' package. If you -use another mail agent (by copying the contents of this buffer) -please ensure that the buffers are attached to your email.\n\n") - (dolist (buffer buffer-list) - (funcall (symbol-function 'mml-insert-empty-tag) - 'part 'type "text/plain" 'encoding "base64" - 'disposition "attachment" 'buffer buffer - 'description buffer)) - (set-buffer-modified-p nil)) - - ;; Don't send. Delete the message buffer. - (set-buffer curbuf) - (set-buffer-modified-p nil) - (kill-buffer nil) - (throw 'dont-send nil)))))) - -(defalias 'tramp-submit-bug 'tramp-bug) - ;; Checklist for `tramp-unload-hook' ;; - Unload all `tramp-*' packages ;; - Reset `file-name-handler-alist' @@ -7521,7 +7283,7 @@ please ensure that the buffers are attached to your email.\n\n") ;; having the possibility of passing a local file there to a local ;; Emacs session (in case I can arrange for a connection back) would ;; be nice. -;; Likely the corresponding tramp server should not allow the +;; Likely the corresponding Tramp server should not allow the ;; equivalent of the emacsclient -eval option in order to make this ;; reasonably unproblematic. And maybe trampclient should have some ;; way of passing credentials, like by using an SSL socket or |