[net.sources] Compressed Batching w/Restricted uux

yost@bty.UUCP (Brian Yost) (11/21/85)

Recently, I ported the USENET software to my system, an Altos 586
running XENIX 3.0.  One of the problems I ran into was with
compressed batching.  The problem is that my particular version
of ``uux'' will allow the following commands to be executed, and
no others:

		rnews	rmail	uusend	uucp

I get the impression that many other sites may have a similarly
restricted version of ``uux,'' so I am posting my solution.

As distributed, compressed batching requires that ``uux'' run
``cunbatch'' to decompress the batched files.  One solution would be
to bypass ``cunbatch'' and replace ``rnews'' with a shell script to
decompress and then call the real ``rnews.''  However, in order to be
capable of receiving unbatched news, batched news, and compressed batched
news, I decided to go into the source for ``rnews'' and have it take
care of decompression.

The idea is straightforward.  First, ``rnews'' must check for the magic
number used by the ``compress'' program (version 4.0).  If this magic
number is seen, then fork/exec ``compress'' with a temp file as its
standard output.  Once this child process has terminated, reopen the
temp file as the standard input to ``rnews,'' and continue as usual.

The routine ``checkbatch'' in the source file ifuncs.c reads the first
character of its input, to see if it is a '#' which indicates batching.
The test for the magic number must be inserted just before the test for
'#'.  If the magic number is seen, the new function ``uncompress'' is
called, which takes care of fork/exec'ing ``compress'' and redirecting
the i/o.

Please note that I have made an effort to limit my modifications to a
single source file.

The first group of additional lines comes right before the test
	if (c == '#')
in the function checkbatch() of ifuncs.c:

743a744,757
> 	/* Brian Yost	11/17/85	infopro!bty!yost
> 	 * Check for the compress(1) program's magic number,
> 	 * 037 235.  If found, uncompress the data before checking
> 	 * for batching.
> 	 */
> 	if (c == '\037') {	/* magic number for compress(1) */
> 		reset_stdin();
> 		uncompress();
> 		c = getc(stdin);
> 		if (c != EOF)
> 			ungetc(c, stdin);
> 		clearerr(stdin);
> 	}
> 	/* no else-if here! */

Note that I've only checked for the first byte of the magic number.
The second addition is the function uncompress(), which I chose to
place right after checkbatch() to keep the modifications localized
as much as possible:

751a766,794
> }
> 
> /* Brian Yost	11/17/85	infopro!bty!yost
>  * pipe stdin through compress(1) into a temporary file, and
>  * then redirect the standard input of rnews from this file.
>  */
> uncompress()
> {
> 	int wait_pid, child_pid, exit_status;
> 	char *tmp_file;
> 
> 	tmp_file = "/tmp/inewsXXXXXX";
> 	mktemp(tmp_file);
> 	if ((child_pid = fork()) == 0) {
> 		char uncompress[BUFLEN];
> 
> 		sprintf(uncompress, "%s/compress", BIN);
> 		/* redirect standard output to tmp_file */
> 		(void) freopen(tmp_file, "w", stdout);
> 		execl(uncompress, "compress", "-d", (char *)0);
> 		xerror("Unable to exec shell to uncompress news.");
> 	}
> 	while ((wait_pid = wait(&exit_status)) != child_pid)
> 		if (wait_pid == -1)
> 			break;
> 
> 	/* now redirect standard input from tmp_file */
> 	(void) freopen(tmp_file, "r", stdin);
> 	(void) unlink(tmp_file);	/* will disappear once closed */

I hope these changes will be of some help to sites with picky ``uux''
programs.  If any errors or omissions are found in the above code, kindly
forward the fixes to me.  Thanks in advance.

Brian Yost
infopro!bty!yost

greg@ncr-sd.UUCP (Greg Noel) (11/28/85)

In article <224@bty.UUCP> yost@bty.UUCP (Brian Yost) offers some code
to allow rnews to automaticly do its own decompression.

The idea is a good one; I believe it should be part of the next release
of netnews.  However, the scheme as offered does an unnecessary amount
of copying.  If the standard input is a pipe (or equivalent stream like
an ethernet link, a common case), reset_stdin() will copy the data to a
file, which will be copied by uncompress into a \second/ file by Brian's
code, and then finally read back into rnews.

An improved method would be (a) use a pipe to get the information from
uncompress to rnews, and (b) use the (undocumented, I know) -n option
of uncompress so that it won't try to read and check the magic number
on the input.  The pain of this is that the first read of the file must
avoid stdio so that only one (or two -- you should check that second
byte as well) bytes will be read and not a full stdio buffer.  Then there
will be \no/ file copying -- uncompress will read the standard input and
write the pipe while readnews will read the pipe.  With reasonable pipe
efficiency, this will never be translated into physical writes on the
disk and should run faster.

The only efficiency problem that I would see is that the eventual stdio
reads would not be reading the file on "natural" filesystem boundries.
Does anyone know a portable way of getting stdio to adjust its initial
read so that the following reads will be lined up?  I don't, and when I
was looking at implementing this, I couldn't decide if the loss of
efficiency would offset the gain from the reduction of file shuffling.
-- 
-- Greg Noel, NCR Rancho Bernardo    Greg@ncr-sd.UUCP or Greg@nosc.ARPA