#include "global.h"
#include "ctype.h"
#include "files.h"
#include <time.h>
#include "bm.h"
#include "cmdparse.h"

#if !defined(_lint)
static char rcsid[] OPTIONAL = "$Id: fwdcmd.c,v 1.22 2001/05/06 16:32:56 brian Exp $";
#endif

int UtcOffset = 0;
int BIDuknos = 0;

#ifdef MBFWD
extern const char *continents[];
#define numcontinents 19

#ifdef ALTERBID
int chkBidAltered = 1;
int holdBidAltered = 1;
#endif
int MbBID = 0;
int MbMID = 1;
char *BIDsuffix;
int MbRSTYLE = 0;
char *Mbqth = NULLCHAR;
char *Mbzip = NULLCHAR;
char *Mbfwdinfo = NULLCHAR;
char *Mbhaddress = NULLCHAR;
int Mtrace = 0;
int FWDareatrace = 1;
#ifdef XFWD
int MXfwd = 0;
int Xtrace = 0;
#endif
#ifdef FBBFWD
int FBBtrace = 0;
int Mfbb = 0;
#endif
#ifdef FBBCMP
int Mfbbcmp = 0;
#endif
int Mbsmtptoo = 0;
char *mbxRCall;
int FWDctlz = 1;
char FWDCall[AXALEN];
int FWDmode = 1, FWDpersonal = 1, FWDbulletins = 1, FWDreverse = 1, FWDinreverse = 1;
int FWDminidle = 30;
int FWDlimittime = 0;
int SYSOPprotect = 1;
static int TAPRspec = 1;
int FWDpmulti = 0;
#ifdef UKIP
int FWDtlines = 0;
int FWDxbid = 0;
#endif

extern void ReadFwdBbs (void);
extern void updateFwd (char *who, char *area,long bid,long size);
extern int dostr (int argc,char *argv[],const char *cmdstr,const char *label, char **str);
extern int forwardreset (int argc,char *argv[],void *p);
extern void forwardingSummary (void);
extern char *mbxtime (char *line);
extern void fwdproc (int, void *, void *);
extern void checkforALTs (void);

#ifdef ALTERBID
static int dombalterbid (int argc,char *argv[],void *p);
static int dombalterhold (int argc,char *argv[],void *p);
#endif
static int dofwdreload (int argc,char *argv[],void *p);
static int dofwdbid (int argc,char *argv[],void *p);
static int dobidsuffix (int argc,char *argv[],void *p);
static int dobiduknos (int argc,char *argv[],void *p);
static int dombutc (int argc,char *argv[],void *p);
static int dombmid (int argc,char *argv[],void *p);
static int dombrsample (int argc,char *argv[],void *p);
static int dombrstyle (int argc,char *argv[],void *p);
static int dombqth (int argc,char *argv[],void *p);
static int dombzipcode (int argc,char *argv[],void *p);
static int dombfwdinfo (int argc,char *argv[],void *p);
static int dombhaddress (int argc,char *argv[],void *p);
static int dombtapr (int argc,char *argv[],void *p);
static int dombtrace (int argc,char *argv[],void *p);
#if defined(XFWD) || defined(FBBFWD)
static int doareatrace (int argc,char *argv[],void *p);
#endif
static void fwdqueuearea (char *bbs, char *area);
static int dofwdqueue (int argc,char *argv[],void *p);
#ifdef FBBFWD
static int dofbbtrace (int argc,char *argv[],void *p);
#endif
static int dombsubchannel (int argc,char *argv[],void *p);
static int dombsysopprotect (int argc,char *argv[],void *p);
static int dombsmtptoo (int argc,char *argv[],void *p);
static int dombrcall (int argc,char *argv[],void *p);
static int domycall (int argc,char *argv[],void *p);
static int dofwdmode (int argc,char *argv[],void *p);
static int dopersonal (int argc,char *argv[],void *p);
static int doactive (int argc,char *argv[],void *p);
static int dolaston (int argc,char *argv[],void *p);
static int dominidle (int argc,char *argv[],void *p);
static int dolimittime (int argc,char *argv[],void *p);
static int dobulletins (int argc,char *argv[],void *p);
static int doreverse (int argc,char *argv[],void *p);
static int doinreverse (int argc,char *argv[],void *p);
static int dosummary (int argc,char *argv[],void *p);
static int dofwdstatus (int argc,char *argv[],void *p);
static int doctlz (int argc,char *argv[],void *p);
int dombkickone (int argc,char *argv[],void *p);
int doforward (int argc,char *argv[],void *p);
#ifdef FBBFWD
#ifdef FBBCMP
static int dofbbcmpstyle (int argc,char *argv[],void *p);
#endif
static int dofbbstyle (int argc,char *argv[],void *p);
#endif
#ifdef XFWD
static int doxstyle (int argc,char *argv[],void *p);
static int doxtrace (int argc,char *argv[],void *p);
#endif
static int dofwdpmulti (int argc,char *argv[],void *p);
#ifdef UKIP
static int dofwdtlines (int argc,char *argv[],void *p);
static int dofwdxbid (int argc,char *argv[],void *p);
#endif

#ifdef CATALOG
#include "catalog.h"

#define CAT fwdcmd_catalog

#define LASTCompleted	__STR(0)
#define enabled		__STR(1)
#define tapr1		__STR(2)
#define tapr2		__STR(3)
#define personal	__STR(4)
#define bulletins	__STR(5)
#define FBBstyle	__STR(6)
#define FBBcompressed	__STR(7)
#define usectlz		__STR(8)
#define reverseout	__STR(9)
#define reversein	__STR(10)
#define activesessions	__STR(11)
#define originalBID	__STR(12)
#define localUTC	__STR(13)
#define localMID	__STR(14)
#define W0RLIstyle	__STR(15)
#define qthusage	__STR(16)
#define usagezipcode	__STR(17)
#define usagefwdinfo	__STR(18)
#define usagehaddr	__STR(19)
#define tapr3		__STR(20)
#define tapr4		__STR(21)
#define fwdtraceflag	__STR(22)
#define FBBtraceflag	__STR(23)
#define subchanneldata	__STR(24)
#define usagesubchannel	__STR(25)
#define validsubchannels __STR(26)
#define maxonsubchannel	__STR(27)
#define forwardSMTP	__STR(28)
#define uknosBID	__STR(29)


#else	/* CATALOG */
static const char LASTCompleted[] = "\nLast completed forwarding sessions:\n";
static const char enabled[] = "Forwarding mode";
static const char tapr1[] = "Make haddress conform to TAPR X.3.4 specification";
static const char tapr2[] =
	"Unless you *MUST*, PLEASE use a haddress that conforms to the X.3.4 spec!\n"
	 "The big losers when you *DON'T* are the Internet gateway SYSOPS!\n\007";
static const char personal[] = "Forwarding Personal Messages";
static const char bulletins[] = "Forwarding Bulletins";
static const char FBBstyle[] = "FBB-style forwarding";
static const char FBBcompressed[] = "FBB-style compression forwarding";
static const char usectlz[] = "Use ^Z intead of /EX to end messages when forwarding";
static const char reverseout[] = "Outgoing Reverse Forwarding Enabled";
static const char reversein[] = "Incoming Reverse Forwarding Enabled";
static const char activesessions[] = "\nActive Forwarding Sessions:\n";
static const char originalBID[] = "Original BID in R: lines";
static const char localUTC[] = "Local Time is UTC";
static const char localMID[] = "Local MID in R: lines";
static const char W0RLIstyle[] = "W0RLI style R: lines";
static const char qthusage[] = "Usage: forward qth <your qth> || \"<your qth, state>\"\n";
static const char usagezipcode[] = "Usage: forward zipcode <your zip>\n";
static const char usagefwdinfo[] = "Usage: forward fwdinfo \"<your R:-line [info]>\"\n";
static const char usagehaddr[] = "Usage: forward haddress <your H-address (without call)>\n";
static const char tapr3[] = "Sorry, but that is not a proper haddress. The continent must be 4-characters.\n";
static const char tapr4[] = 
	"The selected haddress does not adhere to TAPR X.3.4 recommendation. :-(\n"
	"The sooner we all use 4-character continents, the better\n\007";
static const char fwdtraceflag[] = "Forward trace flag";
static const char FBBtraceflag[] = "FBB Forwarding trace flag";
static const char subchanneldata[] = "  Subchannel %2d: Maximum Fwds - %2d, Currently - %2d";
static const char usagesubchannel[] = "Usage: forward subchannel channel# [maxfwds [description]]\n";
static const char validsubchannels[] = "Valid subchannel numbers are 0 through %d\n";
static const char maxonsubchannel[] = "Maximum Forwarding Sessions on Subchannel %d";
static const char forwardSMTP[] = "Forward to PBBS w/SMTP headers";
static const char uknosBID[] = "Use UKNOS-compatible PBBS bids (xxx_call@hamradio)";
#endif /* CATALOG */

static const char strCR[] = "%s\n";
static const char sessstr[] = "     %-9s - %sForwarding\n";
static const char reversestr[] = "Reverse ";


static struct cmds FWDcmds[] = {
	{ "active",	doactive,	0,	0,	NULLCHAR },
#ifdef ALTERBID
	{ "alteredbids",dombalterbid,	0,	0,	NULLCHAR },
	{ "alteredhold",dombalterhold,	0,	0,	NULLCHAR },
#endif
#if defined(XFWD) || defined(FBBFWD)
	{ "areatrace",	doareatrace,	0,	0,	NULLCHAR },
#endif
	{ "bid",	dofwdbid,	0, 	0,	NULLCHAR },
	{ "bidsuffix",	dobidsuffix,	0, 	0,	NULLCHAR },
	{ "biduknos",	dobiduknos,	0, 	0,	NULLCHAR },
	{ "bulletins",	dobulletins,	0,	0,	NULLCHAR },
	{ "ctlz",	doctlz,		0,	0,	NULLCHAR },
#ifdef FBBFWD
#ifdef FBBCMP
	{ "fbb-compression",dofbbcmpstyle,0,	0,	NULLCHAR },
#endif
	{ "fbb-style",	dofbbstyle,	0,	0,	NULLCHAR },
	{ "fbbtrace",	dofbbtrace,	0,	0,	NULLCHAR },
#endif
	{ "fwdinfo", 	dombfwdinfo,	0,	0,	NULLCHAR },
	{ "haddress",	dombhaddress,	0,	0,	NULLCHAR },
	{ "inreverse",	doinreverse,	0,	0,	NULLCHAR },
	{ "kick",	dombkick,	0, 	0,	NULLCHAR },
	{ "kickone",	dombkickone,	2048, 	2,	"forward kickone <bbs> [poll | export]" },
	{ "laston",	dolaston,	0,	0,	NULLCHAR },
	{ "limittime",	dolimittime,	0,	0,	NULLCHAR },
	{ "mid",	dombmid,	0,	0,	NULLCHAR },
	{ "minidle",	dominidle,	0,	0,	NULLCHAR },
	{ "mode",	dofwdmode,		0,	0,	NULLCHAR },
	{ "mycall",	domycall,	0,	0,	NULLCHAR },
	{ "personal",	dopersonal,	0,	0,	NULLCHAR },
	{ "pmulti", dofwdpmulti,    0,  0,  NULLCHAR },
	{ "qth",	dombqth,	0,	0,	NULLCHAR },
	{ "queue",	dofwdqueue,	0,	3,	"forward queue <bbs> <area | all>"},
	{ "rcall",	dombrcall,	0,	0,	NULLCHAR },
	{ "reload",	dofwdreload,	0,	0,	NULLCHAR },
	{ "reset",	forwardreset,	0,	0,	NULLCHAR },
	{ "reverse",	doreverse,	0,	0,	NULLCHAR },
	{ "rsample",	dombrsample,	0,	0,	NULLCHAR },
	{ "rstyle",	dombrstyle,	0,	0,	NULLCHAR },
	{ "summary",	dosummary,	0,	0,	NULLCHAR },
	{ "smtptoo",	dombsmtptoo,	0,	0,	NULLCHAR },
	{ "status",	dofwdstatus,	0,	0,	NULLCHAR },
	{ "subchannel",	dombsubchannel,	0,	0,	NULLCHAR },
	{ "sysopprotect",dombsysopprotect,0,	0,	NULLCHAR },
	{ "tapr",	dombtapr,	0,	0,	NULLCHAR },
	{ "timer",	dombtimer,	0,	0,	NULLCHAR },
#ifdef UKIP
	{ "tlines", dofwdtlines,0,  0,  NULLCHAR },
#endif
	{ "trace",	dombtrace,	0,	0,	NULLCHAR },
	{ "utc",	dombutc,	0,	0,	NULLCHAR },
#ifdef UKIP
	{ "x-bid",  dofwdxbid,  0,  0,  NULLCHAR },
#endif
#ifdef XFWD
	{ "x-style",	doxstyle,	0,	0,	NULLCHAR },
	{ "xtrace",	doxtrace,	0,	0,	NULLCHAR },
#endif
	{ "zipcode",	dombzipcode,	0,	0,	NULLCHAR },
	{ NULLCHAR,	NULL,		0,	0,	NULLCHAR }
};




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


int
dombkickone(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int poll = 0;

	if (argc > 2)	{
		if (tolower(argv[2][0]) == 'p')
			poll = 1;
		else if (tolower(argv[2][0]) == 'e')
			poll = 2;
	}
	checkforALTs ();
	(void) forwardreset(0, NULLCHARP, 0);
	fwdproc (poll, argv[1], (void *)0);
	return 0;
}


static int
dofwdmode(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setint(&FWDmode, enabled, argc, argv);
}


static int
dominidle(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setint(&FWDminidle, "Default Minimum idle time (in secs) between fwding to same station", argc, argv);
}


static int
dolimittime(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setint(&FWDlimittime, "Default Maximum time (in minutes) for a fwding session", argc, argv);
}


static int
dofwdreload(argc,argv,p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
	Numfwds = 0;		/* force a full reload */
	ReadFwdBbs ();
	tprintf ("The list of BBSs in the forward.bbs file has been reloaded\n");
	return 0;
}


static int
dombtapr(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int retval;

	retval = setbool(&TAPRspec, tapr1, argc, argv);
	if (!TAPRspec)
		tputs (tapr2);
	return (retval);
}


static int
dombsysopprotect(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&SYSOPprotect, "Protect 'SYSOP' area from forward deletion", argc, argv);
}


static int
dopersonal(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDpersonal, personal, argc, argv);
}


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


#ifdef ALTERBID
static int
dombalterbid(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&chkBidAltered,"Check for altered BIDS",argc,argv);
}



static int
dombalterhold(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&holdBidAltered,"Hold altered BID messages (rather than delete them)",argc,argv);
}
#endif


#ifdef XFWD
static int
doxstyle(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return (setbool(&MXfwd, "X-style forwarding", argc, argv));
}

static int
doxtrace(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool (&Xtrace, "X-Forwarding trace flag", argc, argv);
}

#endif

#ifdef UKIP
static int
dofwdxbid(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return (setbool(&FWDxbid, "Translate X-BID when forwarding", argc, argv));
}
#endif

#if defined(XFWD) || defined(FBBFWD)
static int
doareatrace(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool (&FWDareatrace, "Display area scan in traces flag", argc, argv);
}
#endif



#ifdef FBBFWD
static int
dofbbstyle(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
register int rc;

	rc = setbool(&Mfbb, FBBstyle, argc, argv);
#ifdef FBBCMP
	if((!rc) && (!Mfbb))	/* Successful */
		Mfbbcmp = FALSE;
#endif
	return rc;
}

#ifdef FBBCMP
static int
dofbbcmpstyle(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
register int rc;

	rc = setbool(&Mfbbcmp, FBBcompressed, argc, argv);
	if((!rc) && (Mfbbcmp))	/* Successful */
		Mfbb = TRUE;
	return rc;
}
#endif	/* FBBCMP */
#endif	/* FBBFWD */


static int
doctlz(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDctlz, usectlz, argc, argv);
}

static int
doreverse(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDreverse, reverseout, argc, argv);
}

static int
doinreverse(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDinreverse, reversein, argc, argv);
}

/* Display or change our AX.25 address for forwarding */
static int
domycall(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
char tmp[AXBUF];

	if(argc < 2){
		tprintf(strCR,pax25(tmp,FWDCall));
		return 0;
	}
	if(setcall(FWDCall,argv[1]) == -1)	{
		if (!*argv[1])
			*FWDCall = 0;
		return -1;
	}
	return 0;
}

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

static int
dofwdstatus(argc,argv,p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
	(void) dofwdmode (0, 0, 0);
	(void) dombsysopprotect (0, 0, 0);
	(void) dobulletins (0, 0, 0);
	(void) dopersonal (0, 0, 0);
	(void) doreverse (0, 0, 0);
	(void) doinreverse (0, 0, 0);
	(void) dombtrace (0, 0, 0);
#if defined(XFWD) || defined(FBBFWD)
	(void) doareatrace (0, 0, 0);
#endif
#ifdef FBBFWD
	(void) dofbbtrace (0, 0, 0);
	(void) dofbbstyle(0, 0, 0);
#endif
#ifdef FBBCMP
	(void) dofbbcmpstyle(0, 0, 0);
#endif
#ifdef XFWD
	(void) doxtrace (0, 0, 0);
	(void) doxstyle(0, 0, 0);
#endif
	(void) doactive (0, 0, 0);
	return (0);
}


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

	/* 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)	{
				tputs (activesessions);
				first = 1;
			}
			tprintf (sessstr, Mbox[i]->name, (Mbox[i]->state == MBX_REVFWD) ? reversestr : "");
		}
	}
	return (0);
}


static int
dolaston(argc,argv,p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
int i;

	/* give last forwarding time */
	tputs (LASTCompleted);
	for (i = 0; i < Numfwds; i++)	{
		tprintf ("\t%-9s - ", MyFwds[i].name);
		if (MyFwds[i].laston)
			tputs (ptime(&MyFwds[i].laston));
		else
			tputs ("(none)\n");
	}
	return (0);
}


static int
dofwdbid(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&MbBID, originalBID, argc, argv);
}



static int
dobiduknos(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&BIDuknos, uknosBID, argc, argv);
}



static int
dobidsuffix(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	(void) dostr (argc,argv,"forward","bidsuffix",&BIDsuffix);
	if (BIDsuffix)	{
		rip(BIDsuffix);
		(void) strupr(BIDsuffix);
	}
	return 0;
}


/*Set the difference between Local time, and UTC !*/
static int
dombutc(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    if(argc < 2) {
        tputs(localUTC);
        if(UtcOffset == 0)
            tputc('\n');
        else {
            if(UtcOffset > 0)
                tputc('+');
            tprintf("%d\n",UtcOffset);
        }
        return 0;
    }
    UtcOffset = atoi(argv[1]);
    return 0;
}


static int
dombmid(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&MbMID, localMID, argc, argv);
}



static int
dombrsample(argc,argv,p)
int argc OPTIONAL;
char *argv[] OPTIONAL;
void *p OPTIONAL;
{
time_t t;
char *cp, buf[40], thetime[100];

	(void) time(&t);
	if (mbxRCall)
		strncpy (buf, mbxRCall, 40);
	else
		(void) pax25(buf,Mycall);
	if((cp = strpbrk(buf, DIGI_IDS)) != NULLCHAR)
		*cp = '\0'; /* remove SSID */
	strncpy (thetime, ptime(&t), 100);
	if (!MbRSTYLE)	{
		tprintf("R:%s @:%s%s%s ", mbxtime(thetime), buf, (Mbhaddress) ? "." : "",
			(Mbhaddress) ? Mbhaddress : "");
		if (Mbfwdinfo)
			tprintf("[%s] ", Mbfwdinfo);
		if (Mbqth)
			tprintf("%s ", Mbqth);
		if (MbMID)
			tputs("#:7388 ");
		if (Mbzip)
			tprintf("Z:%s ", Mbzip);
		if (MbBID)	{
			strncpy (buf, (BIDsuffix) ? BIDsuffix : Hostname, 40);
			(void) strupr (buf);
			if((cp = strchr(buf,'.')) != NULLCHAR)
				*cp = '\0';
			tprintf("$:7388_%s", buf);
		}
	} else
		tprintf("R:%s 7388@%s%s%s", mbxtime(thetime), buf, (Mbhaddress) ? "." : "",
			(Mbhaddress) ? Mbhaddress : "");
	tputc('\n');
	return 0;
}


static int
dombrstyle(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&MbRSTYLE, W0RLIstyle, argc, argv);
}


/* Set the QTH to be used in R: line when forwarding*/
static int
dombqth(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	if (argc > 2) {
		tputs (qthusage);
		return 0;
	}

	if (argc < 2) {
		if (Mbqth != NULLCHAR)
			tprintf (strCR, Mbqth);
	} else {
		if(Mbqth != NULLCHAR)	{
			free (Mbqth);
			Mbqth = NULLCHAR;   /* reset the pointer */
		}
		if(!strlen (argv[1]))
			return 0;		/* clearing the buffer */
		Mbqth = strdup (argv[1]);
	}
	return 0;
}


/*Set the ZIP to be used in the R: line when forwarding */
static int
dombzipcode(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int len;

	if (argc > 2) {
		tputs (usagezipcode);
		return 0;
	}

	if (argc < 2) {
		if (Mbzip != NULLCHAR)
			tprintf (strCR, Mbzip);
	} else {
		len = (int) strlen (argv[1]);
	        if (Mbzip != NULLCHAR)	{
			free (Mbzip);
			Mbzip = NULLCHAR;   /* reset the pointer */
		}
		if (!len)
			return 0;		/* clearing the buffer */
		Mbzip = strdup (argv[1]);
	}
	return 0;
}

/*Set the R: line [info] to be used when forwarding*/
static int
dombfwdinfo(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	if (argc > 2) {
		tputs (usagefwdinfo);
		return 0;
	}

	if (argc < 2) {
		if (Mbfwdinfo != NULLCHAR)
			tprintf (strCR, Mbfwdinfo);
	} else {
		if (Mbfwdinfo != NULLCHAR)	{
			free (Mbfwdinfo);
			Mbfwdinfo = NULLCHAR;   /* reset the pointer */
		}
		if(!strlen (argv[1]))
			return 0;		/* clearing the buffer */
		Mbfwdinfo = strdup (argv[1]);
	}
	return 0;
}


/*Set the hierachical address to be used in R: line when forwarding*/
static int
dombhaddress(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int k;
char *cp;

	if (argc > 2) {
		tputs (usagehaddr);
		return 0;
	}

	if (argc < 2) {
		if(Mbhaddress != NULLCHAR)
			tprintf (strCR, Mbhaddress);
	} else {
		/*make sure they're lower case*/
		(void) strlwr (argv[1]);
		/* check for a proper, 4 character continent */
		for (k = 0; k < numcontinents; k++)	{
			if (((cp = strstr(argv[1], continents[k])) != NULLCHAR) && (*(cp-1) == '.') && (*(cp-5) == '.') && !cp[4])
				break;
		}
		if (k == numcontinents)	{
			if (TAPRspec)	{
				tputs (tapr3);
				return 0;
			} else
				tputs (tapr4);
		}

		if (Mbhaddress != NULLCHAR)	{
			free (Mbhaddress);
			Mbhaddress = NULLCHAR;   /* reset the pointer */
		}
		if (!strlen (argv[1]))
			return 0;		/* clearing the buffer */
		Mbhaddress = strdup (argv[1]);
		/*make sure they're upper case*/
		(void) strupr (Mbhaddress);
	}
	return 0;
}


static int
dombtrace(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool (&Mtrace, fwdtraceflag, argc, argv);
}


#ifdef FBBFWD
static int
dofbbtrace(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool (&FBBtrace, FBBtraceflag, argc, argv);
}
#endif


static int
dombsubchannel(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
int netnum, didheader = 0;
char buf[60], *cp;

	if (argc == 1)	{
		tprintf ("Total available subchannels: %-d (0-%-d)\n", NUMMBX, NUMMBX - 1);
		for (netnum = 0; netnum < NUMMBX; netnum++)	{
			if (subchannels[netnum].limit || subchannels[netnum].used || subchannels[netnum].description)	{
				if (!didheader)	{
					didheader = 1;
					tputs ("Subchannels defined or in use:\n");
				}
				tprintf (subchanneldata, netnum, subchannels[netnum].limit, subchannels[netnum].used);
				if (subchannels[netnum].description)
					tprintf ("  (%s)", subchannels[netnum].description);
				tputs ("\n");
			}
		}
		if (!didheader)
			tputs ("No subchannels defined or in use...\n");
		return 0;
	}
	if (argv[1][0] == '?')	{
		tputs (usagesubchannel);
		return 0;
	}
	netnum = atoi (argv[1]);
	if (netnum > NUMMBX)	{
		tprintf (validsubchannels, NUMMBX - 1);
		return 0;
	}
	if (argc > 3)	{
		if (subchannels[netnum].description)	{
			free (subchannels[netnum].description);
			subchannels[netnum].description = NULLCHAR;
		}
		if (*argv[3])
			subchannels[netnum].description = strdup (argv[3]);
	}
	sprintf (buf, maxonsubchannel, netnum);
	cp = argv[1];
	argv[1] = argv[2];
	argv[2] = cp;
	return setint(&subchannels[netnum].limit,buf,argc - 1,argv);
}


static int
dombsmtptoo(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
    return setbool(&Mbsmtptoo, forwardSMTP, argc, argv);
}


static int
dombrcall(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	(void) dostr (argc,argv,"forward","rcall",&mbxRCall);
	if (mbxRCall)	{
		rip(mbxRCall);
		(void) strupr(mbxRCall);
	}
	return 0;
}


static void
fwdqueuearea (bbs, area)
char *bbs, *area;
{
struct mbx *m;
struct let *cmsg;
int i, messages = 0;
long size = 0L;

	m = (struct mbx *)callocw(1,sizeof(struct mbx));
	strncpy (m->name, bbs, 20);
	changearea(m,area, 0);
	for (cmsg = &m->mbox[1],i = 1; i <= m->nmsgs; i++, cmsg++)
		if (!(cmsg->status & BM_DELETE))	{
			updateFwd (bbs, area, cmsg->bid, cmsg->size);
			size += cmsg->size;
			messages++;
		}
	(void) closenotes (m, 1);
	free (m);
	if (size)	{
		size += 1023;
		size /= 1024;
	}
	tprintf ("Added to forwarding queue for %s: Area '%s' - %d messages (%ldK)\n",
		bbs, area, messages, size);
}


static int
dofwdqueue(argc,argv,p)
int argc OPTIONAL;
char *argv[];
void *p OPTIONAL;
{
struct fwdbbs *f;
int all;
struct arealist *a;

	f = fwdread (argv[1], Numfwds);	/* first get BBS entry */
	if (f == NULLFWDBBS)	{
		tprintf ("Invalid BBS: %s\n", argv[1]);
		return 0;
	}
	all = !stricmp (argv[2], "all");

	for (a = f->areas; a; a = a->next)	{
		if (all || !stricmp (argv[2], a->name))
			fwdqueuearea (f->name, a->name);
	}

	fwdfree (&f);
	return 0;
}

static int
dofwdpmulti(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDpmulti, "Forward personal messages to more than one BBS", argc, argv);
}


#ifdef UKIP
static int
dofwdtlines(argc,argv,p)
int argc;
char *argv[];
void *p OPTIONAL;
{
	return setbool(&FWDtlines, "Add T: Lines when forwarding", argc, argv);
}
#endif

#endif /* MBFWD */
