home *** CD-ROM | disk | FTP | other *** search
- From: dt@yenta.alb.nm.us (David B. Thomas)
- Newsgroups: alt.sources,unix-pc.sources
- Subject: reap: expire news as space needed
- Message-ID: <1990Nov27.073400.7561@yenta.alb.nm.us>
- Date: 27 Nov 90 07:34:00 GMT
-
- Hello, netters! Here's an expire alternative. If you have a small disk,
- this is for you. It was inspired by Mike Murphy's "trasher" posted a few
- weeks ago.
-
- Problem:
- News volume fluctuates wildly...sites with small disks must either
- expire aggresively, often deleting more than necessary, or worry that an
- unexpected huge dose of news might overfill the disk.
-
-
- Solution:
- Implement a tool that expires according to a user-defined scheme
- until sufficient freespace is reclaimed, then stops, leaving as much
- juicy news online as is feasible. Reap does this.
-
-
- Expire Does Two Jobs:
- Both Bnews and Cnews expires really do two jobs:
- 1. trim history files
- 2. delete outdated articles
- Thanks to some inspired jootsing (acronym for "jumping out of the system")
- by Mike Murphy (mrm@sceard.com) and others, it is more than possible to
- separate those two functions. This is, of course, in keeping with the
- unix philosophy of one tool doing one job well!
-
-
- What Reap Does:
- Reap only takes care of the second job: deleting old articles.
- It works by checking freespace, and processing one line at a time from a
- list of expire functions, until the desired freespace is attained.
- Each expire function consists of an age limit in days (decimals okay)
- and a list of newsgroups to process or not process, sys file style. Ex:
-
- .5 alt.sex.pictures,talk,!talk.bizarre,junk
- 1 rec,!rec.games,!rec.humor
-
- This example would check freespace, and if more space is needed, expire
- to .5 days everything in alt.sex.pictures,talk (except for talk.bizarre)
- and junk. Then it would stop and check freespace again. If still more
- space is needed, it would expire to 1 day everything in rec except
- rec.games.* and rec.humor.*. It's that simple.
-
-
- Okay...So How Do I Arrange To Trim The History Files, Since Reap Can't:
- Included in this distribution is a shell script (mostly written
- by Mike Murphy) to handle Cnews history files. It shouldn't be too
- difficult to do something similar for Bnews, or you can give in and use
- the original expire utility with options that tell it to expire the
- history files only...but I think that would be slow. It just comes down
- to removing lines from ordinary text files, based on their contents.
- Murphy and I used awk.
-
-
- But Is It Fast:
- Yes, largely because it doesn't have to do much. Even "find | rm"
- is slower because find is repeatedly exec-ing rm.
-
- Since the functions of deleting articles and trimming history
- are separate, I now run reap every few hours, but trim the history list
- just once a day. That effectively keeps my disk space up to snuff, but
- only thrashes at the history file in the middle of the night.
-
-
- Credits:
- I owe a lot to Mike Murphy for inspiring me with his "trasher"
- system. I also owe a lot to all of your netters who will flood me with
- suggestions and improvements in the coming weeks (hint, hint!).
-
- Note: this uses ustat(2), a system-V call to find disk freespace. It should
- be a very easy hack to use the BSD equivalent. I just don't know how to do
- it.
-
- little david
- dt@yenta.alb.nm.us
-
- -----snip-----------snip-----------snip-----------snip-----------snip------
- #!/bin/sh
- # This is a shell archive (shar 3.44)
- # made 11/27/1990 07:20 UTC by dt@yenta
- # Source directory /u/dt/reap
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 730 -rw-rw-r-- INSTALL
- # 339 -rw-rw-r-- MANIFEST
- # 900 -rw-rw-r-- Makefile
- # 2792 -rw-rw-r-- README
- # 969 -rwxrwxr-x exphist
- # 2539 -rw-rw-r-- lib.c
- # 873 -rw-rw-r-- list.sample
- # 2028 -rw-rw-r-- main.c
- # 2335 -rw-r--r-- reap.8
- # 2150 -rw-rw-r-- reap.c
- # 676 -rw-rw-r-- reap.h
- #
- # ============= INSTALL ==============
- if test -f 'INSTALL' -a X"$1" != X"-c"; then
- echo 'x - skipping INSTALL (File already exists)'
- else
- echo 'x - extracting INSTALL (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'INSTALL' &&
- X
- To install:
- X
- 1. Edit tops of Makefile and main.c to fit your system.
- 2. make
- 3. Compose a sample function list file or use the sample provided to
- X test reap (use the -n option to avoid really removing files).
- 4. su and make install.
- 5. Arrange to trim your news system's history list regularly. If you have
- X Cnews, try the "exphist" script provided, run from cron. That
- X script requires that a tiny file, /usr/lib/news/histdays, contain
- X the number of days of history data to keep, or else you can hardcode
- X in your favorite number. If you have Bnews, I don't have a nifty
- X suggestion, other than using expire(8) with a ridiculously long
- X article expire time, but a sane history expire time.
- 6. Arrange to run reap from cron.
- SHAR_EOF
- chmod 0664 INSTALL ||
- echo 'restore of INSTALL failed'
- Wc_c="`wc -c < 'INSTALL'`"
- test 730 -eq "$Wc_c" ||
- echo 'INSTALL: original size 730, current size' "$Wc_c"
- fi
- # ============= MANIFEST ==============
- if test -f 'MANIFEST' -a X"$1" != X"-c"; then
- echo 'x - skipping MANIFEST (File already exists)'
- else
- echo 'x - extracting MANIFEST (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'MANIFEST' &&
- Included with this distribution are:
- X
- README - general description and credits
- INSTALL - hints on how to install reap and get it going
- Xexphist - history trimmer utility for Cnews
- list.sample - sample function script file for reap
- reap.8 - man page
- lib.c - source
- main.c - source
- reap.c - source
- reap.h - source
- Makefile - makefile
- SHAR_EOF
- chmod 0664 MANIFEST ||
- echo 'restore of MANIFEST failed'
- Wc_c="`wc -c < 'MANIFEST'`"
- test 339 -eq "$Wc_c" ||
- echo 'MANIFEST: original size 339, current size' "$Wc_c"
- fi
- # ============= Makefile ==============
- if test -f 'Makefile' -a X"$1" != X"-c"; then
- echo 'x - skipping Makefile (File already exists)'
- else
- echo 'x - extracting Makefile (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'Makefile' &&
- #----------------------------
- # parameters for installation
- #----------------------------
- X
- # directories where manual and executable are to be installed
- BINDIR = /usr/lib/newsbin/expire
- MANDIR = /usr/man/man8
- X
- # owner, group and file mode for manual and executable
- EXEOWNER = bin
- EXEGROUP = bin
- EXEMODE = 775
- MANOWNER = bin
- MANGROUP = bin
- MANMODE = 664
- X
- X
- # your favorite C compiler
- #CC = cc
- CC = shcc
- X
- # directory access functions library, if not in standard C library.
- LIB = -ldirent
- X
- X
- #-------------
- # boring stuff
- #-------------
- X
- OBJ = main.o lib.o reap.o
- X
- reap: $(OBJ)
- X $(CC) -s -o reap $(SHLIB) $(OBJ) $(LIB)
- X
- $(OBJ): reap.h
- X
- install: reap reap.8
- X cp reap $(BINDIR)
- X chown $(EXEOWNER) $(BINDIR)/reap
- X chgrp $(EXEGROUP) $(BINDIR)/reap
- X chmod $(EXEMODE) $(BINDIR)/reap
- X cp reap.8 $(MANDIR)
- X chmod $(MANMODE) $(MANDIR)/reap.8
- X chown $(MANOWNER) $(MANDIR)/reap.8
- X chgrp $(MANGROUP) $(MANDIR)/reap.8
- SHAR_EOF
- chmod 0664 Makefile ||
- echo 'restore of Makefile failed'
- Wc_c="`wc -c < 'Makefile'`"
- test 900 -eq "$Wc_c" ||
- echo 'Makefile: original size 900, current size' "$Wc_c"
- fi
- # ============= README ==============
- if test -f 'README' -a X"$1" != X"-c"; then
- echo 'x - skipping README (File already exists)'
- else
- echo 'x - extracting README (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'README' &&
- X
- A Problem:
- X News volume fluctuates wildly...sites with small disks must either
- Xexpire aggresively, often deleting more than necessary, or worry that an
- unexpected huge dose of news might overfill the disk.
- X
- X
- A Solution:
- X Implement a tool that expires according to a user-defined scheme
- until sufficient freespace is reclaimed, then stops, leaving as much
- juicy news online as is feasible. Reap does this.
- X
- X
- Expire Does Two Jobs:
- X Both Bnews and Cnews expires really do two jobs:
- X 1. trim history files
- X 2. delete outdated articles
- Thanks to some inspired jootsing (acronym for "jumping out of the system")
- by Mike Murphy (mrm@sceard.com) and others, it is more than possible to
- separate those two functions. This is, of course, in keeping with the
- unix philosophy of one tool doing one job well!
- X
- X
- What Reap Does:
- X Reap only takes care of the second job: deleting old articles.
- It works by checking freespace, and processing one line at a time from a
- list of expire functions, until the desired freespace is attained.
- Each expire function consists of an age limit in days (decimals okay)
- and a list of newsgroups to process or not process, sys file style. Ex:
- X
- X .5 alt.sex.pictures,talk,!talk.bizarre,junk
- X 1 rec,!rec.games,!rec.humor
- X
- This example would check freespace, and if more space is needed, expire
- to .5 days everything in alt.sex.pictures,talk (except for talk.bizarre)
- and junk. Then it would stop and check freespace again. If still more
- space is needed, it would expire to 1 day everything in rec except
- rec.games.* and rec.humor.*. It's that simple.
- X
- X
- Okay...So How Do I Arrange To Trim The History Files, Since Reap Can't:
- X Included in this distribution is a shell script (mostly written
- by Mike Murphy) to handle Cnews history files. It shouldn't be too
- difficult to do something similar for Bnews, or you can give in and use
- the original expire utility with options that tell it to expire the
- history files only...but I think this will be slow. It just comes down
- to removing lines from ordinary text files, based on their contents.
- Murphy and I used awk.
- X
- X
- But Is It Fast:
- X Yes, largely because it doesn't have to do much. Even "find | rm"
- is slower because find is repeatedly exec-ing rm. "rm -rf" has me beat,
- though, I'll bet! :-)
- X
- X Since the functions of deleting articles and trimming history
- are separate, I now run reap every six hours, but trim the history list
- just once a day. That effectively keeps my disk space up to snuff, but
- only thrashes at the history file in the middle of the night.
- X
- X
- Credits:
- X I owe a lot to Mike Murphy for inspiring me with his "trasher"
- system. I also owe a lot to all of your netters who will flood me with
- suggestions and improvements in the coming weeks (hint, hint!).
- X
- X little david
- X dt@yenta.alb.nm.us
- SHAR_EOF
- chmod 0664 README ||
- echo 'restore of README failed'
- Wc_c="`wc -c < 'README'`"
- test 2792 -eq "$Wc_c" ||
- echo 'README: original size 2792, current size' "$Wc_c"
- fi
- # ============= exphist ==============
- if test -f 'exphist' -a X"$1" != X"-c"; then
- echo 'x - skipping exphist (File already exists)'
- else
- echo 'x - extracting exphist (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'exphist' &&
- #! /bin/sh
- # exphist - expire history file
- X
- # =()<. ${NEWSCONFIG-@<NEWSCONFIG>@}>()=
- . ${NEWSCONFIG-/usr/lib/news/bin/config}
- X
- PATH=$NEWSCTL/bin:$NEWSBIN/expire:$NEWSBIN:$NEWSPATH ; export PATH
- umask $NEWSUMASK
- X
- days=`cat /usr/lib/news/histdays`
- X
- lock="$NEWSCTL/LOCKexpire"
- ltemp="$NEWSCTL/L.$$"
- Xecho $$ >$ltemp
- trap "rm -f $ltemp ; exit 0" 0 1 2 15
- if newslock $ltemp $lock
- then
- 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
- fi
- X
- cd $NEWSCTL
- rm -f history.n history.n.pag history.n.dir
- now=`getdate now`
- age=`expr 86400 \* $days`
- ago=`expr $now - $age`
- awk "{split(\$2,dates,\"~\");if(dates[1]>$ago)print \$0}" history >history.n
- mkdbm history.n
- [ -s history.n ] &&
- mv history history.o && # install new ASCII history file
- mv history.n history &&
- rm -f history.pag && # and related dbm files
- rm -f history.dir &&
- mv history.n.pag history.pag &&
- mv history.n.dir history.dir
- Xexit 0
- SHAR_EOF
- chmod 0775 exphist ||
- echo 'restore of exphist failed'
- Wc_c="`wc -c < 'exphist'`"
- test 969 -eq "$Wc_c" ||
- echo 'exphist: original size 969, current size' "$Wc_c"
- fi
- # ============= lib.c ==============
- if test -f 'lib.c' -a X"$1" != X"-c"; then
- echo 'x - skipping lib.c (File already exists)'
- else
- echo 'x - extracting lib.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'lib.c' &&
- X
- /*
- X * lib.c
- X * subroutines needed by reap utility
- X */
- X
- #include "reap.h"
- X
- /*
- X * freeblox(devno)
- X *
- X * assuming devno is the device number of a file system,
- X * this function returns the free space on that file system,
- X * in blocks (whatever that means for that filesystem) as a
- X * long int.
- X *
- X */
- X
- freeblox(devno)
- int devno;
- {
- X static struct ustat ust;
- X
- X if (ustat(devno, &ust)) {
- X fprintf (stderr, "%s: ustat() failed\n", progname);
- X exit (-1);
- X }
- X return (ust.f_tfree);
- X
- } /* freeblox() */
- X
- X
- X
- X
- /*
- X * parse(cmd)
- X * execute a line from the script file
- X *
- X * valid command lines:
- X * a blank line is ignored
- X * # comment (ignored)
- X * days filespecs
- X *
- X */
- X
- parse(cmd)
- char *cmd;
- {
- X double days;
- X char *t,
- X *p,
- X *q,
- X *seps = ",\n ";
- X
- X
- /* skip initial whitespace */
- X p = cmd;
- X while (isspace(*p))
- X ++p;
- X
- /* ignore blank lines or comments */
- X if (*p == '\0' || *p == '#')
- X return(1);
- X
- /* read the expire time from the line as a floating point number,
- X * then figure out what the timestamp on a file that old would be */
- X age = now - (time_t) (atof(p) * SECINDAY);
- X
- /* skip ahead to the filespec list */
- X while (!isspace(*p))
- X ++p;
- X while (isspace(*p))
- X ++p;
- X
- X preclude();
- X for (t = strtok(p, seps); t; t = strtok(NULL, seps)) {
- X /* forbid starting with a slash */
- X if (*t == '/')
- X *t = '.';
- X /* change dots to slashes except in column 1 */
- X while ( (q = strchr(t+1,'.')) != NULL)
- X *q = '/';
- X if (*t == '!')
- X exclude (t+1);
- X else
- X include (t);
- X }
- X
- X reap();
- X
- X return (0);
- X
- } /* parse() */
- X
- X
- X
- /*
- X * newnode,exclude, include, preclude
- X *
- X * functions to maintain global linked lists:
- X * incl include this path in list of dirs to recursively reap
- X * excl leave out this directory and descendants
- X *
- X * the functions are:
- X * include (text) add text to incl list
- X * exclude (text) add text to excl list
- X * preclude() clear both lists
- X */
- struct filspec *
- newnode(text)
- char *text;
- {
- X struct filspec *f;
- X
- X if ( (f = (struct filspec *) malloc (sizeof(struct filspec))) == NULL ||
- X (f->name = malloc (strlen(text)+1)) == NULL) {
- X fprintf (stderr, "%s: out of memory\n", progname);
- X exit (-1);
- X }
- X strcpy (f->name, text);
- X return (f);
- }
- Xexclude(text)
- char *text;
- {
- X struct filspec *f;
- X
- X f = newnode(text);
- X f->next = excl;
- X excl = f;
- }
- include(text)
- char *text;
- {
- X struct filspec *f;
- X
- X f = newnode(text);
- X f->next = incl;
- X incl = f;
- }
- preclude()
- {
- X struct filspec *p;
- X
- X while (incl != NULL) {
- X p = incl;
- X incl = incl->next;
- X free (p);
- X }
- X while (excl != NULL) {
- X p = excl;
- X excl = excl->next;
- X free (p);
- X }
- }
- SHAR_EOF
- chmod 0664 lib.c ||
- echo 'restore of lib.c failed'
- Wc_c="`wc -c < 'lib.c'`"
- test 2539 -eq "$Wc_c" ||
- echo 'lib.c: original size 2539, current size' "$Wc_c"
- fi
- # ============= list.sample ==============
- if test -f 'list.sample' -a X"$1" != X"-c"; then
- echo 'x - skipping list.sample (File already exists)'
- else
- echo 'x - extracting list.sample (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'list.sample' &&
- .1 junk,alt.flame,control,general
- 1 alt.sex.pictures
- 1 comp.os.vms
- .5 talk
- 1 sci,!sci.skeptic
- 2 sci.skeptic
- .5 misc.jobs,misc.handicap
- 2 soc
- 2 alt.tv
- 1 biz
- .5 rec,!rec.arts.anime,!rec.arts.animation,!rec.arts.movies,!rec.games.hack,!rec.ham-radio,!rec.autos,!rec.arts.tv,!rec.audio,!rec.video,!rec.music
- 1 rec.music,!rec.music.synth
- 3 rec.music.synth
- 2 rec.arts.anime,rec.arts.animation,rec.arts.movies,rec.ham-radio,rec.autos,rec.arts.tv,rec.audio,rec.video
- 3 rec.games.hack
- 1 misc.headlines,misc.consumers,misc.kids,misc.legal
- 1 alt.sex,!alt.sex.bondage,!alt.sex.pictures
- 1 comp.sources
- 1 alt.sources
- 2 comp,!comp.os.vms
- 1 news
- 3 misc
- 3 pubnet
- 3 alt
- 3 unix-pc
- # up to here is "normal expire"... now let's get desparate
- .1 alt.sex.pictures
- .1 rec.arts.anime,rec.arts.animation,rec.arts.movies,rec.ham-radio,rec.autos,rec.arts.tv,rec.audio,rec.video
- .1 biz
- .1 talk
- .1 news
- SHAR_EOF
- chmod 0664 list.sample ||
- echo 'restore of list.sample failed'
- Wc_c="`wc -c < 'list.sample'`"
- test 873 -eq "$Wc_c" ||
- echo 'list.sample: original size 873, current size' "$Wc_c"
- fi
- # ============= main.c ==============
- if test -f 'main.c' -a X"$1" != X"-c"; then
- echo 'x - skipping main.c (File already exists)'
- else
- echo 'x - extracting main.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'main.c' &&
- X
- /*
- X * main.c
- X * main routine and globals for reap utility.
- X */
- X
- X
- /* directory containing news articles */
- #define NEWSDIR "/usr/spool/news"
- X
- X
- #include "reap.h"
- X
- /* linked lists for included and excluded file specs */
- struct filspec
- X *incl = NULL,
- X *excl = NULL
- ;
- char
- X *scriptfile = "/usr/lib/news/reaplist",
- X *progname,
- X *newsdir = NEWSDIR
- ;
- int
- X verbose = 0, /* verbosity flag */
- X nodel = 0 /* do-not-unlink flag */
- ;
- time_t
- X age, /* unlink files older than this */
- X now /* current time */
- ;
- X
- X
- X
- main(argc, argv)
- int argc;
- char *argv[];
- {
- X int device, /* dev.no. of disk containing newsdir */
- X c,
- X errflag = 0;
- X long wantblox; /* desired free space */
- X char *p;
- X static char line[MAXLINE];
- X FILE *script; /* file ptr for function script */
- X struct stat st;
- X
- X
- /* parse args */
- X progname = argv[0];
- X
- X while ( (c=getopt(argc,argv,"vnf:")) != EOF)
- X switch(c) {
- X case 'n':
- X ++nodel;
- X break;
- X case 'v':
- X ++verbose;
- X break;
- X case 'f':
- X scriptfile = optarg;
- X break;
- X case '?':
- X ++errflag;
- X break;
- X }
- X
- X if (argc - optind != 1 ||
- X sscanf(argv[optind], "%ld", &wantblox) != 1 )
- X ++errflag;
- X
- X if (errflag) {
- X fprintf (stderr,
- X "usage: %s [-v] [-n] [-f funclist] freeblocks\n", progname);
- X exit (-1);
- X }
- X
- X
- /* stat newsdir to find the number of the device it's on */
- X if (stat(newsdir, &st)) {
- X fprintf (stderr, "%s: can't stat %s\n", progname, newsdir);
- X exit (-1);
- X }
- X device = st.st_dev;
- X
- /* open function file for reading */
- X if ( (script = fopen (scriptfile, "r")) == NULL) {
- X fprintf (stderr, "%s: can't read %s\n", progname, scriptfile);
- X exit (-1);
- X }
- X
- /* when am i? */
- X time (&now);
- X
- /* chdir to newsdir */
- X chdir (newsdir);
- X
- /* main loop is right here ... process until goal reached or end of script */
- X
- X while (freeblox(device) < wantblox &&
- X (p = fgets (line, MAXLINE, script)) != NULL )
- X parse (line);
- X
- X fclose (script);
- X
- /* return 0 if freespace goal was met at exit, 1 if not */
- X exit (freeblox(device) >= wantblox ? 0 : 1);
- X
- } /* main() */
- X
- SHAR_EOF
- chmod 0664 main.c ||
- echo 'restore of main.c failed'
- Wc_c="`wc -c < 'main.c'`"
- test 2028 -eq "$Wc_c" ||
- echo 'main.c: original size 2028, current size' "$Wc_c"
- fi
- # ============= reap.8 ==============
- if test -f 'reap.8' -a X"$1" != X"-c"; then
- echo 'x - skipping reap.8 (File already exists)'
- else
- echo 'x - extracting reap.8 (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'reap.8' &&
- .TH REAP 8 LOCAL
- .SH NAME
- reap - delete news articles as space needed
- .SH SYNOPSIS
- .B reap
- [-v] [-n] [-f funcfile] freeblocks
- .SH DESCRIPTION
- .I Reap
- checks disk freespace and deletes articles according to a user-specified
- scheme until
- .I freeblocks
- minimum freespace is available.
- .PP
- The
- .B -n
- causes a dry run (as in make(1)). When this
- option is specified, reap merely reports which files it would delete if
- the option were left off. This is useful for debugging function scripts.
- However, since no space is actually freed in this mode,
- it will either do nothing
- (there was enough space to begin with) or proceed through the entire function
- script file, indicating that reap would delete all applicable articles.
- .PP
- With the
- .B
- -v
- option, reap prints a verbose commentary on its progress to the standard
- output.
- .PP
- By default, reap looks in /usr/lib/news/reaplist for its list of functions.
- The
- .B -f
- option is used to specify an alternate function script file.
- .SH FUNCTION SCRIPT FILE FORMAT
- A function script file consists of a series of expire functions, one per line.
- Each expire function contains an age (in days, decimals okay), followed
- by a list of newsgroups to be expired.
- Blank lines and lines beginning with a "#" are ignored.
- A sample function script file:
- .PP
- .nf
- X # function script file
- X 0.5 talk,junk,alt.sex.pictures
- X 2 rec,!rec.games,!rec.humor
- X 3 misc
- .fi
- .PP
- In the example,
- if space is needed, reap
- Xexpires to .5 days the entire talk and junk
- hierarchies, and alt.sex.pictures. If
- still more space is needed,
- rec hierarchy (excepting rec.games.* and rec.humor.*) is expired
- to 2 days. If freespace is still short, reap then expires all of misc
- to 2 days.
- .PP
- Note that, while it would be possible to consolidate the second and
- third lines, leaving them separate makes it posisble for reap to stop
- in between them if sufficient space is cleared.
- .SH FILES
- .TP 25
- /usr/spool/news
- News spool directory
- .TP 25
- /usr/lib/news/reaplist
- Default function list file
- .SH DIAGNOSTICS
- Returns zero if sufficient space was free at exit, nonzero otherwise.
- .SH BUGS
- The use of the ustat() system call is not very portable, and your humble
- author isn't aware of its non-system-V equivalents.
- .PP
- Lines in the function file are limited to 512 characters.
- .PP
- What constitutes a disk "block" is implementation-dependent.
- SHAR_EOF
- chmod 0644 reap.8 ||
- echo 'restore of reap.8 failed'
- Wc_c="`wc -c < 'reap.8'`"
- test 2335 -eq "$Wc_c" ||
- echo 'reap.8: original size 2335, current size' "$Wc_c"
- fi
- # ============= reap.c ==============
- if test -f 'reap.c' -a X"$1" != X"-c"; then
- echo 'x - skipping reap.c (File already exists)'
- else
- echo 'x - extracting reap.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'reap.c' &&
- X
- /*
- X * reap.c
- X * contains the reap() function.
- X *
- X * Once the global linked lists incl and excl have been stuffed,
- X * reap() actually scans the filesystem for files that meet the specs
- X * and unlinks them if they are older than the age global variable.
- X */
- X
- #include "reap.h"
- X
- X
- reap()
- {
- X struct filspec *f;
- X
- X for (f = incl; f != NULL; f = f->next) {
- X if (verbose)
- X printf ("scanning %s ...\n", f->name);
- X dodir (f->name);
- X }
- X
- } /* reap() */
- X
- X
- X
- dodir(name)
- char *name;
- {
- X /* the following can be overwritten safely during recursion */
- X static struct filspec *e;
- X static struct stat st;
- X static struct dirent *dp;
- X /* the following must be preserved during recursion */
- X char *fullpath;
- X DIR *dirp;
- X
- X
- X if ( (dirp = opendir(name)) == NULL) {
- X fprintf (stderr, "%s: can't read directory %s\n", progname,
- X name);
- X return (-1);
- X }
- X
- X while ( (dp = readdir(dirp)) != NULL) {
- X
- X /* skip dot and dotdot */
- X if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
- X continue;
- X
- X /* build the full pathname of each object */
- X if ( (fullpath =
- X malloc(strlen(name)+strlen(dp->d_name)+2)) == NULL) {
- X fprintf (stderr, "%s: out of memory\n", progname);
- X exit (-1);
- X }
- X sprintf (fullpath, "%s/%s", name, dp->d_name);
- X
- X /* check for excluded paths */
- X for (e = excl; e != NULL; e = e->next)
- X if (!strcmp (fullpath, e->name))
- X break;
- X if (e != NULL) {
- X free (fullpath);
- X continue;
- X }
- X
- X /* try to stat the object */
- X if (stat(fullpath,&st)) {
- X fprintf (stderr, "%s: can't stat %s\n",
- X progname, fullpath);
- X free (fullpath);
- X continue;
- X }
- X
- X /* recurse if it's a directory */
- X if ( st.st_mode & S_IFDIR ) {
- X dodir (fullpath);
- X free (fullpath);
- X continue;
- X }
- X
- X /* it's a file... leave it alone if it's new enough */
- X if (st.st_mtime > age) {
- X free (fullpath);
- X continue;
- X }
- X
- X if (nodel) {
- X printf ("Would unlink %s\n", fullpath);
- X free (fullpath);
- X continue;
- X }
- X if (verbose)
- X printf ("Unlinking %s\n", fullpath);
- X
- X if (unlink (fullpath) == -1)
- X fprintf (stderr,
- X "%s: cannot unlink %s\n", progname, fullpath);
- X
- X free (fullpath);
- X
- X } /* while */
- X closedir (dirp);
- X
- } /* dodir() */
- SHAR_EOF
- chmod 0664 reap.c ||
- echo 'restore of reap.c failed'
- Wc_c="`wc -c < 'reap.c'`"
- test 2150 -eq "$Wc_c" ||
- echo 'reap.c: original size 2150, current size' "$Wc_c"
- fi
- # ============= reap.h ==============
- if test -f 'reap.h' -a X"$1" != X"-c"; then
- echo 'x - skipping reap.h (File already exists)'
- else
- echo 'x - extracting reap.h (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'reap.h' &&
- X
- /*
- X * reap.h
- X * header file for reap utility
- X */
- X
- #include <stdio.h>
- #include <string.h>
- #include <ctype.h>
- #include <time.h>
- #include <malloc.h>
- #include <sys/stat.h>
- #include <ustat.h>
- #include <dirent.h>
- X
- #define MAXLINE 512 /* max len of line in script */
- #define SECINDAY (3600 * 24) /* seconds in a day */
- X
- /* structure for linked lists of included and excluded file specs */
- struct filspec {
- X char *name;
- X struct filspec *next;
- };
- X
- Xextern struct filspec
- X *incl,
- X *excl
- ;
- Xextern char
- X *progname,
- X *scriptfile,
- X *newsdir
- ;
- Xextern int
- X verbose,
- X nodel,
- X optind
- ;
- Xextern char *optarg;
- Xextern double atof();
- Xextern long freeblox();
- Xextern time_t
- X age,
- X now
- ;
- SHAR_EOF
- chmod 0664 reap.h ||
- echo 'restore of reap.h failed'
- Wc_c="`wc -c < 'reap.h'`"
- test 676 -eq "$Wc_c" ||
- echo 'reap.h: original size 676, current size' "$Wc_c"
- fi
- exit 0
- --
- My friend Franky said he wanted to know something about computers that I
- didn't know, so I suggested he learn COBOL.
-