#include "listserv.h"

static char rcsid[] = "$Header: /nfs/ucsd/local/src/mail/listserv/RCS/main.c,v 1.9 93/02/25 16:04:13 andy Exp Locker: andy $";

FILE *mailer;
FILE *logfile;

main(argc,argv)
int argc;
char **argv;
	{
	char from[256];
	char buf[BUFSIZ];
	char grp[64];
	char dat[64];
	char *p;
	int i;
	int gotcommand = 0;
	int outsider = 0;
	int inheader;
	int log;
	int garbage = 0;

	/* gotta have some default if the From: line is missing */
	strcpy(from, "ListServ");

	inheader = 1;
	while (fgets(buf,BUFSIZ,stdin) != NULL)
		{
		/* drop trailing newline */
		while (buf[(i=strlen(buf)-1)] == '\n')
			buf[i] = '\0';

		/* drop trailing blanks */
		p = buf + (strlen(buf) - 1);
		while (p && *p && p >= buf && isspace(*p))
			*p-- = '\0';

		/* deblank beginning of line */
		p = buf;
		while (p && *p && isspace(*p))
			p++;
		if (p != buf)
			strcpy(buf, p);

		if (strlen(buf) == 0)	/* blank line ends header */
			{
			inheader = 0;
			continue;
			}
		
		/*
		get the From: line so we can return the answer

		Note that we DON'T check that we're in the header when
		picking up the From: line; that's so that we'll take the
		last from line we encounter which makes it handle
		forwarded messages correctly.
		*/
		if (strncasecmp(buf,"From: ",6) == 0)
			{
			strcpy(from, &buf[6]);
			cleanup(from, &outsider);
			printf("outsider = %d\n", outsider);
			continue;
			}
		if (strncasecmp(buf, "From: listserv", 14) == 0
		|| strncasecmp(buf,
			"subject: re: your listserve request", 35) == 0)
			{
			printf("loop detected, flushing mail\n");
			exit(0);
			}
		
		/* 
		don't look for commands in the header 
		*/
		if (inheader)
			continue;
		
		/* avoid mail loops - ignore requests from ourself! */
		if (!strncasecmp(from, "listserv", 8))
			{
			printf("I refuse to talk to myself.\n");
			exit(0);
			}

		/* Throw away bounced mail */
		if (strstr(from, "daemon") != NULL)
			{
			printf("We don't do business with your type.\n");
			exit(0);
			}

		/* force to lower case and scan for commands */
		p = buf;
		while (p && *p)
			{
			if (isupper(*p))
				*p = tolower(*p);
			p++;
			}
		
		/* log the request */
		log = open(LOGFILE, AFLAGS, AMODE);
		if (log == -1)
			perror(LOGFILE);
		else
			{	
			logfile = fdopen(log, "a"); 
			if (logfile != NULL)
				{
				long clock = time(0);
				strcpy(dat,ctime(&clock));
				/* drop trailing newline */
				while (dat[(i=strlen(dat)-1)] == '\n')
					dat[i] = '\0';
				printf("logfile: %s|%s|%s\n", dat, from, buf);
				fprintf(logfile,"%s|%s|%s\n", dat, from, buf);
				fflush(logfile);
				close(log); 
				}
			else
				perror(LOGFILE);
			}

		if (!strncasecmp(buf, "list ",5)
		|| !strncasecmp(buf, "delete-all ",11)
		|| !strncasecmp(buf, "del-all ",8)
		|| !strncasecmp(buf, "unsubscribe-all ",16)
		|| !strncasecmp(buf, "unsub-all ",10)
		|| !strcasecmp(buf, "list")
		|| !strcasecmp(buf, "delete-all")
		|| !strcasecmp(buf, "del-all")
		|| !strcasecmp(buf, "unsubscribe-all")
		|| !strcasecmp(buf, "unsub-all"))
			{
			gotcommand++;
			listsearch(from, buf);
			continue;
			}
	
		if (!strncasecmp(buf,"add ", 4)
		|| !strncasecmp(buf,"subscribe ", 10)
		|| !strncasecmp(buf,"sub ",4))
			{
			gotcommand++;
			subscription(from,buf,1,outsider);
			continue;
			}

		if (!strncasecmp(buf,"delete ", 7)
		|| !strncasecmp(buf,"del ",4)
		|| !strncasecmp(buf,"unsubscribe ", 12)
		|| !strncasecmp(buf,"unsub ",6))
			{
			gotcommand++;
			subscription(from,buf,0,outsider);
			continue;
			}
		
		if (!strcasecmp(buf,"index")
		|| !strcasecmp(buf,"longindex"))
			{
			gotcommand++;
			sendindex(from,buf,!strcasecmp(buf,"longindex"),
				outsider);
			continue;
			}

		if (!strncasecmp(buf, "faq ", 4))
			{
			gotcommand++;
			sendfaq(from, buf, outsider);
			continue;
			}

		if (!strcasecmp(buf, "faq"))
			{
			gotcommand++;
			faqindex(from, buf);
			continue;
			}

		if (!strcasecmp(buf, "info"))
			{
			gotcommand++;
			infoindex(from, buf);
			continue;
			}

		if (!strncasecmp(buf, "info ", 5)
		|| !strncasecmp(buf, "get ",4))
			{
			gotcommand++;
			sendinfo(from, buf);
			continue;
			}

		if (!strcasecmp(buf,"help"))
			{
			gotcommand++;
			sendhelp(from,buf);
			continue;
			}
		
		if (!strncasecmp(buf,"help ",5))
			{
			gotcommand++;
			sscanf(buf,"%*s%s", grp);
			listhelp(from,grp,buf,outsider);
			continue;
			}
		/* Flush message if > 5 lines of garbage */
		if (++garbage > 5)
			{
			printf("Garbled message, flushing...\n");
			exit(0);
			}
		}
	if (gotcommand == 0)
		sendhelp(from, "indecipherable");
	exit(0);
	}

callmailer(redirect, toaddr, request)
char *redirect, *toaddr, *request;
	{
	char cbuf[BUFSIZ];

	printf("callmailer \"%s\",\"%s\",\"%s\"\n", redirect, toaddr, request);

	strcpy(cbuf, MAILER);
	strcat(cbuf, " -f");
	strcat(cbuf, LISTSERVMANAGER);
	strcat(cbuf, " -F\"Mailing List Processor\"");
	strcat(cbuf, " -t -oi"); 
	strcat(cbuf, " "); strcat(cbuf, redirect);
	mailer = popen(cbuf,"w");
	printf("mailer popen '%s'\n", cbuf);
	if (mailer == NULL)
		{
		perror(cbuf);
		exit(1);
		}
	fprintf(mailer,"From: ");
	fprintf(mailer, LISTSERVADDR);
	fprintf(mailer, " (Mailing List Processor)\n");
	fprintf(mailer,"To: %s\n", toaddr);
	fprintf(mailer,"Subject: Re: your LISTSERV request \"%s\"\n", request);
	fprintf(mailer,"\n");
	}

mailcat(mfname,prefix)
char *mfname, *prefix;
	{
	FILE *mf;
	char buf[BUFSIZ];

	printf("mailcat \"%s\", \"%s\"\n", mfname, prefix);

	mf = fopen(mfname,"r");
	if (mf == NULL)
		{
		perror(mfname);
		fprintf(mailer,"This should have been the contents of\n");
		fprintf(mailer,"file '%s' but it's missing!\n",mfname);
		return;
		}

	/* copy the message file into the mailer */
	while (fgets(buf,BUFSIZ,mf) != NULL)
		{
		fputs(prefix,mailer);
		fputs(buf,mailer);
		}
	fclose(mf);
	return;
	}

cleanup(from, outsider)
char *from;
int *outsider;
	{
	char *p, *q;

	printf("cleanup \"%s\"\n", from);

	while (p = index(from,'~'))
		*p = 'X';

	while (p = index(from,'|'))
		*p = 'X';

	/* elide stuff in parenthesis */
	if (p = index(from,'('))
		{
		if ( (q=rindex(from,')')) == NULL)
			{
			/* zap the from line; it's invalid */
			*p = '\0';
			return;
			}
		strcpy(p, q+1);
		}

	if (p = index(from,'<'))
		{
		if ( (q=index(from,'>')) == NULL)
			{
			/* zap the from line; it's invalid */
			*p = '\0';
			return;
			}
		*q = '\0';
		strcpy(from, p+1);
		}

	p = from;

	/* drop trailing blanks */
	p = from + (strlen(from) - 1);
	while (p && *p && p >= from && isspace(*p))
		*p-- = '\0';

	/* 'outsider' indicates whether it's mail from a local user
		or not.  'subscribe' uses that to determine whether
		to acknowledge the existence of the list.  (local users
		may subscribe to anything with a .info file; others
		may only subscribe if there is a .pub file)
	*/

	if (index(from, '!') != NULL)	/* uucp sites are foreign */
		{
		*outsider = 1;
		return;
		}
	if ((p = index(from, '@')) == NULL)	/* on-machine user */
		{
		*outsider = 0;
		return;
		}

	if (strcasecmp(p+1, DOMAIN) == 0)
		{
		*outsider = 0;
		return;
		}
	if ((p = index(p, '.')) == NULL)	/* in-domain user */
		{
		*outsider = 0;
		return;
		}
	if (strncasecmp(p+1, DOMAIN,8) == 0)
		{
		*outsider = 0;
		return;
		}

	*outsider = 1;
	return;
	}

