Another News Batching Program
Jim Crammond
jim at hwcs.UUCP
Wed Oct 17 20:15:22 AEST 1984
#!/bin/sh
export PATH || (echo using sh to extract; /bin/sh $0; kill $$)
echo x - README
cat > README <<'FunkyStuff'
Yet Another Batchnews Program
--- ------- --------- -------
This set of batch and unbatch programs have been
adapted from those written by Jim McKie (mcvax!jim). They
are basically the same except that they conform to the
'standard' described in "Standard for Interchange of USENET
Messages" by Mark Horton and allow different compaction pro-
grams to be used for sites that have alternative programs to
Berkeley's "compact".
1. Features
- --------
Batched news can be compacted using alternative compact
programs to Berkeley's (un)compact(1) program. Some sites
use pack(1) or compress(1) rather than compact(1). These
programs allows a site to use different compact programs to
different sites and similiarly receive different types of
compacted news.
Both compacted and non-compacted forms conform to the
USENET specification so that the batched news can be sent to
rnews(1) on the remote site, which then calls the unbatcher.
The size of (uncompacted) batch files can be limited.
This is useful when the transfer media (such as long-
distance phone calls) imposes limitations on the length of
files transferred.
2. Description
- -----------
Batch reads a list of filenames from standard input of
articles to be batched and creates batch file(s) which it
then passes to uux(1) to forward to rnews at the remote
site.
It can optionally compact the batch files to save on
transmission time and costs.
Batch generates batch files in the USENET 'standard'
format:
#! rnews 1234
article containing 1234 characters
#! rnews 432
article containing 432 characters
....
If the batched file is compacted then batch generates a
file in the following format:
##! compactprog
compacted data
where compactprog is the (base) name of the compact program
used. Unbatch reads the first line to determine if the file
is compacted using a recognised compact program. It has a
table of valid compactprog names along with the correspond-
ing commands to uncompact the batch file.
The resulting (uncompacted) batch file is in the USENET
'standard' format.
Since both of these formats begin with a `#' they are
recognised by rnews to be batched files. Hence "batch" sends
its batches to rnews at the remote site which passes them on
to the unbatcher. The unbatcher does not need to be known
by uux at the remote site.
Sendbatch is a 'frontend' shell script to batch. It is
normally called from crontab.
3. Compatability
- -------------
Unless compacting, batch produces batch files using the
same format as the original batch program distributed with
news_2.10.1. Hence a site using the old unbatch program can
unbatch articles generated by this batcher.
The unbatch program can understand batched files in the
standard format generated by the original news_2.10.1 batch
program. In addition it can understand batched files gen-
erated by Jim McKie's 'batchnews' and if unbatch is invoked
with the -C flag it assumes the file to be compacted by
'batchnews' using the default compact program ( usually com-
pact(1) ).
4. Installation Instructions
- -------------------------
1. Unbatch.c contains a table of batch program names with
their corresponding unbatch program. e.g.
"compact", "/usr/ucb/uncompact"
"compress", "/usr/local/compress -d"
This may need to be edited to suit local requirements.
Note that only the basename of the compact program is
required, but the full path name of the uncompact pro-
gram should be given.
The default compact program in batch.c may also need to
be changed if your Berkeley compact program doesn't
live in /usr/ucb or you don't have it.
2. Depending on whether you are on a V7 or 4.xBSD system,
do "make v7" or "make bsd" as appropriate. Then do a
"make install" to get batch, unbatch, and sendbatch.
You need to do this as "root".
3. If you receive batched files from a site using Jim
McKie's batchnews then do "make compat" to replace
/usr/bin/unbatchnews with a link to unbatch.
4. At the sending site, change the sys file entries for
sites you batch to:
<site>:net.all,fa.all:F:/usr/spool/news/batched/<site>
This causes 2.10 news to list news items for <site> in
the named file.
5. At the sending site, add a line like this to
/usr/lib/crontab
45 0,6,12,18 * * * /usr/lib/news/sendbatch <site1> <site2>
to forward the batched news as often as you like.
If the sender polls the receiver, run this program when
news is to go out. If the receiver polls the sender,
run this program shortly before the poll is expected.
6. If you want the forwarded batched news to be compacted
then add the "-Ccompact" flag to sendbatch above, where
"compact" is the path name of the compact program:
.... /usr/lib/news/sendbatch -C/usr/ucb/compat <site1> ...
compact must be a program which the remote sites'
unbatch understands. If compactprog is not specfied
then it defaults to Berkeley 4.xBSD's compact.
7. The size of the uncompacted batch file can be limited
by the "-mSIZE" flag to sendbatch above, where SIZE is
some number of bytes > 1000. The default is 35000.
Notes
-----
Steps 4 to 7 are unnecessary if you already use Jim
McKie's 'batchnews'.
If you don't have "BATCH" defined in rnews (defs.h to
be precise) then this needs to be set to the pathname of the
unbatch program.
Bugs/Comments to:
Jim Crammond Heriot-Watt University, Edinburgh ...hwcs!jim 8/10/84
----------------------------------------------------------------------
FunkyStuff
echo x - Makefile
cat > Makefile <<'FunkyStuff'
#
# Definitions
#
LIBDIR = /usr/lib/news
BINDIR = /usr/bin
CFLAGS = -O
LFLAGS = -s
OWNER = news
GROUP = news
FILES = README Makefile batch.c unbatch.c sendbatch.v7 sendbatch.bsd
OBJECTS = batch unbatch
all: ${OBJECTS}
bsd:
cp sendbatch.bsd sendbatch.sh
v7:
cp sendbatch.v7 sendbatch.sh
batch: batch.c
cc -o batch $(CFLAGS) $(LFLAGS) batch.c
unbatch: unbatch.c
cc -o unbatch $(CFLAGS) $(LFLAGS) unbatch.c
install: all
cp batch unbatch $(LIBDIR)
cp sendbatch.sh $(LIBDIR)/sendbatch
chown $(OWNER) $(LIBDIR)/batch $(LIBDIR)/unbatch $(LIBDIR)/sendbatch
chgrp $(GROUP) $(LIBDIR)/batch $(LIBDIR)/unbatch $(LIBDIR)/sendbatch
chmod 755 $(LIBDIR)/batch $(LIBDIR)/unbatch $(LIBDIR)/sendbatch
compat: install
rm -f $(BINDIR)/unbatchnews
ln $(LIBDIR)/unbatch $(BINDIR)/unbatchnews
clean:
rm -f ${OBJECTS} sendbatch.sh
FunkyStuff
echo x - batch.c
cat > batch.c <<'FunkyStuff'
/*
* batchnews
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#define SINKCMD "uux - -r -z -gN %s!rnews"
#define TESTCMD "cat -u >> b.out"
#define COMPACT "/usr/ucb/compact"
#define TRACE(fmt, arg) if (tracing) fprintf(stderr, fmt, arg)
main(argc, argv)
int argc;
char *argv[];
{
FILE *sinkfp, *sourcefp, *popen();
char *host;
char *compact = NULL;
int testing = 0;
int tracing = 0;
struct stat statb;
long l, inbytes, infiles, outfiles;
long maxbytes = 35000L, atol();
int status = 0;
char buf[BUFSIZ], sink[BUFSIZ], *sprintf(), *basename();
char *ap, *argv0 = argv[0];
while ((--argc > 0) && ((*++argv)[0] == '-'))
{ ap = argv[0];
switch (*++ap)
{ case 'C':
if (*++ap != '\0')
compact = ap;
else
compact = COMPACT;
TRACE("compact = %s\n", compact);
break;
case 'm':
if ((l = atol(*++ap)) > 0 && l > 1000)
maxbytes = l;
TRACE("maxbytes = %ld\n", maxbytes);
break;
case 't':
testing = 1;
break;
case 'x':
tracing = 1;
break;
default:
break;
}
}
if (argc != 1)
{ ERROR("%s: usage %s [-Ccompactprog] host\n", argv0, argv0);
exit(1);
}
host = *argv;
if (compact)
sprintf(buf, "(echo '##! %s'; %s) | %s", basename(compact),
compact, (!testing) ? SINKCMD : TESTCMD);
else
strcpy(buf, (!testing) ? SINKCMD : TESTCMD);
sprintf(sink, buf, host);
TRACE("sink = %s\n", sink);
l = inbytes = infiles = outfiles = 0L;
sinkfp = NULL;
while (gets(buf) != NULL)
{ TRACE("source = %s\n", buf);
if ((sourcefp = fopen(buf, "r")) == NULL)
{ ERROR("%s: <%s> fails\n", argv0, buf);
continue;
}
if (fstat(fileno(sourcefp), &statb) == -1)
{ ERROR("%s: can't stat %s\n", argv0, buf);
fclose(sourcefp);
continue;
}
if (sinkfp == NULL)
{ if ((sinkfp = popen(sink, "w")) == NULL)
{ ERROR("%s: <%s> fails\n", argv0, sink);
exit(1);
}
outfiles++;
}
TRACE("size = %ld bytes\n", (long)statb.st_size);
inbytes += (long)statb.st_size;
l += (long)statb.st_size;
infiles++;
fprintf(sinkfp, "#! rnews %ld\n", (long)statb.st_size);
while (statb.st_size--)
{ register int c;
if ((c = getc(sourcefp)) == EOF)
break;
putc(c, sinkfp);
}
fclose(sourcefp);
fflush(stdout);
printf("\t%s\n", buf);
if (l > maxbytes)
{ TRACE("batched: %ld bytes\n", l);
status |= pclose(sinkfp);
sinkfp = NULL;
l = 0L;
TRACE("status = %d\n", status);
}
}
fflush(stdout);
if (sinkfp != NULL)
{ status |= pclose(sinkfp);
TRACE("status = %d\n", status);
}
printf("\t%ldb/%ldf -> %ld files\n", inbytes, infiles, outfiles);
exit(status);
}
char *
basename(s)
char *s;
{
char *p = s;
while (*p)
if (*p++ == '/')
s = p;
return(s);
}
ERROR(fmt, arg1, arg2)
register char *fmt;
{
fprintf(stderr, fmt, arg1, arg2);
}
FunkyStuff
echo x - unbatch.c
cat > unbatch.c <<'FunkyStuff'
/*
* unbatchnews
*/
#include <stdio.h>
#define SINKCMD "rnews"
#define TESTCMD "cat -u"
#define TRACE(fmt, arg) if(tracing) fprintf(stderr, fmt, arg)
struct comprog
{ char *comp; /* name of compacter */
char *uncomp; /* name of uncompacter */
} comprogs[] =
{
"compact", "/usr/ucb/uncompact",
"compress", "/usr/local/compress -d",
0,
};
#define UNCOMPACT comprogs[0].uncomp /* for compatability */
char cbuf[BUFSIZ];
main(argc, argv)
int argc;
char *argv[];
{
FILE *sinkfp, *sourcefp, *popen();
char *uncompact = NULL;
int testing = 0;
int tracing = 0;
char buf[BUFSIZ], sink[BUFSIZ], *sprintf(), *scanline();
char *ap, *argv0 = argv[0];
argv0 = *argv;
while ((--argc > 0) && ((*++argv)[0] == '-'))
{ ap = argv[0];
switch (*++ap)
{
#ifdef UNCOMPACT
case 'C':
uncompact = UNCOMPACT;
break;
#endif
case 't':
testing = 1;
break;
case 'x':
tracing = 1;
break;
default:
break;
}
}
if (argc != 0)
{ ERROR("%s: usage %s < source\n", argv0, argv0);
exit(1);
}
sprintf(sink, "%s", !testing ? SINKCMD: TESTCMD);
TRACE("sink = %s\n", sink);
#ifdef UNCOMPACT
if (!uncompact)
#endif
{
setbuf(stdin, NULL);
if (gets(buf) == NULL)
exit(0);
uncompact = scanline(buf);
}
if (uncompact)
{ TRACE("uncompacting with %s\n", uncompact);
if((sourcefp = popen(uncompact, "r")) == NULL)
{ ERROR("%s: <%s> fails\n", argv0, uncompact);
exit(1);
}
if (fgets(buf, BUFSIZ-1, sourcefp) == NULL)
exit(0);
}
else
{ setbuf(stdin, cbuf); /* restore buffered input */
sourcefp = stdin;
}
do {
register int c;
long size, atol();
if (sscanf(buf, "#! rnews %ld", &size) != 1)
#ifdef UNCOMPACT
if((size = atol(buf)) <= 0)
#endif UNCOMPACT
break;
TRACE("size = %ld\n", size);
if((sinkfp = popen(sink, "w")) == NULL){
ERROR("%s: <%s> fails\n", argv0, sink);
exit(1);
}
while(size-- && (c = getc(sourcefp)) != EOF)
putc(c, sinkfp);
pclose(sinkfp);
} while(fgets(buf, BUFSIZ-1, sourcefp) != NULL);
if (uncompact)
pclose(sourcefp);
TRACE("All done\n", "");
exit(0);
}
char *
scanline(line)
char *line;
{
struct comprog *cpp;
char progname[BUFSIZ];
if ( sscanf(line, "##! %s", progname) == 1 )
{ for (cpp= &comprogs[0]; cpp->comp != 0; cpp++)
{ if (strcmp(cpp->comp, progname) == 0)
return( cpp->uncomp );
}
}
return(NULL);
}
ERROR(fmt, arg1, arg2)
register char *fmt;
{
fprintf(stderr, fmt, arg1, arg2);
}
FunkyStuff
echo x - sendbatch.bsd
cat > sendbatch.bsd <<'FunkyStuff'
#!/bin/sh
#
# Send accumulated batched news to sites
#
BatchDir=/usr/spool/news/batched
Log=BLOG
BatchCmd=/usr/lib/news/batch
Args=
Cflg=
Mflg=
Xflg=
cd $BatchDir
for i in $*
do
case $i in
-C) Cflg=$i
;;
-x) Xflg=$i
;;
-m*) Mflg=$i
;;
*) Args="$Args $i"
;;
esac
done
for Site in $Args
do
date >> $Log.$Site
if [ -r $Site ]
then
mv $Site $Site.$$
$BatchCmd $Xflg $Cflg $Mflg $Site < $Site.$$ >> $Log.$Site 2>&1
rm -f $Site.$$
else
echo " No batched news for $Site" >> $Log.$Site
fi
done
FunkyStuff
echo x - sendbatch.v7
cat > sendbatch.v7 <<'FunkyStuff'
: #!/bin/sh
: #
: # Send accumulated batched news to sites
: #
BatchDir=/usr/spool/news/batched
Log=BLOG
BatchCmd=/usr/lib/news/batch
Args=
Cflg=
Mflg=
Xflg=
cd $BatchDir
for i in $*
do
case $i in
-C) Cflg=$i
;;
-x) Xflg=$i
;;
-m*) Mflg=$i
;;
*) Args="$Args $i"
;;
esac
done
for Site in $Args
do
date >> $Log.$Site
if [ -r $Site ]
then
mv $Site $Site.$$
$BatchCmd $Xflg $Cflg $Mflg $Site < $Site.$$ >> $Log.$Site 2>&1
rm -f $Site.$$
else
echo " No batched news for $Site" >> $Log.$Site
fi
done
FunkyStuff
echo Files Extracted
More information about the Comp.sources.unix
mailing list