jim@hwcs.UUCP (Jim Crammond) (10/17/84)
#!/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