rsalz@uunet.uu.net (Rich Salz) (03/16/91)
Submitted-by: Rich $alz <rsalz@bbn.com> Posting-number: Volume 24, Issue 53 Archive-name: newsgate/part03 #! /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: gate.h hdr.c lex.l mail-interface mail2news.1 misc.c # news2mail.1 signoff.c sysexits.h uucp-2-inet # Wrapped by rsalz@litchi.bbn.com on Fri Mar 15 16:42:27 1991 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 'gate.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'gate.h'\" else echo shar: Extracting \"'gate.h'\" \(6518 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/src/RCS/gate.h,v 1.12 91/03/13 15:59:23 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 * One of these is required, but you can set IN_ONEPLACE to /dev/null to X * disable the newsgroup editing. */ X/*efine IN_ONEPLACE "/dev/null" /* .. */ X/*efine 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 * or just put the user's host there. The latter two can cause the X * poster's site to never get the article. Anyhow, pick one. To pick X * neither #define is to get the third behavior -- the user's host. */ X#define FIXED_PATH "news-mail-gateway" /* .. */ X/*efine GATEWAY_NAME "gateway" /* .. */ X X X/* The code in hdr.c does lots of work to canonicalize addresses. You X * shouldn't disable it, but at least one beta-tester wanted to, sigh. */ X#define DO_ADDRESS_CLEANUP /* .. */ 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 MMDF "/usr/mmdf/lib/submit" /* .. */ X/*efine TRUSTED 1 /* .. */ X X X/* Does your Sendmail mailer have the M flag on? */ X#ifdef SENDMAIL X#define REQUIRE_MESSAGE_ID /* .. */ X#endif /* SENDMAIL */ X X X/* I love how we all speak the same language. */ X/*efine CATCHER int /* Type of a signal-catcher */ X#define 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 VOID_EXIT /* Need extern void exit(); */ X#define HAVE_SYSEXITS /* Have <sysexits.h>? */ X#define HAVE_TIMEB /* Have <sys/timeb.h>? */ X#define HAVE_PUTENV /* Have putenv(3) */ X/*efine 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#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 _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} 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 *re_comp(); Xextern char *HackHeader(); 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#ifdef CHARSTAR_SPRINTF Xextern char *sprintf(); X#endif /* CHARSTAR_SPRINTF */ X#ifdef VOID_EXIT Xextern void exit(); X#endif /* VOID_EXIT */ END_OF_FILE if test 6518 -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'\" \(10652 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#include <netdb.h> X#ifdef RCSID Xstatic char RCS[] = X "$Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/hdr.c,v 1.15 91/03/15 16:39:42 rsalz Exp $"; X#endif /* RCSID */ X X X#ifdef TEST X#ifndef DO_FIX_ADDRESS X#define DO_FIX_ADDRESS X#endif /* DO_FIX_ADDRESS */ X#define dprintf(string, buff) (void)printf((string), (buff)) X#else X#define dprintf(string, buff) /* NULL */ X#endif /* TEST */ X X X/* X** List of domains that we recognize. X*/ XSTATIC char RELAY_CS_NET[] = "RELAY.CS.NET"; XSTATIC char *Domains[] = { X /* Don't undo the % hack for sites @RELAY.CS.NET, sigh #1. */ X RELAY_CS_NET, X /* These aren't official domains, but we use them, sigh #2. */ 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** Local user? X*/ XSTATIC int XLocal(p) X register char *p; X{ X for ( ; *p; p++) X if (NETCHR(*p)) X break; X return *p == '\0'; X} X X X/* X** Case-insensitive strncmp. X*/ XSTATIC char * XFound(dp, p) X register char *dp; X register char *p; X{ X register char *q; X register char *r; X X for ( ; *p; p++) X if (CHREQ(*p, *dp)) { X for (q = p, r = dp; *r && CHREQ(*q, *r); q++, r++) X ; X if (*r == '\0') X return p; X } X X return NULL; X} X X X/* X** Find all domain names and make them uppercase: X** joe%site.edu@relay.cs.net --> joe%site.EDU@RELAY.CS.NET X*/ XSTATIC void XCasify(p) X register char *p; X{ X register char *q; X register char *r; X register char **dp; X X for (dp = Domains; dp < ENDOF(Domains); dp++) X for (q = p; q = Found(*dp, q); ) X for (r = *dp; *r; *q++ = *r++) X ; X} X X X/* X** Handle route-addresses: X** @cruft:joe@site --> joe@site X*/ XSTATIC void XRouteAddr(p) X register char *p; X{ X register char *q; X register char *r; X X for (r = p; *p == '@'; p = q) X if ((q = IDX(p, ':')) && IDX(q, '@')) X *q++ = '\0'; X else X break; X if (p > r) X /* Avoid overlaping strcpy() call. */ X while (*r++ = *p++) X ; X} X X/* X** Does the pattern exist in the character range between p and end? X*/ XSTATIC int XBetween(p, pat, q) X register char *p; X register char *pat; X register char *q; X{ X register char *r; X X for (r = pat + strlen(pat); p < q && r >= pat && *--q == *--r; ) X ; X return *r == '\0'; X} X X X/* X** Handle the '%' syntax: X** joe%site.EDU@gateway.DOMAIN -> joe@site.EDU X*/ XSTATIC void XPercent(p) X register char *p; X{ X register char *q; X register char *r; X register char **dp; X X while ((r = IDX(p, '%')) && (q = IDX(r, '@'))) { X for (dp = Domains; dp < ENDOF(Domains); dp++) { X if (*dp == RELAY_CS_NET) X continue; X if (Between(r, *dp, q)) { X *RDX(p, '@') = '\0'; X *RDX(p, '%') = '@'; X break; X } X } X if (dp == ENDOF(Domains)) X break; X } X} X X X/* X** Handle CSNET, which is domainist except in some people's minds: X** joe%site@RELAY.CS.NET --> joe@site.CSNET X** joe%site.EDU@RELAY.CS.NET --> joe@site.EDU X*/ XSTATIC void XCsnet(p) X register char *p; X{ X register char *q; X register char *r; X X if ((q = RDX(p, '@')) X && strcmp(q, "@RELAY.CS.NET") == 0 X && (r = RDX(p, '%'))) { X *RDX(p, '@') = '\0'; X *r = '@'; X if (IDX(r, '.') == NULL) X Strcat(p, ".CSNET"); X } X} X X X/* X** Handle hybrid "!" and "@" addresses: X** a!site!joe@site --> joe@site X** a!site!joe --> joe@site.UUCP X** a!site.EDU!joe --> joe@site.EDU X*/ XSTATIC void XHybrid(p) X register char *p; X{ X register char *q; X register char *user; X char buff[SM_SIZE]; X X if (user = RDX(p, '!')) { X *user++ = '\0'; X if (q = IDX(user, '@')) X *q = '\0'; X q = (q = RDX(p, '!')) ? q + 1 : p; X Sprintf(buff, "%s@%s", user, q); X if (IDX(q, '.') == NULL) X Strcat(buff, ".UUCP"); X Strcpy(p, buff); X } X} X X X/* X** Handle special case for Australia: X** user@site.OZ --> user@site.OZ.AU X*/ XSTATIC void XEndpart(p) X register char *p; X{ X register char *r; X X if ((r = RDX(p, '.')) && r[1] == 'O' && r[2] == 'Z' && r[3] == '\0') X Strcpy(&r[3], ".AU"); X} X X X/* X** General address canonicalizer. X*/ XSTATIC char * XFixAddress(p) X register char *p; X{ X static char buff[1024]; X char host[128]; X X if (Local(p)) { 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 Sprintf(buff, "%s@%s", p, host); X } X else { X Strcpy(buff, p); X Casify(buff); X dprintf(" Casify returns %s\n", buff); X RouteAddr(buff); X dprintf("RouteAddr returns %s\n", buff); X Percent(buff); X dprintf(" Percent returns %s\n", buff); X Csnet(buff); X dprintf(" Csnet returns %s\n", buff); X Hybrid(buff); X dprintf(" Hybrid returns %s\n", buff); X Endpart(buff); X dprintf(" Endpart returns %s\n", buff); 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 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, '<'); ) { 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 register struct hostent *host; X char address[LG_SIZE]; X char fullname[LG_SIZE]; X char scratch[sizeof address]; X X /* We should handle "Full-Name:" too, but it doesn't get read by the X * news header reader. */ X (void)CrackFrom(address, fullname, hp->from); X#ifdef DO_ADDRESS_CLEANUP X Strcpy(address, FixAddress(address)); X#endif /* DO_ADDRESS_CLEANUP */ X X if (AtCount(address) != 1) X p = NULL; X else { X p = IDX(address, '@'); X *p++ = '\0'; X X#ifdef DO_ADDRESS_CLEANUP X /* If we can find the host's official name use that. */ X if (host = gethostbyname(p)) X p = host->h_name; X#endif /* DO_ADDRESS_CLEANUP */ 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#ifdef FIXED_PATH X Strcpy(hp->path, FIXED_PATH); X#else X#ifdef GATEWAY X Sprintf(scratch, "%s!%s!%s", GATEWAY, p, address); X#else X Sprintf(scratch, "%s!%s", p, address); X#endif /* GATEWAY */ X Strncpy(hp->path, scratch, sizeof hp->path); X hp->path[sizeof hp->path - 1] = '\0'; X#endif /* 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} 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*/ Xchar * XHackHeader(hp, SubjectRequired) X register HBUF *hp; X int SubjectRequired; X{ X#ifdef 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 /* 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#ifdef TEST Xmain() X{ X char buff[256]; X int i; X X if (i = isatty(0)) X (void)printf("Enter addresses:\n"); X for ( ; ; ) { X if (i) X (void)printf("> "); X if (gets(buff) == NULL || buff[0] == '\0') X break; X if (buff[0] != '#') X (void)printf("\t%s -> %s\n\n", buff, FixAddress(buff)); X } X X exit(0); X} X#endif /* TEST */ END_OF_FILE if test 10652 -ne `wc -c <'hdr.c'`; then echo shar: \"'hdr.c'\" unpacked with wrong size! fi # end of 'hdr.c' 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'\" \(3664 characters\) sed "s/^X//" >'lex.l' <<'END_OF_FILE' X/* X** Lexical analyzer for the gag language. We have our own FSA X** for comments because it's much smaller and quicker that way. X*/ X%{ X#include "gate.h" X#include "gag.h" X X/* State of our automaton. */ Xtypedef enum _STATE { X S_STAR, S_NORMAL, S_END X} STATE; X X/* Key-value pair. */ Xtypedef struct _PAIR { X char *name; X int value; X} PAIR; X Xchar yyfilename[SM_SIZE]; Xextern int Errors; X X/* List of GAG's keywords. */ XSTATIC PAIR Keywords[] = { X { "default", tDEFAULT }, X { "directory", tDIRECTORY }, X { "distributions", tDISTRIBUTIONS }, X { "dotify", tDOTIFY }, X { "false", tFALSE }, X { "flags", tFLAGS }, X { "gateway", tGATEWAY }, X { "inews", tINEWS }, X { "mail2news", tMAIL2NEWS }, X { "mailcontact", tMAILCONTACT }, X { "mailhost", tMAILHOST }, X { "mailinglist", tMAILINGLIST }, X { "mailpost", tMAILPOST }, X { "moderator", tMODERATOR }, X { "news2mail", tNEWS2MAIL }, X { "organization", tORGANIZATION }, X { "owner", tOWNER }, X { "request_address", tREQUESTADDR }, X { "site", tSITE }, X { "true", tTRUE }, X { "user", tUSER }, X { NULL, 0 } X}; X X%} X X%% X X[-+0-9A-Za-z_.]+ { X /* A simple tID 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 tID; X } X X^#[ \t]+[0-9]+[ \t]+"[^\n]+"[^\n]*$ { X /* C pre-processor control line. */ X register char *p; X char *namep; X X /* Find the line number. */ X for (p = yytext; *p && !isdigit(*p); p++) X ; X /* Parse the number, find the start of the filename. */ X for (yylineno = atoi(p); *p && *p != '"'; p++) X ; X /* March down to the end of the filename. */ 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 int c; X X /* See the Lex paper in Volume 2A or PS1:16 X * for details on this code. */ X if (yytext[yyleng - 1] == '\\') X yymore(); X else { X if ((c = input()) == '"') { X yylval.String = COPY(&yytext[1]); X return tID; X } X unput(c); X yyerror("Bad string"); 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} X X Xyyopen(p) X char *p; X{ X if (p == NULL) X (void)strcpy(yyfilename, "stdin"); X else { X if ((yyin = fopen(p, "r")) == NULL) { X Fprintf(stderr, "%s: Can't open \"%s\" for input, %s.\n", X Pname, p, strerror(errno)); X exit(1); X } X (void)strcpy(yyfilename, p); X } X} X X X/* X** Write an error message. X*/ Xyyerror(p) X char *p; X{ X char buff[SM_SIZE]; X X (void)strncpy(buff, yytext, sizeof buff); X buff[sizeof buff - 1] = '\0'; X Fprintf(stderr, "\"%s\", line %d: %s (near \"%s\")\n", X yyfilename, yylineno, p, buff); X Errors++; X} END_OF_FILE if test 3664 -ne `wc -c <'lex.l'`; then echo shar: \"'lex.l'\" unpacked with wrong size! fi # end of 'lex.l' fi if test -f 'mail-interface' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'mail-interface'\" else echo shar: Extracting \"'mail-interface'\" \(2823 characters\) sed "s/^X//" >'mail-interface' <<'END_OF_FILE' X#! /bin/sh X## A portable mail interface program. Original by Piete Brooks, X## modified by Rich $alz <rsalz@bbn.com> X Xmailer="${mailer-/usr/lib/sendmail}" Xheaders=false X X## Decode the arguments. Xwhile test $# -gt 0 ; do X arg="$1" X shift X case "$arg" in X -A|-ASIS) X asis=true X ;; X -b|-body) X body="$body X$1" X shift X ;; X -c|-cc) X cc="$cc, $1" X shift X headers=true X ;; X -f|-from) X from="$1" X shift X headers=true X ;; X -h|-help) X cat <<EOF XUsage: $0 [flags] [recipients...] X -A -ASIS Send text ASIS, i.e. headers are present in the input X -b -body String which is to be the body of the message X -c -cc Carbon Copy recipients X -f -from From field X -h -help This message X -r -recip Recipient (passed on command line) X -s -subject Set the subject field X -t -to Main recipients X -* ERROR X * treat as recipients XEOF X exit 1 X ;; X -r|-recip) X recip="$recip $1" X shift X ;; X -s|-subject) X subject="$subject, $1" X shift X headers=true X ;; X -t|-to) X to="$to, $1" X shift X headers=true X ;; X -*) X echo $0: invalid argument \""$arg"\" X exit 1 X ;; X *) X to="$to, $arg" X ;; X esac Xdone X X## If no recipients, send to postmaster. Xcase "$to$cc$recip" in X'') X recip=postmaster X ;; Xesac X X## If we got no headers on the command line, read them from the message. Xcase $headers in Xfalse) X asis=true X ;; Xesac X X## Strip off the spurious leading ", " in repeatable items Xcase "$to" in X', '*) X to=`expr "$to" : ", \(.*\)` X ;; Xesac Xcase "$cc" in X', '*) X cc=`expr "$cc" : ", \(.*\)` X ;; Xesac Xcase "$subject" in ', '*) X subject=`expr "$subject" : ", \(.*\)` X ;; Xesac X X## Now do the business. Xcase "$mailer" in X*/sendmail|sendmail|*/sendmail' '*|sendmail' '*) X args="-oi" X if [ -z "$recip" ] ; then X args="$args -t" X fi X ( X if [ ! -z "$subject" ] ; then X echo "Subject: $subject" X fi X if [ ! -z "$from" ] ; then X echo "From: $from" X fi X if [ ! -z "$to" ] ; then X echo "To: $to" X fi X if [ ! -z "$cc" ] ; then X echo "Cc: $cc" X fi X if [ -z "$asis" ] ; then X echo "" X fi X if [ -z "$body" ] ; then X cat X else X echo "$body" | sed 1d X fi X ) | $debug $mailer $args $recip X ;; X X*/submit|submit|*/submit' '*|submit' '*) X args="-tsz" X case "$recip" in X if [ -z "$recip" ] ; then X if [ ! -z "$to" ] ; then X args="${args}gto*" X fi X if [ ! -z "$cc" ] ; then X args="${args}gcc*" X fi X fi X ( X if [ ! -z "$subject" ] ; then X echo "Subject: $subject" X fi X if [ ! -z "$from" ] ; then X echo "From: $from" X fi X if [ ! -z "$to" ] ; then X echo "To: $to" X fi X if [ ! -z "$cc" ] ; then X echo "Cc: $cc" X fi X if [ -z "$asis" ] ; then X echo "" X fi X if [ -z "$body" ] ; then X cat X else X echo "$body" | sed 1d X fi X ) | $debug $mailer $args $recip X ;; X X*) X echo Unknown mailer 1>&2 X exit 1 X ;; X Xesac END_OF_FILE if test 2823 -ne `wc -c <'mail-interface'`; then echo shar: \"'mail-interface'\" unpacked with wrong size! fi # end of 'mail-interface' 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'\" \(5516 characters\) sed "s/^X//" >'mail2news.1' <<'END_OF_FILE' X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/mail2news.1,v 1.11 91/02/12 14:46:17 rsalz Exp $ 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.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 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 options used by X.I mail2news Xare typically punctuation characters, to avoid conflicts with any letters Xthat might be used by X.I inews Xor any other news-processing program. X.PP XAs 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 5516 -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'\" \(2955 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: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/misc.c,v 1.7 91/02/12 14:47:53 rsalz Exp $"; 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, strerror(errno)); X exit(EX_OSERR); X } X return p; X} X X X#ifndef 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 /* HAVE_STRERROR */ 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 *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 **v; X register char *p; 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 2955 -ne `wc -c <'misc.c'`; then echo shar: \"'misc.c'\" unpacked with wrong size! fi # end of 'misc.c' 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'\" \(5362 characters\) sed "s/^X//" >'news2mail.1' <<'END_OF_FILE' X.\" $Header: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/news2mail.1,v 1.7 91/02/12 14:49:43 rsalz Exp $ 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 Xand feeds it 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: 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: 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 5362 -ne `wc -c <'news2mail.1'`; then echo shar: \"'news2mail.1'\" unpacked with wrong size! fi # end of 'news2mail.1' 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'\" \(3327 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 ? 0 : 1); X} END_OF_FILE if test 3327 -ne `wc -c <'signoff.c'`; then echo shar: \"'signoff.c'\" unpacked with wrong size! fi # end of 'signoff.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 'uucp-2-inet' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'uucp-2-inet'\" else echo shar: Extracting \"'uucp-2-inet'\" \(3301 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: /nfs/papaya/u2/rsalz/src/newsgate/src/RCS/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 3301 -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 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 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.