/*
 *  MBLOG.C - 10/15/90 - Logging and Monitoring.
 */

#include "mb.h"

#ifndef MCH_AMIGA
#define ln_jstr (ln_callp + ln_time + (ln_date-2))
#else
int ln_jstr = (ln_callp + ln_time + (ln_date-2));
#endif

#ifdef MCH_AMIGA
/* Add a log_yr variable so that the year can be used as part of the
   date when a log file is renamed. e.g. to log9011.mb instead of log11.mb
*/
int log_yr;
#endif

char *lgfile;
FILE *lfl;

char *monfile;

char *hrdfile, *hrd;
int  hrdmax, hrdn;

/*
 *  Clean the log file.
 *  Force drain of buffers, update of directory item.
 */

clnlog()
{
  if (s_param & s_log_on)
  {
    fclose(lfl);
    lfl = fopen(lgfile, "a+");
  }
}

clslog()
{
#ifndef MCH_AMIGA
  if (s_param & s_log_on) fclose (lfl);
#else
   if(s_param & s_log_on) {
      if(lfl) {
         fclose (lfl);
         lfl = 0;
      }
   }
#endif
}

/*
 *  Open the log file.
 */

opnlog()
{
  if (s_param & s_log_on)
#ifndef MCH_AMIGA
    if ((lfl = fopen(lgfile, "a+")) is NULL) { nofile(lgfile); exit(1); }
#else
    if ((lfl = fopen(lgfile, "a+")) is NULL) { nofile(lgfile); done(1); }
#endif
}

/*
 * Get the log date.
 */

logdat()
{
  if (s_param & s_log_on)
  {
    fseek(lfl, 0L, 0);
    fgets(port->line, linelen, lfl);
    log_mon = 10 * (port->line[3] - '0') + (port->line[4] - '0');
#ifdef MCH_AMIGA
/* Only to allow rename of log file to contain year as well */
    log_yr = 10 * (port->line[1] - '0') + (port->line[2] - '0');
#endif
    fseek (lfl, 0L, 2);
  }
}

/*
 * Change the log file at end of month.
 */

chglog()
{
  register char *logp;
  char logs[80], nlgfile[80];

  log ('X', 'Q', ' ', nullstr);
  clslog();
  logp = strchr(lgfile, '.');
  strncpy( logs, lgfile, (int)(logp-lgfile));
  logs[(int)(logp-lgfile)] = '\0';
#ifndef MCH_AMIGA
  sprintf( nlgfile, "%s%02u%s", logs, log_mon, logp);
#else
/* Put the last two digits of the year in the filename too */
  sprintf( nlgfile, "%s%02u%02u%s", logs, log_yr, log_mon, logp);
#endif
  printf( "%s renamed to %s\n", lgfile, nlgfile);
  rename(lgfile, nlgfile);
  opnlog();
  log ('C', 'I', ' ', nullstr);
  logdat();
}

/*
 *  Log an event.
 */

log(event, fn, sfn, text)
char event, fn, sfn, *text;
{

/*
 *  Do we log this type of event?
 */

  if (!(s_param & s_log_on)) return;

  if (port->dev is p_console) if (!(s_param & s_log_loc))
  switch(event)
  {
    case 'M' : if(!((fn is 'M') or (fn is 'S'))) return; break;
    case 'X' : if(fn isnt 'Q') return; break;
    case 'C' : if(fn isnt 'I') return; break;
    default  : return;
  }

  switch(event)
  {
    case 'U' : if (!(s_param & s_log_gate)) return; break;
    case 'M' : if (!(s_param & s_log_msg))  return; break;
    case 'F' : if (!(s_param & s_log_file)) return; break;
  }

/*
 *  Yes, so log it.
 */

  curtim();
  fprintf(lfl, "%c%s%s%c%c %s\n", event, l_date, l_time, fn, sfn, text);
}

/*
 *  Monitoring ...
 */
#ifdef MCH_SYSOP
opnmon()
{
}
clsmon()
{
}
#else
/* SYSOP doesn't do monitoring at all */
clsmon()
{
  register short  i;
  register char  *c;
  register PORTS *p;

/*
 *  Write out the heard log.
 */

  if ((port->fl = fopen(hrdfile, "w")) isnt NULL)
  {
    sort(hrd, hrdn, ln_call, tmp->scr);
    for (i = 0, c = hrd; i < hrdn; i++, c += ln_call)
      fprintf(port->fl, "%6.6s\n", c);
    fclose(port->fl);
  }

/*
 *  Write out the J list for each port.
 */

  if ((port->fl = fopen(monfile, "w")) isnt NULL)
  {
    for (p = porthd; p isnt NULL; p = p->next)
    {
      for (i = 0, c = p->heard; i < p->nhrd; i++, c += ln_jstr)
      fprintf (port->fl, "%17.17s\n", c);
      fprintf (port->fl, "*** EOF\n");
    }
    fprintf (port->fl, "%s%s\n", l_date, l_time);
    fclose (port->fl);
  }
}

/*
 *  Open "heard log" and "monitor log".
 */

opnmon()
{
  register char *i, *j, *st;
  register PORTS *p;

/*
 *  Open the "heard list" file.
 */
#ifndef MCH_AMIGA
  if ((hrd = (char *)malloc(ln_call * hrdmax)) is NULL) errall();
#else
  if ((hrd = (char *)malloc(ln_call * hrdmax)) is NULL) errall(3);
#endif

  hrdn = 0;

  if ((port->fl = fopen(hrdfile, "r")) isnt NULL)
  {
    i = hrd;
    while((hrdn < hrdmax) and (fgets (port->line, linelen, port->fl) isnt NULL))
    {
      pcall(i, port->line);
      hrdn++; i += ln_call;
    }
    fclose(port->fl);
    sprintf(port->line, "%d calls in %s", hrdn, hrdfile); outstr(port->line);
#ifdef MCH_AMIGA
      sprintf(port->line," hrdmax = %d",hrdmax);
      outstr(port->line);
    if (hrdn is hrdmax) outstr(" (File is full.)");
    outchar('\n');
#endif
  }

/*
 *  Open the monitor file and read the J list for each port.
 */

  if ((port->fl = fopen(monfile, "r")) isnt NULL)
  {
    for (p = porthd; p isnt NULL; p = p->next)
    {
      st = fgets (port->line, linelen, port->fl);
      j = p->heard;
      while (!iseof(port->line) and (st isnt NULL))
      {
   if (p->nhrd < p->maxhrd)
   {
     for (i = port->line; i < port->line + ln_jstr;) *j++ = *i++;
     p->nhrd++;
   }
   st = fgets (port->line, linelen, port->fl);
      }
    }
    fclose(port->fl);
  }
}

/*
 *  Add call in monitored packet to J list of current port.
 */

monitor()
{
  register short l1, l2;
#ifdef MCH_AMIGA
   extern PORTS *devtnc;

   if(devtnc->dev == p_serial)return;
   if(devtnc->dev == p_nulmdm)return;
#endif
  if (port->heard is NULL) return;
  for (l1 = 0; l1 < ln_callp; l1++) if (port->line[l1] is '>')
  {
    if (l1 < 4) return;

    port->line[l1] = '\0';
    for (l2 = 1; l2 < 10; l2++)
    if ((port->line[l1 + l2] is ':') or
#ifdef MCH_AMIGA
/* For KAM */
   (port->line[l1 + l2] is '/') or
#endif
   (port->line[l1 + l2] is ',') or
   (port->line[l1 + l2] is ' ') or
   (port->line[l1 + l2] is '\0'))
    {
      if (l2 > 4) { addcall(port->line, port); addhrd(); }
      return;
    }
    return;
  }
}

/*
 *  Add call to heard list.
 */

addhrd()
{
  register int i;
  register char *p;
  if (hrdn >= hrdmax) return;
  pcall(tmp->scr, port->line);

  for (i = 0, p = hrd; i < hrdn; i++, p += ln_call)
  if (matchn(tmp->scr, p, ln_call)) return;
  strncpy(hrd + (ln_call * hrdn++), tmp->scr, ln_call);
}

/*
 *  Add call to J list.
 */

addcall(cp, p)
char *cp;
PORTS *p;
{
  register char  *k;
  register short i;
  register char  *sk;
  register short si;
  ljsf(tmp->scr, cp, ln_callp);

/*
 *  Check if this call already in list for this port.
 */

  si = -1;
  for (i = 0, k = p->heard; i < p->nhrd; i++, k += ln_jstr)
  if (matchn(tmp->scr, k, ln_callp)) { si = i; sk = k; }

/*
 *  If not already in the list ...
 */

  if (si is -1)
  {
    si = p->nhrd; sk = p->heard + ln_jstr * p->nhrd;
    if (p->nhrd < p->maxhrd) p->nhrd++; else { si--; sk -= ln_jstr; }
  }

/*
 *  Put call at top of list for this port.
 */

  for (; si; si--, sk -= ln_jstr) strncpy (sk, sk - ln_jstr, ln_jstr);
  curtim();
  strncpy(p->heard + ln_callp, l_time, ln_time);
  strncpy(p->heard + ln_callp+ln_time, l_date+2, ln_date-2);
  strncpy(p->heard, tmp->scr, ln_callp);
}
#endif
/*
 *  J command, print list of calls heard.
 */

prthrd()
{
  register short i;
  register char *j;
  register PORTS *p;
#ifdef MCH_SYSOP
   prtx(mcant);
   return;
#endif
  if (port->opt2 is ' ') { shports(); return; }

  if ((p = findport(port->opt2)) is NULL) { prtx(mnport); return; }

  sprintf(tmp->scr, "Port %c, %s\n", p->id, p->name);
  outstr(tmp->scr);

  if (!(p->nhrd)) { prtx(mfind); return; }

  for (i = 0, j = p->heard; i < p->nhrd; i++, j += ln_jstr)
  {
    sprintf(tmp->scr, "%9.9s %4.4s %2.2s/%2.2s\n", j, j + ln_callp,
            j+(ln_callp+ln_time), j+(ln_callp+ln_time+2));
    outstr(tmp->scr);
  }
}

