[alt.sources] News/mail gatewaying software, ALPHA RELEASE, Part01/03

rsalz@bbn.com (Rich Salz) (02/21/89)

This code gateways between newsgroups and mailing lists.  It definitely
has bugs, use at your own risk.  Please send bug reports back to me.
For more details, see the file "README" in the first shar.

Please don't redistribute this code; wait for the "real" version in
comp.sources.unix in a month or two.

Hope to hear from you,
	/rich $alz

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 3)."
# Contents:  MANIFEST Makefile README gag.1 gate.h lex.l mail2news.1
#   misc.c mkmailpost.sh news2mail.1 news2mail.sh signoff.c str.c
#   sysexits.h test-addr test-gag uucp-2-inet
# Wrapped by rsalz@fig.bbn.com on Mon Feb 20 18:36:37 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(1556 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping list
X Makefile                   1	Guess...
X README                     1	Installation notes
X gag.1                      1	Manual page for gag
X gag.y                      3	Gateway alias generator program
X gate.h                     1	Header file, #include'd by everyone
X hdr.c                      2	Header-cracking and address re-writing routines
X lex.l                      1	Tokenizer for gag
X mail2news.1                1	Manual page for mail2news
X mail2news.c                3	Main program for mail->news gateway
X misc.c                     1	Support routines for both programs
X mkmailpost.sh              1	Turn active file into "mailpost" commands
X news2mail.1                1	Manual page for news2mail
X news2mail.c                2	Main program for news->mail gateway
X news2mail.sh               1	A script version of news2mail
X regex.3                    2	Manual page for regex
X regex.c                    3	Regular-expression matching routines
X rfc822.c                   2	Reading and writing mail and news headers
X signoff.c                  1	Program to filter out "add me" requests
X str.c                      1	String and support routines for mail2news
X sysexits.h                 1	System exit codes
X test-addr                  1	Test cases for address-rewriting routines
X test-gag                   1	Test cases for gag program
X uucp-2-inet                1	Mapping of UUCP to Internet hostnames
END_OF_FILE
if test 1556 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(2130 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X##
X##  Makefile for mail/news gateway programs.
X##  $Header: Makefile,v 1.4 88/11/15 16:12:33 rsalz Exp $
X##
XSHELL	= /bin/sh
X
X##  Edit appropriately.  See gate.h before you touch UUCP_INET.
X2_11	= /nfs/papaya/source/news2.11/src
XUUCP_INET=	/usr/lib/news/.admin/uucp-2-inet
XDESTDIR	= /usr/uucp/bin
XOPT	= -g
X#OPT	= -O
XDEFS	=
XCFLAGS	= $(OPT) $(DEFS)
XLOADF	=
X#LOADF	= -s
X
X##  News files, copied over from $(2_11).
XGETDATE	= getdate.o
X
X##  Gag, the gateway alias generator.
XG_SRCS	= gag.c lex.c misc.c
XG_OBJS	= gag.o lex.o misc.o
X
X##  Mail2News, the mail into news part of the gateway.
XM_SRCS	= misc.c regex.c str.c hdr.c mail2news.c rfc822.c
XM_OBJS	= misc.o regex.o str.o hdr.o mail2news.o rfc822.o $(GETDATE)
X
X##  News2Mail, the news into mail part of the gateway.
XN_SRCS	= misc.c news2mail.c
XN_OBJS	= misc.o news2mail.o
X
X
Xall:			gag mail2news news2mail tags lint
X
Xinstall:		all
X	@echo "Install as directed in the README file."
X#	@rm -f $(DESTDIR)/gag $(DESTDIR)/mail2news $(DESTDIR)/news2mail
X#	cp gag mail2news news2mail $(DESTDIR)/.
X#	cp uucp-2-inet $(UUCP_INET)
X
Xclean:
X	rm -f gag mail2news news2mail *.o
X	rm -f tags lint.? core gag.c gag.h lex.c
X#	rm -f Part0?
X
Xtags:			$(N_SRCS) $(M_SRCS)
X	ctags -tw $(N_SRCS) $(M_SRCS) $(G_SRCS) gate.h
X
Xlint:			lint.g lint.m lint.n
X
X
X##
Xmail2news:		$(M_OBJS)
X	@rm -f mail2news
X	$(CC) $(CFLAGS) $(LOADF) -o mail2news $(M_OBJS)
X
Xnews2mail:		$(N_OBJS)
X	@rm -f news2mail
X	$(CC) $(CFLAGS) $(LOADF) -o news2mail $(N_OBJS)
X
Xgag:			$(G_OBJS)
X	@rm -f gag
X	$(CC) $(CFLAGS) $(LOADF) -o gag $(G_OBJS)
X
X
X##
X$(G_OBJS) $(M_OBJS) $(N_OBJS):	gate.h
X
X
X##
Xlint.g:			gag
X	exec lint -a    -h $(DEFS) $(G_SRCS) >lint.g
Xlint.m:			mail2news
X	exec lint -a -b -h $(DEFS) $(M_SRCS) >lint.m
Xlint.n:			news2mail
X	exec lint -a -b -h $(DEFS) $(N_SRCS) >lint.n
X
X
X##  Keep intermediate files around.
Xlex.o:			lex.c
Xgag.o:			gag.c
Xgag.c:			gag.y
X	@rm -f gag.c gag.h
X	yacc -d gag.y
X	@mv y.tab.c gag.c
X	@mv y.tab.h gag.h
X
X
X##
Xshar:
X	@rm -f Part0?
X	makekit -m
X	@rm -f MANIFEST.BAK
X	@-chmod 444 Part0?
X
X
X##  Get the date parser from 2.11 news.
X$(GETDATE):
X	@rm -f $(GETDATE)
X	cd $(2_11) ; make $(GETDATE)
X	cp $(2_11)/$(GETDATE) .
END_OF_FILE
if test 2130 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(3668 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X
XIntroduction
X------------
XThis kit provides two programs for "linking" RFC822 Mail messages and
XRFC1076 Usenet News articles.  Each half of the conversion is handled by a
Xdifferent program, mail2news or news2mail.
X
XWith these programs and the right set of mail aliases and news sys and
Xactive file entries, it is possible to build any set of moderated,
Xunmoderated, one-way, or bi-directional gateways between any set of news
Xand mail groups and lists that your little heart desires.
X
XIf you run a small site with only a couple of machines and a few
Xmostly-local mailing lists, you probably don't want to bother setting this
Xstuff up.  Instead, either convert everything directly to News, or set up
Xlocal moderated groups.  On the other hand, if you provide a large-scale
Xgateway service to the ARPA Internet (e.g., UCB) or you're at a large
Xsite where you can't control everything so tightly (e.g., BBN), then this
Xstuff is for you.  News, especially with the proliferation of NNTP
X(RFC977) and related clients, is generally more efficient than mail, for
Xdisk space, CPU cycles, and network usage.
X
XThe programs work best with sendmail or MMDF and News 2.11.8 or later.
XWe've only run the programs on BSD hosts, but a start toward a System V
Xport has been made.  Who knows, it might even work right now.
X
XThe original version of this package were written by Erik in xxxxx, as a
Xcollection of scripts and programs.  Credit him for the initial design, and
Xaccomodating that to the reality of the networks involved.  In the fall of
X1988, Rich converted everything to C and rewrote the existing programs for
Xesthetics (boo) and efficiency (yeah).  Credit him for the documentation,
Xand any bugs you find.  The regular expressions routines (regex.c and
Xregex.3) were written by Ozan Yigit <yunexus!oz>, and published in Volume 6
Xof comp.sources.unix.  Dan Tappan <tappan@bbn.com> was suckered into running
Xthis stuff at BBN and made a "final" set of fixes.  The package seems
Xpretty solid now, and is processing a few hundred messages a week at BBN.
X
X
XInstallation
X------------
XMail2news uses the date parser from the 2.11 netnews distribution; edit
Xthe Makefile to point to where you keep your source.  There are a
Xhandful of other parameters, all at the beginning of the gate.h header
Xfile.  If should be obvious what values you'll need to put in there.
X
XBy default, the install target in the Makefile is a no-op.  This is
Xmainly due to history, but see the caveat about the UUCP_INET macro
Xin the Makefile.
X
XOnce you've gotten the programs to compile, you'll want to play around
Xwith the alias generator to build stuff.  Erik has a set of M4 macros and
XMakefile that you can use if you prefer.  The hard part is in setting up
Xthe right aliases and news entries to get the system up and working.
X
XAt this point I (R$) should be telling you how to set up the different
Xtypes of groups, but I'm too burnt out on this to bother.  If someone has
Xsome words here to get me started, I'd appreciate it.
X
XFlaws
X-----
XCross-posting and multiple mail recipients are handled very well.
XCross-post means each person mailing list gets a separate message.
XDoes multi-cast fix this, perhaps?
X
XSomeone sending mail to lista and listb means the message only goes
Xinto news.list.a, or news.list.b, depending on which gateway alias
Xgets it first.  Not cool.  Can it be fixed?  Hack, to avoid
Xlosing messages, is to munge the message-id to put the newsgroup
Xname in there.
X
X
XFinally
X-------
XPlease send any comments, kudo's, suggestions, or brick-bats to both of us:
X	Erik Fair				Rich $alz
X	fair@ucbarpa.berkely.edu		rsalz@bbn.com
X
X	$Header: README,v 1.5 88/08/10 12:24:01 rsalz Locked $
END_OF_FILE
if test 3668 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'gag.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'gag.1'\"
else
echo shar: Extracting \"'gag.1'\" \(1121 characters\)
sed "s/^X//" >'gag.1' <<'END_OF_FILE'
X.TH GAG 1 LOCAL
X\" $Header$
X.SH NAME
Xgag \- Gateway alias generator
X.SH SYNOPSIS
X.B gag
X[
X.B \-m
X] [
X.BI \-d directory
X] [
X.B \-s
X] [
X.B \-b
X] [
X.B \-n
X] [
X.B \-p
X] [
Xfile
X]
X.SH DESCRIPTION
X.I Gag
Xis a program that reads a control file and builds entries for
X.IR sendmail (8),
X.IR MMDF (8),
Xand
X.IR Usenet (1)
Xaliases, as an aide to maintaining a mail/news gateway operation.
X.TP
X.B "\-p"
XCreate "post-new-group" aliases for all news.groups
X.SM SENDMAIL
X.TP
X.B "\-s"
XDo sendmail-style aliases, aliases.sm
X.SM MMDF
X.TP
X.B "\-m"
XDo mmdf-style aliases, aliases.mmdf
X.TP
X.BI "\-d" dir
XDirectory for output files
X.SM NETNEWS
X.TP
X.B "\-n"
XCreate news/sys file entries.
X.TP
X.B "\-b"
XAllow bogus newsgroups.
X.SH "BUGS AND CAVEATS"
XThe handling of strings isn't consistant with C, and there are definitely
Xsome memory leaks associated with them.
X.br
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), news2mail(1L).
X.SH AUTHOR
XRich $alz <rsalz@bbn.com>.
END_OF_FILE
if test 1121 -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'\" \(5640 characters\)
sed "s/^X//" >'gate.h' <<'END_OF_FILE'
X/*
X**  HEADER FILE FOR NEWS/MAIL GATEWAY CODE.
X**  $Header: gate.h,v 1.6 88/04/08 15:45:06 rsalz Exp $
X*/
X
X
X/*
X**  START OF CONFIGURATION SECTION
X*/
X
X
X/* Paths to some parts of your netnews installation.  Required. */
X#define INEWS		"/usr/lib/news/inews"
X#define ACTIVE		"/usr/lib/news/active"
X#define NGDELIM		','
X
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/* 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 * Required, but you can set IN_ONEPLACE to /dev/null to disable it. */
X/*efine IN_ONEPLACE	"/dev/null"		/* .. */
X/*efine IN_SPOOLDIR	"/usr/spool/news"	/* .. */
X#define	IN_CMDDIR	"/usr/lib/news/.admin"	/* .. */
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/*efine SENDMAIL	"/usr/lib/sendmail"	/* .. */
X#define	SUBMIT		"/usr/mmdf/lib/submit"	/* .. */
X/*efine TRUSTED		1			/* .. */
X
X
X/* I love how we all speak the same language. */
X#define CATCHER		int		/* Type of a signal-catcher	*/
X/*efine CATCHER		void		/* .. */
X#define IDX		index		/* .. */
X#define RDX		rindex		/* .. */
X/*efine IDX		strchr		/* .. */
X/*efine RDX		strrchr		/* .. */
Xtypedef int		*align_t;	/* Worst-case alignment, for lint */
X#define CHARSTAR_SPRINTF		/* Need extern char *sprintf();	*/
X#define	HAVE_NETDB			/* Have <netdb.h> and friends?	*/
X#define HAVE_SYSEXITS			/* Have <sysexits.h>?		*/
X#define HAVE_SYSWAIT			/* Have <sys/wait.h>?		*/
X#define HAVE_TIMEB			/* Have <sys/timeb.h>?		*/
X
X/* Artificial site to stick into the Path: line, optional. */
X#define	GATEWAY_NAME	"gateway"
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 DEBUG
X#define STATIC		static
X#ifdef	lint
X#undef	RCSID
X#else
X#define RCSID
X#endif	/* lint */
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#ifdef	HAVE_SYSEXITS
X#include <sysexits.h>
X#else
X#include "sysexits.h"
X#endif	/* HAVE_SYSEXITS */
X
X
Xtypedef struct {
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} HBUF;
X
X
X/* String and memory manipulators. */
X#define APPEND(p, t)	strlen(strcpy((p), (t)))
X#define NEW(T, c)	(T *)MyAlloc((c) * sizeof (T))
X#define COPY(s)		((s) ? strcpy(NEW(char, strlen((s)) + 1), (s)) : NULL)
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
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) == '@' || (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#ifdef	lint
X#undef	putc
X#undef	putchar
X#endif	/* 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	 *Estring();
Xextern char	 *MakeLower();
Xextern char	 *re_comp();
Xextern char	 *HackHeader();
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	*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#ifdef	CHARSTAR_SPRINTF
Xextern char	*sprintf();
X#endif	/* CHARSTAR_SPRINTF */
END_OF_FILE
if test 5640 -ne `wc -c <'gate.h'`; then
    echo shar: \"'gate.h'\" unpacked with wrong size!
fi
# end of 'gate.h'
fi
if test -f 'lex.l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'lex.l'\"
else
echo shar: Extracting \"'lex.l'\" \(3594 characters\)
sed "s/^X//" >'lex.l' <<'END_OF_FILE'
X/*
X**  Lexical analyzer for the conduit language.  We have our own FSA
X**  for quotes and comments because it's much smaller and quicker that
X**  way.
X*/
X%{
X#include "gate.h"
X#include "gag.h"
X
X/* State of our two automata. */
Xtypedef enum {
X    S_EAT, S_STAR, S_NORMAL, S_END
X} STATE;
X
X/* Key-value pair. */
Xtypedef struct {
X    char	*name;
X    int		 value;
X} PAIR;
X
Xchar		 yyfilename[SM_SIZE];
X
X/* List of GAG's keywords. */
XSTATIC PAIR	Keywords[] = {
X    {	"command",		COMMAND		},
X    {	"default",		DEFAULT		},
X    {	"directory",		DIRECTORY	},
X    {	"distributions",	DISTRIBUTIONS	},
X    {	"do",			DO		},
X    {	"dotify",		DOTIFY		},
X    {	"flags",		FLAGS		},
X    {	"inews",		INEWSt		},
X    {	"mail2news",		MAIL2NEWS	},
X    {	"mailcontact",		MAILCONTACT	},
X    {	"mailhost",		MAILHOST	},
X    {	"mailinglist",		MAILINGLIST	},
X    {	"mailpost",		MAILPOST	},
X    {	"moderator",		MODERATOR	},
X    {	"news2mail",		NEWS2MAIL	},
X    {	"no",			NO		},
X    {	"onwer",		OWNER		},
X    {	"organization",		ORGANIZATION	},
X    {	"owner",		OWNER		},
X    {	"request_address",	REQUESTADDR	},
X    {	"site",			SITE		},
X    {	"user",			USER		},
X    {	NULL,			0		}
X};
X
X%}
X
X%%
X
X[-+0-9A-Za-z_.]+	{
X		    /* A simple ID or keyword. */
X		    register PAIR	*p;
X
X		    /* Keyword? */
X		    for (p = Keywords; p->name; p++)
X			if (EQ(p->name, yytext))
X			    return(p->value);
X		    yylval.String = COPY(yytext);
X		    return(ID);
X		}
X
X^#[ \t]+[0-9]+[ \t]+"[^\n]+"[^\n]*$	{
X		    /* C pre-processor control line. */
X		    register char	*p;
X		    char		*namep;
X
X		    for (p = yytext; *p && !isdigit(*p); p++)
X			;
X		    for (yylineno = atoi(p); *p && *p != '"'; p++)
X			;
X		    for (namep = p; *++p && *p != '"'; p++)
X			;
X		    *p = '\0';
X		    (void)strncpy(yyfilename, namep, sizeof yyfilename - 1);
X		    yyfilename[sizeof yyfilename - 1] = '\0';
X		}
X
X\"		{
X		    /* Quoted string. */
X		    register char	*p;
X		    register STATE	 S;
X		    register int	 c;
X		    register int	 warned;
X		    char		 buff[SM_SIZE];
X
X		    for (p = buff, S = S_NORMAL, warned = FALSE; ; )
X			switch (c = input()) {
X			default:
X			    S = S_NORMAL;
X    add_char:
X			    /* Leave space for terminating \0. */
X			    if (p < &buff[sizeof buff - 2])
X				*p++ = c;
X			    else if (!warned) {
X				warned = TRUE;
X				*p = '\0';
X				yyerror("String too long");
X			    }
X			    break;
X			case '\n':
X			    /* Eat leading whitespace. */
X			    S = S_EAT;
X			    goto add_char;
X			case ' ':
X			case '\t':
X			    if (S != S_EAT)
X				goto add_char;
X			    break;
X			case '"':
X			    if ((c = input()) == '"') {
X				/* The sequence "" is one single quote. */
X				S = S_NORMAL;
X				goto add_char;
X			    }
X			    unput(c);
X			    /* FALLTHROUGH */
X			case '\0':
X			    /* Terminate the string. */
X			    *p = '\0';
X			    yylval.String = COPY(buff);
X			    return(ID);
X			}
X		}
X
X"/*"	        {
X		    /* Comment. */
X		    register STATE	 S;
X
X		    for (S = S_NORMAL; S != S_END; )
X			switch (input()) {
X			case '/':
X			    if (S == S_STAR) {
X				S = S_END;
X				break;
X			    }
X			    /* FALLTHROUGH */
X			default:
X			    S = S_NORMAL;
X			    break;
X			case '\0':
X			    S = S_END;
X			    break;
X			case '*':
X			    S = S_STAR;
X			    break;
X			}
X		}
X
X[ \t\n]		{
X		    /* Tasty whitespace. */
X#ifdef	lint
X		    /* I am compulsive about lint natterings. */
X		    yytext[0] = yyinput();
X		    yyoutput(yytext[0]);
X		    yyunput(yytext[0]);
X		    REJECT;
X#endif	/* lint */
X		}
X
X.		{
X		    /* Random special character. */
X		    return(*yytext);
X		}
X
X%%
X
X
X/*
X**  Called by lex at end-of-stream.  Return one if no more input.
X*/
Xint
Xyywrap()
X{
X    return(1);
X}
END_OF_FILE
if test 3594 -ne `wc -c <'lex.l'`; then
    echo shar: \"'lex.l'\" unpacked with wrong size!
fi
# end of 'lex.l'
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'\" \(4950 characters\)
sed "s/^X//" >'mail2news.1' <<'END_OF_FILE'
X.TH MAIL2NEWS 1 LOCAL
X\" $Header: mail2news.1,v 1.6 88/08/10 12:24:11 rsalz Locked $
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 \-n newsgroups
X] [
X.BI \-o organization
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(these flags are recognized by
X.I mail2news
Xbefore being passed on to
X.IR inews ).
X.PP
XIf debugging is enabled and the ``\-.'' flag is specified, the (modified)
Xarticle is sent to the standard output, rather than feed into
X.IR inews .
X.PP
XAs a concession to
X.IR sendmail (8)
Xalias processing the argument to the ``\-o'' flag is handled specially.
XSince
X.I sendmail
Xdoes not preserve case in the mail headers, a period in the argument means
Xthat the following character should be converted to uppercase; two periods
Xmean 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 .u...c...b.. .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 U.C.B. 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
X.IR MMDF )
Xand returned to the originator, who will in turn be confused because she
Xdoesn't know anything at all about this gateway 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), news2mail(1L).
X.SH AUTHORS
XErik E. Fair <fair@ucbarpa.berkeley.edu>,
X.br
XRich $alz <rsalz@bbn.com>.
X.br
XOzan Yigit <yunexus!oz> wrote the regular\-expression routines.
END_OF_FILE
if test 4950 -ne `wc -c <'mail2news.1'`; then
    echo shar: \"'mail2news.1'\" unpacked with wrong size!
fi
# end of 'mail2news.1'
fi
if test -f 'misc.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'misc.c'\"
else
echo shar: Extracting \"'misc.c'\" \(2873 characters\)
sed "s/^X//" >'misc.c' <<'END_OF_FILE'
X/*
X**  Miscellaneous routines.
X*/
X#include "gate.h"
X#ifdef	RCSID
Xstatic char RCS[] =
X	"$Header$";
X#endif	/* RCSID */
X
X
X/*
X**  Allocate memory.
X*/
Xalign_t
XMyAlloc(i)
X    int			 i;
X{
X    align_t		 p;
X
X    if ((p = (align_t)malloc((unsigned int)i)) == NULL) {
X	Fprintf(stderr, "%s:  Could not allocate %d bytes: %s\n",
X		Pname, i, Estring());
X	exit(EX_OSERR);
X    }
X    return(p);
X}
X
X
X/*
X**  Return a printable representation of errno.
X*/
Xchar *
XEstring()
X{
X    static char		 buff[20];
X
X    if (errno >= 0 && errno < sys_nerr)
X	return(sys_errlist[errno]);
X    Sprintf(buff, "Error code %d", errno);
X    return(buff);
X}
X
X
X/*
X**  Free up something that Split() made.
X*/
Xvoid
XSplitFree(p)
X    char	***p;
X{
X    if (p && *p) {
X	free((*p)[0]);
X	free((char *)*p);
X	*p = NULL;
X    }
X}
X
X
X/*
X**  This is an AWK-style split routine.  If the split character is NULL,
X**  we split on space or tab and eat long stretches of same (that is, no
X**  null fields will result).  Returns number of fields made.
X*/
Xint
XSplit(s, p, c)
X    register char	  *s;
X    char		***p;
X    register char	   c;
X{
X    register char	  *cp;
X    register int	   blank;
X    register int	   n;
X    register int	   i;
X
X    if (s == NULL || *s == '\0') {
X	Fprintf(stderr, "%s:  Someone was a pinhead!\n", Pname);
X	abort();
X    }
X
X    i = strlen(s) + 1;
X    cp = NEW(char, i);
X    /* This is too much -- we'll realloc what we really need later. */
X    i *= sizeof (char*);
X    *p = NEW(char*, i);
X
X    if (c == '\0') {
X	/* Eat multiple whitespace characters. */
X	for (blank = TRUE, n = 0; *s; s++)
X	    if (WHITE(*s)) {
X		if (!blank)
X		    *cp++ = '\0';
X		blank = TRUE;
X	    }
X	    else {
X		if (blank)
X		    (*p)[n++] = cp;
X		*cp++ = *s;
X		blank = FALSE;
X	    }
X
X	if (n == 0) {
X	    (*p)[0] = cp;
X	    SplitFree(p);
X	    return(0);
X	}
X    }
X    else
X	/* Normal case: find all occurrences of "c" and null them as field
X	 * terminators; add new string starts to the array of pointers to
X	 * strings. */
X	for ((*p)[0] = cp, n = 1; *s; s++)
X	    if (*s == c) {
X		*cp++ = '\0';
X		(*p)[n++] = cp;
X	    }
X	    else
X		*cp++ = *s;
X
X    /* Free up the excess space. */
X    *p = (char **)REALLOC(*p, (n + 1) * sizeof (char *));
X    (*p)[n] = NULL;
X    return(n);
X}
X
X
X
X/*
X**  Read in a file of lines, dump it into an array of strings.
X*/
Xchar **
XReadFile(Name)
X    char		 *Name;
X{
X    register FILE	 *F;
X    register char	 *p;
X    register char	**v;
X    register int	  i;
X    char		**value;
X    char		  buff[SM_SIZE];
X
X    /* Open file, count number of lines therein. */
X    if ((F = fopen(Name, "r")) == NULL) {
X	perror(Name);
X	exit(EX_OSFILE);
X    }
X    for (i = 1; fgets(buff, sizeof buff, F); i++)
X	;
X
X    rewind(F);
X    for (v = value = NEW(char*, i); fgets(buff, sizeof buff, F); ) {
X	if (p = IDX(buff, '\n'))
X	    *p = '\0';
X	if (buff[0] && buff[0] != '#')
X	    *v++ = COPY(buff);
X    }
X
X    *v = NULL;
X    return(value);
X}
END_OF_FILE
if test 2873 -ne `wc -c <'misc.c'`; then
    echo shar: \"'misc.c'\" unpacked with wrong size!
fi
# end of 'misc.c'
fi
if test -f 'mkmailpost.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mkmailpost.sh'\"
else
echo shar: Extracting \"'mkmailpost.sh'\" \(886 characters\)
sed "s/^X//" >'mkmailpost.sh' <<'END_OF_FILE'
X#! /bin/sh
X##  $Header$
X##  Script to make a set of "mailpost" commands for all groups in
X##  the news active file.
X##  Usage:
X##	makemailpost [news active file [mail2newspath] ]
X##
X
Xcase $# in
X[012])
X    ;;
X*)
X    echo "Usage: `basename $0` [activefile [mail2newspath] ]" 1>&2
X    exit 1
X    ;;
Xesac
X
XACTIVE=${2-/usr/lib/news/active}
Xif [ ! -f ${ACTIVE} ] ; then
X    echo "`basename $0`:  Can't read input ${ACTIVE}." 1>&2
X    exit 1
Xfi
X
X##  Write the prolog.
Xecho "/*"
Xecho "**  Generated from ${ACTIVE}"
Xecho "**  by `whoami`"
Xecho "**  on `date`"
Xecho "*/"
Xif [ "$3" != "" ] ; then
X    echo 'default mail2news "'$3'";'
Xfi
X
X##  Create the sed temporary file and run it
Xtrap "rm -f /tmp/mmp$$ ; exit 1" 1 2 3 15
Xcat >/tmp/mmp$$ <<\EOF
X/m$/d
Xs/ .*$//
X/^to/d
X/^control/d
X/^junk/d
X/\<test\>/d
X/\<announce\>/d
Xs/^.*$/mailpost &;/
XEOF
Xsed -f /tmp/mmp$$ <${ACTIVE} | sort
X
Xrm -f /tmp/mmp$$
END_OF_FILE
if test 886 -ne `wc -c <'mkmailpost.sh'`; then
    echo shar: \"'mkmailpost.sh'\" unpacked with wrong size!
fi
chmod +x 'mkmailpost.sh'
# end of 'mkmailpost.sh'
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'\" \(3513 characters\)
sed "s/^X//" >'news2mail.1' <<'END_OF_FILE'
X.TH NEWS2MAIL 1 LOCAL
X\" $Header: news2mail.1,v 1.4 87/09/09 17:02:41 rsalz Release1 $
X.SH NAME
Xnews2mail \- feed a Usenet news article to mail
X.SH SYNOPSIS
X.B news2mail
Xlistname contactaddr requestname 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, and feeds it to
X.IR sendmail (8).
XIn particular,
X.I news2mail
Xswallows control messages,
Xremoves all but the last three entries from the ``References'' line,
Xand merges the ``From'' and ``Path'' header lines to build a single
X``From'' line for the mail message.
XThe ``Date,'' ``Subject,'' ``Reply\-To,'' ``Message\-ID,'' and ``Organization''
Xline are passed through unchanged.
XAll other headers are removed.
X.PP
XThe article is taken from the file specified on the command line, or read
Xfrom standard input if not specified.
X.PP
X.IR Mail2news
Xtries to shrink the path by taking note of neighboring \s-2UUCP\s0 hosts and
Xscanning for other Internet hosts that it can short\-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
X.I "This needs more work, cf. Erik Fair's documentation for 'gateway'"
X.PP
XSuppose the following article arrives
X.IR comp.sources.unix\| :
X.RS
X.nf
XPath: bbn!husc6!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: rs@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 have to occasionally be examined and trimmed down.
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 AUTHORS
XErik E. Fair <fair@ucbarpa.berkeley.edu>,
X.br
XRich $alz <rsalz@bbn.com>.
END_OF_FILE
if test 3513 -ne `wc -c <'news2mail.1'`; then
    echo shar: \"'news2mail.1'\" unpacked with wrong size!
fi
# end of 'news2mail.1'
fi
if test -f 'news2mail.sh' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'news2mail.sh'\"
else
echo shar: Extracting \"'news2mail.sh'\" \(1919 characters\)
sed "s/^X//" >'news2mail.sh' <<'END_OF_FILE'
X#! /bin/sh
X##  $Header: news2mail.sh,v 1.1 88/11/16 15:02:52 rsalz Exp $
X##  A short, mostly-awk, script to send news on stdin out as mail.
X##  Usage:  news2mail <address>
X##  Written by John Quatermain, <jsq@longway.com> <<--SPELLING????
X##  Light editing by Rich $alz <rsalz@bbn.com>.
XPATH=/usr/local:/usr/ucb:/bin:/usr/bin ; export PATH
X
Xcase $1 in
X"")
X    echo "Usage:  `basename $0` address"
X    exit 1
X    ;;
X"-")
X    TO="cat -u"
X    ;;
X*)
X    TO="/bin/mail $1"
X    ;;
Xesac
X
Xawk '
XBEGIN {
X	header = 1;
X	date = "";
X}
Xheader == 1 && /^$/ {
X	# End of headers; print dates.
X	header = 0;
X	if (pdate != "" && date ~ /GMT/ && pdate !~ /GMT/) {
X		print "Date: "pdate;
X		print "Posted-Date: "date;
X	} else {
X		if (date != "")
X			print "Date: "date;
X		if (pdate != "")
X			print "Posted-Date: "pdate;
X	}
X}
Xheader == 0 {
X	print $0;
X	next;
X}
X$1 == "Relay-Version:"		{ next; }
X$1 == "Posting-Version:"	{ next; }
X$1 == "Path:"			{ next; }
X$1 == "From"			{ next; }
X$1 == "Date-Received:"		{ next; }
X$1 == "Received-Date:"		{ next; }
X#$1 == "Newsgroups:"		{ next; }
X#$1 == "Organization:"		{ next; }
X$1 == "Approved:"		{ next; }
X$1 == "Lines:"			{ next; }
X$1 == "Date:" {
X	date = $2;
X	for (i = 3; i <= NF; i++)
X		date = date " " $i;
X	next;
X}
X$1 == "Posted-Date:" {
X	pdate = $2;
X	for (i = 3; i <= NF; i++)
X		pdate = pdate " " $i;
X	next;
X}
X$1 == "From:" {
X	address=$2;
X	name = "";
X	surround = 0;
X	for (f = 3; f <= NF; f++) {
X		if ($f ~ /,/)
X			surround=1;
X		if (split ($f, parts, "(") > 1)
X			it = parts[2];
X		else
X			it = $f;
X		if (split ($f, parts, ")") > 1)
X			it = parts[1];
X		if (name == "")
X			name = it;
X		else
X			name = name " " it;
X	}
X	if (address ~ /.UUCP$/) {
X		split(address, parts, "@");
X		address = sprintf ("%s%%%s@%s", \
X			parts[1], parts[2], "'`hostname`'");
X	}
X	if (surround != 0)
X		printf ("From: %s (%s)\n", address, name);
X	else
X		printf ("From: %s <%s>\n", name, address);
X	next;
X}
X{
X	print $0;
X}' | eval $TO
END_OF_FILE
if test 1919 -ne `wc -c <'news2mail.sh'`; then
    echo shar: \"'news2mail.sh'\" unpacked with wrong size!
fi
chmod +x 'news2mail.sh'
# end of 'news2mail.sh'
fi
if test -f 'signoff.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signoff.c'\"
else
echo shar: Extracting \"'signoff.c'\" \(3326 characters\)
sed "s/^X//" >'signoff.c' <<'END_OF_FILE'
X/*
X**  SIGNOFF
X**  Quickie hack to see of a mail message is a "please drop me" request.
X**  Exit's with status 0 if it is a regular message, or 1 if it appears to
X**  be a one of this administrative requests that annoy everyone when
X**  they're sent to the whole list.  Optional first argument is the name
X**  of the input file, or stdin is read if none is given.
X**
X**  Original program written by Russ Nelson, <nelson@clutx.clarkson.edu>.
X**  Severely hacked on by Rich $alz, <rsalz@bbn.com>.  This program is
X**  basically incorporated into mail2news; it's pulled out here for
X**  demonstration.
X**
X**  For example, here is a script that could be used as a wrapper around
X**  the mail2news program:
X**	#! /bin/sh
X**	cat >/tmp/signoff$$
X**	if /usr/lib/news/signoff </tmp/signoff$$ ; then
X**	    /usr/ucb/Mail -s "Sign on/off request" usenet </tmp/signoff$$
X**	else
X**	    /usr/lib/news/mail2news.real </tmp/signoff$$
X**	fi
X**	exec rm /tmp/signoff$$
X**
X**  Russ ran the following test for a month and got only one real message
X**  (a gnu.gcc bug report) treated as a subscription request.  He doesn't
X**  know how many subs made it out to the net, tho:  that would entail
X**  reading ALL netnews articles -- yuck!
X**
X**  Put the following line in your news sys file:
X**	allmail:all::/usr/lib/news/ts
X**  here is the "ts" script:
X**	#! /bin/sh
X**	cat >/tmp/ts.$$
X**	/usr/lib/news/signoff </tmp/ts.$$ || mail usenet </tmp/ts.$$
X**	exec rm /tmp/ts.$$
X**
X**  Perhaps a better way to test is to make the test less conservative,
X**  and see what "real" articles get caught, and make adjustments then?
X**  Comments solicited.
X*/
X#include <stdio.h>
X#include <ctype.h>
X
X#define EQ(a, b)		(strcmp((a), (b)) == 0)
X
X
Xmain(ac, av)
X    int			 ac;
X    char		*av[];
X{
X    register FILE	*F;
X    register char	*p;
X    register int	 c;
X    register int	 drop_or_add;
X    register int	 from_or_to;
X    register int	 mail_word;
X    register int	 count;
X    char		 word[128];
X
X    /* Get input. */
X    if (ac < 2)
X	F = stdin;
X    else if ((F = fopen(av[1], "r")) == NULL) {
X	(void)fprintf(stderr, "%s: cannot open %s\n", av[0], av[1]);
X	exit(1);
X    }
X
X    /* Skip headers by waiting for the first blank line. */
X    while (fgets(word, sizeof word, F) && *word != '\n')
X	    ;
X
X    /* Clear counts. */
X    drop_or_add = 0;
X    from_or_to = 0;
X    mail_word = 0;
X    count = 0;
X
X    /* Read input a word at a time. */
X    for (p = word; (c = getc(F)) != EOF; ) {
X	if (!isalpha(c)) {
X	    *p = '\0';
X	    if (p > word)
X		count++;
X	    p = word;
X
X	    if (EQ(word, "remove") || EQ(word, "drop") || EQ(word, "off")
X	     || EQ(word, "subscribe") || EQ(word, "get") || EQ(word, "add"))
X		drop_or_add++;
X	    else if (EQ(word, "from") || EQ(word, "to"))
X		from_or_to++;
X	    else if (EQ(word, "mail") || EQ(word, "mailing")
X		  || EQ(word, "list") || EQ(word, "dl"))
X		mail_word++;
X	}
X	else if (p < &word[sizeof word - 1])
X	    *p++ = isupper(c) ? tolower(c) : c;
X    }
X
X    (void)fclose(F);
X
X    /* Use fancy-shmancy AI techniques to determine what the message is. */
X    c = count < 25 && drop_or_add && from_or_to && mail_word;
X
X#ifdef	DEBUG
X    printf("%s: %d words, %d drop, %d mail --> %s\n",
X	   av[1] ? av[1] : "<stdin>",
X	   count, drop_or_add, mail_word,
X	   c ? "yes" : "no");
X#endif	/* DEBUG */
X
X    /* Exit appropriately. */
X    exit(c);
X}
END_OF_FILE
if test 3326 -ne `wc -c <'signoff.c'`; then
    echo shar: \"'signoff.c'\" unpacked with wrong size!
fi
# end of 'signoff.c'
fi
if test -f 'str.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'str.c'\"
else
echo shar: Extracting \"'str.c'\" \(730 characters\)
sed "s/^X//" >'str.c' <<'END_OF_FILE'
X/*
X**  String-related routines for mail2news.
X*/
X#include "gate.h"
X#ifdef	RCSID
Xstatic char RCS[] =
X	"$Header$";
X#endif	/* RCSID */
X
X
X/*
X**  For Ozan Yigit's public domain regex.
X*/
X/* ARGSUSED */
Xvoid
Xre_fail(text, arg)
X    char	*text;
X    int		 arg;
X{
X}
X
X
X/*
X**  Convert string to lower case.
X*/
Xchar *
XMakeLower(s)
X    register char	*s;
X{
X    register char	*p;
X
X    if (s)
X	for (p = s; *p; p++)
X	    if (isupper(*p))
X		*p = tolower(*p);
X    return(s);
X}
X
X
X/*
X**  Free up something that ReadFile made.  This doesn't belong here,
X**  but news2mail doesn't need it, so we don't want it in misc.c.
X*/
Xvoid
XFreeFile(V)
X    char		**V;
X{
X    register char	**p;
X
X    if (p = V) {
X	while (*p)
X	    free(*p++);
X	free((char *)V);
X    }
X}
END_OF_FILE
if test 730 -ne `wc -c <'str.c'`; then
    echo shar: \"'str.c'\" unpacked with wrong size!
fi
# end of 'str.c'
fi
if test -f 'sysexits.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sysexits.h'\"
else
echo shar: Extracting \"'sysexits.h'\" \(4568 characters\)
sed "s/^X//" >'sysexits.h' <<'END_OF_FILE'
X/*
X * Copyright (c) 1987 Regents of the University of California.
X * All rights reserved.
X *
X * Redistribution and use in source and binary forms are permitted
X * provided that the above copyright notice and this paragraph are
X * duplicated in all such forms and that any documentation,
X * advertising materials, and other materials related to such
X * distribution and use acknowledge that the software was developed
X * by the University of California, Berkeley.  The name of the
X * University may not be used to endorse or promote products derived
X * from this software without specific prior written permission.
X * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
X * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
X * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
X *
X *	@(#)sysexits.h	4.5 (Berkeley) 7/6/88
X */
X
X/*
X**  SYSEXITS.H -- Exit status codes for system programs.
X**
X**	This include file attempts to categorize possible error
X**	exit statuses for system programs, notably delivermail
X**	and the Berkeley network.
X**
X**	Error numbers begin at EX__BASE to reduce the possibility of
X**	clashing with other exit statuses that random programs may
X**	already return.  The meaning of the codes is approximately
X**	as follows:
X**
X**	EX_USAGE -- The command was used incorrectly, e.g., with
X**		the wrong number of arguments, a bad flag, a bad
X**		syntax in a parameter, or whatever.
X**	EX_DATAERR -- The input data was incorrect in some way.
X**		This should only be used for user's data & not
X**		system files.
X**	EX_NOINPUT -- An input file (not a system file) did not
X**		exist or was not readable.  This could also include
X**		errors like "No message" to a mailer (if it cared
X**		to catch it).
X**	EX_NOUSER -- The user specified did not exist.  This might
X**		be used for mail addresses or remote logins.
X**	EX_NOHOST -- The host specified did not exist.  This is used
X**		in mail addresses or network requests.
X**	EX_UNAVAILABLE -- A service is unavailable.  This can occur
X**		if a support program or file does not exist.  This
X**		can also be used as a catchall message when something
X**		you wanted to do doesn't work, but you don't know
X**		why.
X**	EX_SOFTWARE -- An internal software error has been detected.
X**		This should be limited to non-operating system related
X**		errors as possible.
X**	EX_OSERR -- An operating system error has been detected.
X**		This is intended to be used for such things as "cannot
X**		fork", "cannot create pipe", or the like.  It includes
X**		things like getuid returning a user that does not
X**		exist in the passwd file.
X**	EX_OSFILE -- Some system file (e.g., /etc/passwd, /etc/utmp,
X**		etc.) does not exist, cannot be opened, or has some
X**		sort of error (e.g., syntax error).
X**	EX_CANTCREAT -- A (user specified) output file cannot be
X**		created.
X**	EX_IOERR -- An error occurred while doing I/O on some file.
X**	EX_TEMPFAIL -- temporary failure, indicating something that
X**		is not really an error.  In sendmail, this means
X**		that a mailer (e.g.) could not create a connection,
X**		and the request should be reattempted later.
X**	EX_PROTOCOL -- the remote system returned something that
X**		was "not possible" during a protocol exchange.
X**	EX_NOPERM -- You did not have sufficient permission to
X**		perform the operation.  This is not intended for
X**		file system problems, which should use NOINPUT or
X**		CANTCREAT, but rather for higher level permissions.
X**		For example, kre uses this to restrict who students
X**		can send mail to.
X**
X**	Maintained by Eric Allman (eric@berkeley, ucbvax!eric) --
X**		please mail changes to me.
X**
X**			@(#)sysexits.h	4.5		7/6/88
X*/
X
X# define EX_OK		0	/* successful termination */
X
X# define EX__BASE	64	/* base value for error messages */
X
X# define EX_USAGE	64	/* command line usage error */
X# define EX_DATAERR	65	/* data format error */
X# define EX_NOINPUT	66	/* cannot open input */
X# define EX_NOUSER	67	/* addressee unknown */
X# define EX_NOHOST	68	/* host name unknown */
X# define EX_UNAVAILABLE	69	/* service unavailable */
X# define EX_SOFTWARE	70	/* internal software error */
X# define EX_OSERR	71	/* system error (e.g., can't fork) */
X# define EX_OSFILE	72	/* critical OS file missing */
X# define EX_CANTCREAT	73	/* can't create (user) output file */
X# define EX_IOERR	74	/* input/output error */
X# define EX_TEMPFAIL	75	/* temp failure; user is invited to retry */
X# define EX_PROTOCOL	76	/* remote error in protocol */
X# define EX_NOPERM	77	/* permission denied */
X# define EX_CONFIG	78	/* configuration error */
END_OF_FILE
if test 4568 -ne `wc -c <'sysexits.h'`; then
    echo shar: \"'sysexits.h'\" unpacked with wrong size!
fi
# end of 'sysexits.h'
fi
if test -f 'test-addr' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test-addr'\"
else
echo shar: Extracting \"'test-addr'\" \(387 characters\)
sed "s/^X//" >'test-addr' <<'END_OF_FILE'
Xuucp-site!user
Xsite.dom.com!user
Xsite1.dom.com!user@site2.dom2.com
Xuser@site.arpa
Xuser%site.edu@relay.cs.net
Xuser%site@relay.cs.net
Xuusite1!uusite2!uucp-site!user
Xuusite1!uusite2!uucp-site.edu!user
Xuusite1!uucp-site.bogus!user
Xuser@dec-site.uucp
Xuser@site.oz
Xseismo!site.oz!user
Xuser%site.bitnet@bitgate
Xuser%gate1%gate.edu@bitgate
X@router:user@site.com
Xuser%site1.edu%site2.com@gateway
END_OF_FILE
if test 387 -ne `wc -c <'test-addr'`; then
    echo shar: \"'test-addr'\" unpacked with wrong size!
fi
# end of 'test-addr'
fi
if test -f 'test-gag' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'test-gag'\"
else
echo shar: Extracting \"'test-gag'\" \(2404 characters\)
sed "s/^X//" >'test-gag' <<'END_OF_FILE'
X/*
X**  Test suite
X*/
X
X
X/*
X**  BBN MAILING LISTS
X*/
X/* default inews flags = ""; */
Xdefault distributions = "world usa na ne bbn ddn gnu inet";
Xdefault directory = "/usr/lib/news/.admin";	/* Where MMDF scripts are */
Xdefault mail2news = "/usr/uucp/bin/mail2news";	/* Paths to gateway	*/
Xdefault news2mail = "/usr/uucp/bin/news2mail";	/*   programs		*/
Xdefault mailcontact = "usenet";			/* Put in mail headers	*/
Xdefault mailhost = "mailer.bbn.com";		/* MMDF list processor	*/
Xdefault do mailinglist;				/* Going both ways	*/
Xdefault organization = "BBN news/mail gateway";
Xdefault owner = "usenet";			/* Sendmail alias owner	*/
Xdefault site = "gateway";			/* Psuedo news site	*/
Xdefault user = "news";				/* MMDF script owner	*/
X
X/*
Xbbn.bboard		bboard;
Xbbn.test		test;
Xrec.equestrian		horse
X    err, unh, will this work???:
X	news2mail = "v6mail -to kenr@ccp.bbn.com 
X		-subj 'Forwarded Horse Article'"
X	site = "ccp.bbn.com";
X*/
X
Xmailpost comp.foo;
X
X
X/*
X**  GNU MAILING LISTS (OSU)
X*/
Xdefault site = "internet";			/* Psuedo news site	*/
Xdefault inews flags = "-x internet -d gnu";	/* Flags for mail2news	*/
Xdefault mail2news = "/usr/lib/news/nrecnews";	/* Path to mail2news	*/
Xdefault mailhost = "prep.ai.mit.edu";		/* Home of mailing list	*/
Xdefault do mailinglist;				/* Going both ways	*/
Xdefault organization = dotify("GNUs Not Usenet");
Xdefault owner = "usenet";			/* Sendmail alias owner	*/
X
Xgnu.announce			info-gnu
X    moderator "info-gnu@prep.ai.mit.edu"
X    inews flags "-d gnu";
Xgnu.emacs			info-gnu-emacs;
Xgnu.emacs.bug			bug-gnu-emacs;
Xgnu.gdb.bug			bug-gdb;
Xgnu.gcc				info-gcc;
Xgnu.gcc.bug			bug-gcc;
Xgnu.g++				info-g++;
Xgnu.g++.bug			bug-g++;
Xgnu.chess			info-chess;
Xgnu.ghostscript.bug		bug-ghostscript;
Xgnu.utils.bug			bug-gnu-utils;
Xgnu.emacs.gnus			info-gnus-english
X    mailhost = "cis.ohio-state.edu";
Xgnu.emacs.vms		vms-gnu-emacs
X    mailhost = "harvard.havard.edu";
Xgnu.emacs.lisp.manual		gnu-manual
X    mailhost = "a.cs.uiuc.edu";
X
X/*
X# MODP(list, newsgroup, distribution, remote_host)
X# MODPOST(mailing_list, newsgroups, remote_host)
X*/
X
X
X/*
X**  OSU LOCAL MAILING LISTS
X*/
Xalt.sca				sca
X    inews flags = "-d alt -x internet"
X    mailhost = "mc.lcs.mit.edu"
X    no mailinglist
X    organization = dotify("Society for Creative Anachronism");
X
Xcis.big-lan			big-lan
X    inews flags = "-d cis -x internet"
X    mailhost = "suvm.acs.syr.edu"
X    organization = dotify("The Internet");
END_OF_FILE
if test 2404 -ne `wc -c <'test-gag'`; then
    echo shar: \"'test-gag'\" unpacked with wrong size!
fi
# end of 'test-gag'
fi
if test -f 'uucp-2-inet' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp-2-inet'\"
else
echo shar: Extracting \"'uucp-2-inet'\" \(3259 characters\)
sed "s/^X//" >'uucp-2-inet' <<'END_OF_FILE'
X##  This file maps UUCP names to Internet names.
X##  Blank lines, and lines starting with # are ignored.
X##  $Header: uucp-2-inet,v 1.2 87/10/01 14:06:50 rsalz Release1 $
X##  (I added uunet and bbn.)
Xames			ames.arpa
Xaurora			ames-aurora.arpa
Xkestrel			kestrel.arpa
Xlll-crg			lll-crg.arpa
Xlll-lcc			lll-lcc.arpa
Xstyx			lll-tis-b.arpa
Xcmcl2			nyu.arpa
Xyale			yale.arpa
Xrandvax			rand-unix.arpa
Xosu-eddie		ohio-state.arpa
Xuunet			uunet.uu.net
X
Xcunyvm.bitnet		cunyvm.bitnet
Xpsuvm.bitnet		psuvm.bitnet
X
Xmcnc			mcnc.org
X
Xbrl-smoke		smoke.brl.mil
Xbrl-sem			sem.brl.mil
Xbrl-adm			adm.brl.mil
Xcod			cod.nosc.mil
Xmarlin			marlin.nosc.mil
Xmplvax			mplvax.nosc.mil
Xnoscvax			bass.nosc.mil
X
Xelroy			elroy.jpl.nasa.gov
Xseismo			seismo.css.gov
Xlanl			lanl.gov
Xmordor			mordor.s1.gov
Xhc			hc.dspo.gov
X
Xbbn			bbn.com
Xhplabs			hplabs.hp.com
Xdecwrl			decwrl.dec.com
Xbellcore		bellcore.bellcore.com
Xpetrus			petrus.bellcore.com
XDiamond			diamond.bbn.com
Xsun			sun.com
Xsri-spam		spam.istc.sri.com
Xsri-unix		unix.sri.com
Xthink			think.com
Xburdvax			burdvax.prc.unisys.com
Xbigburd			bigburd.prc.unisys.com
Xparcvax			parcvax.xerox.com
X
Xarizona			arizona.edu
XShasta			shasta.stanford.edu
Xacf2			acf2.nyu.edu
Xacf3			acf3.nyu.edu
Xacf4			acf4.nyu.edu
Xcsd2			csd2.nyu.edu
Xmit-athena		athena.mit.edu
Xathena.mit.edu		athena.mit.edu
Xbatcomputer		tcgould.tn.cornell.edu
Xbu-cs			bu-cs.bu.edu
Xbucsb.bu.edu		bucsb.bu.edu
Xcaip			caip.rutgers.edu
Xcit-vax			csvax.caltech.edu
Xcit-vlsi		vlsi.caltech.edu
Xcornell			cu-arpa.cs.cornell.edu
Xcvl			cvl.umd.edu
Xendor			endor.harvard.edu
Xeneevax			eneevax.umd.edu
Xernie.Berkeley.EDU	ernie.berkeley.edu
Xglacier			glacier.stanford.edu
Xgvax			gvax.cs.cornell.edu
Xgymble			gymble.umd.edu
Xh.cc.purdue.edu		h.cc.purdue.edu
Xprinceton		princeton.edu
Xharvard			harvard.harvard.edu
Xhusc4			husc4.harvard.edu
Xhusc6			husc6.harvard.edu
Xoddjob			oddjob.uchicago.edu
Xgargoyle		gargoyle.uchicago.edu
Xsphinx			sphinx.uchicago.edu
Xim4u			im4u.utexas.edu
Xius2.cs.cmu.edu		ius2.cs.cmu.edu
Xsei.cmu.edu		sei.cmu.edu
Xj.cc.purdue.edu		j.cc.purdue.edu
Xll-xn			xn.ll.mit.edu
Xmimsy			mimsy.umd.edu
Xmit-amt			media-lab.media.mit.edu
Xmit-athena		athena.mit.edu
Xmit-eddie		eddie.mit.edu
Xmit-hermes		hermes.ai.mit.edu
Xmit-prep		prep.ai.mit.edu
Xmit-trillian		trillian.mit.edu
Xprep.ai.mit.edu		prep.ai.mit.edu
Xpt.cs.cmu.edu		pt.cs.cmu.edu
Xpur-ee			ee.ecn.purdue.edu
Xpurdue			purdue.edu
Xriacs			icarus.riacs.edu
Xrice			rice.edu
Xrochester		cs.rochester.edu
Xrover.ri.cmu.edu	rover.ri.cmu.edu
Xrutgers			rutgers.rutgers.edu
Xsdcsvax			sdcsvax.ucsd.edu
Xspice.cs.cmu.edu	spice.cs.cmu.edu
Xsvax			svax.cs.cornell.edu
Xtalcott			talcott.harvard.edu
Xtopaz			topaz.rutgers.edu
Xucbcad			cad.berkeley.edu
Xucbvax			ucbvax.berkeley.edu
Xucla-cs			locus.ucla.edu
Xuiucdcs			a.cs.uiuc.edu
Xuiucdcsb		b.cs.uiuc.edu
Xuiucdcsc		c.cs.uiuc.edu
Xuiucdcsm		m.cs.uiuc.edu
Xuiucdcsp		p.cs.uiuc.edu
Xuiucuxc			uxc.cso.uiuc.edu
Xumcp-cs			mimsy.umd.edu
Xumd5			umd5.umd.edu
Xoberon			usc-oberon.usc.edu
Xut-ngp			ngp.utexas.edu
Xut-sally		sally.utexas.edu
Xutah-cs			cs.utah.edu
Xutah-gr			gr.utah.edu
Xutastro			astro.as.utexas.edu
Xuw-beaver		beaver.cs.washington.edu
Xuw-june			june.cs.washington.edu
Xuwmacc			unix.macc.wisc.edu
Xuwvax			rsch.wisc.edu
Xwjh12			wjh12.harvard.edu
X
XCS.UCL.AC.UK		cs.ucl.ac.uk
Xcs.ucl.ac.uk		cs.ucl.ac.uk
END_OF_FILE
if test 3259 -ne `wc -c <'uucp-2-inet'`; then
    echo shar: \"'uucp-2-inet'\" unpacked with wrong size!
fi
# end of 'uucp-2-inet'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    echo "Have fun; bug reports to rsalz@bbn.com"
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.