/*
 *  MB.C - 2/17/89 - MailBox mainline code.
 */

/*
 *  Copyright (C) 1987, 1988
 *  On Modules by H. N. Oredson
 *  Copyright (C) 1988, 1989
 *  By the CBBS Group.
 *
 *  This code was originality created and distributed
 *  to the packet radio community by W0RLI and VE3GYQ.
 *  It is being further being developed by the CBBS Group.
 *  It may be freely copied for non-commercial use,
 *  as long as this notice is retained.
 *
 *  This notice and Copyright apply to all modules
 *  referenced by this module.
 *
 */

#include "mb.h"

char  *ver = "\nC-BBS V6.1, 17 Feb 1989\n";

char  *nullstr = "";

PORTS *porthd = NULL;
PORTS *cport  = NULL;
PORTS *port;

int   scrmax, dirmax;
TMP   *tmp;
MLM   *motd;
char  *helpfile, *infofile;
char  *bbmenu, *symenu, *rmenus, *mumsg;
char  *reqmsg, *qth, *keylst;
char  *mcant, *mdone, *mfind, *mexst, *mnfile, *mnmsg;
char  *mprot, *mtime, *mwhat, *mnport, *mndir, *minuse;
char  achar, rchar, tchar, wchar;
word  s_param;
byte  s_flag, unt_hr, window, c_flag, b_flag;
char  scmd[24];

#ifdef MCH_AMIGA
extern short debug;
extern short BaudRate;
extern short tapr_flag;
#endif

main(argc, argv)
int argc;
char *argv[];
{
#ifdef MCH_AMIGA
   if(argc > 1) {
      while(argv[1][0] == '-') {
         switch(argv[1][1]) {
         case 'b':
            BaudRate = atoi(&argv[1][2]);
            break;
         case 't':
            /* tell serial read routine to strip high bit off all bytes
               read from the TNC because it is a TAPR upgrade kit that
               generates NO parity only with the parity bit forced to one
            */
            tapr_flag++;
            break;
         }
         argc--;
         argv++;
      }
   }
   if(openterm()) {
      printf("error opening terminal\n");
      exit();
   }
   if(argc > 2)debug = 1;
   if(initser()) {
      printf("error opening serial port\n");
      closeterm();
      exit();
   }

   if(inittimer()) {
      printf("error opening timer\n");
      cleanser();
      closeterm();
      exit();
   }
#endif
  if (argc > 1) init(argv[1]); else init("config.mb");

  while (true)
  {
    bidok = false;
    hidok = false;
#ifdef MCH_AMIGA
      titles();
#endif
    do_idle();
    setbusy();
    login();
#ifndef MCH_AMIGA
    if (!(port->mode & exclude)) do_cmds();
    logo();
#else
/*FIX 8  ignore idle terminal caused by monitoring data that looks like a
         "*** CONNected" message.
*/
    if(!(port->mode & idle)) {
       if(!(port->mode & exclude)) do_cmds();
       logo();
    }
#endif
  }
}

do_cmds()
{
  register PORTS *p;
  register char  *i, *o;

  p = port;

  while(true)
  {
    prompt();
    getcmd();
    if (p->mode & gone) return;

/*
 *  Console broke in on a user?
 */

    if (p->flags & p_opreq)
    {
      p->flags clrbit p_opreq;
      prtx(talkm1);
      if (p->tmode)
      {
         cmdtnc();
         convtnc();
      }
      ioport(cport);
      prtx(mumsg);
      cport->fl = NULL;
      term(p);
      ioport(p);
      tncstate();
      if (p->tmode) trantnc(); else convtnc();
      if (p->mode & gone) return;
    }

/*
 *  Check for LINK.
 *  Require "LINKED to" to be first command.
 */

    else if (islink(p->line))
    {
      if (p->cmdcnt) p->msg = mwhat; else
      {
        strcpy(p->line, p->line + 14);
        logina(true);
        remnl(p->line);
        log('C', 'L', ' ', p->line);
        if (p->mode & exclude) return;
      }
    }

/*
 *  Must be a command.
 */

    else
    {
      docmd();
      if (p->errors > p->errmax) p->mode = forced;
      if (p->mode & (gone | idle | logout)) return;
    }
  }
}

/*
 *  Q command: exit to DOS.
 */

#ifndef MCH_AMIGA
done()
{
  byte pflg;

  if (sure()) return;
#else
extern short done_flag;
done(askflag)
int askflag;
{
   byte pflg;
   done_flag = 0;
   if(!askflag && sure()) return;
   cursor_off();
#endif

  upduser(cport->user);
  log('X', 'Q', ' ', nullstr);
  clslog();
  clsusr();
  clsmsg();
  clsmon();
  iooff();                 /* also calls inittnc("tnc.off") */
  clrbusy();
  pflg = getp_flag();
  putp_flag(pflg clrbit window);
#ifdef MCH_AMIGA
   endtimer();
   cleanser();
   freefcb();
   closeterm();
#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;

/*
 *  Tell sysop who this is.
 */

  if (p isnt cport) { ioport(cport); prtx(mumsg); ioport(p); }

/*
 *  Show any connect request seen on the user port.
 */

  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);

/*
 *  Display the prompt.
 */

  curtim();
  switch (p->mode)
  {
    case local :
    case sysop :
      prtx(symenu);
      break;

    case remote:
      if (!(p->user->options & u_bbs))
      {
        if (s_param & s_p_name) if (!(p->user->state & u_name)) prtx(um[4]);
        if (s_param & s_p_home) if (!(p->user->state & u_home)) prtx(um[5]);
        if (s_param & s_p_zip)  if (!(p->user->state & u_zip))  prtx(um[6]);
      }

      if (p->user->options & (u_bbs | u_expert)) prtx(bbmenu); else prtx(rmenus);
      break;
  }
}

/*
 *  Log the user off.
 *  Do any defered remote sysop command.
 */

logo()
{
  register PORTS *p;
  register PORTS *tp;
  register char t;

  p = port;

  switch(p->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'; distnc(); break;
    case timeout: t = 'T'; prtx(mtime); break;
    default     : t = '?'; break;
  }

  log('X', t, ' ', nullstr);

/*
 *  If any port was used in terminal mode by the console,
 *  disconnect it.
 */

  if (p->dev is p_console)
  for (tp = porthd; tp isnt NULL; tp = tp->next)
  if (tp->flags & p_term)
  {
    ioport(tp);
    tp->mode = remote;
    distnc();
    tp->mode = idle;
    tp->flags clrbit p_term;
  }

  ioport(p);

/*
 *  Change TNC back to "standard" if was in "sysop" mode.
 *  May have just THOUGHT we discon, REALLY disconnect.
 */

  if (p->dev is p_tnc)
  {
    if (p->flags & p_clrsys) mkrem();
    p->mode = remote;
    distnc();
  }
  if (p->dev is p_serial) p->flags clrbit p_trans;
  p->mode = idle;

  upduser(p->user);

/*
 *  If there was a "deferred remote sysop command" do it.
 */

  ioport(cport);
  if (s_param & s_cmd)
  {
    s_param clrbit s_cmd;
    strcpy(cport->line, scmd);
    parse();
    wait(10);               /* Give sysop chance to get HIS system online */
    cport->mode = local;    /* Do command as if console did it */
    docmd();
    cport->mode = idle;
  }

  clnlog();
  clsusr();
  setfwd();
  clsmsg();
}

/*
 *  MailBox is idle.
 *  See if there is anything to do, and do it.
 *  If nothing to do, wait for connect.
 */
#ifndef MCH_AMIGA
/* REMOVE do_idle AND acmd() */
do_idle()
{
  register PORTS *p;
  register short curmin, lastmin;

  for (p = porthd; p isnt NULL; p = p->next) p->ec = p->ecmon;

  getc_flag();
  if (c_flag & window) acmd();

  allon();  /* Turn on monitoring and connects */
  clrbusy();
  curtim();
  curmin = 10 * (l_time[2] - '0') + (l_time[3] - '0');
  while(true)
  {

/*
 *  Check the port command flag to see if another window has
 *  issued a command request. If so setup and do the command.
 */

    getc_flag();
    if (c_flag & window)
    {
      setbusy();
      alloff();
      acmd();
      allon();
      clrbusy();
    }

    lastmin = curmin;
    curtim();
    curmin = 10 * (l_time[2] - '0') + (l_time[3] - '0');

/*
 *  Once each minute:
 *  Forward now, if it is time on any port.
 */

    if (curmin isnt lastmin) afwd(curmin);

/*
 *  Look for a login.
 */

    for (p = porthd; p isnt NULL; p = p->next)
    {
      ioport(p);
      if (instat()) switch(p->dev)
      {
        case p_serial:
          p->flags clrbit p_give;
          getdat();
          p->flags setbit p_give;
          if (iscon(p->line)) return;
          break;

        case p_tnc:
          p->flags clrbit p_give;
          getdat();
          p->flags setbit p_give;
          if (iscon(p->line)) return;
          monitor();
          break;

        case p_console:
          if (inchar() is wchar) return;
          break;
      }
      p->flags setbit p_give;
    }
  }
}
/*
 *  Do commands retrieved from the bios.
 */

acmd()
{
   char need_msg = false;

   port->mode = local;
   getcomd();
   if (s_flag & s_dv) begin_lock();
   if (port->opt1 is 'X')
   {
     readmsg();
     readusr();
     need_msg = true;
   }
   getc_flag();
   putc_flag( c_flag clrbit window);
   if (s_flag & s_dv) end_lock();
   sprintf(port->line, "%c%c", port->opt1, port->opt2);
   parse();
   docmd();
   if (need_msg)
   {
     clnlog();
     setfwd();
     clsmsg();
     clsusr();
   }
   port->mode = idle;
}
#endif
