#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix@uunet.uu.net if you want that tool.
# Contents:  gag.1 gate.h hdr.c mail2news.1 news2mail.1 patchlevel.h
#   regex.3
# Wrapped by rsalz@nntp.com on Tue Jan 30 22:17:05 1996
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 3 (of 4)."'
if test -f 'gag.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gag.1'\"
else
  echo shar: Extracting \"'gag.1'\" \(9103 characters\)
  sed "s/^X//" >'gag.1' <<'END_OF_FILE'
X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/gag.1,v 1.6 91/04/01 09:43:50 rsalz Exp Locker: rsalz $
X.TH GAG 1 LOCAL
X.SH NAME
Xgag \- Gateway alias generator
X.SH SYNOPSIS
X.in +.5i
X.na
X.ti -.5i
X.B gag
X[
X.B \-a
X] [
X.BI \-b bbn_file
X] [
X.BI \-c cnews_file
X] [
X.BI \-i innnews_file
X] [
X.BI \-n bnews_file
X] [
X.BI \-d mmdf_dir
X] [
X.BI \-s sendmail_file
X] [
X.BI \-t PP_shell
X] [
X.BI \-u PP_user
X] [
X.B \-b
X] [
X.B \-p
X] [
X.I file
X]
X.ad
X.in -.5i
X.SH DESCRIPTION
X.I Gag
Xreads a control file and builds entries for
X.IR sendmail (8),
X.IR BBN ,
X.IR MMDF (8),
Xand
X.IR PP (8)
Xalias files, as well as
X.IR Netnews (1)
Xsys file entries.
XIt is an auxiliary program for helping to maintain a mail/news
Xgateway operation.
XA typical
X.I gag
Xfile sets up default values for all the parameters, then contains a list
Xof newsgroup\-mailing list pairs.
XGroup-specific values can override the defaults.
X.PP
X.I Gag
Xinput is fairly free-form.
XIt ignores C-style comments, and whitespace is allowed anywhere.
XThere are a couple of dozen keywords, and case is significant; most
Xof the keywords are parameters used to control the gatewaying.
XQuoted strings are written as they are in C, except they may not
Xspan lines.
X.PP
XUsing the parameters enumerated below,
X.I gag
Xcan write six different sets of alias files:
X.RS
X.ta \w'InterNetNews  'u
X.nf
XBBN	if the ``\-b'' flag is used
XMMDF	if the ``\-m'' flag is used
XB News	if the ``\-n'' flag is used
XC News	if the ``\-c'' flag is used
XInterNetNews	if the ``\-i'' flag is used
XSendmail	if the ``\-s'' flag is used
XPP shell	If the ``\-t'' flag is used
XPP user	if the ``\-u'' flag is used
X.fi
X.RE
XAny combination of these flags is allowed.
X.I Gag
Xdoes not edit any existing files; all output blindly overwrites the
Xspecified output files.
XThe intent is that you review the output, then manually update the
Xproduction versions.
XDoing something like ``gag \-n /usr/lib/news/sys'' is a sure recipe for
Xdisaster!
XDo something like this, instead:
X.RS
X.nf
X    sed '/--START-OF-GATEWAY-OUTPUT-/,/--END-OF-GATEWAY-OUTPUT-/d' \e
X	</usr/lib/news/sys >/tmp/sys
X    gag -n - <gag.data >>/tmp/sys
X    mv /tmp/sys /usr/lib/news/sys
X.fi
X.RE
X.PP
X.I Gag
Xnormally complains about attempts to gateway groups that are not in
Xthe news active file; use the ``\-a'' suppresses this check, assuming
Xthat all named groups are valid.
X.PP
XBBN-style
Xaliases can't pipe into a command with parameters.
XFor example,
X.I sendmail
Xcan have an entry like this in
X.IR /usr/lib/aliases (5):
X.RS
X.ta \w'post-bboard:  'u
X.nf
Xpost-bboard:	"|/usr/lib/news/mail2news -n bbn.bboard \e
X	-o 'BBN News/Mail Gateway' \e
X	-d bbn"
X.fi
X.RE
XWith BBN, it is necessary to create an alias that feeds into a custom script:
X.RS
X.ta \w'bboard-gate:  'u
X.nf
Xbboard-gate:	@mailer.bbn.com { "news|/usr/lib/news/.admin/gate-bboard" }
X	bboard-gate@mailer.bbn.com
X.fi
X.RE
X.I Gag
Xwill also create the utility script invoked by the above alias:
X.RS
X.ta \w'exec 'u
X.nf
X#! /bin/sh
X##  This script is on the "bboard" mailing list.
Xexec /usr/lib/news/mail2news -n bbn.bboard \e
X	-o "BBN News/Mail Gateway" \e
X	-d bbn
X.fi
X.RE
XTo create these scripts, use the ``\-d'' flag to name the directory where
Xthey should be created; ``\-d .'' will create them in the current directory.
X.PP
X.I MMDF
Xaliases are similar to
X.IR sendmail 's,
Xexcept that the the scripts are run under a specified user id
X(see below).
X.PP
X.I PP
Xuses two files, a shell and user file, whose format is not described here.
X.PP
XSome sites want to create mail aliases that forward into each newsgroup;
Xthat is, mail sent to ``comp-foo-bar'' should get posted to the ``comp.foo.bar''
Xnewsgroup.
XIf the ``\-p'' flag is used, then each gatewayed group will get such an
Xalias created.
XThe
X.IR mkmailpost (1L)
Xcommand can be used to create
X.I gag
X``mailpost'' commands for all entries in the news active file.
XNote that using
X.I mkmailpost
Xand the ``\-p'' flag will almost certainly result in the creation of duplicate
Xaliases.
X.PP
XThe parameters that control the gatewaying are:
X.IP directory
XThe directory where the BBN alias scripts are kept.
X(In the above example, the directory is
X.IR /usr/lib/news/.admin .)
X.IP distributions
XA space-separated list of distributions to forward from news to mail.
XIn most cases, this will be the full set of distributions received, but
Xit can be convenient, for example, to not forward regional articles out
Xto a world-wide mailing list.
XWith distributions set to ``world usa na'' then the news sys entry
Xfor ``comp.foo'' will have this in the second field:
X.in +.5i
X.nf
X<site>:\e
X  world,!world.all,usa,!usa.all,na,!na.all,comp.foo,!comp.foo.all\e
X  <rest of entry>
X.in -.5i
X.fi
X.IP "inews flags"
XThese are flags to pass on to
X.IR inews (8)
Xwhen gatewaying a mail message into netnews.
XThey are put on the
X.I news2mail (1)
Xcommand line, which will pass them along.
XA common use is to set a default distribution or organization.
X.IP mail2news
XThe full pathname of the
X.I mail2news
Xprogram.
X.IP mailcontact
XThis is the name of the person listed in the ``For more information, contact''
Xpart of the header generated by
X.IR news2mail .
X.IP mailhost
XWhen remote mailing lists are gatewayed into local newsgroups, it can
Xoften be convenient to provide a local alias that forwards on to the
Xremote host.
XFor example, if the list ``info-foo'' is maintained at ``vax.host.edu''
Xthen it is possible to create a local alias that just forwards to
X``info-foo@vax.host.edu.''
X.IP "mailinglist"
XIf set to ``true,'' then
X.I gag
Xwill write aliases that forward on to the list at the current mailhost; if
Xset to ``false'' than no such aliases will be written.
X.IP moderator
XIf set, then the value is put on the
X.I mail2news
Xcommand line with the ``\-a'' flag.
XThis is useful for making a semi-moderated one-way gateway.
X.IP news2mail
XThe full pathname of the
X.I news2mail
Xprogram.
X.IP organization
XIf set, then the value is put on the
X.I mail2news
Xcommand line with the ``\-o'' flag.
X.IP owner
XIf set, then all
X.I sendmail
Xaliases also have an ``owner\-'' version, with this value as the
Xrecipient, to receive trouble reports.
X.IP request_address
XMost mailing lists have a ``\-request'' address to handle list administration.
XWhen gatewaying the list ``info-foo'' if the maintenance address isn't
X``info-foo-request'' set this parameter to the proper address.
X.IP site
XThis is the name of the site to use in the news sys file; ``gateway'' is
Xa common choice.
X.IP user
XWhen running scripts under
X.I MMDF
X(either normal or with the BBN style)
Xa userid to setuid to must be given.
X.PP
XNote that there is some overlap in these parameters.
XIn particular the ``moderator'' and ``organization'' parameters can really
Xbe subsumed by the ``inews flags'' parameter.
XThey are explicitly called out, however, for convenience in specifying
Xthe types of gatewaying.
XFor example, while all gatewayed groups might go out with the same
Xdistribution, only some might need an
X.I Approved:
Xheader line.
X.SH "THE LANGUAGE"
XA
X.I gag
Xfile is composed of intermixed parts of three different constructs:
Xdefaults, mail/news posting entries, mail/news gateway entries.
X.PP
XIndividual groups can override the default parameters.
XThe defaults can be changed at any time, and retain the new value for
Xthe rest of the file or until changed again.
XFor example, most mail aliases will be ``owned'' by
X.IR postmaster ,
Xbut it might be convenient to set the forwarding address on specific
Xaliases to someone else.
XFor example:
X.RS
X.DT
X.nf
X/* Send gateway complaints to postmaster */
Xdefault owner = "postmaster";
X
X/* The "animals" list is privately maintained. */
Xgateway bbn.animals animal-rights
X	owner = "canus-major";
X.fi
X.RE
XThe syntax is explained in more detail, below.
X.PP
XA default parameter assignment looks like one of the following:
X.RS
X.DT
X.nf
X\fBdefault\fP <parameter> \fB= true ;\fP
X\fBdefault\fP <parameter> \fB= false ;\fP
X\fBdefault\fP <parameter> \fB=\fP "string value" \fB;\fP
X\fBdefault\fP <parameter> \fB= dotify (\fP "value" \fB) ;\fP
X.fi
X.RE
XThe last form is used to translate mixed-case strings into the prefix-period
Xform used by
X.IR mail2news .
X.PP
XA gateway declaration looks like this:
X.RS
X.DT
X.nf
X\fBgateway\fP <newsgroup> <mailinglist>
X	[ parameter settings ] \fB;\fP
X.fi
X.RE
XThe parameter settings are like the default settings shown above, except
Xthat the word ``default'' is left off, as are all semicolons but the
Xlast one.
X.PP
XTo set up a simple unidirectional newsgroup/mailing list gateway, use a
X``mailpost'' declaration:
X.RS
X.DT
X.nf
X\fBmailpost\fP <newsgroup> \fB;\fP
X.fi
X.RE
X.SH "BUGS AND CAVEATS"
X.I Gag
Xdoesn't free most of the memory that it allocates; in essence, the entire
Xinput must fit into the process space.
X.PP
XIn generating news
X.I sys
Xfile entries, remember that the command is a
X.IR sprintf (3)
Xformat string, and any percent signs
X.RI ( % )
Xmust be doubled or they will be taken as a formatting control.
X.SH "SEE ALSO"
Xmail2news(1L), mkmailpost(1L), news2mail(1L).
X.SH AUTHORS
XRich $alz <rsalz@bbn.com>, replacing some
X.I m4
Xscripts that
X.br
XErik E. Fair <fair@apple.com> wrote.
X.br
XPiete Brooks <pb@computer-lab.cambridge.ac.uk> provided the PP support.
END_OF_FILE
  if test 9103 -ne `wc -c <'gag.1'`; then
    echo shar: \"'gag.1'\" unpacked with wrong size!
  fi
  # end of 'gag.1'
fi
if test -f 'gate.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gate.h'\"
else
  echo shar: Extracting \"'gate.h'\" \(8413 characters\)
  sed "s/^X//" >'gate.h' <<'END_OF_FILE'
X/*
X**  HEADER FILE FOR NEWS/MAIL GATEWAY CODE.
X**  $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/gate.h,v 1.19 91/07/18 21:14:18 rsalz Exp Locker: rsalz $
X*/
X/* SUPPRESS 460 *//* '/' '*' occurred inside a comment */
X
X
X/*
X**  START OF CONFIGURATION SECTION
X*/
X
X
X/* Paths to some parts of your netnews installation.  Required.
X * If you set INEWS to point to a C News relaynews, then set NO_H_FLAG. */
X#define INEWS		"/usr/lib/news/inews"
X#define ACTIVE		"/usr/lib/news/active"
X#define NGDELIM		','
X
X/* If you #define this, then the -h flag will not be appended and the -=
X * flag will not delete it. */
X#undef NO_H_FLAG
X
X/* In writing Paths into From addresses, we can look at the output
X * of uuname from the L.sys file.  Define both or neither of the next
X * two.  We can also map some UUCP names to their domain names, if
X * the third line is enabled.  The UUCP_INET should match the value
X * in the Makefile.  This violates the "write once" rule, but it's
X * too much of a pain to fix for this one symbol. */
X#define UUNAME		"/usr/lib/news/.admin/uuname.out"
X#define L_SYS		"/usr/lib/uucp/L.sys"
X#define UUCP_INET	"/usr/lib/news/.admin/uucp-2-inet"
X
X
X/* Do you want news2mail to use the Path line in generating the From line?
X */
X#define USE_PATH_FOR_FROM
X
X
X/* Do you need to handle eight-bit characters in your addresses?  If
X * not (e.g., just USASCII) then #undef the next line.
X */
X#define DO_8BIT_CHARS
X
X
X/* Where does the control file for talk.foo live?
X *	IN_ONEPLACE:	specified filename
X *	IN_SPOOLDIR:	/usr/spool/news/talk/foo/recnews.cmd
X *	IN_CMDDIR:	/usr/lib/news/.admin/talk.foo
X * One of these is required, but you can set IN_ONEPLACE to /dev/null to
X * disable the newsgroup editing. */
X#undef IN_ONEPLACE	"/dev/null"
X#undef IN_SPOOLDIR	"/usr/spool/news"
X#define	IN_CMDDIR	"/usr/lib/news/.admin"
X
X
X/* What do you want to do with the Path: line?  Put in a fixed string
X * (such as pointing to a mail reflector saying "Don't trust Path
X * lines as a way to reply").  Put a fixed "fake host" in the Path
X * before the user's host and name, or put just the user's host and
X * name there.  Note that the latter two can cause the poster's site
X * to never get the article sent to them.  Anyhow, pick one.  To pick
X * neither #define is to get the third behavior -- the user's host. */
X#define FIXED_PATH	"gateway"		/* .. */
X#undef	GATEWAY_NAME	"gateway"
X
X/* If the "hostname" you use for news (such as in the pathline) is not
X * the same as `hostname`, then define WHOAMI to be your news name (e.g.,
X * the contents of the C News file /usr/lib/news/whoami). */
X#undef WHOAMI		"bbn"
X
X
X/* The code in hdr.c does lots of work to canonicalize addresses.  You
X * might want to disable it if your sendmail.cf (e.g.) is very very good.
X * You might want to disable DO_GETHOSTBYNAME because gethostbyname(3)
X * doesn't handle MX records, and in some setups doesn't return a full
X * domain name. */
X#define DO_ADDRESS_CLEANUP			/* .. */
X#define DO_GETHOSTBYNAME			/* .. */
X
X
X/* Are you running sendmail or MMDF?  Pick one.  If you believe in
X * trusted users (MMDF doesn't?) to lie to your mailer, set the
X * user-ID. */
X#undef SENDMAIL	"/usr/lib/sendmail"
X#undef TRUSTED		1
X#define	MMDF		"/usr/mmdf/lib/submit"	/* .. */
X#undef MMDF_DELIVER_NOW
X
X
X/* Does your Sendmail mailer have the M flag on, requiring a Message-ID?
X * And do you want to require that the first line by a "From " line? */
X#if	defined(SENDMAIL)
X#define REQUIRE_MESSAGE_ID			/* .. */
X#undef REQUIRE_UNIX_FROM
X#endif	/* defined(SENDMAIL) */
X
X
X/* I love how we all speak the same language. */
X#define CATCHER		void		/* Type of a signal-catcher	*/
X#define IDX		index
X#define RDX		rindex
Xtypedef int		*align_t;	/* Worst-case alignment, for lint */
X#define CHARSTAR_SPRINTF		/* Need extern char *sprintf();	*/
X#define VOID_EXIT			/* Need extern void exit();	*/
X#define HAVE_SYSEXITS			/* Have <sysexits.h>?		*/
X#define HAVE_PUTENV			/* Have putenv(3)		*/
X#undef HAVE_STRERROR			/* Have strerror(3)?		*/
X
X#define SM_SIZE		512		/* A smallish buffer size	*/
X#define LG_SIZE		1024		/* big buffer size		*/
X
X/* Error log (stderr) for news2mail. */
X#define ERR_LOG		"/usr/lib/news/.admin/news2mail.out"
X#define TEMPFILE	"/tmp/gateXXXXXX" /* Temporary file pattern	*/
X
X
X/* Enable debugging code? */
X#define STATIC		static
X#if	!defined(lint) && !defined(SABER)
X#define RCSID
X#endif	/* !defined(lint) && !defined(SABER) */
X
X/*
X**  END OF CONFIGURATION SECTION.
X*/
X
X
X
X#include <stdio.h>
X#include <ctype.h>
X#include <sys/types.h>
X
X#if	defined(HAVE_SYSEXITS)
X#include <sysexits.h>
X#else
X#include "sysexits.h"
X#endif	/* defined(HAVE_SYSEXITS) */
X
X
Xtypedef struct _HBUF {
X    char	approved[SM_SIZE];	/* Approved:		*/
X    char	ctlmsg[LG_SIZE];	/* Control:		*/
X    char	subdate[SM_SIZE];	/* Date: (submission)	*/
X    char	distribution[SM_SIZE];	/* Distribution:	*/
X    char	expdate[SM_SIZE];	/* Expires:		*/
X    char	followto[SM_SIZE];	/* Followup-to:		*/
X    char	from[SM_SIZE];		/* From:		*/
X    char	followid[SM_SIZE];	/* References:		*/
X    char	keywords[SM_SIZE];	/* Keywords:		*/
X    char	ident[SM_SIZE];		/* Message-ID:		*/
X    char	nbuf[LG_SIZE];		/* Newsgroups:		*/
X    char	organization[SM_SIZE];	/* Organization:	*/
X    char	title[SM_SIZE];		/* Subject:		*/
X    char	replyto[SM_SIZE];	/* Reply-To:		*/
X    char	summary[SM_SIZE];	/* Summary:		*/
X    char	path[LG_SIZE];		/* Path:		*/
X    char	sender[SM_SIZE];	/* Sender:		*/
X    char	mimeversion[SM_SIZE];	/* MIME-Version:	*/
X    char	mimexfer[LG_SIZE];	/* Content-Transfer-Encoding: */
X    char	mimetype[LG_SIZE];	/* Content-Type:	*/
X} HBUF;
X
X#if	defined(__GNUC__) || defined(__STDC__)
Xtypedef char const	*STRING;
X#else
Xtypedef char		*STRING;
X#endif	/* defined(__GNUC__) || defined(__STDC__) */
X
X/* String and memory manipulators. */
X#define APPEND(p, t)	strlen(strcpy((p), (t)))
X#define NEW(T, c)	(T *)MyAlloc((int)((c) * sizeof (T)))
X#define COPY(s)		strcpy(NEW(char, strlen((s)) + 1), (s))
X#define REALLOC(p, s)	realloc((char *)(p), (unsigned int)(s))
X
X
X/* Array sizing. */
X#define SIZEOF(x)	(sizeof x / sizeof x[0])
X#define ENDOF(x)	(&x[SIZEOF(x)])
X
X#if	!defined(DO_8BIT_CHARS)
X#define ADDRCHAR	char	/* Addresses internal representation	*/
X#define QUOTE_MASK	0x0080	/* Mask to turn on 8-bit quoting	*/
X#define UNQUOTE_MASK	0x007F	/* Mask to turn off the 8-bit quote	*/
X#else
X#define ADDRCHAR	short	/* Addresses internal representation	*/
X#define QUOTE_MASK	0x0100	 /* Mask to turn on 9-bit quoting	*/
X#define UNQUOTE_MASK	0x00FF	/* Mask to turn off the 9-bit quote	*/
X#endif	/* !defined(DO_8BIT_CHARS) */
X
X/* String and character operations. */
X#define WHITE(c)	((c) == ' ' || (c) == '\t')
X#define EQ(a, b)	((a)[0] == (b)[0] && strcmp((a), (b)) == 0)
X#define EQn(a, b, n)	((a)[0] == (b)[0] && strncmp((a), (b), (n)) == 0)
X#define NETCHR(c)	((c) == '%' || (c) == '@' || (c) == '!')
X#define CHREQ(c, d)	((d) == (islower((c)) ? toupper((c)) : (c)))
X
X
X/* Fundamental constants of the universe. */
X#define TRUE		1
X#define FALSE		0
X#define FAIL		(-1)
X
X
X/* SHUT UP! */
X#if	defined(lint)
X#undef	putc
X#undef	putchar
X#endif	/* defined(lint) */
X
X#define Close		(void)close
X#define Fflush		(void)fflush
X#define Fprintf		(void)fprintf
X#define Fputs		(void)fputs
X#define Signal		(void)signal
X#define Sprintf		(void)sprintf
X#define Strcpy		(void)strcpy
X#define Strcat		(void)strcat
X#define Strncpy		(void)strncpy
X
X
X/*
X**  External declarations.
X*/
X
X/* Program name; exists once for each main(). */
Xextern	char	*Pname;
X
X/* Routines we provide. */
Xextern align_t	MyAlloc();
Xextern int	Split();
Xextern int	CrackFrom();
Xextern void	re_modw();
Xextern void	SplitFree();
Xextern void	FreeFile();
Xextern char	**ReadFile();
Xextern char	*re_comp();
Xextern STRING	HackHeader();
Xextern void	rfc822read();
Xextern void	yyopen();
Xextern void	yyerror();
Xextern int	re_exec();
Xextern int	rfc822write();
X
Xextern char	*strerror();
X
X/* Variables and routines that Unix(tm) provides. */
Xextern int	errno;
Xextern int	sys_nerr;
Xextern int	optind;
Xextern char	*sys_errlist[];
Xextern char	**environ;
Xextern char	*optarg;
X
Xextern FILE	*popen();
Xextern char	*IDX();
Xextern char	*RDX();
Xextern char	*ctime();
Xextern char	*malloc();
Xextern char	*mktemp();
Xextern char	*realloc();
Xextern char	*strcat();
Xextern char	*strncat();
Xextern char	*strcpy();
Xextern char	*strncpy();
X#if	defined(CHARSTAR_SPRINTF)
Xextern char	*sprintf();
X#endif	/* defined(CHARSTAR_SPRINTF) */
X#if	defined(VOID_EXIT)
Xextern void	exit();
X#endif	/* defined(VOID_EXIT) */
END_OF_FILE
  if test 8413 -ne `wc -c <'gate.h'`; then
    echo shar: \"'gate.h'\" unpacked with wrong size!
  fi
  # end of 'gate.h'
fi
if test -f 'hdr.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'hdr.c'\"
else
  echo shar: Extracting \"'hdr.c'\" \(11239 characters\)
  sed "s/^X//" >'hdr.c' <<'END_OF_FILE'
X/*
X**  Header-cracking and address re-writing routines, with sincere
X**  apologies to Upas and Sendmail.
X*/
X#include "gate.h"
X#if	defined(DO_GETHOSTBYNAME)
X#include <netdb.h>
X#endif	/* defined(DO_GETHOSTBYNAME) */
X#if	defined(RCSID)
Xstatic char RCS[] =
X	"$Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/hdr.c,v 1.21 91/07/18 20:00:57 rsalz Exp $";
X#endif	/* defined(RCSID) */
X
X
X#if	defined(TEST)
X#if	!defined(DO_FIX_ADDRESS)
X#define DO_FIX_ADDRESS
X#endif	/* !defined(DO_FIX_ADDRESS) */
X#if	!defined(DO_ADDRESS_CLEANUP)
X#define DO_ADDRESS_CLEANUP
X#endif	/* !defined(DO_ADDRESS_CLEANUP) */
X#else
X#define dprintf(string, buff)	/* NULL */
X#endif	/* defined(TEST) */
X
X
X#if	defined(DO_ADDRESS_CLEANUP)
X/*
X**  List of domains that we recognize.
X*/
XSTATIC STRING	Domains[] = {
X    /* These aren't official domains, but we use them. */
X	".BITNET",
X	".UUCP",
X    /* Official organizational domains. */
X	".ARPA",	".COM",	".EDU",	".GOV",	".INT",	".MIL",
X	".NATO",	".NET",	".ORG",
X    /* Official natonal domans. */
X	".AR",	".AT",	".AU",	".BE",	".BR",	".CA",	".CH",	".CL",
X	".CN",	".CR",	".CS",	".DE",	".DK",	".EC",	".EG",	".ES",
X	".FI",	".FR",	".GR",	".HK",	".HU",	".IE",	".IL",	".IN",
X	".IS",	".IT",	".JP",	".KR",	".LK",	".MX",	".MY",	".NI",
X	".NL",	".NO",	".NZ",	".PH",	".PL",	".PR",	".PT",	".SE",
X	".SG",	".SU",	".TH",	".TR",	".TW",	".UK",	".US",	".UY",
X	".YU",	".ZA"
X};
X
X
X/*
X**  Handle route-addresses:
X**	@cruft:joe@site --> joe@site
X*/
XSTATIC void
XRouteAddr(p)
X    register ADDRCHAR	*p;
X{
X    register ADDRCHAR	*q;
X    register ADDRCHAR	*r;
X
X    if (*p != '@')
X	/* Not a route -- leave alone. */
X	return;
X
X    /* Find the last '@'. */
X    for (r = p; *r; r++)
X	continue;
X    while (*--r != '@')
X	continue;
X
X    /* Find the preceeding colon. */
X    for (q = r; q > p && *q != ':'; q--)
X	continue;
X    r = q++;
X    if (r > p)
X	while ((*p++ = *q++) != 0)
X	    continue;
X}
X
X
X/*
X**  Handle the '%' syntax:
X**	joe%site.EDU@gateway.DOMAIN -> joe@site.EDU
X*/
XSTATIC void
XPercent(p)
X    register ADDRCHAR	*p;
X{
X    register ADDRCHAR	*q;
X    register ADDRCHAR	*r;
X    register ADDRCHAR	*s;
X    register STRING	*dp;
X    register STRING	pat;
X
X    /* Find the rightmost '@'. */
X    for (r = p; *r; r++)
X	continue;
X    while (--r > p)
X	if (*r == '@')
X	    break;
X
X    for (; *r == '@'; r = q) {
X	/* Find the '%' just before the '@'. */
X	for (q = r; q > p && *q != '&'; q--)
X	    continue;
X	if (*q != '%')
X	    break;
X
X	for (dp = Domains; dp < ENDOF(Domains); dp++) {
X	    pat = *dp + strlen(*dp);
X	    for (s = r, pat--, s--; pat > *dp && s > q; pat--, s--)
X		if (*s != *pat
X		 && (!isupper(*pat) || *s != tolower(*pat)))
X		    break;
X	    if (*s != *pat)
X		/* Assume **dp == '.' or not letter. */
X		continue;
X	    *r = '\0';
X	    *q = '@';
X	    break;
X	}
X    }
X}
X
X
X/*
X**  Handle hybrid "!" and "@" addresses:
X**	a!site!joe@site --> leave alone
X**	a!site!joe --> site!joe@a.uucp
X**	a!site.EDU!joe --> joe@site.EDU
X*/
XSTATIC void
XHybrid(p)
X    register ADDRCHAR	*p;
X{
X    register ADDRCHAR	*q;
X    register ADDRCHAR	*r;
X    register ADDRCHAR	*user;
X
X    /* Already has an '@' */
X    for (q = p; *q; q++)
X	if (*q == '@')
X	    return;
X
X    /* Make sure there is a '!' */
X    for (user = p; *user; user++)
X	if (*user == '!')
X	    break;
X    if (*user != '!')
X	return;
X
X    for (*q++ = '@', *user = '\0', r = p; *r; r++)
X	*q++ = *r;
X    /* Copy back to beginning of list */
X    for (*q = '\0', r = p; *++user; r++)
X	*r = *user;
X    for (*r = '\0', user = r; *user != '@'; user--)
X	if (*user == '.')
X	    return;
X    *r++ = '.';
X    *r++ = 'U';
X    *r++ = 'U';
X    *r++ = 'C';
X    *r++ = 'P';
X    *r++ = '\0';
X}
X#endif	/* defined(DO_ADDRESS_CLEANUP) */
X
X
X#if	defined(TEST)
XSTATIC void
Xdprintf(prompt, p)
X    char	*prompt;
X    ADDRCHAR	*p;
X{
X    (void)printf("%s returns:  ", prompt);
X    for ( ; *p; p++) {
X	if (*p & QUOTE_MASK)
X	    (void)putchar('\\');
X	(void)putchar(*p & UNQUOTE_MASK);
X    }
X    (void)putchar('\n');
X}
X#endif	/* defined(TEST) */
X
X/*
X**  General address canonicalizer.
X*/
XSTATIC char *
XFixAddress(p)
X    register ADDRCHAR	*p;
X{
X    static char		buff[1024];
X    register char	*cp;
X    register int	local;
X    char		host[128];
X
X#if	defined(DO_ADDRESS_CLEANUP)
X    RouteAddr(p);
X    dprintf("RouteAddr", p);
X    Percent(p);
X    dprintf("  Percent", p);
X    Hybrid(p);
X    dprintf("   Hybrid", p);
X#endif	/* defined(DO_ADDRESS_CLEANUP) */
X
X    /* Copy address, removing all quoting, and see if it's local. */
X    for (local = 1, cp = buff; (*cp = *p & UNQUOTE_MASK) != '\0'; cp++, p++)
X	if (NETCHR(*p))
X	    local = 0;
X
X    if (local) {
X	if (gethostname(host, sizeof host) < 0) {
X	    Fprintf(stderr, "%s:  Can't get my hostname, %s.\n",
X		    Pname, strerror(errno));
X	    exit(EX_TEMPFAIL);
X	}
X	Strcat(buff, "@");
X	Strcat(buff, host);
X    }
X    return buff;
X}
X
X
X/*
X**  This subroutine is a concession to the realities of the Internet and
X**  and the USENET. Much as the idea is distasteful and likely to get me
X**  in trouble, I have to hack message-ids into a format that the USENET
X**  won't choke on.  Pray that if we're doing multiple insertion point
X**  gatewaying that ALL the gateways mung exactly the same things.
X**
X**  (Death to HERMES! Death to UNIX/MM-11! Death to EAN!)
X*/
XSTATIC int
XFixMessageID(s)
X    register char	*s;
X{
X    register int	atdot;
X    register int	closed;
X    register char	*p;
X    register char	*q;
X
X    /* Skip leading space.  Should be done in general header routines,
X     * but this is the only place that cares. */
X    if (WHITE(*s) || *s == '\n') {
X	for (p = s; WHITE(*p) || *p == '\n'; p++)
X	    continue;
X	for (q = s; (*q++ = *p) != '\0'; p++)
X	    continue;
X    }
X
X    /* Quickie tests -- why waste time? */
X    if (*s != '<')
X	return FALSE;
X
X    for (atdot = FALSE, closed = FALSE; *++s; )
X	switch (*s) {
X	default:
X	    if (!isascii(*s) || iscntrl(*s) || isspace(*s))
X		return FALSE;
X	    break;
X	case '<':
X	    /* Already got one. */
X	    return FALSE;
X	case '>':
X	    /* I hope no one is stupid enough to quote this... */
X	    closed = TRUE;
X	    s[1] = '\0';
X	    break;
X	case '.':
X	case '@':
X	    /* We should check for a domain spec, not just either/or. */
X	    atdot = TRUE;
X	    break;
X	case '\t':
X	case ' ':
X	case '"':
X	    /* Avoid various problem characters. */
X	    *s = '_';
X	    break;
X	}
X
X    return atdot && closed;
X}
X
X
X/*
X**  Fix up the contents of In-Reply-To: fields and References: fields.
X*/
XSTATIC void
XFixReferences(hp)
X    register HBUF		*hp;
X{
X    register char		*cp;
X    register char		*ep;
X    register char		*p;
X    register char		*max;
X    char			scratch[LG_SIZE];
X
X    cp = hp->followid;
X    max = cp + strlen(cp);
X    for (p = scratch; (cp = IDX(cp, '<')) != NULL; ) {
X	if ((ep = IDX(cp, '>')) == NULL
X	 || ((ep - cp) + 1) > sizeof scratch - (p - scratch + 2))
X	    /* Unterminated ID, or no more room. */
X	    break;
X
X	if (FixMessageID(cp)) {
X	    if (p > scratch) {
X		*p++ = ' ';
X		*p++ = '\0';
X	    }
X	    p += APPEND(p, cp);
X	}
X	cp = ep + 2;
X	if (cp >= max)
X	    break;
X    }
X    Strcpy(hp->followid, scratch);
X}
X
X
X/*
X**  Count the number of '@' in the string.
X*/
XSTATIC int
XAtCount(s)
X    register char	*s;
X{
X    register int	n;
X
X    for (n = 0; *s; s++)
X	if (*s == '@')
X	    n++;
X    return n;
X}
X
X
X/*
X**  Canonicalize the "From:" line into the form
X**	From: local-part@domain (full-name)
X** RFC822 doesn't require the comment to be at the end of the string
X** like that.
X*/
XSTATIC void
XFixFrom(hp)
X    register HBUF		*hp;
X{
X    register char		*p;
X#if	defined(DO_GETHOSTBYNAME)
X    register struct hostent	*host;
X#endif	/* defined(DO_GETHOSTBYNAME) */
X    char			address[LG_SIZE];
X    char			fullname[LG_SIZE];
X    char			scratch[sizeof address];
X    ADDRCHAR			temp[LG_SIZE];
X
X    /* We should handle "Full-Name:" too, but it doesn't get read by the
X     * news header reader. */
X    (void)CrackFrom(temp, fullname, hp->from);
X    Strcpy(address, FixAddress(temp));
X
X    if (AtCount(address) != 1)
X	p = NULL;
X    else {
X	p = RDX(address, '@');
X	*p++ = '\0';
X
X#if	defined(DO_GETHOSTBYNAME)
X	/* If we can find the host's official name use that. */
X	if ((host = gethostbyname(p)) != NULL)
X	    p = host->h_name;
X#endif	/* defined(DO_GETHOSTBYNAME) */
X
X	/* We know have the canonical hostname; glue back together. */
X	Sprintf(scratch, "%s@%s", address, p);
X	Strncpy(address, scratch, sizeof address);
X	address[sizeof address - 1] = '\0';
X	p = IDX(address, '@');
X	*p++ = '\0';
X    }
X
X    /* Policy decision; what to put in the path? */
X#if	defined(FIXED_PATH)
X    Strcpy(hp->path, FIXED_PATH);
X#else
X#if	defined(GATEWAY_NAME)
X    Sprintf(scratch, "%s!%s!%s", GATEWAY_NAME, p, address);
X#else
X    Sprintf(scratch, "%s!%s", p, address);
X#endif	/* defined(GATEWAY_NAME) */
X    Strncpy(hp->path, scratch, sizeof hp->path);
X    hp->path[sizeof hp->path - 1] = '\0';
X#endif	/* defined(FIXED_PATH) */
X
X    /* Restore the @ if we took it out. */
X    if (p)
X	*--p = '@';
X
X    if (fullname[0]) {
X	p = address + strlen(address);
X	*p++ = ' ';
X	*p++ = '(';
X	p += APPEND(p, fullname);
X	*p++ = ')';
X	*p++ = '\0';
X    }
X
X    /* Stick the canonicalized From: back in. */
X    Strcpy(hp->from, address);
X    for (p = hp->from; *p; p++)
X	*p &= 0x7F;
X}
X
X
X#define ERROR "\
XMessage-ID syntax error.\n\
X*** Please refer to page 23, paragraph 4.6.1. and Appendix D\n\
X*** of NIC RFC #822 for the correct syntax, and fix your mailer."
X
X/*
X** Check an RFC822 header for validity and hack it to RFC1036 spec.
X** returns NULL for everything OK, or a character pointer to an
X** error message.
X*/
XSTRING
XHackHeader(hp, SubjectRequired)
X    register HBUF		*hp;
X    int				SubjectRequired;
X{
X#if	defined(REQUIRE_MESSAGE_ID)
X    /* Sendmail (almost) always has a Message-ID */
X    if (hp->ident[0] == '\0')
X	return "Message-ID header missing";
X    if (!FixMessageID(hp->ident))
X	return ERROR;
X#else
X    /* MMDF doesn't always have a Message-ID. */
X    if (hp->ident[0] && !FixMessageID(hp->ident))
X	return ERROR;
X#endif	/* defined(REQUIRE_MESSAGE_ID) */
X
X    /* Newsgroups */
X    if (hp->nbuf[0] == '\0')
X	return "Newsgroups header missing";
X
X    /* Subject */
X    if (hp->title[0] == '\0') {
X	if (SubjectRequired)
X	    return "Subject header missing";
X	Strcpy(hp->title, "(none)");
X    }
X
X    /* From */
X    if (hp->from[0] == '\0')
X	return "From header missing";
X    FixFrom(hp);
X
X    /* References and In-Reply-To */
X    if (hp->followid[0]) 
X	FixReferences(hp);
X
X    return NULL;
X}
X
X
X#if	defined(TEST)
X
Xchar	*Pname = "address-test";
X
X#if	!defined(HAVE_STRERROR)
X/*
X**  Return a printable representation of errno.
X*/
Xchar *
Xstrerror(x)
X    int			x;
X{
X    static char		buff[20];
X
X    if (x >= 0 && x < sys_nerr)
X	return sys_errlist[x];
X    Sprintf(buff, "Error code %d", x);
X    return buff;
X}
X#endif	/* !defined(HAVE_STRERROR) */
X
Xmain()
X{
X    HBUF	hp;
X    char	buff[BUFSIZ];
X    int		interactive;
X
X    interactive = isatty(0);
X    if (interactive)
X	(void)printf("Enter addresses, EOF to exit:\n");
X    for ( ; ; ) {
X	if (interactive) {
X	    (void)printf(">  ");
X	    (void)fflush(stdout);
X	}
X	if (gets(buff) == NULL)
X	    break;
X	if (buff[0] != '#' && buff[0] != '\0') {
X	    if (!interactive) {
X		(void)printf("%s\n", buff);
X		(void)fflush(stdout);
X	    }
X	    (void)strcpy(hp.from, buff);
X	    FixFrom(&hp);
X	    (void)printf("\t-> %s\n\n", hp.from);
X	}
X    }
X
X    exit(0);
X}
X#endif	/* defined(TEST) */
END_OF_FILE
  if test 11239 -ne `wc -c <'hdr.c'`; then
    echo shar: \"'hdr.c'\" unpacked with wrong size!
  fi
  # end of 'hdr.c'
fi
if test -f 'mail2news.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mail2news.1'\"
else
  echo shar: Extracting \"'mail2news.1'\" \(5693 characters\)
  sed "s/^X//" >'mail2news.1' <<'END_OF_FILE'
X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/mail2news.1,v 1.13 91/07/18 15:01:54 rsalz Exp Locker: rsalz $
X.TH MAIL2NEWS 1 LOCAL
X.SH NAME
Xmail2news \- feed a mail message into Usenet news
X.SH SYNOPSIS
X.B mail2news
X[
X.B \-\&.
X] [
X.B \-F
X] [
X.BI \-= program
X] [
X.BI \-n newsgroups
X] [
X.BI \-o organization
X] [
X.BI \-d distribution
X] [
X.BI \-a approval
X] [
X.B inewsflags
X]
X.SH DESCRIPTION
X.I Mail2news
Xreads an RFC822 Mail message on standard input, writes the headers to conform
Xwith RFC1036 (superceeding RFC850) Usenet News article.
XA subject is required, unless one of the
X.IR inews (8)
X``\-x'' or ``\-o'' flags are specified.
X.PP
XIf the ``\-.'' flag is specified, the modified article is sent to the
Xstandard output, rather than feed into
X.IR inews .
X.PP
XBy default,
X.I mail2news
Xsends its input to ``inews \-h''; this can be changed by using the ``\-=''
Xflag, which will send the output to the specified program.
XNote that no argument parsing is done, so that only a single word may
Xbe specified with the ``\-='' flag.
X.PP
XThe ``\-o,'' ``\-n,'' ``\-d,'' or ``\-a'' flags may be used to specify the
XOrganization, Newsgroups, Distribution, or Approved header in the message.
XNote that unlike the
X.I inews
Xparallels of these flags, the ``\-n'' flag overrides any Newsgroups header
Xthat might appear in the message, while the other flags specify defaults
Xif the message does not have the headers.
XIn addition, as a concession to
X.IR sendmail (8)
Xalias processing the argument to the ``\-o'' flag is handled specially.
XSince many
X.I sendmail.cf
Xfiles do not have the ``preserve case'' flag on for the ``prog'' mailer,
Xa period in the argument means that the following character should be converted
Xto uppercase; two periods mean to output a single period.
XFor example, if the following line is in
X.IR /usr/lib/aliases (5):
X.RS
Xpost\-news\-admin:
X    "|/usr/local/bin/mail2news \-o '.the .b...b...n.. .gateway' \-n news.admin"
X.RE
Xthen messages to mailed to
X.I post\-news\-admin
Xwill be posted to the ``news.admin'' newsgroup with the following header line:
X.RS
XOrganization: The B.B.N. Gateway
X.RE
X.PP
XIf the ``\-F'' flag is given, then
X.I mail2news
Xwill try to filter out
Xthe ``please add me to your mailing list'' messages often sent by
Xnetwork neophytes.
XThis is done by looking for short messages which have words like
X.I subscribe
Xin them.
X.PP
X.I Mail2news
Xcan modify the newsgroups an article is sent to, based on regular expressions
Xfound in the ``Title:'', ``Keywords:'', and ``Summary:'' headers.
XThe headers are scanned once for each newsgroup the article is originally
Xdestined for, provided a mapping file exists for the newsgroup.
X(The path to the mapping file depends on a compile\-time parameter.)
XFor example, if a mail message is to be sent to
X.I talk.foo
Xand
X.IR soc.bar ,
X.I mail2news
Xwill scan the headers twice.
XIf the file
X.I /usr/lib/news/.admin/talk.foo
X(or
X.IR /usr/spool/news/talk/foo/recnews.cmd )
Xexists, the commands in that file are interpreted.
XThe scan is repeated, with the appropriate file for
X.IR soc.bar .
XIn the explanation below, the ``current newsgroup'' will be first
X.I talk.foo
Xand then
X.IR soc.bar .
X.PP
XBlank lines, and lines beginning with a pound sign
X.RI ( # )
Xare ignored.
XOther lines should like like this:
X.RS
X.IR "delim pattern delim command whitespace " "[" "arg" "]"
X.RE
XThe
X.I delim
Xcan be any character; if it appears in the pattern, it should be
Xpreceeded by a backslash
X.RI ( \e ).
XThe
X.I pattern
Xis an
X.RI `` ed (1)\-style''
Xregular expression, as detailed in the
X.IR regex (3L)
Xmanual page.
XThe
X.I command
Xis a single letter from the set
X.RI [ adkmq ],
Xand is described below.
XThe
X.I whitespace
Xis, obviously, any combination of spaces and tabs.
XFinally, the optional
X.I arg
Xshould be a comma\-separated list of newsgroups to be acted on by the
Xcommand.
X.PP
XThe valid commands are:
X.RS
X.nf
X.ta \w'm      'u +\w'Quiet kill    'u
Xa	Add	All newsgroups in the arg are added
Xd	Delete	The current group is deleted from the article
Xk	Kill	The article is returned, and arg is given as a contact name
Xm	Move	The current group is deleted and the arg group is added
Xq	Quiet kill	The article is quietly ignored
X.fi
X.RE
X.PP
XFor example, here is a fragment from the mapping file for a
X.I local.bboard
Xnewsgroup:
X.RS
X.nf
X.ta \w'/apartment/m   'u
X# Move seminars and talks
X/seminar/m	local.seminars,region.seminars
X/lecture/m	local.seminars,region.seminars
X# Move housing requests
X/housing/m	local.housing
X/apartment/m	local.housing
X# Kill flames
X/flame/k	the anti-flame society
X/jerk/q	@placeholder
X# Copy machine downtime announcements
X/downtime/a	local.config,news.config
X# If you want something, it's not forsale
X/want/a		local.wanted
X/want/d		@placeholder
X.fi
X.RE
XThe last two lines show how one might tweak cross\-posts, if the mapping
Xfile were for a
X.I local.wanted
Xnewsgroup.
X.SH DIAGNOSTICS
XAlmost all return values from system calls and standard I/O library routines
Xare checked.
XIf anything goes wrong, a diagnostic message is sent to standard error, where
Xit will presumably be picked up by
X.I sendmail
X(or other mail-processing program) and returned to the originator, who will
Xin turn be confused because she doesn't know anything at all about this
Xgateway program.
X.SH FILES
X.ta \w'uucp\-2\-inet  'u
Xuucp\-2\-inet	Mapping of ``Path:'' names to Internet hostnames.
X.br
Xinews	News delivery program.
X.br
XThe full paths to these files are compile\-time constants; see
X.I gate.h
Xin the source for the exact details.
X.SH "SEE ALSO"
Xgag(1L), mkmailpost(1L), news2mail(1L).
X.SH AUTHORS
XRich $alz <rsalz@bbn.com>, after
X.I nrecnews
Xby
X.br
XErik E. Fair <fair@apple.com>.
X.br
XOzan Yigit <yunexus!oz> wrote the regular\-expression routines.
END_OF_FILE
  if test 5693 -ne `wc -c <'mail2news.1'`; then
    echo shar: \"'mail2news.1'\" unpacked with wrong size!
  fi
  # end of 'mail2news.1'
fi
if test -f 'news2mail.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'news2mail.1'\"
else
  echo shar: Extracting \"'news2mail.1'\" \(5359 characters\)
  sed "s/^X//" >'news2mail.1' <<'END_OF_FILE'
X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/news2mail.1,v 1.8 91/04/01 09:43:57 rsalz Exp Locker: rsalz $
X.TH NEWS2MAIL 1 LOCAL
X.SH NAME
Xnews2mail \- feed a Usenet news article to mail
X.SH SYNOPSIS
X.B news2mail
X[
X.BI \-E var=value
X] [
X.B \-.
X]
Xlistname listaddr listadmin host [ article ]
X.SH DESCRIPTION
X.PP
X.I News2mail
Xreads a news article edits the headers to make it look like an RFC822 mail
Xmessage.
XIt feeds the results to
X.IR sendmail (8),
X.IR MMDF (8),
Xor a shell script.
XIf the ``\-.'' flag is used, then the results are sent to standard output,
Xfor debugging.
X.PP
XThe article is taken from the file specified on the command line, or read
Xfrom standard input if not specified.
X.PP
XThe ``\-E'' flag can be used to set environment variables for the delivery
Xprogram that is invoked.
XThey should be of the form ``name=value'' as in
X\&``\-E mailer=/usr/lib/pp/cmds/submit''.
X.PP
X.I News2mail
Xswallows control messages,
Xremoves all but the last three entries from the ``References'' header,
Xand merges the ``From'' and ``Path'' headers to build a single
X``From'' header for the mail message (see below).
XThe ``Date,'' ``Subject,'' ``Reply\-To,'' ``Message\-ID,'' and ``Organization''
Xheaders are passed through unchanged.
XAny other headers in the original input are removed.
X.PP
XTo ``To,'' and ``Sender'' headers and the SMTP destination envelope are set
Xaccording to the parameters specified on the command line.
XThe ``To'' header is set to be \fIlistname\fP, with \fI@host\fP appended if there
Xis no atsign in \fIlistname\fP.
XThis should contain the name of the mailing list.
XThe mail is actually sent to \fIlistaddr\fP by specifying it as the
Xrecipient in the mailer command line.
X(If \fIlistaddr\fP does not have an atsign, then \fIlistaddr@host\fP is used.)
XBy treating the ``To'' header and the destination envelope separately,
Xother members of the mailing list can properly reply to the messages that
Xpass through
X.IR news2mail .
XIn addition, \fIlistaddr\fP can be an address that sends to everyone on
Xthe list except the gateway.
XThis is an optimization, however, because
X.IR inews (8)
Xwill reject any Message-ID that it has already seen.
X.PP
XThe ``Sender'' header is set to be \fIlistadmin\fP, with \fI@host\fP
Xappended if there is no atsign in \fIlistadmin\fP.
XThese values should correspond to the maintainer of the mailing list.
XSome mailers will also automatically fill in the ``Return-Path'' header
Xwith this value.
X.PP
XThe goal of the header manipulations is to send the news article to all
Xrecipient of the mailing list, but with the headers set so that delivery
Xerrors are sent to the list maintainer for disposition.
X.PP
X.IR Mail2news
Xtries to shrink the ``Path'' header by taking note of neighboring
X\s-2UUCP\s0 hosts and scanning for other Internet hosts that it can
Xshort\-circuit to.
X.IR Uuname (1)
Xis used to check for \s-2UUCP\s0 neighbors; the file
X.I uucp\-2\-inet
Xis read to map \s-2UUCP\s0 names to Internet domain names.
XFor efficiency,
X.I mail2news
Xstores
X.IR uuname 's
Xoutput in a private file, and will only call
X.I uuname
Xif the file is older than the \s-2UUCP\s0
X.IR L.sys (5)
Xfile.
X.PP
XIn order to have
X.I sendmail
Xbelieve that the headers it has created are valid,
X.I news2mail
Xmust be able to 
X.IR setuid (2)
Xto one of
X.IR sendmail 's
Xtrusted users.
X.SH EXAMPLE
X.PP
XSuppose the following article arrives
X.IR comp.sources.unix\| :
X.RS
X.nf
XPath: news.bbn.com!uunet!rsalz
XFrom: rsalz@uunet.UU.NET (Rich Salz)
XNewsgroups: comp.sources.unix
XSubject: v10INF1:  Introduction to comp.sources.unix
XMessage\-ID: <830@uunet.UU.NET>
XDate: 10 Aug 87 21:57:17 GMT
XExpires: 10 Nov 87 22:17:17 GMT
XOrganization: UUNET Communications Services, Arlington, VA
XLines: 189
XApproved: rsalz@uunet.UU.NET
X
XThis is the first of two introductory articles about comp.sources.unix.
X\&...
X.fi
X.RE
XAlso, assume the following line is in your news sys file (see
X.IR news (5)):
X.RS
X.nf
Xgateway:world,comp.sources.unix::\e
X.ti +.5i
Xnews2mail unix\-sources rsalz unix\-sources\-request bbn.com
X.fi
X.RE
XThe
X.I news2mail
Xprogram would generate the following article and feed it to
X.IR sendmail :
X.RS
X.nf
XReceived: from USENET by bbn.com with netnews
X	for rsalz@bbn.com (unix\-sources@bbn.com);
X	contact usenet@bbn.com if you have questions.
XTo: unix\-sources@bbn.com
XDate: 10 Aug 87 21:57:17 GMT
XFrom: rsalz@uunet.uu.net (Rich Salz)
XSender: unix\-sources\-request@bbn.com
XSubject: v10INF1:  Introduction to comp.sources.unix
XMessage\-ID: <830@uunet.UU.NET>
XOrganization: UUNET Communications Services, Arlington, VA
X
XThis is the first of two introductory articles about comp.sources.unix.
X\&...
X.fi
X.RE
X.SH DIAGNOSTICS
XMost return values from I/O routines are checked; if anything goes
Xwrong, a diagnostic message is sent to a log file.
XThis file will occasionally have to be examined and trimmed.
X.SH FILES
X.ta \w'news2mail.out  'u
Xnews2mail.out	Error log (standard error)
X.br
Xuucp\-2\-inet	Mapping of ``Path'' names to Internet hostnames.
X.br
Xuuname.out	Last output from
X.IR uuname .
X.br
XThe full paths to these files are compile\-time constants; see
X.I gate.h
Xin the source for the exact details.
X.SH "SEE ALSO"
Xgag(1L), mail2news(1L).
X.SH AUTHOR
XRich $alz <rsalz@bbn.com>, after a set of scripts and a excellent manpage by
X.br
XErik E. Fair <fair@apple.com>.
X.br
XPiete Brooks <pb@computer-lab.cambridge.ac.uk> helped write the option-handling.
END_OF_FILE
  if test 5359 -ne `wc -c <'news2mail.1'`; then
    echo shar: \"'news2mail.1'\" unpacked with wrong size!
  fi
  # end of 'news2mail.1'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
  echo shar: Extracting \"'patchlevel.h'\" \(2878 characters\)
  sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X/*
X**  HEADER FILE FOR NEWS/MAIL GATEWAY CODE.
X**  $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/patchlevel.h,v 1.6 91/07/22 10:26:54 rsalz Exp $
X**
X**  $Log:	patchlevel.h,v $
X**  Revision 1.6  91/07/22  10:26:54  rsalz
X**  Add comments and #ifdef to use C News getabsdate routines.
X**  
X**  Revision 1.5  91/07/18  14:05:34  rsalz
X**  Add REQUIRE_UNIX_FROM #define.
X**  Have mail2news turn "From " into "Sender:" (Rickert).
X**  Add -a and -d flags to mail2news, document them, and reword description
X**  of the flags. (Rickert).
X**  Remove . from NETCHR list (Rickert).
X**  Update WHOAMI comment in gate.h
X**  Ran through static Saber-C analysis.
X**  Replace "I'm burnt out comment" with different words.
X**  Put X-Unparseable-Date if we can't parse date in mail2news.
X**  
X**  Revision 1.4  91/04/08  10:14:31  rsalz
X**  patch02:  TrimEnvironment was not quite right.
X**  patch02:	Neil Rickert <rickert@cs.niu.edu>
X**  patch02:  Invalid dates weren't caught in the RFC822-parser.
X**  patch02:	Neil Rickert <rickert@cs.niu.edu>
X**  patch02:  Change Makefile to be more clear about how to get getdate.o
X**  patch02:	Rich $alz <rsalz@bbn.com>
X**  
X**  Revision 1.3  91/04/01  09:43:10  rsalz
X**  patch01:  README had wrong RFC number.
X**  patch01:	Mark Moraes <moraes@cs.toronto.edu>
X**  patch01:  Not all systems have <netdb.h>.
X**  patch01:  Have TrimEnvironment set environ to empty array, not a null pointer.
X**  patch01:  	Gordon L. Burditt <gordon@sneaky.lonestar.org>
X**  patch01:  Closefile in gag.y was closing the wrong file.
X**  patch01:	Mike Pelletier <stealth@engin.umich.edu>
X**  patch01:  There is a multi-word typo in news2mail.1
X**  patch01:  	Brian Kanton <brian@ucsd.edu>
X**  patch01:  Was getting coredumps if UUNAME and L_SYS are #undef'd.
X**  patch01:	Kannan Varadhan <kannan@oar.net>
X**  patch01:  News2mail was putting out an extra space between the header name
X**  patch01:  and the colon.
X**  patch01:	Michael Gengenbach <gengenba@forwiss.uni-passau.de>
X**  patch01:  Fixed GATEWAY/GATEWAY_NAME confusion; added more explanatory
X**  patch01:  comments about what it (and FIXED_PATH) do.
X**  patch01:  Added C News and InterNetNews support to gag.  (-i is currently
X**  patch01:  about as useful to the outside world as -b, but I need it.)
X**  patch01:  Added warning that gag overwrites files and doesn't edit them,
X**  patch01:  and some other verbiage.
X**  patch01:  Described how to prevent loops and a simple-minded way that uses
X**  patch01:  one sys file entry when gatewaying many newsgroups into mail.
X**  patch01:  	Rich $alz <rsalz@bbn.com>
X**  
X**  Revision 1.2  91/02/12  15:02:40  rsalz
X**  Incorporate all known major code fixes.
X**  For release to NNTP-MANAGERS, prior to posting.
X**  I hope next release will be 2.0, reasonable patches.
X**  
X**  Revision 1.1  89/07/10  13:04:23  rsalz
X**  Initial revision
X**  
X*/
X#define PATCHLEVEL	1
END_OF_FILE
  if test 2878 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
  fi
  # end of 'patchlevel.h'
fi
if test -f 'regex.3' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'regex.3'\"
else
  echo shar: Extracting \"'regex.3'\" \(7417 characters\)
  sed "s/^X//" >'regex.3' <<'END_OF_FILE'
X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/RCS/regex.3,v 1.4 91/02/12 14:50:56 rsalz Exp $
X.TH REGEX 3 LOCAL
X.SH NAME
Xre_comp, re_exec, re_subs, re_modw, re_fail \- regular expression handling
X.SH SYNOPSIS
X.nf
X.B "char *re_comp(pat)"
X.B "char *pat;"
X.sp
X.B "re_exec(str)"
X.B "char *str;"
X.sp
X.B "re_subs(src, dst)"
X.B "char *src;"
X.B "char *dst;"
X.sp
X.B "void re_fail(msg, op)"
X.B "char *msg;"
X.B "char op;"
X.sp
X.B "void re_modw(str)"
X.B "char *str;"
X.fi
X.SH DESCRIPTION
XThese functions implement
X.IR ed (1)\-style
Xpartial regular expressions and supporting facilities.
X.PP
X.I Re_comp
Xcompiles a pattern string into an internal form (a deterministic finite\-state
Xautomaton) to be executed by
X.I re_exec
Xfor pattern matching.
X.I Re_comp
Xreturns zero if the pattern is compiled successfully, otherwise it returns an
Xerror message string.
XIf
X.I re_comp
Xis called with a null pointer or a pointer to an empty string, it returns
Xwithout changing the currently compiled regular expression.
X.PP
X.I Re_comp
Xsupports the same limited set of
X.I "regular expressions"
Xfound in
X.I ed
Xand Berkeley
X.IR regex (3)
Xroutines:
X.in +1i
X.de Ti
X.sp
X.ti -1i
X.ta 0.5i +0.5i +0.5i
X..
X.Ti
X[1]	\fIchar\fP	Matches itself, unless it is a special
Xcharacter (meta\-character): \fB. \e [ ] * + ^ $\fP
X.Ti
X[2]	\fB.\fP	Matches \fIany\fP character.
X.Ti
X[3]	\fB\e\fP	Matches the character following it, except
Xwhen followed by a digit, \fB(\fP, \fB)\fP, \fB<\fP or \fB>\fP
X(see [7], [8] and [9]).
XIt is used as an escape character for all other meta\-characters, and itself.
XWhen used in a set ([4]), it is treated as an ordinary character.
X.Ti
X[4]	\fB[\fP\fIset\fP\fB]\fP	Matches one of the characters in the set.
XIf the first character in the set is \fB^\fP, it matches a character \fInot\fP
Xin the set.
Xthe shorthand
X.IR S \- E
Xspecifies the set of characters
X.I S
Xthrough
X.IR E ,
Xinclusive.
XThe special characters \fB]\fP and \fB\-\fP have no special meaning if they
Xappear as the first characters in the set.
X.nf
X.ta \w'[a\-zA\-Z0\-9]    'u
XExamples	Match
X[a\-z]		any lowercase alpha
X[^]\-]		any char except ] and \-
X[^A\-Z]		any char except uppercase alpha
X[a\-zA\-Z0\-9]	any alphanumeric
X.fi
X.Ti
X[5]	\fB*\fP	Any regular expression form [1] to [4], followed by the
Xclosure character (*) matches zero or more matches of that form.
X.Ti
X[6]	\fB+\fP	Same as [5], except it matches one or more.
X.Ti
X[7]	\e\|( \e)	A regular expression in the form [1] to [10], enclosed
Xas \e\|(\fIform\fP\e) matches what form matches.
XThe enclosure creates a set of tags, used for [8] and for pattern
Xsubstitution in
X.IR re_subs .
XThe tagged forms are numbered starting from one.
X.Ti
X[8]	\ed	A \e followed by a digit matches whatever a previously tagged
Xregular expression ([7]) matched.
X.Ti
X[9]	\fB\e<\fP	Matches the beginning of a \fIword\fP; that is,
Xan empty string followed by a letter, digit, or _ and not preceded by a
Xletter, digit, or _ .
X.Ti
X	\fB\e>\fP	Matches the end of a \fIword\fP; that is, an empty
Xstring preceded by a letter, digit, or _ , and not followed by a letter,
Xdigit, or _ .
X.Ti
X[10]		A composite regular expression \fIxy\fP where \fIx\fP and
X\fIy\fP are in the form of [1] to [10] matches the longest match of \fIx\fP
Xfollowed by a match for \fIy\fP.
X.Ti
X[11]	\fB^ $\fP	A regular expression starting with a \fB^\fP character
Xand/or ending with a \fB$\fP character, restricts the pattern matching to the
Xbeginning of the line, and/or the end of line (anchors).
XElsewhere in the pattern, \fB^\fP and \fB$\fP are treated as ordinary
Xcharacters.
X.in -1i
X.PP
X.I Re_exec
Xexecutes the internal form produced by
X.I re_comp
Xand searches the argument string for the regular expression described
Xby the internal form.
X.I Re_exec
Xreturns 1 if the last regular expression pattern is matched within the string,
X0 if no match is found.
XIn case of an internal error (corrupted internal form),
X.I re_exec
Xcalls the user\-supplied
X.I re_fail
Xand returns 0.
X.PP
XThe strings passed to both
X.I re_comp
Xand
X.I re_exec
Xmay have trailing or embedded newline characters, but must be properly
Xterminated with a NUL.
X.PP
X.I Re_subs
Xdoes
X.IR ed \-style
Xpattern substitution, after a successful match is found by
X.I re_exec.
XThe source string parameter to
X.I re_subs
Xis copied to the destination string with the following interpretation:
X.sp
X.in +1i
X.Ti
X[1]	&	Substitute the entire matched string in the destination.
X.Ti
X[2]	\e\fId\fP	Substitute the substring matched by a tagged subpattern
Xnumbered \fId\fP, where \fId\fP is between 1 and 9, inclusive.
X.Ti
X[3]	\e\fIc\fP	Treat the next character literally, unless the
Xcharacter is a digit ([2]).
X.in -1i
X.PP
XIf the copy operation with the substitutions is successful,
X.I re_subs
Xreturns 1.
XIf the source string is corrupted, or the last call to
X.I re_exec
Xfails, it returns 0.
X.PP
X.I Re_modw
Xis used to
Xadd new characters into an internal table to
Xchange the re_exec's understanding of what
Xa \fIword\fP should look like, when matching with \fB\e<\fP and \fB\e>\fP
Xconstructs. If the string parameter is 0 or null string,
Xthe table is reset back to the default, which contains \fBA\-Z a\-z 0\-9 _\fP .
X.PP
X.I Re_fail
Xis a user\-supplied routine to handle internal errors.
X.I Re_exec
Xcalls
X.I re_fail
Xwith an error message string, and the opcode character that caused the error.
XThe default
X.I re_fail
Xroutine simply prints the message and the opcode character to the standard
Xerror and calls
X.IR exit (2).
X.SH EXAMPLES
XFor additional details, refer to the sources.
X.PP
X.RS
X.nf
X.ta \w'\e\|(foo\e)[1\-3]\e1    'u
Xfoo*.*	fo foo fooo foobar fobar foxx ...
X
Xfo[ob]a[rz]	fobar fooar fobaz fooaz
X
Xfoo\e\e+	foo\e foo\e\e foo\e\e\e  ...
X
X\e\|(foo\e)[1\-3]\e1	foo1foo foo2foo foo3foo
X(This is the same as \fIfoo[1\-3]foo\fP, but it takes less internal space.)
X
X\e\|(fo.*\e)\-\e1	foo\-foo fo\-fo fob\-fob foobar\-foobar ...
X.fi
X.RE
X.SH DIAGNOSTICS
X.I Re_comp
Xreturns one of the following strings if an error occurs:
X.RS
X.nf
X.I "No previous regular expression"
X.I "Empty closure"
X.I "Illegal closure"
X.I "Cyclical reference"
X.I "Undetermined reference"
X.I "Unmatched \e\|("
X.I "Missing ]"
X.I "Null pattern inside \e\|(\e)"
X.I "Null pattern inside \e<\e>"
X.I "Too many \e\|(\e) pairs"
X.I "Unmatched \e)"
X.fi
X.RE
X.SH REFERENCES
X.nf
X.IR "Software tools" ", Kernighan & Plauger."
X.IR "Software tools in Pascal" ", Kernighan & Plauger."
X.IR "Grep sources [rsx\-11 C dist]" ", David Conroy."
X.IR "Ed \- text editor" ", Unix Programmer's Manual."
X.IR "Advanced editing on Unix" ", B. W. Kernighan."
X.IR "RegExp sources" ", Henry Spencer."
X.fi
X.SH "HISTORY AND NOTES"
XThese routines are
X.IR Public Domain ,
Xyou can get them in source.
XThey are derived from various implementations found in the
X.I "Software Tools"
Xbooks, and David Conroy's
X.IR grep .
XThey are NOT derived from licensed/restricted software.
XFor more interesting/academic/complicated implementations, see Henry Spencer's
X.I regexp
Xroutines, or the
X.I "GNU Emacs"
Xpattern
Xmatching module.
X.PP
X.I Re_comp
Xand
X.I re_exec
Xgenerally perform at least as well as their licensed counterparts.
XIn a very few instances, they are about 10% to 15% slower.
X.SH AUTHOR
XOzan S. Yigit <yunexus!oz>.
X.br
XThis manual page was edited from the original by Rich $alz <rsalz@bbn.com>.
X.SH BUGS
XThe internal buffer for the compiled pattern is not checked for overflow;
Xthe size is currently 1024 bytes.
X.br
XThere are no doubt other bugs, too.
X.SH "SEE ALSO"
Xed(1), egrep(1), fgrep(1), grep(1)
END_OF_FILE
  if test 7417 -ne `wc -c <'regex.3'`; then
    echo shar: \"'regex.3'\" unpacked with wrong size!
  fi
  # end of 'regex.3'
fi
echo shar: End of archive 3 \(of 4\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 4 archives.
    rm -f ark[1-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
