Subject: Perl inews & anne.jones

From: [email-masked] (Kenneth Herron)
Date: 9 Jan 92 04:17:39 GMT

Here they are, inews and anne.jones scripts for C news, compatible with
the shell versions, written in perl.  This combination is up to 4x as
fast as the shell versions, while performing more comprehensive checks
on the submitted article.  Please see the file Readme for installation
instructions.

The rewritten C news, due out this spring, will probably make this code
obsolete, but it's nice to have in the meantime.

I welcome all comments about this software, particularly portability
notes.

--Kenneth Herron
========================Cut here=============================
#! /bin/sh
: This is a shell archive, meaning:
: 1. Remove everything above the '#! /bin/sh' line.
: 2. Save the resulting text in a file.
: 3. Execute the file with /bin/sh '(not csh)' to create the files:
:	'Readme'
:	'inews.pl'
:	'anne.jones.pl'
:	'config.EXAMPLE'
: This archive created: 'Wed Jan  8 22:58:00 1992
'
export PATH; PATH=/bin:$PATH
echo shar: extracting "'Readme'" '(4596 characters)'
if test -f 'Readme'
then
	echo shar: will not over-write existing file "'Readme'"
else
sed 's/^X//'  >'Readme' <<'SHAR_EOF'
XInews.pl and anne.jones.pl, by Kenneth Herron
XBoth programs are placed in the public domain.  No warranty is expressed
Xor implied.
X
XThis package is a perl replacement for the C news inews and anne.jones
Xscripts.  This version offers the following improvements over the shell
Xinews:
X
X1)	Header formatting -- All headers except for Path: and Message-ID:
X	are formatted (via continuation lines) so that no line is more than 
X	80 characters.  Extraneous white space is removed from Newsgroups:, 
X	Followup-To:, and Distribution:.  Blank headers are tossed.  All
X	tabs are converted to spaces.  Inews generates an X-Bytes: header in 
X	addition to Lines:, giving the size of the article body.
X
X2)	No temporary files -- Both headers and body are held in memory.
X
X3)	No backgrounding -- This inews never backgrounds itself; if it can't 
X	pipe an article to relaynews in a reasonable amount of time, it pipes 
X	it to newsspool.  The -W command line option forces it to use 
X	relaynews.  This is a big win for sites that let NNTP clients post 
X	articles; the article is checked more thoroughly and usually posted 
X	before inews returns, so if relaynews rejects it the remote user 
X	won't be left in the dark.
X
X4)	Improved error messages (IMHO).
X
XAnd, of course,
X
X5)	Much faster.  "inews -N" is about 4x as fast (3-4 seconds vs.  14-16 
X	for the stock inews on our system).  On our system, inews.pl reads,
X	verifies, and posts the article in a second or so longer than inews
X	takes to read the article and background itself.
X
XThere are a few gotcha's with it:
X
X1)	Inews.pl takes pains not to start relaynews if one is already running,
X	but a race condition may let it happen anyway.  If so, the poster will 
X	have to wait until another relaynews finishes.  This should be a very 
X	rare occurrance.  I am open for suggestions on how to improve this.
X
X2)	I use getpwuid() to determine the poster's ID and real name; this 
X	simply returns the first user with the same UID.  Sites which treat
X	the GCOS field differently from us will have to modify anne.jones.pl
X	to properly get the poster's real name; comments in anne.jones.pl
X	cover this.
X
X3)	Inews.pl still runs spacefor up to three times; anne.jones.pl runs 
X	newshostname, getabsdate, and getdate.  Some of this could be removed 
X	but not portably; for example sites using the part-binary spacefor
X	can run dostatfs directly.
X
X4)	Groups marked =some.other.group in the active file are treated the
X	same as inews treats them, i.e. they are allowed in the Newsgroups:
X	line.  The article can eventually be rejected by relaynews if the
X	actual group is marked m, n, or x.  Handling these groups properly
X	would slow it down a bit (but may be worth doing if you have a lot
X	of these groups in your active file).
X
XAs far as I know, anne.jones.pl is completely compatible with anne.jones,
Xand can replace anne.jones even if you don't use inews.pl.  Inews.pl can 
Xalso use the original anne.jones, so long as you set $ENV{'trversion'} 
Xproperly.  I haven't really tested one without the other, however.
X
XTo install:
X
X1)	Upgrade to perl 4.0, patchlevel 19 if needed :-)  Seriously,
X	the scripts were originally developed under patchlevel 10, and
X	may not work under earlier versions.
X
X2)	Verify that you have ctime.pl in your perl library directory;
X	you should, as it's included with the perl distribution.
X
X3)	Copy your original inews and anne.jones to a safe place, just
X	in case.
X
X4)	Create a config.pl file based on your site's config file and using 
X	the supplied example as a guide.  DO NOT USE THE EXAMPLE AS-IS AND 
X	DO NOT CHANGE THE VALUES FROM THE EQUIVALENTS IN CONFIG--you will 
X	trip security code in relaynews and it will refuse to run.  Place 
X	this config.pl file in the same directory as your config file 
X	(/usr/lib/news/bin or wherever).
X
X5)	Edit the #! line in each script to point to your perl.  Look over 
X	the code and verify that anne.jones.pl will extract the user's full 
X	name from the GCOS field properly.  Modify anything that doesn't
X	suit you; notable targets are the maximum article size and the
X	wait period (six seconds) before running newsspool.
X
X6)	Replace inews with the perl version.  Here, all of the "public" 
X	copies of inews are symlinks to .../inject/inews, so I just changed 
X	them to point to the perl version in the same directory.
X
X7)	Place anne.jones.pl in the same directory as anne.jones, .../inject.
X	Inews.pl wants to run anne.jones.pl, so you don't have to replace
X	the original.
X
X8)	Test to your satisfaction...
X
XPlease send questions and comments to me, [email-masked].
X
X-- Kenneth Herron, 8-Jan-1992
SHAR_EOF
if test 4596 -ne "`wc -c < 'Readme'`"
then
	echo shar: error transmitting "'Readme'" '(should have been 4596 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'inews.pl'" '(9395 characters)'
if test -f 'inews.pl'
then
	echo shar: will not over-write existing file "'inews.pl'"
else
sed 's/^X//'  >'inews.pl' <<'SHAR_EOF'
X#! /usr/local/perl
X#
X# inews.pl -- a perl inews replacement for C news, by Kenneth Herron
X# version 1.0, released 8-Jan-1992.
X# Placed in the public domain.  No warranty is expressed or implied.
X#
Xrequire '/var/lib/cnews/config.pl';
X# anne.jones wants to know what kind of tr you have.  Rather than run it
X# in every inews run just to find out, do this:
X#
X#	echo B | tr A-Z a-z
X#
X# If it prints 'b' you have v7, otherwise you have v6.  According to
X# a comment in inews, SysV will typically be v6.  Our BSD system is v7.
X# The perl anne.jones doesn't care either way.
X$ENV{'PATH'} = "$NEWSCTL/bin:$NEWSBIN/inject:$NEWSBIN/relay:$NEWSBIN:$NEWSPATH";
X$ENV{'trversion'} = 'v7';
X$ENV{'PASSEDFROM'} = '';	# needed by anne.jones (?)
X$TOOBIG = 62 * 1024;		# largest article allowed, *sans headers*
X$relayopts = '-i';
X
Xsub circular_file {
X	if (open(STDOUT, ">>$ENV{'HOME'}/dead.article")) {
X		while (($h,$v) = each %hdr) {
X			print $h . ': ' . $v . "\n";
X		}
X		print "\n";
X		print @body;
X		warn "$0: article placed in $ENV{'HOME'}/dead.article\n";
X	}
X	else {
X		warn "$0: cannot write to $ENV{'HOME'}/dead.article\n";
X		warn "$0: cannot save article\n";
X	}
X	exit(1);
X}
X
Xsub format_hdr {
X	local ($_) = $_[0] . ': ' . $hdr{$_[0]} . "\n" ;
X	tr/\t/ /;
X	if (/^Path: |^Message-ID: / || (80 > length($_))) {
X		$_;
X	}
X	else {
X		local(@h) = grep(!/^$/,split(/(.{1,75}$)|(.{10,75}[, ]+)/));
X		join("\n    ", @h) . "\n";
X	}
X}
X
Xsub write_article {
X	local($DEST) = $_[0];  # file handle to write to
X	for ($i = $[; $i <= $#hord; $i++) {
X		if (!print $DEST do format_hdr($hord[$i])) {
X			warn "$0: error while writing article.\n";
X			do circular_file();
X		}
X	}
X	if (!(print $DEST "\n", @body)) {
X		warn "$0: error while writing article.\n";
X		do circular_file();
X	}
X	close $DEST;
X	if ($?) {
X		warn "An error may have occurred while writing the\n";
X		warn "article.  A copy is being saved just in case.\n";
X		do circular_file();
X	}
X	exit(0);
X}
X
X# parse the command line.  None of the getopt packages we have will
X# do things properly, so we have to do it by hand...
X
Xwhile ($#ARGV >= 0) {
X	$arg = $ARGV[0];
X	shift;
X	if ($arg =~ /^-/) {
X		# it's a switch
X		if ($arg =~ /^-debug$/) {
X			$debug = $ARGV[0]; shift; next;
X		}
X		@sw = split(//,$arg);
X		shift(@sw);	# get rid of the leading '-'
X		for $sw (@sw) {
X			if ($sw eq 't') {
X				$hdr{'Subject'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'n') {
X				$hdr{'Newsgroups'} = $ARGV[0]; 
X				shift @ARGV;next;
X			}
X			if ($sw eq 'e') {
X				$hdr{'Expires'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'F') {
X				$hdr{'References'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'r') {
X				$hdr{'Reply-To:'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'f') {
X				$hdr{'From'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'd') {
X				$hdr{'Distribution'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'c') {
X				$hdr{'Control'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'a') {
X				$hdr{'Approved'} = $ARGV[0]; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'o') {
X				$ENV{'ORGANIZATION'} = $ARGV[0];
X				shift @ARGV; next;
X			}
X			if ($sw eq 'x') { 
X				$exclusion = "-x $ARGV[0]"; 
X				shift @ARGV; next;
X			}
X			if ($sw eq 'h') { $hashdrs = 1; next; }
X			if ($sw eq 'W') { $waitforit = 1; next; }
X			if ($sw eq 'V') { $relayopts = ''; next; }
X			if ($sw eq 'N') { $nopost = 1; next; }
X			if ($sw eq 'A') { $autopost = 1; next; }
X			if ($sw eq 'D') { next; }
X			if ($sw eq 'M') { next; }
X			if ($sw eq 'C') {
X				die "$0: -C is not supported by this inews\n";
X			}
X			warn "$0: Unrecognized option: $sw\n";
X		}
X	}
X	else {
X		# it's a file name 
X		if (!defined($article)) {
X			$article = $arg;
X			shift @ARGV;
X		}
X		else {
X			warn "$0: more than one article specified\n";
X		}
X	}
X}
X
Xif ($article) {
X	open(ART, $article) || die "$0: can't open $article\n";
X} else {
X	open(ART, "<&STDIN") || die "$0: can't read article\n";
X}
X
X# read in the article.  Headers are placed in %hdr along with any from
X# the command line.  The article is saved line-by-line in @body.  We perform
X# a few conversions on the headers:
X#   -	Continued headers are tacked onto the existing part, with the
X#	separating \n and whitespace removed.
X#   -	Tabs in headers are converted to spaces (1 tab -> 1 space)
X#   -   Misc. control characters are stripped from both header & body
X#
X# The tr commands will need modification if you allow posting of articles
X# containing escape characters (eg JIS-encoded Kanji).
X 
X$line = 0;
Xwhile (<ART>) {
X	if (/^\S+:/) {
X		# new header
X		($h,$v) = split(/:\s*/, $_, 2);
X		# correct header's case
X		$h =~ s/([^-]+(-|$))/\L\u$1/g;
X		$h = 'Message-ID' if ($h eq 'Message-Id');
X		chop($v);		# remove \n
X		$hdr{$lasthdr = $h} = $v;
X	}
X	elsif (/^[\t ]+\S/ && $line) {
X		# continued header -- note this requires text on the line.
X		# A line containing only white space is considered the end
X		# of the headers.
X		chop;			# remove \n
X		$hdr{$lasthdr} =~ s/\s+$//;
X		s/^[\t ]+/ /;
X		$hdr{$lasthdr} .= $_;
X	}
X	else {
X		# anything else is considered the start of the article
X		last;
X	}
X	$line++;
X}
X
X$_ = <ART> until (eof(ART) || ! /^$/);
X
X$size = 0;
Xdo {
X	tr/\001-\007\013\015-\037//d;
X	$size += length;
X	push(@body, $_);
X} while (<ART>);
Xclose(ART);
X
X# .signature
Xif (open(ART, "${ENV{'HOME'}}/.signature")) {
X	$h = 0;
X	push(@body, "-- \n");
X	$size += 4;
X	while (<ART>) {
X		tr/\001-\007\013\015-\037//d;
X		$size += length;
X		push(@body, $_);
X		last if (++$h >= 4);
X	}
X}
Xclose(ART);
X
Xif ($size >= $TOOBIG) {
X	warn <<EOF ;
X$0: Your article is $size characters in size, which is too large to 
Xpost in one piece.  Please edit your posting to be less than $TOOBIG
Xcharacters, or split it into pieces if necessary.
XEOF
X	do circular_file();
X}
X
X# remove some headers we know we'll be replacing
Xdelete $hdr{'Lines'};
Xdelete $hdr{'X-Bytes'};
X
X# run the headers through anne.jones -- since anne.jones buffers headers
X# there is no risk of deadlock.
Xpipe(AJR,AJW);
Xpipe(INR,INW);
Xif (0 == open(AJ, "-|")) {
X	# child process
X	close(INW); close(AJR);
X	open(STDOUT, ">&AJW");
X	open(STDIN, "<&INR");
X	exec 'anne.jones.pl';
X}
Xelse {
X	# parent
X	close(INR); close(AJW);
X	foreach $h (keys %hdr) {
X		print INW $h, ': ', $hdr{$h}, "\n";
X	}
X	undef %hdr;
X	close(INW);
X	while (<AJR>) {
X		chop;
X		split(/: /,$_,2);
X		$hdr{$_[0]} = $_[1];
X		push(@hord, $_[0]);
X	}
X	close(AJR);
X	do circular_file() if ($?);
X}
X
X# Lines:  & Bytes: headers -- no need to run these through anne.jones
X$hdr{'X-Bytes'} = $size;
Xpush(@hord, 'X-Bytes');
X$hdr{'Lines'} = (@body + 1);
Xpush(@hord, 'Lines');
X
X# validate list of newsgroups against active file & see if any are moderated
X
Xif (defined($hdr{'Control'})) {
X	@ng = ('control');
X}
Xelse {
X	@ng = split(/,/, $hdr{'Newsgroups'});
X}
X$ng = "^" . join('\s|^', @ng) . '\s';
Xopen(ART, "$NEWSCTL/active") || die "$0: can't read active file\n";
Xwhile (<ART>) {
X	if (/$ng/o) {
X		split;
X		$ng{$_[0]} = $_[3];
X		last if (++$ngct >= $#ng);
X	}
X}
Xclose(ART);
Xundef @ng;
X
Xforeach $ng (keys %ng) {
X	if ($ng{$ng} =~ /^[nx]/) {
X		# group is no-local-posting or disabled
X		warn "$0: The group $ng may not be posted to.  Please\n";
X		warn "remove it from your group list and try again.\n";
X		do circular_file();
X	}
X	elsif (($ng{$ng} =~ /^m/) && (!defined($hdr{'Approved'}))) {
X		open(ART, "$NEWSCTL/mailpaths") || 
X			die "$0: mailpaths can't be read\n";
X		while (<ART>) {
X			if (/^$ng\b|^backbone\b|^all\b|^internet\b/) {
X				($d, $adr) = split;
X				if (-1 != ($sub = index($adr, '%s'))) {
X					$ng =~ tr/./-/;
X					substr($adr, $sub, 2) = $ng;
X				}
X				warn "$0: mailing your article to $adr\n";
X				open(OUT, "| mail $adr") || 
X					die "$0: can't start the mailer\n";
X				do write_article(OUT);
X			}
X		}
X		# no entry in mailpaths
X		warn "$0: No entry in mailpaths covering $ng.\n";
X		warn "unable to mail article to the moderator.\n";
X		do circular_file();
X	}
X	else {
X		# if it passes either of the above two tests, the article is
X		# okay for posting so far; we still have to check all the groups
X		$grpok++;
X	}
X}
X
Xif (!$grpok) {
X	warn "$0: No groups in $hdr{'Newsgroups'} allow posting\n";
X	do circular_file();
X}
X
Xdo write_article(STDOUT) if ($nopost);
X
X# free space check
X
Xif (!$autopost) {
X	if (0 >= (0 +`spacefor 1 articles`)) {
X		warn "$0: not enough free space on $NEWSARTS\n";
X		do circular_file();
X	}
X}
Xelse {
X	$i = 0;
X	while ((`spacefor 1 articles` <= 0) && (`spacefor 1 control` <= 0)) {
X		last if (++$i >= 5);
X		sleep 30;
X	}
X	if ($i) {
X		if (open(OUT, "|mail $NEWSMASTER")) {
X			print OUT <<EOF;
X
X	$0: Space low on $NEWSARTS and/or $NEWSCTL.
X
X		Sincerely,
X		$0
XEOF
X			close(OUT);
X		}
X		# we'll try to post the article anyway
X	}
X}
X
X# finally it can be posted
X
X# See if there's another relaynews running.  If there is, we may want 
X# to run newsspool instead.
X
X# we build these ahead of time to avoid any delay after checking the lock
X@rcmd = ('relaynews', '-s');
Xpush(@rcmd, $relayopts) if ($relayopts);
Xpush(@rcmd, ('-d', $debug)) if ($debug);
X@ncmd = ("$NEWSBIN/input/newsspool", '-i');
X
Xif (!$waitforit) {
X	$i = 6;
X	sleep(1) while (-e "$NEWSCTL/LOCK" && $i--);
X}
Xif ($pid = open(OUT, '|-')) {
X	if (defined $pid) {
X		do write_article(OUT);
X	}
X	else {
X		warn "$0: cannot inject news article\n";
X		do circular_file();
X	}
X		
X}
Xelse {
X	# child process
X	if ($waitforit || ! -e _) {
X		exec @rcmd;
X	}
X	else {
X		select(STDERR);
X		$| = 1;
X		print "Your article is being stored for later processing.\n";
X		exec @ncmd;
X	}
X}
SHAR_EOF
if test 9395 -ne "`wc -c < 'inews.pl'`"
then
	echo shar: error transmitting "'inews.pl'" '(should have been 9395 characters)'
fi
chmod +x 'inews.pl'
fi # end of overwriting check
echo shar: extracting "'anne.jones.pl'" '(5225 characters)'
if test -f 'anne.jones.pl'
then
	echo shar: will not over-write existing file "'anne.jones.pl'"
else
sed 's/^X//'  >'anne.jones.pl' <<'SHAR_EOF'
X#! /usr/local/perl
X#
X# anne.jones.pl -- a perl anne.jones/defhdrs.awk replacement
X# for C news, by Kenneth Herron
X# Version 1.1, released 8-Jan-1992.
X# Placed in the public domain.  No warranty is expressed or implied.
X#
X# This script, like the original anne.jones, expects a proper C news
X# installation to be available.  In addition, you must set up a perl
X# version of the config script (call it config.pl) in the same directory
X# as config.
X
Xrequire '/var/lib/cnews/config.pl';
Xrequire 'ctime.pl';
X$ENV{'PATH'} = "$NEWSCTL/bin:$NEWSBIN/inject:$NEWSBIN:$NEWSPATH";
Xumask $NEWSUMASK;
X
Xsub do_date { 
X	local(@_) = split(/ +/,&ctime($_[0]), 6); 
X	chop($_[$#_]);
X	$_[3] =~ s/^(\d:)/0$1/;
X	@_;
X}
X
X$subjname = 'Subject';
X$ctlname = 'Control';
X$ngname = 'Newsgroups';
X$msgidname = 'Message-ID';
X$pathname = 'Path';
X$datename = 'Date';
X$fromname = 'From';
X$orgname = 'Organization';
X$distrname = 'Distribution';
X$sendername = 'Sender';
X$expiresname = 'Expires';
X$followname = 'Followup-To';
X
X# read headers on stdin; placing them in an associative array.  This
X# is stolen from inews.pl.
X
Xwhile (<>) {
X	tr/\001-\007\013\015-\037//d;	# remove inviso-chars
X	split(/: /,$_,2);
X	next unless ($_[1]);		# lose blank headers
X	chop($hdr{$_[0]} = $_[1]);	
X}
X
Xif (open(IN, "$NEWSCTL/mailname")) {
X	chop($mailname = <IN>);
X	close(IN);
X}
Xelse {
X	chop($mailname = `newshostname`);
X}
X$mailname .= '.uucp' if (index($mailname, '.') < $[);
X
X# get the user's login name
X# This is not as robust as the original anne.jones; if LOGNAME isn't defined
X# we just pick the first matching UID (note we're using our EUID).
X# note to porters:  Our gecos field looks like this:
X#	...:Kenneth Herron,POT1105,72975,8736045:...
X#           name           office  phone home-phone
X
X($user, $name) = (getpwuid($>))[0,6];
X$name =~ s/,.*//;
X$user = $ENV{'LOGNAME'} if ($ENV{'LOGNAME'});
Xif (open(IN, "$ENV{'HOME'}/.name")) {
X	chop($name = <IN>);
X	close(IN);
X}
X$name = '(' . $name . ')' unless ($name =~ /^\(.*\)$/);
X
X# Validate Date: & Expires: headers (generate Date: if none exists).
X
X$oldtz = $ENV{'TZ'};
X$ENV{'TZ'} = 'GMT';
X($dow,$mn,$dy,$tm,$tz,$yr) = &do_date($hdr{$datename}?
X	`getabsdate "$hdr{$datename}"` :time);
X$hdr{$datename} = $dow . ', ' . join(' ', $dy,$mn,$yr,$tm,$tz);
X
Xif ($hdr{$expiresname}) {
X	# getdate is more permissive than getabsdate, but slower
X	# and more likely to make a wrong guess in marginal cases.  Henry
X	# & Geoff threaten to change it to getreldate in the future
X	if ($time = `getdate "$hdr{$expiresname}"`) {
X		$ENV{'TZ'} = 'GMT';
X		($dow,$mn,$dy,$tm,$tz,$yr) = &do_date($hdr{$expiresname} ?
X			`getdate "$hdr{$expiresname}"` : time);
X		$hdr{$expiresname}= $dow . ', ' . join(' ',$dy,$mn,$yr,$tm,$tz);
X	}
X}
X
X# organization -- inews passes this in the environment if it knows it
Xunless ($hdr{$orgname}) {
X	unless ($ENV{$orgname}) {
X		if (open(IN, $NEWSCTL . '/organization')) {
X			chop($hdr{$orgname} = <IN>);
X			close(IN);
X		}
X		# add your own backup here if desired
X	}
X	else {
X		$hdr{$orgname} = $ENV{$orgname};
X	}
X}
X
X# the rest of this is based on defhdrs.pl, the result of running
X# defhdrs.awk through a2p.
X$status = 0;			# error status
X
X# copy %hdr to %hdrval, stripping control characters & blank headers
X# as we go (recall there are no newlines in these headers)
Xwhile (($h, $v) = each %hdr) {
X	next unless ($v);
X	$h =~ tr/\001-\037\177//d;
X	$v =~ tr/\001-\037\177//d;
X	$hdrval{$h} = $v;
X}
Xundef %hdr;
X
Xif ($hdrval{$subjname} eq '') {
X	print STDERR 'You have no ', $subjname, ": header!\n";
X	$status = 1;
X}
Xif ($hdrval{$ngname} eq '') {
X	print STDERR 'You have no ', $ngname, ": header!\n";
X	$status = 1;
X}
Xif ($hdrval{$pathname} eq '') {
X	$hdrval{$pathname} = $user;
X}
Xif ($hdrval{$msgidname} eq '') {
X	# generate message ID
X	$ENV{'TZ'} = $oldtz; 
X	($mn, $dy, $tm, $yr) = (&do_date(time))[1,2,3,5];
X	$tm =~ tr/://d;
X	$hdrval{$msgidname} = "<${yr}${mn}${dy}.${tm}.$$@${mailname}>";
X}
Xif ($hdrval{$fromname} eq '') {
X	$hdrval{$fromname} = $user . '@' . $mailname . ' ' . $name;
X}
Xelsif ($hdrval{$sendername} eq '') {
X	$hdrval{$sendername} = $user . '@' . $mailname . ' ' . $name;
X}
Xif ($hdrval{$distrname} eq 'world') {
X	delete $hdrval{$distrname};
X}
Xif ($hdrval{$ctlname} eq '' && 
X    substr($hdrval{$subjname}, 0, 14) eq 'Subject: cmsg ') {
X	$hdrval{$ctlname} = substr($hdrval{$subjname}, 5);
X}
X
X# Strip white space from Newsgroups:, Followup-To:, and Distribution:
X$hdrval{$ngname} =~ tr/\t //d;
X$hdrval{$distrname} =~ tr/\t //d if ($hdrval{$distrname});
X$hdrval{$followname} =~ tr/\t //d if ($hdrval{$followname});
X
X# field the all.all.ctl hack, for the sake of the backward only:
X# clone Subject: to make Control:
X# This is not quite the same as the cmsg case (above)
Xif ($hdrval{$ctlname} eq '' && $hdrval{$ngname} =~ /\.ctl(,|$)/) {
X	$hdrval{$ctlname} = $hdrval{$subjname};
X}
X
X# print headers -- do the first in order, then any that are left over.
X# A comment in defhdrs.awk implies that B news requires Path: before From:.
Xfor $h ($ctlname, $ngname, $pathname, $fromname, $subjname) {
X	if ($hdrval{$h}) {
X		print $h, ': ', $hdrval{$h}, "\n";
X		delete $hdrval{$h};
X	}
X}
X# print the rest the way they come out
Xforeach $h (keys %hdrval) {
X	if ($hdrval{$h}) {
X		print $h, ': ', $hdrval{$h}, "\n";
X	}
X}
Xexit $status;
SHAR_EOF
if test 5225 -ne "`wc -c < 'anne.jones.pl'`"
then
	echo shar: error transmitting "'anne.jones.pl'" '(should have been 5225 characters)'
fi
chmod +x 'anne.jones.pl'
fi # end of overwriting check
echo shar: extracting "'config.EXAMPLE'" '(936 characters)'
if test -f 'config.EXAMPLE'
then
	echo shar: will not over-write existing file "'config.EXAMPLE'"
else
sed 's/^X//'  >'config.EXAMPLE' <<'SHAR_EOF'
X#! /usr/local/perl
X# perl version of the Cnews config file
X# This is an example; yours will set the variables to different values.
X# Read and heed the warnings in config about changing it; they apply
X# to this file too.
X
X$ENV{'NEWSCTL'} = '/net/lib.news' if (!defined($ENV{'NEWSCTL'}));
X$ENV{'NEWSBIN'} = '/var/lib/cnews' if (!defined($ENV{'NEWSBIN'}));
X$ENV{'NEWSARTS'} = '/usr/spool/news' if (!defined($ENV{'NEWSARTS'}));
X$ENV{'NEWSPATH'} = '/bin:/usr/bin:/usr/ucb:/usr/local' 
X	if (!defined($ENV{'NEWSPATH'}));
X$ENV{'NEWSUMASK'} = '002' if (!defined($ENV{'NEWSUMASK'}));
X$ENV{'NEWSMASTER'} = 'usenet' if (!defined($ENV{'NEWSMASTER'}));
X$ENV{'NEWSCONFIG'} = '/var/lib/cnews/config' if (!defined($ENV{'NEWSCONFIG'}));
X
X$NEWSCTL = $ENV{'NEWSCTL'};
X$NEWSBIN = $ENV{'NEWSBIN'};
X$NEWSARTS = $ENV{'NEWSARTS'};
X$NEWSPATH = $ENV{'NEWSPATH'};
X$NEWSUMASK = $ENV{'NEWSUMASK'};
X$NEWSMASTER = $ENV{'NEWSMASTER'};
X$NEWSCONFIG = $ENV{'NEWSCONFIG'};
SHAR_EOF
if test 936 -ne "`wc -c < 'config.EXAMPLE'`"
then
	echo shar: error transmitting "'config.EXAMPLE'" '(should have been 936 characters)'
fi
fi # end of overwriting check
:	End of shell archive
exit 0
-- 
Kenneth Herron                                       [email-masked]
University of Kentucky                                  +1 606 257 2975
Department of Mathematics        Don't tell Ken, but his .signature has
                          been infected by the .signature virus (v2.2f)