
/*
 *  MBINIT.C - 9/19/88 - Read configuration file.
 */

#include "mb.h"

#ifdef MCH_AMIGA
#include <exec/memory.h>
extern long AvailMem();
extern char *AllocMem();
extern char tmpstr[];
extern int numpass;
extern int ln_jstr;
#endif
#define minheap 8192
#define minscr  4096
#define maxscr  16384

/*
 *  Read one line from the configuration file.
 *  The first field is a number. Return it.
 */

rdnumb()
{
  fgets (port->line, linelen, port->fl);
  parse ();
  return atoi (port->fld[0]);
}

/*
 *  Read one line from the configuration file.
 *  The first field is a YES / NO keyword.
 *  Return true if Y, false if N.
 */

kw()
{
  fgets(port->line, linelen, port->fl);
  parse();
  return(*port->fld[0] is 'Y');
}

/*
 *  Read one line from the configuration file.
 *  The first field is a letter.
 *  Return the control character corresponding to that letter.
 */

char cchr()
{
  fgets (port->line, linelen, port->fl);
  return (*port->line - 64);
}

/*
 *  Read one line from the configuration file.
 *  Squirrel it away in allocated memory.
 *  Return a pointer to it.
 */

char *rdstr()
{
  fgets (port->line, linelen, port->fl);
  return strdup(port->line);
}

/*
 *  Read a line from the configuration file.
 *  Remove the new line at end.
 *  Squirrel it away in allocated memory.
 *  Return a pointer to it.
 */

char *rdstrnl()
{
  fgets (port->line, linelen, port->fl);
  remnl(port->line);
  return strdup(port->line);
}

/*
 *  Read multiple lines from the configuration file, until "*** EOF".
 *  Squirrel them away in allocated memory in MLM structure.
 *  Return a pointer to the structure.
 */

MLM *rdmstr()
{
  register MLM *h, *m, *t;

  h = NULL;
  fgets (port->line, linelen, port->fl);
  while (!iseof(port->line))
  {
    m = (MLM *) malloc(sizeof(MLM));
    if (h is NULL) h = m; else t->next = m;
    m->next = NULL;
    t = m;
    m->text = strdup(port->line);
    fgets(port->line, linelen, port->fl);
  }
  return h;
}

/*
 *  Read multiple lines from the configuration file, until "*** EOF".
 *  Build the message hold list.
 */

rdhold()
{
  register HOLD *hp;

  hold = NULL;
  fgets (port->line, linelen, port->fl);
  while (!iseof(port->line))
  {
    hp = (HOLD *)malloc(sizeof(HOLD));
    hp->next = hold; hold = hp;
    parse();
    pcall(hp->call, port->fld[0]);

    fgets (port->line, linelen, port->fl);
  }
}

/*
 *  Read multiple lines from the configuration file, until "*** EOF".
 *  Build the @ BBS translation list.
 */

rdxbbs()
{
  register XBBS *xp;

  xbbs = NULL;
  fgets (port->line, linelen, port->fl);
  while (!iseof(port->line))
  {
    xp = (XBBS *)malloc(sizeof(XBBS));
    xp->next = xbbs; xbbs = xp;
    parse();
    pcall(xp->from, port->fld[0]);

    if (port->flds is 1) fill(xp->to, ' ', ln_call);
    else pcall(xp->to, port->fld[1]);

    fgets (port->line, linelen, port->fl);
  }
}

/*
 *  Read the directory path section of the configuration file.
 */

rdpaths()
{
  register DIRPATH *p, *path;
  register char *st;

  dphd = NULL;
  fgets(port->line, linelen, port->fl);
  while (!iseof(port->line))
  {
    path = (DIRPATH *) malloc(sizeof(DIRPATH));
    path->next = NULL;
    if (dphd is NULL) dphd = path; else p->next = path;
    p = path;

    parse();
    st = port->fld[0];
    path->flags = 0;
    path->id = *st++;
    while(*st)
    {
      switch(*st)
      {
        case 'D': path->flags setbit dp_dnload; break;
        case 'U': path->flags setbit dp_upload; break;
        default : ;
      }
      st++;
    }
    path->path = rdstrnl();
    path->name = rdstrnl();

    fgets(port->line, linelen, port->fl);
  }
}

/*
 *  Read the port definition section of the configuration file.
 */

rdports()
{
  register PORTS *p, *pt;
  register char *st;
  short first = true;
  byte mask = 0x00000001;
  byte pflg;
  window = 0;

  pt = porthd;
  fgets (port->line, linelen, port->fl);
  while (!iseof(port->line))
  {
    parse();

    if (!first)
    {
      pt = (PORTS *) malloc(sizeof(PORTS));
      pt->cmd  = (char *)malloc(cmdlen);
      pt->line = (char *)malloc(linelen);
      p->next = pt;
    }

    first = false;
    p = pt;
    pt->next = NULL;

    p->mode = idle;
    p->lport = NULL;

    pt->user = (USER *)malloc(sizeof(USER));
    pt->user->rn = 0;

    pt->mmhs = (MSG_HDR *)malloc(sizeof(MSG_HDR));
    pt->mmhs->rn = 0;

    pt->cmdcnt = 0;
    pt->msg = NULL;

    st = port->fld[0];
    pt->dev    = 0;
    pt->priv   = 0;
    pt->flags  = p_give | p_dotmr;
    pt->ecmon  = false;
    pt->eccmds = false;
    pt->ecuser = false;
    pt->tmode  = false;
    pt->id     = *st++;
    pt->idn    = (int)(pt->id - 'A');
    if (pt->idn < 8) window setbit (mask << pt->idn);
    while(*st)
    {
      switch(*st)
      {
/*
 *  Device type.
 */
        case 'C': pt->dev = p_console; cport = pt; break;
        case 'S': pt->dev = p_serial;  break;
        case 'T': pt->dev = p_tnc;     break;
/*
 *  Device characteristics.
 */
        case 'E': pt->flags setbit p_echo;   break;
        case 'L': pt->flags setbit p_lf;     break;
        case '1': pt->ecmon  = true;         break;
        case '2': pt->ecuser = true;         break;
        case '3': pt->eccmds = true;         break;
        case 'X': pt->tmode  = true;         break;
/*
 *  Port priveleges and permissions.
 */
        case 'B': pt->priv setbit p_bbs;     break;
        case 'D': pt->priv setbit p_dnload;  break;
        case 'G': pt->priv setbit p_gate;    break;
        case 'I': pt->priv setbit p_ilcal;   break;
        case 'M': pt->priv setbit p_mon;     break;
        case 'R': pt->priv setbit p_sysop;   break;
        case 'U': pt->priv setbit p_upload;  break;
      }
      st++;
    }
    pt->mode   = idle;
    pt->ctime  = atoi(port->fld[1]);
    pt->dtime  = atoi(port->fld[2]);
    pt->mtime  = atoi(port->fld[3]);
    pt->mcount = atoi(port->fld[4]);
    pt->maxhrd = atoi(port->fld[5]);
    pt->ndigi  = atoi(port->fld[6]);
    pt->fwdmin = atoi(port->fld[7]);
    pt->errmax = atoi(port->fld[8]);
    pt->ftime  = atoi(port->fld[9]);

    pt->nhrd   = 0;
#ifndef MCH_AMIGA
    pt->heard  = (char *) malloc(13 * pt->maxhrd);
#else
    pt->heard  = (char *) malloc(ln_jstr * pt->maxhrd);
#endif
    pt->name   = rdstrnl();

    pt->ec = pt->ecmon;

    fgets(port->line, linelen, port->fl);
  }
  pflg = getp_flag();
  putp_flag (pflg setbit window);
#ifndef MCH_AMIGA
  printf ("Window %X  port flag %X\n", window, pflg);
#else
  sprintf(tmpstr,"Window %02x  port flag %02\n", window, pflg);
  ttputs(tmpstr);
#endif

  ioinit();
#ifndef MCH_AMIGA
/* This is done by inittnc which is called by ioinit */
/*
 *  Drain any garbage from the port.
 */

  for (p = porthd; p isnt NULL; p = p->next)
  {
    ioport(p);
    switch(p->dev)
    {
      case p_tnc    :
        while(instat()) inchar();
        p->mode = remote;
        if (p->tmode) p->flags setbit p_trans;
        distnc();
        p->mode = idle;
        break;

      case p_serial :
      case p_console:
        while(instat()) inchar();

      default       : ;
    }
  }
#endif
  ioport(porthd);
#ifndef MCH_AMIGA
   printf("\n");
#else
  ttputc('\n');
#endif
}

/*
 *  Do the initialization. Called from mainline.
 */

init(file)
char *file;
{
  word avl;
#ifdef MCH_AMIGA
   word fast;
   char tstr[100];
#endif

/*
 *  Set default system params.
 */

  s_param = s_page;

/*
 *  Need structure for parse, so allocate a port.
 */

  porthd       = (PORTS *) malloc(sizeof(PORTS));
  porthd->cmd  = (char *)  malloc(cmdlen);
  porthd->line = (char *)  malloc(linelen);
  ioport(porthd);

/*
 *  Open the configuration file.
 */

  if ((port->fl = fopen(file, "r")) is NULL)
  {
#ifndef MCH_AMIGA
    printf("Cannot open %s\n", file); exit(1);
#else
    sprintf(tmpstr,"Cannot open %s\n", file); done(1);
    ttputs(tmpstr);
#endif
  }

/*
 *  Read the configuration file, set everything up.
 */

  rdports();
  rdpaths();
  rdxbbs();
  rdhold();
  rdcnf();

  fclose(port->fl);

  ioport(cport);

  opnmon();
  opnmsg();
  opnusr();
  opnbid();

  rduser(tcall, cport->user);

/*
 *  If owners user record did not exist, make him one of the right kind.
 */

  if (!cport->user->rn)
  {
    cport->user->options = u_bbs | u_sysop | u_local;
    strncpy(cport->user->home_bbs, tcall, ln_call);
    upduser(cport->user);
  }

  opnlog();
  log ('C','I',' ',nullstr);

/*
 *  Grab a mess of memory.
 *  16k max. Leave at least 8k for heap.
 */
#ifndef MCH_AMIGA
  avl = _memavl();
  if ( (avl - minheap) > maxscr ) scrmax = maxscr;
  else scrmax = avl - minheap;
  if (scrmax < minscr)
  {
    printf("Too little memory available.\n");
    exit(1);
  }
  tmp = (TMP *) malloc(scrmax);
  printf("There is %u free space, %u will be used.\n", avl, scrmax + minheap);
#else
   /* get free space in Kb */
   avl = (int)(AvailMem(MEMF_CHIP)>>10);
   fast = (int)(AvailMem(MEMF_FAST)>>10);
   /* Just ask for the whole 16Kb ... If it's not there try scrmin */
   scrmax = maxscr;
   tmp = (TMP *) malloc(maxscr);
   if(tmp == 0) {
      tmp = (TMP *) malloc(minscr);
      scrmax = minscr;
      if(tmp == 0) {
         sprintf(tstr,"Not enough memory available.\n");
         ttputs(tstr);
         endtimer();
         cleanser();
         freefcb();
         closeterm();
         exit(1);
      }
   }
   /* amiga doesn't need a 'heap' */
   sprintf(tstr,"%uKb Chip, %uKb Fast Memory. %uKb will be used.\n",
                         avl,fast, scrmax >> 10);
   ttputs(tstr);
#endif
  dirmax = scrmax / sizeof(DIRENT);
  seed();
  dosinit();

/*
 *  Set initial beacon text.
 */

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

seed()
{
  register long curmin;
  register int cm;
  curmin = gettime();
  cm = (short)(curmin & 0xffff);
  srand(curmin);
}
/*
 *  Read the rest of the configuration file,
 *  after the port and path definitions.
 */

rdcnf()
{
  register int i;

/*
 *  Login message.
 */

  motd = rdmstr();

/*
 *  Prompts.
 */

  bbmenu = rdstr();  /* Prompt for connected bbs */
  symenu = rdstr();  /* Local and remote sysop prompt */
  rmenus = rdstr();  /* User prompt */

/*
 *  Who are we?
 */

  fgets (port->line, linelen, port->fl);
  pcall (tcall, port->line);

/*
 *  Where are we?
 */

  qth = rdstrnl();

/*
 *  Who is our name server?
 */

  fgets (port->line, cmdlen, port->fl);
  pcall (wpcall, port->line);

/*
 *  File names and directory paths used by MailBox.
 */

  helpfile = rdstrnl();
  infofile = rdstrnl();
  fwdfile  = rdstrnl();
  lgfile   = rdstrnl();
  monfile  = rdstrnl();
  mbfile   = rdstrnl();
  mbbfile  = rdstrnl();
  usfile   = rdstrnl();
  usbfile  = rdstrnl();
  msgdir   = rdstrnl();
  bidfile  = rdstrnl();

  hrdfile  = rdstrnl();
  hrdmax   = rdnumb();

/*
 *  Automatic mail untangle at what hour?
 *  NO or YES hh  Where hh is the untangle hour 0-23
 */

  if (kw())
  {
  s_param setbit s_unt;
  unt_hr = atoi(port->fld[1]);
  }

/*
 *  Give time slice back to DESQview?
 */

  if (kw()) s_flag setbit s_dv;

/*
 *  Prompt for user info?
 */

  if (kw()) s_param setbit s_p_name;
  if (kw()) s_param setbit s_p_home;
  if (kw()) s_param setbit s_p_zip;

/*
 *  Logging
 */

  if (kw()) s_param setbit s_log_on;
  if (kw()) s_param setbit s_log_gate;
  if (kw()) s_param setbit s_log_file;
  if (kw()) s_param setbit s_log_msg;
  if (kw()) s_param setbit s_log_loc;

/*
 *  Control characters.
 */

  achar = cchr();
  rchar = cchr();
  tchar = cchr();
  wchar = cchr();

  pausemsg = rdstr();
/* Text for local display of user call. */
  mumsg = rdstr();
/* Text to send when get connect request. */
  reqmsg = rdstr();
/* Various "talk to the owner" texts. */
  talkm1 = rdstr();
  talkm2 = rdstr();
  talkm3 = rdstr();
  talkm4 = rdstr();
/* GateWay Messages. */
#ifndef MCH_AMIGA
  for (i = 0; i < num_gm; i++) gm[i] = rdstr();
#else
  for (i = 0; i < num_gm; i++) rdstr();
#endif
/* MailBox messages. */
  for (i = 0; i < num_mm; i++) mm[i] = rdstr();
/* Max calls in unread mail list. */
  ufwdm = rdnumb();
  bfwdm = rdnumb();
/* Kill regular message after forward? */
  if (kw()) s_param setbit s_kill;
/* Kill F message after forward? */
  if (kw()) s_param setbit s_fkill;
/* Generate service msg after KT? */
  if (kw()) s_param setbit s_svc;
/* Enable ET command? */
  if (kw()) s_param setbit s_edtfc;
/* How many days before a message becomes stale */
  tstaleb = rdnumb();
  tstalen = rdnumb();
  tstaleu = rdnumb();
/* Upload/download prompts. */
  fm = rdstr();
/* User file text. */
  for (i = 0; i < num_um; i++) um[i] = rdstr();
  remnl(um[0]);
/* Error/status messages. */
  mcant  = rdstr();
  mfind  = rdstr();
  mprot  = rdstr();
  mexst  = rdstr();
  mtime  = rdstr();
  mwhat  = rdstr();
  mdone  = rdstr();
  mnport = rdstr();
  mndir  = rdstr();
  mnfile = rdstr();
  mnmsg  = rdstr();
  minuse = rdstr();
/* Null ifdef to notify a change to V6 */
#ifdef MCH_AMIGA
#endif
#ifdef NEWPASS
   numpass = initpwd();
sprintf(tmpstr,"NUMPASS = %d\n",numpass);
ttputs(tmpstr);
#else
   keylst = rdstr();
#endif
}
