home *** CD-ROM | disk | FTP | other *** search
- ;; Allows GNUS to make posts in the background (via a second NNTP connection.)
- ;; By Jamie Zawinski <jwz@lucid.com> 6-jun-93
- ;; Copyright (C) 1993 Free Software Foundation, Inc.
-
- ;; This file is part of XEmacs.
-
- ;; XEmacs is free software; you can redistribute it and/or modify it
- ;; under the terms of the GNU General Public License as published by
- ;; the Free Software Foundation; either version 2, or (at your option)
- ;; any later version.
-
- ;; XEmacs is distributed in the hope that it will be useful, but
- ;; WITHOUT ANY WARRANTY; without even the implied warranty of
- ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- ;; General Public License for more details.
-
- ;; You should have received a copy of the GNU General Public License
- ;; along with XEmacs; see the file COPYING. If not, write to the Free
- ;; Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;; This makes it possible for GNUS to post new articles by opening a second
- ;; (or third, or fourth...) NNTP connection and posting on that asynchronously,
- ;; instead of tying up the primary NNTP connection until the post completes.
- ;; This is nice because on some servers, posting a new article takes an
- ;; obscenely long time. Drawbacks of using this are slightly less feedback
- ;; about whether your post has succeeded (you might exit emacs before you got
- ;; to see the diagnostics) and that opening these subsequent connections uses
- ;; more resources on the NNTP server (and I suppose some servers might limit
- ;; the number of connections as well.)
- ;;
- ;; It would be nice if, instead of having to decide whether to post in the
- ;; foreground or background up front, we could arrange so that ^G during a
- ;; foreground post turned it into a background post (the zmacs mailer did
- ;; this, it was swell) but that's hard, because by the time a foreground post
- ;; has begun, the primary nntp connection is already wedged. To do this, we'd
- ;; have to make the primary connection be the posting connection (the one that
- ;; will get nuked when the post completes) and install a new primary
- ;; connection. Actually I guess that's not so hard after all.
-
- (require 'nntp)
-
- ;; It probably wouldn't be too hard to make this work;
- ;; if you do it send me the changes.
- (if (string-match "flee" nntp-version)
- (error "nntp-post-bg doesn't work with flee's version of nntp.el"))
-
- (defvar nntp-post-background 'query
- "If t, each post will make a new connection to the NNTP server.
- This means that you don't have to wait for the post to complete to
- continue reading articles. If nil, posts will be made on the same
- connection. If any other value, you will be asked.")
-
- (or (fboundp 'buffer-disable-undo)
- (fset 'buffer-disable-undo 'buffer-flush-undo))
-
- (defun nntp-open-server-internal (host &optional service)
- "Open connection to news server on HOST by SERVICE (default is nntp)."
- (save-excursion
- ;; Use TCP/IP stream emulation package if needed.
- (or (fboundp 'open-network-stream)
- (require 'tcp))
- ;; Initialize communication buffer.
- ;; jwz: changed to use generate-new-buffer to support multiple connections.
- (if (and nntp-server-buffer (buffer-name nntp-server-buffer))
- (kill-buffer nntp-server-buffer))
- (setq nntp-server-buffer (generate-new-buffer " *nntpd*"))
- (set-buffer nntp-server-buffer)
- (buffer-disable-undo (current-buffer))
- (erase-buffer)
- (kill-all-local-variables)
- (setq case-fold-search t) ;Should ignore case.
- (setq nntp-server-process
- (open-network-stream "nntpd" (current-buffer)
- host (or service "nntp")))
- (setq nntp-server-name host)
- ;; It is possible to change kanji-fileio-code in this hook.
- (run-hooks 'nntp-server-hook)
- ;; Kill this process without complaint when exiting Emacs.
- (process-kill-without-query nntp-server-process)
- ;; Return the server process.
- nntp-server-process
- ))
-
- (defvar nntp-post-bg-state) ;local to buffer of bg process
- (defvar nntp-post-bg-source) ;the buffer of the message to post (modified)
- (defvar background-post-queue nil) ;pending procs
-
- (defun nntp-request-post ()
- "Post a new news article from the text of the current buffer."
- (cond
- ((or (eq nntp-post-background t)
- (and nntp-post-background (y-or-n-p "Post in background? ")))
- (let ((nntp-status-string nil)
- (nntp-server-process nil)
- (nntp-server-buffer nil)
- (message (current-buffer)))
- (message "Opening NNTP connection for posting...")
- (or (nntp-open-server gnus-nntp-server gnus-nntp-service)
- (error "couldn't open new NNTP connection for posting."))
- (set-process-filter nntp-server-process 'nntp-post-bg-filter)
- (message "Opening NNTP connection for posting... encoding text...")
- (save-excursion
- (set-buffer (generate-new-buffer " *bg-post-text*"))
- (erase-buffer)
- (buffer-disable-undo (current-buffer))
- (insert-buffer message)
- (nntp-encode-text)
- (setq message (current-buffer)))
- (save-excursion
- (set-buffer message)
- (rename-buffer (let ((b (generate-new-buffer " *bg-post*")))
- (prog1 (buffer-name b) (kill-buffer b)))))
- (save-excursion
- (set-buffer nntp-server-buffer)
- (set (make-local-variable 'nntp-post-bg-state) 'post)
- (set (make-local-variable 'nntp-post-bg-source) message)
- (setq background-post-queue
- (cons nntp-server-process background-post-queue))
- (nntp-send-command nil "POST"))
- (message "Posting will proceed in background.")))
- (t
- (message "NNTP: awaiting POST connection...")
- (if (nntp-send-command "^[23].*\r$" "POST")
- (progn
- (message "NNTP: got POST connection; encoding text...")
- (nntp-encode-text)
- (message "NNTP: got POST connection; sending text...")
- (nntp-send-region-to-server (point-min) (point-max))
- ;; 1.2a NNTP's post command is buggy. "^M" (\r) is not
- ;; appended to end of the status message.
- (message "NNTP: text sent; awaiting response...")
- (prog1
- (nntp-wait-for-response "^[23].*$")
- (message "NNTP: post complete.")))))))
-
- (defun nntp-post-bg-error (proc error)
- (let ((buffer (process-buffer proc)))
- (save-excursion
- (set-buffer buffer)
- (setq nntp-post-bg-state 'error)
- (kill-buffer nntp-post-bg-source)
- (delete-process proc)
- (kill-buffer buffer)))
- (setq background-post-queue (delq proc background-post-queue))
- (if error (error error)))
-
- (defun nntp-post-bg-filter (proc string)
- (save-excursion
- (let ((buffer (process-buffer proc)))
- (set-buffer buffer)
- (goto-char (point-max))
- (insert string)
- (cond
- ((eq nntp-post-bg-state 'post)
- ;; have sent POST command, waiting for response
- (cond ((not (re-search-backward "^[2345].*\r$")) ; no response yet
- nil)
- ((looking-at "[23]") ; ok, now send text
- (erase-buffer)
- (message "NNTP: got POST connection; sending text...")
- ;; This synchronously sends the entire post. It may be
- ;; that this will block for an unacceptably long time on
- ;; some servers, while waiting for the streams to drain.
- ;; It might therefore be worthwhile to write an async
- ;;version of nntp-send-region-to-server.
- (save-excursion
- (set-buffer nntp-post-bg-source)
- (let ((nntp-server-process proc)
- (nntp-server-buffer buffer)
- (ok nil))
- (unwind-protect
- (progn
- (nntp-send-region-to-server (point-min) (point-max))
- (setq ok t))
- (or ok (nntp-post-bg-error proc nil)))))
- (message "NNTP: text sent; awaiting response in background.")
- (setq nntp-post-bg-state 'sent))
- (t
- (nntp-post-bg-error proc
- (concat "POST failed: "
- (buffer-substring (point) (progn (end-of-line) (point))))))))
- ((eq nntp-post-bg-state 'sent)
- ;; have sent text of message, waiting for response
- (cond ((not (re-search-backward "^[2345].*\r$")) ; no response yet
- nil)
- ((looking-at "[23]") ; ok, we're done.
- (erase-buffer)
- (setq nntp-post-bg-state 'closed)
- (set-buffer (other-buffer))
- (delete-process proc)
- (kill-buffer buffer)
- (setq background-post-queue (delq proc background-post-queue))
- (message "Background post complete!")
- )
- (t
- (nntp-post-bg-error proc
- (concat "POST failed: "
- (buffer-substring (point) (progn (end-of-line) (point))))))))
- (t
- (error "internal error: nntp-post-bg-state is %s"
- nntp-post-bg-state))))))
-
- (defun nntp-post-bg-maybe-warn-about-pending-posts ()
- (if (null background-post-queue)
- nil
- (or (if (cdr background-post-queue)
- (yes-or-no-p
- (format "There are %d background posts in progress; exit anyway? "
- (length background-post-queue)))
- (yes-or-no-p
- "There is a background post in progress; exit anyway? "))
- (error ""))))
-
- (if (fboundp 'add-hook)
- (add-hook 'kill-emacs-hook 'nntp-post-bg-maybe-warn-about-pending-posts))
-
- (provide 'nntp-post-bg)
-