#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <utility/tagitem.h>
#include <dos/dostags.h>
#include <clib/dos_protos.h>
#include <dos.h>
#include <time.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <libraries/dosextens.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <libraries/locale.h>
#include <proto/locale.h>

/* These are only used in ks1.3 , in 2.0 we use System() */
long SyncRun(char *,char *,BPTR,BPTR);
#pragma libcall ArpBase SyncRun                 021C    109804
struct 	Library *ArpBase=NULL;

#include "/lib/iomodes.h"
#include "/lib/misc.h"
#include "/lib/users.h"

int tolower(int);

#include "mail.h"

#define STRINGARRAY
#include "maillanguage.h"

#define MAXMSGS		120

void __regargs __chkabort(void);
void __regargs __chkabort(void){}

void chkabort(void) {}

extern struct DosLibrary *DOSBase;
struct Library *LocaleBase=NULL;
struct Catalog *catalog=NULL;

static const char vers[]="$VER: AMI 1.6 (31.3.95)";


char	mailhome[128]="AXsh:usr/spool/mail/",
		passwdfile[80]="AXsh:etc/passwd",
		user[64]="root",
		language[80]="",
		editor[80]="editor",
		home[128]="AXsh:home/root/",
		thismachine[64]="demo",
		realname[128]="Pasi 'Albert' Ojala",
		organization[128]="AXsh";
char	Sendmail[MAXLINELEN]="internal",
		Routetable[MAXLINELEN]="AXsh:usr/spool/mail/Routetable",
		Aliasfile[MAXLINELEN]="AXsh:usr/spool/mail/Mailaliases",
		Spooldir[MAXLINELEN]="AXsh:usr/spool/outgoing/%s/",
		Timezone[10]="GMT";
int 	numberofmsgs,
		lastread=0,
		rows=24,
		lowest=0,curpos=0,curframe=0;
BOOL	flag[MAXMSGS],group_reply=FALSE,
		reply=FALSE;

struct message
{
	char	from[MAXNAMELEN];
	char	cc[MAXNAMELEN];
	char	date[MAXNAMELEN];
	char	subject[MAXNAMELEN];
	int		size;
	int		length;
	long	firstchar;
};


struct message	messagelist[MAXMSGS];

long MyRunCommand(char *,char *,BPTR,BPTR);

void cleanexit(int error);
void openthings(void);
void getstring(char *CommandString, BOOL echo, BOOL cursors);
int  scanmsgs(void);
void readconfig(void);
void mailmenu(void);
void generatemail(char *to,char *sub,char *cc, int inc);
void deletemsg(int msg);
void readmsg(int msg);
void savemsg(char *name);
void updateheaderscreen(void);
void updatestatusline(BOOL newmail);
void parsefrom(char *emailaddr,char *str);
int  check_mail(char *mailhome,char *loginname);


long MyRunCommand(char *command,char *args,BPTR in,BPTR out)
{
	struct TagItem stags[3];
	static char commandbuffer[256];

	if(!in)
		in=Input();
	if(!out)
		out=Output();

	if(ArpBase)
		return (SyncRun(command,args,in,out));
	else
	{
		sprintf(commandbuffer,"%s %s\n",command,args);
		stags[0].ti_Tag = SYS_Input;
		stags[0].ti_Data= in;
		stags[1].ti_Tag = SYS_Output;
		stags[1].ti_Data= out;
		stags[2].ti_Tag = TAG_DONE;
		return(System(commandbuffer, stags));
	}
}


void cleanexit(int error)
{
	if(ArpBase)
	{
		setmode(MODE_CONSOLE);
		CloseLibrary(ArpBase);
	}
	else
	{
		SetMode(Input(),MODE_CONSOLE);
	}

	if(LocaleBase)
	{
		if(catalog)
			CloseCatalog(catalog);
		CloseLibrary(LocaleBase);
	}
	printf("\033[%d;1H\n\n",rows-1);
	exit(error);
}

void openthings(void)
{
	int i;

	if(DOSBase->dl_lib.lib_Version<36)
	{
		if(!(ArpBase=(struct Library *)OpenLibrary("arp.library",39)))
		{
			printf("\aCannot open arp.library\n");
			cleanexit(10);
		}
		setmode(MODE_RAW);
	}
	else
		SetMode(Input(),MODE_RAW);

	/* Let's see if we're running on 2.1 .. :-) */
	LocaleBase=OpenLibrary("locale.library",38L);
	for(i=0;i<MAXMSGS;i++)
		flag[i]=FALSE;
}


char *printout(ULONG strnum)
{
	if(catalog)
		return (char *)GetCatalogStr(catalog,strnum,AppStrings[strnum].as_Str);
	else
		return (char *)AppStrings[strnum].as_Str;
}


#define M_NOR	0
#define M_ESC	1
#define M_CSI	2

void getstring(char *a, BOOL echo, BOOL cursors)
{
	int i=0,found=0;
	int mode=M_NOR;
	const int b=79;
	unsigned char c;

	printf("\033[%d;0H\033[K$",rows-1);
	fflush(stdout);
    while(!found)
	{
		if(curpos>=numberofmsgs)
		{
			curpos=numberofmsgs-1;
			updateheaderscreen();
		}
		c=0;
		if(WaitForChar(Input(),4000000))
		{
			if(Read(Input(),&c,1)<1)
				cleanexit(0);
		}

		if(c==0x03 || (SetSignal(0,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
		{
			printf(printout(MSG_BREAK));
			cleanexit(0);
		}
		if(!c)
			continue;
							/* ^n        ^p */
		if(mode==M_NOR && (c==0x0e || c==0x10))
		{
			mode=M_CSI;
			if(c==0x0e)
				c='B';
			else
				c='A';
		}

		if(mode==M_NOR)
		{
			switch(c)
			{
			case 0x0a:
			case 0x0d:
				found=1;
   				a[i]=0;
				break;
			case 0x7f:
			case 0x08:
				if(i>0)
				{
					if(echo)
						printf("\033[%d;%dH \010",rows-1,i+1);
					i--;
				}
				break;
			case 0x09:
				flag[curpos]=!flag[curpos];
				printf("\033[%d;2H%c",1+curpos-curframe*(rows-3),flag[curpos]?0x2a:0x20);
				break;
			case 0x1b:
				mode=M_ESC;
				break;
			case 0x9b:
				mode=M_CSI;
				break;
			default:
				if(i<b-2 && c>0x1f && (c<0x80 || c>0x9f))
				{
					a[i++]=c;
					if(echo)
						printf("\033[%d;%dH%c",rows-1,i+1,c);
				}
			}
		}
		else
		if(mode==M_ESC)
		{
			if(c=='[')
				mode=M_CSI;
			else
				mode=M_NOR;
		}
		else
		if(mode==M_CSI)
		{
			if(cursors)
			{
				switch(c)
				{
				case 'A':
					if(--curpos<0)
					{	curpos=0;
					}
					else
					{	if((curpos%(rows-3))==rows-4)
							updateheaderscreen();
						else
							printf("\033[%d;0H \033[%d;0H>",curpos+2-curframe*(rows-3),curpos+1-curframe*(rows-3));
					}
					break;
				case 'B':
					if(++curpos>=numberofmsgs)
					{	curpos=numberofmsgs-1;
					}
					else
					{
						if(curpos==(curframe+1)*(rows-3))
							updateheaderscreen();
						else
							printf("\033[%d;0H \033[%d;0H>",curpos-curframe*(rows-3),curpos+1-curframe*(rows-3));
					}
					break;
				}
			}
			mode=M_NOR;
		}
		fflush(stdout);
	}
}


int scanmsgs(void)
{
	FILE	*fp;
	char	thisline[MAXNAMELEN],temp[MAXNAMELEN];
	int		length=0,size=0,mode,
			counter=0,count=0;
	long	prevpos;

	sprintf(temp,"%s%s",mailhome,user);
	if(!(fp=fopen(temp,"r")))
	{
		return 0;
	}

	messagelist[0].firstchar=ftell(fp);
	mode=1;	/* search for end of the header */
	while(!feof(fp) && counter<MAXMSGS)
	{
		prevpos=ftell(fp);
		if(fgets(thisline,MAXNAMELEN,fp)==0)
			break;

		if(feof(fp))
			break;

		count++;
		length++;

		if(mode==0)	/* message body or between :-) */
		{
			if( !strnicmp(thisline,"From ",5))
			{
				messagelist[counter].length=length-1;
				messagelist[counter++].size=size;
				length=1;
				size=0;
				messagelist[counter].firstchar=prevpos;

				messagelist[counter].from[0]=0;
				messagelist[counter].cc[0]=0;
				messagelist[counter].date[0]=0;
				messagelist[counter].subject[0]=0;

				mode=1;
			}
		}
		else
		if(mode==1)
		{
			if(thisline[0]=='\n' ||
				thisline[0]=='\r' ||
				!strcmp(thisline,".\n"))	/* end of header/message */
				mode=0;

			if(!strnicmp("From: ",thisline,6))
			{
				strcpy(messagelist[counter].from,thisline+6);
				messagelist[counter].from[strlen(messagelist[counter].from)-1]=0;

			}
			if(!strnicmp("Cc: ",thisline,4))
			{
				strcpy(messagelist[counter].cc,thisline+4);
				messagelist[counter].cc[strlen(messagelist[counter].cc)-1]=0;
			}
			if(!strnicmp("Date: ",thisline,6))
			{
				strcpy(messagelist[counter].date,thisline+6);
				messagelist[counter].date[strlen(messagelist[counter].date)-1]=0;
			}
			if(!strnicmp("Subject: ",thisline,9))
			{
				strcpy(messagelist[counter].subject,thisline+9);
				messagelist[counter].subject[strlen(messagelist[counter].subject)-1]=0;
			}
		}
		size+=strlen(thisline);
	}
	if(length)
	{
		messagelist[counter].length=length;
		messagelist[counter++].size=size;
	}
	messagelist[counter].firstchar = ftell(fp);
	fclose(fp);
	return counter;
}


void readconfig(void)
{
	FILE	*fp;
	char	thisline[82],
			nextline[82],
			temp[82];

	if(fp=fopen("AXsh:etc/rc","rb"))
	{
		while(!feof(fp))
		{
			if(fgets(thisline,80,fp)==0)
				break;

			if(thisline[0]=='%')
			{
				if(fgets(nextline,80,fp)==0)
					break;
				nextline[strlen(nextline)-1]=0;

				if(!strnicmp("%passwdfile:",thisline,12))
					strncpy(passwdfile,nextline,80);
				if(!strnicmp("%thismachine:",thisline,13))
					strcpy(thismachine,nextline);
				if(!strnicmp("%organization:",thisline,14))
					strcpy(organization,nextline);
				if(!strnicmp("%spooldir:",thisline,10))
					strcpy(Spooldir,nextline);
				if(!strnicmp("%timezone:",thisline,10))
				{
					strncpy(Timezone,nextline,9);
					Timezone[9]=0;
				}
			}
		}
		fclose(fp);
	}
	else
	{
		printf(printout(MSG_NO_RC));
		cleanexit(0);
	}

	if(fp=fopen("AXsh:etc/rc.mail","rb"))
	{
		while(!feof(fp))
		{
			if(fgets(thisline,80,fp)==0)
				break;
			if(thisline[0]=='%')
			{
				if(fgets(nextline,80,fp)==0)
					break;
				nextline[strlen(nextline)-1]=0;

				if(!strnicmp("%mailhome:",thisline,10))
					strcpy(mailhome,nextline);
				if(!strnicmp("%sendmail:",thisline,10))
					strcpy(Sendmail,nextline);
				if(!strnicmp("%routetable:",thisline,12))
					strcpy(Routetable,nextline);
				if(!strnicmp("%aliasfile:",thisline,11))
					strcpy(Aliasfile,nextline);
			}
		}
		fclose(fp);
	}

    /* read user's config */
	if(ArpBase)
	{
		who(COM_GET,NULL,"user",user);
		who(COM_GET,NULL,"home",home);
		who(COM_GET,NULL,"language",language);
		who(COM_GET,NULL,"realname",realname);
		who(COM_GET,NULL,"visual",editor);	/* default was 'editor' */
		who(COM_GET,NULL,"rows",temp);
	}
	else
	{
		GetVar("user", user, sizeof(user), GVF_LOCAL_ONLY);
		GetVar("home", home, sizeof(home), GVF_LOCAL_ONLY);
		GetVar("language", language, sizeof(language), GVF_LOCAL_ONLY);
		GetVar("realname", realname, sizeof(realname), GVF_LOCAL_ONLY);
		GetVar("visual", editor, sizeof(editor), GVF_LOCAL_ONLY);
		GetVar("rows", temp, sizeof(temp), GVF_LOCAL_ONLY);
	}
	rows=atoi(temp);
	if(!rows)	rows=24;	/* default */
	if(rows<4)	rows=20;
	if(rows>100)	rows=100;
}


void updateheaderscreen(void)
{
	int i=0,last,first;
	char temp[160];

	while(curpos>=i)
		i+=rows-3;
	if((curframe=i/(rows-3)-1)<0) curframe=0;
	if((last=(curframe+1)*(rows-3))>numberofmsgs)
		last=numberofmsgs;

	for(i=first=curframe*(rows-3);i<last;i++)
	{
		printf("\033[%d;0H",(i-first+1));
		if(curpos==i)
			printf(">");
		else
			printf(" ");

		if(flag[i])
			printf("*");
		else
			printf(" ");
		printf("%2d",i+1);
		parsefrom(temp,messagelist[i].from);
		strcat(temp,"                        ");

		if(messagelist[i].date[3]==',')
			sprintf(temp+22," %-s                       ",messagelist[i].date+5);
		else
			sprintf(temp+22," %-s                       ",messagelist[i].date);

		sprintf(temp+49," %s",messagelist[i].subject);
		temp[71]=0;
		printf(" %s\033[K",temp);
	}

/*	I had to write these words down somewhere and it seemed .. it seemed..
	it seemed like here was some free space :-)

	Ironbound/Fancy Poultry
	~~~~~~~~~~~~~~~~~~~~~~~

	In the Ironbound section					In the Ironbound section
	Near Avenue L								Near Avenue L
	Where the Potuguese women					Where the Potuguese women
	Come to see what you sell					Come to see what you sell
	With the coulds so low						With the coulds so low
	The morning so slow							The morning so slow
	As the wires cut through the sky			As the wires cut through the sky

	The beams and bridges						She stops at the stall
	Cut the light on the ground					Fingers the ring
	Into little triangles						Opens her purse and feels a longing
	And the rails run round						Away from the Ironbound border
	Through the rust and heat
	The light and sweet							"Fancy poulty
	Coffee color of her skin					Parts sold here
	Bound up in iron and wire and fate			Breasts and thighs and hearts
	Watching her walk him up to the gate		Backs are cheap
	In front of the Ironbound schoolyard		And wings are nearly
												Fancy poultry
	Kids will grow like weeds on a fence		Parts sold here
	She says they look for the light			Breasts and thighs and hearts
	They try to make sense						Backs are cheap
	They come up through the cracks				And wings are nearly
	Like grass on the tracks					Free"
	And she touches him goodbye					Nearly free
												Nearly free
	Steps off the curb and into the street
	The blood and the feathers near her feet
	Into the Ironbound market					-Suzanne Vega 1987 */


	if(lowest>rows-2) lowest=rows-2;
	if(last-first+1<lowest)
	{
		for(i=last-first+1;i<lowest;i++)
			printf("\033[%d;0H\033[K",i);
	}
	lowest=last-first+1;
	fflush(stdout);
}

void updatestatusline(BOOL newmail)
{
	if(!newmail)
		printf(printout(MSG_AMI_STATUS),rows-2,vers+6);
	else
		printf(printout(MSG_AMI_STATUS_NEW_MAIL),rows-2,vers+6);
	fflush(stdout);
}


void mailmenu(void)
{
	FILE	*fp,*fp2;
	int		i,j,messu;
	char 	com[128],temp[128],to[160],subject[160];
	BOOL	exitbit=FALSE,
			show_headers=TRUE;

	sprintf(com,"%s.mailrc",home);
	if(!(fp=fopen(com,"r")))
	{
		if(!(fp=fopen(com,"w")))
		{
			printf(printout(MSG_CANT_CREATE),".mailrc");
		}
		else
		{
			fprintf(fp,"%d\n",lastread);
			fclose(fp);
		}
	}
	else
	{
		fgets(com,10,fp);
		curpos=lastread=atoi(com);
		fclose(fp);
	}
	com[0]=0;
	numberofmsgs=scanmsgs();
	if(!numberofmsgs)
	{
		printf(printout(MSG_NO_MAIL_FOR),user);
		sprintf(temp,"%s%s",mailhome,user);
		DeleteFile(temp);
		cleanexit(0);
	}

	if(lastread>numberofmsgs)
		lastread=numberofmsgs;
	if(lastread<1)
		lastread=1;
	updatestatusline(FALSE);
	while(!exitbit)
	{
		if(!numberofmsgs)
			break;

		if(check_mail(mailhome,user))
		{
			numberofmsgs=scanmsgs();
			updatestatusline(TRUE);
			if(lastread>numberofmsgs)
				lastread=numberofmsgs;
			if(lastread<1)
				lastread=1;
			updateheaderscreen();
			printf("\a");
			fflush(stdout);
		}
		if(curpos>=numberofmsgs)
			curpos=numberofmsgs-1;
		if(!show_headers)
		{
			getstring(com,TRUE,TRUE);
		}
		if(!strcmp("g",com) || !strcmp("give",com))
		{
			j=FALSE;
			for(i=0;i<numberofmsgs;i++)
			{
				if(flag[i])
				{
					if(lastread<i+1)
						lastread=i+1;
					flag[i]=!flag[i];	/* now what the heck is this doing :-) */
					readmsg(i);
					j=TRUE;
					printf(printout(MSG_AMI_ANYKEY));
					fflush(stdout);
					while(!WaitForChar(Input(),5000000));
					Read(Input(),temp,1);
				}
			}
			if(j)
			{
				lowest=1;
				updatestatusline(FALSE);
				updateheaderscreen();
			}
		}
		if(!com[0] && !show_headers)
		{
			readmsg(curpos);
			printf(printout(MSG_AMI_ANYKEY));
			fflush(stdout);
			while(!WaitForChar(Input(),50000000));
			Read(Input(),temp,1);

			lowest=1;
			updatestatusline(FALSE);
			updateheaderscreen();
		}
		if(!strcmp("h",com) || !strcmp("headers",com) || show_headers)
		{
			show_headers=FALSE;
			updateheaderscreen();
		}
		if(com[0]=='?')
		{
			printf(printout(MSG_AMI_HELP1));
			printf(printout(MSG_AMI_HELP2));
			printf(printout(MSG_AMI_HELP3));
			lowest=21;
			printf(printout(MSG_AMI_ANYKEY));
			fflush(stdout);
			while(!WaitForChar(Input(),60000000));
			Read(Input(),temp,1);

			updateheaderscreen();
		}
		if(!strcmp("x",com) || !strcmp("exit",com))
			exitbit=TRUE;

		if(!strcmp("q",com) || !strcmp("quit",com))
		{
			if(numberofmsgs)
			{
				sprintf(temp,"%s%s",mailhome,user);
				if(fp=fopen(temp,"r"))
				{
					sprintf(temp,"%smbox",home);
					if(fp2=fopen(temp,"a"))
					{
						while(temp[0])
						{
							if(fgets(temp,80,fp)==0)
								break;
							fputs(temp,fp2);
						}
						fclose(fp2);
					}
					else
					{
						printf(printout(MSG_CANT_OPEN),"mbox");
						cleanexit(0);
					}
					fclose(fp);
				}
				else
				{
					printf(printout(MSG_CANT_OPEN),temp);
					cleanexit(0);
				}
			}
			sprintf(temp,"%s%s",mailhome,user);
			if(!DeleteFile(temp))
				printf(printout(MSG_CANT_DELETE),temp);
			lastread=1;
			printf(printout(MSG_SAVED_MESSAGES),numberofmsgs,"mbox");
			exitbit=TRUE;
		}

		if(!strncmp("s ",com,2) || !strncmp("save ",com,5))
		{
			j=0;
			while(com[j]!=' ') j++;
			while(com[j]==' ') j++;
			for(i=0;i<numberofmsgs;i++)
			{
				if(flag[i])
				{
					lastread=i+1;
					savemsg(com+j);
					flag[i]=FALSE;
				}
			}
			updateheaderscreen();
		}

		if(!strcmp("r",com) || !strcmp("reply",com))
		{
			group_reply=FALSE;reply=TRUE;
			for(j=0;j<numberofmsgs;j++)
			{
				if(flag[j])
				{
					if(strnicmp(messagelist[j].subject,"Re:",3))
						sprintf(subject,"Re:%s",messagelist[j].subject);
					else
						strcpy(subject,messagelist[j].subject);
					parsefrom(to,messagelist[j].from);
					/* get the E-mail address */
					generatemail(to,subject,"",-1);
					flag[j]=FALSE;
				}
			}
			updatestatusline(FALSE);
			numberofmsgs=scanmsgs();
			updateheaderscreen();
		}

		if(!strcmp("R",com) || !strcmp("ccreply",com))
		{
			group_reply=reply=TRUE;
			for(j=0;j<numberofmsgs;j++)
			{
				if(flag[j])
				{
					if(strnicmp(messagelist[j].subject,"Re:",3))
						sprintf(subject,"Re:%s",messagelist[j].subject);
					else
						strcpy(subject,messagelist[j].subject);
					parsefrom(to,messagelist[j].from);

					generatemail(to,subject,messagelist[j].cc,-1);
					flag[j]=FALSE;
				}
			}
			updatestatusline(FALSE);
			numberofmsgs=scanmsgs();
			updateheaderscreen();
		}
		if(!strcmp("r!",com) || !strcmp("reply!",com))
		{
			group_reply=FALSE;reply=TRUE;
			for(j=0;j<numberofmsgs;j++)
			{
				if(flag[j])
				{
					if(strnicmp(messagelist[j].subject,"Re:",3))
						sprintf(subject,"Re:%s",messagelist[j].subject);
					else
						strcpy(subject,messagelist[j].subject);
					parsefrom(to,messagelist[j].from);

					generatemail(to,subject,"",j);
					flag[j]=FALSE;
				}
			}
			updatestatusline(FALSE);
			numberofmsgs=scanmsgs();
			updateheaderscreen();
		}

		if(!strcmp("R!",com) || !strcmp("ccreply!",com))
		{
			group_reply=reply=TRUE;
			for(j=0;j<numberofmsgs;j++)
			{
				if(flag[j])
				{
					if(strnicmp(messagelist[j].subject,"Re:",3))
						sprintf(subject,"Re:%s",messagelist[j].subject);
					else
						strcpy(subject,messagelist[j].subject);
					parsefrom(to,messagelist[j].from);

					generatemail(to,subject,messagelist[j].cc,j);
					flag[j]=FALSE;
				}
			}
			updatestatusline(FALSE);
			numberofmsgs=scanmsgs();
			updateheaderscreen();
		}
		if(!strcmp("d",com) || !strcmp("delete",com))
		{
			messu=0;
			for(i=0;i<numberofmsgs;i++)
			{
				if(flag[i])
				{
					deletemsg(0);
					com[0]=0;
					if(!numberofmsgs) exitbit=TRUE;
					if(lastread>numberofmsgs)	lastread=numberofmsgs;
					updatestatusline(FALSE);
					numberofmsgs=scanmsgs();
					if(curpos>=numberofmsgs)	curpos=numberofmsgs-1;
					updateheaderscreen();
					break;
				}
			}
		}
		if(!strncmp("m ",com,2) || !strncmp("mail ",com,5))
		{
			group_reply=reply=FALSE;
			j=0;
			while(com[j]!=' ') j++;
			while(com[j]==' ') j++;
			strcpy(to,com+j);
			generatemail(to,"","",-1);
			numberofmsgs=scanmsgs();
			updatestatusline(FALSE);
			updateheaderscreen();
		}

		messu=atoi(com);
		if(messu>0 && messu<=numberofmsgs)
		{
			readmsg(messu-1);
			lastread=messu;
		}
	}
	sprintf(com,"%s.mailrc",home);
	if(!(fp=fopen(com,"w")))
	{
		printf(printout(MSG_CANT_OPEN),".mailrc");
	}
	else
	{
		sprintf(com,"%d",curpos);
		fputs(com,fp);
		fclose(fp);
	}
}

void savemsg(char *name)
{
	FILE	*fpsource, *fpdest;
	char	temp[128];
	int		i;

	sprintf(temp,"%s%s",mailhome,user);
	if(fpsource=fopen(temp,"r"))
	{
		sprintf(temp,"%s%s",home,name);
		if(fpdest=fopen(temp,"a"))
		{
			fseek(fpsource,messagelist[lastread-1].firstchar,OFFSET_BEGINNING);

			for(i=0;i<=messagelist[lastread-1].length;i++)
			{
				fgets(temp,100,fpsource);
				fputs(temp,fpdest);
			}
			fclose(fpdest);
		}
		else
			printf(printout(MSG_CANT_OPEN),temp);
		fclose(fpsource);
	}
	else
		printf(printout(MSG_CANT_OPEN),temp);
}

void readmsg(int msg)
{
	FILE	*fp;
	char	temp[128],c;
	int		i,j=0,lines=0;

	printf("\033[0;0H\033[J");
	fflush(stdout);
	sprintf(temp,"%s%s",mailhome,user);
	if(fp=fopen(temp,"r"))
	{
		printf(printout(MSG_MESSAGE),msg+1);
		fseek(fp,messagelist[msg].firstchar,OFFSET_BEGINNING);

		for(i=0;i<messagelist[msg].length;i++)
		{
			fgets(temp,80,fp);
			if(++lines>(rows-2))
			{
				j=0;
				while(!j)
				{
					printf("\033[7m-More-\033[m");
					fflush(stdout);
					while(!WaitForChar(Input(),50000000));
					Read(Input(),&c,1);

					printf("\b\b\b\b\b\b\033[K");
					fflush(stdout);
					switch(c)
					{
					case 'h':
						printf(printout(MSG_PAGER_HELP));
						break;
					case 0x03:
					case 'q':
						j=2;
						break;	/* quit== ok */
					case ' ':
						lines=0;	/* full page */
						j=1;
						break;
					case 0x0a:
					case 0x0d:
						lines--;	/* one line */
						j=1;
						break;
					case 'd':
						lines-=(rows-2)/2+1;	/* half page */
						j=1;
						break;
					default:
						printf(printout(MSG_H_FOR_HELP));
					}
				}
			}
			if(j==2)	break;
			printf("%s",temp);
		}
		fclose(fp);
		printf("\n");
	}
	else
		printf(printout(MSG_CANT_OPEN),temp);
}

void deletemsg(int msg)
{
	FILE	*fpsource,
			*fpdest;
	char	temp[128],
			com[128];
	int		i,l,z,messu=0;
	BOOL	ok=FALSE;

	sprintf(temp,"%s%s",mailhome,user);
	if(fpsource=fopen(temp,"r"))
	{
		sprintf(temp,"%s.%smailtemp",mailhome,user);
		if(fpdest=fopen(temp,"w"))
		{
			for(i=0;i<numberofmsgs;i++)
			{
				if(flag[i])
				{
					flag[i]=FALSE;
				}
				else
				{
					fseek(fpsource,messagelist[i].firstchar,OFFSET_BEGINNING);
					l = messagelist[i].size;
					if(l != messagelist[i+1].firstchar-messagelist[i].firstchar)
					{
						fprintf(stderr, "huihai\n");
					}

					while(l)
					{
						z = 128;
						if(l<128)
							z = l;
						if(!(z = fread(com, 1, z, fpsource)))
							break;
						fwrite(com, 1, z, fpdest);
						l -= z;
					}
					printf("\b");
					switch(messu)	/* A neat Sun boot up emulation :-) */
					{
					case 0:
						printf("-");
						break;
					case 1:
						printf("\\");
						break;
					case 2:
						printf("|");
						break;
					case 3:
						printf("/");
						break;
					}
					messu = (messu+1)&3;
					fflush(stdout);
				}
			}
			fseek(fpsource,messagelist[numberofmsgs].firstchar,OFFSET_BEGINNING);
			while(l = fread(com, 1, 128, fpsource))	/* copy rest, there may be new messages */
			{
				fwrite(com, 1, l, fpdest);
			}
			ok=TRUE;
			fclose(fpdest);
		}
		else
			printf(printout(MSG_CANT_OPEN),temp);
		fclose(fpsource);
	}
	else
		printf(printout(MSG_CANT_OPEN),temp);
	if(ok)
	{
		sprintf(temp,"%s%s",mailhome,user);
		if(!DeleteFile(temp))
			printf(printout(MSG_CANT_DELETE),temp);
		sprintf(temp,"%s.%smailtemp",mailhome,user);
		sprintf(com,"%s%s",mailhome,user);
		if(rename(temp,com))
			printf(printout(MSG_CANT_RENAME),temp,com);
		if((numberofmsgs=scanmsgs())<1)
		{
			DeleteFile(com);
			cleanexit(0);
		}
	}
}

#define ALLOCSIZE	16*MAXLINELEN
void generatemail(char *oldto,char *sub,char *oldcc, int inc)
{
	FILE	*fp,*fp2;
	char	*buffer,*temp,*subject,*aika,*from,*cc,*to,*arg[10];
	int		i,j,count,alku,argcount;

	if(!(buffer=(char *)AllocMem(ALLOCSIZE,MEMF_PUBLIC | MEMF_CLEAR)))
	{
		printf(printout(MSG_MEM_ALLOC_ERR),ALLOCSIZE);
		return;
	}
	to=(cc=(from=(aika=(subject=(temp=buffer)+MAXLINELEN)+MAXLINELEN)+MAXLINELEN)+MAXLINELEN)+MAXLINELEN;
	for(i=0;i<10;i++)
		arg[i]=to+MAXLINELEN*i+MAXLINELEN;

	printf("\033[0;0H\033[J");
	if(!oldto[0])
	{
		printf(printout(MSG_AMI_ASK_TO));
		getstring(to,TRUE,FALSE);
	}
	else
		strcpy(to,oldto);
	if(!sub[0])
	{
		printf(printout(MSG_AMI_ASK_SUBJECT));
		fflush(stdout);
		getstring(subject,TRUE,FALSE);
	}
	else
		strcpy(subject,sub);
	if(!oldcc[0])
	{
		printf(printout(MSG_AMI_ASK_CC));
		fflush(stdout);
		getstring(cc,TRUE,FALSE);
	}
	else
		strcpy(cc,oldcc);

	if(subject[0])
	{
		get_time(aika);
		sprintf(temp,"%s.letter_",home);

		if(!(fp=fopen(temp,"w")))
		{
			printf(printout(MSG_CANT_WRITE),".letter_");
			return;
		}
		else
		{
			fprintf(fp,"Date: %sSubject: %s\nOrganization: %s\n\n",aika,subject,organization);
			if(inc!=-1 && inc<numberofmsgs)
			{
				sprintf(temp,"%s%s",mailhome,user);
				if(fp2=fopen(temp,"r"))
				{
					fseek(fp2,messagelist[inc].firstchar,OFFSET_BEGINNING);

					i=0;
					do
					{
						fgets(temp,MAXNAMELEN,fp2);
						i++;
					}
					while(temp[0]=='\n' && !feof(fp2));

					fprintf(fp,"%s writes to %s (%s):\n",messagelist[inc].from,user,realname);

					/* Skip header */
					while(!feof(fp2) && i<messagelist[inc].length)
					{
						i++;
						if(fgets(temp,MAXNAMELEN,fp2)==0)
							break;
						if(temp[0]=='\n' || temp[0]=='\r')
							break;
					}

					/* Include message */
					for(;i<messagelist[inc].length;i++)
					{
						fgets(temp,MAXNAMELEN,fp2);
						if(strcmp(temp,".\n"))
							fprintf(fp,">%s",temp);
					}
					fclose(fp2);
				}
			}

			fclose(fp);
			sprintf(temp,"%s.letter_",home);
			do
			{
				sprintf(aika,"AXsh:bin/%s",editor);
				MyRunCommand(aika,temp,Input(),Output());
				setmode(MODE_RAW);
				printf(printout(MSG_EDIT_SEND_ABORT));
				do
				{
					i=getchar();
					if(i==0x03 || (SetSignal(0,SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C))
						return;
					i=tolower(i);
				}
				while(i!='a' && i!='s' && i!='e');
				printf("%c\n",i);
				if(i=='a')
				{
					FreeMem(buffer,ALLOCSIZE);
					return;
				}
			}
			while(i!='s');

			/* check the message for illegal strings and append signature */

			sprintf(temp,"%s.letter",home);
			if(fp=fopen(temp,"w"))
			{
				sprintf(temp,"%s.letter_",home);
				if(fp2=fopen(temp,"r"))
				{
					while(!feof(fp2))
					{
						if(fgets(temp,MAXNAMELEN,fp2)==0)
							break;
						if(!strnicmp(temp,"From ",5) || !strcmp(temp,"."))
							fprintf(fp,">%s",temp);
						else
							fputs(temp,fp);
					}
					fclose(fp2);
				}
				else
					printf(printout(MSG_CANT_OPEN),temp);
				fclose(fp);
			}
			else
				printf(printout(MSG_CANT_OPEN),temp);

			sprintf(temp,"%s.signature",home);
			if(fp=fopen(temp,"r"))
			{
				sprintf(temp,"%s.letter",home);
				if(fp2=fopen(temp,"a"))
				{
					while(!feof(fp))
					{
						if(fgets(temp,MAXNAMELEN,fp)==0)
							break;
						if(!strnicmp(temp,"From ",5) || !strcmp(temp,"."))
							fprintf(fp2,">%s",temp);
						else
							fputs(temp,fp2);
					}
					fputc('\n',fp2);
					fclose(fp2);
				}
				else
					printf(printout(MSG_CANT_OPEN),temp);
				fclose(fp);
			}
			else
				printf(printout(MSG_CANT_OPEN),temp);

			/* OK, .letter is now written and ready to be sent */

			sprintf(from,"%s@%s",user,thismachine);
			strcat(cc," ");
			strcat(cc,to);
			i=alku=argcount=0;
			while (cc[i])
			{
				while(cc[i]==' ' || cc[i]==',') i++; /* skip soft spaces */
				alku=i;
				while(cc[i] && cc[i]!=' ' && cc[i]!=',')
					arg[argcount][i-alku]=cc[i++];
				arg[argcount][i-alku]=0;
				if(i!=alku)
					argcount++;
			}

			for(count=0;count<argcount;count++)	/* expand hostnames */
			{
				i=strlen(arg[count]);
				while(arg[count][i]!='@' && i) i--;
				if(i)
				{	strcpy(temp,arg[count]+i+1);
					arg[count][i+1]=0;/* mask host name */

					expandhostname(temp,temp);

					strcat(arg[count],temp);	/* append host name */
				}
				else
				{
					if(!strcmp(Sendmail,"internal"))
					{
						strcat(arg[count],"@");
						strcat(arg[count],thismachine);
					}
				}
			}

			if(!strcmp(Sendmail,"internal"))
			{
				for(count=0;count<argcount;count++)
				{
					strcpy(to,arg[count]);
					cc[0]=0;
					for(i=0;i<argcount;i++)
					{
						if(i!=count)
						{
							if(cc[0])
								strcat(cc," ");
							strcat(cc,arg[i]);
						}
					}
					sprintf(temp,"%s.letter",home);
					delivermessage(temp,from,realname,to,cc,-1,-1);
				}
			}
			else
			{
				strcpy(to,arg[0]);
				cc[0]=0;
				for(i=1;i<argcount;i++)
				{
					if(cc[0])
						strcat(cc," ");
					strcat(cc,arg[i]);
				}

				i=j=0;
				while(Sendmail[i])
				{
					if(Sendmail[i]=='%')
					{
						switch(Sendmail[i+1])
						{
						case 'f':
							strcpy(temp+j,home);
							strcat(temp,".letter");
							j+=strlen(home)+7;
							i+=2;
							break;
						case 'u':
							strcpy(temp+j,user);
							j+=strlen(user);
							i+=2;
							break;
						case 'r':
							strcpy(temp+j,realname);
							j+=strlen(realname);
							i+=2;
							break;
						case 't':
							strcpy(temp+j,to);
							j+=strlen(to);
							i+=2;
							break;
						case 'c':
							strcpy(temp+j,cc);
							j+=strlen(cc);
							i+=2;
							break;
						default:
							i++;
						}
					}
					else
						temp[j++]=Sendmail[i++];
				}
				temp[j]=0;
			/*	printf("%s\n",temp);*/
				Execute(temp,0,Output());
			}
		}
	}
	sprintf(temp,"%s.letter_",home);
	DeleteFile(temp);
	FreeMem(buffer,ALLOCSIZE);
}

void parsefrom(char *emailaddr,char *str)
{
	int i=0,j=0,lmode=1;

	while(str[i])
	{
		switch(str[i])
		{
		case '\"':
			break;
		case '(':
			lmode=0;
			break;
		case ')':
			lmode=1;
			break;
		case '<':
			j=0;
			break;
		case '>':
			emailaddr[j]='\0';
			return;
		default:
			if(lmode)
				emailaddr[j++]=str[i];
		}
		i++;
	}
	emailaddr[j]='\0';
	i=0;
	while(emailaddr[i] && emailaddr[i]==' ')
		i++;
	if(i)
		strcpy(emailaddr,emailaddr+i);	/* remove leading spaces */
	i=0;
	while(emailaddr[i] && emailaddr[i]!=' ')
		i++;
	emailaddr[i]='\0';			/* take only first word */
}

int check_mail(char *mailhome,char *loginname)
{
	char temp[200];
	BPTR lock;
	static struct DateStamp lastmail={0,0,0};
	static long mailsize=0;
	struct FileInfoBlock fib;
	int error=0;

	if(lastmail.ds_Days==-1 || !mailhome || !loginname)	/* first time around here get date */
	{
		DateStamp(&lastmail);
		return 0;
	}

	sprintf(temp,"%s%s",mailhome,loginname);	/* any new mail to user? */
	if(lock=Lock(temp,ACCESS_READ))
	{
		if(Examine(lock,&fib))
		{
			if(lastmail.ds_Days<fib.fib_Date.ds_Days ||
				((lastmail.ds_Days==fib.fib_Date.ds_Days) && (lastmail.ds_Minute<fib.fib_Date.ds_Minute)) ||
				((lastmail.ds_Days==fib.fib_Date.ds_Days) && (lastmail.ds_Minute==fib.fib_Date.ds_Minute) && lastmail.ds_Tick<fib.fib_Date.ds_Tick))
			{
			    if(fib.fib_Size>mailsize)
			    {
	    			error=-1;
	    		}
			}
    		mailsize=fib.fib_Size;
			lastmail=fib.fib_Date;	/* remember the date */
		}
		UnLock(lock);
	}
	/* else no mail at all */
	return error;
}


void main(int argc, char *argv[])
{
	openthings();
	readconfig();
	check_mail(NULL,NULL);	/* get current date */

	if(language[0] && LocaleBase)
	{
		catalog=(struct Catalog *)OpenCatalog(NULL,"AXsh.mail.catalog",OC_Language,language,TAG_DONE);
	}

	if(rows<22)
		printf(printout(MSG_NEED_BIGGER_DISPLAY));
	else
	{
		switch(argc)
		{
		case 2:
			generatemail(argv[1],"","",-1);
			break;
		case 3:
			generatemail(argv[1],argv[2],"",-1);
			break;
		case 4:
			generatemail(argv[1],argv[2],argv[3],-1);
			break;
		default:
			mailmenu();
		}
	}
	cleanexit(0);
}
