v06i052: Usenet news batcher control program (newbatchA)
sources-request at mirror.UUCP
sources-request at mirror.UUCP
Mon Jul 14 22:43:00 AEST 1986
Submitted by: cca!caip!cbmvax!bpa!espo (Bob Esposito)
Mod.sources: Volume 6, Issue 52
Archive-name: newbatchA
[ This is the first of two batched news utility programs (BNUP, to coin
an acronym). It was written on a SystemV machine, but it looks like
it would be fairly easy to convert to BSD and, e.g., the directory
library. Stuff dealing with the UUCP queue is much less portable,
of course, but Bob nicely provides a default mechanism. Take a look
at the check_uucp routine, however -- I think you may want a different
default value. Also, I added a modified xerror routine that doesn't
depend on knowing the internal's of the FILE struct. I haven't
tested it, but a "grep xerror *." seems to say I'm ok; add -DUSE_PORT_CODE
for my version. --r$ ]
#!/bin/sh
# This is a shell archive. Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# Contents: README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile
# bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c
echo x - README
sed 's/^XX//' > "README" <<'@//E*O*F README//'
XXThe program provides a better way to handling batching of USENET news
XXto neighboring sites. It works with 2.10B and later, including
XX2.10.3B, which provides compression batching.
XXPlease send any questions and bug reports to me (bpa!espo) for
XXdistribution to the net. This software is public domain, and cannot be
XXsold for any profit.
XXNbatcher was written for UNIX (trademark of AT&T) System V, but should
XXbe compatible with most version currently being used today. It is
XXpresently running on a VAX (trademark of DEC) 11/780 feeding 5 remote
XXsites with news. Two important issues MUST be noted here.
XXSince nbatcher checks the UUCP directory for each site listed in the
XXcontrol file, directory configuration should be UUCPDIR/sitename, e.g.
XX/usr/spool/uucp/foo for site foo. But since not everyone is generic,
XXI've allowed nbatcher to skip over the UUCP byte counting routine if
XXthis is not so. In addition to this, some uucpcleanup daemons remove
XXthe site directory if there's nothing spooled there. When this
XXhappens, nbatcher will notify you of this and continue on.
XXThe other issue is that you MUST configure your NEWSLIB/sys file using the
XXbatch syntax as described in the USENET Installation document. Field 3
XXshould contain the `F' flag indicating a batched transmission for that
XXsite and field 4 should contain the filename where news article's full
XXpathname will be appended to. Nbatcher requires that the filename in
XXfield 4 match the sitename in the control file. For example, the entry:
XX foo:net,mod,usa,na,to.foo:F:/usr/spool/batchnews/foo
XXsays that all news articles going to site `foo' will be batched, using
XXthe file `foo' in /usr/spool/batchnews. Nbatcher's control file entry:
XX foo:3,14,22:16:150000:
XXwill get the news article's full pathname from /usr/spool/batchnews/foo
XXfor batching. This requirement MUST be adhered to for nbatcher to work
XXcorrectly. I believe most sites that batch news use this type of
XXconfiguration, since its easy to keep track of a remote site's work.
XXNote that the name of the directory "/usr/spool/batchnews" is set
XXin the Makefile.
XXThe manual page describes the control file, as does nbatcher.doc. Note
XXthat even though nbatcher indicates max bytes has been reached, if that
XXsite gets compressed batches, the next time nbatcher runs for that site
XXwork could get scheduled.
XXAlso included is a utility program called "bst," BatchSTatus, which
XXshows who many news articles are currently in the batch file for each
XXsystem. Just type "make bst" for that and copy it to where you want,
XXusually LIBDIR. Note that bst does reads on the directory structure
XXdirectly.
XXInstallation is simple: look at the first few #define's in nbatcher.h;
XXalso edit the Makefile for the appropriate BATCHDIR and LIBDIR for your
XXsite. Type "make" or "make install."
XXNOTE: Read the comments in parse.c concerning MAX_BYTES. This is the
XXmaximum amount of bytes per site that's allowed in the control file for
XXqueue_size. Change it at your own risk!
XX Bob Esposito
XX bpa!espo
XX Bell of Penna.
@//E*O*F README//
chmod u=rw,g=rw,o=rw README
echo x - nbatcher.1
sed 's/^XX//' > "nbatcher.1" <<'@//E*O*F nbatcher.1//'
XX.TH NBATCHER 1 LOCAL
XX.SH NAME
XXnbatcher \- new batching system for news
XX.SH SYNOPSIS
XX.B nbatcher
XX.IR "(run out of " cron ".)"
XX.SH DESCRIPTION
XX.PP
XX.I Nbatcher
XXis a program designed to send batched USENET data out in an orderly and
XXcontrolled fashion, while providing alternative transmission methods.
XXAs such, it is a replacement for
XX.I csendbatch
XXand the like, which typically require many entries in
XX.IR crontab .
XX.I Nbatcher
XXis intended to be run hourly out of
XX.I cron
XXas the USENET administrator (NEWSID).
XX.PP
XX.I Nbatcher
XXscans the file
XX.I nbatcher.ctl
XXin the NEWSLIB directory to determine if work should be spooled for a system.
XXIn the control file, lines starting with asterisks are ignored; data lines
XXare comprised of five colon\-separated fields:
XX.RS
XXsite:hour:bits:queue_size:command
XX.RE
XX.TP ``site''
XXName of the USENET neighbor; it is the same as the site in the news
XX.I sys
XXfile.
XX.TP ``hours''
XXThis field is patterned after
XX.IR cron 's.
XXIf the hour is ``off,'' no work is spooled for the site.
XXAn hour of ``*'' matches every hour.
XXIt is also possible to specify specific hours, (e.g., 8, 09, or 22), a
XXcomma\-separated list (e.g., 8,09,22), or a twenty\-four range, like
XX1-\15 for 10am through 3pm and 22\-4, for 10pm through 4am.
XX.TP ``bits''
XXThis field specifies the number of bits to use in compression; it should be
XXa number between nine and 16, inclusive, or null.
XXIf a number is specified, it is passed on to the
XX.I compress
XXprogram via the ``\-b'' flag.
XX.TP ``queue_size''
XXThis field specifies the maximum number of bytes allowed in the UUCP queue
XXfor this site.
XXThe default is 100K.
XXThe UUCP queue size is determined by looking in the
XX.IR /usr/spool/uucp/ site
XXdirectory; if it doesn't exist, the check is bypassed.
XXIf there is data in the UUCP queue,
XX.I nbatcher
XXwill only queue up as many USENET transfers as will fit within the limit
XXspecified by the ``queue_size'' field.
XX.TP ``command''
XXThis field is used to specific the UUCP command that should be used to queue
XXthe job; as distributed, the default is ``uux \- \-r site!rnews''; note the
XXabsence of the ``\-z'' flag.
XX.PP
XXTo set up a USENET neighbor to be controlled by
XX.IR nbatcher ,
XXthe news
XX.I sys
XXentry for the neighbor must be modified to specify the ``F'' flag, and the
XXfile used to contain the article names must be
XX.RI BATCHDIR/sysname ,
XXwhere BATCHDIR is set in the Makefile as distributed.
XX.SH FILES
XX.TP NEWSLIB/nbatcher.log
XXA logfile of failures, postponements, etc.
XX.SH BUGS
XXParsing of the control file is fairly robust, but not perfect.
@//E*O*F nbatcher.1//
chmod u=rw,g=rw,o=rw nbatcher.1
echo x - nbatcher.ctl
sed 's/^XX//' > "nbatcher.ctl" <<'@//E*O*F nbatcher.ctl//'
XX*
XX* NBATCHER.CTL
XX* Edit and install in your NEWSLIB directory.
XX*
XX* Comments start with *; data lines look like:
XX* site:hours:bits:queue_size:command
XX* Where
XX* site = name of the remote site
XX* hour = when to do work (* is all, off is never, 22-4 is ok)
XX* bits = passed on to compress via -b; null gets default
XX* queue_size = Max # bytes allowed in UUCP queue before postponing
XX* command = optional command line
XX*
XX* See manpage and README for more info.
@//E*O*F nbatcher.ctl//
chmod u=rw,g=rw,o=rw nbatcher.ctl
echo x - nbatcher.doc
sed 's/^XX//' > "nbatcher.doc" <<'@//E*O*F nbatcher.doc//'
XXDETAILED DESCRIPTION OF "NBATCHER.CTL" FILE
XX-------------------------------------------
XXAs distributed, nbatcher.ctl contains just a terse summary of its
XXformat. For each site you feed news to, providing that site uses the
XX":F:BATCHDIR/site" batching syntax in the sys file, a corresponding
XXentry should exist in nbatcher.ctl Each line is a five-field,
XXcolon-separated entry indicating what to do for that site. The default
XXfor BATCHDIR is /usr/spool/batchnews.
XXThe format is:
XX site:hour:bits:queue_size:command
XXThe site field is the name of the UUCP site that will get the batched
XXnews. There MUST be a file in the BATCHDIR directory with the
XXsitename. Nbatcher will complain about mismatches. This file contains
XXa full-path listing of the files to batch.
XXNext is the hour field. The syntax directly imitates the crontab entry
XXfor hour. If hour = "*", than assume a match for every hour. If hour
XX= "off", then no work is ever spooled for this site. (This is the only
XXdifference from crontab). You can specify a specific hour, like 8 or
XX09 or 22. Or a range of hours, like 10-15, meaning check for work from
XX10am thru 3pm. You can also cycle thru a 24-hour period by saying
XX22-4, which matches for 10pm thru 4am. Also, hours comma separated
XXlike 7,14,21, says check for work at 7 AM, 4PM and 9PM only. This
XXgives lots of flexibility for sites that feed multiple remotes.
XXNext is the bits field, which has a value of 9-16, or may be left blank.
XXIf non-null, this field is directly passed on to compress with the -b
XXflag. If it is null, then no compression is done for this site.
XXThe queue_size field is the maximum number of bytes allowed on the UUCP
XXqueue at any time. It defaults to 100K bytes, and if it's greater than
XX1MB (see parse.c about MAX_BYTES), than it uses 1MB as the default
XXnumber of bytes.
XXWhat nbatcher does is first check the UUCPDIR for that site and sums up
XXthe number of bytes already on-queue. The size of each news article is
XXaccumulated prior to batching to the tempfile, and this accumulation +
XXthe UUCP on-queue bytes are checked to see if they surpass the queue_size
XXvalue. If not, things proceed normally. But if it would exceed the
XXmax value, then spool what's already been batched, and save the
XXremainder of the articles for the next scheduled batch.
XXThis is so noted in the nbatcher.log file, showing the UUCP bytes that
XXwere on-queue (if any), and the number of bytes that were spooled.
XXAlso, if nbatcher is run from a terminal instead of from cron, a copy
XXof what gets logged is sent to the terminal.
XXThe last field is the command field. This optional field is used for
XXspecific UUCP command execution. As written, it defaults to "uux - -r
XXsite!rnews". Since my uux doesn't require the -z option for rnews, I
XXleft it out of the UUX define in nbatcher.h This can easily be changed
XXfor your own taste, or just use the command field.
XXExample:
XX site-A:3,10:16:450000:
XXCheck for work for site-A at 3AM and 10AM. Use compress with
XX16 bits and only spool up to 450K bytes, using "uux - -r site-A!rnews".
XXAnother example:
XX foo:23-4::300000:uux - -r -z foo!rnews
XXCheck for work for foo between 11PM and 4AM. No compression is used
XXand spool up to 300K bytes using the command field.
XXThis format should help ease UUCP congestion on the local site for
XXnews. I currently feed 5 remote sites, compressed and non-compressed
XXformats, and have noticed a vast improvement in disk space as well as
XXout port availability for UUCP. It has allowed me to check for work
XXfor all sites every hour, since there's a limit on how much gets
XXqueued. And if the remote doesn't answer on the hourly UUCP poll, so
XXwhat! Nbatcher just won't spool any more until the queue_size limit
XXon-queue is reduced.
XXNbatcher was designed to weed out any illegal syntax in the control
XXfile, but it's not bug-proof, so use some discretion.
XXBob Esposito
XXBell of Penna.
XXJune 1986
@//E*O*F nbatcher.doc//
chmod u=rw,g=rw,o=rw nbatcher.doc
echo x - Makefile
sed 's/^XX//' > "Makefile" <<'@//E*O*F Makefile//'
XX#
XX# Makefile for nbatcher
XX#
XX# R.J. Esposito
XX# Bell of Penna.
XX# June 1986
XX#
XX# You MUST define BATCHDIR as the place where USENET
XX# puts the articles to be batched.
XX#
XX# LIBDIR is where you USENET library is and also
XX# MUST be defined.
XXBATCHDIR = /usr/spool/batchnews
XXLIBDIR = /misc/lib/usenet
XXCFLAGS = -O -c
XXLFLAGS = -s
XXDFLAGS = -DBATCHDIR='"$(BATCHDIR)"' -DLIBDIR='"$(LIBDIR)"'
XXOBJS = define.o main.o parse.o checkwork.o nbatcher.o logger.o
XXSRC = define.c main.c parse.c checkwork.c nbatcher.c logger.c nbatcher.h bst.c
XXDOCS = README nbatcher.ctl nbatcher.doc
XXall: $(OBJS)
XX $(CC) $(DFLAGS) $(LFLAGS) -o nbatcher $(OBJS)
XX chmod 0755 nbatcher
XXinstall: all
XX cp nbatcher $(LIBDIR)
XX chmod 0755 $(LIBDIR)/nbatcher
XX cp nbatcher.ctl $(LIBDIR)/nbatcher.ctl
XX chmod 0644 $(LIBDIR)/nbatcher.ctl
XXdefine.o: nbatcher.h define.c
XX $(CC) $(CFLAGS) $(DFLAGS) define.c
XXmain.o: nbatcher.h main.c
XX $(CC) $(CFLAGS) $(DFLAGS) main.c
XXparse.o: nbatcher.h parse.c
XX $(CC) $(CFLAGS) $(DFLAGS) parse.c
XXcheckwork.o: nbatcher.h checkwork.c
XX $(CC) $(CFLAGS) $(DFLAGS) checkwork.c
XXnbatcher.o: nbatcher.h nbatcher.c
XX $(CC) $(CFLAGS) $(DFLAGS) nbatcher.c
XXlogger.o: nbatcher.h logger.c
XX $(CC) $(CFLAGS) $(DFLAGS) logger.c
XXbst: bst.c
XX $(CC) $(CFLAGS) $(DFLAGS) bst.c
XX $(CC) $(LFLAGS) -o bst bst.o
XXclean:
XX rm -f *.o *.shar
XXclobber: clean
XX rm -f nbatcher
XXshar:
XX shar -v $(SRC) $(DOCS) Makefile > nbatcher.shar
@//E*O*F Makefile//
chmod u=rw,g=rw,o=rw Makefile
echo x - bst.c
sed 's/^XX//' > "bst.c" <<'@//E*O*F bst.c//'
XX/*
XX * bst.c - a utility for indicating how many
XX * news articles are ready for batching
XX * for each site in the BACTHDIR directory.
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include <sys/types.h>
XX#include <sys/stat.h>
XX#include <sys/dir.h>
XXchar buf[512];
XXFILE *dd;
XXstruct direct dp;
XXstruct stat st;
XXmain()
XX{
XX int fd, j;
XX int bcnt, lcnt;
XX if(chdir(BATCHDIR) != 0) {
XX perror(BATCHDIR);
XX exit(1);
XX }
XX if((dd=fopen(".", "r")) == NULL) {
XX printf("can't open %s\n", BATCHDIR);
XX exit(1);
XX }
XX while((fread((char *)&dp, sizeof(dp), 1, dd)) == 1) {
XX if(dp.d_ino == 0 || dp.d_name[0] == '.')
XX continue;
XX if(stat(dp.d_name, &st) != 0) {
XX printf("can't stat %s\n", dp.d_name);
XX exit(1);
XX }
XX if(st.st_size <= 0 )
XX continue;
XX if((fd=open(dp.d_name, 0)) < 0) {
XX printf("can't open %s\n", dp.d_name);
XX exit(1);
XX }
XX lcnt = 0;
XX while((bcnt=read(fd,buf,512)) > 0) {
XX for(j=0; j<=bcnt; j++)
XX if(buf[j] == '\n')
XX lcnt += 1;
XX }
XX close(fd);
XX printf("%s\t %d article", dp.d_name, lcnt);
XX printf("%c\n", lcnt > 1 ? 's' : ' ');
XX }
XX}
@//E*O*F bst.c//
chmod u=rw,g=rw,o=rw bst.c
echo x - checkwork.c
sed 's/^XX//' > "checkwork.c" <<'@//E*O*F checkwork.c//'
XX/*
XX *
XX * checkwork.c - look to see if there's any work
XX * to do for a site.
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include <sys/types.h>
XX#include <sys/stat.h>
XX#include <sys/utsname.h>
XX#include <sys/dir.h>
XX#include <ctype.h>
XX#include <time.h>
XX#include "nbatcher.h"
XXwork_to_do ()
XX{
XX register char *p;
XX struct tm *localtime(), *tp;
XX struct stat st;
XX char buf[BUFSIZ];
XX long time(), clock;
XX int hour;
XX short num, upper, lower;
XX sprintf (buf, "%s/%s", BATCHDIR, ep.site);
XX if (stat(buf, &st) < 0)
XX xerror ("bad stat on %s\n", buf);
XX /* if the size of the batch file is
XX zero, return FALSE
XX */
XX if (st.st_size == 0)
XX return (FALSE);
XX /* now see if it time to do anything */
XX clock = time ((long *)0);
XX tp = localtime (&clock);
XX hour = tp->tm_hour;
XX p = (char *) ep.hour;
XX if (*p == '*') /* match any hour */
XX return (check_uucp());
XX if (strncmp(p, "off", 3) == 0) /* just what it says, off */
XX return (FALSE);
XX /* parse thru hour field to see if
XX this is the hour to do work */
XX num = 0;
XX do {
XX num = num*10 + (*p - '0');
XX } while (isdigit(*++p));
XX if (num == hour)
XX return (check_uucp());
XX if (*p == '-') {
XX lower = num;
XX p++;
XX num = 0;
XX do {
XX num = num*10 + (*p - '0');
XX } while (isdigit(*++p));
XX upper = num;
XX if (lower < upper) { /* normal hour range */
XX if (hour >= lower && hour <= upper)
XX return (check_uucp());
XX } else if (lower > upper) { /* 24 hr. cycle thru */
XX if (hour >= lower || hour <= upper)
XX return (TRUE);
XX } else
XX return (FALSE);
XX }
XX if (*p == ',') {
XX p++;
XX while (*p) {
XX num = 0;
XX do {
XX num = num*10 + (*p - '0');
XX } while (isdigit(*++p));
XX if (num == hour)
XX return (check_uucp());
XX p++;
XX }
XX }
XX return (FALSE);
XX}
XX/* If check_uucp cannot find the remote site
XX * directory, just bypass the byte counting
XX * routine. This is necessary because the
XX * uucpcleanup daemon, on some sites, removes
XX * the site directory when there's nothing there.
XX */
XXcheck_uucp()
XX{
XX struct utsname utsn;
XX struct direct dp;
XX struct stat st;
XX FILE *dfp;
XX char u_name[9], buf[80];
XX short prefix_len;
XX if (uname(&utsn) < 0)
XX xerror ("can't get local nodename\n");
XX sprintf (buf, "%s/%s", UUCPDIR, ep.site);
XX if (chdir(buf) < 0) {
XX fprintf (stderr, "nbatcher: can't chdir to %s - bypassing UUCP check\n", buf);
XX return (TRUE);
XX }
XX if ((dfp=fopen(".", "r")) == NULL) {
XX fprintf (stderr, "nbatcher: fopen error on %s - bypassing UUCP check\n", UUCPDIR);
XX return (TRUE);
XX }
XX sprintf (buf, "D.%s", utsn.nodename);
XX prefix_len = (short) strlen(buf);
XX n_bytes = 0;
XX while ((fread((char *)&dp, sizeof(dp), 1, dfp)) == 1) {
XX if (dp.d_ino == 0 || dp.d_name[0] == '.')
XX continue;
XX if (strncmp(dp.d_name, buf, prefix_len))
XX continue;
XX if (stat(dp.d_name, &st) < 0) {
XX fprintf (stderr, "nbatcher: bad stat on UUCP_file %s - bypassing\n", dp.d_name);
XX continue;
XX }
XX n_bytes += st.st_size;
XX if (n_bytes > ep.m_bytes) {
XX fclose (dfp);
XX return (FALSE);
XX }
XX }
XX fclose (dfp);
XX if (chdir(LIBDIR) < 0)
XX xerror ("can't chdir back to %s\n", LIBDIR);
XX return (TRUE);
XX}
@//E*O*F checkwork.c//
chmod u=rw,g=rw,o=rw checkwork.c
echo x - define.c
sed 's/^XX//' > "define.c" <<'@//E*O*F define.c//'
XX/*
XX * define.c - global defines for nbatcher.
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include "nbatcher.h"
XXFILE *lfp,
XX *tfp,
XX *log = NULL;
XXlong n_bytes,
XX cu_bytes;
XXchar *tfile = NULL;
XXshort vflg = 0,
XX nfiles = 10;
XXint fcnt = 0,
XX scnt = 0;
@//E*O*F define.c//
chmod u=rw,g=rw,o=rw define.c
echo x - logger.c
sed 's/^XX//' > "logger.c" <<'@//E*O*F logger.c//'
XX/*
XX *
XX * logger.c - log info about nbatcher
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include <time.h>
XX#include "nbatcher.h"
XXlog_it (bytes)
XXlong bytes;
XX{
XX struct tm *localtime(), *tp;
XX long time(), clock;
XX char logfile[80], buf[BUFSIZ];
XX char pbuf[BUFSIZ];
XX sprintf (logfile, "%s/%s", LIBDIR, "nbatcher.log");
XX if (log == NULL) {
XX if ((log=fopen(logfile, "a")) == NULL)
XX fprintf (stderr, "can't append to logfile\n");
XX }
XX rewind (log, 0L, 2); /* just incase */
XX clock = time ((long *)0);
XX tp = localtime (&clock);
XX sprintf (buf, "%.2d/%.2d %.2d:%.2d %s: %d %s batched, %d %s queued\n",
XX tp->tm_mon+1, tp->tm_mday, tp->tm_hour, tp->tm_min, ep.site,
XX fcnt, (fcnt==1 ? "file" : "files"), scnt,
XX (scnt==1 ? "file" : "files"));
XX if (bytes)
XX sprintf (pbuf, "%s\tmax bytes reached. UUCP bytes was %ld, byte count = %ld\n",
XX buf, n_bytes, bytes);
XX else
XX sprintf (pbuf, "%s", buf);
XX if (vflg)
XX fprintf (stdout, "%s",pbuf);
XX if (log != NULL)
XX fputs (pbuf, log);
XX}
@//E*O*F logger.c//
chmod u=rw,g=rw,o=rw logger.c
echo x - main.c
sed 's/^XX//' > "main.c" <<'@//E*O*F main.c//'
XX/*
XX *
XX * main.c - for nbatcher
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include "nbatcher.h"
XXmain()
XX{
XX int uid;
XX FILE *cfp;
XX char fbuf[BUFSIZ];
XX uid = getuid();
XX if (uid && uid != NEWSUID)
XX xerror ("permission denied - not NEWSUSER\n");
XX if (chdir(LIBDIR) < 0)
XX xerror ("can't chdir to %s\n", LIBDIR);
XX if ((cfp=fopen("nbatcher.ctl", "r")) == NULL)
XX xerror ("no `batcher.ctl' file found\n");
XX if (isatty(0))
XX vflg = TRUE;
XX while ((fgets(fbuf, sizeof(fbuf), cfp)) != NULL) {
XX if (fbuf[0] == '*' || fbuf[0] == '\n')
XX continue;
XX parse_entry (fbuf);
XX if (!work_to_do())
XX continue;
XX batch_it ();
XX }
XX fclose (cfp);
XX unlink (tfile);
XX exit (0);
XX}
XX
@//E*O*F main.c//
chmod u=rw,g=rw,o=rw main.c
echo x - nbatcher.c
sed 's/^XX//' > "nbatcher.c" <<'@//E*O*F nbatcher.c//'
XX/*
XX *
XX * nbatcher.c - where it really happens.
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include <sys/types.h>
XX#include <sys/stat.h>
XX#include <time.h>
XX#include "nbatcher.h"
XXbatch_it ()
XX{
XX struct stat st;
XX FILE *bfp, *afp;
XX char fbuf[BUFSIZ], lckfile[40];
XX char tbuf[80];
XX short count;
XX int c;
XX if (chdir(BATCHDIR) < 0)
XX xerror ("can't chdir to %s\n", BATCHDIR);
XX /* we create a lock file for two purposes,
XX first to make sure a previous nbatcher
XX didn't blowup and leave the lock file
XX laying around, and second to put the
XX remaining news article filenames when
XX we go over the max UUCP bytes and there's
XX still files remaining for batching.
XX */
XX sprintf (lckfile, ".%s.lock", ep.site);
XX if (!access(lckfile, 0))
XX xerror ("lockfile already exists for %s\n", ep.site);
XX if ((lfp=fopen(lckfile, "w")) == NULL)
XX xerror ("can't create lockfile for %s\n", ep.site);
XX /* now that we've locked ourselves for this site,
XX lets carry on */
XX if ((bfp=fopen(ep.site, "r")) == NULL)
XX xerror ("can't open %s/%s for reading\n", BATCHDIR, ep.site);
XX if (tfile == NULL) {
XX tfile = mktemp("/tmp/bnewsXXXXXX");
XX if ((tfp=fopen(tfile, "w")) == NULL)
XX xerror ("can't open %s for writing\n", tfile);
XX }
XX count = fcnt = scnt = 0;
XX cu_bytes = 0;
XX while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL) {
XX fbuf[strlen(fbuf)-1] = '\0'; /* remove the newline */
XX if ((afp=fopen(fbuf, "r")) == NULL) {
XX fprintf (stderr, "bypassing article %s: can't read it\n",
XX fbuf);
XX continue;
XX }
XX if (fstat (fileno(afp), &st) < 0)
XX xerror ("fstat failed on %s\n", fbuf);
XX cu_bytes += st.st_size;
XX /* if the max byte count is exceeded,
XX save the remaining files for later */
XX if ((cu_bytes + n_bytes) > ep.m_bytes) {
XX fprintf (lfp, "%s\n", fbuf); /* put the '\n' back */
XX while ((fgets(fbuf, sizeof(fbuf), bfp)) != NULL)
XX fputs (fbuf, lfp);
XX fclose (bfp);
XX fclose (lfp);
XX fclose (afp);
XX unlink (ep.site);
XX if (link(lckfile, ep.site) < 0)
XX xerror ("can't link lockfile to %s\n", ep.site);
XX unlink (lckfile);
XX chown (ep.site, NEWSUID, NEWSGID);
XX if (count)
XX spoolit ();
XX if (cu_bytes - st.st_size)
XX log_it (cu_bytes - st.st_size);
XX return;
XX }
XX sprintf (tbuf, "#! rnews %ld\n", st.st_size);
XX fputs (tbuf, tfp);
XX while ((c=getc(afp)) != EOF)
XX putc (c, tfp);
XX fclose (afp);
XX if (++count == nfiles) {
XX spoolit ();
XX count = 0;
XX }
XX fcnt++;
XX }
XX /* The final spool if less than nfiles
XX is encountered. The zero out the
XX batchfile and unlink the lock file */
XX spoolit ();
XX close (creat(ep.site, 0664));
XX chown (ep.site, NEWSUID, NEWSGID);
XX unlink (lckfile);
XX /* here we log what we've done, and
XX if vflg is set, a copy to stdout
XX as well */
XX log_it (0);
XX if (chdir(LIBDIR) < 0)
XX xerror ("can't chdir back to %s\n", LIBDIR);
XX}
XXspoolit ()
XX{
XX struct stat st;
XX char cmd[BUFSIZ], cfile[80];
XX FILE *pfp;
XX int c;
XX fclose (tfp);
XX stat (tfile, &st);
XX /* if for some reason the temp file
XX is zero, just return */
XX if (st.st_size == 0)
XX return;
XX /* if ep.c_bits is set use COMPRESS to compress
XX the temp file first
XX */
XX if (ep.c_bits) {
XX sprintf (cmd, "%s -b%d %s", COMPRESS, ep.c_bits, tfile);
XX if (system(cmd) != 0)
XX xerror ("system(%s) failed\n", cmd);
XX strcpy (cfile, tfile);
XX strcat (cfile, ".Z");
XX if ((tfp=fopen(cfile, "r")) == NULL)
XX xerror ("can't open %s for reading\n", cfile);
XX /* if ep.command has a specific command
XX for UUCP spooling, use it. If not,
XX use UUX.
XX */
XX if (ep.command[0] != '\0')
XX strcpy (cmd, ep.command);
XX else
XX sprintf (cmd, "%s %s!rnews", UUX, ep.site);
XX /* now popen the command for writing
XX and send it the contents of tempfile */
XX if ((pfp=popen(cmd, "w")) == NULL)
XX xerror ("popen failed on %s\n", cmd);
XX /********************************************
XX * for version 2.10.3 and above,
XX * prepend `#! cunbatch'.
XX *
XX * NOTE: The remote site MUST be able to
XX * except this format, or it will
XX * be lost!!!
XX *******************************************/
XX fputs ("#! cunbatch\n", pfp);
XX while ((c=getc(tfp)) != EOF)
XX putc (c, pfp);
XX pclose (pfp);
XX fclose (tfp);
XX unlink (cfile);
XX } else { /* regular batching here */
XX if ((tfp=fopen(tfile, "r")) == NULL)
XX xerror ("can't open %s for reading\n", tfile);
XX /* if ep.command has a specific command
XX for UUCP spooling, use it. If not,
XX use UUX.
XX */
XX if (ep.command[0] != '\0')
XX strcpy (cmd, ep.command);
XX else
XX sprintf (cmd, "%s %s!rnews", UUX, ep.site);
XX if ((pfp=popen(cmd, "w")) == NULL)
XX xerror ("popen failed on %s\n", cmd);
XX while ((c=getc(tfp)) != EOF)
XX putc (c, pfp);
XX pclose (pfp);
XX fclose (tfp);
XX }
XX if ((tfp=fopen(tfile, "w")) == NULL)
XX xerror ("can't re-open %s\n", tfile);
XX scnt++;
XX}
@//E*O*F nbatcher.c//
chmod u=rw,g=rw,o=rw nbatcher.c
echo x - parse.c
sed 's/^XX//' > "parse.c" <<'@//E*O*F parse.c//'
XX/*
XX *
XX * parse.c - nbatcher line parser for the control file
XX *
XX *
XX * R.J. Esposito
XX * Bell of Penna.
XX * June 1986
XX *
XX */
XX#include <stdio.h>
XX#include <sys/types.h>
XX#include <ctype.h>
XX#include "nbatcher.h"
XX#define MAX_BYTES 1000000L /* max allowable bytes */
XXparse_entry (line)
XXchar *line;
XX{
XX register char *p;
XX short num, upper;
XX short lower, dash;
XX long l_num;
XX upper = 23; /* upper hour limit */
XX lower = 0; /* lower hour limit */
XX dash = 0;
XX clear_entry (&ep); /* zero out the structure */
XX p = (char *) ep.site;
XX /* get the site name and copy
XX it to the structure */
XX while (*line && *line != COLON)
XX *p++ = *line++;
XX *p = '\0';
XX if (*++line == '\n' || *line == '\0')
XX xerror ("illegal number of fields\n");
XX /* check that its valid */
XX if (ep.site[0] == '\0')
XX xerror ("null site name in control file\n");
XX /* now, parse the hour string and check
XX for valid syntax */
XX p = (char *) ep.hour;
XX while (*line && *line != COLON)
XX *p++ = *line++;
XX *p = '\0';
XX if (*++line == '\n' || *line == '\0')
XX xerror ("illegal number of fields\n");
XX if (ep.hour[0] == '\0')
XX xerror ("null hour string in control file\n");
XX /* now re-scan the hour in structure and
XX weed out the badies */
XX if (ep.hour[0] == '*' && ep.hour[1] != '\0')
XX xerror ("invalid hour string syntax: %s\n", ep.hour);
XX else if (ep.hour[0] == '*')
XX goto h_skip;
XX if (strcmp(ep.hour, "off", 3) == 0 && ep.hour[3] != '\0')
XX xerror ("invalid hour string syntax: %s\n", ep.hour);
XX else if (strncmp(ep.hour, "off", 3) == 0)
XX goto h_skip;
XX p = (char *) ep.hour;
XX if (!isdigit(*p))
XX xerror ("non-numeric char in hour string: %c\n", *p);
XX while (*p) {
XX num = 0;
XX do {
XX num = num*10 + (*p - '0');
XX } while (isdigit(*++p));
XX if (num < lower || num > upper)
XX xerror ("illegal hour: %d\n", num);
XX if (!*p)
XX break;
XX if (*p == '-' && dash)
XX xerror ("syntax error in hour field\n");
XX else if (*p == '-')
XX dash = TRUE;
XX if (*p != ',' && *p != '-')
XX xerror ("non-numeric char in hour string: %c\n", *p);
XX else if (!isdigit(*++p))
XX xerror ("syntax error in hour field\n");
XX }
XX /* now that thats over with, let do the compression
XX field. Only 9-16 is allowed, except a null field
XX indicates no compression for this site. */
XXh_skip:
XX num = 0;
XX while (*line && *line != COLON) {
XX if (!isdigit(*line))
XX xerror ("non-numeric in compression field\n");
XX num = num*10 + (*line++ - '0');
XX }
XX if (*++line == '\n' || *line == '\0')
XX xerror ("illegal number of fields\n");
XX if (num != 0 && (num < 9 || num > 16))
XX xerror ("illegal compression bits: %d\n", num);
XX ep.c_bits = num;
XX /* now check the max. bytes for UUCP queue.
XX Note: There is a max. allowable # of bytes
XX here, set at 1MB. Change it at your
XX own risk.
XX */
XX l_num = 0;
XX while (*line && *line != COLON) {
XX if (!isdigit(*line))
XX xerror ("non-numeric in max. bytes field\n");
XX l_num = l_num*10 + (*line++ - '0');
XX }
XX if (l_num > MAX_BYTES)
XX xerror ("%ld max. bytes exceeds allowable maximun\n", l_num);
XX if (l_num != 0)
XX ep.m_bytes = l_num;
XX else
XX ep.m_bytes = DFL_BYTES;
XX /* and finally the command line (if there is one) */
XX p = (char *) ep.command;
XX if (*++line != '\n' && *line != '\0') {
XX while (*line && *line != '\n')
XX *p++ = *line++;
XX *p = '\0';
XX }
XX}
XX#ifdef USE_PORT_CODE
XXxerror (fmt, a1, a2)
XXchar *fmt;
XXchar *a1, *a2;
XX{
XX char buf[BUFSIZ];
XX sprintf (buf, fmt, a1, a2);
XX printf ("nbatcher: %s\n", fmt);
XX exit (99);
XX}
XX#else
XXxerror (fmt, argp)
XXchar *fmt;
XXint argp;
XX{
XX char buf[BUFSIZ];
XX char fbuf[BUFSIZ];
XX FILE prwbuf;
XX register char *cp;
XX
XX prwbuf._flag = _IOWRT;
XX prwbuf._file = _NFILE;
XX prwbuf._cnt = 32767;
XX prwbuf._ptr = (unsigned char *)buf;
XX prwbuf._base = (unsigned char *)buf;
XX sprintf (fbuf, "%s: %s", "nbatcher", fmt);
XX _doprnt (fbuf, (char *)&argp, &prwbuf);
XX putc ('\0', &prwbuf);
XX for (cp = buf; *cp != '\0'; cp++)
XX putchar (*cp);
XX exit (99);
XX}
XX#endif /* USE_PORT_CODE */
XXclear_entry (s)
XXchar *s;
XX{
XX register int i;
XX for (i=0; i<sizeof(struct file_entry); *s++ = '\0', i++)
XX ;
XX}
@//E*O*F parse.c//
chmod u=rw,g=rw,o=rw parse.c
echo Inspecting for damage in transit...
temp=/tmp/sharin$$; dtemp=/tmp/sharout$$
trap "rm -f $temp $dtemp; exit" 0 1 2 3 15
cat > $temp <<\!!!
60 480 3043 README
76 441 2526 nbatcher.1
14 88 459 nbatcher.ctl
81 678 3907 nbatcher.doc
67 185 1387 Makefile
61 159 1088 bst.c
155 501 3094 checkwork.c
27 52 284 define.c
50 148 1022 logger.c
47 103 699 main.c
212 696 4805 nbatcher.c
202 668 4011 parse.c
1052 4199 26325 total
!!!
wc README nbatcher.1 nbatcher.ctl nbatcher.doc Makefile bst.c checkwork.c define.c logger.c main.c nbatcher.c parse.c | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp
if test -s $dtemp
then echo "Ouch [diff of wc output]:" ; cat $dtemp
else echo "No problems found."
fi
exit 0
More information about the Mod.sources
mailing list