%{

#include "m2nconfig.h"

#include <stdio.h>
#include <string.h>
#include <time.h>
#include <syslog.h>
#include <unistd.h>

#ifdef HAS_GETOPT
#include <getopt.h>
extern char *optarg;
extern int optind, opterr, optopt;
#else
int optind = 1;
#endif

int sayit = 0;
int hasdate = 0;
int hasmsgid = 0;
int hasfrom = 0;
int hassubj = 0;
int modrepl = MODERATED_REPLYTO;
char *ufrom = NULL;
FILE *out;
char *replyto = NULL;
char *evar = ENV_GROUP;
int debugflag = 0;
int mung_msgids = MUNG_MSGIDS;
char *group, *gprefix;

void addheaders();
void out_msgid(char *, char *);
void out_munged(char *, int);

%}

%s BODY
%s UFROM
%s MSGID
%s IRT

%%

<INITIAL>^From[ ]*	{ BEGIN(UFROM); }
<UFROM>[^ ]*		{ if (ufrom == NULL) ufrom = strdup(yytext); sayit = 0; BEGIN(INITIAL); }
<INITIAL>^From:		{ fprintf(out, "%s", yytext); sayit = 1; hasfrom = 1; }

<INITIAL>^Subject:	{ fprintf(out, "%s", yytext); sayit = 1; hassubj = 1; }

<INITIAL>^Reply-To:	{
	if (replyto || modrepl)
		fprintf(out, "X-");
	fprintf(out, "%s", yytext);
	sayit = 1;
}

<INITIAL>^(Approved|Article|Content-Length|Content-Transfer-Encoding|Content-Type|Control|Delivered|Distribution|M[iI][mM][eE]-Version|Newsgroups|Path|Precedence|Received|Status|X-Delivered|X-Mailer|X-Newsreader|Xref): {
	/* headers that get tossed */
	sayit = 0;
	}

<INITIAL>^(Expires|Keywords|Lines|Organization|References|Summary|X-[A-Z][a-zA-Z-]*):	{
	/* headers that are simply copied if they are found */
	/* (includes any unrecognised X-Whatever ones) */
	fprintf(out, "%s", yytext);
	sayit = 1;
	}

<INITIAL>^Date:[ \t][ \t]*[A-Za-z, ]*[0-9][0-9]*[ ][A-Z][a-z][a-z][ ][0-9][0-9]*[ ][0-9][0-9]:[0-9][0-9]:[0-9][0-9][ ].*$	{
	fprintf(out, "%s\n", yytext);
	hasdate = 1;
	}

<INITIAL>^Message-I[Dd]:[^<]*	{ BEGIN(MSGID); sayit = 0; }
<MSGID><.*>$			{ out_msgid("Message-ID", yytext); hasmsgid = 1; }
<MSGID>.|\n			{ BEGIN(INITIAL); }

<INITIAL>^In-Reply-To:[^<]*	{ BEGIN(IRT); sayit = 0; }
<IRT><.*>			{ out_msgid("References", yytext); BEGIN(INITIAL); }
<IRT>.|\n			{ BEGIN(INITIAL); }

<INITIAL>^[A-Z][a-zA-Z-]*:	{
	/* unrecognised headers are copied with an X- prefix */
	fprintf(out, "X-%s", yytext);
	sayit = 1;
	}

<INITIAL>\n\n	{ addheaders(); BEGIN(BODY); }

<INITIAL>[ \t].*	{ if (sayit) fprintf(out, "%s\n", yytext); }

<BODY>.*		{ fprintf(out, "%s", yytext); }
<BODY>\n		{ fprintf(out, "\n"); }

.|\n			{ sayit = 0; /* ignore garbage */ }

%%

main(int argc, char ** argv) {
#ifdef HAS_GETOPT
	char c;
	while ((c=getopt(argc, argv, "dmRr:e:")) != EOF) {
		switch(c) {
			case 'd':
				debugflag = 1;
				break;
			case 'm':
				mung_msgids = 1;
				break;
			case 'r':
				replyto = strdup(optarg);
				break;
			case 'R':
				modrepl = 1;
				break;
			case 'e':
				evar = strdup(optarg);
				break;
			case '?':
			}
		}
#else
	/* manual parsing */
	if (optind<argc && strcmp(argv[optind], "-d") == 0) {
		debugflag = 1;
		optind++;
		}
#endif
	group = (optind<argc) ? argv[optind] : NULL;
	if (evar && *evar)
		group = getenv(evar);
	if (group == NULL || *group == '\0') {
		syslog(LOG_MAIL|LOG_ERR, "No group given (evar=\"%s\")\n",
			evar ? evar : "NULL");
		group = DEFAULTGROUP;
		}
	gprefix = strchr(group, '.') ? "" : GROUPPREFIX;
	if (debugflag)
		out = stdout;
	else if ((out = popen(COMMANDPIPE, "w")) == NULL) {
		/* complain */
		syslog(LOG_MAIL|LOG_ERR, "Could not pipe to \"%s\"\n",
			COMMANDPIPE);
		exit(1);
		}
	fprintf(out, "Newsgroups: ");
	out_munged(gprefix, 0);
	out_munged(group, 0);
	fprintf(out, "\n");
	fprintf(out, "Path: not-for-mail\n");
	ufrom = getenv("SENDER");
	yylex();
	if ( debugflag == 0 )
		if (pclose(out)) {
			/* complain */
			syslog(LOG_MAIL|LOG_ERR,
				"Error %m on pipe close (\"%s\")\n",
				COMMANDPIPE);
			}
		else {
			syslog(LOG_MAIL|LOG_INFO,
				"Processed message for %s from %s\n",
				group, ufrom ? ufrom : "unknown");
			}
	exit(0);
	}

void addheaders() {
	char *wdays[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
	char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
		"Aug", "Sep", "Oct", "Nov", "Dec" }; 
	time_t now = time(NULL);
	struct tm *gmt = gmtime(&now);
	if (hasfrom == 0 && ufrom != NULL)
		fprintf(out, "From: %s\n", ufrom);
	if (hassubj == 0)
		fprintf(out, "Subject: <none>\n");
	if (hasdate == 0)
		fprintf(out, "Date: %s, %02d %s %04d %02d:%02d:%02d GMT\n",
			wdays[gmt->tm_wday], gmt->tm_mday, month[gmt->tm_mon],
			gmt->tm_year + 1900,
			gmt->tm_hour, gmt->tm_min, gmt->tm_sec);
	if (hasmsgid == 0)
		fprintf(out, "Message-ID: <%04d%02d%02d.%02d%02d%02d.%d@%s>\n",
			gmt->tm_year + 1900, gmt->tm_mon, gmt->tm_mday,
			gmt->tm_hour, gmt->tm_min, gmt->tm_sec,
			getpid(), MYFQDN);
#ifdef DISTRIBUTION
	fprintf(out, "Distribution: %s\n", DISTRIBUTION);
#endif
	if (modrepl) {
		fprintf(out, "Reply-To: ");
		out_munged(gprefix, 1);
		out_munged(group, 1);
		fprintf(out, "@%s\n", MYFQDN);
		}
	else if (replyto) {
		fprintf(out, "Reply-To: %s\n", replyto);
		}
	fprintf(out, "Sender: %s@%s\n", NEWSUSER, MYFQDN);
	fprintf(out, "Approved: %s@%s\n\n", NEWSUSER, MYFQDN);
	}	

void out_msgid(char *hdr, char *msgid) {
	if (mung_msgids)
		fprintf(out, "%s: <%s-%s\n", hdr, group, msgid+1);
	else
		fprintf(out, "%s: %s\n", hdr, msgid);
	}

void out_munged(char *s, int dothyph) {
	int c;
	while (c = *s++) {
		if (dothyph && c == '.')
			c = '-';
		else if (isupper(c))
			c = tolower(c);
		fputc(c, out);
		}
	}
