From: frank.kaefer@stasys.sta.sub.org (Frank Kaefer)
Newsgroups: de.comp.sources.os9,comp.os.os9
Subject: MNews Prerelease Part07/09
Date: 23 Dec 92 19:41:42 GMT
Followup-To: de.comp.sources.d
Organization: Stasys News Server, Starnberg, Germany
NNTP-Posting-Host: stasys.sta.sub.org

Submitted-by: Ulrich Dessauer <ud@Nightmare.ddt.sub.org>
Archive-name: mnews/part07

: ----- Cut here ----- Cut here ----- Cut here ----- Cut here -----
: Use  sh filename  to extract shell archive
: This shell archive contains following files:
:     'MAN/News_in.prf                               666 bytes'
:     'MAN/News_out.prf                              448 bytes'
:     'MAN/Rnews.prf                                 680 bytes'
:     'MAN/Sbatch.prf                               2299 bytes'
:     'MAN/Sys.prf                                  3156 bytes'
:     'MISC/Makefile                                 912 bytes'
:     'MISC/decode.c                                3366 bytes'
:     'MISC/delold.c                                2730 bytes'
:     'MISC/encode.c                                3063 bytes'
:     'MISC/news_in.c                               1585 bytes'
:     'MISC/news_out.c                              3113 bytes'
:     'MISC/nstat.c                                 9149 bytes'
:     'MISC/rot13.c                                 1040 bytes'
:     'MISC/unmap.c                                 2012 bytes'
:     'RNEWS/Makefile                                453 bytes'
:     'RNEWS/compr.c                                4277 bytes'
: 
if test -f 'MAN/News_in.prf' ; then
  echo 'File MAN/News_in.prf already exists, overwriting it'
  del 'MAN/News_in.prf'
fi
echo Extracting \"'MAN/News_in.prf'\"
sed "s/^X//" >'MAN/News_in.prf' <<'__END__OF__THIS__FILE__'
X.THS News_in 8L News
X.SH NAME
X$N - gateways incoming mails to news.
X.SH SYNOPSIS
X$N [-f=<sender>] <newsgroup>
X.SH DESCRIPTION
XIn combination with
X.B News_out
X$N can be used to forward news as mails and to allow answering to an
Xarticle via mail. For this you need a flexible mail transport agent,
Xe.g. sendmail or MMail. The
X.B <sender>
Xis optional and currently not used.
X.B <newsgroup>
Xmust be a valid newsgroup either with dots or with hyphens. Valid
Xnewsgroups are then (e.g.) comp-lang-c or rec.games.frp. The hyphen
Xsolution is used to avoid a miss-parsing the dots as domains.
X.SH CAVEATS
XThis is only a very primitiv solution and may cause several problems.
X
__END__OF__THIS__FILE__
if test -f 'MAN/News_out.prf' ; then
  echo 'File MAN/News_out.prf already exists, overwriting it'
  del 'MAN/News_out.prf'
fi
echo Extracting \"'MAN/News_out.prf'\"
sed "s/^X//" >'MAN/News_out.prf' <<'__END__OF__THIS__FILE__'
X.THS News_out 8L News
X.SH NAME
X$N - gateways incoming news to mail.
X.SH SYNOPSIS
X$N <receiver>
X.SH DESCRIPTION
XIn combination with
X.B News_in
X$N can be used to forward news as mails and to allow answering to an
Xarticle via mail. $N tries to set the
X.B Reply-To:
Xline to a valid name (<group>\@newsgroup.<local-domain>) to allow a
Xsimple answer posting by the user.
X.SH CAVEATS
XThis is only a very primitiv solution and may cause several problems.
X
__END__OF__THIS__FILE__
if test -f 'MAN/Rnews.prf' ; then
  echo 'File MAN/Rnews.prf already exists, overwriting it'
  del 'MAN/Rnews.prf'
fi
echo Extracting \"'MAN/Rnews.prf'\"
sed "s/^X//" >'MAN/Rnews.prf' <<'__END__OF__THIS__FILE__'
X.THS Rnews 8L News
X.SH NAME
XRnews - Receive batched Articles from remote System
X.SH SYNOPSIS
Xrnews [-d=<dbglvl>] [<file>]
X.SH DESCRIPTION
X.ti +3
XRnews is called by a remote system to unpack the received news article
Xand feed them to Inews.  If Inews failed for any reasons, rnews will
Xstore this article in
X.B /h0/SPOOL/RNEWS
X(or whereever set using Sysinfo).
X.SH FILES
X.O /h0/SPOOL/RNEWS
XStore failed article there.
X.NO /h0/SPOOL/UUCP/.LOG/rnews.log
XThe logfile, will only be written if existing.
X.EO
X.SH SYSINFO
X.O RNEWS.DIR,s=/h0/SPOOL/RNEWS
XSets the directory where failed article should be placed
X.EO
X.SH SEE ALSO
X Inews - in this distribution
X Sbatch - in this distribution
__END__OF__THIS__FILE__
if test -f 'MAN/Sbatch.prf' ; then
  echo 'File MAN/Sbatch.prf already exists, overwriting it'
  del 'MAN/Sbatch.prf'
fi
echo Extracting \"'MAN/Sbatch.prf'\"
sed "s/^X//" >'MAN/Sbatch.prf' <<'__END__OF__THIS__FILE__'
X.THS Sbatch 8L News
X.SH NAME
XSbatch - Collect and batch News article for remote system
X.SH SYNOPSIS
X.raw
Xsbatch [-c|-c7|-cf|-cf7|-b|-s] [-B=<size>] [-t]
X       [-G=<grade>] [-f=<size>] [-C=<cmd>] [-n=<system>]
X       <system>
X.noraw
X.SH DESCRIPTION
X.ti +3
XSbatch collects all article which should be send to a remote system.
XOn default all articles are batched into one file until the size limit
Xis reached. With
X.O -c
Xyou can compress the news to get a better throughput.
X.NO -cf
Xforces `freeze' to be used instead of compresss.
X.NO -c7
Xwill encode them after compression to transmit them over lines which
Xonly supports 7 Bit.
X.NO -cf7
Xwill be used for 7 Bit channels with `freeze' to compress data.
X.NO -s
Xall articles are spooled as single files.
X.NO -f=<size>
Xgives the limit of a file in kBytes. the default is 50 kByte. 
X.NO -B=<bitcount>
XTo compress with another bitvalue than 16 (the default, use the option
Xto set the bitvalue to 12 to 16. 
X.NO -G=<grade>
XIf your delivering program accepts a grade character in the command
Xstring then you can change this here. 
X.NO -C=<cmd>
Xthe delivery command can be changed with this to a complete new value. 
XThe command may contain two different sequences for inserting the grade
Xcharacter and the system name.  These are
X.bold
X\%S
Xfor the system and
X.bold
X\%G
Xfor the grading.
X.NO -t
Xthis is for use with eight bit characters. If your neighbor host doesn't
Xsupport these characters then they are translated back to pure seven bit
XASCII. Currently only the german umlaute for ISO8859/1 are supported.
X.NO -n=<system>
XIf the name in the command to forward news differs from the filename the
Xbatchfile is stored then this is used as the filename of the batched
Xarticles.
X.EO
X.SH CAVEATS
XThe files are stored in temporary on /dd. If this too small things may
Xfail.
X.SH BUGS
XMay be a lot, none known.
X.SH FILES
X.O /h0/SPOOL/BATCH
XThe articles are stored herein, for each system one file with the
Xfilename of the system. The format is an optional flagfield seperated
Xfrom the main filename by a bar
X.RB (` | ').
XCurrently there are the two flags
X.RB ` N '
Xand
X.RB ` C '
Xfor non-convert and convert from 8 bit (if these optiones are proper
Xinserted the `-t' option is obsolete.)
X.EO
X.SH SEE ALSO
X Inews - in this distribution
X Rnews - in this distribution
__END__OF__THIS__FILE__
if test -f 'MAN/Sys.prf' ; then
  echo 'File MAN/Sys.prf already exists, overwriting it'
  del 'MAN/Sys.prf'
fi
echo Extracting \"'MAN/Sys.prf'\"
sed "s/^X//" >'MAN/Sys.prf' <<'__END__OF__THIS__FILE__'
X.THS Sys 5L News
X.SH NAME
XSys - this file describes the mechanism to forward received articles to
Xother sites or to programs.
X.SH DESCRIPTION
X.ti +3
XThis files specifies the newsgroups and distributions to be forwarded to
Xanother site or to be pipe'd to a program. So you are able to limit the
Xamount of articles to be forwarded by area (distribution) or/and the
Xtopics (newsgroups).
X.SH FORMAT
XThe format of the file is
X.ce
X<system>{> <flags>}:<newsgroups>:<dists>{:<program>}
Xwhere
X.B <system>
Xis in general the system to forward the news (or an ID for programs).
XYou can append a list of other systemnames (seperated by a slash
X.B /
Xform the main system), which are seperated by commas to stop forwarding
Xarticles which had already passed these systems. The
X.B <flags>
Xare a list of flags which are inserted before the filename in the
Xbatchfile. These flags are interpreted by sbatch only. The
X.B <newsgroups>
Xis a list of newsgroups which are in regular expression format (using
XHenry Spencer's regular expression library), seperated by spaces.
XInternal the expression will be enclosed with
X.B ^
Xand
X.bold
X\$
Xto allow only exact matches.
X.B <dists>
Xare the distributions which aren't regular expressions, but they may
Xcontain the meta characters
X.B ?
Xand
X.B *
Xto match one (?) or zero or more (*) characters. The <newsgroups> and
X<dists> field allow a not operation by prefixing an expression with an
X.B !
Xso you can select specific items not to be forwarded. If an article
Xshould be forwarded the filename is written in a file in
X.B /h0/SPOOL/BATCH
Xwith the filename equal to <system> (if possible). This file is used by
X.B sbatch
Xto send the articles themselves.
X.PP
XThe
X.B <program>
Xis optional but if it is given the filename of the article isn't written
Xto the file mentioned above but the article itself is pipe'd to this
Xprogram (so the program must read the article from stdin).
X.PP
XIf the first character of <program> is a plus sign then the rest will be
Xused as a full path to a directory where to store the articles with
Xincreasing numbers. If the first character is a minus sign then the rest
Xis a full path to a directory which is used instead of the batch
Xdirectory (/h0/SPOOL/BATCH).
X.PP
XEach line in this file may be continued in the next line if the last
Xcharacter in the prvious line had been a backslash.
X.PP
XIf a line starts with a colon
X.RB ( : )
Xthen the rest of the line is taken as a filename of a file to be
Xincluded.  With this features it is possible to create one file for each
Xsystem which can be changed from remote via mail.  For this purpose the
Xprogram
X.B remsys
Xcan be found in this distribution.
X.SH EXAMPLES
X.raw 4
Xmyfeed:!local.* to\\.myfeed !to\\..* .*:!local *
Xsubfeed:(sub|muc)\\..*:sub muc world
Xsave:.*source.*:*:save_it
X.noraw
X.B myfeed
Xwill get everything expect these newsgroups which are prefixed by
X.B local
Xor have distribution
X.B local
Xor have the prefix
X.B to.
Xand not followed by myfeed.
X.B subfeed
Xwill only receive groups of a local are (Newsgroups prefixed by muc. or
Xsub. and distribution muc sub and world). The entry
X.B save
Xwill store (assuming a proper program) all articles in source groups.
__END__OF__THIS__FILE__
if test -f 'MISC/Makefile' ; then
  echo 'File MISC/Makefile already exists, overwriting it'
  del 'MISC/Makefile'
fi
echo Extracting \"'MISC/Makefile'\"
sed "s/^X//" >'MISC/Makefile' <<'__END__OF__THIS__FILE__'
X# $Id: Makefile_v 1.1.1.1 90/09/08 16:08:49 ud Exp $
X# $Log:	Makefile_v $
X# Revision 1.1.1.1  90/09/08  16:08:49  ud
X# Insert entry for delold
X# 
X# Revision 1.1  90/08/31  15:28:34  cv
X# Initial revision
X# 
X#
XCC=	cc
XG=	-g
XCFLAGS=	-qt=/dd/TMP $G -v=.. -v=../8BIT
XLIBS=	-l=/dd/LIB/os9lib.l
XLFLAGS=	-q $(LIBS) $G
XODIR=	/h0/ETC/CMDS
X
Xencode:	encode.r
X
Xdecode:	decode.r
X
Xdelold:	delold.r
X	$(CC) $(LFLAGS) delold.r -f=$(ODIR)/$@ -m=50
X	fixmod -uo2.39 $(ODIR)/$@
X
Xunmap:	unmap.r
X	$(CC) $(LFLAGS) unmap.r -f=$(ODIR)/$@
X	fixmod -uo90.91 $(ODIR)/unmap
X
Xnews_in:	news_in.r
X	$(CC) $(LFLAGS) news_in.r -f=$(ODIR)/$@
X	fixmod -uo2.39 $(ODIR)/$@
X
Xnews_out:	news_out.r
X	$(CC) $(LFLAGS) news_out.r -f=$(ODIR)/$@ -l=/dd/LIB/8bit.l
X	fixmod -uo2.39 $(ODIR)/$@
X
Xrot13:	rot13.r
X	$(CC) $(LFLAGS) rot13.r -f=$(ODIR)/$@ -l=/dd/LIB/8bit.l
X
Xnstat:	nstat.r
X	$(CC) $(LFLAGS) nstat.r -f=$(ODIR)/$@ -l=/dd/LIB/8bit.l
X	fixmod -uo2.39 $(ODIR)/$@
__END__OF__THIS__FILE__
if test -f 'MISC/decode.c' ; then
  echo 'File MISC/decode.c already exists, overwriting it'
  del 'MISC/decode.c'
fi
echo Extracting \"'MISC/decode.c'\"
sed "s/^X//" >'MISC/decode.c' <<'__END__OF__THIS__FILE__'
X#include <stdio.h>
X
X#ifdef SCCSID
Xstatic char	*SccsId = "@(#)decode.c	1.3	5/15/85";
X#endif /* SCCSID */
X
X/*
X * This program is the inverse of encode
X *
X * It collects runs of 12 characters, combines pairs of those
X * to form 6 13 bit numbers, extracts the top bit of each of
X * those to make a 13th 6 bit character, and splits each of
X * the remaining 6 12 bit numbers to form 12 6 bit ones.
X *
X * The strings of 6 bit numbers are collected into groups of
X * 4 and converted into 3 8 bit characters.
X *
X * Now all that would be trivial, if we didn't need to worry
X * about ending all this correctly.  About 1/2 of the following
X * program wouldn't be here if the ending didn't matter....
X */
X
X/*
X * the following pair of characters can never occur as a pair
X * in legal input (since (90 * 91 + 90) > 2^13) - they are
X * noticed at the beginning of a 12 char block, and serve to
X * indicate that this block is the terminator.  The character
X * immediately following is the (expanded) terminator length.
X */
X#define	ENDMARK1	((90*91 + 90) / 91)
X#define	ENDMARK2	((90*91 + 90) % 91)
X
Xmain()
X{
X	register c;
X	register char *p;
X	register i;
X	register first = 1;
X	register cnt = 0;
X	int errcnt = 0;
X	char b12[12];
X	char c12[12];
X
X	p = b12;
X	i = 12;
X
X	while ((c = getchar()) != EOF) {
X		if (c < ' ' || c >= (' ' + 91)) {
X			if (errcnt++ == 0)
X				fprintf(stderr, "decode: Bad data\n");
X			continue;
X		}
X		if (i == 10 && p[-1] == ENDMARK1 && p[-2] == ENDMARK2) {
X			cnt = c - ' ';
X			i = 12;
X			p -= 2;
X			continue;
X		}
X		*p++ = c - ' ';
X		if (--i == 0) {
X			if (p == &b12[12]) {
X				if (!first)
X					pack12(c12, 12, 0);
X				else
X					first = 0;
X				p = c12;
X			} else {
X				pack12(b12, 12, 0);
X				p = b12;
X			}
X			i = 12;
X		}
X	}
X
X	if (p >= &b12[0] && p < &b12[12]) {
X		if (!first)
X			pack12(c12, 12, i == 12 ? cnt : 0);
X	} else
X		pack12(b12, 12, i == 12 ? cnt : 0);
X
X	if (i != 12) {
X		if (p >= &b12[0] && p < &b12[12])
X			pack12(b12, 12-i, cnt);
X		else
X			pack12(c12, 12-i, cnt);
X	}
X
X	exit(0);
X}
X
Xstatic char b4[4];
Xstatic int cnt = 0;
X
Xpack12(p, n, last)
X	register char *p;
X	register n;
X	int last;
X{
X	register i;
X	register char *q;
X	char b13[13];
X
X	{
X		register c;
X		register c13;
X
X		q = b13;
X		c13 = 0;
X
X		for (i = 0; i < n; i += 2) {
X			c = *p++ * 91;
X			c += *p++;
X			c13 <<= 1;
X			if (c & (1 << 12))
X				c13 |= 1;
X			*q++ = (c >> 6) & 0x3f;
X			*q++ = c & 0x3f;
X		}
X		*q++ = c13;
X		if (last)
X			q = &b13[last];
X	}
X
X	p = b13;
X	n = q - p;
X	i = cnt;
X	q = &b4[cnt];
X
X	while (--n > 0) {
X		*q++ = *p++;
X		if (++i == 4) {
X			char b3[3];
X			register char *b = b4;
X
X			/* inline expansion of pack6bit, to save calls ... */
X
X			q = b3;
X			*q++ = (b[0] << 2) | ((b[1] >> 4) & 0x3);
X			*q++ = (b[1] << 4) | ((b[2] >> 2) & 0xf);
X			*q = (b[2] << 6) | (b[3] & 0x3f);
X
X			q = b3;
X			while (--i > 0)
X				putchar(*q++);
X
X			q = b4;
X		}
X	}
X
X	*q++ = *p++;	/* the last octet */
X	++i;
X
X	if (last || i == 4) {
X		pack6bit(b4, i, last);
X		i = 0;
X	}
X
X	cnt = i;
X}
X
Xpack6bit(p, n, last)
X	register char *p;
X	register int n;
X	int last;
X{
X	register char *q;
X	register i = 3;
X	char b3[3];
X
X	if (last) {
X		i = p[n-1];
X		if (i >= 3) {
X			fprintf(stderr, "Badly encoded file\n");
X			i = 3;		/* do the best we can */
X		}
X	}
X
X	q = b3;
X	*q++ = (p[0] << 2) | ((p[1] >> 4) & 0x3);
X	*q++ = (p[1] << 4) | ((p[2] >> 2) & 0xf);
X	*q = (p[2] << 6) | (p[3] & 0x3f);
X
X	q = b3;
X
X	while (--i >= 0)
X		putchar(*q++);
X}
X
__END__OF__THIS__FILE__
if test -f 'MISC/delold.c' ; then
  echo 'File MISC/delold.c already exists, overwriting it'
  del 'MISC/delold.c'
fi
echo Extracting \"'MISC/delold.c'\"
sed "s/^X//" >'MISC/delold.c' <<'__END__OF__THIS__FILE__'
X/*
X * $Log:	delold.c_v $
X * Revision 1.1  90/09/08  15:52:24  cv
X * Initial revision
X * 
X */
X# ifndef	LINT
Xstatic char rcsid[] = "$Id: delold.c_v 1.1 90/09/08 15:52:24 cv Exp $";
Xstatic char copyright[] = "Copyright (C) 1989, 1990 by Ulrich Dessauer, Germering, Germany.\n";
X# endif		LINT
X# include	<stdio.h>
X# include	<ctype.h>
X# include	<time.h>
X# include	<types.h>
X# include	<stat.h>
X# include	<dir.h>
X# include	"news.h"
X
Xextern char	*malloc ();
Xextern int	errno;
X
Xtypedef struct _dirlist {
X	char	fn[33];
X	int	isdir;
X	struct _dirlist	*next;
X} dirlist;
X
Xtime_t	secs;
Xtime_t	tim;
Xint	count;
Xchar	fpath[1024];
X
Xvoid
Xdo_scan (path)
Xchar *path;
X{
X	DIR		*dp;
X	struct direct	*ent;
X	dirlist		*head, *cur, *tmp;
X	register char	*p;
X	char		*sav;
X	struct stat	st;
X
X	if (path)
X		if (chdir (path) < 0) {
X			fprintf (stderr, "Can't chdir to %s (errno %d).\n", path, errno);
X			return;
X		}
X	head = NULL;
X	cur = NULL;
X	if (!(dp = opendir ("."))) {
X		fprintf (stderr, "Can't open '%s' (errno %d), skip over.\n", path ? path : "[root]", errno);
X		if (path)
X			chdir ("..");
X		return;
X	}
X	if (path) {
X		p = fpath;
X		while (*p)
X			++p;
X		sav = p;
X		*p++ = '/';
X		strcpy (p, path);
X		printf ("Now in %s\n", fpath);
X	}
X	while (ent = readdir (dp)) {
X		if (ent->d_name[0] == '.')
X			continue;
X		p = ent->d_name;
X		while (*p)
X			if (!isdigit (*p))
X				break;
X			else
X				++p;
X		if (!(tmp = (dirlist *) malloc (sizeof (dirlist)))) {
X			fprintf (stderr, "PANIC: Out of memory! (errno %d)\n", errno);
X			closedir (dp);
X			exit (1);
X		}
X		strcpy (tmp->fn, ent->d_name);
X		tmp->isdir = (*p != '\0');
X		tmp->next = NULL;
X		if (!head)
X			head = tmp;
X		else
X			cur->next = tmp;
X		cur = tmp;
X	}
X	closedir (dp);
X	cur = head;
X	while (cur) {
X		if (cur->isdir)
X			do_scan (cur->fn);
X		else if (stat (cur->fn, &st) == -1)
X			fprintf (stderr, "Can't stat %s (errno %d).\n", cur->fn, errno);
X		else if (st.st_mtime + secs < tim)
X			if (unlink (cur->fn) < 0)
X				fprintf (stderr, "Can't unlink %s (errno %d).\n", cur->fn, errno);
X			else
X				++count;
X		tmp = cur;
X		cur = cur->next;
X		free ((char *) tmp);
X	}
X	if (path) {
X		*sav = '\0';
X		chdir ("..");
X	}
X}
X
Xint
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char	buf[256];
X	int	days;
X
X	setuid (getmuid ());
X	if ((argc != 2) || (!isdigit (argv[1][0])))
X		exit (_errmsg (1, "Usage: %s <days>\n", argv[0]));
X	if ((days = atoi (argv[1])) < 1)
X		exit (_errmsg (1, "<days> must be greater than zero.\n"));
X	secs = (time_t) (days * 24 * 60 * 60);
X	time (&tim);
X	if (!info_str (NEWSDIR, buf, sizeof (buf)))
X		strcpy (buf, DEF_NEWSDIR);
X	if (chdir (buf) < 0)
X		exit (_errmsg (1, "Can't chdir() to %s, errno %d.\n", buf, errno));
X	strcpy (fpath, ".");
X	count = 0;
X	do_scan (NULL);
X	printf ("%d old articles deleted.\n", count);
X}
__END__OF__THIS__FILE__
if test -f 'MISC/encode.c' ; then
  echo 'File MISC/encode.c already exists, overwriting it'
  del 'MISC/encode.c'
fi
echo Extracting \"'MISC/encode.c'\"
sed "s/^X//" >'MISC/encode.c' <<'__END__OF__THIS__FILE__'
X#include <stdio.h>
X
X#ifdef SCCSID
Xstatic char	*SccsId = "@(#)encode.c	1.3	5/15/85";
X#endif /* SCCSID */
X
X/*
X * Produce a 7 bit printable encoding of stdin on stdout.
X *
X * Encoding uses acsii chars from ' ' .. 'z'
X * (040 .. 0172) (0x20 - 0x7a) inclusive
X *
X * Method is to expand 3 chars -> 4 6 bit ones.
X * Then collect 13 6 bit chars, and spread the 13th over
X * the preceding 12, so that each of the 12 chars is now
X * 6.5 bits.  These 2 6.5 bit chars are a little hard
X * to represent on most common machines (one of these days
X * sane hosts will have 1/2 bits just for this program)
X * so we take a pair of them, and represent that in 13 bits.
X * 13 bits (max value 8191) can be represented as
X *	A * 91 + B
X * where A < 91, B < 91  (91^2 == 8281, so it fits!)
X *
X * Each of A and B is encoded as a character by adding 32
X * to make it printable (ie: 0x20).
X *
X * The termination conditions are foul beyond belief.  Don't
X * monkey with them!
X *
X * If you think its a fluke that 040 .. 0171 just happen to
X * be the chars that Piet Beertema's uucp 'f' protocol transmits
X * as single bytes, you're insane.  0172 chars are produced
X * with lower frequency than any other (given random data)
X * so the doubling that occurs with that we will just suffer.
X * (A newer 'f' proto, sometime, will probably not use 0172)
X */
X
X/*
X * the following pair of characters cannot legally occur
X * in normal output (since 90*91 + 90 == 8280, which > 2^13)
X * so we use them to indicate that the data that follows is the
X * terminator.  The character immediately following this
X * pair is the length of the (expanded) terminator (which
X * otherwise might be indeterminable)
X */
X#define	ENDMARK1	((90*91 + 90) / 91 + ' ')
X#define	ENDMARK2	((90*91 + 90) % 91 + ' ')
X
Xmain()
X{
X	register char *p;
X	register char *e;
X	register c;
X	char b3[3];
X
X	p = b3;
X	e = b3 + 3;
X	while ((c = getchar()) != EOF) {
X		*p++ = c;
X		if (p == e) {
X			encode(b3, 3);
X			p = b3;
X		}
X	}
X	encode(b3, p - b3);
X	flushout();
X	exit(0);
X}
X
Xstatic char b13[13];
Xstatic int cnt = 0;
X
Xencode(c, n)
X	register char *c;
X	int n;
X{
X	register char *p;
X	register i = cnt;
X	register j;
X	char b4[4];
X
X	p = b4;
X
X	p[0] = (c[0] >> 2) & 0x3f;
X	p[1] = ((c[0] & 0x3) << 4) | ((c[1] >> 4) & 0xf);
X	p[2] = ((c[1] & 0xF) << 2) | ((c[2] >> 6) & 0x3);
X	if (n == 3)
X		p[3] = c[2] & 0x3f;
X	else
X		p[3] = n;
X
X	c = &b13[i];
X	for (j = 4; --j >= 0; i++) {
X		if (i == 13) {
X			dumpcode(b13, 13);
X			c = b13;
X			i = 0;
X		}
X		*c++ = *p++;
X	}
X	cnt = i;
X}
X
Xflushout()
X{
X	putchar(ENDMARK1);
X	putchar(ENDMARK2);
X	putchar(cnt + ' ');
X	dumpcode(b13, cnt);
X}
X
Xdumpcode(p, n)
X	register char *p;
X	register int n;
X{
X	register last;
X	register c;
X
X	if (n == 13)
X		n--, last = p[12];
X	else if (n & 1)
X		last = (1 << (6-1));
X	else
X		last = 0;
X
X	for ( ; n > 0; n -= 2) {
X		c = *p++ << 6;
X		c |= *p++;
X		if (last & (1 << (6-1)))
X			c |= (1 << 12);
X		last <<= 1;
X
X		/*
X		 * note: 91^2 > 2^13, 90^2 < 2^13, (91 + ' ') is printable
X		 */
X
X		/* oh for a compiler that would only do one division... */
X		putchar((c / 91) + ' ');
X		putchar((c % 91) + ' ');
X	}
X}
X
__END__OF__THIS__FILE__
if test -f 'MISC/news_in.c' ; then
  echo 'File MISC/news_in.c already exists, overwriting it'
  del 'MISC/news_in.c'
fi
echo Extracting \"'MISC/news_in.c'\"
sed "s/^X//" >'MISC/news_in.c' <<'__END__OF__THIS__FILE__'
X# include	<stdio.h>
X
Xextern char	*index ();
Xextern char	*strdup ();
Xextern FILE	*xpopen ();
X
Xvoid
Xusage ()
X{
X	fprintf (stderr, "Usage: news_in [-f=<sender>] <newsgroup>\n");
X}
X
Xint
Xmain (ac, av)
Xint ac;
Xchar *av[];
X{
X	char	*from;
X	char	*group;
X	int	t;
X	char	*ptr;
X	FILE	*pp;
X	char	buf[260];
X	int	n;
X	int	err;
X	int	pend;
X
X	setuid (getmuid ());
X	from = NULL;
X	group = NULL;
X	for (t = 1; t < ac; ++t)
X		if (av[t][0] == '-') {
X			ptr = av[t] + 1;
X			while (*ptr) {
X				switch (*ptr) {
X					case 'f':
X						ptr += *(ptr + 1) == '=' ? 2 : 1;
X						from = ptr;
X						while (*ptr)
X							++ptr;
X						break;
X					case '?':
X						usage ();
X						exit (1);
X					default:
X						break;
X				}
X				if (*ptr)
X					++ptr;
X			}
X		} else if (!group)
X			group = strdup (av[t]);
X	if (!group)
X		exit (1);
X	ptr = group;
X	while (ptr)
X		if (ptr = index (ptr, '-'))
X			*ptr++ = '.';
X	if (!_strccmp (group, "postmaster"))
X		pp = xpopen ("mail -s=News_In Postmaster", "w");
X	else
X		pp = xpopen ("inews -h", "w");
X	if (!pp)
X		exit (1);
X	err = 0;
X	pend = 0;
X	while ((n = readln (0, buf, 256)) > 0)
X		if (!group) {
X			if (fwrite (buf, sizeof (char), n, pp) != n) {
X				++err;
X				break;
X			}
X		} else {
X			if ((buf[n - 1] != '\n') || pend) {
X				pend = (!pend);
X				if (fwrite (buf, sizeof (char), n, pp) != n) {
X					++err;
X					break;
X				}
X				continue;
X			} else if (n == 1) {
X				fprintf (pp, "Newsgroups: %s\n\n", group);
X				free (group);
X				group = NULL;
X			} else if (fwrite (buf, sizeof (char), n, pp) != n) {
X				++err;
X				break;
X			}
X		}
X	free (buf);
X	if (pclose (pp))
X		++err;
X	exit (err ? 1 : 0);
X}
__END__OF__THIS__FILE__
if test -f 'MISC/news_out.c' ; then
  echo 'File MISC/news_out.c already exists, overwriting it'
  del 'MISC/news_out.c'
fi
echo Extracting \"'MISC/news_out.c'\"
sed "s/^X//" >'MISC/news_out.c' <<'__END__OF__THIS__FILE__'
X# include	<stdio.h>
X# include	<c8type.h>
X
Xextern char	*cuserid ();
Xextern char	*getenv ();
Xextern char	*index ();
Xextern char	*malloc ();
Xextern char	*strdup ();
Xextern char	*strredup ();
Xextern FILE	*xpopen ();
X
Xstruct {
X	char	*pat;
X	int	len;
X} todel[] = {
X	"path:",	5,
X	"message-id:",	11,
X	"reply-to:",	9,
X	"sender:",	7,
X	NULL,		0
X};
X
Xchar *
Xgetng (og, s)
Xchar *og;
Xregister char *s;
X{
X	char	*sav;
X
X	if (s = index (s, ':')) {
X		++s;
X		while (is8space (*s))
X			++s;
X		sav = s;
X		while (*s && (*s != ',') && (!is8space (*s)))
X			++s;
X		*s = '\0';
X		og = strredup (og, sav);
X		s = og;
X		while (s = index (s, '.'))
X			*s++ = '-';
X	}
X	return (og);
X}
X		
Xint
Xmain (ac, av)
Xint ac;
Xchar *av[];
X{
X	FILE		*pp;
X	FILE		*fp;
X	char		fn[128];
X	char		*cmd;
X	int		t;
X	int		siz;
X	int		n;
X	int		inhead;
X	int		mode;
X	char		*ng;
X	char		*path;
X	char		fhost[128];
X	char		sender[160];
X	register char	*sptr;
X	register char	*ptr;
X
X	setuid (getmuid ());
X	if (ac < 2)
X		exit (0);
X	if (!(sptr = cuserid ()))
X		if (!(sptr = getenv ("USER")))
X			if (!(sptr = getenv ("LOGNAME")))
X				sptr = "Postmaster";
X	strcpy (sender, sptr);
X	sptr = sender;
X	while (*sptr)
X		++sptr;
X	*sptr++ = '@';
X	if (gethostname (sptr, 64))
X		while (*sptr)
X			++sptr;
X	strcpy (fhost, "newsgroup");
X	ptr = fhost;
X	while (*ptr)
X		++ptr;
X	if (info_str ("hostdomain", ptr + 1, 96)) {
X		*ptr = '.';
X		strcpy (sptr, ptr);
X	} else
X		*sptr = '\0';
X	siz = 0;
X	for (t = 1; t < ac; ++t)
X		siz += strlen (av[t]) + 4;
X	siz += 64;
X	if (!(cmd = malloc (siz < 260 ? 260 : siz)))
X		exit (0);
X	strcpy (cmd, "rmail");
X	for (t = 1; t < ac; ++t) {
X		strcat (cmd, " '");
X		strcat (cmd, av[t]);
X		strcat (cmd, "'");
X	}
X	strcpy (fn, "/dd/TMP/newsoutXXXXXX");
X	mktemp (fn);
X	if (!(fp = fopen (fn, "w+")))
X		exit (0);
X	if (pp = xpopen (cmd, "w")) {
X		ng = NULL;
X		path = NULL;
X		inhead = 1;
X		mode = 0;
X		while ((n = readln (0, cmd, 256)) > 0) {
X			cmd[n] = '\0';
X			if (inhead)
X				for (t = 0; todel[t].pat; ++t)
X					if (!_strnccmp (cmd, todel[t].pat, todel[t].len))
X						break;
X			if ((!inhead) || (!todel[t].pat))
X				if (fputs (cmd, fp) == -1)
X					break;
X			if (inhead)
X				if (n == 1)
X					inhead = 0;
X				else {
X					if ((mode < 1) && (!_strnccmp (cmd, "Newsgroups:", 11))) {
X						ng = getng (ng, cmd);
X						mode = 1;
X					} else if ((mode < 2) && (!_strnccmp (cmd, "Followup-To:", 12))) {
X						ng = getng (ng, cmd);
X						mode = 2;
X					} else if ((!path) && (!_strnccmp (cmd, "Path:", 5)))
X						path = strdup (cmd + 5);
X				}
X		}
X		inhead = ng ? 1 : 0;
X		if (path) {
X			if (ptr = index (path, '\n'))
X				*ptr = '\0';
X			ptr = path;
X			while (is8space (*ptr))
X				++ptr;
X			while (*ptr)
X				if (is8alnum (*ptr) || index (".-+", *ptr))
X					++ptr;
X				else
X					*ptr++ = '!';
X			ptr = path;
X			while (is8space (*ptr))
X				++ptr;
X			fprintf (pp, "From %s\n", ptr);
X		}
X		fseek (fp, 0, 0);
X		while (fgets (cmd, 256, fp)) {
X			if (inhead)
X				if (!strcmp (cmd, "\n")) {
X					fprintf (pp, "Sender: %s\n", sender);
X					fprintf (pp, "Reply-To: %s@%s\n", ng, fhost);
X					inhead = 0;
X				}
X			if (fputs (cmd, pp) == -1)
X				break;
X		}
X		fclose (fp);
X		unlink (fn);
X		pclose (pp);
X	}
X}
X	
__END__OF__THIS__FILE__
if test -f 'MISC/nstat.c' ; then
  echo 'File MISC/nstat.c already exists, overwriting it'
  del 'MISC/nstat.c'
fi
echo Extracting \"'MISC/nstat.c'\"
sed "s/^X//" >'MISC/nstat.c' <<'__END__OF__THIS__FILE__'
X# include	<stdio.h>
X# include	<c8type.h>
X# include	<modes.h>
X# include	<time.h>
X# include	<types.h>
X# include	<stat.h>
X
X# define	GROUP		"Newsgroups: "
X# define	FROM		"From: "
X
Xextern char	*index ();
Xextern char	*malloc ();
Xextern char	*strdup ();
X
Xtypedef enum {
X	False = 0,
X	True
X}	Bool;
X
Xstatic char	*help[] = {
X	"Syntax: nstat [<opts>] [<filename>] [<opts>]\n",
X	"Function: generates a statistic file or evaluates it\n",
X	"Options:\n",
X	"      -e        evaluate the statfile\n",
X	"      -p=<str>  prefix of every groupname\n",
X	"      -o=<file> the output file for the evaluation (def. stdout).\n",
X	"      -d        delete statfile after evaluation\n",
X	"      -h        create header to pipe directly to inews -h\n",
X	"      -t=<file> use <file> as timestamp since last report\n",
X	NULL
X};
X
Xstatic void
Xusage ()
X{
X	register int	t;
X
X	for (t = 0; help[t]; ++t)
X		fputs (help[t], stderr);
X}
X
Xstatic void
Xcollect (fd, file)
Xregister int fd;
Xchar *file;
X{
X	register char	*ptr;
X	char		*group;
X	char		*system;
X	register int	size;
X	register char	*buf;
X	register Bool	inhead;
X	register int	n;
X	char		*tmp;
X
X	if (! (buf = malloc (520)))
X		return;
X	group = NULL;
X	system = NULL;
X	size = 0;
X	inhead = True;
X	while ((n = readln (fd, buf, 512)) > 0) {
X		size += n;
X		if (inhead == True)
X			if (n == 1)
X				inhead = False;
X			else {
X				buf[n - 1] = '\0';
X				if ((! group) && (! _strnccmp (buf, GROUP, sizeof (GROUP) - 1))) {
X					ptr = buf + sizeof (GROUP) - 1;
X					while (is8space (*ptr))
X						++ptr;
X					group = strdup (ptr);
X				} else if ((! system) && (! _strnccmp (buf, FROM, sizeof (FROM) - 1))) {
X					ptr = buf + sizeof (FROM) - 1;
X					while (is8space (*ptr))
X						++ptr;
X					if (tmp = index (ptr, '@')) {
X						++tmp;
X						for (ptr = tmp; *ptr && (! is8space (*ptr)) && (! index ("()>", *ptr)); ++ptr)
X							;
X						*ptr = '\0';
X						system = strdup (tmp);
X					}
X				}
X			}
X	}
X	close (fd);
X	if (! (group && system))
X		return;
X	sprintf (buf, "%s %d %s\n", group, size, system);
X	n = strlen (buf);
X	if ((fd = open (file, S_IWRITE)) == -1)
X		fd = create (file, S_IWRITE, 03);
X	else
X		lseek (fd, 0, 2);
X	if (fd != -1) {
X		write (fd, buf, n);
X		close (fd);
X	}
X}
X
Xtypedef struct _list {
X	char	*name;		/* Group/System name			*/
X	int	count;		/* # of articles			*/
X	int	cper;		/* % * 100 (e.g. 100 = 1% 10000 = 100%)	*/
X	int	size;		/* size of all articles			*/
X	int	sper;		/* as cper				*/
X	int	average;	/* avergae size of article		*/
X	int	xpost;		/* number of crosspostings		*/
X	struct _list
X		*next;
X}	list;
X
Xstatic int
Xadd_list (root, name, size, xpost)
Xlist **root;
Xchar *name;
Xint size;
Xint xpost;
X{
X	register list	*run, *tmp;
X
X	for (run = *root; run; run = run -> next)
X		if (! _strccmp (run -> name, name))
X			break;
X	if (run) {
X		run -> count++;
X		run -> size += size;
X		if (xpost > 1)
X			run -> xpost++;
X	} else if ((! (tmp = (list *) malloc (sizeof (list)))) || (! (tmp -> name = strdup (name)))) {
X		fprintf (stderr, "Can't alloc for new list entry.\n");
X		return (-1);
X	} else {
X		tmp -> count = 1;
X		tmp -> size = size;
X		tmp -> next = *root;
X		tmp -> xpost = (xpost > 1) ? 1 : 0;
X		*root = tmp;
X	}
X	return (0);
X}
X
Xstatic void
Xaver_list (tmp)
Xregister list *tmp;
X{
X	register int	ccount, csize;
X	register list	*start;
X
X	ccount = 0;
X	csize = 0;
X	start = tmp;
X	while (tmp) {
X		tmp -> average = tmp -> size / tmp -> count;
X		csize += tmp -> size;
X		ccount += tmp -> count;
X		tmp = tmp -> next;
X	}
X	for (tmp = start; tmp; tmp = tmp -> next) {
X		tmp -> cper = (tmp -> count * 10000) / ccount;
X		tmp -> sper = (tmp -> size * 10000) / csize;
X	}
X}
X
Xstatic void
Xsort_list (root, tosize)
Xlist **root;
Xregister Bool tosize;
X{
X	register list	*r, *p, *c, *t;
X
X	r = *root;
X	p = NULL;
X	c = r;
X	while (c -> next)
X		if (tosize ? (c -> next -> size > c -> size) : (c -> next -> count > c -> count)) {
X			if (p) {
X				p -> next = c -> next;
X				c -> next = c -> next -> next;
X				p -> next -> next = c;
X				c = p;
X				if (c == r)
X					p = NULL;
X				else
X					for (p = r; p -> next != c; p = p -> next)
X						if (! p -> next) {
X							fprintf (stderr, "*** Error in sorting! ***\n");
X							break;
X						}
X			} else {
X				c = c -> next;
X				r -> next = c -> next;
X				c -> next = r;
X				r = c;
X			}
X		} else {
X			p = c;
X			c = c -> next;
X		}
X	*root = r;
X}
X
Xstatic void
Xdump_list (fp, header, first, tmp)
Xregister FILE *fp;
Xchar *header, *first;
Xregister list *tmp;
X{
X	fprintf (fp, "\n%s:\n", header);
X	fprintf (fp, "%-25.25s  %7.7s (xx.xx%%)  %7.7s (xx.xx%%)  %7.7s  %7.7s\n",
X		first, "Size", "Count", "Siz/Cont", "X-post");
X	for (; tmp; tmp = tmp -> next)
X		fprintf (fp, "%-25.25s  %7d (%2d.%02d%%)  %7d (%2d.%02d%%)  %7d  %7d\n",
X			tmp -> name, tmp -> size,
X			tmp -> sper / 100, tmp -> sper % 100,
X			tmp -> count,
X			tmp -> cper / 100, tmp -> cper % 100,
X			tmp -> average, tmp -> xpost);
X}
X
Xstatic void
Xevaluate (ifile, ofile, prefix, delete, news_header, timestamp)
Xchar *ifile, *ofile;
XBool delete;
Xchar *prefix;
XBool news_header;
Xchar *timestamp;
X{
X	FILE		*fp;
X	list		*groot;
X	list		*sroot;
X	list		*tmp;
X	char		*rifile;
X	register char	*buf;
X	register int	n;
X	int		fd;
X	char		*siz, *sys;
X	char		*xpost;
X	char		*ptr, *gp;
X	int		size;
X	int		len;
X	int		tmpfd;
X	time_t		tim;
X	struct tm	*tt;
X	struct tm	ts;
X	struct stat	st;
X
X	if (! (buf = malloc (520))) {
X		fprintf (stderr, "Can't alloc for input buffer.\n");
X		return;
X	}
X	if (delete) {
X		if (! (rifile = malloc (strlen (ifile) + 40))) {
X			fprintf (stderr, "Can't alloc for temp. filename.\n");
X			return;
X		}
X		strcpy (rifile, ifile);
X		strcat (rifile, "XXXXXX");
X		mktemp (rifile);
X		if (rename (ifile, rifile)) {
X			fprintf (stderr, "Can't rename %s to %s, aborted.\n", ifile, rifile);
X			return;
X		}
X	} else
X		rifile = NULL;
X	groot = NULL;
X	sroot = NULL;
X	if ((fd = open (rifile ? rifile : ifile, S_IREAD)) == -1) {
X		fprintf (stderr, "Can't open %s, aborted.\n", rifile ? rifile : ifile);
X		return;
X	}
X	len = (prefix && *prefix) ? strlen (prefix) : 0;
X	while ((n = readln (fd, buf, 512)) > 0) {
X		buf[n - 1] = '\0';
X		if (! (siz = index (buf, ' ')))
X			continue;
X		*siz++ = '\0';
X		if (! (sys = index (siz, ' ')))
X			continue;
X		*sys++ = '\0';
X		size = atoi (siz);
X		n = 1;
X		xpost = buf;
X		gp = NULL;
X		do {
X			if (ptr = index (xpost, ',')) {
X				*ptr++ = '\0';
X				++n;
X			}
X			if ((! gp) && ((! len) || (! _strnccmp (xpost, prefix, len))))
X				gp = xpost;
X			xpost = ptr;
X		} while (xpost);
X		if (! gp)
X			continue;
X		if ((add_list (& groot, gp, size, n) < 0) || (add_list (& sroot, sys, size, n) < 0))
X			return;
X	}
X	close (fd);
X	if (ofile) {
X		if (! (fp = fopen (ofile, "w"))) {
X			fprintf (stderr, "Can't open %s for writing.\n", ofile);
X			return;
X		}
X	} else
X		fp = stdout;
X	if (news_header) {
X		time (& tim);
X		tt = localtime (& tim);
X		fprintf (fp, "Subject: Newsstatistic (%02d/%02d/%02d)\n\n",
X			tt -> tm_year % 100, tt -> tm_mon + 1, tt -> tm_mday);
X	}
X	if (timestamp) {
X		if (stat (timestamp, & st) == -1)
X			fprintf (fp, "\nFirst evaluation\n");
X		else if (tt = localtime (& st.st_mtime)) {
X			ts = *tt;
X			time (& tim);
X			tt = localtime (& tim);
X			fprintf (fp, "Last evaluation: %02d/%02d/%02d\n",
X				ts.tm_year % 100, ts.tm_mon + 1, ts.tm_mday);
X			tim -= st.st_mtime;
X			tim = tim / (24 * 60 * 60);
X			fprintf (fp, "Data collected for %d day%s.\n",
X				tim, tim != 1 ? "s" : "");
X		}
X		if ((tmpfd = creat (timestamp, S_IWRITE)) != -1)
X			close (tmpfd);
X	}
X	aver_list (groot);
X	aver_list (sroot);
X	sort_list (& groot, True);
X	dump_list (fp, "Group statistic (sorted by size)", "Groupname", groot);
X	sort_list (& groot, False);
X	dump_list (fp, "Group statistic (sorted by # of Articles)", "Groupname", groot);
X	sort_list (& sroot, True);
X	dump_list (fp, "System statistic (sorted by size)", "Systemname", sroot);
X	sort_list (& sroot, False);
X	dump_list (fp, "System statistic (sorted by # of Articles)", "Systemname", sroot);
X	if (ofile)
X		fclose (fp);
X	if (delete)
X		unlink (rifile);
X}
X
Xint
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X	register int	t;
X	register char	*ptr;
X	char		*file;
X	char		*ofile;
X	char		*prefix;
X	char		*timestamp;
X	Bool		eval;
X	Bool		delete;
X	Bool		news_header;
X
X	file = "NewsStat";
X	ofile = NULL;
X	prefix = NULL;
X	timestamp = NULL;
X	eval = False;
X	delete = False;
X	news_header = False;
X	for (t = 1; t < argc; ++t)
X		if (argv[t][0] == '-') {
X			ptr = argv[t] + 1;
X			while (*ptr) {
X				switch (*ptr) {
X					case 'p':
X						ptr += *(ptr + 1) == '=' ? 2 : 1;
X						prefix = ptr;
X						while (*ptr)
X							++ptr;
X						break;
X					case 'o':
X						ptr += *(ptr + 1) == '=' ? 2 : 1;
X						ofile = ptr;
X						while (*ptr)
X							++ptr;
X						break;
X					case 't':
X						ptr += *(ptr + 1) == '=' ? 2 : 1;
X						timestamp = ptr;
X						while (*ptr)
X							++ptr;
X						break;
X					case 'e':
X						eval = True;
X						break;
X					case 'd':
X						delete = True;
X						break;
X					case 'h':
X						news_header = True;
X						break;
X					case '?':
X					default:
X						usage ();
X						exit (*ptr == '?' ? 0 :
X							_errmsg (1, "Unknown option '%c'.\n", *ptr));
X				}
X				if (*ptr)
X					++ptr;
X			}
X		} else
X			file = argv[t];
X	setuid (getmuid ());
X	if (eval == False)
X		collect (0, file);
X	else
X		evaluate (file, ofile, prefix, delete, news_header, timestamp);
X}
__END__OF__THIS__FILE__
if test -f 'MISC/rot13.c' ; then
  echo 'File MISC/rot13.c already exists, overwriting it'
  del 'MISC/rot13.c'
fi
echo Extracting \"'MISC/rot13.c'\"
sed "s/^X//" >'MISC/rot13.c' <<'__END__OF__THIS__FILE__'
X# include	<modes.h>
X# include	<c8type.h>
X
Xextern char	*malloc ();
X
Xchar8		table[256];
X
Xvoid
Xrot (fdi, fdo)
Xint fdi, fdo;
X{
X	static char8	*store = (char *) 0;
X	register char8	*ptr;
X	register int	n, t;
X
X	if (! store)
X		if (! (store = (char8 *) malloc (4096 + 4)))
X			return;
X	while ((n = read (fdi, store, 4096)) > 0) {
X		t = n;
X		ptr = store;
X		while (t-- > 0) {
X			*ptr = table[*ptr];
X			++ptr;
X		}
X		if (fdo != -1) {
X			if (write (fdo, store, n) != n)
X				break;
X		} else {
X			if (lseek (fdi, -n, 1) == -1)
X				break;
X			if (write (fdi, store, n) != n)
X				break;
X		}
X	}
X}
X			
Xint
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X	register int	t;
X
X	for (t = 0; t < 256; ++t)
X		if ((t >= 'a' && t <= 'm') || (t >= 'A' && t <= 'M'))
X			table[t] = t + 13;
X		else if ((t >= 'n' && t <= 'z') || (t >= 'N' && t <= 'Z'))
X			table[t] = t - 13;
X		else
X			table[t] = t;
X	if (argc == 1)
X		rot (0, 1);
X	else
X		for (t = 1; t < argc; ++t) {
X			int	fd = open (argv[t], S_IREAD | S_IWRITE);
X
X			if (fd != -1) {
X				rot (fd, -1);
X				close (fd);
X			}
X		}
X}
X			
__END__OF__THIS__FILE__
if test -f 'MISC/unmap.c' ; then
  echo 'File MISC/unmap.c already exists, overwriting it'
  del 'MISC/unmap.c'
fi
echo Extracting \"'MISC/unmap.c'\"
sed "s/^X//" >'MISC/unmap.c' <<'__END__OF__THIS__FILE__'
X/*
X * $Log:	unmap.c_v $
X * Revision 1.1  90/08/31  15:28:37  cv
X * Initial revision
X * 
X */
X# ifndef	LINT
Xstatic char rcsid[] = "$Id: unmap.c_v 1.1 90/08/31 15:28:37 cv Exp $";
Xstatic char copyright[] = "Copyright (C) 1989, 1990 by Ulrich Dessauer, Germering, Germany.\n";
X# endif		LINT
X# include	<ctype.h>
X# include	<modes.h>
X
Xextern char	*strdup ();
X
Xchar *
Xskip (s)
Xregister char *s;
X{
X	while (*s && (!isspace (*s)))
X		++s;
X	if (*s)
X		*s++ = '\0';
X	while (isspace (*s))
X		++s;
X	return (s);
X}
X
Xchar *
Xstrip (s)
Xregister char *s;
X{
X	register char	*p;
X	register char	c;
X
X	if ((*s == '\'') || (*s == '"')) {
X		c = *s++;
X		p = s;
X		while (*p && (*p != c))
X			++p;
X		*p = '\0';
X	}
X	return (s);
X}
X
Xint
Xmain (argc, argv)
Xint argc;
Xchar *argv[];
X{
X	char		buffer[256];
X	int		n;
X	int		fd;
X	char		*eof;
X	char		*fn;
X	int		len;
X	register char	*ptr, *sav;
X
X	setuid (getmuid ());
X	eof = 0;
X	fn = 0;
X	fd = -1;
X	if ((argc != 1) && (argc != 2))
X		exit (_errmsg (1, "Usage: %s [<directory>].\n", argv[0]));
X	if (argc == 2)
X		if (chdir (argv[1]) < 0)
X			exit (_errmsg (1, "Can't chdir() to %s.\n", argv[1]));
X	while ((n = readln (0, buffer, 256)) > 0) {
X		buffer[n - 1] = '\0';
X		if (!_strnccmp (buffer, "cat ", 4)) {
X			sav = skip (buffer);
X			do {
X				ptr = skip (sav);
X				if ((!strcmp (sav, "<<")) && (!eof)) {
X					sav = ptr;
X					ptr = skip (sav);
X					sav = strip (sav);
X					eof = strdup (sav);
X				} else if ((!strcmp (sav, ">")) && (!fn)) {
X					sav = ptr;
X					ptr = skip (sav);
X					sav = strip (sav);
X					fn = strdup (sav);
X				}
X				sav = ptr;
X			} while (*sav);
X			if (eof && fn)
X				break;
X		}
X	}
X	if ((n > 0) && eof && fn) {
X		if ((fd = creat (fn, S_IWRITE)) != -1) {
X			chmod (fn, 013);
X			len = strlen (eof);
X			while ((n = readln (0, buffer, 256)) > 0) {
X				buffer[n - 1] = '\0';
X				if (n >= len && (!strcmp (eof, buffer)))
X					break;
X				else {
X					write (fd, buffer, n - 1);
X					write (fd, "\n", 1);
X				}
X			}
X			close (fd);
X		}
X	}
X	if (n > 0)
X		while (readln (0, buffer, 256) > 0)
X			;
X	close (0);
X}
__END__OF__THIS__FILE__
if test -f 'RNEWS/Makefile' ; then
  echo 'File RNEWS/Makefile already exists, overwriting it'
  del 'RNEWS/Makefile'
fi
echo Extracting \"'RNEWS/Makefile'\"
sed "s/^X//" >'RNEWS/Makefile' <<'__END__OF__THIS__FILE__'
X# $Id: Makefile_v 1.1 90/08/31 15:37:55 ud Exp $
X# $Log:	Makefile_v $
X# Revision 1.1  90/08/31  15:37:55  ud
X# Initial revision
X# 
X#
XCC=	cc
XG=	-g
XCFLAGS=	-qt=/dd/TMP $G -v=..
XLIBS=	-l=/dd/LIB/os9lib.l
XLFLAGS=	-qm=4 $(LIBS) $G
XODIR=	/h0/ETC/CMDS
X
XRNEWSC=	rnews.c send.c compr.c compr7.c logit.c mail.c
XRNEWSR=	rnews.r send.r compr.r compr7.r logit.r mail.r
X
X$(ODIR)/rnews:	$(RNEWSR)
X	$(CC) $(LFLAGS) $(RNEWSR) -f=$(ODIR)/rnews
X
Xtags:	$(RNEWSC)
X	ctags $?
__END__OF__THIS__FILE__
if test -f 'RNEWS/compr.c' ; then
  echo 'File RNEWS/compr.c already exists, overwriting it'
  del 'RNEWS/compr.c'
fi
echo Extracting \"'RNEWS/compr.c'\"
sed "s/^X//" >'RNEWS/compr.c' <<'__END__OF__THIS__FILE__'
X/*
X * $Log:	compr.c_v $
X * Revision 1.1  90/08/31  15:37:57  ud
X * Initial revision
X * 
X */
X# ifndef	LINT
Xstatic char rcsid[] = "$Id: compr.c_v 1.1 90/08/31 15:37:57 ud Exp $";
X# endif		LINT
X# include <stdio.h>
X# include <modes.h>
X# include <ctype.h>
X# include "rnews.h"
X
Xextern void	logit ();
Xextern void	start_rnews ();
Xextern long	lseek ();
Xextern char	*findmod ();
Xextern char	*index ();
Xextern char	*mktemp ();
Xextern char	*strcpy ();
X
Xextern int	errno;
X
Xvoid
Xdo_exec (cmd,w,r)
Xchar *cmd;
Xint w,r;
X{
X	extern int	os9forkc ();
X	extern char	**environ;
X	int		o0, o1;
X	char		**arg;
X	int		t, status, pid;
X	
X	o0 = dup (0);
X	o1 = dup (1);
X	(void) close (0);
X	(void) dup (w);
X	(void) close (1);
X	(void) dup (r);
X	t = 0;
X	if (getargs (cmd, &arg) > 0) {
X		logit (4,"Fork: '%s'\n",arg[0]);
X		if ((pid = os9exec (os9forkc,findmod (arg[0],arg[0]),arg,environ,0,0,3)) < 0) {
X			logit (2,"ERROR: Can't fork '%s'\n", arg[0]);
X			error |= FATAL;
X			return;
X		} else
X			while (((t = wait (&status)) != pid) && (t != -1))
X				;
X		logit (status ? 2 : 3,"'%s' returns %d\n",arg[0],status);
X	} else {
X		error |= FATAL;
X		logit (2, "ERROR: Can't alloc memory for getargs\n");
X	}
X	(void) close (0);
X	(void) dup (o0);
X	(void) close (o0);
X	(void) close (1);
X	(void) dup (o1);
X	(void) close (o1);
X	if (status)
X		error |= FATAL;
X}
X
Xvoid	
Xcompr (fd,scratch,cmd)
Xint fd;
Xint scratch;
Xchar *cmd;
X{
X	char		tmp[40 + sizeof (TEMPDIR)];
X	char		*buf;
X	register char	*x;
X	register int	n;
X	unsigned int	siz, temp;
X	int		o;
X	
X	(void) sprintf (tmp,"%s/compr.XXXXXX", TEMPDIR);
X	(void) mktemp (tmp);
X	_unlink (tmp);
X	siz = 20000;
X	while ((siz != 0) && ((buf = malloc (siz + 5)) == (char *) NULL))
X		siz -= 1000;
X	if (!siz) {
X		logit (2,"ERROR: Can't alloc memory\n");
X		error |= SIMPLE;
X		return;
X	}
X	if ((o = create (tmp,S_IREAD | S_IWRITE,03, 0)) < 0) {
X		logit (2,"ERROR: Can't create tmpfile '%s'\n",tmp);
X		error |= SIMPLE;
X		free (buf);
X		return;
X	}
X	errno = 0;
X	while ((n = read (fd,buf,siz)) > 0) {
X		logit (6,"Read %d bytes\n",n);
X		x = buf;
X		temp = (unsigned int) n;
X		while (n-- > 0) {
X			if (*x && (index ("\l\r",*x) != (char *) NULL))
X				*x = *x == '\l' ? '\r' : '\l';
X			++x;
X		}
X		n = write (o,buf,temp);
X		logit (6,"Wrote %d bytes\n",n);
X		if (n < 0) {
X			logit (2,"ERROR: Can't write tmpfile '%s'\n", tmp);
X			close (o);
X			_unlink (tmp);
X			error |= SIMPLE;
X			free (buf);
X			return;
X		}
X	}
X	(void) lseek (o,0,0);
X	o = uncompress_it (o,tmp,cmd);
X	if (error) {
X		if (o != -1)
X			(void) close (o);
X		_unlink (tmp);
X		free (buf);
X		return;
X	} else {
X		close (o);
X		if ((o = open (tmp, S_IREAD)) < 0) {
X			_unlink (tmp);
X			free (buf);
X			error |= SIMPLE;
X			return;
X		}
X	}
X	start_rnews (o,scratch);
X	(void) close (o);
X	_unlink (tmp);
X	free (buf);
X}
X
Xint
Xuncompress_it (o,ofile,cmd)
Xint o;
Xchar *ofile;
Xchar *cmd;
X{
X	char		tmp[40 + sizeof (TEMPDIR)];
X	char		*ucpr;
X	char		*buf;
X	unsigned int	siz, temp;
X	register int	n;
X	register char	*x;
X	int		w;
X	
X	(void) sprintf (tmp, "%s/uncpr.XXXXXX", TEMPDIR);
X	(void) mktemp (tmp);
X	_unlink (tmp);
X	if (((ucpr = malloc ((unsigned int) (strlen (cmd) + 2))) == (char *) NULL) || ((w = create (tmp,S_IREAD | S_IWRITE,03, 0)) < 0)) {
X		error |= FATAL;
X		return (-1);
X	} else
X		(void) strcpy (ucpr,cmd);
X	do_exec (ucpr,o,w);
X	(void) close (o);
X	(void) unlink (ofile);
X	if (error) {
X		(void) close (w);
X		_unlink (tmp);
X		free (ucpr);
X		return (-1);
X	}
X	if ((o = create (ofile,S_IREAD | S_IWRITE,03)) < 0) {
X		logit (2,"ERROR: Can't create tmpfile '%s'\n",ofile);
X		(void) close (w);
X		_unlink (tmp);
X		free (ucpr);
X		error |= FATAL;
X		return (-1);
X	}
X	(void) lseek (w,0,0);
X	siz = 20000;
X	while (siz && ((buf = malloc (siz + 5)) == (char *) NULL))
X		siz -= 1000;
X	if (!siz) {
X		(void) close (w);
X		_unlink (tmp);
X		error |= FATAL;
X		free (ucpr);
X		return (o);
X	}
X	while ((n = read (w,buf,siz)) > 0) {
X		logit (6,"Read %d bytes\n",n);
X		temp = (unsigned int) n;
X		x = buf;
X		while (n-- > 0) {
X			if (*x && (index ("\l\r",*x) != (char *) NULL))
X				*x = *x == '\l' ? '\r' : '\l';
X			++x;
X		}			
X		n = write (o,buf,temp);
X		logit (6,"Wrote %d bytes\n",n);
X		if (n < 0) {
X			logit (2,"ERROR: Can't write data to '%s'\n",ofile);
X			close (o);
X			o = -1;
X			error |= FATAL;
X			break;
X		}
X	}
X	(void) close (w);
X	free (buf);
X	free (ucpr);
X	_unlink (tmp);
X	return (o);
X}
__END__OF__THIS__FILE__
exit 0
: end of shell archive

-- 
Frank Kaefer # fkk@stasys.sta.sub.org # Starnberg, Germany
Xref: sparky de.comp.sources.os9:11 comp.os.os9:1553