/*
 *  MB.C - 6/14/    87 - MailBox mainline code.
 */

/*
 *  Copyright (C) 1987
 *  H. N. Oredson
 *  134 Ponderosa Drive
 *  Santa Cruz, ca 95060
 *
 *  This code was created and distributed
 *  to the packet radio community by W0RLI and VE3GYQ.
 *  It may be freely copied for non-commercial use,
 *  as long is this notice is retained.
 *
 *  This notice and Copyright apply to all modules
 *  referenced by this module.
 */

#include "mb.h"
#include "mbexp.h"
#if	(XENIX|UNIX|BSD)
#include <sys/termio.h>
#endif

extern int sprompt, rfwd, rfwdok, dohfwd;	/* AY-871007 */
char *ready_bbs;				/* AY-881005 */
word do_announce;				/* AY-881005 */

#if !DOMAIN_NO	/* AY-880903 */
extern int domainok, extfwdok;
#endif

#if (XENIX|UNIX|BSD)    /* CHANGED SMC */
char *ver = "\nW0RLI V3.3 19 June 1987. [R45.32 Expanded by JA3JWI(881215)]\n";
#else
char *ver = "\nW0RLI V3.3 [R46.06 Expanded by JA3JWI and JH1RSV Jul.23,1991]\n";
#endif
char *nullstr = "" ;  /* NOV11,89 */

PORTS *porthd, *port, *cport;
int  scrmax, dirmax;
TMP  *tmp;
char *helpfile, *infofile;
char *bbmenu, *symenu, *rmenus, *lmenus, *mumsg;
char *motd, *reqmsg, *qth;
char *mcant, *mdone, *mfind, *mexst, *mnfile, *mnmsg;
char *mprot, *mtime, *mwhat, *mnport, *mndir, *minuse;
char achar, rchar, tchar, wchar;
word s_param;
char scmd[linelen];	/* AY-881105 */

main(argc, argv)
int argc;
char *argv[];
{
	register short waiting;
	register char *i, *o;
	register PORTS *p;

	if (argc > 1)
		init(argv[1]);
	else
#if (XENIX|UNIX|BSD)               /* CHANGED SMC */
        init("config.mb");
#else
        init("config.mbx");        /* CHANGED SMC */
#endif
	if (RECSIZE != sizeof(MSG_HDR) ||
	   (RECSIZE != sizeof(MSG_BID)) ||
	   (RECSIZE != sizeof(MSG_EXT)) ||
	   (RECSIZE != sizeof(MAIL_HDR)) ||
	   (RECSIZE != sizeof(USER_HDR)) ||
	   (RECSIZE != sizeof(USER))) {
                fprintf(stderr, "    Data Size incompatible.\n" );
                fprintf(stderr, "    Please Recopile it.\n");
		exit(-1);
	}
		
	initenv();    /* AY-2 */
	setupbid();   /* AY-20 */

	while (true)
	{
		while (port->mode & (idle | exclude | logout | gone))
		{
#if !DOMAIN_NO	/* AY-880903 */
			domainok = extfwdok =
#endif
			sprompt = rfwd = rfwdok = dohfwd = false;
			waitcon();
		}

		p = port;


		prompt();
		settmr(&port->expire, port->ctime);
		waiting = true;
		while(waiting) {
			if (!(port->mode & local))
				switch(otalk()) {
				case 1: 
					settmr(&port->expire, port->ctime); 
					prompt(); 
					break;
				case 2: 
					waiting = false; 
					break;
				default: 
					break;
				}

			if (waiting) {
#if	(XENIX|UNIX|BSD)	/* AY-880502 */
				if (port->dev is p_console)
					waiting = !getdat(); 
				else if (instat())
					waiting = !getdat(); 
#else
				if (instat())
					waiting = !getdat(); 
#endif
				else if (!chktmr(port->expire)) {
					waiting = false; 
					port->mode = timeout;
					port->flds = 1;
				}
			}
		} /* End of AY-50 */

/*
**  Console broke in on a user.
*/

		if (port->flags & p_opreq) {
			port->flags clrbit p_opreq;
			prtx(talkm1);
			cmdtnc();	/* TNC to Command mode first */
			save_tnc_mode();/* Set the TNC to Terminal mode */
			convtnc();	/* Resume the TNC to convers mode */
			ioport(cport);
			prtx(mumsg);
                        term(cport, p, false); /* Nov.11,89 */
			ioport(p);
			tncstate();
			resume_tnc();	/* Resume the TNC Parameter's */
			convtnc();
		} else if (!(port->mode & gone)) {
			if (!islink(port->line)) {
				docmd();
				if (port->errors > port->errmax) port->mode = forced;
			} else {
/*
**  Require "LINKED to" to be first command.
*/
				if (port->cmdcnt)
					port->msg = mwhat; 
				else {
					for (i = port->line + 14, o = port->line; *i; )
						*o++ = *i++;
					logina(true);
					remnl(port->line);
					log('C', 'L', ' ', port->line);
				}
			}
		}
	}
}

/*
**  Q command: exit to OS.
*/

done()
{
        outstr ("Are you sure (Y/N)?\n");     /* May5,90 add check */
        while (!getdat()) ;
        if (( port->line[0] != 'Y') and ( port->line[0] != 'y')) return ;

	upduser(cport->user);
        log('X', 'Q', ' ', nullstr); /* Nov11,89 */
	clslog();
	clsusr();
	clsmsg();
	clsmon();
	iooff();
#if !SEM_NO	/* AY-881005 */
	rm_sem();
#endif
	exit(0);
}

/*
**  Give the user a prompt.
*/

prompt()
{
	register PORTS *p, *tp;

	p = port;
	if (p->msg isnt NULL) prtx(p->msg);
	p->msg = NULL;

#if (XENIX|UNIX|BSD)	/* AY-880914 */
	flushport(2);
#endif

/*
**  Tell sysop who this is.
*/

	if (p isnt cport) { 
		ioport(cport); 
		prtx(mumsg); 
		ioport(p); 
	}

	if (p->flags & p_req) prtx(reqmsg);
	p->flags clrbit p_req;

/*
**  Bleed off any connect requests on other ports.
*/

	for (tp = porthd; tp isnt NULL; tp = tp->next)
		if (tp->mode & idle)
		if ((tp->dev is p_tnc) and (tp isnt p)) {
			ioport(tp);
			while (instat()) getdat();
		}
	ioport(p);

/*
**  Now actually do the prompt.
*/

	curtim();
	switch (p->mode) {
	case local : 
		prtx(lmenus); 
		break;
	case sysop : 
		prtx(symenu); 
		break;
	case remote:
		if (!(p->user->options & u_bbs)) {
			if (!(p->user->state & u_name)) prtx(um[14]);
			if (!(p->user->state & u_home)) prtx(um[15]);
		}
		if (sprompt) {
			outstr(">\n");
		} else {
			if (p->user->options & (u_bbs | u_expert))
				prtx(bbmenu);
			else
				prtx(rmenus);
		}
		break;
	}
}

/*
**  Set up the beacon line.
*/

#if ANNOUNCE_NO
setfwd()
{
	register char *cp, *lp;
	register short i;

	if (s_param & s_mchange)
	{
		bldfwd();
		strcpy(port->line, "BT Mail for:");
		cp = ufwd; 
		lp = port->line + strlen(port->line);
		while ((cp < ufwd + ln_call * ufwdn) and (lp < port->line + 112))
		{
			*lp++ = ' ';
			for (i = 0; i < ln_call; i++, cp++) if (*cp isnt ' ') *lp++ = *cp;
		}
		*lp++ = '\n';
		*lp++ = '\r';      /* AY-871120 */
		*lp = '\0';
		alltnc(port->line);
	}
}
#else
/*
**	Message Service.	AY-880923
*/

setfwd() { }
setfwd2(buf)
char *buf;
{
register char *cp, *lp;
register short i;
char tmpcall[ln_call];

	if (s_param & s_mchange) bldfwd();	/* AY-881124 */
	strcpy(buf, "Mail for:");
	cp = ufwd; 
	lp = buf + strlen(buf);
	while ((cp < ufwd + ln_call * ufwdn) and (lp < buf + 112)) {
		*lp++ = ' ';
		for (i = 0; i < ln_call; i++, cp++)
			if (*cp isnt ' ') *lp++ = *cp;
	}
	*lp++ = '\n';
	*lp++ = '\r';
	*lp = '\0';
}

announce()
{

static char buf[linelen * 2];
	setfwd2(buf);
	if (strlen(buf) <= 11) buf[0] = '\0';  /* Only "Mail for:\n\r" */
	if (do_announce) beacon(buf);
}

/* Transmit Beacon line AY-881124 */
#endif

/*
**  Log the user off.
*/

logo()
{
	register char t;

	switch(port->mode)
	{
	case idle	: 
		t = 'A'; 
		break; /* Init bbs logout */
	case logout : 
		t = 'B'; 
		break;
	case discon : 
		t = 'D'; 
		break;
	case exclude: 
		t = 'E'; 
		break;
	case forced : 
		t = 'F'; 
		break;
	case timeout: 
		t = 'T'; 
		prtx(mtime); 
		break;
	default	: 
		t = '?'; 
		break;
	}

        log('X', t, ' ', nullstr);  /* Nov11,89 */


/*
**  Change TNC back to "standard" if was in "sysop" mode.
**  May have just THOUGHT we discon, REALLY disconnect.
*/

	if (!(port->dev is p_console))
	{
		if (port->flags & p_clrsys) mkrem();
		port->mode = remote;
		distnc();
		port->mode = idle;
	}

	upduser(port->user);

	clnlog();
	clnuser();

/*
** If Shared mail.dat, I wish to clean the mail.dat evry D/C. AY-881123
*/
#if SHARE
	clnmsg();
	if (s_param & s_mchange) setfwd();
#else
	if (s_param & s_mchange)
	{
		clnmsg();
		setfwd();
	}
#endif

/*
**  If there was a "defered remote sysop command" do it.
*/

	ioport(cport);
	if (s_param & s_cmd)
	{
		strcpy(cport->line, scmd);
#if	(XENIX|UNIX|BSD)
		mbsleep(10);
#else
		wait(10);
#endif
		cport->mode = local;
		docmd();
		cport->mode = idle;
		s_param clrbit s_cmd;
	}

/*
**	Now MB ready to use, so announce it.
*/
	announce();

	allon(); /* Turn on monitoring & connects */
}

#if SHARE	/* AY-881123 */
open_files()
{
register int count;
extern int errno;

DBGMSG((stderr, "Enterring open_files()\n\r"));
	count = 0;
	while ((ufl = open(usfile, O_RDWR | O_BINARY)) < 0) {
		nofile(usfile);
		count++;
		sleep(5);
		if (count < 11) continue;
		/* Die if can't open until 60 Sec */
		syserr("can't open user.dat\n\r", errno);
	}
	count = 0;
	while ((mfl = open(mbfile, O_RDWR | O_BINARY)) < 0) {
		nofile(mbfile);
		count++;
		sleep(5);
		if (count < 11) continue;
		/* Die if can't open until 60 Sec */
		syserr("can't open mail.dat\n\r", errno);
	}
	setmfhs();
}

close_files()
{
DBGMSG((stderr, "Enterring close_files()\n\r"));
	clsmsg();	/* Close mail.dat */
	clsusr();	/* Close user.dat */
}
#endif

/*
**  User has said bye, timed out, or been forced off; MailBox going idle.
**  See if there is anything to do, and do it.
**  If nothing to do, wait for connect.
*/

waitcon()
{
extern word latest;	/* AY-881006 */
register int i;		/* AY-881127 */
register PORTS *p;
register short anyfwd, curmin;
register short lastmin;	/* AY-881109 */

/*
**  Log present user out.
*/
	logo();

#if SHARE
/*
**  If Sharering The mail.dat/user.dat, Close Them. AY-881123
*/
	close_files();
#endif

/*
**  Loop, looking for something to do.
*/
	while(true) {
		lastmin = curmin;	/* AY-881109 */
		curtim();
		curmin = 10 * (l_time[2] - '0') + (l_time[3] - '0');

#if SHARE /* AY-881123 */
/*
**  Write out the monitor file once each hour.
*/
		if (lastmin and !curmin) {
			alloff();
			clsmon();
			open_files();	/* Open mail.dat & user.dat */
			dwuser();
			close_files();	/* Close mail.dat & user.dat */
			allon();
		}
#else
		if (lastmin and !curmin) {
			alloff();
			clsmon();
			dwuser();
			allon();
		}
#endif
		if (lastmin isnt curmin) {
/*
**  Mark the ports that should forward at this minute.
*/
			anyfwd = false;
			for (p = porthd; p isnt NULL; p = p->next) {
				if (p->fwdmin isnt curmin) {
					p->flags setbit p_fwdok; 
				} else {
					if (p->flags & p_fwdok) { 
						p->flags setbit p_dofwd; 
						anyfwd = true; 
					}
				}
			}
/*
**  If any ports forward at this minute, do the forwarding.
*/
			i = anyfwd;
#if SHARE /* AY-881123 */
			if (anyfwd) {
				alloff();
				cport->flds = 0; /* Flag this as automatic */
				open_files();	/* Open mail.dat & user.dat */
				fwd();
				close_files();	/* Close mail.dat & user.dat */
				if (s_param & s_mchange) { 
					clnlog(); 
					clnmsg(); 
					setfwd(); 
				}
				allon();
			}
#else
			if (anyfwd) {
				alloff();
				cport->flds = 0; /* Flag this as automatic */
				fwd();
				if (s_param & s_mchange) { 
					clnlog(); 
					clnmsg(); 
					setfwd(); 
				}
				allon();
			}
#endif
			if (i) if (do_announce) announce();

/*
**	Put TNC into the command mode.
**	If the TNC is Idle, I want to it corectory command mode.
**	0 and 5 Min each We send a pare of ctrl_c & CR, only one time.
**	We will be able to free from UI "con o mo o" etc etc. AY-880621
*/
			switch (l_time[3]) {
			case '0':
/*                        case '5':                Feb11,90 */
				alltnc("\3\n");
				allcmd(t_con);
				break;
			default:
				break;
			}
		}

/*
**  Look for a login.
*/

		for (p = porthd; p isnt NULL; p = p->next) {
			ioport(p);
			if (instat()) {
				switch(p->dev) {
				case p_hayes:
				case p_serial:
				case p_memory:	
					getdat();
					if (iscon(p->line)) { 
						login(); 
						return; 
					}
					break;
				case p_tnc:
					p->flags clrbit p_give;
					getdat();
					p->flags setbit p_give;
					if (iscon(p->line)) { 
						login(); 
						return; 
					}
#if !MON_NO	/* AY-880922 */
					else
						monitor();
#endif
					break;
				case p_console:
					if (inchar() is wchar) { 
						login(); 
						return; 
					}
					break;
				}
			}
		}
		latest = port->user->msg_number;	/* AY-881006 */
	}
}
/*
 *  IS Command    Print information
*/
printseting()
{
register int i;
#if !DOMAIN_NO
char buf[40], *strchr();
#endif

	i = 1;
	sprintf(tmp->scr, "%2d. SID is:%s", i++, rliversion);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Let host to MBL mode by: %s", i++, mblmode);
	outstr(tmp->scr);
        sprintf(tmp->scr, "%2d. BBS only is:%s", i++, bbsonly_msg);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Too many digi's is:%s", i++, tomanydigi_msg);
	outstr(tmp->scr);
        sprintf(tmp->scr, "%2d. System can't do it is:%s", i++, mcant); /* May2,91*/
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Aborted by user is:%s", i++, abortby_usr);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Listing Kanji titled message:%s\n", i++,
				    (check_kanji_title & 1) ? "Yes" : "No");
	outstr(tmp->scr);
#if 0   /* May 2,91*/
        sprintf(tmp->scr, "%2d. Announce BBS ready to connect:%s\n",
                    i++, ready_bbs);                        /* ADD "\n" SMC */
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Do annouce with above msg: %s\n",
					i++, (do_announce & 1) ? "Yes" : "No");
	outstr(tmp->scr);
#endif
        sprintf(tmp->scr, "%2d. Annouce \"Mail for ...\" when D/C: %s\n",
					i++, (do_announce & 2) ? "Yes" : "No");
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Annouce \"Mail for ...\" each hour: %s\n",
					i++, (do_announce & 4) ? "Yes" : "No");
	outstr(tmp->scr);
#if	(XENIX|UNIX|BSD)
	sprintf(tmp->scr, "%2d. Interface file MB & Xenix is %s\n",
					i++, mailingfile);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Mailer program name with opt:%s\n",
					i++, mailer);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. To: Feeld check file name:%s\n", i++, to_file);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. At: Feeld check file name:%s\n", i++, at_file);
	outstr(tmp->scr);
	sprintf(tmp->scr, "%2d. Kill forwarded to xenix mailer:%s\n",
	    				i++, (kill_after_m & 1) ? "Yes" : "No");
	outstr(tmp->scr);
#endif
}
