/******
 for Manx compile with -WO option
*******/

#include <exec/types.h>
#include <exec/exec.h>
#include <dos/dos.h>
#include <stdio.h>
#include <stdlib.h>
#include "dh0:code/code20/defines.h"
struct MailHeader MS;
char conf[200];
struct MailStat OMS;
BOOL UPDATE=FALSE;
void NullStats();
int TLock(char *str);
void sr(char *str);
char temp[200];
long Slot;
long GetFileSize(char *str);
long FileSize=0L;
long TotalSlots=0L;
long TempSlot=0L;
char TempFile[200];
char StatFile[200];
void InitStat();
BOOL StatError=TRUE;
int ValidStat();
long GetStat();
long StatNum;
BOOL Eoj=TRUE;
void end();
main(int argc,char *argv[])
{
  FILE *fi,*fo;
  if(argc<2 || argc >3)
  {
    printf("\n\n");
    printf("MsgBaseRepair version 1.0 written by Joseph Hodge\n");
    printf("Usage: MsgBaseRepair <conference path> [UPDATE]\n");
    printf("   ie: MsgBaseRepair BBS:PD\n");
    printf("\n");
    printf("WARNING! This utility will not make a backup and\n");
    printf("         will attempt to fix your msgbase if it\n");
    printf("         detects any errors\n\n");
    printf("         THE BBS MUST BE OFFLINE WHEN RUNNING THIS\n");
    printf("         UTILITY\n");
    printf("This is an AmiExpress 1.1w+ utility\n");

    printf("\n");
    exit(0);
  }
  printf("\n\nMsgBaseRepair version 1.0\nwritten by Joseph Hodge\n");
    
  strcpy(conf,argv[1]);
  sr(conf);
  if(!TLock(conf))
  {
     printf("Can't locate conference location %s\n",conf);
     printf("\n");
     exit(0);
  }
  Slot=0L;
  if(argc==3)
  {
    UPDATE=TRUE;
  }
  strcpy(StatFile,conf);
  strcat(StatFile,"/MsgBase/MailStats");
  if(!TLock(StatFile))
  {
    StatError=TRUE; StatNum=-1L;
    Eoj=FALSE;
  }else
  { StatError=FALSE; StatNum=GetStat(); }
  strcat(conf,"/MsgBase/HeaderFile");
  NullStats();
printf("*---------------------------------------------*\n");
    
  if(TLock(conf))
  {
    while(1)
    {
      FileSize=GetFileSize(conf);
      TotalSlots=FileSize/(long)sizeof(struct MailHeader);
      printf("Total Slots = %ld\n",TotalSlots);
      printf("Partial     = %ld\n",FileSize%(long)sizeof(struct MailHeader));
      if(StatNum==-1L)
    { printf("NextMsgNum  = UNKNOWN\n");
      }
 else printf("NextMsgNum  = %ld <---Per MailStats\n",StatNum);
       printf("*---------------------------------------------*\n");
      if(FileSize%(long)sizeof(struct MailHeader))
      {
        Eoj=FALSE;
     printf("\nMsgBase HeaderFile is corrupt                \n");
       printf("Rebuilding HeaderFile                        \n");
        sprintf(TempFile,"%s.old",conf);
        Rename(conf,TempFile);
        fi=fopen(TempFile,"rb");
        fo=fopen(conf,"wb");
        TempSlot=0L;
        while(TempSlot<TotalSlots)
        {
          fread((APTR)&MS,sizeof(struct MailHeader),1,fi);
          fwrite((APTR)&MS,sizeof(struct MailHeader),1,fo);
          TempSlot +=1L;
        }
        fclose(fi);
        fclose(fo);
        DeleteFile(TempFile);
        InitStat();
        OMS.HighMsgNum=MS.MsgNumb+1L;
        fo=fopen(StatFile,"wb");
        fwrite((APTR)&OMS,sizeof(struct MailStat),1,fo);
        fclose(fo);
        printf("MailStats updated\n");
        StatError=FALSE;
      }
      else break;
     }
    fi=fopen(conf,"rb");
    if(fi==NULL)
    {
      printf("Error! can't open file %s\n",conf);Eoj=FALSE;
      end();
    }
    Slot=TotalSlots -1L;
    fseek(fi,(long)sizeof(struct MailHeader)*Slot,SEEK_SET);
    fread((APTR)&MS,sizeof(struct MailHeader),1,fi);
    fclose(fi);
    printf("Current MailHeader for Slot %ld\n",Slot+1);
    printf("\n");
    printf("Status       :%c\n",MS.Status[0]);
    printf("MsgNumb      :%ld\n",MS.MsgNumb);
    printf("ToName       :%s\n",MS.ToName);
    printf("FromName     :%s\n",MS.FromName);
    printf("Subject      :%s\n",MS.Subject);
    printf("MsgDate      :%ld\n",MS.MsgDate);
    printf("Recv         :%ld\n",MS.Recv);
    printf("\n");
    if(StatError)
    {
     InitStat(); Eoj=FALSE;
        OMS.HighMsgNum=MS.MsgNumb+1L;
        fo=fopen(StatFile,"wb");
        fwrite((APTR)&OMS,sizeof(struct MailStat),1,fo);
        fclose(fo);
        printf("MailStats updated\n");
        StatError=FALSE;
    }
    else if(!ValidStat())
    {
        InitStat();Eoj;
      OMS.HighMsgNum=MS.MsgNumb+1L;
        fo=fopen(StatFile,"wb");
        fwrite((APTR)&OMS,sizeof(struct MailStat),1,fo);
        fclose(fo);
        printf("MailStats updated\n");
        StatError=FALSE;
    }
  }
  else
  {
    if(!UPDATE)
    {
      printf("Error!, HeaderFile does not exist for this conference\n");
      printf("This is normal if the message base has not been used\n");
      printf("But if the message base has been used then please run\n");
      printf("this utility with the UPDATE option\n");
      printf("\n\n");
      if(TLock(StatFile))
      {
        DeleteFile(StatFile);
      }
      exit(0);
    }
  }
  if(UPDATE)
  {
    printf("Enter New Status    >:");
    gets(temp);
    MS.Status[0]=temp[0];
    printf("Enter New MsgNum    >:");
    gets(temp);
    MS.MsgNumb=atol(temp);
    printf("Enter New ToName    >:");
    gets(temp);
    strcpy(MS.ToName,temp);
    printf("Enter New FromName  >:");
    gets(temp);
    strcpy(MS.FromName,temp);
    printf("Enter New Subject   >:");
    gets(temp);
    strcpy(MS.Subject,temp);
    printf("Enter New MsgDate   >:");
    gets(temp);
    MS.MsgDate=atol(temp);
    printf("Enter New Recv      >:");
    gets(temp);
    MS.Recv=atol(temp);

    fi=fopen(conf,"wb");
    if(fi==NULL)
    {
      printf("Error!, can't create HeaderFile file\n");
      printf("\n\n");Eoj=FALSE;
      end();
    }
    fseek(fi,(long)sizeof(struct MailHeader)*Slot,SEEK_SET);
    
    fwrite((APTR)&MS,sizeof(struct MailHeader),1,fi);
    fclose(fi);
     InitStat();
        OMS.HighMsgNum=MS.MsgNumb+1L;
        fo=fopen(StatFile,"wb");
        fwrite((APTR)&OMS,sizeof(struct MailStat),1,fo);
        fclose(fo);
        printf("MailStats updated\n");
  }
  end();
}
void end()
{
  printf("*---------------------------------------------*\n");
  if(Eoj)
  {
  printf("*     MESSAGE BASE APPEARS TO BE CORRECT      *\n");
  printf("*---------------------------------------------*\n");
  }
  exit(0);
}
void sr(char *str)
{
  register int i;
  i=strlen(str)-1;
  while(i>-1)
  {
    if(*(str+i)<=32) *(str+i)='\0'; else break;
    i--; 
  }
}
#define ACCESS_READ -2
int TLock(char *str)
{
  long lock;
  if(lock=Lock(str,ACCESS_READ))
  {
    UnLock(lock); return(1);
  }
  return(0);
}
void NullStats()
{
  strcpy(MS.Status,"");
  MS.MsgNumb=0L;
  strcpy(MS.ToName,"");
  strcpy(MS.FromName,"");
  strcpy(MS.Subject,"");
  MS.MsgDate=0L;
  MS.Recv=0L;
  MS.Pad=' ';
}
long GetFileSize(char *str)
{
struct FileInfoBlock *FBlock;
long *FLock;

  long fsize=-1L;
if((FLock = Lock(str,ACCESS_READ)) == NULL)
        {
          printf("Can't lock file\r\n");
          return(-1L);
        }
        if((FBlock=AllocMem((long)sizeof(struct FileInfoBlock),MEMF_CHIP)) == NULL)
        {
          printf("Out of chipmem for FileInfoBlock\r\n");
          UnLock(FLock);
          return(-1L);
        }
        if( Examine(FLock,FBlock) )
        {
          fsize = FBlock->fib_Size;
        }
        UnLock(FLock);
        FreeMem(FBlock,sizeof(struct FileInfoBlock));
        return(fsize);
}

void InitStat()
{
   OMS.LowestKey=1L;
  OMS.HighMsgNum=0L;
  OMS.LowestNotDel=1L;
  strcpy(OMS.Pad,"     ");
}

int ValidStat()
{
  FILE *fi;
  if(TLock(StatFile))
  {
    fi=fopen(StatFile,"rb");
    fread((APTR)&OMS,sizeof(struct MailStat),1,fi);
    fclose(fi);
    if(OMS.HighMsgNum!=MS.MsgNumb+1L)
    {
      return(0);
    }
    return(1);
  }
  return(0);
}
long GetStat()
{
  FILE *fi;
   if(TLock(StatFile))
  {
    fi=fopen(StatFile,"rb");
    fread((APTR)&OMS,sizeof(struct MailStat),1,fi);
    fclose(fi);
    return(OMS.HighMsgNum);
  }
  return(-1L);
}