[gnu.emacs.gnus] News- and mail-reading in a single GNUS

karl@triceratops.cis.ohio-state.edu (Karl Kleinpaste) (05/17/89)

I got some very helpful changes from Steve Popovich
<popovich@park.cs.columbia.edu> regarding how to convince one GNUS to
do both news and mail.  His changes worked (mostly, anyway - one or
two minor glitches) but still didn't provide both news and mail at the
same time, which is what I really wanted.  So I spent most of the last
day or two hacking GNUS on and off until it got to where it will do
this for me.  The following is a shar file, containing a README
description of what's needed, plus sample shell scripts and one very
small change to nnspool.el to make your mail and news turn into one
logical type of communication that can be read with GNUS.

Enjoy,
--Karl

#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
#	README
#	.emacs-hooks
#	.forward
#	make-active
#	nnspool.el.diff
#	pmd
# This archive created: Tue May 16 16:15:11 1989
export PATH; PATH=/bin:$PATH
echo shar: extracting "'README'" '(2162 characters)'
if test -f 'README'
then
	echo shar: will not over-write existing file "'README'"
else
sed 's/^X//' << \gnus-hacks > 'README'
XThis file documents a scheme for using GNUS to read both news and mail
Xin a single GNUS incarnation.  Several steps are needed, and some
Xchanges will almost certainly be needed in any new environment.
X
X[1] Create a personal mail delivery program of some sort.  In the shar
Xfile in which this README came, there is a csh script called `pmd'
Xwhich knows how to deliver mail to a directory subhierarchy under
X~/Memos.  In that directory are subdirs such as personal, list, and so
Xforth.  Pmd knows how to find a file .last, which contains an integer
Xrepresenting the number of the last mail item saved in that directory.
XPmd saves the mail, locks the .last file, increments to the next one,
Xand saves the mail in the appropriate directory.  Have your mail sent
Xthrough this delivery filter via a .forward file such as that
Xenclosed.
X
X[2] Create a symlink to /usr/spool/news in the top-level mail
Xdirectory, e.g.:
X	ln -s /usr/spool/news ~/Memos/netnews
X
X[3] Install the very small enclosed patch to nnspool.el, and recompile
Xit.  This makes nnspool look for a personalized routine for choosing
Xan active file, rather than blindly taking the system default.  Note
Xthat it will still operate in its old fashion if no such function is
Xdefined.
X
X[4] Take the enclosed .emacs-hooks file, and install it in your own
X.emacs with local changes as appropriate.  This will probably mean
Xthat you will need to change how nnspool-personal-active-file works
Xunless you take mine raw.  It works, but it's by no means the last
Xword.  The csh script make-active is used by nnspool-personal-active-
Xfile; it generates a file ~/Memos/active in the usual form, but
Xincludes one's personal mail subhierarchy as part of the active file.
XNote that nnspool-spool-directory must have a trailing `/'.
X
X[5] Save a copy of your .newsrc to forestall catastrophe, and then
Xedit .newsrc to add "netnews." to the beginning of each line.
X
X[6] Take a deep breath, start a fresh Emacs to get the .emacs changes,
Xand invoke GNUS.  It'll go hack up an active file, and then show you
Xall your news and mail as though it were all news.
X
XSuggestions, improvements, bug fixes are all most welcome.
X
X--Karl
gnus-hacks
if test 2162 -ne "`wc -c < 'README'`"
then
	echo shar: error transmitting "'README'" '(should have been 2162 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'.emacs-hooks'" '(1980 characters)'
if test -f '.emacs-hooks'
then
	echo shar: will not over-write existing file "'.emacs-hooks'"
else
sed 's/^X//' << \gnus-hacks > '.emacs-hooks'
X;; I always load it up directly, rather than autoloading it.
X(load "gnus")
X;;
X;; Extra ignorable headers.
X(setq gnus-ignored-headers
X      (concat gnus-ignored-headers
X	      "\\|^Errors-To:\\|^Precedence:\\|^Received:\\|^UNIX-From:"))
X;;
X;; Set your private mail directory as the news spool area.
X(setq nnspool-spool-directory "~/Memos/") ; note trailing `/'
X;;
X;; The following 2 defvars are strictly personalized;
X;; used in the function following.  Roll your own...
X(defvar karl-active-file-maker "~/bin/make-active"
X  "*Personalized active file generator")
X(defvar karl-active-file "~/Memos/active"
X  "*Personalized active file")
X;;
X;; This is the function needed by nnspool-pick-active-file
X;; in order to discriminate between ordinary netnews reading
X;; and modified news-and-mail reading.  It must create a
X;; file in the same format as the netnews active file, and
X;; then return that file's filename to the caller.
X(defun nnspool-personal-active-file ()
X  "Returns a filename string for a personal active file."
X  (message "Hacking personalized active file...")
X  (call-process karl-active-file-maker nil nil nil
X		; remaining stuff is args to the active file maker.
X		nnspool-spool-directory "personal" "list")
X  (message "Hacking personalized active file...done.")
X  karl-active-file
X)
X;;
X;; If you want an RMAIL-like forwarding
X;; function, use the rest of this.
X(defun gnus-Subject-forward ()
X  "Forward the current message to another user."
X  (interactive)
X  (switch-to-buffer gnus-Article-buffer)
X  (let ((forward-buffer gnus-Article-buffer) ; used to be (current-buffer)
X	(subject (concat "["
X			 (mail-strip-quoted-names (mail-fetch-field "From"))
X			 ": " (or (mail-fetch-field "Subject") "") "]")))
X    ;; There are always 2 buffers visible; use this window.
X    (mail nil nil subject)
X    (save-excursion
X      (goto-char (point-max))
X      (forward-line 1)
X      (insert-buffer forward-buffer))))
X(define-key gnus-Subject-mode-map "F" 'gnus-Subject-forward)
gnus-hacks
if test 1980 -ne "`wc -c < '.emacs-hooks'`"
then
	echo shar: error transmitting "'.emacs-hooks'" '(should have been 1980 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'.forward'" '(27 characters)'
if test -f '.forward'
then
	echo shar: will not over-write existing file "'.forward'"
else
sed 's/^X//' << \gnus-hacks > '.forward'
X"|/usr/local/bin/pmd karl"
gnus-hacks
if test 27 -ne "`wc -c < '.forward'`"
then
	echo shar: error transmitting "'.forward'" '(should have been 27 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'make-active'" '(947 characters)'
if test -f 'make-active'
then
	echo shar: will not over-write existing file "'make-active'"
else
sed 's/^X//' << \gnus-hacks > 'make-active'
X#!/bin/csh -f
X#
X# Script to generate an active file on the fly.
X# Builds a pseudoactive file which represents personal mail under
X# $1 plus pseudonews in $1/netnews (a symlink to the real news area).
X#
Xset dir=$1
Xshift
Xset active=$dir/active
Xset nactive=/usr/lib/news/active
Xif ($#argv < 1) then
X	echo make-active: usage: make-active directory subdirs...
X	exit 99
Xendif
X#
X# Find directories and their associated .last files.  Then take
X# base dirnames, change to newsgroup name format, and build the
X# mail-based active file out of it all.
X#
Xcd $dir
Xset list=(`find $* -name .last -print`)
Xset count=$#list
Xset nlist=()
Xforeach i ($list)
X	set j=$i:h
X	set nlist=($nlist `echo $j | tr / .`)
Xend
Xcp /dev/null $active
X@ i = 1
Xwhile ($i <= $count)
X	echo $nlist[$i] `cat $list[$i]` 00000 y >> $active
X	@ i ++
Xend
X#
X# Now add the whole canonical active file,
X# prefixing every group with "netnews.".
Xsed -e 's/^/netnews./' < $nactive >> $active
X#
Xexit 0
gnus-hacks
if test 947 -ne "`wc -c < 'make-active'`"
then
	echo shar: error transmitting "'make-active'" '(should have been 947 characters)'
fi
chmod +x 'make-active'
fi # end of overwriting check
echo shar: extracting "'nnspool.el.diff'" '(1090 characters)'
if test -f 'nnspool.el.diff'
then
	echo shar: will not over-write existing file "'nnspool.el.diff'"
else
sed 's/^X//' << \gnus-hacks > 'nnspool.el.diff'
X*** nnspool.el.old	Tue May 16 14:38:40 1989
X--- /usr/local/lib/emacs/lisp/nnspool.el	Tue May 16 14:30:15 1989
X***************
X*** 242,248 ****
X  (defun nntp-request-list ()
X    "List valid newsgoups."
X    (save-excursion
X!     (nnspool-find-file nnspool-active-file)))
X  
X  (defun nntp-request-last ()
X    "Set current article pointer to the previous article
X--- 242,248 ----
X  (defun nntp-request-list ()
X    "List valid newsgoups."
X    (save-excursion
X!     (nnspool-find-file (nnspool-pick-active-file))))
X  
X  (defun nntp-request-last ()
X    "Set current article pointer to the previous article
X***************
X*** 351,353 ****
X--- 351,361 ----
X        (setq idx (1+ idx)))
X      (concat (file-name-as-directory nnspool-spool-directory) group "/")
X      ))
X+ 
X+ (defun nnspool-pick-active-file ()
X+   "Return a filename string for the active file."
X+   ;; If the user has defined his own active file creator,
X+   ;; use it.  Otherwise, return the "standard" active file.
X+   (if (fboundp 'nnspool-personal-active-file)
X+       (nnspool-personal-active-file)
X+     nnspool-active-file))
gnus-hacks
if test 1090 -ne "`wc -c < 'nnspool.el.diff'`"
then
	echo shar: error transmitting "'nnspool.el.diff'" '(should have been 1090 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'pmd'" '(1917 characters)'
if test -f 'pmd'
then
	echo shar: will not over-write existing file "'pmd'"
else
sed 's/^X//' << \gnus-hacks > 'pmd'
X#!/bin/csh -f
X#
X# Personal mail delivery.
X# This saves mail to a personal area where one can happily
X# run GNUS on it, rather than use a normal mailer.
X#
X# Configuration.
Xumask 077
Xset path=(/usr/local/bin /usr/ucb /bin /usr/bin /etc /usr/etc)
Xset dir=~/Memos
Xset tmp=/tmp/pmd-$$
X#
X# Save the mail momentarily, and set a Lines: count in it.
Xcat - > $tmp
Xset totlen=`wc -l < $tmp`
Xset lines=(`sed '1,/^$/d' < $tmp | wc -l`)
X@ headerlen = $totlen - $lines
Xed - $tmp << EOF >& /dev/null
X$headerlen
Xi
XLines: $lines
X.
Xw
Xq
XEOF
X#
X# Deduce headers appropriately.
Xset nonomatch
Xset from=(`head -1 $tmp`)
Xif ($#from < 2) then
X	echo Bogus mail: From line has $#from items.
X	exit 23
Xendif
Xset from=(`echo "$from[2]" | sed -e 's/@.*//' -e 's/\(.*\)!\(.*\)/\2/'`)
Xif ("$from" =~ *-[Rr][Ee][Qq][Uu][Ee][Ss][Tt]*) then
X	set subdir=list/general
Xelse if ("$from" =~ *[Mm][Aa][Ii][Ll][Ee][Rr]-[Dd][Aa][Ee][Mm][Oo][Nn]*) then
X	# Mailer-Daemon bounces.
X	set subdir=mailer-daemon
Xelse
X	# Personal mail
X	if ((-e $dir/personal/"$from") && (-d $dir/personal/"$from")) then
X		set subdir=personal/"$from"
X	else
X		set subdir=personal/general
X	endif
Xendif
Xunset nonomatch
X#
X# Now save the mail appropriately.
X#
X# Lock.
Xset keyf=$dir/$subdir/KEY
Xset seqfile=$dir/$subdir/.last
Xset success=no
X@ retry = 0
Xwhile (($retry < 10) && ($success == no))
X	rm $keyf
X	if ($status == 0) then
X		# The key was there when we wanted it.
X		set success=yes
X	else
X		# The key was not there - someone else
X		# had already taken it.  Wait and retry.
X		sleep 10
X		@ retry ++
X	endif
Xend
X#
X# If we fall out to here without success, we failed 10 times to
X# get the key.  Result: Who cares?  We'll go forward anyway,
X# and re-assert the key when we're done.
X#
X# Get next filenumber.
Xset seq=(`cat $seqfile`)
X@ seq ++
Xecho $seq > $seqfile
X#
X# Unlock and save.
Xtouch $keyf
Xsed -e '1s/^From /UNIX-From: /' < $tmp > $dir/"$subdir"/$seq
X#
X# Clean up and exit.
Xrm -f $tmp
Xexit 0
gnus-hacks
if test 1917 -ne "`wc -c < 'pmd'`"
then
	echo shar: error transmitting "'pmd'" '(should have been 1917 characters)'
fi
chmod +x 'pmd'
fi # end of overwriting check
#	End of shell archive
exit 0