/* This small program imports Maximus CBCS 3.0x CALLINFO.BBS/LASTUSxx.BBS
   into BT-XE's history file */
/* by Alex Woick, 2:244/1351 970531 */
/* Compiler used: Watcom 10.0a, tested to compile DOS16 and OS/2 v2 versions */


#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <io.h>
#include <ctype.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <share.h>

/* this is max.h from Maximus 3.01 "structs.zip" package */
#include "max.h"

typedef struct _ADDRESS
{
    word Zone;
    word Net;
    word Node;
    word Point;
    char *Domain;
} ADDR, *ADDRP;

#include "..\..\include\history.h"

#define YEAR(t)   (((t & 0xFE00) >> 9) + 1980) 
#define MONTH(t)  ((t & 0x01E0) >> 5) 
#define DAY(t)    (t & 0x001F) 

#define HOUR(t)   ((t & 0xF800) >> 11) 
#define MINUTE(t) ((t & 0x07E0) >> 5) 
#define SECOND(t) ((t & 0x001F) << 1) 

struct m_pointers prm;
char *offsets;

int ReadMaxPrm(const char *maxprmname)
{
  int prmfile;
  long heaplen;
  long numread;

  prmfile = shopen(maxprmname, O_RDONLY|O_BINARY);
  if (prmfile != -1) {
    numread = read(prmfile, &prm, sizeof(struct m_pointers));
    if (numread!=sizeof(struct m_pointers)) {
      close(prmfile);
      return -1;
    }
    heaplen = filelength(prmfile)-prm.heap_offset;
    offsets = (char *)malloc(heaplen);
    if (offsets) {
      lseek(prmfile, prm.heap_offset, SEEK_SET);
      read(prmfile, offsets, heaplen);
      close(prmfile);
      return 0;
    }
  }
  return -1;
}

char *nicepath(char *s) {
/* writes a backslash to the end of the string */

  int i;

  if (s==NULL) return(s);

  i = strlen(s);
  if (i > 0) {
    if (s[i-1] != '\\') {
      strcat(s,"\\");
    }
  }
  return(s);
}


int GetMax3Lastcall(CALLHIST *phist, struct callinfo *pcallinfo, struct _usr *plastuser, word task)
{
  struct tm st;

  memset(phist, 0, sizeof(CALLHIST));

  strncpy(phist->h.b2.name,  plastuser->name,  sizeof(phist->h.b2.name));
  strncpy(phist->h.b2.handle, plastuser->alias, sizeof(phist->h.b2.handle));
  strncpy(phist->h.b2.city,  pcallinfo->city,  sizeof(phist->h.b2.city));      
  phist->h.b2.filesup = pcallinfo->filesup;
  phist->h.b2.filesdn = pcallinfo->filesdn;
  phist->h.b2.kbup    = pcallinfo->kbup;
  phist->h.b2.kbdn    = pcallinfo->kbdn;
  phist->h.b2.calls   = pcallinfo->calls;
  phist->h.b2.read    = pcallinfo->read;
  phist->h.b2.posted  = pcallinfo->posted;
  phist->h.b2.baud    = plastuser->delflag;

  phist->task = task;
  phist->outgoing=0;
  phist->calltype = CT_BBS;
  phist->subclass = SC_CALLINFO;
 
  st.tm_sec = SECOND(pcallinfo->login.dos_st.time);
  st.tm_min = MINUTE(pcallinfo->login.dos_st.time);
  st.tm_hour = HOUR(pcallinfo->login.dos_st.time);
  st.tm_mday = DAY(pcallinfo->login.dos_st.date);
  st.tm_mon = MONTH(pcallinfo->login.dos_st.date) - 1;
  st.tm_year = YEAR(pcallinfo->login.dos_st.date) - 1900;
  st.tm_isdst = -1;
  phist->starttime = mktime(&st);

  printf("Logon:  %02d.%02d.%02d %02d:%02d:%02d (%ul)\n", st.tm_mday, st.tm_mon, st.tm_year, st.tm_hour, st.tm_min, st.tm_sec, phist->starttime);

  st.tm_sec = SECOND(pcallinfo->logoff.dos_st.time);
  st.tm_min = MINUTE(pcallinfo->logoff.dos_st.time);
  st.tm_hour = HOUR(pcallinfo->logoff.dos_st.time);
  st.tm_mday = DAY(pcallinfo->logoff.dos_st.date);
  st.tm_mon = MONTH(pcallinfo->logoff.dos_st.date) - 1;
  st.tm_year = YEAR(pcallinfo->logoff.dos_st.date) - 1900;
  st.tm_isdst = -1;

  printf("Logoff: %02d.%02d.%02d %02d:%02d:%02d (%ul)\n", st.tm_mday, st.tm_mon, st.tm_year, st.tm_hour, st.tm_min, st.tm_sec, mktime(&st));

  phist->length = mktime(&st) - phist->starttime;

  printf("Length: %d seconds\n", phist->length);

  return 0;
}


void help()
/* show short usage help */
{
  printf ("Usage:   GETMAX3 [/h:<btxe_history_file> [/m:<max.prm>] [/t:<task_number>]\n");
  printf ("Example: GETMAX3 /h:P:\\BTXE\\TASK\\ALLTASKS.HST /m:L:\\MAX\\MAX.PRM /t:2\n\n");
  printf ("Defaults: btexe_history_file: %%BINKLEY%%\\TASK\\CALLHIST.ALL\n");
  printf ("          max.prm:            %%MAXIMUS%%\n");
  printf ("          task_number:        %%TASK%%, if not defined then from max.prm\n");
  exit (1);
}

int main (int argc,char **argv)
{
    CALLHIST rec;

    char tmp[255], tmp2[255];
    char *s, *opt;
    char shistfname[255];
    char *smaxprm;
    char *stasknr;

    unsigned tasknr=0;
    FILE *callerbbs;
    FILE *lastuserbbs;
    FILE *callhist;

    struct _usr     lastuserrec;
    struct callinfo callinforec;

    int i;

    putenv("TZ=GMT0"); /* make it compatible to BT's misbehaviour        */
    tzset();           /* TJW: Read TZ variable and adapt time functions */
    
    printf ("Maximus CBCS 3.0x to BT-XE 1.0, by Alex Woick, 2:244/1351\n");
    printf ("-------------------------------------------------------------------------------\n");

    /* set the defaults */

    strcpy(shistfname, "CALLHIST.ALL");
    s = getenv("BINKLEY");
    if (s) {
      strcpy(shistfname, s);
      nicepath(shistfname);
      strcat(shistfname, "TASK\\CALLHIST.ALL");
    }
    smaxprm = getenv("MAXIMUS");
    stasknr = getenv("TASK");

    for (i=1; i<argc; i++) {
      opt = argv[i];
      if (strlen(opt)>3 && (opt[0]=='/' || opt[0]=='-') && opt[2]==':') {
        switch (toupper(opt[1])) {
        case 'H': strcpy(shistfname, opt+3);
           break;
        case 'M': smaxprm = opt+3;
           break;
        case 'T': stasknr = opt+3;
           break;
        default: help();
          break;
        }
      } else
        help();
    }
    if (stasknr) {
      tasknr=atoi(stasknr);
    }
    printf("tasknr=%u\n", tasknr);
    if (tasknr==0) {
      printf("task number not given or not >=1: '%s'\n", stasknr);
      exit(-1);
    }

    if (ReadMaxPrm(smaxprm)) {
      printf("cannot read Maximus .PRM file '%s'\n", smaxprm);
      exit(-1);
     }

    strcpy(tmp, PRM(sys_path));
    nicepath(tmp);

    sprintf(tmp2, "%slastus%02x.bbs", &tmp, tasknr);
    printf("lastuser.bbs='%s'\n", tmp2);
    lastuserbbs = fopen(tmp2, "rb");
    if (!lastuserbbs) {
      printf("cannot open '%s'\n", tmp2);
      free(offsets);
      exit(-1);
    }
    fread(&lastuserrec, 1, sizeof(struct _usr), lastuserbbs);
    fclose(lastuserbbs);

    sprintf(tmp2, "%s.bbs", PRM(caller_log));
    printf("callers logfile='%s'\n", tmp2);
    callerbbs = fopen(tmp2, "rb");
    if (!callerbbs) {
      printf("cannot open callers logfile '%s'\n", tmp2);
      free(offsets);
      exit(-1);
    }
    printf("BT XE history file='%s'\n", shistfname);
    for (i=1; i<=255; i++) { /* search the last 255 entries */
      fseek(callerbbs, -(long)i * (long) sizeof(struct callinfo), SEEK_END);
      fread(&callinforec, 1, sizeof(struct callinfo), callerbbs);
      if (callinforec.task==tasknr) { /* found the last entry in caller.bbs for this task */
        printf("Found last user: %s (task=%u)\n", callinforec.name, callinforec.task);
        GetMax3Lastcall(&rec, &callinforec, &lastuserrec, tasknr);
        callhist = fopen (shistfname,"a+b");
        if (!callhist) {
          printf ("Unable to open output file '%s'\n", shistfname);
          exit (-1);
        }
        fwrite (&rec,1, sizeof(CALLHIST), callhist);
        fclose (callhist);
        printf ("Done.\n");
        break;
      }
    }
    if (i==256) {
      printf("Cannot find entry for last user in '%s'\n", tmp2);
    }
    fclose(callerbbs);
    free(offsets);

    return 0;
}
