/*
 *	Simple mail user interface for KA9Q IP/TCP package.
 *	A.D. Barksdale Garbee II, aka Bdale, N3EUA
 *	Copyright 1986 Bdale Garbee, All Rights Reserved.
 *	Permission granted for non-commercial copying and use, provided
 *	this notice is retained.
 *	Copyright 1987 1988 Dave Trulli NN2Z, All Rights Reserved.
 *	Permission granted for non-commercial copying and use, provided
 *	this notice is retained.
 *
 *	Ported to NOS at 900120 by Anders Klemets SM0RGV.
 *
 *  Userlogging, 'RM' and 'KM' implementation,
 *  more-prompts for all types
 *  920307 and later, by Johan. K. Reinalda, WG7J/PA3DIS
 *  920719 and later, by Brian A. Lantz, KO4KS
 */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#ifdef MSDOS
#include <io.h>
#endif
#include "global.h"
#include "config.h"
#include "ftpserv.h"
#include "smtp.h"
#include "proc.h"
#include "usock.h"
#include "socket.h"
#include "telnet.h"
#include "timer.h"
#include "session.h"
#include "files.h"
#include "mailbox.h"
#include "cmdparse.h"
#include "bm.h"
#include "mailutil.h"

#ifndef UNIX
#define		SETVBUF
#endif
#if	defined(UNIX) || defined(MICROSOFT)
#include	<sys/types.h>
#endif
/*
#if	defined(UNIX) || defined(MICROSOFT) || defined(__TURBOC__)
#include	<sys/stat.h>
#endif
#ifdef AZTEC
#include <stat.h>
#endif
*/
#include <fcntl.h>
#include "bm.h"
#include "mailbox.h"

#ifdef SETVBUF
#define		MYBUF	1024
#endif

extern long ftell();
extern int makeBBSbid __ARGS((char *bid, char *line, int ours));
extern char DFAR *cb_lookname __ARGS((char *));
extern char *skipwhite __ARGS((char *ptr));
extern char *skipnonwhite __ARGS((char *ptr));
char Badmsg[] = "Invalid Message number %d\n";
char Nomail[] = "No messages\n";
static char NoMsgs[] = "No message numbers given\n";
static char anymore[] = "More(N=no)? ";
static char Noaccess[] = "Unable to access %s\n";
static int readnotes __ARGS((struct mbx *m, int already));
static long isnewmail __ARGS((struct mbx *m));
static int initnotes __ARGS((struct mbx *m));
int lockit __ARGS((struct mbx *m));
long fsize __ARGS((char *name));
static void mfclose __ARGS((struct mbx *m));
extern char *nntp_name_expansion __ARGS((char *name));


FILE *
subdir_fopen (name, mode)
char *name, *mode;
{
FILE *fp;
char *cp;

#define ENOENT 2

	if ((fp = fopen (name, mode)) != (FILE *)0)
		return fp;
	if ((errno == ENOENT) && !strchr (mode, 'r'))	{
		cp = &name[1];
		while ((cp = strpbrk (cp, "/\\")) != (char *)0)	{
			*cp = 0;
			if (access (name, 0))
				if (mkdir (name))
					return ((FILE *) 0);
			*cp++ = '/';
		}
		fp = fopen (name, mode);
		return fp;	/* NULL if STILL not opened */
	}
	return ((FILE *) 0);
}


#ifdef MAILBOX

static int
initnotes(m)
struct mbx *m;
{
register struct	let *cmsg;
char buf[256];
int 	i, ret;
int wasit = 0;

	if (m->mfile != NULLFILE)	{
		fclose (m->mfile);
		wasit = m->nmsgs;
	}
	sprintf(buf,"%s/%s.txt",Mailspool,m->area);
	if ((m->mfile = subdir_fopen(buf,READ_TEXT)) == NULLFILE)
		return 0;
	m->mboxsize = filelength (fileno(m->mfile));
	if(!(m->sid & MBX_SID) && !stricmp(m->area,m->name)) /* our private mail area */
		m->mysize = m->mboxsize;
	m->nmsgs = 0;
	m->change = 0;
	m->newmsgs = 0;
	m->anyread = 0;
	/* Allocate space for reading messages */
	readnotes(m, wasit);
#ifdef USERLOG
	m->current = 0; /*reset it*/
	if (m->nmsgs)
		for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)
			if ((cmsg->status & BM_READ) == 0) {
				m->current = i; /* first new message */
				break;
			}

	/* start at one if no new messages */
	if ((m->current == 0) && m->nmsgs)
		m->current++;
#endif
	return 0;
}

/* readnotes assumes that ifile is pointing to the first
 * message that needs to be read.  For initial reads of a
 * notesfile, this will be the beginning of the file.  For
 * rereads when new mail arrives, it will be the first new
 * message.
 */
static int
readnotes(m, already)
register struct mbx *m;
int already;
{
register FILE *fp;
char mailbox[100];
long size;
register int i, isit;
register struct	let *cmsg;
struct let *new;

	m->newmsgs = m->hmsgs = 0;
	sprintf(mailbox,"%s/control/%s.ctl",Mailspool,m->area);
	if((fp = subdir_fopen(mailbox,READ_BINARY)) != NULLFILE){
#if !defined(TNOS_68K)
		m->stdoutbuf = mallocw(MYBUF);
		setvbuf(fp, m->stdoutbuf, _IOFBF, MYBUF);
#endif
		size = filelength (fileno(fp));
/*		fseek (fp, 0L, 2);
		size = ftell (fp);
		fseek (fp, 0L, 0);	*/
		new = (struct let *) malloc (size + sizeof(struct let));
		fread (&new[1], (unsigned)size, 1, fp);
		fclose(fp);
		if (already && !strcmp (m->area, m->name))
			memcpy (new, m->mbox, (already + 1) * sizeof(struct let));
#if !defined(TNOS_68K)
		free (m->stdoutbuf);
		m->stdoutbuf = 0;
#endif
		free (m->mbox);
		m->mbox = new;
		m->nmsgs = (int) (size / (long) sizeof(struct let));
		isit = issysarea (m->area);
		for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)
			if (isit)	{
				if ((cmsg->bid > m->lastread) && !(cmsg->status & BM_DELETE))
					m->newmsgs++;
				else
					cmsg->status |= BM_READ;
				if (cmsg->status & BM_ONHOLD)
					m->hmsgs++;
			} else if (!(cmsg->status & BM_READ))
				m->newmsgs++;
	}
	else
		m->nmsgs = 0;
	return 0;
}

/* list headers of a notesfile a message */
/* Rearranged display - WG7J */
int
dolistnotes(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct mbx *m;
struct	let *cmsg;
char	*cp, *s;
char smtp_date[SLINELEN], smtp_from[SLINELEN];
char smtp_subject[SLINELEN], tstring[LINELEN], type;
char smtp_to[SLINELEN], smtp_bid[30];
int start, stop;
long	size;
char	*area;
int c,usemore=0,lin;
#ifdef USERLOG
long msgid;
#endif

	m = (struct mbx *) p;

	/*If this user doesn't have read-permissions,
	 *we're not going to let him list anything - WG7J    */
	if(m->privs & NO_READCMD) 	{
		tputs(Noperm);
		return 0;
	}

	if (m->mfile == NULLFILE) {
		tputs(Nomail);
		return 0;
	}
	if((m->stype == 'S' || m->stype == '$' || m->stype == '>' || m->stype == '<') && argc == 1) {
		tputs("Search criterium needed!\n");
		return 0;
	}

	if((lin=m->morerows) != 0)
		usemore = 1;    /* Display More prompt */

	area = strdup(m->area);
	while((cp = strchr(area,'/')) != NULLCHAR)
		*cp = '.';
	bbscolorcls (m);
	tprintf("Mail area: ");
	bbscolorchange (m, "09");
	tprintf (area);
	bbscolorchange (m, "0B");
	tprintf ("  %d ", m->nmsgs);
	bbscolorchange (m, "0F");
	tprintf ("message%s -  ",m->nmsgs == 1 ? " " : "s ");
	bbscolorchange (m, "0B");
	tprintf ("%d ", m->newmsgs);
	bbscolorchange (m, "0F");
	tprintf ("new\n\nStat  #        TO         FROM  DATE    SIZE SUBJECT\n");
	free(area);

	stop = m->nmsgs;
	if(m->stype == 'L') {		/* LL (List Latest) command */
		if(argc > 1)
			start = stop - atoi(argv[1]) + 1;
		else
			start = stop;
		if (start < 1)
			start = 1;
	} else {
		if((m->stype == 'A') || (m->stype == '>') || (m->stype == '<') || (m->stype == 'S') || (m->stype == '$') || (m->stype == 'H')) {
			start = 1;
			stop = m->nmsgs;
		} else {
			if(argc > 1)
				start = atoi(argv[1]);
			else
#ifdef USERLOG
				start = m->nmsgs - m->newmsgs + 1;
#else
				start = 1;
#endif
			if(argc > 2)
				stop = atoi(argv[2]);
		}
	}
	if(stop > m->nmsgs)
		stop = m->nmsgs;
	if(start < 1 || start > stop) 	{
		if((m->stype == ' ') || (m->stype == 'M'))
			tputs("No new mail.\n");
		else
			tputs("Invalid range.\n");
		return 0;
	}
	for (cmsg = &m->mbox[start]; start <= stop; start++, cmsg++) {
		*smtp_date = '\0';
		*smtp_from = '\0';
		*smtp_subject = '\0';
		*smtp_to = '\0';
		*smtp_bid = '\0';
		type = ' ';
		fseek(m->mfile,cmsg->start,0);
		size = cmsg->size;
		/* Be a little less selfish - WG7J */
		pwait(NULL);

#ifdef USERLOG
/* We need to get the id from the last message listed !
 * m->mbox[i].start (ie cmsg->start) points to the 'From ' line
 * next are the 'Received....' and 'ID...' lines
 * These are thes line added by our smtp server.
 * following the 'AA' is the number that we want ! - WG7J
 */
		if(start == stop) {
			/*The 'From ' line*/
			fgets(tstring,sizeof(tstring),m->mfile);
			size -= strlen(tstring);
            /*The 'Received' line*/
			fgets(tstring,sizeof(tstring),m->mfile);
			size -= strlen(tstring);
			/*The 'ID' line*/
			fgets(tstring,sizeof(tstring),m->mfile);
			size -= strlen(tstring);
            /* find id number */
#ifdef nope
            if((cmsg->bid > m->lastread) && (cmsg->bid > m->newlastread))
                m->newlastread = cmsg->bid;			
#else
			if((cp=strstr(tstring,"AA")) != NULLCHAR) {
				/*what follows is the message-number*/
				msgid = atol(cp+2);
				if((msgid > m->lastread) && (msgid > m->newlastread))
					m->newlastread = msgid;
			}
#endif
		}
#endif

		while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile) != NULLCHAR) {
			pwait(NULL);
			if (*tstring == '\n')   /* end of header */
				break;
			size -= strlen(tstring);
			rip(tstring);
			/* handle continuation later */
			if (*tstring == ' '|| *tstring == '\t')
				continue;
			switch(htype(tstring)) {
			case FROM:	cp = getaddress(tstring,0);
					strncpy(smtp_from,cp != NULLCHAR ? cp : "", 8);
					if((cp=strchr(smtp_from,'@')) != NULLCHAR)
						*cp = '\0';         /* get rid of @-host or @-bbs field */
					break;
			case SUBJECT:	cp = skipwhite (&tstring[9]);
					strncpy (smtp_subject,cp, 35);
					break;
			case MSGID:	strncpy (smtp_bid,&tstring[12], 29);
					break;
			case DATE:	if ((cp = strchr(tstring,',')) == NULLCHAR)
						cp = &tstring[6];
					else
						cp++;
					/* skip spaces */
					while (*cp == ' ') 	cp++;
					if(strlen(cp) < 17)
						break; 	/* not a valid length */
					s = smtp_date;
					/* copy day */
					if (atoi(cp) < 10 && *cp != '0')
						*s++ = ' ';
					else
						*s++ = *cp++;
					*s++ = *cp++;

					*s++ = ' ';
					*s = '\0';
					while (*cp == ' ')
						cp++;
					strncat(s,cp,3);	/* copy month */
#ifdef use_time
        			        cp += 3;
					while (*cp == ' ')
						cp++;
					/* skip year */
					while (isdigit(*cp))
						cp++;
					/* copy time */
					strncat(s,cp,6); /* space hour : min */
#endif
                			break;
			case BBSTYPE:	type = tstring[16];
					break;
			case TO:	strncpy (smtp_to,&tstring[4], 13);
					break;
			case NOHEADER:	break;
			}
		}
		if(m->stype == ' ' || m->stype == 'L' || m->stype == 'M' ||
			m->stype == 'A' || (type == m->stype && m->stype != ' ') ||
			((m->stype == 'H') && (cmsg->status & BM_ONHOLD)) ||
			((m->stype == 'S') && (strstr(strlwr(smtp_subject),argv[1]) != NULLCHAR)) ||
			((m->stype == '<') && (strstr(strlwr(smtp_from),argv[1]) != NULLCHAR)) ||
			((m->stype == '$') && (strstr(strlwr(smtp_bid),argv[1]) != NULLCHAR)) ||
			((m->stype == '>') && (strstr(strlwr(smtp_to),argv[1]) != NULLCHAR))) 		{
				lin--;
				if ((cmsg->status & BM_DELETE) && !(m->privs & SYSOP_CMD))
					strcpy (smtp_subject, "[DELETED]");
				bbscolorchange (m, "07");
				tprintf("%c%c%c%c%3d ",
					(start == m->current ? '>' : ' '),
					(cmsg->status & BM_ONHOLD ? 'H' :
					cmsg->status & BM_DELETE ? 'D' : ' '),
					(cmsg->status & BM_READ ? 'Y' : 'N'),
					(cmsg->status & BM_PERMANENT) ? 'P' : ' ',
					start);
				bbscolorchange (m, "0E");
				tprintf("%13.13s ",smtp_to);
				bbscolorchange (m, "0C");
				tprintf("%8.8s ",smtp_from);
				bbscolorchange (m, "07");
				tprintf("%-7.7s ",smtp_date);
				tprintf("%5ld ",cmsg->size);
				bbscolorchange (m, "0E");
				tprintf("%.34s\n", smtp_subject);
		}
		/* More prompting added - WG7J */
		if(usemore && lin == 0)		{
			if(m->type == TELNET || m->type == TIP)
				c = tkeywait("--More--",0,m->linemode);
			else  /* For AX.25 and NET/ROM connects - WG7J */
				c = mykeywait(anymore, m);
#ifdef MBXTDISC
			start_timer(&m->tdisc);
#endif
			if(c == -1 || c == 'q' || c == 'Q' || c == 'n' || c == 'N')
				break;
#ifdef TNOS_68K
			if(c == '\l' || c == '\r')
#else
			if(c == '\n' || c == '\r')
#endif
				lin = 1;
			else
				lin = m->morerows;

		}
	}
	return 0;
}

/*  save msg on stream - if noheader set don't output the header */
int
msgtofile(m,msg,tfile,noheader)
struct mbx *m;
int msg;
FILE *tfile;   /* already open for write */
int noheader;
{
	char	tstring[LINELEN];
	long 	size;

	if (m->mfile == NULLFILE) {
		tprintf(Nomail);
		return -1;
	}
	fseek(m->mfile,m->mbox[msg].start,0);
	size = m->mbox[msg].size;

	if (noheader) {
		/* skip header */
		while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
		       != NULLCHAR) {
			size -= strlen(tstring);
			pwait (NULL);
			if (*tstring == '\n')
				break;
		}
	}
	while (size > 0 && fgets(tstring,sizeof(tstring),m->mfile)
	       != NULLCHAR) {
		pwait (NULL);
		size -= strlen(tstring);
		fputs(tstring,tfile);
		if (ferror(tfile)) {
			tprintf("Error writing mail file\n");
			return -1;
		}
	}
	return 0;
}

void
dodeleting (m, msg)
struct mbx *m;
int msg;
{
	switch (m->stype)	{
		case 'U':	m->mbox[msg].status &= ~BM_DELETE;
				tprintf("Msg %d Un-Killed.\n", msg);
				break;
		case 'A':	m->mbox[msg].status &= ~BM_ONHOLD;
				tprintf("Msg %d Available.\n", msg);
				break;
		case 'H':	m->mbox[msg].status |= BM_ONHOLD;
				tprintf("Msg %d Held.\n", msg);
				break;
		case 'T':	m->mbox[msg].status &= ~BM_PERMANENT;
				tprintf("Msg %d Temporary.\n", msg);
				break;
		case 'P':	m->mbox[msg].status |= BM_PERMANENT;
				tprintf("Msg %d Permanent.\n", msg);
				break;
		default :	m->mbox[msg].status |= BM_DELETE;
				tprintf("Msg %d Killed.\n", msg);
				if (!issysarea (m->area))
					m->change |= CHG_DELETE;
				break;
	}
	statusCtl (m->area, "ctl", &m->mbox[msg], msg, 0);
}


/* dodelmsg - delete message in current notesfile */
/* Modified to allow the 'KM' command. 920307 -  WG7J */
/* also handles holsing/releasing messages - KO4KS */
int
dodelmsg(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct mbx *m;
	int msg,i;
    char *myargv[NARG];
    int myargc;
    int maxmsg;
    struct let *cmsg;
    char *tmpbuf;
    int start, end;

    m = (struct mbx *) p;

    /* If this user doesn't have read-permissions,
     * we're not going to let him kill/hold anything;
     * allow anyone to kill/hold messages in areas
     * who's names start with 'nts' - WG7J
     */
    /* Check if we have permission to delete others mail */
    if( (m->privs & NO_READCMD) || (m->privs & NO_SENDCMD) ||
        ( !(m->privs & FTP_WRITE) &&
            stricmp(m->area,m->name) &&
            strnicmp(m->area,"nts",3)) ){
        tputs(Noperm);
        return 0;
    }
    if ((m->stype == 'A' || m->stype == 'H' || m->stype == 'P' || m->stype == 'T') && !(m->privs & SYSOP_CMD))	{
        tputs(Noperm);
        return 0;
    }
    if (m->stype == 'S')	{
	myargc = msg = atoi(argv[1]);
	i = atoi(argv[2]);
	if ((argc < 3) || !msg || !i)
            tputs(NoMsgs);
	else	{
		for ( ; myargc <= i; myargc++)	{
			m->mbox[myargc].status |= BM_DELETE;
			statusCtl (m->area, "ctl", &m->mbox[myargc], myargc, 0);
		}
		if (!issysarea (m->area))
			m->change |= CHG_DELETE;
		tprintf("Msgs %d to %d Killed.\n", msg, i);
	}
        return 0;
    }
    if (m->mfile == NULLFILE) {
        tputs(Nomail);
		return 0;
	}
    /*If this is the KM command, setup myargv[]
     *to contain up to NARG message numbers - WG7J
     */
    if(m->stype == 'M') {
        myargc = 1;
        /* scan all messsages to find read ones */
        maxmsg = min(m->nmsgs,NARG-1);
        for(i=1;i<=maxmsg;i++){
            cmsg = &m->mbox[i];
            if(cmsg->status & BM_READ) { /*found a read msg!*/
                tmpbuf = mallocw(18); /*allocate space for the new argument*/
                myargv[myargc++] = itoa(i,tmpbuf,10);
            }
        }
        if(myargc == 1) {
            tputs(NoMsgs);
            return 0;
        }
         argc = myargc;
    } else {
        if(argc == 1) 	{
            if (m->stype != 'A')	{
		msg = m->current;
		dodeleting (m, msg);
            	return 0;
            } else	{
	        for(i=1;i<=m->nmsgs;i++){
        	    cmsg = &m->mbox[i];
	            if(cmsg->status & BM_ONHOLD)	{
			cmsg->status &= ~BM_ONHOLD;
			statusCtl (m->area, "ctl", cmsg, i, 0);
		    }
	        }
		tprintf("All Messages Available.\n");
		return 0;
	    }
        }
        /*simply point to the old arguments*/
        for(i=1;i<argc;i++)
            myargv[i] = argv[i];
    }

    /* See if x - y format was used and use a for i = x to y loop */
    if(myargv[2][0] == '-') {
        start = atoi(myargv[1]);
        end   = atoi(myargv[3]);
        if(start < 0 || start > m->nmsgs || end < 0 || end > m->nmsgs ) {
            tprintf(Badmsg,start);
            start = end-1;
        }
        for(i=start;i<=end;i++) {
            msg = i;
	    dodeleting (m, msg);
        } /* endfor */
    } else for(i = 1; i < argc; ++i) {
        tmpbuf = strchr(myargv[i],'-'); /* N5KNX: allow from-to msg specification */
        msg = atoi(myargv[i]);
        if (tmpbuf == NULLCHAR)
            maxmsg = msg;
        else
            maxmsg = atoi(++tmpbuf);
        if (maxmsg < msg) {
            tprintf(Badmsg,myargv[i]);
            continue;
        }
        for (; msg <= maxmsg; msg++) {
            if(msg < 0 || msg > m->nmsgs) {
                tprintf(Badmsg,msg);
                continue;
            }
	dodeleting (m, msg);
	}
    }
    /* If this was 'KM'
     * free the memory allocated for myargv[] - WG7J
     */
    if(m->stype == 'M') {
        for(i=1;i<argc;i++)
            free(myargv[i]);
    }
    return 0;
}

struct clparms	{
	int nostatus,
	    nodelete;
      long *hostsize;
       char name[20] ;         /* Name of remote station */
       char area[64];		/* name of current mail area */
      FILE *mfile;		/* mail data file pointer */
struct let *mbox;
        int nmsgs;		/* number of messages in this mail box */
        int isbbs;
};


static void
close_notes (a, b, c)
int a;
void *b, *c;
{
struct clparms *cl;
struct	let *cmsg;
char *line;
char tstring[LINELEN], buf[256];
char buf2[256];
long size, diff;
FILE	*nfile;
int i, nextisBID, numwritten = 0;
long msgid;
char *cp;
int foundstatus, firstIDline;

	cl = (struct clparms *) b;
	line = tstring;
	sprintf(buf,"%s/control/%s.ctl",Mailspool,cl->area);
	remove (buf);

	fclose (cl->mfile);
	sprintf(buf,"%s/%s.txt",Mailspool,cl->area);
	sprintf(buf2,"%s/%s.bak",Mailspool,cl->area);
	remove (buf2);		/* delete it here, just in case! */
	rename (buf, buf2);
	if ((cl->mfile = subdir_fopen(buf2,READ_TEXT)) == NULLFILE)	{
		rmlock(Mailspool,cl->area);
		free (cl);
		return;
	}
	if ((nfile = subdir_fopen(buf,WRITE_TEXT)) == NULLFILE) {
		fclose(cl->mfile);
		rmlock(Mailspool,cl->area);
		free (cl);
		return;
	}
	/* copy tmp file back to notes file */
	for (cmsg = &cl->mbox[1],i = 1; i <= cl->nmsgs; i++, cmsg++) {
		fseek(cl->mfile,cmsg->start,0);
		pwait (NULL);
		cmsg->start = ftell(nfile);
		size = cmsg->size;
		diff = 0;
		foundstatus = 0;
		/* It is not possible to delete messages if nodelete is set */
		if ((cmsg->status & BM_DELETE) && !cl->nodelete)
			continue;
		nextisBID = 0;
		firstIDline = 0;
		/* copy the header */
		while (size > 0 && fgets(line,LINELEN,cl->mfile) != NULLCHAR) {
			pwait(NULL);  /* can cause problems if exiting NOS */
			if (!firstIDline && nextisBID && (cp=strstr(line,"AA")) != NULLCHAR) {
				/*what follows is the message-number*/
				msgid = atol(cp+2);
				nextisBID = 0;
				firstIDline = 1;
				}
			if (!strncmp (line, Hdrs[RECEIVED], strlen(Hdrs[RECEIVED])))
				nextisBID = 1;
			if (!strncmp (line, Hdrs[STATUS], strlen(Hdrs[STATUS])))
				foundstatus = 1;
			size -= strlen(line);
			if (*line == '\n') {
#ifdef notagain
				if (cmsg->status & BM_FORWARDED)	{
					fprintf(nfile,"%s%s\n",Hdrs[XFORWARD],
						cl->name);
					diff += (strlen(Hdrs[XFORWARD]) + strlen(cl->name) + 1);
				}
#endif
				if (!foundstatus && (cmsg->status & BM_READ) != 0 && !cl->nostatus)  {
					fprintf(nfile,"%sR\n",Hdrs[STATUS]);
					diff += (strlen(Hdrs[STATUS]) + 2);
				}
				fprintf(nfile,"\n");
				break;
			}
			fputs(line,nfile);
			pwait(NULL);  /* can cause problems if exiting NOS */
		}
		pwait (NULL);
		while (size > 0 && fgets(line,LINELEN,cl->mfile) != NULLCHAR) {
			pwait(NULL);  /* can cause problems if exiting NOS */
			if (!cl->nostatus && !strncmp (line, Hdrs[RRECEIPT], strlen(Hdrs[RRECEIPT]))
				&& !strcmp (cl->name, cl->area) && (cmsg->status & BM_RRECEIPT))	{
					fputs("Return-Receipt-Sent\n", nfile);
					diff -= strlen(line);
					diff += 20;
				}
				else
					fputs(line,nfile);
			size -= strlen(line);
			pwait(NULL);   /* dont want no damaged files */
			if (ferror(nfile)) {
				(void) fclose(nfile);
				fclose(cl->mfile);
				rmlock(Mailspool,cl->area);
				free (cl);
				return;
			}
		}
		cmsg->status &= BM_READ;
		cmsg->size += diff;
		updateCtl (cl->area, cmsg);
		fflush(nfile);
		numwritten++;
	}
	if (!cl->isbbs && !stricmp(cl->name,cl->area))
		*cl->hostsize = ftell(nfile); /* Update the size of our hosts' mailbox */
					  /* potientially dangerous! */
	/* remove a zero length file */
	if (!numwritten)		{
		(void) fclose(nfile);		
		(void) unlink(buf);
	} else
		(void) fclose(nfile);
	fclose (cl->mfile);
	remove (buf2);		/* leave it around, for now! NOT! */
	rmlock(Mailspool,cl->area);
	free (cl->mbox);
	free (cl);
	pwait(NULL);
	return;
}



/* close the temp file while coping mail back to the mailbox */
int
closenotes(m)
struct mbx *m;
{
int i, nostatus, nodelete = 0;
struct clparms *cl;

	if (m->mfile == NULLFILE)
		return 0;
	nostatus = issysarea(m->area);

	/* Allow any user to delete from area names starting with 'nts' */
	if(!strnicmp(m->area,"nts",3))
		nostatus = 0;
	if(!m->change || nostatus) {	/* no changes were made (or bulletin) */
		mfclose(m);
		m->mboxsize = 0;
		return 0;
	}
	/* If this area is not our own private message area, then we will not add a
	 * Status line to indicate that the message has been read.
	 */
	if (strcmp (m->area, m->name))	{
		nostatus = 1;
		/* Don't delete messages from public message areas unless you are
		 * a SYSOP.
		 */
		nodelete = !(m->privs & SYSOP_CMD);
        }
	/* Allow any user to delete from area names starting with 'nts' */
	if(!strnicmp(m->area,"nts",3))
		nodelete = 0;        
	/* If not a SYSOP, not an "nts" area, not our area, AND deletions, must be BBS forward */
	if (nodelete && (m->change & CHG_DELETE))	{
		nodelete = 0;
		log(-1,"MBOX forwarding rewrite of personal area '%s' by %s ", m->area, m->name);
	}

	if(nostatus && nodelete)	{
		mfclose(m);
		m->mboxsize = 0;
		return 0;
	}
	scanmail(m);
	if(lockit(m))
		return -1;
	cl = (struct clparms *) malloc (sizeof (struct clparms));
	cl->nodelete = nodelete;
	cl->nostatus = nostatus;
	cl->hostsize = &m->mysize;
	cl->isbbs = (m->sid & MBX_SID);
	strcpy (cl->name, m->name);
	strcpy (cl->area, m->area);
	cl->mfile = m->mfile;
	cl->nmsgs = m->nmsgs;
	cl->mbox = m->mbox;
	newproc("Closing notefile", 2560, close_notes, 0, cl, 0, 0);
	pwait(NULL);
 	m->mfile = NULLFILE;
 	m->mbox = (struct let *) 0;
	mfclose(m);
	m->mboxsize = 0;
	return 0;
}


/* Returns 1 if name is in the given area file, 0 otherwise */
static int
is_area(name, listfile)
char *name, *listfile;
{
char buf[LINELEN], *cp;
FILE *fp;

	if((fp = fopen(listfile,READ_TEXT)) == NULLFILE)
		return 0;
	while(fgets(buf,sizeof(buf),fp) != NULLCHAR) 	{
		/* The first word on each line is all that matters */
		if(isalnum(buf[0])) 	{ /* skip comments */
		        if((cp = strpbrk(buf," \t\n")) != NULLCHAR)
				*cp = '\0';
			nntp_name_expansion (buf);
		        if(stricmp(name,buf) == 0) {    /* found it */
				fclose(fp);
				return 1;
				}
			}
		}
	fclose(fp);
	return 0;
}

/* Returns 1 if name is a public message Area, 0 otherwise */
int
isarea(name)
char *name;
{
	return (is_area (name, Arealist));
}

/* Returns 1 if name is a public message Area, 0 otherwise */
int
issysarea(name)
char *name;
{
	return (is_area (name, AreaSlist));
}

int
lockit(m)
struct mbx *m;
{
	int c, cnt = 0;

	while(mlock(Mailspool,m->area)) {
		mspause(1000L/MSPTICK);	/* Wait one second */
		if(++cnt == 10) {
			char buf[80];
			sprintf (buf, "Mail file '%s' is busy, Abort or *Retry ? ", m->area);
			cnt = 0;
			c = tkeywait(buf,1,m->linemode);
			if (c == 'A' || c == 'a' || c == EOF) {
				mfclose(m);
				return 1;
			}
		}
	}
	return 0;
}

/* read the next message or the current one if new */
int
doreadnext(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct mbx *m;
	char buf[10], *newargv[2];
	m = (struct mbx *) p;
	if (m->mfile == NULLFILE)
		return 0;
	if ((m->mbox[m->current].status & BM_READ) != 0) {
		if (m->current == 1 && m->anyread == 0)
			;
		else if (m->current < m->nmsgs) {
			m->current++;
		} else {
			tprintf("Last message\n");
			return 0;
		}
	}
	sprintf(buf,"%d",m->current);
	newargv[0] = "read";
	newargv[1] = buf;
	return doreadmsg(2,newargv,p);
}



void
leadingCaps (str, others)
char *str;
int others;
{
char *cp;

	cp = str;
	strlwr (cp);
	if (!others)	{
		if ((cp = strchr(cp, ' ')) != 0)
			strupr (cp);
		return;
	}
	do	{
		cp = strchr (cp, ' ');
		if (cp != NULL)	{
			cp = skipwhite(cp);
			*cp = toupper (*cp);
		}
	} while (cp);
}


char *
mblookname (m, str)
struct mbx *m;
char *str;
{

	if ((m != NULLMBX) && (m->realname) && (*m->realname == '(') && (m->realname[1] != ')'))
		return (strdup (m->realname));

	if (strchr (str, '('))
		return (0);	/* already has a name */
#ifdef SAMCALLB
	return (cb_lookname (str));
#else
	return (0);
#endif
}



extern int MbRead;

/* display message on the crt given msg number */
/* Modified to allow the 'RM' command, 920307 - WG7J */
int
doreadmsg(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct mbx *m;
	register int c, col, lin;
	unsigned char	buf[MAXBUF+2], *cp, *cp2;
	char *subj = 0, *theto = 0;
    int msg, cnt, i, usemore=0, verbose, mbxheader, pathcol;
	int	header, lastheader;
	long 	size;
    char *myargv[NARG];
    int myargc;
    int maxmsg;
    struct let *cmsg;
    char *tmpbuf;
    char *returnreceipt;
#ifdef USERLOG
    long msgid;
#endif

	m = (struct mbx *) p;

    /*Check for read-permissions - WG7J */
    if(m->privs & NO_READCMD) {
        tputs(Noperm);
        return 0;
    }
    if (m->stype == 'O')
    	return (dombroute (argc, argv, p));
    if ((m->mfile == NULLFILE) || (m->nmsgs == 0)) {
		tprintf(Nomail);
		return 0;
	}
    if((lin=m->morerows) != 0)
        usemore = 1;    /* Display More prompt */

    /*If this is the RM or VM command, setup myargv[]
     *to contain up to NARG message numbers - WG7J
     */
    if(m->stype == 'M') {
        myargc = 1;
        if(!m->newmsgs) {
            tputs(Nomail);
            return 0;
        }
        /* scan all messsages to find unread ones */
        maxmsg = min(m->nmsgs,NARG-1);
        for(i=1;i<=maxmsg;i++){
            cmsg = &m->mbox[i];
            if(!(cmsg->status & BM_READ)) { /*found an unread msg!*/
                tmpbuf = mallocw(18); /*allocate space for the new argument*/
                myargv[myargc++] = itoa(i,tmpbuf,10);
            }
        }
        argc = myargc;
    } else {
        /*simply point to the old arguments*/
        for(i=1;i<argc;i++)
            myargv[i] = argv[i];
    }
    if(argc == 1) {
        tputs("Usage: Read/Verbose #\n");
        return 0;
    }
    m->state = MBX_READ;
    for(i = 1; i < argc; ++i) {
        msg = atoi(myargv[i]);
		if( msg < 1 || msg > m->nmsgs) {
			tprintf(Badmsg,msg);
            goto iamdone;
		}
        MbRead++;
		fseek(m->mfile,m->mbox[msg].start,0);
#ifdef USERLOG
        /* Check the ID number of this message and
         * adjust new lastread count, if needed - WG7J
         */
        fgets(buf,MAXBUF+2,m->mfile);    /* the 'From ' line */
        fgets(buf,MAXBUF+2,m->mfile);    /* the 'Received: ' line */
        fgets(buf,MAXBUF+2,m->mfile);    /* the ' ID' line */
        /* find id number */
        if((cp=strstr(buf,"AA")) != NULLCHAR) {
        /*what follows is the message-number*/
            msgid = atol(cp+2);
	    if((msgid > m->lastread) && (msgid > m->newlastread))
                m->newlastread = msgid;
			}
        fseek(m->mfile,m->mbox[msg].start,0);
#endif
#ifdef nope /* was USERLOG */
            if((m->mbox[msg].bid > m->lastread) && (m->mbox[msg].bid > m->newlastread))
                m->newlastread = m->mbox[msg].bid;
#endif

	m->anyread = 1;
	returnreceipt = 0;
        size = m->mbox[msg].size;
		m->current = msg;
		header = NOHEADER;
		mbxheader = 0;
        if((*argv[0] == 'v') || (m->stype == 'H'))
			verbose = 1;	/* display all header lines */
		else
			verbose = 0;

	m->inmessage = 1;
	if(m->stype != 'M')
		bbscolorcls (m);
	bbscolorchange (m, "07");
		tprintf("Message #%d %s\n", msg,
			m->mbox[msg].status & BM_ONHOLD ? "[On Hold - Awaiting Review of SYSOP]" :
			m->mbox[msg].status & BM_DELETE ? "[Deleted]" : "");

	if ((m->mbox[msg].status & (BM_ONHOLD | BM_DELETE)) && !(m->privs & SYSOP_CMD))
	        continue;

        /* When you have sysop privs,
         * only mark your own private area as read and changed.
         * other areas, only mark as read, NOT changed !
         * for regular users, simply mark all as read and changed.
         * That way sysops can read other's mail without
         * marking stuff read that really wasn't read by
         * the right person !
         * for regular users, simply mark as read.
         * 910312 - WG7J
         */
        if(!(m->mbox[msg].status & BM_READ)) {
            m->mbox[msg].status |= BM_READ;
                /* regular users */
            if(!issysarea (m->area) && (!(m->privs & SYSOP_CMD) || \
               ((m->privs & SYSOP_CMD) && !strcmp(m->name,m->area)))) /*sysops*/
			m->change |= CHG_READ;
            m->newmsgs--;
        }
		--lin;
		col = 0;
		while (!feof(m->mfile) && size > 0) {
			for (col = 0;  col < MAXBUF;) {
				c = getc(m->mfile);
				size--;
				if (feof(m->mfile) || size == 0) /* end this line */
					break;
				if (c == '\t') {
					cnt = col + 8 - (col & 7);
					if (cnt >= MAXBUF) /* end this line */
						break;
					while (col < cnt)
						buf[col++] = ' ';
				} else {
					if (c == '\n')
						break;
					buf[col++] = c;
				}
			}
			if(col < MAXBUF)
				buf[col++] = '\n';
			buf[col] = '\0';
			if(mbxheader > 0) {
			     /* Digest R: lines and display as a Path: line */
			     if(strnicmp(buf,"R:",2) != 0 ||
				(cp = strchr(buf,'@')) == NULLCHAR) {
				  tputc('\n');
				  bbscolorchange (m, "0B");
				  mbxheader = -1; /* don't get here again */
				  verbose = 1;
			     }
			     else {
				  if(*(++cp) == ':')
				       ++cp;
				  for(cp2 = cp; isalnum(*cp2); ++cp2)  ;
				  *cp2 = '\0';
				  if(mbxheader++ == 1) {
				  	bbscolorchange (m, "07");
		                       tputs(Hdrs[PATH]);
				       pathcol = 5;
				       --lin;
				  }
				  else {
				       tputc('!');
				       if(++pathcol + strlen(cp) > MAXCOL-3){
					    tputs("\n      ");
					    pathcol = 5;
					    --lin;
				       }
				  }
				  tputs(cp);
				  pathcol += strlen(cp);
				  ++lin;	/* to allow for not printing it later */
			     }
			}
			if(col == 1 && !mbxheader)	{
			     bbscolorchange (m, "0B");
			     /* last header line reached */
			     if (!verbose)
				     mbxheader = 1;
			}
			if(verbose)
/*				tputs(buf);	*/
				colorprintf (NULLCHAR, m->usecolor, buf);
			if (!strncmp (Hdrs[RRECEIPT], buf, strlen(Hdrs[RRECEIPT])))
				returnreceipt = strdup(&buf[strlen(Hdrs[RRECEIPT])]);
			if(!verbose && !mbxheader){
				lastheader = header;
				if(!isspace(*buf))
					header = htype(buf);
				else
					header = lastheader;
				switch(header) {
				case SUBJECT:	subj = strdup (&buf[strlen(Hdrs[SUBJECT]) - 4]);
						tputs(buf);
						break;
				case MSGID:	/* give a "traditional BBS" version to the user */
						{
						char bid[30];

							makeBBSbid (bid, buf, 1);
							strupr (bid);
							tprintf ("%s%s\n", Hdrs[MSGID], bid);
						}
						break;
				case TO:        theto = strdup (&buf[strlen(Hdrs[TO])]);
				case FROM:	{
						char DFAR *nm;
							rip (buf);
							tputs (buf);
							nm = strchr (buf, ' ');
							if ((nm = mblookname (NULLMBX, ++nm)) != 0)	{
								tputs (nm);
								free (nm);
							}
							tputc ('\n');
						}
						break;
				case CC:
				case DATE:
				case REPLYTO:
				case APPARTO:
				case ERRORSTO:
				case XMAILGROUP:
				case ORGANIZATION:
					tputs(buf);
					break;
				default:
					++lin;
				}
			}
			col = 0;
            if(usemore && --lin <= 0){
                if(m->type == TELNET || m->type == TIP)
                    c = tkeywait("--More--",0,m->linemode);
                else  /* For AX.25 and NET/ROM connects - WG7J */
                    c = mykeywait(anymore, m);
#ifdef MBXTDISC
		start_timer(&m->tdisc);
#endif
                lin = m->morerows;
				if(c == -1 || c == 'q' || c == 'Q')
					break;
#ifdef TNOS_68K
				if(c == '\l' || c == '\r')
#else
				if(c == '\n' || c == '\r')
#endif
					lin = 1;
			}
        }
	if (returnreceipt && !(m->mbox[msg].status & BM_RRECEIPT))	{
		struct mbx *mm;
		m->mbox[msg].status |= BM_RRECEIPT;
		rip (returnreceipt);	/* strip off <CR> */
		tprintf ("[Sending return receipt to '%s']\n", returnreceipt);
		mm = (struct mbx *) malloc (sizeof (struct mbx));
		mm->tomsgid = mm->date = mm->origbbs = mm->tofrom = NULLCHAR;
		mm->origto = returnreceipt;
		mm->subject = subj;
		mm->realname = "()";
		rip (subj);	/* strip off <CR> */
		subj[0] = subj[1] = 'R';
		subj[2] = ':';
		subj[3] = ' ';
		mm->stype = 'P';
		strcpy (mm->name, m->name);
		if ((mm->tfile = tmpfile()) != NULLFILE)	{
			struct list *cclist = NULLLIST;
			char fullfrom[MBXLINE];
			addlist(&cclist, returnreceipt, 0, returnreceipt);
			sprintf (fullfrom, "%s@%s", m->name, Hostname);
			mbx_data (mm, NULLLIST, NULLCHAR, 0);
			rip (theto);	/* strip off the <CR> */
			fprintf (mm->tfile, "Message received - Originally addressed to: '%s'\n", theto);
			fseek(mm->tfile, 0L, 0);	/* rewind file */
			queuejob (mm->tfile, Hostname, cclist, fullfrom);
			fclose (mm->tfile);
			del_list(cclist);
			smtptick(NULL);		/* wake up SMTP to send mail */
			}
		free (mm);
		free(returnreceipt);
		}
	free (subj);
	free (theto);
	m->inmessage = 0;
	}
iamdone:
    /* If this was 'RM' or 'VM',
     * free the memory allocated for myargv[] - WG7J
     */
    if(m->stype == 'M') {
        for(i=1;i<argc;i++)
            free(myargv[i]);
    }
    return 0;
}

/* Set up m->to when replying to a message. The subject is returned in
 * m->line.
 */
int
mbx_reply(argc,argv,m,cclist,rhdr)
int argc;
char *argv[];
struct mbx *m;
struct list **cclist;	/* Pointer to buffer for pointers to cc recipients */
char **rhdr;		/* Pointer to buffer for extra reply headers */
{
char subject[MBXLINE], *msgid = NULLCHAR, *date = NULLCHAR;
char *cp;
int msg, lastheader, header = NOHEADER;
long size;

	/* Free anything that might be allocated
	 * since the last call to mbx_to() or mbx_reply()
	 */
	free(m->to);
	m->to = NULLCHAR;
	free(m->tofrom);
	m->tofrom = NULLCHAR;
	free(m->tomsgid);
	m->tomsgid = NULLCHAR;
	free(m->origto);
	m->origto = NULLCHAR;
	subject[0] = '\0';

	if(argc == 1)
	     msg = m->current;
	else
	     msg = atoi(argv[1]);
	if (m->mfile == NULLFILE) {
	     if(m->sid & MBX_SID)
		  tputs("NO - ");
		tputs(Nomail);
		return 0;
	}
	if(msg < 1 || msg > m->nmsgs) {
	     if(m->sid & MBX_SID)
		  tputs("NO - ");
	     tputs(Badmsg);
	     return -1;
	}
	fseek(m->mfile,m->mbox[msg].start,0);
	size = m->mbox[msg].size;
	m->current = msg;
	while(size > 0 && fgets(m->line,MBXLINE-1,m->mfile) != NULLCHAR) {
	     size -= strlen(m->line);
	     if(m->line[0] == '\n')	/* end of header */
		  break;
	     rip(m->line);
	     lastheader = header;
	     if(!isspace(m->line[0])) {
		  header = htype(m->line);
		  lastheader = NOHEADER;
	     }
	     switch(header) {
	     case SUBJECT:
		  if(strlen(m->line) > 11 && !strnicmp(&m->line[9],"Re:",3))
		       strcpy(subject,&m->line[9]);
		  else
		       sprintf(subject,"Re: %s",&m->line[9]);
		  break;
	     case FROM:
		  if(m->to == NULLCHAR && (cp = getaddress(m->line,0)) !=
		     NULLCHAR)
		       m->to = strdup(cp);
		  break;
	     case REPLYTO:
		  if((cp = getaddress(m->line,0)) != NULLCHAR) {
		       free(m->to);
		       m->to = strdup(cp);
		  }
		  break;
	     case MSGID:
		  free(msgid);
		  msgid = strdup(&m->line[12]);
		  break;
	     case DATE:
		  free(date);
		  date = strdup(&m->line[6]);
		  break;
#ifdef notdef
         /* don't want a reply back to myself - WG7J */
         case TO:
         case APPARTO:
#endif
         case CC:
		  /* Get addresses on To, Cc and Apparently-To lines */
		  cp = m->line;
		  m->line[strlen(cp)+1] = '\0';	/* add extra null at end */
		  for(;;) {
		       if((cp = getaddress(cp,lastheader == header ||
			   cp != m->line)) == NULLCHAR)
				    break;
		       addlist(cclist,cp,0,cp);
		       /* skip to next address, if any */
		       cp += strlen(cp) + 1;
		  }
		  break;
	     }
	}
	if(msgid != NULLCHAR || date != NULLCHAR) {
	     *rhdr = mallocw(LINELEN);
	     sprintf(*rhdr,"In-Reply-To: your message ");
	     if(date != NULLCHAR) {
		  sprintf(m->line,"of %s.\n",date);
		  strcat(*rhdr,m->line);
		  if(msgid != NULLCHAR)
		       strcat(*rhdr,"             ");
	     }
	     if(msgid != NULLCHAR) {
		  sprintf(m->line,"%s\n",msgid);
		  strcat(*rhdr,m->line);
	     }
	     free(msgid);
	     free(date);
	}
	strcpy(m->line,subject);
	return 0;
}

#ifdef USERLOG

/*get the last message listed/read
 *from the areaname.USR file
 *keeps track for each user.
 *February '92, WG7J
 */
void
getlastread(m)
struct mbx *m;
{
	FILE *Alog;
	char buf[256];
	char *cp;
	int found=0;

    m->lastread = m->newlastread = 0L;

	sprintf(buf,"%s/users/%s.usr",Mailspool,m->area);
	if ((Alog = subdir_fopen(buf,"r+")) == NULLFILE) {
		/* USR file doesn't exist, create it */
		if((Alog = subdir_fopen(buf,"w")) == NULLFILE)
			return;
		/* Add this user as first one */
        sprintf(buf,"%s 0\n",m->name);
		fputs(buf,Alog);
		fclose(Alog);
		return;
	}
	/*Find user in the usr file for this area*/
	for(;;) {
		if(fgets(buf,sizeof(buf),Alog) == NULLCHAR)
            break;
		if((cp=strchr(buf,' ')) != NULLCHAR)
			*cp = '\0';
		if(!stricmp(m->name,buf)) {
			/*found user*/
            cp++;
			while(*cp == ' ')   /*skip blanks*/
				cp++;
			m->lastread = atol(cp);
			found = 1;
			break;
		}
	}
	if(!found) {
		/*Add user*/
        sprintf(buf,"%s 0\n",m->name);
		fputs(buf,Alog);
	}
	fclose(Alog);
	return;
}

/* Write the new last read id number to the USR file - WG7J
 * only update if this is not a bbs,
 * current area is a public area and not 'help',
 * or anything that starts with 'sys',
 * and a new message was actually listed/read
 */
void
setlastread(m)
struct mbx *m;
{
FILE *Alog, *tfile;
char buf[256];
char tmpname[80];
char *cp;
int doit = 0;

    if((m->sid & MBX_SID) || (m->newlastread <= m->lastread) )
        return;

/*	if(issysarea(m->area))
		if ((m->privs & MBX_SYSOP) || (stricmp(m->area, "help")))
			doit = 1;	*/
      if(isarea(m->area) && strcmp(m->area, "help"))
      	  doit = 1;
      if ((m->privs & SYSOP_CMD) && issysarea(m->area))
      	  doit = 1;

      if (doit)		{

#ifdef notdef
    tprintf("SETLAST: %d\n",m->newlastread);
#endif


        sprintf(buf,"%s/users/%s.usr",Mailspool,m->area);

        /* Rename the USR file to a tempfile */
#ifdef UNIX
	strcpy(tmpname, buf);
	strcat(tmpname, ".bak");
#else
        tmpnam(tmpname);
#endif
        if(rename(buf,tmpname))
            /* Can't rename ??? */
            return;

        if((Alog = subdir_fopen(buf,"w")) == NULLFILE) {
            /* can't creat new USR file ???*/
            rename(tmpname,buf);    /* try to undo the damage */
            return;
        }

        if((tfile = subdir_fopen(tmpname,"r")) == NULLFILE)
            /* can't open renamed file ??? */
            return;

        /*Write all users back, but update this one!*/
        while(fgets(buf,sizeof(buf),tfile) != NULLCHAR) {
            if((cp=strchr(buf,' ')) != NULLCHAR)
                *cp = '\0';
            if(!stricmp(m->name,buf)) {
                /*found this user*/
                sprintf(buf,"%s %lu\n",m->name,m->newlastread);
            } else
                *cp = ' '; /* restore the space !*/
            fputs(buf,Alog);
        }
        fclose(tfile);
        unlink(tmpname);
        fclose(Alog);
    }
    return;
}

#endif /*USERLOG*/

void
scanmail(m)		 /* Get any new mail */
struct mbx *m;
{
long diff;

	if ((diff = isnewmail(m)) == 0L)
		return;
	if(lockit(m))
		return;
	initnotes(m);
	rmlock(Mailspool,m->area);
}

/* Check the current mailbox to see if new mail has arrived.
 * Returns the difference in size.
 */
static long
isnewmail(m)
struct mbx *m;
{
char buf[256];

	sprintf(buf,"%s/%s.txt",Mailspool,m->area);
	return fsize(buf) - m->mboxsize;
}

/* Check if the private mail area has changed */
long
isnewprivmail(m)
struct mbx *m;
{
long cnt;
char buf[256];

	sprintf(buf,"%s/%s.txt",Mailspool,m->name);
	cnt = m->mysize;
	m->mysize = fsize(buf);
	return m->mysize - cnt; /* != 0 not more than once */
}


void
notifynewmail (m)
struct mbx *m;
{	/* not a BBS, but from within ANY area */
	if (!(m->sid & MBX_SID) && (isnewprivmail(m) > 0L))	{
		tprintf("\007You have new mail in your personal area (%s). Please Kill when read!\n", m->name);
		usflush(Curproc->output);
	}
}

#endif

/* This function returns the length of a file. The proper thing would be
 * to use stat(), but it fails when using DesqView together with Turbo-C
 * code.
 */
long
fsize(name)
char *name;
{
long cnt;
FILE *fp;

	if((fp = subdir_fopen(name,READ_TEXT)) == NULLFILE)
		return -1L;
	fseek(fp,0L,2);
	cnt = ftell(fp);
/*	cnt = filelength (fileno(fp)); */
	fclose(fp);
	return cnt;
}

/* close the temporary mail file */
static void
mfclose(m)
struct mbx *m;
{
	if(m->mfile != NULLFILE)
		fclose(m->mfile);
	m->mfile = NULLFILE;
#ifdef SETVBUF
	free(m->stdoutbuf);
	m->stdoutbuf = NULLCHAR;
#endif
}


/* erase a previous prompt via backspaces */
void
backEmUp (len)
int len;
{
int i;
	/* Get rid of the prompt */
	for(i=len;i != 0;i--)
		tputc('\b');
	for(i=len;i != 0;i--)
		tputc(' ');
	for(i=len;i != 0;i--)
		tputc('\b');
	tflush ();
}


/* Print prompt and read one character, telnet version */
int
tkeywait(prompt,flush,linemode)
char *prompt;	/* Optional prompt */
int flush;	/* Flush queued input? */
int linemode;	/* Negotiate line mode? */
{
	int c, cl, oldimode,oldomode;

	if(flush && socklen(Curproc->input,0) != 0)
		recv_mbuf(Curproc->input,NULL,0,NULLCHAR,0); /* flush */
	if(prompt == NULLCHAR)
		prompt = "Hit enter to continue"; 
	tprintf("%s",prompt);
	/* hack - handle Unix telnet clients correctly */
	if (linemode)
	    tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,2,IAC,SE);
	tprintf("%c%c%c",IAC,WILL,TN_ECHO);
	usflush(Curproc->output);

	/* discard the response */

	oldimode = sockmode(Curproc->input,SOCK_BINARY);
	oldomode = sockmode(Curproc->output,SOCK_BINARY);

	while((c = rrecvchar(Curproc->input)) == IAC){
		c = rrecvchar(Curproc->input);
		if(c == SB) {
			if((c = rrecvchar(Curproc->input)) == EOF)
				break;
			cl = c;
			c = rrecvchar(Curproc->input);
			while((c != EOF) && !(cl == IAC && c == SE)) {
				cl = c;
				c = rrecvchar(Curproc->input);
			}
		} else if(c > 250 && c < 255)
			rrecvchar(Curproc->input);
	}

	sockmode(Curproc->output,oldomode);
	sockmode(Curproc->input,oldimode);

	backEmUp (strlen(prompt));
	tprintf("%c%c%c",IAC,WONT,TN_ECHO);
	if (linemode)
	    tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
	usflush(Curproc->output);
	return c;
}

/* Print -more- prompt and read reply,
 * AX.25 and NETROM version - WG7J
 * <CR> is taken as a 'Yes'
 */
int
mykeywait(prompt,m)
char *prompt;
struct mbx *m;
{
    tputs(prompt);
    usflush(Curproc->output);
    if(recvline(m->user, m->line, MBXLINE) == -1) {
        return -1;
    }
    /* Only 'N' or 'n' really matters */
    if((*m->line == 'N') || (*m->line == 'n'))
        return -1;
    return 0;
}
