/* Some of the code in this file was originally based on the following file:
 * gateway.c : Paul Healy, EI9GL, 900818
 *
 * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
 * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
 */
 /* Mods by G1EMM and WG7J */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "global.h"
#include "config.h"
#include "bm.h"
#include "mailbox.h"
#include "smtp.h"
#include "cmdparse.h"
#include "proc.h"
#include "socket.h"
#include "timer.h"
#include "usock.h"
#include "netuser.h"
#include "ax25.h"
#include "netrom.h"
#include "nr4.h"
#include "files.h"
#include "mailfor.h"
#include "hardware.h"

#ifdef MBFWD

#define NOSUBCHANNEL (NUMMBX + 10)
extern int MbForwarded;
extern char MboxId[], MboxIdFwd[];
#ifdef FBBFWD
extern char MboxIdFBB[], MboxIdFwdFBB[];
int Mfbb = 0;
#endif
extern int BBSdump;
extern int MbBID, MbMID;
#define ISPROMPT(s) (strlen(s) > 1 && s[strlen(s)-2] == '>')
static struct timer fwdtimer;
unsigned subchannels[NUMMBX];
int subchannelusage[NUMMBX];
int lastSessionSkipped;
int FWDmode = 1, FWDpersonal = 1, FWDbulletins = 1, FWDreverse = 1;
#ifdef LZW
int FWDlzw = 1;
#else
int FWDlzw = 0;
#endif

static void mark_forwarded __ARGS((FILE *fp,long ind));
static char *findident __ARGS((char *str, int n, char *result));
static void sendmsg __ARGS((struct mbx *m,int msgn,char *thebid));
char *mbxtime __ARGS((char *line));
static int fwdinit __ARGS((struct mbx *m));
static char *fwdanybbs __ARGS((struct mbx *m,int *poll));
static int timeok __ARGS((char *line));
static void fwdtick __ARGS((void *v));
static void fwdproc __ARGS((int, void *, void *));
static int isconnbbs __ARGS((struct mbx *m));
static void startfwd __ARGS((int a,void *v1,void *v2));
static int openconn __ARGS((int argc,char *argv[],void *p));
static int sendmsgtobbs __ARGS((struct mbx *m,int msgn,char *dest,int bulletin));
static int makecl __ARGS((struct mbx *m,int msgn,char *dest,char *line,char *subj,char *bid,int *bul));
static char *grabtext __ARGS((char *from,char *to,int marker));
void forwardingSummary __ARGS((void));
extern char *nntp_name_expansion __ARGS((char *name));
extern void msgiddelete __ARGS((register char *string));
extern void statusCtl __ARGS((char *who, char *extension,struct let *info,int entry, int readit));
#ifdef LZW
static int dolzw __ARGS((int argc,char *argv[],void *p));
void togglelzw __ARGS((int soc, int mode));
#endif
static int domode __ARGS((int argc,char *argv[],void *p));
static int dopersonal __ARGS((int argc,char *argv[],void *p));
static int dobulletins __ARGS((int argc,char *argv[],void *p));
static int doreverse __ARGS((int argc,char *argv[],void *p));
static int dosummary __ARGS((int argc,char *argv[],void *p));
static int dostatus __ARGS((int argc,char *argv[],void *p));
int doforward __ARGS((int argc,char *argv[],void *p));
static int checkone __ARGS((char *line, char *str, char *sub));
int adaptaddress __ARGS((char *line));
static int fwdthisarea __ARGS((struct mbx *m,FILE *fwd,char *area, char *newto));
static void fwdcleanup __ARGS((int index,struct mbx *m,char *string));
int AREAlookup __ARGS((char *area,int index));
#ifdef FBBFWD
static int dofbbstyle __ARGS((int argc,char *argv[],void *p));
#endif

#ifdef UNIX
char *ltoa __ARGS((long value, char *string, int radix));

char *
ltoa (value, string, radix)
long value;
char *string;
int radix;
{
	/* assume radix of 10, since only called with that value */
	sprintf(string, "%ld", value);
	return (string);
}
#endif



#ifdef LZW
static int
dolzw(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&FWDlzw,"Forward using lzw",argc,argv);
}
#endif


static int
domode(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&FWDmode,"Forwarding enabled",argc,argv);
}


static int
dopersonal(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&FWDpersonal,"Forwarding Personal Messages",argc,argv);
}


static int
dobulletins(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&FWDbulletins,"Forwarding Bulletins",argc,argv);
}


#ifdef FBBFWD
static int
dofbbstyle(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&Mfbb,"FBB-style forwarding",argc,argv);
}
#endif


static int
doreverse(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return setbool(&FWDreverse,"Reverse Forwarding Enabled",argc,argv);
}

static int
dosummary(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	forwardingSummary();
	return 0;
}

static int
dostatus(argc,argv,p)
int argc;
char *argv[];
void *p;
{
int i, first = 0;

	dobulletins (0, 0, 0);
#ifdef LZW
	dolzw (0, 0, 0);
#endif
	domode (0, 0, 0);
	dopersonal (0, 0, 0);
	doreverse (0, 0, 0);
	dofbbstyle(0, 0, 0);

	/* also give forwarding in progress report */
	for(i = 0; i < NUMMBX; ++i)	{
		if(Mbox[i] == NULLMBX)
			continue;
		if ((Mbox[i]->state == MBX_FORWARD) || (Mbox[i]->state == MBX_REVFWD))	{
			if (!first)	{
				tprintf ("\nActive Forwarding Sessions:\n");
				first = 1;
			}
			tprintf ("     %-9s - %sForwarding\n", Mbox[i]->name, (Mbox[i]->state == MBX_REVFWD) ? "Reverse " : "");
		}
	}
	return (0);
}


static struct cmds DFAR FWDcmds[] = {
	"bulletins",	dobulletins,	0,	0,	NULLCHAR,
#ifdef FBBFWD
	"fbb-style",	dofbbstyle,	0,	0,	NULLCHAR,
#endif
#ifdef	LZW
	"lzw",		dolzw,		0,	0,	NULLCHAR,
#endif
	"mode",		domode,		0,	0,	NULLCHAR,
	"personal",	dopersonal,	0,	0,	NULLCHAR,
	"reverse",	doreverse,	0,	0,	NULLCHAR,
	"status",	dostatus,	0,	0,	NULLCHAR,
	"summary",	dosummary,	0,	0,	NULLCHAR,
	NULLCHAR,
};


int
doforward(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	return subcmd(FWDcmds,argc,argv,p);
}



/***************************************************************************
   findident copies the 'n'th alphanumeric sequence from 'str' to result.
   It returns a ptr to result. It returns "\0" for missing identifier etc.
   Uses isalnum macro to decide on alphanumeric/non-alnum status.
*/
static char *
findident(str, n, result)
char *str, *result;
int n;
{
   int count; /* current identifier */
   count = 0;
   *result = '\0';
   while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
      while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
         str++;
      if ( (*str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
         count++;
         while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
            if (count==n)
               *result++ = *str++;
            else str++;
         if (count==n)
            *result = '\0';
         }
      }
   return result;
}

extern char *Mbhaddress;
extern char *Mbfwdinfo;
extern char *Mbqth;
extern int MbRSTYLE;
extern char *Mbzip;
extern int Mbsmtptoo;
extern int Mbfullsvc;
extern int UtcOffset;
extern char shortversion[];


static int
checkone (line,str,sub)
char *line, *str, *sub;
{
char *cp;

	if (!strnicmp (line, str, strlen(str)) && (cp = strstr (line, Hostname)) != NULLCHAR)	{
		strcpy (cp, sub);
		return 1;
	}
	return 0;
}


int
adaptaddress (line)
char *line;
{
char buf[60], *cp;

	pax25(buf,Mycall);
	if((cp = strchr(buf,'-')) != NULLCHAR)
		*cp = '\0'; /* remove SSID */
	strcat (buf, (Mbhaddress != NULLCHAR) ? Mbhaddress : "");
	strcat (buf, "\n");
	if (checkone (line, Hdrs[XMAILGROUP], buf))
		return 1;
	if (checkone (line, Hdrs[ERRORSTO], buf))
		return 1;
	return (checkone (line, Hdrs[REPLYTO], buf));
}


/**************************************************************************/
/* sendmsg() modified to send the R: line always.
 * also added some additional strings like qth and zipcode etc. to R: line.
 * Original SMTP headers get forwarded optionally.
 * 920114 - WG7J
 */

static void
sendmsg(m,msgn,thebid)
struct mbx *m;
int msgn;
char *thebid;
{
char buf[LINELEN], tb[LINELEN], *cp;
int rec = 0; /* rec is line-counter */
#ifdef nope
int len;
#endif
long cnt;
unsigned int msgid=0; /* message id number - WG7J */
int col, ccnt;
char c;

    /*point to start of this message in file*/
	fseek(m->mfile,m->mbox[msgn].start,0);
    /*get message size*/
    cnt = m->mbox[msgn].size;

	/* If the data part of the message starts with "R:" the RFC-822
	 * headers will not be forwarded. Instead we will add an R:
	 * line of our own.
	 */
    /* ALWAYS forward with "R:" line */
    for(;;) {
        /*read a line*/
        if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
            break;
        pwait (NULL);
        /*adjust message character count*/
		cnt -= strlen(buf);
        if(rec == 1) {
            /* look at the line following Received:
             * This has the ID followed by ' ; date&time in arpa-format'
             */
            /*get the message number from the ID line - WG7J*/
            if((cp=strstr(buf,"AA"))!= NULLCHAR)
                /*what follows is the message-number*/
                msgid = atoi(cp+2);
            /*get the ARPA format date/time string*/
            if((cp = strchr(buf,';')) != NULLCHAR){
                strcpy(tb,cp+1); /* point to the date of receipt */
            }
            /*ALWAYS send the R: line */
            pax25(buf,Mycall);
            if((cp = strchr(buf,'-')) != NULLCHAR)
                *cp = '\0'; /* remove SSID */
            /*If mbox header is off, don't send the R: line*/
	    if (Mbfullsvc)	{
	    	    if(!MbRSTYLE)	{
		            usprintf(m->user,"R:%s @:%s%s%s ", mbxtime(tb), buf,
				(Mbhaddress != NULLCHAR) ? "." : "",
				(Mbhaddress != NULLCHAR) ? Mbhaddress : "");
			    if (Mbfwdinfo)
				usprintf(m->user, "[%s] ", Mbfwdinfo);
	        	    if (Mbqth)
				usprintf(m->user,"%s ", Mbqth);
			    if (MbMID)
				usprintf(m->user,"#:%u ", msgid);
			    if (Mbzip)
				usprintf(m->user,"Z:%s ", Mbzip);
	        	    if (MbBID && (thebid[0] == '$'))
	        	    	usprintf(m->user, "$:%s", &thebid[1]);
		            usprintf(m->user, "\n");
		    } else
			    usprintf(m->user, "R:%s %d@%s%s%s\n", mbxtime(tb), msgid, buf, (Mbhaddress) ? "." : "",
				(Mbhaddress) ? Mbhaddress : "");
	    }
            break;
        }
		/* The first Received: line is the one that we have added */
        if(!rec && htype(buf) == RECEIVED)
		     ++rec;
    }
    /*Go past the SMTP headers to the data of the message.
     *Check if we need to forward the SMTP headers!
     *920114 - WG7J
     */
    for(;;) {
        if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
            break;
        pwait (NULL);
        cnt -= strlen(buf);
        if(*buf == '\n')    /* last header line */
            break;
        if (adaptaddress (buf))
       	        usputs(m->user,buf);
        else if(Mbsmtptoo) { /*YES, forward SMTP headers TOO !*/
            switch(htype(buf)) {
                case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
                case STATUS:   /* Don't forward the "Status:" line either */
                case BBSTYPE:
                case SUBJECT:
                case TO:
                case DATE:
                    break;
                case FROM:
                    /* Don't forward the "From: " line either.
                     * make it ">From: "
                     */
                    cp = strdup(buf);
                    strcpy(buf,">");
                    strcat(buf,cp);
                    free(cp);        /*note fall-through*/
                default:
                    usputs(m->user,buf);
            }
        }
    }
    /* If this is a message that originated locally,
     * there are NO other R: headers
     * in that case send a '\n',
     * to separate the text from our R:-header - WG7J
     */
    if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
        return; /* NO text ??? */
    cnt -= strlen(buf);
    if(strncmp(buf,"R:",2)) /* NO R: found! */
        /*Now a blank line, separating our headers and body*/
        usputs(m->user,"\n");
    if (!strncmp (Hdrs[RRECEIPT], buf, strlen(Hdrs[RRECEIPT])))	{  /* return receipt line */
	if (!isarea (m->area))		/* only send if not a bulletin */
		usputs(m->user,buf);
	else
	    fgets(buf,sizeof(buf),m->mfile);  /* eat the blank line following */
	    cnt -= strlen(buf);
	}
    else
	    usputs(m->user,buf);

    /* the rest of the message is treated below */
#ifdef nope
    do {
		len = min(cnt,sizeof(buf)-1);
		if(fread(buf,1,len,m->mfile) != len)
			break;
		pwait (NULL);
		cnt -= len;
		buf[len] = '\0';
		usputs(m->user,buf);
	} while(cnt);
#else
		col = 0;
		while (!feof(m->mfile) && cnt > 0) {
			for (col = 0;  col < MAXBUF;) {
				c = getc(m->mfile);
				cnt--;
				if (feof(m->mfile) || cnt == 0) /* end this line */
					break;
				if (c == '\t') {
					ccnt = col + 8 - (col & 7);
					if (ccnt >= MAXBUF) /* end this line */
						break;
					while (col < ccnt)
						buf[col++] = ' ';
				} else {
					if (c == '\n')
						break;
					buf[col++] = c;
				}
			}
			if(col < MAXBUF)
				buf[col++] = '\n';
			buf[col] = '\0';
			usputs(m->user,buf);
			pwait (NULL);
		}
#endif
}

/* Parse a line for date and time in Arpanet format
 * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
 * (yymmdd/hhmmz)
 */
char *
mbxtime(line)
char *line;
{
    extern char *Months[];
    static char buf[13];
    char *cp;
    int year,month,day,hour,minute,maxdays;

    cp = line;
    while(isspace(*cp))    /* skip initial blanks */
        ++cp;
    if(*cp == '\0')
        return NULLCHAR;
    if(strlen(cp) < 22)
        return NULLCHAR;
    cp += 5;
    day = atoi(cp);
    if(*(++cp) != ' ')
        ++cp;
    ++cp;
    for(month=0; month < 12; ++month)
        if(strnicmp(Months[month],cp,3) == 0)
            break;
    if(month == 12)
        return NULLCHAR;

    /* Get things, and adjust for GMT/UTC time - WG7J */
    month++;
    year = atoi(cp+4);
    hour = atoi(cp + 7);
    minute = atoi(cp + 10);

    if(UtcOffset != 0) {
        hour -= UtcOffset;
        /* See if we went past midnight */
        if(hour > 23) {
            hour -= 24;
            ++day;
            /*Check for next month*/
            if(month == 2) { /*February, check leap-year*/
                if((year%4) == 0)
                    maxdays = 29;
                else
                    maxdays = 28;
            } else {
                if((month%2) == 0)
                    maxdays = 30;
                else
                    maxdays = 31;
            }
            if(day > maxdays) { /*adjust month*/
                day = 1;
                if(++month == 13) { /*next year*/
                    month = 1;
                    year++;
                }
            }
        } else
            if(hour < 0) { /*previous day !*/
                hour += 24;
                if(--day == 0) { /*previous month*/
                    if(--month == 0) { /*previous year*/
                        year--;
                        month = 12;
                    }
                    if(month == 2) { /* February, check leap year */
                        if((year%4) == 0)
                            day = 29;
                        else
                            day = 28;
                    } else {
                        if((month%2) == 0)
                            day = 30;
                        else
                            day = 31;
                    }
                }
            }
    }

    sprintf(buf,"%02d%02d%02d/%02d%02dz",year,month,day,hour,minute);
    return buf;
}
     
static char *
grabtext(from, to, marker)
char *from, *to;
int marker;
{
   while (*from!=marker)
      *to++ = *from++;
   *to = '\0';
   return from+1;
}

/* Makes a command line and returns -1 if the message cannot be sent. */
static int
makecl(m, msgn, dest, line, subj, bid, bul)
struct mbx *m;
int msgn;		/* Message number */
char *dest;		/* Destination address to use instead of To: line */
char *line, *subj;	/* Buffers to keep command line and subject */
char *bid;	/* Buffer to keep bid */
int *bul;       /* True if message is in public message area */
{
   int bulletin = *bul;
   int foundbid = 0;
   char to[LINELEN], atbbs[LINELEN], from[LINELEN], buf[LINELEN], *cp;
#ifdef FBBFWD
    char bid2[LINELEN];
#endif

   if(m->mfile == NULLFILE)
	return -1;

   if(!bulletin && (m->mbox[msgn].status & BM_READ))
	return -1;	/* the message was already read */
   fseek(m->mfile,m->mbox[msgn].start,0);
   *bid = *to = *atbbs = *from = '\0';
   if(subj != NULLCHAR)
	*subj = '\0';
   m->stype = bulletin ? 'B' : 'P';	/* default to SB or SP */
   while (fgets(buf,sizeof(buf),m->mfile)) {
      if (buf[0] == '\n')
         break; /* envelope finished */
      switch (htype(buf)) {
      case TO:
	    /* The following code tries to parse "To: " lines where the
	     * address looks like any of the following: "to@atbbs",
	     * "<to@atbbs>", "<to%atbbs@host>" and with possible spaces
	     * surrounding the '<>' characters.
	     */
	    if((cp = getaddress(buf,0)) == NULLCHAR)
			break;
	    strcpy(to,cp);
	    if((cp = strchr(to,'%')) != NULLCHAR) { /* look for a '%' */
			strcpy(atbbs,cp + 1);
			*cp = '\0';    /* "to" ends at the '%' character */
	    }
	    else {	/* no '%' but maybe a '@'? */
			if((cp = strchr(to,'@')) != NULLCHAR) {
				strcpy(atbbs,cp + 1);
				*cp = '\0';   /* "to" ends at the '@' character */
			}
	    }
	    if(*atbbs != '\0')		/* either '%' or '@' found */
		 /* cut "atbbs" at the first '@' character */
		 for(cp = atbbs; *cp != '\0'; ++cp)
		      if(*cp == '@') {
			   *cp = '\0';
			   break;
		      }
	    /* "to" or "atbbs" should not be more than 6 characters (ALEN).
	     * If "to" is too long, it might simply be because the area name
	     * is longer than 6 characters, but it might also be because
	     * the address on the To: line is in an obscure format that we
	     * failed to parse (eg '!' character notation.)
	     */
	    if(strlen(to) > ALEN) {
		/* Play safe and set "to" and "atbbs" to the area name */
		strcpy(to,m->area);
		strcpy(atbbs,m->area);
      	    }

/* why would we want to add an atbbs if the message doesn't have one originally ?!?! */
#if 0
	    if(*atbbs == '\0')
		strcpy(atbbs,to);
#endif

      	    to[ALEN] = '\0';
	    /* Only if the BBS supports "hierarchical routing designators"
	     * is the atbbs field allowd to be longer than 6 characters and
	     * have dots in it.
	     */
	    if((m->sid & MBX_HIER_SID) == 0) {
		 atbbs[ALEN] = '\0';	/* 6 character limit */
		 if((cp = strchr(atbbs,'.')) != NULLCHAR)
		      *cp = '\0';	/* cut "atbbs" at first dot */
	    }
            break;
      case MSGID:
	    /* The following code distinguishes between two different types
	     * of Message-IDs: <abcde@callsign.bbs> and <abcde@host.domain>.
	     * The first type is converted to $abcde and the second to
	     * $abcde_host.domain. This preserves compability with BBSes.
	     */
	    if((cp = getname(buf)) == NULLCHAR)
			break;
	    bid[0] = '$';
	    strcpy(&bid[1],cp);
		cp = strchr(bid,'@');
	    /* A trailing ".bbs" indicates that the Message-ID was generated
	     * from a BBS style message, and not a RFC-822 message.
	     */
        if(cp != NULLCHAR && stricmp(&bid[strlen(bid) - 4], ".bbs") == 0) {
			*cp = '\0'; /*retain the bid given by user*/
            foundbid = 1; /* Indicate we found a 'real' bid - WG7J */
        } else {
			/*This is a message with no bid, MSGID is <msg#@hostname>
			 *make this BID style '$msg#_host'
			 *ie. replace @ with _ and
			 *cut off after first part of hostname	- WG7J
			 */
			*cp = '_';
			if((cp = strchr(cp,'.')) != NULLCHAR)
				*cp = '\0';
		}
	    bid[13] = '\0';	/* BIDs should be no longer than 13 bytes */
      	    break;
      case SUBJECT:
        if(subj != NULLCHAR) {
      		(void) grabtext(buf+9, subj, '\n');
            /* Make sure subject isn't empty - WG7J */
            cp = subj;
            while(*cp == ' ' || *cp == '\t')
                cp++;
            if(*cp == '\0')
                strcpy(subj,"None");
        }
            break;
      case FROM:
	    if((cp = getaddress(buf,0)) != NULLCHAR) {
	    	if (!strnicmp (cp,"REQSVR",6) || !strnicmp (cp, "MAILER-DAEMON", 13))	{	/* MAILER-DAEMON going out->call sign */
	    		pax25(buf,Mycall);
	    		cp = strchr (buf, '-');
	    		if (cp)
	    			*cp = 0;
	    		strcpy (from, buf);
	    	} else
			findident(cp, 1, from);		/* cp points to from@domain */
		from[ALEN] = '\0';	/* 6 character limit */
	    }
            break;
      case XFORWARD:
	    if((cp = getaddress(buf,0)) == NULLCHAR)
		 break;
	    if(stricmp(m->name,cp) == 0)	{
	    	
		/* This message has already been forwarded, abort */
		return -1;
	    }
	    break;
      case BBSTYPE:
	    m->stype = buf[16];
            /* if it comes from a NTS area,
             * always send as traffic, ie 'ST' - WG7J
             */
            if(!strnicmp(m->area,"nts",3))
                m->stype = 'T';
            if(m->stype == 'B') {
                bulletin = 1;
                *bul = 1;
            }
	    break;
      default:
	    break;
      }
   }
   /* Check for an invalid RFC-822 header */
   if((to[0] == '\0' && ((dest != NULLCHAR && *dest == '\0') ||
      dest == NULLCHAR)) || from[0] == '\0')
	return -1;

   if(line != NULLCHAR) {
	if(dest != NULLCHAR && *dest != '\0'){
	     /* strip off hierarchical routing designators from the predefined
	      * destination address if they are not supported
	      */
	     if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
	       NULLCHAR)
		*cp = '\0';
	     sprintf(line, "S%c %s < %s ", m->stype, dest, from);
	}
	else	{
#ifdef FBBFWD
            if(Mfbb && (m->sid & MBX_FBBFWD)) {
               if(atbbs)
                  sprintf(line, "FB %c %s %s %s ", m->stype, from, atbbs, to);
               else
                  sprintf(line, "FB %c %s %s %s ", m->stype, from, "local", to);
            } else
#endif
	     sprintf(line, "S%c %s%s%s < %s ", m->stype, to, (*atbbs) ? " @ " : "", atbbs, from);
	}
#ifdef nope
    /* This fixes the problem with personal MIDs being the same with
     * messages generated from aliases, RMAIL, or mail-groups. Changes
     * the bid from $abcde_host.domain to $abcde_destinationuser. - KO4KS
     */
    if (!bulletin && (m->sid & MBX_MID))	{
    	if ((cp = strrchr (bid, '_')) != NULLCHAR)	{
    		*cp++;
    		if (!strnicmp (Hostname, cp, strlen(cp)))	{
    			*(cp-1) = '%';
			if(dest != NULLCHAR && *dest != '\0')
				strcpy (cp, dest);
			else
				strcpy (cp, to);
			bid[13] = '\0';
			if ((cp = strchr (bid, '.')) != NULLCHAR)
				*cp = '\0';
		}
	}
    }
#endif

    /* This keeps us from adding a MID to someone else's message */
    if (!foundbid)	{	/* if one wasn't found, but GENERATED */
	fgets(buf,sizeof(buf),m->mfile);	/* get first data line */
	if (!strnicmp (buf, "R:", 2))	/* if it has at least one "R:" line */
		bid[0] = '\0';		/* blank out the MID */
    }

    /* convert the bid to upper case for compatability with BBSs */
    strupr (bid);

    /* Add the bid to bulletins,
     * AND ALSO to anything that came in with a bid !
     * Takes care off duplicate 'SP SYSOP@xxx $BID' problems - WG7J
     * ALSO add it to ALL messages if the remote system supports MID's - WG7J
     */
#ifdef FBBFWD
       if(Mfbb && (m->sid & MBX_FBBFWD) &&
/*          ((m->sid & MBX_MID) || ((bulletin || foundbid) & (m->sid & MBX_SID)))) */
	    ((m->sid & MBX_MID) || (bulletin && (m->sid & MBX_SID))))
          /* Append BID ( minus the '$' character. */
          strcat(line,&bid[1]);
       else
#endif
/*    if((m->sid & MBX_MID) || ((bulletin || foundbid) & (m->sid & MBX_SID))) */
      if((m->sid & MBX_MID) || (bulletin && (m->sid & MBX_SID)))
	     strcat(line,bid);
#ifdef FBBFWD
       if(Mfbb && (m->sid & MBX_FBBFWD)) {
          strcat(line," ");
          strcat(line,(char *)ltoa(m->mbox[msgn].size,bid2,10));
       }
#endif
	strcat(line,"\n");
   }
   return 0;
}

static int /* 0 = ok, -1 = problem so disc */
sendmsgtobbs(m, msgn, dest, bulletin)
struct mbx *m;
int msgn;
char *dest;		/* Optional destination address to override To: line */
int bulletin;
{
int result = -1;
char line[64], subj[256], thebid[LINELEN];

	if(makecl(m, msgn, dest, line, subj, thebid, &bulletin) == -1)
		return 0;	/* do not forward this particular message */
	tputs(line);		 /* Send mail offer to bbs */
	rip(line);
	usflush(m->user);
	if (recvline (m->user, m->line, MBXLINE) != -1 ) 	{
		if (m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) 	{
			/* Got 'OK' or any line if the bbs is unsofisticated */
			tprintf("%s\n", subj);
			sendmsg(m,msgn,thebid);   /* send the message */
			tputs("/EX\n"); /* was 0x1a */
			usflush(m->user);
			/* get F> for a good deliver */
			while (recvline (m->user, m->line, MBXLINE) != -1 )
				if (ISPROMPT(m->line)) 	{
					log(m->user,"MBOX bbs mail sent: %s ", line);
#ifdef notagain
					if(bulletin)
						m->mbox[msgn].status |= BM_FORWARDED;
					else	{
#endif
					if(!bulletin)	{
						m->mbox[msgn].status |= BM_DELETE;
						statusCtl (m->area, "ctl", &m->mbox[msgn], msgn, 0);
						m->change |= CHG_DELETE;
					}
					result = 0;
					MbForwarded++;
					break;
				}
		} else { /* OK response not received from bbs */
			if (tolower(m->line[0]) == 'n' || tolower(m->line[0]) == 'r') { /* 'NO/REJECT' response */
        	  		log(m->user,"MBOX bbs mail refused: %s\n     %s",line,m->line);
#ifdef notagain
				/* Mark refused message as forwarded if it is a bulletin.
				 * The message was probably a duplicate. Non-bulletin
				 * messages are sent without BID, so they cannot be dected
				 * as duplicates. The reason why it was refused is probably
				 * because the address was invalid. Retry later.
				 */
				if(bulletin)	{
		                	m->mbox[msgn].status |= BM_FORWARDED;
					statusCtl (m->area, "ctl", &m->mbox[msgn], msgn, 0);
/*	        		        m->change = 1;	*/
        	    		}
#endif
				result = 0;	/* don't want it, so skip it! */
			} else
	       	  		log(m->user,"MBOX bbs mail - unexpected response: %s\n     %s",line,m->line);
			
			/* should get a F> here */
			while (recvline (m->user, m->line, MBXLINE) != -1 )
				if (ISPROMPT(m->line)) 		{
	      				result = 0;
					break;
	      			}
		}
	} /* OK or NO here */
	if (m->stype != 'B')
		msgiddelete (&thebid[1]);
	return result;
}


static void
mark_forwarded (fp, ind)
FILE *fp;
long ind;
{
long save;

	clearerr(fp);
	save = ftell (fp);
	fseek (fp, ind, SEEK_SET);
	fputc ('*', fp);       /* mark as done! */
	fflush (fp);
        fseek (fp, save, SEEK_SET);
}


#ifdef FBBFWD
#include "fbb.inc"
#endif

/* Forward messages from one message area.  */
static int
fwdthisarea (m, fwd, area, newto)
struct mbx *m;
FILE *fwd;
char *area, *newto;
{
int  bulletin;
long bid, pos = 0;
int index, changed = 0, i;
int err = 0;
char *cp;
struct	let *cmsg;
char line[80];

	pwait (NULL);
	bulletin = isarea(area);	/* public area */
	if (bulletin && !FWDbulletins)
		return err;
	if (!bulletin && !FWDpersonal)
		return err;
	rewind (fwd);
	while(!err && fgets(line,MBXLINE,fwd) != NULLCHAR) {
		fflush (fwd);
		pwait (NULL);
		if (*line != '*')	{	/* if not already done */
			if ((cp = strpbrk(&line[1]," \t")) != NULLCHAR)
				*cp++ = '\0';
			if (!stricmp (area, &line[1]))	{ /* only if for us */
				bid = atol (cp);
				if (!changed)	{	/* if not already changed */
					changearea(m,area, (int) 1);
					changed = 1;
				}
				index = 0;
				for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)
					if (bid == cmsg->bid)	{
						index = i;
						break;
					}
				if (index && !(cmsg->status & (BM_ONHOLD | BM_DELETE)))	{
					if(sendmsgtobbs(m, index, newto, bulletin) == -1)
						err = 1;	/* abort */
				}
				if (!index || (!err && !(cmsg->status & BM_ONHOLD)))
					mark_forwarded(fwd, pos);
			}
		}
		pos = ftell (fwd);	/* get new backup position */
	}
	return err;
}


/* This is the main entry point for reverse forwarding. It is also used
 * for normal, "forward", forwarding.
 */
int
dorevfwd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
char oldarea[64], *area, *cp;
struct mbx *m;
int err = 0;
unsigned i = NOSUBCHANNEL;
FILE *fwd;
long thesize, theend, thetop, newsize;
char name[256];

	m = (struct mbx *)p;
	/* indicate we are doing reverse forwarding, if we are not already
	 * doing normal forwarding.
	 */
	if(m->state != MBX_FORWARD)	{
		if (!FWDreverse)
			goto notallowed;
		m->state = MBX_REVFWD;
		if ((m->sid & MBX_SID) && m->mysize)
    			smtptick(NULL);		/* wake SMTP to send that mail */
    		m->mysize = 0;
    	}
	if(fwdinit(m) != -1) 	{
		strcpy(oldarea,m->area);
		sprintf (name, "%s/%s", Mailspool, m->name);
		nntp_name_expansion (name);
		strcat (name, ".fwd");
		strlwr (name);
		if((fwd = fopen(name,UPDATE_TEXT)) == NULLFILE)
			return 0;	/* shouldn't happen except with reverse fwd */
		log(m->user,"MBOX %sforwarding mail to: %s ", (m->state == MBX_REVFWD) ? "reverse " : "", m->name);
		thesize = filelength(fileno(fwd));	/* so we know if any new */
		thetop = ftell (m->tfile);
		while(!err)	{
			if (m->privs & EXCLUDED_CMD)
				break;
			newsize = filelength(fileno(fwd));
			if (thesize != newsize)	{
				/* if new mail came in to forward, start back
				   up at the top of the areas to forward.
				   This allows you to push personal traffic
				   at highest priority */
				thesize = newsize;
				fseek (m->tfile, thetop, 0);
			}
			if (fgets(m->line,MBXLINE,m->tfile) == NULLCHAR)
				break;
			if(*m->line == '-')	/* end of record reached */
				break;
			if(*m->line == '#')	/* skip comments */
				continue;
			if (*m->line == '=')	{	/* subchannel number */
				i = atoi (&m->line[1]);
				if (i > NUMMBX || subchannelusage[i] == subchannels[i])	{	/* maxed out */
					err = 1;
					i = NOSUBCHANNEL;
					continue;
				} else
					subchannelusage[i]++;
			}
			rip(m->line);		/* adds extra null at end */
			if ((cp = strpbrk(m->line," \t")) != NULLCHAR)
				*cp = '\0';
			if(*m->line == '\0' || *m->line == '.' || *m->line == '+' || *m->line == '@')
				continue;
			/* get the optional destination field, cp will point
			 * at null byte if it is missing.
			 */
			cp = &m->line[strlen(m->line)] + 1;
			while(*cp != '\0' && isspace(*cp)) /* strip blanks */
			     ++cp;
			cp = strdup(cp);
			area = strdup(m->line);
			err = fwdthisarea (m, fwd, area, cp);
			free(cp);
			free(area);
		}
		fclose(m->tfile);
		m->tfile = NULLFILE;
		if(*oldarea != '\0')
			changearea(m,oldarea, (int) 1);
		theend = filelength(fileno (fwd));
		if (!err && thesize == theend)		{
			rewind (fwd);
			while(fgets(m->line,MBXLINE,fwd) != NULLCHAR) {
				pwait (NULL);
				if (*m->line != '*')	{	/* if not already done */
					err = 1;
					break;
				}
			}
			fclose (fwd);
			if (!err)
				remove (name);
		} else
			fclose (fwd);
	}
	if (i != NOSUBCHANNEL)
		subchannelusage[i]--;
	if(m->state == MBX_FORWARD)
		return 0;
notallowed:
	tprintf("*** Done\n");
/*	if((m->sid & MBX_RLI_SID) || (m->sid & MBX_FBB))	*/	/* disconnect if it is a W0RLI or FBB bbs */
	if(m->sid & MBX_RLI_SID)	/* disconnect if it is a W0RLI bbs */
		return domboxbye(0,NULL,m);
	return 0;
}

/* Read the forward file for a record for the connected BBS. If found,
 * return 0 if this is the right time to forward, m->tfile is left pointing
 * at the first message area to be forwarded.
 * returns -1, also, if nothing queued for forwarding.
 */
static int
fwdinit(m)
struct mbx *m;
{
char host[80];
char name[256];
int start = 1;

	if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
		return -1;
	while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
		if(*m->line == '\n')
			continue;
		if(*m->line == '#')
			continue;
		/* lines starting with '-' separate the forwarding records */
		if(*m->line == '-') {
			start = 1;
			continue;
		}
		if(start) {
			start = 0;
			/* get the name of this forwarding record */
			findident(m->line,1,host);
			if(stricmp(m->name,host) == 0) {
				if(!timeok(m->line))
					break;
				sprintf (name, "%s/%s.fwd", Mailspool, host);
				strlwr (name);
				if (access (name, 0))	/* nothing in this area! */
					break;
				/* eat the connect command line */
				do	{
					fgets(m->line,MBXLINE,m->tfile);
				} while (*m->line == '#' || *m->line == '\n');
				return 0;
			}
		}
	}
	fclose(m->tfile);
	m->tfile = NULLFILE;
	return -1;
}
/* Read the forward file for a record for the connected BBS. If found,
 * determine if this is the right time to forward, and return the command
 * line to establish a forwarding connection. m->tfile is left pointing
 * at the first message area to be forwarded.
 */
static char *
fwdanybbs(m, poll)
struct mbx *m;
int *poll;
{
	char host[80];
	int start = 1, i;
	if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
					== NULLFILE)
		return NULLCHAR;
	*poll = 0;  /* Default to no polling */
	while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
		if(*m->line == '\n')
			continue;
		if(*m->line == '#')
			continue;
		/* lines starting with '-' separate the forwarding records */
		if(*m->line == '-') {
			start = 1;
			continue;
		}
		if(start) {
			start = 0;
			/* get the name of this forwarding record */
			findident(m->line,1,host);
			strcpy(m->name,host);
			if(!timeok(m->line))
				continue;	/* too late or too early */
			/* Check for polling - WG7J */
			i=2;
			findident(m->line,2,host);
			while(*host) {
				if(*host == 'P' || *host == 'p') {
					*poll = 1;
					break;
				}
				i++;
				findident(m->line,i,host);
			}
			/* get the connect command line */
			do	{
				fgets(m->line,MBXLINE,m->tfile);
			} while (*m->line == '#' || *m->line == '\n');
			return strdup(m->line);
		}
	}
	fclose(m->tfile);
	m->tfile = NULLFILE;
	return NULLCHAR;
}

/* get any groups of four digits that specify the begin and ending hours of
 * forwarding. Returns 1 if forwarding may take place.
 */
static int
timeok(line)
char *line;
{
	char hours[80], *now;
	long t;
	int t1, t2, pos = 2;
	findident(line,pos++,hours);
	if(*hours == '\0')
		return 1;	/* no digits default to 0023, ie. anytime */
	time(&t);
	now = ctime(&t) + 11;
	*(now + 2) = '\0';
	while(*hours != '\0') {
		t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
		t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
		if(atoi(now) >= t1 && atoi(now) <= t2)
			return 1;		/* right in time */
		findident(line,pos++,hours);	/* get next group if any */
	}
	return 0;	/* too early or too late */
}

int
dombtimer(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	if(argc < 2){
		tprintf("Forwarding timer: %lu/%lu\n",
			read_timer(&fwdtimer)/1000L,
			dur_timer(&fwdtimer)/1000L);
		return 0;
	}
	stop_timer (&fwdtimer);	/* just in case */
	fwdtimer.func = (void (*)__ARGS((void *)))fwdtick;/* what to call on timeout */
	fwdtimer.arg = NULL;		/* dummy value */
	set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
	start_timer(&fwdtimer);     /* fire it up */
	return 0;
}

int
dombkick(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	fwdtick (NULL);
	return 0;
}


/* MDMII: fwdproc is the old fwdtick.   But, since it can call mspause, which is
 * very very bad for timer functions :-( this has been converted to a server.
 */
static void
fwdtick(v)
void *v;
{
	start_timer(&fwdtimer);		/* and restart the timer */
	if (FWDmode)
		if (newproc ("forward daemon", 2048, fwdproc, 0, NULL, NULL, 0) == NULLPROC)
			log (-1, "Couldn't start Forwarding process");
}


/* called when the forward timer expires or explicitly by dombkick() */
static void
fwdproc(nerf,v1,v2)
int nerf;		/* unused */
void *v1, *v2;	/* unused */
{
char *cc, *cp;
struct mbx *m;
unsigned i;
int poll, skip = 0;
char name[256];
time_t t;

	if(Mtrace)
	        printf("mailbox: forward started\n");
	if((m = newmbx()) == NULLMBX){
		if(Mtrace)
			printf("forward: unable to start new maibox\n");
		return;
	}
	time(&t);
	m->logontime = (long) t;
	m->user = Curproc->output;
	m->name[0] = 0;
	m->state = MBX_TRYING;
	lastSessionSkipped = 0;
	while((cc = fwdanybbs(m,&poll)) != NULLCHAR) {
		i = NOSUBCHANNEL;
		if(Mtrace)
	        	printf("mailbox: examining '%s'\n", m->name);
		pwait (NULL);
		if(isconnbbs(m)) 	{
			/* already connected to this BBS, skip it */
			skip = 1;
			if (Mtrace)
				printf ("fwd: '%s' already connected\n", m->name);
		}
		while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
			if(*m->line == '#')
				continue;
			if(*m->line == '\n')
				continue;
			
			if(*m->line == '-') {	/* end of record reached */
				skip = 0;
				break;
			}
			if (*m->line == '=')	 /* sub-channel info */
				i = atoi (&m->line[1]);
			if((cp = strpbrk(m->line," \t")) != NULLCHAR)
				*cp = '\0';
			if(skip || *m->line == '\0' || *m->line == '.' || \
				*m->line == '+' || *m->line == '@')
				continue;
			pwait (NULL);
			/* If we poll, there is no need to check message area, since this
			 * is also done later. It will speed things up here - WG7J
			 */
			if (!poll)	{	/* don't need if polling */
				sprintf (name, "%s/%s.fwd", Mailspool, m->name);
				strlwr (name);
				if(Mtrace)
			        	printf("mailbox: checking for file '%s'\n", name);
			}
			skip = 1;
			if (poll || !access (name, 0))	{
				if (i != NOSUBCHANNEL || subchannelusage[i] == subchannels[i])	{	/* maxed out */
					lastSessionSkipped = 1;
					continue;
				}
				if(Mtrace)
					printf("forward: to %s\n",m->name);
				if (i != NOSUBCHANNEL)
					subchannelusage[i]++;
				newproc("Mbox forwarding", 3072,startfwd, (int)i, (void *)cc,(void *)strdup(m->name),0);
			} else
				free (cc);
			cc = NULLCHAR;
		}
		free(cc);
	}
	m->state = MBX_FORWARD;
	exitbbs(m);
}

/* returns 1 if m->name matches the name of another connected mailbox. */
static int
isconnbbs(m)
struct mbx *m;
{
	int i;
	for(i = 0; i < NUMMBX; ++i)
		if(Mbox[i] != NULLMBX && Mbox[i] != m &&
			(stricmp(m->name,Mbox[i]->name) == 0) && (m->state != MBX_TRYING))
				return 1;
	return 0;
}

/* possible commands on the command line in the forwarding file */
static struct cmds cfwdcmds[] = {
	"tcp",		openconn,	0, 0, NULLCHAR,
	"telnet",	openconn,	0, 0, NULLCHAR,
#ifdef AX25
	"ax25",		openconn,	0, 0, NULLCHAR,
	"connect",	openconn,	0, 0, NULLCHAR,
#endif
#ifdef NETROM 
	"netrom",	openconn,	0, 0, NULLCHAR,
#endif
	NULLCHAR
};

static void
fwdcleanup (index, m, string)
int index;
struct mbx *m;
char *string;
{
	if(Mtrace && string)
		printf(string, m->name);
	exitbbs(m);
	if (index != NOSUBCHANNEL)
		subchannelusage[index]--;
	if (lastSessionSkipped)
		fwdtick (NULL);
}


/* this function is called whenever the forwarding timer expires */
static void
startfwd(a,v1,v2)
int a;
void *v1, *v2;
{
struct mbx *m;
char *cc;
int32 timeout;
int rval;
char *cp;
char Continue[MBXLINE];
time_t t;

	cc = (char *) v1;
	if((m = newmbx()) == NULLMBX) {
		free(cc);
		free((char *)v2);
		if (a != NOSUBCHANNEL)
			subchannelusage[a]--;
		return;
	}
	time(&t);
	m->logontime = (long) t;
	strcpy(m->name,(char *)v2);
	free((char *)v2);
	m->state = MBX_TRYING;
	/* open the connection, m->user will be the new socket */
	if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
		free(cc);
		fwdcleanup (a, m, "forward: unknown protocol\n");
		return;
	}
	free(cc);
	m->state = MBX_FORWARD;
	sockowner(m->user,Curproc);
	close_s(Curproc->output);
	close_s(Curproc->input);
	/* m->user will be closed automatically when this process exits */
	Curproc->output = Curproc->input = m->user;
	/* We'll do our own flushing right before we read input */
	setflush(m->user,-1);

	if(fwdinit(m) == -1) {
		/* it is probably not the right time to forward anymore */
		fwdcleanup (a, m, NULLCHAR);
		return;
	}
	/* read the connect script. Lines starting with a dot will be sent
	 * to the remote BBS.
	 */
    Continue[0] = '\0';
    while((cp=fgets(m->line,MBXLINE,m->tfile)) != NULLCHAR) {
    	if (*m->line == '#' || *m->line == '=' || *m->line == '\n')
    		continue;
        /* Expanded to do timeouts, and return string recognition - WG7J */
        if(*m->line == '.') {           /* send this line */
            tputs(m->line + 1);
            if(Mtrace)
                printf("fwd: %s > %s\n",m->name,m->line+1);
            Continue[0] = '\0';         /* reset reply string */
        } else if(*m->line == '+') {    /* string upon wich we continue ! */
            strcpy(Continue,m->line+1);
            rip(Continue);              /* get rid of \n */
        } else if(*m->line == '@') {    /* string that sets timeout */
            timeout = atoi(m->line+1);
            if(timeout)                 /* if a valid conversion */
                timeout *= 1000;        /* in ms ! */
            else
                timeout = 90*1000L;     /* default to 1.5 minutes */
            if(Mtrace)
                printf("fwd: %s, wait %ld < %s\n",m->name,timeout/1000,Continue);
            /* Now do the actual response interpretations */
            alarm(timeout);
            rval = recvline(m->user,m->line,MBXLINE);
            alarm(0L);
            /* Did we timeout, or connection disappear ? */
            if(Mtrace) {
                printf("fwd: %s, rx %d",m->name,rval);
                if(rval >= 0)
                    printf(", %s",m->line);
                else
                    putchar('\n');
            }
            if((rval < 0) || (strstr(m->line,Continue) == NULLCHAR)) {
            	fwdcleanup (a, m, "fwd: %s, aborted!\n");
                return;
            }
            Continue[0] = '\0';         /* reset reply string */
        } else      /* must be the end of the script */
            goto go_on;

        usflush(m->user);   /* send it, if any */
    }
    /* Now we've past all in-between stuff, go talk to the bbs ! */
go_on:
	usflush(m->user);
	fclose(m->tfile);
	m->tfile = NULLFILE;

    /* make sure there is something left ! */
    if(cp == NULLCHAR) {
    	fwdcleanup (a, m, "fwd: forward.bbs error!\n");
        return;
    }
    if(Mtrace)
        printf("fwd: %s, script done\n",m->name);

	/* read the initial output from the bbs, looking for the SID */
	for(;;) {
                timeout = 120*1000L;     /* wait up to 2 minutes for each response line */
		if(Mtrace)
                	printf("fwd: %s, wait %ld < %s\n",m->name,timeout/1000,">");
		alarm(timeout);
		rval = recvline(m->user,m->line,MBXLINE);
		alarm(0L);
		if(rval == -1) {
			fwdcleanup (a, m, NULLCHAR);
			return;
		}
		if(ISPROMPT(m->line))
			break;
		if(*m->line == '[') {		/* parse the SID */
			rip(m->line);
			mbx_parse(m);
			continue;
		}
	}
	/* Now sync the two ends as telnet password messes them up */
	if(socklen(m->user,0))		/* discard any remaining input */
		recv_mbuf(m->user,NULL,0,NULLCHAR,0);

	/* send our SID if the peer announced its SID */
	if(m->sid & MBX_SID) {
#ifdef FBBFWD
		if (Mfbb)
			tputs(FWDlzw ? MboxIdFwdFBB : MboxIdFBB);
		else
#endif
		tputs(FWDlzw ? MboxIdFwd : MboxId);
		usflush(m->user);
#ifdef LZW
		/* If we both support it, go into compression here */
	    	if (FWDlzw && m->sid & MBX_TNOS)
    			togglelzw (m->user, 1);		
#endif
		for(;;) {
			if(recvline(m->user,m->line,MBXLINE) == -1) {
				exitbbs(m);
				return;
			}
			if(ISPROMPT(m->line))
				break;
		}
	}
	/* start the actual forwarding */
#ifdef FBBFWD
    if(Mfbb && (m->sid & MBX_FBBFWD)) {
       dofbbfwd(0,NULL,(void *)m);
       return;
    }
    else
#endif
	dorevfwd(0,NULL,(void *)m);
	/* ask for reverse forwarding or just disconnect */
	if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
	   (m->sid & MBX_SID) == 0) {
	   	fwdcleanup (a, m, NULLCHAR);
		close_s(Curproc->output);
		return;
	}
	usflush(m->user);
	/* parse the commands that are are received during reverse
	 * forwarding.
	 */
	while(recvline(m->user,m->line,MBXLINE) > 0) {
		if (m->privs & EXCLUDED_CMD)
			break;
		rip(m->line);
		if((rval = mbx_parse(m)) == -2)	/* got the "*** Done" command */
			break;
		if (rval && BBSdump)	/* we dump for all unknowns! */
			break;
		if (m->privs & EXCLUDED_CMD)
			break;
		tputs("F>\n");
		usflush(m->user);
	}
#if 0
/*	if((m->sid & MBX_RLI_SID) || (m->sid & MBX_FBB))	{	*/	/* disconnect if it is a W0RLI or FBB bbs */
	if(m->sid & MBX_RLI_SID)	{	/* disconnect if it is a W0RLI bbs */
		domboxbye(0,NULL,m);
		return;
	}
#else
	domboxbye(0,NULL,m);
#endif
	if ((m->sid & MBX_SID) && m->mysize)
    		smtptick(NULL);		/* wake SMTP to send that mail */
	fwdcleanup (a, m, NULLCHAR);
        usflush(Curproc->output);
	mspause(500L);
	close_s(Curproc->output);
}

/* open a network connection based upon information in the cc line.
 * m->user is set to the socket number.
 */
static int
openconn(argc,argv,p)
int argc;
char *argv[];
void *p;
{
	struct mbx *m;
	char sock[MAXSOCKSIZE], alias[AXBUF];
#ifdef NETROM
    struct nrroute_tab *rp;
#endif
	union sp sp;
	int len;

    m = (struct mbx *)p;
	sp.p = sock;
	if(argc < 2)
		return -1;
	switch(*argv[0]) {
	case 't':
		sp.in->sin_family = AF_INET;
		if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0)
			return -1;
		/* get the optional port number */
		if(argc > 2)
			sp.in->sin_port = atoip(argv[2]);
		else
			sp.in->sin_port = IPPORT_TELNET;
		if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1)
			return -1;
		len = sizeof(*sp.in);
        m->family = AF_INET; /*So the user list will be correct! - WG7J */
        break;
#ifdef AX25
	case 'a':
	case 'c':	/* allow 'c' for 'connect' as well */
		if(argc < 3)
			return -1;
		sp.ax->sax_family = AF_AX25;
		strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
		setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
		/* no digipeaters for now, use the "ax25 route add" command */
		if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1)
			return -1;
		len = sizeof(*sp.ax);
        m->family = AF_AX25; /*So the user list will be correct! - WG7J */
		break;
#endif /* AX25 */
#ifdef NETROM
	case 'n':
        /* See if the requested destination could be an alias, and
         * use it if it is.  Otherwise assume it is an AX.25
         * address.
         */
        putalias(alias,argv[1],0);
        strupr(argv[1]);
        if ((rp = find_nrboth(alias,argv[1])) == NULLNRRTAB)  {
            if(Mtrace)
            tprintf("fwd: Netrom route unavailable - %s\n",argv[1]);
            return -1;
        }
        /* Setup the local side of the connection */
        sp.nr->nr_family = AF_NETROM;
		len = sizeof(*sp.nr);
		if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1) {
		     if(Mtrace)
			  tprintf("fwd: unable to open netrom socket - %s\n",argv[1]);
			
		     return -1;
		}
		memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
        memcpy(sp.nr->nr_addr.node,Nr_iface->hwaddr,AXALEN);
		bind(m->user,sp.p,len);

        /* Now the remote side */
        memcpy(sp.nr->nr_addr.node,rp->call,AXALEN) ;
        /* The user callsign of the remote station is never
		 * used by NET/ROM, but it is needed for the psocket() call.
		 */
        memcpy(sp.nr->nr_addr.user,rp->call,AXALEN) ;

        m->family = AF_NETROM; /*So the user list will be correct! - WG7J */
	break;
#endif /* NETROM */
	default:
		return -1;
	}
	sockmode(m->user,SOCK_ASCII);
	if(connect(m->user,sp.p,len) == -1) {
		log(m->user,"MBOX forward failed: %s errno %d",
				sockerr(m->user),errno);
		close_s(m->user);
		return -1;
	}
	return m->user;
}


void
forwardingSummary()
{
int k;
register FILE *fp;
char buf[100], *cp;
int totbul = 0, totper = 0, bul, per;

	for (k = 0; k < Numfwds; k++)		{
		sprintf(buf,"%s/%s.fwd",Mailspool,MyFwds[k]);
		strlwr(buf);
		per = bul = 0;
		if((fp = fopen(buf,READ_TEXT)) != NULLFILE)	{
			while (fgets(buf,sizeof(buf),fp) != NULLCHAR)
				if (*buf == ' ')	{
					cp = strchr (&buf[1], ' ');
					if (cp)		{
						*cp++ = 0;
						if (isarea (&buf[1]))
							bul++;
						else
							per++;
					}
				}
			fclose(fp);
		}
		tprintf ("Queued for forwarding to %-10.10s:   Bulletins/Personal (%5d/%-5d)\n", MyFwds[k], bul, per);
		totbul += bul;
		totper += per;
	}
	if (k)
		tprintf ("Total messages to forward          :   Bulletins/Personal (%5d/%-5d)\n\n", totbul, totper);
	else
		tprintf ("You have no BBS's in your 'forward.bbs' file!\n");
}


int
AREAlookup (area, index)
char *area;
int index;
{
FILE *fp;
int start = 1;
int checking = 0;
char *cp;
char line[80];
int retval = 0;

/*    if(Checklock)
          return retval;	*/
    if((fp=fopen(Forwardfile,READ_TEXT)) == NULLFILE)
        return retval;
    /*Now scan the forward.bbs file to find bbs's*/
    while(fgets(line,sizeof(line),fp) != NULLCHAR) {
        if(*line == '\n')
            continue;
        if(*line == '#')
        	continue;
        if(*line == '.' || *line == '+' || *line == '@' || *line == '=')
        	continue;
        /* lines starting with '-' separate the forwarding records */
        if(*line == '-') {
            start = 1;
            checking = 0;
            continue;
        }
        if (checking && !strnicmp (area, line, strlen(area)))	{
		cp = &line[strlen(area)];
		if (*cp == ' ' || *cp == '\n' || *cp == '\t')	{
			retval = 1;
			break;
		}
	}
        if(start) {
            start = 0;
            if (checking)
            	break;
            /* get the name of this forwarding record */
            if((cp=strpbrk(line," \n\t")) != NULLCHAR)
                *cp = '\0';
            if(strlen(line) > FWDBBSLEN)
                continue;   /*What kind of bbs-call is this ?*/
            if (!stricmp (MyFwds[index], line))
            	checking = 1;
        }
    }
    fclose(fp);
    return retval;
}


#endif /*MBFWD*/
