From decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!allbery Sat Jan 6 11:04:57 PST 1990 Article 1263 of comp.sources.misc: Path: decwrl!ucbvax!tut.cis.ohio-state.edu!cs.utexas.edu!uunet!allbery From: jrp@rducky.UUCP (JIM PICKERING) Newsgroups: comp.sources.misc Subject: v09i097: pexpire for Cnews Message-ID: <75759@uunet.UU.NET> Date: 5 Jan 90 00:02:46 GMT Sender: allbery@uunet.UU.NET Organization: Technical Solutions, Inc. Lines: 1790 Approved: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) Posting-number: Volume 9, Issue 97 Submitted-by: jrp@rducky.UUCP (JIM PICKERING) Archive-name: cn_pexpire Here is a new version of pexpire that I have modified for Cnews. Since it was originally copyrighted by Dave Taylor, I have enclosed his correspondence allowing me to post it. jim Jim Pickering c/o Technical Solutions || (north) ..csustan!polyslo!rducky!jrp P.O. Box 1045 || (south) ..sdsu!polyslo!rducky!jrp Arroyo Grande, CA 93421 || (south) ..csun!polyslo!rducky!jrp (805) 473-1037 || (east) ..csufres!polyslo!rducky!jrp ------------------------------------------------------------------------------ Jim, You are more than welcome to distribute a new version of my Pexpire program.. thanks for modifying it to work with C news too! Ciao! -- Dave Taylor Intuitive Systems Mountain View, California taylor@limbo.intuitive.com or {uunet!}{decwrl,apple}!limbo!taylor ------------------------------------------------------------------------------ #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed tncli as standard input via # unshar, or by typing "sh 'MANIFEST' <<'END_OF_FILE' X File Name Archive # Description X----------------------------------------------------------- X MANIFEST 1 This shipping list X Makefile 1 X README 1 X README.CNEWS 1 X bpexpire.1 1 X cpexpire.1 1 X dopexpire 1 X pexpire.batch 1 X pexpire.c 1 X pexpire.defs 1 X pexpire.h 1 X pexplist 1 END_OF_FILE if test 486 -ne `wc -c <'MANIFEST'`; then echo shar: \"'MANIFEST'\" unpacked with wrong size! fi # end of 'MANIFEST' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(3310 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for the pexpire program X# X# by Dave Taylor, Hewlett-Packard Co. X# Cnews modifications by Jim Pickering (jrp@rducky) X XSHELL = /bin/sh XCFILES = pexpire.c XHEADERS = pexpire.h XOBJS = pexpire.o X X# our executable ... if you change this, you'll have to edit dopexpire (Cnews) XPROGNAME = pexpire X X# our doexpire(8) replacement for Cnews XBATCHNAME= dopexpire X X# Bnews man directory XMANDIR = /usr/man/local/man1 X# Cnews man directory XMANDIR = /usr/man/local/man8 X X# Bnews install directory XNEWSDIR = /usr/lib/news X# Cnews install directory ... if you change this, you'll have to edit dopexpire XNEWSDIR = /usr/lib/newsbin/expire X X# Cnews pexplist install directory ... if you change this, you'll have to edit X# dopexpire XLISTDIR = /usr/lib/news X X# the next is probably the only thing you'll need to locally customize X# to reflect the top level location of the netnews source on your X# machine ... Bnews X XNEWS_SRC = /usr/local/src/news.2.11 X XINCLUDEDIR = -I${NEWS_SRC} XLIBS = -lPW XRM = rm -f X X# use for BNEWS XCFLAGS = -O ${INCLUDEDIR} X# use for CNEWS XCFLAGS = -O -DCNEWS X X# your favorite C compiler XCC = /bin/cc XCC = /bin/ccc X X${PROGNAME}: ${OBJS} X ${CC} -o ${PROGNAME} -s ${OBJS} ${LIBS} X Xpexpire.c: pexpire.h Xpexpire.o: pexpire.c X Xclean: X ${RM} ${OBJS} LINT.OUT core $(PROGNAME) tempxxx X Xlint: LINT.OUT X XLINT.OUT: ${CFILES} X lint ${DEFINE} ${INCLUDEDIR} ${CFILES} ${LIBS} > LINT.OUT X Xshar: X ${RM} Part* MANIFEST X makekit -oMANIFEST Makefile README* cpexpire.1 bpexpire.1 pexpire.c pexpire.defs pexpire.h pexpire.batch dopexpire pexplist X compress Part* X Xrealclean: shar clean X ${RM} MANIFEST Makefile README* cpexpire.1 bpexpire.1 pexpire.c pexpire.defs pexpire.h pexpire.batch dopexpire pexplist X Xbnewsinstall: $(PROGNAME) X mv $(PROGNAME) $(NEWSDIR) X chmod 0750 $(NEWSDIR)/$(PROGNAME) X chown news $(NEWSDIR)/$(PROGNAME) X chgrp news $(NEWSDIR)/$(PROGNAME) X cp pexpire.defs $(NEWSDIR) X chown news $(NEWSDIR)/pexpire.defs X chgrp news $(NEWSDIR)/pexpire.defs X cp bpexpire.1 $(MANDIR)/pexpire.1 X chown bin $(MANDIR)/pexpire.1 X chgrp bin $(MANDIR)/pexpire.1 X chmod 0444 $(MANDIR)/pexpire.1 X @echo X @echo "\tInstall pexpire.batch and" X @echo "\t\tput an entry for $(PROGNAME) in /usr/lib/crontab" X @echo X Xbnewsuninstall: X ${RM} $(NEWSDIR)/$(PROGNAME) X ${RM} $(NEWSDIR)/pexpire.defs X ${RM} $(MANDIR)/pexpire.1 X Xcnewsinstall: $(PROGNAME) $(BATCHNAME) X mv $(PROGNAME) $(NEWSDIR) X chmod 0775 $(NEWSDIR)/$(PROGNAME) X chown bin $(NEWSDIR)/$(PROGNAME) X chgrp bin $(NEWSDIR)/$(PROGNAME) X cp $(BATCHNAME) $(NEWSDIR) X chmod 0775 $(NEWSDIR)/$(BATCHNAME) X chown bin $(NEWSDIR)/$(BATCHNAME) X chgrp bin $(NEWSDIR)/$(BATCHNAME) X cp pexplist $(LISTDIR)/pexplist X chown bin $(LISTDIR)/pexplist X chgrp bin $(LISTDIR)/pexplist X chmod 0444 $(LISTDIR)/pexplist X cp cpexpire.1 $(MANDIR)/pexpire.8 X chown bin $(MANDIR)/pexpire.8 X chgrp bin $(MANDIR)/pexpire.8 X chmod 0444 $(MANDIR)/pexpire.8 X ${RM} $(MANDIR)/dopexpire.8 X ln $(MANDIR)/pexpire.8 $(MANDIR)/dopexpire.8 X @echo X @echo "Put a similar entry for $(BATCHNAME) in /usr/lib/crontab:" X @echo "\t44 0 * * * /bin/su news -c '/usr/lib/newsbin/expire/dopexpire'" X @echo X Xcnewsuninstall: X ${RM} $(NEWSDIR)/$(PROGNAME) X ${RM} $(NEWSDIR)/$(BATCHNAME) X ${RM} $(LISTDIR)/pexplist X ${RM} $(MANDIR)/pexpire.8 X ${RM} $(MANDIR)/dopexpire.8 END_OF_FILE if test 3310 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(852 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X X Additional Administrative Notes for Pexpire X X August 29th, 1988 X X It is strongly recommended that you read the man page for the X netnews expire() command, studying the '-e' and '-E' options, X then read the pexpire() man page distributed with the pexpire X package. X X From there, you need to edit the Makefile to ensure that it X is pointing at the right source directory for netnews, then X edit the file "pexpire.h". X X You should notice that pexpire.h expects that the netnews X "defs.h" file is available -- it grabs the default expiration X times from that file (see the extensively commented "pexpire.h" X file for details). X X Finally, this is a first distribution, so there might very well X be problems and non-portabilities. If you come across anything, X please drop me a note. X X Dave Taylor X X taylor@hplabs.hp.com END_OF_FILE if test 852 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'README.CNEWS' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README.CNEWS'\" else echo shar: Extracting \"'README.CNEWS'\" \(1093 characters\) sed "s/^X//" >'README.CNEWS' <<'END_OF_FILE' Xsubject: Notes for Pexpire for Cnews Xdate: December 30, 1989 Xfrom: Jim Pickering (jrp@rducky) X X X XIt is strongly recommended that you read the man page for Xthe Cnews expire(8) command, studying the expire list line Xoptions, then read the cpexpire.1 man page distributed with Xthe pexpire package. Note that dopexpire() does not use X/usr/lib/news/explist. X XYou may need to edit the Makefile, edit the file X"pexpire.h", edit the file "pexplist", and edit the file X"dopexpire", paying particular attention to lines after '# XYOU MAY WANT TO EDIT THE FOLLOWING'. To install, as root Xdo a 'make cnewsinstall'. X XCredit-where-credit-is-due department: XDave Taylor (taylor@limbo.intuitive.com) originally wrote Xpexpire. I made some relatively minor modifications so that Xit would run under Cnews. His copyright stands. Dopexpire Xis just a doexpire ripoff from Cnews, written by Henry Spencer Xand Geoff Collyer at U. of Toronto. The man page is a Xcombination of both Cnews' expire(8) and Dave's pexpire(1) man Xpages. X XIf you come across problems and non-portabilities, please Xdrop me a note. X Xjim END_OF_FILE if test 1093 -ne `wc -c <'README.CNEWS'`; then echo shar: \"'README.CNEWS'\" unpacked with wrong size! fi # end of 'README.CNEWS' fi if test -f 'bpexpire.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'bpexpire.1'\" else echo shar: Extracting \"'bpexpire.1'\" \(8460 characters\) sed "s/^X//" >'bpexpire.1' <<'END_OF_FILE' X.TH PEXPIRE 1M local X.ad b X.SH NAME Xpexpire - expire netnews groups based on local readership X.SH SYNOPSIS X.B pexpire X[-cgrov] X[-e cmd] X[-a N] X[-h N] X[-H N] X.SH HP-UX COMPATIBILITY X.TP 10 XLevel: XHP-UX/CONTRIBUTED X.TP XOrigin: XHewlett-Packard X.SH DESCRIPTION X.I Pexpire Xis intended to offer a finer granularity in the expiration of Xnetnews articles on a multi-user machine. The philosophy behind Xit is that there are typically a large set of newsgroups that Xno-one on the machine reads, which makes them very likely targets Xfor shorter expiration times. X.PP XThis program allows you to do exactly that \(em it lets you set Xdefault expiration times for all groups on your machine depending Xon if they are subscribed to or not, then checks each users X".newsrc" to ascertain this information. The finaly output of Xthe program is a set of \fIexpire\fR commands suitable for automatic execution Xout of cron. X.PP XThe flags understood are: X.TP 8 X.B \-a n XSet default history expire value to 'n'. X.sp XThere are actually three Xflags to do with expiration dates that \fIpexpire\fR understands: Xthe `-a' flag to set the default history expire value, and the `-h' Xand `-H' flags to set a bracketing for when the `-E' flag needs to Xbe output. X.sp XThat doesn't make any sense, I'm sure, so let's look at it this Xway: the \fIexpire\fR program uses two different expiration Xdates, one for when the article should be removed, and another Xfor when the entry should be removed from the ``history'' file. XWith that in mind, the `-a' flag sets the default history expire Xdate for the `history' file, and the `-h' and `-H' flags set up Xthe window (eg. the program checks: X.ft CW X.nf X X min-hist-expire < current-expire < max-hist-expire X X.fi X.ft R Xfor each \fIexpire\fR command output). Please see the X\fIexpire\fR man page for more information on the `-e' Xand `-E' flags. X.sp XThe default value for this is 28 days. X.TP 8 X.B \-c XMake the groupname list comma separated, rather than space Xseparated. This is a cosmetic change to the output, but you Xmight have a version of \fIexpire\fR that wants one or the Xother explicitly. X.TP 8 X.B \-e cmd XUses 'cmd' for output rather than the default expire program X.sp XThe default set to ``/usr/local/lib/news/expire''. X.TP 8 X.B \-g n XForces `n' or less groups output per command. XThis is because some versions of \fIexpire\fR have a limit as Xto the number of groups they'll accept for expiration in a single Xinvocation. X.sp XThe default is 50 groups. X.TP 8 X.B \-h n XSet the default minimum history expire value to 'n' (see `-a' above) X.sp XThe current default is set to 14 days. X.TP 8 X.B \-H n XSet the default maximum history expire value to 'n' (see `-a' above) X.sp XThe current default is set to 28 days. X.TP 8 X.B \-r XTakes user id 0 account ".newsrc" files into account \(em a lot of Xsites have multiple roots, with each having their usual home Xdirectory (eg. the one for their non-administrative account). XIn a situation like this there is no reason to pay the extra Xoverhead of checking their ".newsrc" file twice. X.sp XThe default is to ignore user id 0 accounts. X.TP 8 X.B \-o XForces one-group-per-line output format. X.sp XThe default is to use the value of the `-g' flag for groups per Xoutput line. X.TP 8 X.B \-v XTurns on verbose output mode. X.PP XIn addition, the program allows the administrator to define a file Xthat contains default expiration times for groups or sets of Xgroups. This file is called ``pexpire.defaults'' and the format Xit expects is: X.nf X X pattern +expire -expire X X.fi XWhere the pattern can be any reguler expression accepted by the Xregexp(3c) package, the +expire is the number of days to expire Xthe group if people are reading it, and -expire is the number Xof days to expire the group if no-one is reading it currently. X.SH EXAMPLES XThe configuration we have locally for ourselves has the following X"pexpire.defaults" file: X.nf X.ft CW X X # X # This is the "pexpire" default expiration times file. The X # format of this file is: X # X # <+expire> <-expire> X # X # where <+expire> is the expiration date for groups that are X # currently read by people on this machine, <-expire> are for X # those that are unread, and is any regular X # expression as per regexp(3c). X # X # It is recommended that you have ".*" as the first expression so X # that you can set the default expiration for all groups. The X # processing order of this information is: X # for each pattern read in this file: X # for each group in the active file: X # if the pattern matches, set the dates accordingly. X # X # this means that the patterns "^comp.*" and "source" in that X # order would result in "comp.unix.sources" having the source X # expire times. X # X # NOTE: never lead an expression with an asterisk -- assume all X # patterns are unrooted, and use '^' to get them left rooted X # if you want to X .* 14 1 X ^hp.* 30 15 X ^comp.* 10 2 X ^talk.* 7 1 X ^soc.* 7 1 X ^news.* 14 2 X source 14 7 X test 1 1 X comp.mail.elm 56 28 X X.ft R X.fi XNotice that the first regular expression, ``.*'', gives us the default Xexpiration time for all groups on our machine, then we modify it according Xto local interests and needs. Also notice that patterns default to being Xable to `float', that is, ``source'' matches all groups that have the word Xsource in their names, whether left, right, or not rooted at all. X.sp XAdditionally, we invoke the following shell script via cron: X.nf X.ft CW X X : Use /bin/sh X X # expire news using pexpire() X # script written by Rob Sartin, HP (sartin@hplabs.hp.com) X X expire_script="/tmp/expire$$" X trap 'rm -f $expire_script' 0 1 2 3 15 X X # display our disk space utilization before the command ... X X echo "Expiring old news" X echo "\\nBefore:" X bdf X X # get the netnews home directory by fiddling /etc/passwd: X X eval `awk -F: "/^netnews:/"' { printf "LIBDIR=%s;\\n", $6 }' \\ X < /etc/passwd` X X # create the new expire script X X rm -f ${expire_script} X ${LIBDIR}/pexpire > ${expire_script} 2>/dev/null X chmod 0755 ${expire_script} X X # and execute it: X X ${expire_script} X X # finally, output disk space utilization after the command X X echo "\\nAfter:" X bdf X X # and we're done. X X exit 0 X X.ft R X.fi XNote that you can have a minimal script by having the following Xsequence instead, if you choose: X.ft CW X.nf X X : Use /bin/sh X X PEXPIRE=/usr/local/lib/news/pexpire X TMPFILE=/tmp/expire.$$ X X $PEXPIRE > $TMPFILE X X sh $TMPFILE X X exit 0 X X.fi X.ft R XThough the former is recommended. X.PP XAlso, you can test out the pexpire program to see what it thinks Xthe expiration time of a specific group is, for example, by a Xsequence like: X.nf X.ft CW X X % pexpire -o -e expire | grep \fIgroup you're interested in\fR X X.ft R X.fi XFor example: X.nf X.ft CW X X % pexpire -o -e expire | grep soc.singles X X expire -e 7 -E 28 -n soc.singles X X.ft R X.fi XThis tells us that the group is to be expired in 7 days, but that Xthe actual article entries are to remain in the netnews history Xfile for 28 days. X.PP XWe can also find out what user ``.newsrc'' files are Xchecked with: X.nf X.ft CW X X % pexpire > /dev/null X X Checking against ".newsrc" for the following users: X sartin taylor jin markc X X.ft R X.fi Xor, with the `-v' verbose option turned on: X.nf X.ft CW X X % pexpire -v | sed '/^$/,$d' X X Read 511 groups out of the active file. X Checked against 10 patterns in the default-expire file. X Checking against .newsrc for user "sartin" X Checking against .newsrc for user "taylor" X Checking against .newsrc for user "jin" X Checking against .newsrc for user "markc" X X.ft R X.fi X.SH AUTHOR XDave Taylor, Hewlett-Packard Company (taylor\s-1@\s+1hplabs.hp.com) X.SH FILES X.nf X.if n .ta 26 X.if t .ta 20 X/etc/passwd for accounts to check ".newsrc" files X$USER/.newsrc for each account on the machine, to check X$NETNEWS usually ``/usr/local/lib/news'' X$NETNEWS/active Where the netnews active file lives X$NETNEWS/expire The `real' \fIexpire\fR command X$NETNEWS/pexpire.default home for the ``pexpire.default'' file X/bin/sh valid login shell for user X/bin/csh valid login shell for user X/bin/ksh valid login shell for user X/bin/rsh valid login shell for user X.SH SEE\ ALSO Xexpire(1) END_OF_FILE if test 8460 -ne `wc -c <'bpexpire.1'`; then echo shar: \"'bpexpire.1'\" unpacked with wrong size! fi # end of 'bpexpire.1' fi if test -f 'cpexpire.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cpexpire.1'\" else echo shar: Extracting \"'cpexpire.1'\" \(3939 characters\) sed "s/^X//" >'cpexpire.1' <<'END_OF_FILE' X.\" =()<.ds a @@>()= X.ds a /usr/spool/news X.\" =()<.ds b @@>()= X.ds b /usr/lib/newsbin X.\" =()<.ds c @@>()= X.ds c /usr/lib/news X.\" =()<.ds m @@>()= X.ds m postmaster X.ad b X.TH PEXPIRE 8 local X.SH NAME Xpexpire, dopexpire - expire netnews groups based on local readership X.SH SYNOPSIS X.B \*b/expire/pexpire X[ X.B \-s X] X[ X.B \-v X] X[ X.B \-e N X] X[ X.B \-r N X] X[ X.B \-p N X] X[ X.B \-E N X] X[ X.B \-R N X] X[ X.B \-P N X] X.br X.B \*b/expire/doexpire Xexpireoptions X.SH DESCRIPTION X.I Pexpire Xis intended to offer a finer granularity in the expiration of Xnetnews articles on a multi-user machine. The philosophy behind Xit is that there are typically a large set of newsgroups that Xno-one on the machine reads, which makes them very likely targets Xfor shorter expiration times. X.PP XThis program allows you to do exactly that \(em it lets you set Xdefault expiration times for all groups on your machine depending Xon if they are subscribed to or not, then checks each users X".newsrc" to ascertain this information. The finaly output of Xthe program is a set of \fIexpire\fR lines suitable for automatic execution Xby \fIdopexpire\fR out of cron. X.PP XThe flags understood are: X.TP 8 X.B \-e N XSet expirey period of all read news groups to 'N'. XThe default value for this is 14 days. X.TP 8 X.B \-r N XSet retention period of all read news groups to 'N'. XThe default value for this is 14 days. X.TP 8 X.B \-p N XSet purge period of all read news groups to 'N'. XThe default value for this is 14 days. X.TP 8 X.B \-E N XSet expirey period of all unread news groups to 'N'. XThe default value for this is 1 day. X.TP 8 X.B \-R N XSet retention period of all unread news groups to 'N'. XThe default value for this is 1 day. X.TP 8 X.B \-P N XSet purge period of all unread news groups to 'N'. XThe default value for this is 1 day. X.TP 8 X.B \-s XTakes user id 0 account ".newsrc" files into account \(em a lot of Xsites have multiple roots, with each having their usual home Xdirectory (eg. the one for their non-administrative account). XIn a situation like this there is no reason to pay the extra Xoverhead of checking their ".newsrc" file twice. X.sp XThe default is to ignore user id 0 accounts. X.TP 8 X.B \-v XTurns on verbose output mode. X.PP XWe can find out what user ``.newsrc'' files are Xchecked with: X.nf X.ft CW X X.B X % \*b/expire/pexpire -v | sed '/^$/,$d' X X Read 511 groups out of the active file. X Checked against 10 patterns in the default-expire file. X Checking against .newsrc for user "sartin" X Checking against .newsrc for user "taylor" X Checking against .newsrc for user "jin" X Checking against .newsrc for user "markc" X X.ft R X.fi X.PP X.I Dopexpire Xchecks whether another \fIdopexpire\fR is running, Xchecks that there is enough disk space for expiry and archiving, Xbuilds the temporary expire list using \fIpexpire\fR and \fI\*c/pexplist\fR, Xinvokes \fIexpire\fR with any \fIexpireoptions\fR given and with Xtemporary expire list as the control file, Xand reports any difficulties by sending mail to \fI\*m\fR. XThis is usually better than just running \fIexpire\fR directly. XIf space is adequate for archiving but persistently inadequate for the Xtemporaries needed for history rebuilding, \fIdopexpire\fR reports this Xand invokes \fIexpire\fR with the \fB\-r\fR option. X.SH AUTHOR XDave Taylor, Hewlett-Packard Company (taylor\s-1@\s+1hplabs.hp.com) X.br XModified for Cnews by Jim Pickering (jrp\s-1@\s+1rducky) X.SH FILES X.nf X.if n .ta 26 X.if t .ta 20 X/etc/passwd for accounts to check ".newsrc" files X$USER/.newsrc for each account on the machine, to check X\*c/active where the netnews active file lives X\*c/pexplist where the system default pexpire list lives X\*c/LOCKexpire lock file X\*c/L.$$ lock file X/bin/sh valid login shell for user X/bin/csh valid login shell for user X/bin/ksh valid login shell for user X/bin/rsh valid login shell for user X.SH SEE ALSO Xexpire(8), doexpire(8) END_OF_FILE if test 3939 -ne `wc -c <'cpexpire.1'`; then echo shar: \"'cpexpire.1'\" unpacked with wrong size! fi # end of 'cpexpire.1' fi if test -f 'dopexpire' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'dopexpire'\" else echo shar: Extracting \"'dopexpire'\" \(2449 characters\) sed "s/^X//" >'dopexpire' <<'END_OF_FILE' X#! /bin/sh X# dopexpire - overall administration for expire using pexpire X X# =()<. ${NEWSCONFIG-@@}>()= X. ${NEWSCONFIG-/usr/lib/news/bin/config} X XPATH=$NEWSCTL/bin:$NEWSBIN/expire:$NEWSBIN:$NEWSPATH ; export PATH Xumask $NEWSUMASK X Xlock="$NEWSCTL/LOCKexpire" Xltemp="$NEWSCTL/L.$$" X X# retention, expire, and purge defaults for 'all' groups that we may have X# missed with pexpire or our default file Xretention_default="0" Xexpirey_default="0" Xpurge_default="0" X X#sysadmin supplied expiration defaults Xdefaults_file="$NEWSCTL/pexplist" X X# expire list generated by pexpire Xpexpire_list="/tmp/pexpire$$" Xpexpire_tmp="/tmp/pexptmp$$" X X# expired and bounds strings for expire(8) Xexpire_string="/expired/\tx\t14\t-" Xbounds_string="/bounds/\tx\t0-1-90\t-" X Xecho $$ >$ltemp Xtrap "rm -f $ltemp ; exit 0" 0 1 2 15 Xif newslock $ltemp $lock Xthen X trap "rm -f $ltemp $lock ; exit 0" 0 1 2 15 Xelse X echo "$0: expire apparently already running" | mail "$NEWSMASTER" X exit 1 Xfi X Xif test " `spacefor 1 archive`" -le 0 Xthen X echo "$0: not enough space for archiving" | mail "$NEWSMASTER" X exit 1 Xfi X Xcd $NEWSCTL Xropt=-r Xfor counter in x x x x # four tries Xdo X size="`sizeof history history.pag history.dir`" X if test " `spacefor $size control`" -gt 0 X then X ropt= X break X fi X sleep 600 # and hope it will improve Xdone Xif test " $ropt" = " -r" Xthen X echo "$0: short of space for temporaries, resorting to \`expire -r'" | X mail "$NEWSMASTER" Xfi X Xtrap "rm -f $pexpire_list $ltemp $lock ; exit 0" 0 1 2 15 X Xecho $expire_string > $pexpire_list Xecho $bounds_string >> $pexpire_list Xif test -s $defaults_file Xthen X cat $defaults_file >> $pexpire_list Xfi Xtrap "rm -f $pexpire_list $pexpire_tmp $ltemp $lock ; exit 0" 0 1 2 15 Xpexpire -E 0.5 -R 0.5 -P 0.5 -e 14 -r 14 -p 14 > $pexpire_tmp 2>/tmp/doex$$ Xif test -s /tmp/doex$$ Xthen X (echo 'pexpire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER" X rm -f /tmp/doex$$ X exit 1 Xfi X# sort in reverse order so groups at top of hierarchy don't expire lower X# groups, i.e. rec.humor may affect rec.humor.funny if before Xsort -r $pexpire_tmp >> $pexpire_list Xrm -f $pexpire_tmp Xtrap "rm -f $pexpire_list $ltemp $lock ; exit 0" 0 1 2 15 Xecho "all\tx\t$retention_default-$expirey_default-$purge_default\t-" >> $pexpire_list Xexpire $ropt $* $pexpire_list 2>/tmp/doex$$ Xif test -s /tmp/doex$$ Xthen X (echo 'expire problems:' ; cat /tmp/doex$$ ) | mail "$NEWSMASTER" X rm -f /tmp/doex$$ X exit 1 Xfi Xrm -f /tmp/doex$$ Xexit 0 END_OF_FILE if test 2449 -ne `wc -c <'dopexpire'`; then echo shar: \"'dopexpire'\" unpacked with wrong size! fi chmod +x 'dopexpire' # end of 'dopexpire' fi if test -f 'pexpire.batch' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pexpire.batch'\" else echo shar: Extracting \"'pexpire.batch'\" \(446 characters\) sed "s/^X//" >'pexpire.batch' <<'END_OF_FILE' X# Use /bin/sh X# expire news using pexpire() X# script written by Rob Sartin, HP (sartin@hplabs.hp.com) Xexpire_script="/tmp/expire$$" Xtrap 'rm -f $expire_script' 0 1 2 3 15 X X# display our disk space utilization before the command ... X XPEXPIRE=/usr/lib/news/pexpire X X# create the new expire script X X${PEXPIRE} > ${expire_script} 2>/dev/null Xchmod 0750 ${expire_script} X X# and execute it: X X${expire_script} > /dev/null 2>&1 X X# and we're done. Xexit 0 END_OF_FILE if test 446 -ne `wc -c <'pexpire.batch'`; then echo shar: \"'pexpire.batch'\" unpacked with wrong size! fi chmod +x 'pexpire.batch' # end of 'pexpire.batch' fi if test -f 'pexpire.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pexpire.c'\" else echo shar: Extracting \"'pexpire.c'\" \(21446 characters\) sed "s/^X//" >'pexpire.c' <<'END_OF_FILE' X/** pexpire.c **/ X X/** This program is designed to set the expire dates of newsgroups according X to whether they are read locally or not. The idea is that it is easy X to go into users .newsrc files and compile an overall list of who reads X what groups, then 1-day-expire those groups that no-one is reading. X X This hinges on the availability of other local machines to serve as X archives for various groups, as well as the understanding of the X local users that subscribing to a new newsgroup will more than likely X net you almost *no* new articles -- but will allow the news to flow X in normally and then gradually build up to a more reasonable level. X X (C) Copyright 1988 Dave Taylor X X *************************************************************************** X ** Permission is granted for unlimited modification, use, and dist- ** X ** ribution, except that this software may not be sold for profit ** X ** directly nor as part of any software package. This software is made ** X ** available with no warranty of any kind, express or implied. ** X *************************************************************************** X X**/ X X#include X#include X X#include "pexpire.h" X X#define ROOT_UID 0 /* who's root? */ X X#define MAX_GROUPS 1024 /* should be sufficient */ X X#define SLEN 128 X X#define COLON ':' X X#ifndef TRUE X# define TRUE 1 X# define FALSE 0 X#endif X X/** some easy to read and use macro functions **/ X X#define whitespace(c) (c == ' ' || c == '\t') X#define matches(re,pat) (regex(re, pat) != NULL) X X#define plural(n) (n == 1 ? "" : "s") X X/** and data structures/global variables for the program **/ X Xstruct group_rec { X char *name; X int is_read; X#ifndef CNEWS X int read_expire; X int unread_expire; X#endif X }; X Xchar *login_shells[] = { "/bin/sh", "/bin/csh", "/bin/ksh", "/bin/rsh", "" }; X Xstruct group_rec groups[MAX_GROUPS]; X Xint group_count = 0, /** total number of groups **/ X verbose = FALSE, /** lots of output? **/ X#ifndef CNEWS X comma_separated = TRUE, /** output list format **/ X groups_per_cmd, /** .. and more too **/ X X min_history_expire, /** for the expire() cmd **/ X max_history_expire, /** " " **/ X default_history_expire, /** " " **/ X X output_one_per_line = FALSE, /** final output format **/ X#endif X include_root = FALSE; /** include root .newsrc? **/ X X#ifndef CNEWS Xchar *prog_name, /** program name for errors **/ X expire_cmd[SLEN]; /** expire cmd we'll use **/ X#else Xchar *prog_name; /** program name for errors **/ Xdouble read_retention_period, X read_purge_period, X read_expirey_period, X unread_retention_period, X unread_purge_period, X unread_expirey_period; X#endif X X/** forward definitions and other stuff to keep LINT a happy clam **/ X Xchar *regcmp(), *regex(), *strcpy(), *strcat(), *strchr(), *malloc(); Xvoid exit(), perror(), qsort(); X X/** The algorithm that we'll be using here is: X X 1. Read in the active file to get a list of all newsgroups available X X 2. Go through the ``EXPIRE_DEFAULTS'' file (bnews version) to set initial X expiration dates (typically by high level groups -- it's left rooted). X This file typically has two sets of numbers, the first being for groups X that are being actively read, the second being for those that are X not. For example: X X soc.* 24 1 X X would set any soc.* group to a 24 day expire if read, and a 1 day X expire if not. X X 3. Then, for each user of the system: X X if they have a .newsrc, X tag as 'read' any group that the user subscribes to X X 4. Sort the newsgroups by expiration date (bnews version), then output a X shell script suitable for automatic execution (bnews version) or output X an expire list file for expire(1) (cnews version) ... X X**/ X Xmain(argc, argv) Xchar *argv[]; X{ X extern char *optarg; X int c; X X /** first off let's grab the program name for error messages **/ X X prog_name = *argv; X X /** initialize some values that can be changed by the user **/ X#ifndef CNEWS X groups_per_cmd = DEFAULT_GROUPS_PER_LINE; X X max_history_expire = DEFAULT_MAX_HISTORY_EXPIRE; X min_history_expire = DEFAULT_MIN_HISTORY_EXPIRE; X X default_history_expire = DEFAULT_HISTORY_EXPIRE; X X (void) strcpy(expire_cmd, EXPIRE); X X /** now process the starting arguments **/ X X while ((c = getopt(argc, argv, "a:ch:H:e:g:rov")) != EOF) { X#else X read_retention_period = READ_RETENTION_DEFAULT; X read_purge_period = READ_PURGE_DEFAULT; X read_expirey_period = READ_EXPIREY_DEFAULT; X unread_retention_period = UNREAD_RETENTION_DEFAULT; X unread_purge_period = UNREAD_PURGE_DEFAULT; X unread_expirey_period = UNREAD_EXPIREY_DEFAULT; X while ((c = getopt(argc, argv, "r:e:p:R:E:P:sv")) != EOF) { X#endif X switch (c) { X X#ifndef CNEWS X case 'a' : default_history_expire = atoi(optarg); X break; X X case 'c' : comma_separated = TRUE; X break; X X case 'e' : (void) strcpy(expire_cmd, optarg); X break; X X case 'g' : groups_per_cmd = atoi(optarg); X break; X X case 'h' : min_history_expire = atoi(optarg); X break; X X case 'H' : max_history_expire = atoi(optarg); X break; X X case 'r' : include_root = TRUE; X break; X X case 'o' : output_one_per_line = TRUE; X break; X X case 'v' : verbose = TRUE; X break; X X default : (void) fprintf(stderr, X "\nUsage: %s [-a n] [-c] [-e cmd] [-g] [-h n] [-H n] [-r] [-o] [-v]\n", X prog_name); X (void) fprintf(stderr,"\nWhere:\n"); X (void) fprintf(stderr, X " -a n \tset default history expire value to 'n' (see the man page)\n"); X (void) fprintf(stderr, X " \t(the current default is set to %d day%s)\n", X DEFAULT_HISTORY_EXPIRE, X plural(DEFAULT_HISTORY_EXPIRE)); X (void) fprintf(stderr, X " -c \tmake the groupname list comma separated, rather than space\n"); X (void) fprintf(stderr, X " -e cmd\tuses 'cmd' for output rather than the default expire program\n"); X (void) fprintf(stderr, X " \t(current default set to \"%s\")\n", EXPIRE); X (void) fprintf(stderr, X " -g n \tforces `n' or less groups output per command (default = %d)\n", X DEFAULT_GROUPS_PER_LINE); X (void) fprintf(stderr, X " -h n \tset the default minimum history expire value to 'n'\n"); X (void) fprintf(stderr, X " \t(the current default is set to %d day%s)\n", X DEFAULT_MIN_HISTORY_EXPIRE, X plural(DEFAULT_MIN_HISTORY_EXPIRE)); X (void) fprintf(stderr, X " -H n \tset the default maximum history expire value to 'n'\n"); X (void) fprintf(stderr, X " \t(the current default is set to %d day%s)\n", X DEFAULT_MAX_HISTORY_EXPIRE, X plural(DEFAULT_MAX_HISTORY_EXPIRE)); X (void) fprintf(stderr, X " -r \ttakes UID 0 account .newsrc files into account\n"); X (void) fprintf(stderr, X " -o \tforces one-group-per-line output format\n"); X (void) fprintf(stderr, X " -v \tturns on verbose output mode\n\n"); X exit(0); X#else X case 's' : include_root = TRUE; X break; X X case 'v' : verbose = TRUE; X break; X X case 'r' : read_retention_period = atof(optarg); X sscanf(optarg,"%lg",&read_retention_period); X break; X X case 'p' : read_purge_period = atof(optarg); X sscanf(optarg,"%lg",&read_purge_period); X break; X X case 'e' : read_expirey_period = atof(optarg); X sscanf(optarg,"%lg",&read_expirey_period); X break; X X case 'R' : X sscanf(optarg,"%lg",&unread_retention_period); X break; X X case 'P' : X sscanf(optarg,"%lg",&unread_purge_period); X break; X X case 'E' : X sscanf(optarg,"%lg",&unread_expirey_period); X break; X X default : (void) fprintf(stderr, "\nUsage: %s [-r n] [-e n] [-p n] [-R n] [-E n] [-P n] [-s] [-v]\n", prog_name); X (void) fprintf(stderr,"\nWhere:\n"); X (void) fprintf(stderr, "\t-r n\tset retention period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_RETENTION_DEFAULT); X (void) fprintf(stderr, "\t-e n\tset expirey period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_EXPIREY_DEFAULT); X (void) fprintf(stderr, "\t-p n\tset purge period for read news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", READ_PURGE_DEFAULT); X (void) fprintf(stderr, "\t-R n\tset retention period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_RETENTION_DEFAULT); X (void) fprintf(stderr, "\t-E n\tset expirey period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_EXPIREY_DEFAULT); X (void) fprintf(stderr, "\t-P n\tset purge period for unread news groups to 'n',\n\t\twhere 'n' may be a decimal fraction (default = %g).\n", UNREAD_PURGE_DEFAULT); X (void) fprintf(stderr, "\t-s\ttakes UID 0 account .newsrc files into account\n"); X (void) fprintf(stderr, "\t-v\tturns on verbose output mode\n\n"); X exit(0); X#endif X } X } X X /** next let's read in the netnews active file **/ X X read_active_file(); X X /** read in the EXPIRE_DEFAULTS file and set default expires **/ X#ifndef CNEWS X set_default_expiration_dates(); X#endif X /** check each user for a .newsrc and mark groups subscribed **/ X X check_each_user(); X X /** whip through a quick resort by expiration time **/ X#ifndef CNEWS X sort_groups_by_expiration(); X#endif X /** and finally output the script that we can execute **/ X X output_script(); X X /** and we're done **/ X X return(0); X} X Xread_active_file() X{ X /** this routine reads in the active file, sorts it, and X returns. It is assumed that it always works - if something X fails it will exit from here.. X **/ X X int compare(); X X FILE *fd; X char buffer[SLEN]; X register int i; X X if ((fd = fopen(ACTIVE_FILE, "r")) == NULL) { X (void) fprintf(stderr,"%s: cannot open active file '%s':\n", X prog_name, ACTIVE_FILE); X perror("fopen"); X exit(1); X } X X while (fgets(buffer, SLEN, fd) != NULL) { X X /** get just the first word ... **/ X X for (i=0; ! whitespace(buffer[i]); i++) ; X buffer[i] = '\0'; X X if ((groups[group_count].name = malloc((unsigned)(i+1))) == NULL) { X (void) fprintf(stderr,"%s: couldn't malloc memory for group '%s'\n", X prog_name, buffer); X perror("malloc"); X exit(1); X } X X /** now load up the new record and increment our counter **/ X X (void) strcpy(groups[group_count].name, buffer); X groups[group_count].is_read = FALSE; X#ifndef CNEWS X groups[group_count].read_expire = DEFAULT_READ_EXPIRE; X groups[group_count].unread_expire = DEFAULT_UNREAD_EXPIRE; X#endif X X group_count++; X X /** and on to the next one... **/ X } X X (void) fclose(fd); X X qsort(groups, (unsigned) group_count, X sizeof (struct group_rec), compare); X X if (verbose) X (void) printf("Read %d group%s out of the active file.\n", X group_count, plural(group_count)); X} X X#ifndef CNEWS Xset_default_expiration_dates() X{ X /** this routine is responsible for reading in the default X expire file and setting the default expiration dates on X all of the groups in memory. If there is no file or it X is impossible to get to, then the defaults indicated in X this program will be used for all groups. X X The format of the file is quite simple: X X < tab > <+expire> <-expire> X X where +expire is the expiration time if people are reading X the group, and -expire is if they're not. The regular X expression format is that of regex(3c), so you can have X structures such as "^comp.*" and so on. X **/ X X FILE *fd; X char buffer[SLEN], *regular_expression; X int read_expire, unread_expire; X register int i, count = 0; X X if ((fd = fopen(EXPIRE_DEFAULTS, "r")) == NULL) { X (void) fprintf(stderr,"%s: Couldn't read file '%s'\n", X prog_name, EXPIRE_DEFAULTS); X (void) fprintf(stderr, X "(Using default expirations: read = %d, unread = %d)\n", X DEFAULT_READ_EXPIRE, DEFAULT_UNREAD_EXPIRE); X perror("fopen"); X (void) fprintf(stderr,"---\n"); X X /** now spin through setting all expire dates accordingly **/ X X for (i=0; i < group_count; i++) { X groups[i].read_expire = DEFAULT_READ_EXPIRE; X groups[i].unread_expire = DEFAULT_UNREAD_EXPIRE; X } X X return; X } X X /** if we've gotten here we've got the file open and ready X to work with... **/ X X while (fgets(buffer, SLEN, fd) != NULL) { X X if (buffer[0] == '#' || strlen(buffer) < 3) continue; X X (void) sscanf(buffer, "%*s %d %d", &read_expire, &unread_expire); X X count++; X X for (i=0;! whitespace(buffer[i]); i++) ; X buffer[i] = '\0'; X X /** now apply this pattern to all groups we've got, setting X the expire date as makes sense... **/ X X regular_expression = regcmp(buffer, (char *) 0); X X for (i=0 ; i < group_count; i++) X if (matches(regular_expression, groups[i].name)) { X groups[i].unread_expire = unread_expire; X groups[i].read_expire = read_expire; X } X } X X (void) fclose(fd); X X if (verbose) X (void) printf("Checked against %d pattern%s in default-expire file.\n", X count, plural(count)); X} X#endif X Xcheck_each_user() X{ X /** this routine goes through the /etc/passwd file to X find all the users on the machine. For each entry X found, it will ascertain if they have a login shell X then look for a .newsrc file. If they have one, it X will extract all the groups that they currently read, X marking each in memory as being read .. X **/ X X FILE *fd; X struct passwd *getpwent(), *pass; X char newsrc[SLEN], buffer[SLEN], user_list[SLEN]; X register int i; X X /** initialize **/ X X user_list[0] = '\0'; X X /** and step through the password file .. **/ X X while ((pass = getpwent()) != NULL) { X /*if (has_login_shell(pass->pw_shell)) { */ X X if (pass->pw_uid == ROOT_UID && ! include_root) X continue; X X (void) sprintf(newsrc, "%s/%s", pass->pw_dir, NEWSRC); X X if ((fd = fopen(newsrc, "r")) == NULL) continue; X X if (verbose) X (void) printf("Checking against %s for user \"%s\"\n", X NEWSRC, pass->pw_name); X else { X if (user_list[0] != '\0') (void) strcat(user_list, " "); X (void) strcat(user_list, pass->pw_name); X } X X while (fgets(buffer, SLEN, fd) != NULL) X if (strchr(buffer, COLON) != (char *) NULL) { X for (i=0;buffer[i] != COLON; i++); X buffer[i] = '\0'; X mark_as_read(buffer); X } X X (void) fclose(fd); X /*}*/ X } X X if (verbose && strlen(user_list) > 0) X (void) fprintf(stderr, X "Checked against \"%s\" for the following users:\n\t%s\n", X NEWSRC, user_list); X} X X#ifndef CNEWS Xsort_groups_by_expiration() X{ X /** We now resort the list according to the expiration date of X the group... X **/ X X int compare_expirations(); X X qsort(groups, (unsigned) group_count, sizeof (struct group_rec), X compare_expirations); X} X#endif X Xoutput_script() X{ X /** Now that we've gotten the groups sorted by their X expiration date, we can output a script that is suitable X for input to the real netnews expire() program... X **/ X X register int i; X#ifndef CNEWS X int current_expire_time = 0, expire, X groups_on_line = 0, on_line = 0, in_expiration = 0; X X /** set the current expiration time, then: X for each group that has the same date X output the group name X when we hit a new date output the new format line X **/ X X for (i=0; i < group_count; i++) { X X /** set the expiration time based on if the group is X currently being read or not... X **/ X X expire = groups[i].is_read ? groups[i].read_expire : X groups[i].unread_expire; X X if (output_one_per_line) { X if (expire > max_history_expire) X (void) printf("%s -e %d -E %d -n %s\n", X expire_cmd, expire, expire, groups[i].name); X else if (expire < min_history_expire) X (void) printf("%s -e %d -E %d -n %s\n", X expire_cmd, expire, default_history_expire, X groups[i].name); X else X (void) printf("%s -e %d -n %s\n", X expire_cmd, expire, groups[i].name); X } X else { X if ( expire != current_expire_time || X in_expiration > groups_per_cmd) { X if (expire > max_history_expire) X (void) printf("\n%s -e %d -E %d -n ", X expire_cmd, expire, expire); X else if (expire < min_history_expire) X (void) printf("\n%s -e %d -E %d -n ", X expire_cmd, expire, default_history_expire); X else X (void) printf("\n%s -e %d -n ", expire_cmd, expire); X groups_on_line = 0; X current_expire_time = expire; X in_expiration = 0; X } X X in_expiration++; X X on_line += strlen(groups[i].name) + 1; X X if (on_line > 66) { X (void) printf("%c \\\n\t", groups_on_line > 0? ',':' '); X on_line = 8 + strlen(groups[i].name); X groups_on_line = 0; X } X X if (groups_on_line) X (void) printf("%c%s", comma_separated? ',' : ' ', groups[i].name); X else X (void) printf("%s", groups[i].name); X X groups_on_line++; X } X } X (void) printf("\n"); X#else X for (i=0; i < group_count; i++) { X X /** set the expiration time based on if the group is X currently being read or not... X **/ X X if (groups[i].is_read) X (void) printf("%s\tx\t%g-%g-%g\t-\n",groups[i].name, read_retention_period, read_expirey_period, read_purge_period); X else X (void) printf("%s\tx\t%g-%g-%g\t-\n",groups[i].name, unread_retention_period, unread_expirey_period, unread_purge_period); X } X#endif X} X Xint Xcompare(a,b) Xstruct group_rec *a, *b; X{ X /** strcmp() routine for our data structure, rather than the X simple expedient of just using strcmp directly. See the X invocation of qsort() above X **/ X X return( strcmp(a->name, b->name) ); X} X X#ifndef CNEWS Xint Xcompare_expirations(a, b) Xstruct group_rec *a, *b; X{ X /** strcmp() routine for data for second sort -- this one X is a sort by the expiration date of the groups. To X do this we want to look at the is_read flag and from X that decide which of the two expiration dates we want to be X looking at. X **/ X X return ( (b->is_read ? b->read_expire : b->unread_expire) - X (a->is_read ? a->read_expire : a->unread_expire) ); X} X#endif X Xint Xhas_login_shell(shell_name) Xchar *shell_name; X{ X /** returns TRUE iff the shell given is contained in the X list of possible login shells compiled with. X **/ X X register int i; X X for (i=0; login_shells[i][0] != '\0'; i++) X if (strcmp(login_shells[i], shell_name) == 0) return(TRUE); X X return(FALSE); X} X Xmark_as_read(name) Xchar *name; X{ X /** Mark the group specified as being read -- it's extracted X from a users .newsrc file. X **/ X X int index; X X if ((index = find_group(name)) == -1) X (void) fprintf(stderr, X "** Couldn't find group '%s' in internal tables?? **\n", X name); X else X groups[index].is_read = TRUE; X} X Xint Xfind_group(name) Xchar *name; X{ X /** A binary search of the list to find the group - returns the X index into the 'groups' array of the group, or '-1' if not X in the list. X **/ X X register int first = 0, last, middle, difference; X X last = group_count-1; X X while (first <= last) { X middle = ((first+last) / 2); X X difference = strcmp(name, groups[middle].name); X X if (difference < 0) X last = middle - 1; X else if (difference == 0) X return(middle); X else X first = middle + 1; X } X X return(-1); X} END_OF_FILE if test 21446 -ne `wc -c <'pexpire.c'`; then echo shar: \"'pexpire.c'\" unpacked with wrong size! fi # end of 'pexpire.c' fi if test -f 'pexpire.defs' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pexpire.defs'\" else echo shar: Extracting \"'pexpire.defs'\" \(1087 characters\) sed "s/^X//" >'pexpire.defs' <<'END_OF_FILE' X# X# This is the "pexpire" default expiration times file. The format of this X# file is: X# X# <+expire> <-expire> X# X# where <+expire> is the expiration date for groups that are currently X# read by people on this machine, <-expire> are for those that are unread, X# and is any regular expression as per regexp(3c). X# X# It is recommended that you have ".*" as the first expression so that you X# can set the default expiration for all groups. The processing order of X# this information is: X# for each pattern read in this file: X# for each group in the active file: X# if the pattern matches, set the dates accordingly. X# X# this means that the patterns "^comp.*" and "source" in that order X# would result in "comp.unix.sources" having the source expire times. X# X# NOTE: never lead an expression with an asterisk -- assume all patterns X# are unrooted, and use '^' to get them left rooted if you want to X.* 14 1 X^comp.* 8 2 X^talk.* 2 1 X^soc.* 2 1 X^news.* 5 2 X^ba.* 2 1 X^ca.* 2 1 X^misc.* 5 1 X^sci.* 2 1 X^slo.* 2 1 END_OF_FILE if test 1087 -ne `wc -c <'pexpire.defs'`; then echo shar: \"'pexpire.defs'\" unpacked with wrong size! fi # end of 'pexpire.defs' fi if test -f 'pexpire.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pexpire.h'\" else echo shar: Extracting \"'pexpire.h'\" \(4166 characters\) sed "s/^X//" >'pexpire.h' <<'END_OF_FILE' X/** pexpire.h **/ X X/**************************************************************************** X This set of defines are those that might need to be localized or otherwise X customized for your local system and setting. X ****************************************************************************/ X X/** first off, where's your netnews active file? It'd be a suprise if X it wasn't as indicated here, but you can change it if you want. X**/ X#define ACTIVE_FILE "/usr/lib/news/active" X X/** NEWSRC is simply the name of the file kept in users home directories **/ X#define NEWSRC ".newsrc" X X X X X#ifndef CNEWS X/***********************/ X/***********************/ X/** define for Bnews **/ X/***********************/ X/***********************/ X X/** Next, the pexpire program has a default set of rules X that can be applied to the set of groups to determine the expiration dates X either by top-level newsgroup (eg. "comp.*") or down to the X specific group (eg. "comp.sys.hp"). Please see the expire man X page for more discussion of this file. X**/ X X#define EXPIRE_DEFAULTS "/usr/lib/news/pexpire.defs" X#endif X X X/** Finally, this is the command used for expiration of news (bnews version). X Most likely it'll be located in the same directory as the active file X (see above). If you're running a strange expire command you might want X to check to ensure it understands "-e", "-E" and "-n" flags... see the man X page for further details. X**/ X X#ifndef CNEWS X#define EXPIRE "/usr/lib/news/expire" X X/** the default history expire (bnews version) is the standard number of days X that an article is allowed to live in the history file -- regardless of how X long it is on the machine in actual text form. (This is different so that X you don't get into looping trouble with very fast expires and multiple news X feeds). X X The netnews source has HISTEXP and DFLTEXP in seconds, and for our X own use, we'll change those back into days ... X**/ X X#define DEFAULT_MAX_HISTORY_EXPIRE (HISTEXP / DAYS) X#define DEFAULT_MIN_HISTORY_EXPIRE (DFLTEXP / DAYS) X X/** if a group is being expired at less than the default minimum history X exiration time (bnews version), then we want to ensure that we have the X default time rather than the one specific to the group. That is, if we X have a group with a 1 day expire, we still want to keep the articles X in the history file for, say, 2 weeks... X**/ X X#define DEFAULT_HISTORY_EXPIRE (HISTEXP / DAYS) X X/** next, if the program cannot find your pexpire.default file (bnews version), X it will us the next two settings as the default for groups that are being X subscribed to and those that are not. Recommended that the unread X expire not be incredibly short here in case the daemon messes up one X night - you might come back and a major chunk of news is gone! X**/ X X#define DEFAULT_READ_EXPIRE 7 X#define DEFAULT_UNREAD_EXPIRE 0 X X/** finally, when the program outputs the commands for eventual shell X execution (bnews version), it tries to keep them in a format that the X netnews expire(UTIL) command can deal with. One of the problems is that X it is possible to have all 400 - 500 groups expire at the same X time, and it's too much for a single invocation. Instead, you can X fine tune this to be the largest value possible, but smaller than X the max limit of expire(). X**/ X X#define DEFAULT_GROUPS_PER_LINE 30 X X/************** end of local customization for Bnews ******************/ X X#define DAYS (60L*60L*24L) X#define WEEKS (7*DAYS) X#define DFLTEXP 2*WEEKS /* default no. of seconds to expire in */ X#define HISTEXP 4*WEEKS /* default no. of seconds to forget in */ X#else X X/***********************/ X/***********************/ X/** defines for Cnews **/ X/***********************/ X/***********************/ X X/* X** read/unread default retention, purge, and expirey days X*/ X#define READ_RETENTION_DEFAULT 14.0 X#define READ_PURGE_DEFAULT 14.0 X#define READ_EXPIREY_DEFAULT 14.0 X#define UNREAD_RETENTION_DEFAULT 1.0 X#define UNREAD_PURGE_DEFAULT 1.0 X#define UNREAD_EXPIREY_DEFAULT 1.0 X X X#endif END_OF_FILE if test 4166 -ne `wc -c <'pexpire.h'`; then echo shar: \"'pexpire.h'\" unpacked with wrong size! fi # end of 'pexpire.h' fi if test -f 'pexplist' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pexplist'\" else echo shar: Extracting \"'pexplist'\" \(389 characters\) sed "s/^X//" >'pexplist' <<'END_OF_FILE' X# X# pexplist X# X# This file contains entries that override later defaults generated by pexpire. X# See dopexpire for use and expire(8) for format. X# X X# big non-tech groups held long enough for a long weekend X#ca,ba,sci,rec,talk,soc,misc,alt x 4-4-4 - X X# real noise gets thrown away fast Xjunk,control x 1-1-1 - X X# dump all maps ... dopexpire being run by uuhosts Xcomp.mail.maps x 0-0-0 - END_OF_FILE if test 389 -ne `wc -c <'pexplist'`; then echo shar: \"'pexplist'\" unpacked with wrong size! fi # end of 'pexplist' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have tne archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0