/* 
 *   Copyright (c) 1990 Rodney Volz
 *   ALL RIGHTS RESERVED 
 * 
 *   THIS SOFTWARE PRODUCT CONTAINS THE
 *   UNPUBLISHED SOURCE CODE OF RODNEY VOLZ
 *
 *   The copyright notices above do not evidence
 *   intended publication of such source code.
 *
 */

/*
 * MERCURY UUCP SOURCECODE [elm.c]
 */

#define _ELM

#include "define.h"
#include "uulib.c"
#include "header.c"
#include "scr.c"

overlay "main"


#define SCROLLSTEP	5
#define MAXMSG		255

int root = 0;
int pointer;
int offset;
int msganz;
int remote;
int need;			/* Do we need refresh, a shower? */
static char *spaces = "                                                    ";
static struct header	*msghd[MAXMSG];
static char	*title[MAXMSG];
static char	home[LLEN],
		folder[LLEN],
		logname[LLEN],
		fullname[LLEN],
		mqueue[LLEN],
		receiver[LLEN];
		tmpdir[LLEN];


main(argc,argv)
int argc;
char *argv[];
{
	int i,n,n2;
	long l;
	char c;
	char s[LLEN],s2[LLEN],s3[LLEN],s4[LLEN];
	struct header *hd;
	char deleted = 0;

	need = 0;
	remote = 0;

	if (argc == 2)
	{
		remote = 1;
		strcpy(argv[1],receiver);
	}

	getprof(2,home);
	sys_impdirn(home);
	getprof(1,logname);
	getprof(3,fullname);

	getconf(21,tmpdir);
	sys_impdirn(tmpdir);

	strcpy(home,folder);	/* $HOME is our std folder */

restart:
	pointer = 0;	/* First message is selected */
	offset = 0;	/* Display starts with first message */
	
	
	strcpy(folder,s);
	stradd("*.msg",s);

	i = 0;

	if (remote)
		goto fast;

	locate(1,25);
	send("\033l");
	for (n = sfirst(s); n >= 0; n = snext(s))
	{
		locate(1,25);
		send("Messages: ");
		sendd(i + 1);
		
		dtaxtr(s2,&l,&c);
	
		sprintf(s,"%s%s",folder,s2);
		msghd[i] = (struct header *)fgethead(s);

		if (i++ == MAXMSG)
		{
			printf("Too many messages!\n");
			exit(0);
		}
	}
	msganz = i;

	sort();

fast:
	for (n = 0; n < msganz; n++)
	{
		hd = msghd[n];
		strcpy("",s);

		sprintf(s2,"N %s%s",hd->fromfull,spaces);
		s2[18] = '\0';
		stradd(s2,s);

		sprintf(s2,"  %s%s",hd->subject,spaces);
		s2[28] = '\0';
		stradd(s2,s);

		sprintf(s2,"  %s%s",hd->date,spaces);
		s2[30] = '\0';
		stradd(s2,s);

		title[n] = (char *)malloc((long)LLEN);
		strcpy(s,title[n]);
	}


	window();

	for(;;)
	{
		locate(10,20);
		send("            ");
		locate(10,20);

		if (!remote)
			i = inp();
		else
		{
			i = 'm';
			out(i);
		}


		if (need)
		{
			locate(1,21);
			send("\033l");
			locate(1,22);
			send("\033l");
			need = 0;
			locate(10,20);
			out(i);
		}
		

		/* We don't view unavailable messages. */

		/* Space and Enter will do as "view" */
		if ((i == ' ') || (i == 13))
		{
			i = 'v';
			locate(10,20);
			out(i);
		}

		if ((linstr("duvrfse",i) != -1) && (msganz == 0))
			i = '_';

		
		switch(i)
		{
			case '+':	/* next message */
			{
				++pointer;
				if (pointer >= msganz)
				{
					--pointer;
					break;
				}
				
				if (pointer > (offset + 9))
				{
					offset += SCROLLSTEP;
					hdisplay();
				}
				
				hupdate(pointer - 1);
				hupdate(pointer);
				break;
			}
			
			case '-':	/* previous message */
			{
				--pointer;
				if (pointer < 0)
				{
					++pointer;
					break;
				}
				
				if (pointer < (offset))
				{
					offset -= SCROLLSTEP;
					hdisplay();
				}
				hupdate(pointer + 1);
				hupdate(pointer);
				break;
			}
			
			case 'Q':	/* Quit Mailer */
			{
				send("uit");
				locate(1,21);
				send("\033l");

				if (killthem() != 0)
				{
					n = twhatnow("Remove deleted messages? [yn]","yn");
					if (n == 1)
						cleanup();
				}
				
				locate(1,23);
				cr(2);
				exit(0);
			}

			case 'v':	/* View message */
			{
				send("iew");
				locate(1,23);
				view();
				break;
			}

			case 'd':	/* Delete message */
			{
				deleted = 1;
				send("elete");
				locate(1,21);
				center("- Deleted -");
				*title[pointer] = 'D';
				hupdate(pointer);
#if 0
				locate(1,21);
				send("\033l");
#endif
				++need;
				break;
			}
			
			case 'u':	/* Undelete message */
			{
				send("ndelete");
				locate(1,21);
				center("- Undeleted -");
				*title[pointer] = 'N';
				hupdate(pointer);
#if 0
				locate(1,21);
				send("\033l");
#endif
				++need;
				break;
			}
			
			case 'M':	/* Move to folder */
			{
				send("ove");
				if (move('m') == 1)
					goto fast;
				break;
			}
			
			case 'D':	/* Dup to folder */
			{
				send("uplicate");
				move('d');
				break;
			}
			
			case 'F':	/* select Folder */
			{
				send("older");
				if (sfold() == 1)
				{
					cleanmsg();
					goto restart;
				}
			
				break;
			}
			
			case 'C':	/* Cleanup */
			{
				send("leanup");
				if (cleanup() == 1)
					goto fast;
				break;
			}

			case 's':	/* Save message */
			{
				send("ave ");
				save();
				break;
			}

			case 'o':	/* Options */
			{
				send("ptions");
				locate(1,21);
				center("no options so far... maybe in the near future!");
				++need;
				break;
			}

			case 'e':	/* Decrypt message */
			{
				send(" -> decrypt ");
				mail_decrypt();
				break;
			}

			case 'm':	/* Mail a message */
			{
				send("ail");
				sendmail((remote == 0) ? 'm' : 'd');
				break;
			}

			case 'r':	/* reply to current message */
			{
				send("eply");
				sendmail('r');
				break;
			}

			case 'f':	/* Forward a message*/
			{
				send("orward");
				sendmail('f');
				break;
			}

			case 'h':	/* Help */
			{
				help();
				window();
				break;
			}

			case '_':
			{
				break;
			}

			default:
			{
				locate(1,21);
				send("No such command.");
				++need;
				break;
			}
		}
	}
}


hdisplay()
{
	int n,i;
	
	i = 0;
	for (n = offset; (n < msganz) && (i < 10); n++)
	{
		locate(2,(i++) + 4);
		if (pointer == n)
		{
			send("\033p ");
			send(title[n]);
			send(" \033q");
		}
		else
		{
			send(" ");
			send(title[n]);
			send(" ");
		}
	}

	
	for (n = i; n < 10; n++)
	{
		locate(1,n + 4);
		send("\033l");
	}
}


hupdate(nr)
int nr;
{
	if (offset < 0)
		return(0);

	locate(2,nr - offset + 4);
	if (pointer == nr)
	{
		send("\033p ");
		send(title[nr]);
		send(" \033q");
	}
	else
	{
		send(" ");
		send(title[nr]);
		send(" ");
	}
}



window()
{
	char s[LLEN],s2[LLEN];

	cls();
	locate(1,1);
	center(" Mercury UUCP's ELM derivat ");

#if 0
	locate(1,1);
	send(logname);
	locate(1,2);
	send("(");
	send(fullname);
	send(")");
#endif
	
	hdisplay();

	locate(1,18);
	send("\033l");

	if (strcmp(folder,home) == TRUE)
	{
		center("Folder: [std]");
	}
	else
	{
		strcpy(folder,s);
		s[strlen(s) - 1] = '\0';
		strcpys(s,s2,rinstr(s,'\\') + 1,strlen(s));
		strcpy("Folder: [",s);
		stradd(s2,s);
		stradd("]",s);
		center(s);
	}
	
	locate(1,20);
	send(spaces);
	locate(1,20);
	send("Command: ");

	locate(1,23);

	center("m)ail r)eply f)orward s)ave d)elete D)uplicate M)ove F)older");
	center("h)elp v)iew u)ndelete o)ptions d(e)crypt C)leanup Q)uit");
}



help()
{
	char s[LLEN];
	cls();
	center("- Mercury ELM commands -");
	cr(1);
	send("+ or - ............... Select message");
	cr(1);
	send("v)iew or <space> ..... Display currently selected message");
	cr(1);
	send("m)ail ................ Send a message to someone");
	cr(1);
	send("r)reply .............. Reply to a message");
	cr(1);
	send("f)orward ............. Forward this message to another receiver");
	cr(1);
	send("s)save ............... Write a message to a file (default \"received\"");
	cr(1);
	send("d)elete .............. Mark a message for deletion");
	cr(1);
	send("u)ndelete ............ Un-mark message");
	cr(1);
	send("M)ove ................ Move a message to a folder (a directory)");
	cr(1);
	send("F)older .............. Select a folder");
	cr(1);
	send("o)tions .............. [ reserved for future use ]");
	cr(1);
	send("d(e)crypt ............ UUdecode and DES decrypt message");
	cr(1);
	send("C)leanup ............. Delete marked messages physically");
	cr(1);
	send("Q)uit ................ leave ELM");
	cr(2);
	send("Hit any key.");
	inp();
}





edi(file)	/* Editor aufrufen */
char file[];
{
	char sys_ed[LLEN];
	char s[LLEN],s2[LLEN],s3[LLEN];

	getconf(20,sys_ed);
	strcpy(sys_ed,s);

	sys_exec(s,file);

	curs();

	return(0);
}


sys_mail(sfile,head)	/* <file> in die Mail-Queue stellen */
char *sfile;
struct header *head;
{
	static char s[LLEN],s2[LLEN],s3[LLEN],s4[LLEN],file[LLEN],sequence[LLEN];
	static char sys_mqueue[LLEN],sys_myname[LLEN],usr_home[LLEN];
	int inh,outh,n,a,cnt;
	static char xout[LLEN],sender[LLEN],dout[LLEN],domain[LLEN];
	char lo[LLEN];
	long sys_fread();

	getconf(4,(char *)domain);

	getconf(2,(char *)sys_myname);
	getprof(2,(char *)usr_home);
	sys_impdirn((char *)usr_home);

	getconf(14,(char *)sys_mqueue);
	sys_impdirn((char *)sys_mqueue);


	strcpy((char *)sfile,(char *)file);

	while (0 == 0)
	{
		strcpy("",s);

		while(strlen(s) < 7)
		{
			n = 0;
			while(n == 0)
			{
				n = sys_rnd(9);
			}

			str(n,(char *)s2);
			stradd(s2,(char *)s);
		}

		strcpy(s,sequence);	/* Sequence is '1234' */

		strcpy(sys_mqueue,dout);
		stradd("a",dout);
		stradd(sequence,dout);
		stradd(".d",dout);	/* DOUT Name steht. */

		strcpy(sys_mqueue,xout);
		stradd("a",xout);
		stradd((char *)sequence,(char *)xout);
		stradd(".x",(char *)xout);


		if ((exist(xout) == FALSE) && (exist(dout) == FALSE))
			break;
	}

	/************************************* '???.D' erzeugen */

	inh = open((char *)file,2);		/* Open in-file readonly */
	if (inh < 0)
	{
		send("Error opening input file.");
		cr(1);
		gemerror(inh);
		return(-1);
	}

	outh = open((char *)dout,1);	/* Creative open */

	if (outh <= 0)
	{
		cr(1);
		send("Error opening for output: ");
		send(dout);
		send(".");
		cr(1);
		return;
	}

	strcpy("ELM: ",lo);

	if (valid(head->from))
	{
		strcpy(head->from,sender);
	}
	else
		if (valid(head->sender))
		{
			strcpy(head->sender,sender);
		}
		else
		{
			send("sys_mail: Couldn't get sender's name.");
			cr(1);
			return(-1);
		}

	stradd(sender,lo);
	stradd(" -> ",lo);


	sd(s2);
	sprintf(s,"From %s %s remote from %s",sender,s2,sys_myname);

	/* Datum in der Form "Tue May 16 06:11:13 1989" erzeugen */


#if 0	/* This would be *non* standard. */
	stradd(domain,s);
#endif

	uu_putline(outh,s);	/* Zeile 1: From vaxima... */


	if (valid(head->id))
	{
		strcpy("Message-Id: ",s);
		stradd(head->id,s);
	}
	else
	{
		sprintf(s,"Message-Id: <%s@%s%s>",sequence,sys_myname,domain);
	}

	uu_putline(outh,s);	/* Zeile 4: 'Message-Id: <kjighkjg'... */

	strcpy("From: ",s);
	stradd(sender,s);
	stradd("@",s);
	stradd(sys_myname,s);
	stradd(domain,s);
	if (valid(head->fromfull))
	{
		stradd(" (",s);
		stradd(head->fromfull,s);
		stradd(")",s);
	}

	uu_putline(outh,s);	/* 'From: root@merkur.uucp (Die Systemverwaltung) */

	if (valid(head->replyto))
	{
		strcpy("Reply-To: ",s);
		stradd(head->replyto,s);
		if (valid(head->replytofull))
		{
			stradd(" (",s);
			stradd(head->replytofull,s);
			stradd(")",s);
		}
		uu_putline(outh,s);
	}

	strcpy("X-Version: [elm] ",s);
	stradd(VERSION,s);
	uu_putline(outh,s);

	stradd(head->to,lo);

	if (valid(head->subject))
	{
		strcpy("Subject: ",s);
		stradd(head->subject,s);

		uu_putline(outh,s);	/* Subject-line */

		stradd(" subj:",lo);
		stradd(head->subject,lo);
	}


	log(lo,"mail");

	strcpy("To: ",s);
	stradd(head->to,s);
	if (valid(head->tofull))
	{
		stradd(" (",s);
		stradd(head->tofull,s);
		stradd(")",s);
	}
	uu_putline(outh,s);	/* To: <receiver>@<host> */

	/* Carbon copy */
	if (valid(head->cc))
	{
		sprintf(s,"Cc: %s",head->cc);
		uu_putline(outh,s);
	}

	if (valid(head->date))
	{
		strcpy("Date: ",s);
		stradd(head->date,s);
	}
	else
	{
		sys_dayname(s2);
		sys_time(s3);
		sys_monthname(s4);
		sprintf(s,"Date: %s, %d %s %d %s MET",s2,sys_dayofmonth(),s4,sys_year() % 100,s3);
	}
                                /* Date: Mon, 99 Jun 90              */
	uu_putline(outh,s);	/* Date: Day, 99 May 99 14:30:08 MET */

	/* Nicht RFC822-konform */
	if (valid(head->organization))
	{
		strcpy("Organization: ",s); /* Organization: Blablabla... */
		stradd(head->organization,s);

		uu_putline(outh,s);
	}

	
	uu_putline(outh,"");	/* Eine Leerzeile drunter! */

	/* So, und jetzt wird der Rest 'drunterkopiert. */
	while (getline(inh,s) != -1)
	{
		filter(s);	/* ^M's filtern */
		uu_putline(outh,s);
	}
	close(inh);

	strcpy(usr_home,s2);
	sys_impdirn(s2);

	stradd("signatur.mai",s2);

	inh = open(s2,2);	/* Open signature file */
	if (inh < 0)
	{
		locate(1,21);
		send("\033l");
		locate(1,21);
		center("- No signature -");
	}
	else
	{
		uu_putline(outh,"");
		uu_putline(outh,"--");

		while (0 == 0)
		{
			a = getline(inh,s);

			if (a == -1)
				break;

			filter(s);

			uu_putline(outh,s);
		}
		close(inh);
	}
	close(outh);


	/*********************** Xfile ausgeben ************************/

	outh = open(xout,1);	/* Open for creation */
	if (outh <= 0)
	{
		send("Error opening ");
		send(xout);
		send(" as output.");
		cr(1);
		return;
	}

	strcpy("U ",s);
	stradd((char *)sender,(char *)s);
	stradd(" ",s);
	stradd(sys_myname,s);
	uu_putline(outh,s);

	strcpy("F D.",s);
	stradd(sequence,s);
	uu_putline(outh,s);

	strcpy("I D.",s);
	stradd(sequence,s);
	uu_putline(outh,s);

	strcpy("C rmail ",s);
	stradd(head->to,s);
	uu_putline(outh,s);

	close(outh);
}


mail_encrypt(file)
char *file;
{
	char s[LLEN],s2[LLEN],s3[LLEN],temp[LLEN];
	char des[LLEN],uuenc[LLEN];
	int inh,outh;

	locate(1,22);
	send("\033l");
	

	locate(1,21);
	send("\033lEnter encryption password: ");
	rec(s);

	if (strlen(s) < 4)
	{
		locate(1,21);
		send("Password too short.\033K");
		++need;
		return(-1);
	}


	locate(1,21);
	send("\033lRepeat, please: ");
	rec(s2);

	locate(1,21);
	send("\033lRepeat, please: #####");

	if (strcmp(s,s2) != TRUE)
	{
		locate(1,21);
		send("Passwords do not match.\033K");
		++need;
		return(-1);
	}

#if 0
	if (strlen(s) < 4)
	{
		locate(1,21);
		send("Password too short.\033K");
		++need;
		return(-1);
	}
#endif

	strcpy(tmpdir,temp);
	mktmp(temp);


	getconf(23,des);
	getconf(24,uuenc);

	if ((exist(des) == FALSE) || (exist(uuenc) == FALSE))
	{
		cls();
		send("Couldn't find DES and/or uuencode.");
		cr(1);
		send("Update field 23 and/or 24 in your config file.");
		cr(1);
		send("-- Hit Return --");
		rec(s);
		window();
		return(-1);
	}

	strcpy("-e -k ",s2);
	stradd(s,s2);
	stradd(" ",s2);
	stradd(file,s2);
	stradd(" ",s2);
	stradd(temp,s2);

	locate(1,21);
	send("\033l");
	center("- DES running -");

	noenv_exec(des,s2);

	if (exist(temp) != TRUE)
	{
		cls();
		send("Error running des.");
		cr(1);
		send("Check your configuration file.");
		cr(1);
		send("-- Hit Return --");
		rec(s);
		window();
		return(-1);
	}


	strcpy(temp,s2);
	stradd(" ",s2);

	strcpy(tmpdir,s3);
	mktmp(s3);

	stradd(s3,s2);
	stradd(" message.des",s2);

	locate(1,21);
	send("\033l");
	center("- UUENCODE running -");
	noenv_exec(uuenc,s2);

	if (exist(s3) != TRUE)
	{
		cls();
		send("Error running uuencode.");
		cr(1);
		send("Check your configuration file.");
		cr(1);
		rec(s);
		window();
		return(-1);
	}

	sys_remove(file);
	sys_rename(s3,file);
	locate(1,22);
	send("\033l");
	locate(1,21);
	send("\033l");
	center("- Encryption completed -");
	++need;
}






mail_decrypt()
{
	char s[LLEN],s2[LLEN],s3[LLEN],temp[LLEN],file[LLEN];
	char des[LLEN],uudec[LLEN];
	struct header *head;
	int inh,outh;

	head = msghd[pointer];
	strcpy(head->file,file);

	locate(1,22);
	send("\033l");
	
	locate(1,21);
	send("\033lEnter decryption password: ");
	rec(s);
	
	locate(1,21);
	send("\033lRepeat, please: ");
	rec(s2);

	locate(1,21);
	send("\033lRepeat, please: #####");

	if (strcmp(s,s2) != TRUE)
	{
		locate(1,21);
		send("Passwords do not match.\033K");
		return(-1);
	}

	if (strlen(s) < 4)
	{
		locate(1,21);
		send("Password too short.\033K");
		return(-1);
	}


	getconf(23,des);
	getconf(25,uudec);


	if ((exist(des) == FALSE) || (exist(uudec) == FALSE))
	{
		cls();
		send("Couldn't find DES and/or uudecode.");
		cr(1);
		send("Update field 23 and/or 25 in your config file.");
		cr(1);
		send("-- Hit Return --");
		rec(s);
		window();
		return(-1);
	}


	strcpy(tmpdir,temp);
	mktmp(temp);

	strcpy(file,s2);
	stradd(" ",s2);
	stradd(temp,s2);

	locate(1,21);
	send("\033l");
	center("- UUDECODE running -");

	noenv_exec(uudec,s2);

	if (exist(temp) != TRUE)
	{
		cls();
		send("Error running uudecode.");
		cr(1);
		send("Check your configuration file.");
		cr(1);
		send("-- Hit Return --");
		rec(s);
		window();
		return(-1);
	}

	strcpys(file,s3,0,rinstr(file,'.'));
	stradd("des",s3);
	sys_remove(s3);
	sys_rename(file,s3);

	strcpy("-d -k ",s2);
	stradd(s,s2);
	stradd(" ",s2);
	stradd(temp,s2);
	stradd(" ",s2);
	stradd(file,s2);

	locate(1,21);
	send("\033l");
	center("- DES running -");

	noenv_exec(des,s2);

	if (exist(file) != TRUE)
	{
		cls();
		send("Error running des.");
		cr(1);
		send("Check your configuration file.");
		cr(1);
		sys_rename(s3,file);
		send("-- Hit Return --");
		rec(s);
		window();
		return(-1);
	}

	locate(1,21);
	send("\033l");
	
	stradd(" is a copy of the original message.",s3);
	center(s3);
	++need;
}



m_options(hd)
struct header *hd;
{
	int n,i;
	char s[LLEN],s2[LLEN];

	send("\033E");
	cr(2);
	send("	- Change \"[T]o:\"-line");
	cr(1);
	send("	- Insert \"[R]eply-to:\"-line");
	cr(1);
	send("	- New \"[S]ubject:\"-line");
	cr(1);
	send("	- Add \"[C]c:\"-line");
	cr(1);
	send("	- E[x]it this menu");
	cr(1);


	locate(1,21);
	n = twhatnow("Your choice:","trscx");

	switch(n)
	{
		case 1:
		{
			send("To (old): ");
			send(hd->to);
			if (valid(hd->tofull));
			{
				send(" (");
				send(hd->tofull);
				send(")");
			}
			cr(1);
			send("To (new): ");
			rec(s);
			cr(1);
			trim(s);
			if (s[0])
			{
				strcpy("",hd->tofull);
				adrparse(s,hd->to,hd->tofull);
			}
			else
			{
				send("Nothing changed.");
				cr(1);
			}
			break;
		}

		case 2:
		{
			if (valid(hd->replyto))
			{
				send("Reply-To (old): ");
				send(hd->replyto);
				if (valid(hd->replytofull));
				send(" (");
				send(hd->replytofull);
				send(")");
				cr(1);
				send("Reply-To (new): ");
			}
			else
			{
				send("Reply-To: ");
			}
			
			rec(s);
			cr(1);
			trim(s);
			if (valid(s))
			{
				strcpy("",hd->replytofull);
				adrparse(s,hd->replyto,hd->replytofull);
			}
			else
			{
				send("Nothing changed.");
				cr(1);
			}
			return(0);
		}

		case 3:
		{
			if (valid(hd->subject))
			{
				send("Subject (old): ");
				send(hd->subject);
				cr(1);
				send("Subject (new): ");
			}
			else
				send("Subject: ");
			
			rec(s);
			cr(1);
			trim(s);
			if (!*s)
			{
				send("Subject-line left unchanged.");
				cr(1);
			}
			else
				strcpy(s,hd->subject);
			return(0);
		}

		case 4:
		{
			send("Carbon copy doesn't work in this Version!");
			cr(1);
			if (valid(hd->cc))
			{
				send("Cc (old): ");
				send(hd->cc);
				send("Cc (new): ");
			}
			else
			{
				send("Cc: ");
			}
			
			rec(s);
			cr(1);
			trim(s);
			if (valid(s))
			{
				adrparse(s,hd->cc,s2);
			}
			else
			{
				send("Nothing changed.");
				cr(1);
			}
			return(0);
		}
	}
}

view()
{
	int n,inh;
	char c;
	struct header *hd;
	char s[LLEN];

	hd = msghd[pointer];

	inh = open(hd->file,2);

	n = 0;
	cls();

	for(; getline(inh,s) != -1;)
	{
		++n;
		n += strlen(s) / 80;
		send(s);
		cr(1);
		
		if (n > 23)
		{
			send("\033p - More - \033q");
			if (inp() == 'q')
			{
				close(inh);
				window();
				return(0);
			}
			
			send("\033l");
			n = 0;
		}
	}

	close(inh);
	send("\033p - End of file - \033q");
	inp();
	window();
}
	




twhatnow(s,s2)
char *s,*s2;
{
	char c;
	int n;

	for (;;)
	{
		send(s);
		send(" ");
		c = inp();
		cr(1);

		if ((linstr(s2,c) == -1) || (c == '\0'))
		{
			locate(1,22);
			send("Ambigous! ");
		}
		else
		{
			return(linstr(s2,c) + 1);
		}
	}
}





save()
{
	static char s[LLEN + 10],s2[LLEN];
	long dmy;
	struct header *head;
	int inh,outh;

	locate(1,21);
	send("Write message to file: ");
	rec(s);
	trim(s);
	if (!valid(s))
		strcpy("received",s);

	strcpy(home,s2);
	stradd(s,s2);

	lower(s2);

	sprintf(s,"Writing to %s...",s2);
	locate(1,21);
	send("\033l");
	center(s);

	head = msghd[pointer];


	inh = open(head->file,2);

	locate(1,22);
	if (exist(s2) == TRUE)
	{
		center("- Appending -");
		outh = open(s2,4);
	}
	else
	{
		center("- Creating new file -");
		outh = open(s2,1);
	}

	for (;;)
	{
		dmy = sys_fread(inh,200l,s);
		sys_fwrite(outh,dmy,s);
		if (dmy < 200l)
			break;
	}

	uu_putline(outh,"");
	close(outh);
	close(inh);
#if 0
	locate(1,21);
	send("\033l");
	
	locate(1,22);
	send("\033l");
#endif
	++need;
}





	
	

sendmail(opt)
char opt;
{
	int n,inh,outh;
	static char s[LLEN],s2[LLEN],s3[LLEN],s4[LLEN];
	static char orgline[LLEN];
	struct header *hd;
	static char temp[LLEN];
	struct header *head;

	hd = (struct header *)malloc((long)sizeof(struct header));
	bzero(hd,(long)sizeof(struct header));
	
	getconf(3,orgline);


	/* handle reply */
	if (opt == 'r')
	{
		head = msghd[pointer];
		head = gethead(head->file);

		if (valid(head->replyto))
		{
			strcpy(head->replyto,hd->to);
			if (valid(head->replytofull))
				strcpy(head->replytofull,hd->tofull);
		}
		else
			if (valid(head->from))
			{
				strcpy(head->from,hd->to);
				if (valid(head->fromfull))
					strcpy(head->fromfull,hd->tofull);
			}
			else
			if (valid(head->apparent))
			{
				strcpy(head->apparent,hd->to);
				if (valid(head->apparentfull))
					strcpy(head->apparentfull,hd->tofull);
			}
			else
				if (valid(head->sender))
				{
					strcpy(head->sender,hd->to);
					if (valid(head->senderfull))
						strcpy(head->senderfull,hd->tofull);
				}

				
		if (valid(hd->to))
		{
			locate(1,21);
			send("\033lReceiver: ");
			send(hd->to);
			if (valid(hd->tofull))
			{
				send(" (");
				send(hd->tofull);
				send(")");
			}
		}

		if (valid(head->subject))
		{
			strcpy(head->subject,s);
			s[3] = '\0';
			if (strcmp(s,"Re:") != TRUE)
				sprintf(hd->subject,"Re: %s",head->subject);
			else
				sprintf(hd->subject,"%s",head->subject);
		}
		else
			strcpy("Re: (none)",hd->subject);

		locate(1,22);
		send("\033lSubject: ");
		send(hd->subject);
		send("\033K");
		
		mfree((long)head);
	} /* Reply */


	
	/* handle forwarding */
	if (opt == 'f')
	{
		head = msghd[pointer];
		sprintf(hd->subject,"Forwarded: %s",head->subject);

		locate(1,22);
		send("\033lSubject: ");
		send(hd->subject);
	} /* Forwarding */

	
	/* Non-interactive (direct) mode */
	if (opt == 'd')
	{
		strcpy(receiver,hd->to);
		locate(1,21);
		send("\033lReceiver: ");
		send(hd->to);
	} /* direct mode */


	

	if (!valid(hd->to) || (opt == 'f'))
	{
		locate(1,21);
		send("\033lReceiver: ");
		rec(s);
		adrparse(s,hd->to,hd->tofull);
	}

	trim(hd->to);
	if (!valid(hd->to))
	{
		locate(1,21);
		send("\033l");
		send("Mail failed: no receiver specified.");
		locate(1,22);
		send("\033l");
		++need;
		return(0);
	}

	if (!valid(hd->subject))
	{
		locate(1,22);
		send("\033lSubject: ");
		rec(hd->subject);
	}
	
	trim(hd->subject);
	if (!valid(hd->subject))
	{
		locate(1,22);
		send("\033lSubject: (none)");
		strcpy("(none)",hd->subject);
	}

	strcpy(tmpdir,temp);
	mktmp(temp);

	if (opt == 'f')
	{
		sys_fcopy(head->file,temp);

#if 0
		locate(1,21);
		send("\033lMail to ");
		send(hd->to);
#endif
	

#if 0		/* Too much bla again... */
		locate(1,22);
		send("\033l");
		n = twhatnow("Edit message? yes, no, cancel?","ync");
	
		if (n == 3)
		{
			window();
			return(0);
		}
	
		if (n == 2)
			goto norm_whatagain;
#else
		goto norm_whatagain;

#endif
	}

	if (opt == 'r')
	{
		locate(35,25);
		send("- Quoting -");
		head = msghd[pointer];
		inh = open(head->file,2);
		if (inh < 0)
		{
			send("Error opening ");
			send(head->file);
					send(" as input.");
						cr(1);
						return(-1);
					}

					outh = open(temp,1);
					if (outh <= 0)
					{
						/* Oh no damned bugs... */
						send("Error opening ");
						send(temp);
						send(" as output.");
						cr(1);
						return(-1);
					}

					strcpy("In ",s2);
					if (valid(head->id))
						stradd(head->id,s2);
					else
						stradd("your letter",s2);
					stradd(", you write:",s2);

					putline(outh,s2);


					while (getline(inh,s) != -1)
					{
						strcpy("> ",s2);
						stradd(s,s2);
						putline(outh,s2);
					}

					close(inh);
					close(outh);
					
	}
	

	locate(1,25);
	center("- Invoking editor -");

	strcpy(temp,s2);

normed_again:
	edi(temp);
	window();

norm_whatagain:
	locate(1,21);
	send("Mail to ");
	send(hd->to);
	trim(hd->tofull);

	if (valid(hd->tofull));
	{
		send(" (");
		send(hd->tofull);
		send(")");
	}
	send("\033K");


	locate(1,22);
	n = twhatnow("What now? Edit, Send, Cancel, DES-Encrypt, Options?","escdo");
	switch(n)
	{
	case 1:	
		goto normed_again;
	case 2: 
		break;
	case 3:
		{
			locate(1,21);
			send("\033l");
			center("- Cancelled -");
			locate(1,22);
			send("\033l");
			++need;
			goto norm_cancel;
		}
	case 4:
		{
			mail_encrypt(temp);
			goto norm_whatagain;
		}
	case 5:
		{
			m_options(hd);
			window();
			goto norm_whatagain;
		}
	}


	strcpy(logname,hd->from);
	strcpy(fullname,hd->fromfull);
	strcpy(orgline,hd->organization);

	sys_mail(temp,hd);

#if 0
	bcc:
	locate(1,22);
	send("\033lBcc: ");
	rec(s);
	trim(s);
	locate(1,22);
	send("\033l");
	if (valid(s))
	{
		adrparse(s,hd->to,hd->tofull);
		if (valid(hd->to))
		{
			sys_mail(temp,hd);
			locate(1,22);
			send("\033l");
			center("- Bcc okay -");
		}
		else
		{
			locate(1,22);
			send("\033l");
			center("- Invalid receiver -");
		}
		goto bcc;
	}
#endif
	

	locate(1,21);
	send("\033l");
	center("- Mail sent -");
	++need;

norm_cancel:
	mfree(hd);
	if (remote)
	{
		locate(1,24);
		cr(1);
		exit(0);
	}
	return(0);
}


int killthem()
{
	int i;
	for (i = 0; i < msganz; i++)
	{
		if (*title[i] == 'D')
			return(1);
	}
	return(0);
}



sfold()
{
	char s[LLEN];
	char s2[LLEN];
	char atr;
	long l;
	int clup;



	clup = 0;
	if (killthem())
	{
		locate(1,21);
		send("You have marked some messages as deleted.");
		locate(1,22);
		switch(twhatnow("R)emove them, k)eep them or r)emain in this folder?","Rkr"))
		{
			case 1:
			{
				++clup;
				cleanup();
				break;
			}

			case 3:
			{
				locate(1,22);
				send("\033l");
				locate(1,21);
				send("\033l");
				center("- Remaining in this folder -");
				++need;
				return(0);
			}
		}
	}
	locate(1,22);
	send("\033l");
	locate(1,21);
	send("\033l");
	send("Select folder: ");
	rec(s);
	trim(s);

#if 0
	lower(s);
#endif

	if (strcmp(s,"std") == TRUE)
		strcpy("",s);

	if (strcmp(s,"..") == TRUE)
		strcpy("",s);

	if (strcmp(s,"standard") == TRUE)
		strcpy("",s);

	if (strcmp(s,"home") == TRUE)
		strcpy("",s);

	if (!valid(s))
	{
		if (clup)
			return(1);
		
		if (strcmp(folder,home) != TRUE)
		{
			strcpy(home,folder);
			return(1);
		}

		locate(1,21);
		send("\033l");
		center("- Remainig in standard folder -");
		++need;

		return(0);
	}
	
	strcpy(home,s2);
	stradd(s,s2);
	sys_impdirn(s2);
	s2[strlen(s2) - 1] = '\0';

	locate(1,21);
	send("\033l");

	++need;
	
	if (sfirst(s2) >= 0)
	{
		dtaxtr(s,&l,&atr);

		if (atr == 16)
		{
			strcpy(s2,folder);
			sys_impdirn(folder);
			return(1);
		}
		else
		{
			center("- You must supply a folder's name -");
			if (clup)
				return(1);
			else
				return(0);
		}

	}
	else
	{
		center("- No match -");
		if (clup)
			return(1);
		else
			return(0);
	}
}




move(mode)
char mode;
{
	char s[LLEN];
	char s2[LLEN];
	char atr;
	long l;
	int n;
	struct header *hd;

	mode = (mode == 'm') ? 1 : 0;

	locate(1,21);
	if (mode)
		send("Move to folder: ");
	else
	{
		send("Duplicate to folder: ");
		++need;
	}

	rec(s);

	trim(s);
	if (!valid(s))
	{
		locate(1,21);
		send("\033l");
		center("- No such folder -");
		++need;
		return(0);
	}


	strcpy(home,s2);

	if ((strcmp(s,"std") != TRUE) && (strcmp(s,"standard") != TRUE)
	&& (strcmp(s,"home") != TRUE) && (strcmp(s,"..") != TRUE))
			stradd(s,s2);


	sys_impdirn(s2);

	if ((!mode) && (strcmp(s2,folder) == TRUE))
	{
		locate(1,21);
		send("\033l");
		center("- Illegal operation -");
		++need;
		return(0);
	}

	
	s2[strlen(s2) - 1] = '\0';

	if (sfirst(s2) >= 0)
	{
		dtaxtr(s,&l,&atr);

		if (atr == 16)
		{
			sys_impdirn(s2);
			mktmp(s2);
			stradd(".msg",s2);
			
			hd = msghd[pointer];
			if (sys_fcopy(hd->file,s2) == -1)
			{
				locate(1,21);
				send("\033l");
				center("- Copy failed -");
				++need;
				return(0);
			}

			if (mode)
			{
				sys_remove(hd->file);

				--msganz;

				for (n = pointer; n < msganz; n++)
					msghd[n] = msghd[n + 1];

				if (pointer >= msganz)
					--pointer;
			}
			return(1);
		}
		else
		{
			locate(1,21);
			send("\033l");
			center("- You must specify a folder's name -");
			++need;
			return(0);
		}

	}
	
	locate(1,21);
	send("\033l");
	center("- No such folder -");
	++need;
	return(0);
}



cleanmsg()
{
	int i;

	for (i = 0; i < msganz; i++)
		mfree((long)msghd[i]);
}

sort()
{
	static struct header *hd[MAXMSG],*head;
	struct dta *dta;
	unsigned int dlist[MAXMSG];
	unsigned int dmax,dmin,l,age;
	unsigned int i,n;



	dmin = 65000;
	dmax = 0;	


	for (i = 0; i < msganz; i++)
	{
		head = msghd[i];
		hd[i] = head;

#if 0
		sfirst(head->file);
		dta = getdta();
#endif

		age = e_age((char *)(head->date));
		
		if (age > dmax)
			dmax = age;

		if (age < dmin)
			dmin = age;

		dlist[i] = age;

#if DEBUG
		send("dlist [");
		sendd(i);
		send("] == ");
		sendd(dlist[i]);
		cr(1);
#endif
	}
	++dmax;
	--dmin;


#if DEBUG
	printf("Dmax: %d Dmin: %d\n",dmax,dmin);
	inp();
#endif

	
	n = 0;
	for (l = (unsigned int)dmax; l != (unsigned int)dmin; l--)
	{
		for (i = (unsigned int)0; i < msganz; i++)
		{
			if ((dlist[i] == (unsigned int)l) && (l != 0))
			{
				
				msghd[n++] = hd[i];
				dlist[i] = 0l;
			}
		}
	}
}





e_age(hdate)
char *hdate;
{
	static char s[LLEN],s2[LLEN],*p;
	int day,month,time;
	unsigned int l;

	static char *monthname[] = {
					"Jan", "Feb", "Mar", "Apr",
					"May", "Jun", "Jul", "Aug",
					"Sep", "Oct", "Nov", "Dec",
					""
	};

	
	/*

	-+ Possible time stamps +-
	
	Wed, 13 Jun 90 16:00:57
	Mon 11 Jun 1990 21:57
	11 Jun 1990 21:57 (Mon)
	Tue Jun 12 01:05:50 1990
	*/

	/* Get date */

	strcpys(hdate,s2,0,linstr(hdate,' ') - 1);
	if (val(s2) > 0)
	{
		p = hdate;
#if DEBUG
		printf("No skip. %s\n",p);
#endif
	}
	else
	{
		for (p = hdate; *p != ' '; ++p);
		++p;
#if DEBUG
		printf("Skipped to: %s\n",p);
#endif
	}

	/* now p points to dayofmonth or to monthname. */
	strcpys(p,s,0,linstr(p,' ') - 1);

#if DEBUG
	printf("First arg: %s\n",s);
#endif
	
	if (strlen(s) < 3)
	{
		day = val(s);
		for (; *p != ' '; ++p);
		++p;
		strcpys(p,s,0,linstr(p,' ') - 1);
		for (month = 0; (strcmp(s,monthname[month]) != TRUE) && (month < 12); ++month);
	}
	else
	{
		for (month = 0; (strcmp(s,monthname[month]) != TRUE) && (month < 12); ++month);
		for (; *p != ' '; ++p);
		++p;
		strcpys(p,s,0,linstr(p,' ') - 1);
		day = val(s);
	}

#if DEBUG
	printf("Day/month: %d %d\n",day,month);
#endif
	
	for (p = hdate; *p != ':'; p++);
	for (; *p != ' '; --p);
	++p;

	strcpys(p,s,0,linstr(p,':') - 1);
	time = val(s);

	l = time;
	l += (day * 24);
	l += (month * 24 * 32);

	return(l);
}




cleanup()
{
	int n,i;
	struct header *mhd[MAXMSG],*hd;
	
	locate(1,21);
	if (killthem() != 0)
	{
		center("- Removing marked messages -");
	
		for (n = 0; n < msganz; ++n)
		{
			mhd[n] = msghd[n];
			
			if (*title[n] == 'D')
			{
			 	hd = msghd[n];
				
				if (sys_remove((char *)hd->file) < 0)
				{
					printf("Couldn't remove %s\n",hd->file);
					gemerror(sys_remove(hd->file));
					cr(1);
					exit(0);
				}
			}

 		}
		
		for (i = n = 0; n < msganz; n++)
		{
			if (*title[n] != 'D')
				msghd[i++] = mhd[n];
		}
		msganz = i;

		if (msganz == 0)
			exit(0);

		while (pointer >= msganz)
			--pointer;

		return(1);
	}
	else
	{
		center("- No messages marked -");
		return(0);
		++need;
	}
}

	

   
