1 ;;; nnspool.el --- spool access for GNU Emacs
3 ;; Copyright (C) 1988, 1989, 1990, 1993, 1994, 1995, 1996, 1997, 1998,
4 ;; 2000, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6 ;; Author: Masanobu UMEDA <umerin@flab.flab.fujitsu.junet>
7 ;; Lars Magne Ingebrigtsen <larsi@gnus.org>
10 ;; This file is part of GNU Emacs.
12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by
14 ;; the Free Software Foundation; either version 2, or (at your option)
17 ;; GNU Emacs is distributed in the hope that it will be useful,
18 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ;; GNU General Public License for more details.
22 ;; You should have received a copy of the GNU General Public License
23 ;; along with GNU Emacs; see the file COPYING. If not, write to the
24 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25 ;; Boston, MA 02110-1301, USA.
34 (eval-when-compile (require 'cl))
36 (nnoo-declare nnspool)
38 (defvoo nnspool-inews-program news-inews-program
39 "Program to post news.
40 This is most commonly `inews' or `injnews'.")
42 (defvoo nnspool-inews-switches '("-h" "-S")
43 "Switches for nnspool-request-post to pass to `inews' for posting news.
44 If you are using Cnews, you probably should set this variable to nil.")
46 (defvoo nnspool-spool-directory
47 (file-name-as-directory (if (boundp 'news-directory)
48 (symbol-value 'news-directory)
50 "Local news spool directory.")
52 (defvoo nnspool-nov-directory (concat nnspool-spool-directory "over.view/")
53 "Local news nov directory.")
55 (defvoo nnspool-lib-dir
56 (if (file-exists-p "/usr/lib/news/active")
59 "Where the local news library files are stored.")
61 (defvoo nnspool-active-file (concat nnspool-lib-dir "active")
62 "Local news active file.")
64 (defvoo nnspool-newsgroups-file (concat nnspool-lib-dir "newsgroups")
65 "Local news newsgroups file.")
67 (defvoo nnspool-distributions-file (concat nnspool-lib-dir "distribs.pat")
68 "Local news distributions file.")
70 (defvoo nnspool-history-file (concat nnspool-lib-dir "history")
71 "Local news history file.")
73 (defvoo nnspool-active-times-file (concat nnspool-lib-dir "active.times")
74 "Local news active date file.")
76 (defvoo nnspool-large-newsgroup 50
77 "The number of articles which indicates a large newsgroup.
78 If the number of articles is greater than the value, verbose
79 messages will be shown to indicate the current status.")
81 (defvoo nnspool-nov-is-evil nil
82 "Non-nil means that nnspool will never return NOV lines instead of headers.")
84 (defconst nnspool-sift-nov-with-sed nil
85 "If non-nil, use sed to get the relevant portion from the overview file.
86 If nil, nnspool will load the entire file into a buffer and process it
89 (defvoo nnspool-rejected-article-hook nil
90 "*A hook that will be run when an article has been rejected by the server.")
92 (defvoo nnspool-file-coding-system nnheader-file-coding-system
93 "Coding system for nnspool.")
97 (defconst nnspool-version "nnspool 2.0"
98 "Version numbers of this version of NNSPOOL.")
100 (defvoo nnspool-current-directory nil
101 "Current news group directory.")
103 (defvoo nnspool-current-group nil)
104 (defvoo nnspool-status-string "")
107 ;;; Interface functions.
109 (nnoo-define-basics nnspool)
111 (deffoo nnspool-retrieve-headers (articles &optional group server fetch-old)
112 "Retrieve the headers of ARTICLES."
114 (set-buffer nntp-server-buffer)
116 (when (nnspool-possibly-change-directory group)
117 (let* ((number (length articles))
119 (default-directory nnspool-current-directory)
120 (do-message (and (numberp nnspool-large-newsgroup)
121 (> number nnspool-large-newsgroup)))
122 (nnheader-file-coding-system nnspool-file-coding-system)
124 (if (and (numberp (car articles))
125 (nnspool-retrieve-headers-with-nov articles fetch-old))
126 ;; We successfully retrieved the NOV headers.
128 ;; No NOV headers here, so we do it the hard way.
129 (while (setq article (pop articles))
130 (if (stringp article)
131 ;; This is a Message-ID.
132 (setq ag (nnspool-find-id article)
133 file (and ag (nnspool-article-pathname
136 ;; This is an article in the current group.
137 (setq file (int-to-string article)))
138 ;; Insert the head of the article.
140 (file-exists-p file))
142 (princ article (current-buffer))
143 (insert " Article retrieved.\n")
145 (inline (nnheader-insert-head file))
147 (if (search-forward "\n\n" nil t)
151 (goto-char (point-max))
155 (delete-region (point) (point-max)))
158 (zerop (% (incf count) 20))
159 (nnheader-message 5 "nnspool: Receiving headers... %d%%"
160 (/ (* count 100) number))))
163 (nnheader-message 5 "nnspool: Receiving headers...done"))
165 ;; Fold continuation lines.
166 (nnheader-fold-continuation-lines)
169 (deffoo nnspool-open-server (server &optional defs)
170 (nnoo-change-server 'nnspool server defs)
172 ((not (file-exists-p nnspool-spool-directory))
173 (nnspool-close-server)
174 (nnheader-report 'nnspool "Spool directory doesn't exist: %s"
175 nnspool-spool-directory))
176 ((not (file-directory-p
178 (file-truename nnspool-spool-directory))))
179 (nnspool-close-server)
180 (nnheader-report 'nnspool "Not a directory: %s" nnspool-spool-directory))
181 ((not (file-exists-p nnspool-active-file))
182 (nnheader-report 'nnspool "The active file doesn't exist: %s"
183 nnspool-active-file))
185 (nnheader-report 'nnspool "Opened server %s using directory %s"
186 server nnspool-spool-directory)
189 (deffoo nnspool-request-article (id &optional group server buffer)
190 "Select article by message ID (or number)."
191 (nnspool-possibly-change-directory group)
192 (let ((nntp-server-buffer (or buffer nntp-server-buffer))
195 ;; This is a Message-ID.
196 (when (setq ag (nnspool-find-id id))
197 (setq file (nnspool-article-pathname (car ag) (cdr ag))))
198 (setq file (nnspool-article-pathname nnspool-current-group id)))
201 (not (file-directory-p file))
202 (save-excursion (nnspool-find-file file))
203 ;; We return the article number and group name.
205 (cons nnspool-current-group id)
208 (deffoo nnspool-request-body (id &optional group server)
209 "Select article body by message ID (or number)."
210 (nnspool-possibly-change-directory group)
211 (let ((res (nnspool-request-article id)))
214 (set-buffer nntp-server-buffer)
215 (goto-char (point-min))
216 (when (search-forward "\n\n" nil t)
217 (delete-region (point-min) (point)))
220 (deffoo nnspool-request-head (id &optional group server)
221 "Select article head by message ID (or number)."
222 (nnspool-possibly-change-directory group)
223 (let ((res (nnspool-request-article id)))
226 (set-buffer nntp-server-buffer)
227 (goto-char (point-min))
228 (when (search-forward "\n\n" nil t)
229 (delete-region (1- (point)) (point-max)))
230 (nnheader-fold-continuation-lines)))
233 (deffoo nnspool-request-group (group &optional server dont-check)
235 (let ((pathname (nnspool-article-pathname group))