#define MAIN_PROG
#include "bbs.h"
#undef MAIN_PROG

#include <graphics/displayinfo.h>
#include <intuition/intuition.h>
#include <graphics/gfxbase.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include "deadline.h"
void ModemOffHook(void);
BOOL ReadComputerTypes(void);
void Randomize(void);
void AllocateConfs(int NumConfs);
void DeAllocateConfs(void);
int DeCode(void);
void LoadKey(void);
void (*dumfunc)(char *s);
void (*secfunc)(APTR s,APTR d);
static void closelibs(void);
int Menu(void);
int Logon_Sequence(void);

int LastValidUser = 2;
int Dropped_Hook=0;
int NotRelative=TRUE;
char langtitle[80];
char lang[20];
extern char *MyVerStr;
struct Commands HCmds;
char *SkipdFiles;
char SystemPrompt[80];
int relogon;
int templogon;
int loadedmsg;
extern __far struct Library *DOSBase;
int RingCount;
struct MyEditor
{
  SHORT MaxFileLength;
  UBYTE MaxScrLength;
  UBYTE EditorTop;
  UBYTE EditorMaxWidth;
  ULONG EditorFlags;       // Flags for the editor, duh!
  char *EditorFile;
  char *EditorIncludeFile;
  char *EditorPrependFile;
  char *EditorPostPendFile;
};
extern struct MyEditor EditorStruct;

//UWORD pens[]= { 0,7,7,7,0,3,0,0,0,~0 };
//struct TagItem screentags[2];

void CheckDeadLine(ULONG myTime);
struct NewScreen MYNewScreen =
 {
 0,0,640,200,3,0,1,  /* leftedge,topedge,Width,Height,Depth,DetailPen, BlockPen */
 HIRES,CUSTOMSCREEN,NL,           /* display modes,screen type,Font */
 NL,NL,NL                           /* Title,screen gadgets,CustomBitMap  */
};

struct NewWindow MYNewWindow = {
  0,12,640, 188,      /* left edge, top edge, width, height */
  0, 1, NL,
  ACTIVATE|BACKDROP|BORDERLESS,
  NL, NL, NL, NL, NL, 70, 30, 704, 480, CUSTOMSCREEN
};

struct NewWindow PaneStatus =
{ 0,10,640,30,3,4, NL,SIMPLE_REFRESH,NL,NL,NL,NL,NL,0,0,640,40, CUSTOMSCREEN};

struct NewWindow CloseIt = {
  0,0,28,10,0,1,          /* 0,0,587,10,0,1 */
  GADGETUP|GADGETDOWN,NOCAREREFRESH|BORDERLESS,
  NL,NL,NL,NL,NL,0,0,640,40,CUSTOMSCREEN
};

struct Gadget MG =
 {NL,0,0,0,0,GADGHCOMP|GADGIMAGE,RELVERIFY, BOOLGADGET,NL,NL,NL,NL,0,NL};

/* this has to stay the same size since below we set the 20th pos to the node number */
#define OPENIT_WINTITLE  "AmiExpress BBS Node xxx"

struct NewWindow OpenIt = {
  0,11,300,23,0,1,            /* 0,0,587,10,0,1 */
  CLOSEWINDOW,WINDOWDRAG|WINDOWDEPTH|NOCAREREFRESH|WINDOWCLOSE,
  NL,NL,OPENIT_WINTITLE,         /* Convert to AmiExpress BBS Node xxx */
  NL,NL,0,0,640,40,WBENCHSCREEN
};

struct NewWindow ZmodemStats = {
  170,50,350,125,0,1,         /* 0,0,587,10,0,1 */
  CLOSEWINDOW,WINDOWDRAG|NOCAREREFRESH|WINDOWCLOSE,
  NL,NL,NL, NL,NL,0,0,350,130,CUSTOMSCREEN };


/* moved from flagfiles.c ..was static */
char *IsInList(char *s,char *c,int *length);  /* also used in check_list.c */

/* Stealth Mode, Requires STEALTH_MODE in the Node icon to activate */
/* This tells express to ask for the system password before displaying
   any connect messages 
*/

int Stealth=0;
int PhoneCheck;
int AddFlagtoList(char *s)
{
 char *p;
 int stat;
 if(strlen(s)>1) {
     strupr(s);
     strcat(s," ");
     if(strlen(flaglist)+strlen(s)>2040) {
         AEPutStr("Too many flags\r\n");
         return(1);
     }
     if(!(p=IsInList(flaglist,s,&stat)))     strcat(flaglist,s);
     return(2);
 }
 return(0);
}

 /* remove file from Nodework (normally t: dir) that tells who is online
 (each node )*/

static void ClearUser(void)

{

 sprintf(GSTR1,"%snode%ld.user",NodeWork,Cmds->AcLvl[LVL_NODE_NUMBER]);
 DeleteFile(GSTR1);

 sprintf(GSTR1,"%snode%ld.userkeys",NodeWork,Cmds->AcLvl[LVL_NODE_NUMBER]);
 DeleteFile(GSTR1);
}

static void Display_Logo(void)
{
 ConPutStr("\014[1;33m\n\n\n\n\n                               Express BBS[0m\n\n");
 ConPutStr("                             Initializing...");
}

static char PortName[30];  /* our MsgPort Name, Node # appended */

#define RN 37L            /* current library version */

static void Init_System(BYTE iconats)
{


if(iconats)
	{
     IconifySig=0L;
	KEYIN=0; 
	ICON=1;
	}
else
	{
     ICON=0;
	OpenDisplay();
	Display_Logo();
	}
 OpenTimer();
 TimerSig=1L<<TimerPort->mp_SigBit;

 MyClearStatusPane();     /* (RTS) clear status pane & install user */

if(!(HistoryBuf=(UBYTE *)AllocMem(MAXHIST*250,MEMF_CLEAR)))
     ShutDown("No memory for history");

 if(OpenSerial(Cmds->OpeningBaud,(UBYTE)8,(UBYTE)1)!=0) {
     sprintf(GSTR3,"Can't open %s!",Cmds->SerDev);
     ShutDown(GSTR3);
 }
 if(!TrapDoor)
 {
   IntDoReset(Sopt->OffHook);
   Delay(60L);
   SerPutStr(Cmds->MInit);
   SerPutChar('\r');
   Delay(60L);
 }
 PurgeLine();


}


struct DiskObject *ConfObj=NL;

extern struct myst my_struct;


extern int BatchError;        /**** BatchError Flg ****/

int SHUTBATCH = 0;

char WorkStr[255];

BOOL DupeYes = FALSE;
BOOL QuickAllowed = TRUE;
char SysopCommand[100];

/* end 11w */
void options(void);

int CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */

   /******************************************************************\
    *                              MAIN()                            *
   \******************************************************************/
char SingleName[] = "AEStat ";
extern unsigned long doorextsig;
int Valer=0;
struct Library *IconBase=NL;
void main(int argc,char *argv[])
{
  struct MsgPort *tempport;
  AnsiColor=1;
  tzset();
  mytask=(struct Process *)FindTask(NULL);
  doorextsig=AllocSignal(-1L);
  EditorStruct.EditorFlags=0L;
IO_Flags[IOFLAG_FIL_IN]=0;
PagedFlag=0;

 //screentags[0].ti_Tag=SA_Pens;
 //screentags[0].ti_Data=(ULONG)pens;
 //screentags[1].ti_Tag=TAG_DONE;
 //MYNewScreen.Extension=screentags;
 ComputerTypes[0] = NL;
 ComputerEntries = DeBuG = ShutDownFlag = ZWindow = OnlineEdit = SysopStatus= 
 NOFKeys = FreeDownloads = ICON = AWAITLOGON = ICONATS = TrueReset = 0;
 DStatBar=KEYIN=1;
 CaptureFP=NL;

 DOSBase=(struct Library *)OpenLibrary("dos.library",0L);
 if(!(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library",RN)))
       ShutDown("Can't open intuition.library");

 if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",RN)))
     ShutDown("Can't open  intuition.library");
 if(!(GadToolsBase=(struct Library *)OpenLibrary("gadtools.library",0L)))
     ShutDown("Can't open  GadToolsLibrary");
 if(!(UtilityBase = (struct UtilityBase *)OpenLibrary("utility.library",RN)))
     ShutDown("Can't open utility.library");

 if(!(RexxSysBase = (struct RexxSysBase *)OpenLibrary("rexxsyslib.library",0)))
     puts("rexxsyslib.library not found, AREXX port disabled\n");
  AslBase=OpenLibrary("asl.library",0L);
 IconBase=OpenLibrary("icon.library",0L);
  /*----------------------- Get our Config File ------------------------- */

 /**** store node number from commandline in the GSTR1 variable ****/
 strcpy(GSTR1,argv[1]);

 /**** allocate memory for storing skipped uploads ****/
 SkipdFiles=AllocMem(32000L,MEMF_CLEAR|MEMF_PUBLIC);
 
 /**** Initiate communication to ACP ****/
 CreateServerRP(argv[1][0]-'0');

 DoorSig=ResControl(Cmds->AcLvl[LVL_NODE_NUMBER]);
 
 LoadKey();
 Valer=DeCode();
 
 /**** If MultiCom port initialized in ACP then setup appropriate links ****/
 if(Sopt->Toggles[10])
 {
    SingleNode=(struct SinglePort *)Sopt->s;
    MasterNode=(struct MultiPort *)Sopt->t;
 }
/** see if we already exist */
 /*-- Get out port name and check if we are already running --*/
 sprintf(PortName,"%s%d",PORT_NAME,Cmds->AcLvl[LVL_NODE_NUMBER]);  /* cfg port */

 if(tempport=FindPort(PortName)) {
     sprintf(GSTR3,"Node %d already running!\n",Cmds->AcLvl[LVL_NODE_NUMBER]);
     ShutDown(GSTR3);
 }

 if(!(MyRexxPort=(struct MsgPort *) CreatePort(PortName,0L))) {
     sprintf(GSTR3,"Can't create Port: %s",PortName);
     ShutDown(GSTR3);
 }

 RexxSig = 1L << MyRexxPort->mp_SigBit;

 Online_Baud = Online_BaudR=Cmds->OpeningBaud;   

 /**** See if we need to use STEALTH_MODE ****/
 sprintf(NodeStr,"%sNode%u",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);
 Stealth=IsFromIcon(NodeStr,"STEALTH_MODE"); 
 if(!GetFromIconStr(NodeStr,"SYS_PWRD_PROMPT",SystemPrompt)) strcpy(SystemPrompt,">: ");

 /**** Setup upload path ****/
 sprintf(NodeStr,"%sNode%u/",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);

  /** * * FIX WHEN TITLE CHANGES  suppose the file string is shorter then 20 ? */
 sprintf(OpenIt.Title+20,"%03d",Cmds->AcLvl[LVL_NODE_NUMBER]);

 /**** Check to see if we are running AmiXnet ****/
 sprintf(GSTR1,"%sAmiXnet/MyNode",Cmds->BBSLoc);
 if(!GetFromIconStr(GSTR1,"NODE.ID",Sopt->BBSConfig)) strcpy(Sopt->BBSConfig,"");
 /**** Determine Max number of conferences ****/
 sprintf(GSTR1,"%sConfConfig",Cmds->BBSLoc);
 Boards_Are_Active=IntFromIcon(GSTR1,"NCONFS");

 /**** Allocate and load all CONFERENCE ICONS into memory for quick reference ****/
 ConfObj=GetDiskObject(GSTR1);
 AllocateConfs(Boards_Are_Active);

 strcpy(NodeWork,Cmds->BBSLoc);

 if(!Sopt->StatBar) DStatBar=0;

 sprintf(UserDataLoc,"%sUser.Data",Cmds->BBSLoc);
 sprintf(UserKeyLoc,"%sUser.keys",Cmds->BBSLoc);

 if(Sopt->OffHook[0]=='\0')
 {
    strcpy(Sopt->OffHook,"ATM0H1");
 }
 

 BitPlanes=Sopt->BitPlanes;

if(Sopt->TrapDoor){ TrapDoor=TRUE; sprintf(TrapConnect,"CONNECT %ld",atol(argv[2]));}

	if(BitPlanes>4||BitPlanes<0)
		{
		BitPlanes=3;
		}
		MYNewScreen.LeftEdge=(UWORD)Sopt->LeftEdge;
		MYNewScreen.TopEdge=(UWORD)Sopt->TopEdge;
		MYNewScreen.Width=(UWORD)Sopt->Width;
		MYNewScreen.Height=(UWORD)Sopt->Height;
		MYNewWindow.Height=MYNewScreen.Height-MYNewWindow.TopEdge;
		MYNewWindow.Width=MYNewScreen.Width;
		PaneStatus.Width=MYNewScreen.Width;
          if(Sopt->Toggles[6]){
              MYNewScreen.BlockPen=7;
              MYNewWindow.BlockPen=7;
           }
		if(MYNewScreen.Height>399&&BitPlanes!=0)
			{
			MYNewScreen.ViewModes=MYNewScreen.ViewModes|LACE;
			if(BitPlanes>4)
				{
				BitPlanes=4;
				}
			}
	if(BitPlanes==0)
		{
		PaneStatus.Height+=11;
		ZmodemStats.Type=WBENCHSCREEN;
    
		PaneStatus.Type=WBENCHSCREEN;
		CloseIt.Type=WBENCHSCREEN;
		MYNewWindow.Type=WBENCHSCREEN;
		MYNewWindow.LeftEdge=MYNewScreen.LeftEdge;
		MYNewWindow.Width=MYNewScreen.Width;
		PaneStatus.TopEdge=MYNewScreen.TopEdge;
            MYNewWindow.TopEdge=MYNewScreen.TopEdge;
            MYNewWindow.Height=MYNewScreen.Height;
		PaneStatus.LeftEdge=MYNewScreen.LeftEdge;
		CloseIt.TopEdge=MYNewScreen.TopEdge;
		CloseIt.LeftEdge=MYNewScreen.LeftEdge;
          ZmodemStats.LeftEdge=MYNewWindow.LeftEdge+(MYNewWindow.Width/4);
          ZmodemStats.TopEdge=MYNewWindow.TopEdge+(MYNewWindow.Height/4);
		}
	if(BitPlanes<2)
		{
		PaneStatus.DetailPen=0;
		PaneStatus.BlockPen=1;
		}

 sprintf(WorkStr,"%sNode%u/Work/",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);

 Forbid();
 SetTaskPri(FindTask(0),(LONG)Cmds->TaskPri);
 Permit();

 my_struct.max_desclines = 8;
 my_struct.numlastcallers = 0;
 my_struct.flags = 0;
 my_struct.lastcallerlevel = 255;
 my_struct.callerlist = NL;


if(Sopt->ShutDown[0]!=NULL) { SHUTBATCH=1;  }

if(Sopt->Interlace) { MYNewScreen.ViewModes=MYNewScreen.ViewModes|LACE; }

if(Sopt->QLogon) QuickAllowed=FALSE;

if(Sopt->TakeCredits) TakeCredits=TRUE;

if(Sopt->Iconify) ICONATS=1; else ICONATS=0;

if(Sopt->Toggles[0]) TrueReset=TRUE;

if(Sopt->Toggles[1]) NotRelative=FALSE;

/****** Toggles[2]=DoorLog 
        Toggles[3]=StartLog
        Toggles[4]=No TimeOut
        Toggles[5]=No MCI Msgs
*******/

sprintf(GSTR1,"%snode%d.user",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);

if(TLock(GSTR1)) DeleteFile(GSTR1);

 /**** Determine if RINGCOUNT option is selected ****/
sprintf(GSTR1,"%sNode%d",Cmds->BBSLoc,Cmds->AcLvl[LVL_NODE_NUMBER]);
 RingCount=IntFromIcon(GSTR1,"RINGCOUNT");
 if(RingCount==0) RingCount=1;
 PhoneCheck=IsFromIcon(GSTR1,"PHONECHECK");
 ClearOveride();
sprintf( titlebar,"    AmiExpress BBS (c)%s  %s                      Node %ld",GetDate(),MyVerStr,Cmds->AcLvl[LVL_NODE_NUMBER]);
sprintf(ptitlebar,"       AmiExpress BBS (c)%s  %s                      Node %ld",GetDate(),MyVerStr,Cmds->AcLvl[LVL_NODE_NUMBER]);

if(BitPlanes!=0)
	{
	MYNewScreen.DefaultTitle=(UBYTE *)&titlebar;
	}
else
	{
	  PaneStatus.Title=(UBYTE *)&ptitlebar; // Used in 0 bitplanes(JOE)
     MYNewWindow.Title=(UBYTE *)&titlebar;
	}


 Randomize();   /* 11w Check for Cycle Screens */
                                //(RTS)
 if(!(ReadComputerTypes()))     ShutDown("Computer Types Error");
                  /* Read in callers log to process for last callers util */

 SySChat=Cmds->AcLvl[LVL_DEFAULT_CHAT_ON];      /* set Sysop Chat Mode */
 if(Sopt->Toggles[9]) { QuietNode=TRUE; SendQuietFlag(1); }
                        else { QuietNode=FALSE; SendQuietFlag(0); }
 /* get top uploader/download cps */

 Startup_Time=time(NL);
 
 sprintf(GSTR1,ctime(&Startup_Time));
 GSTR1[strlen(GSTR1)-1]='\0';
 sprintf(GSTR2,"####### BBS Node %d started on %s #######\n",Cmds->AcLvl[LVL_NODE_NUMBER],GSTR1);
 StartLog(GSTR2);
 Init_System(ICONATS);
 relogon=0; templogon=0;
 //CheckDeadLine(Startup_Time);
 FOREVER {
 
    

     if(!TrapDoor){ Reset_System(1); }

     MCIViewSafe=TRUE;


     Whence_The_Logon=AWAIT_LOGON;
    if(Cmds->AcLvl[29]) ADD_BIT(ACS_DO_CALLERSLOG);
       if(Sopt->Toggles[14]) ADD_BIT(ACS_WILDCARDS);
     Whence_The_Logon=Await_Logon();   /* User logged on system */
     if(Whence_The_Logon==REMOTE_LOGON) SetEnvStat(ENV_CONNECT);
Relogon:
     strcpy(User.Pass,"");
     EditorStruct.EditorFlags=0L;
     User.LineLength=24;
     strcpy(Conference_Location,"");
     loadedmsg=0;
     BeenUDd=LogON=0;
     ValidUser=2;
     NumHistItems=0;
     WhichHist=0;
     HistorySelect=0;
     Time_limit=1800L;
     Time_holder=0;
     strcpy(flaglist,"");
     strcpy(GSTR1,Cmds->BBSLoc);
	strcat(GSTR1,"SystemStats");
	System_Calls=IntFromFile(GSTR1,GSTR2);
	System_Calls++;
	IntToFile(GSTR1,System_Calls);
     if(relogon) { Whence_The_Logon=templogon; relogon=0; }
     BatchError = 0;

     NewSinceFlag=0;
    if(TrapDoor) Whence_The_Logon=REMOTE_LOGON;
     templogon=Whence_The_Logon;
     switch(Whence_The_Logon) {
         case SYSOP_LOGON:
             Sysop_Account_Sequence();
             ValidUser=1;
             CheckUserOnLine(&User,0);
             break;
         case LOCAL_LOGON:
         case REMOTE_LOGON:
             if(KEYIN&&Cmds->AcLvl[LVL_SCREEN_TO_FRONT]&&MYScreen)    ScreenToFront(MYScreen);
             GI1=Logon_Sequence();      /* User logged on SYstem */
             if(GI1!=SUCCESS) {
                goto Skip;
             }
             break;
         case SUSPEND_LOGON:
             goto DownUnder;
     }                        /* end switch */

sprintf(GSTR1,"%sScreenTypes",Cmds->BBSLoc);
         sprintf(GSTR2,"TITLE.%d",User.ScreenType+1);
         GetFromIconStr(GSTR1,GSTR2,langtitle);
         sprintf(GSTR2,"TYPE.%d",User.ScreenType+1);
         GetFromIconStr(GSTR1,GSTR2,lang);
/*---11w Cycle screens --- */
 if(QuickFlag) goto byp;
if(User.Sec_Status > Cmds->PSAcLvl[0] && Whence_The_Logon!=SYSOP_LOGON) {
             sprintf(GSTR1,"%sLogon",Sopt->NodeScreen);
     
     if(ChecktoDisplay(GSTR1,GSTR3,1,0)) DoPause();
  }
/*--- end 11w cycle screens --- */

//--------------------------------------------------------
byp: ;

     GI1=Menu();
                      /*  RTS  OUR MAIN ONLINE USER LOOP */
     SetEnvStat(ENV_NOTACTIVE);
     if(CaptureFP) {
         fclose(CaptureFP);
         CaptureFP=NL;
     }
     Check_Online_Status();
     ChatFlag=0;
     flaglist[0]='\0';

 Skip:
     ClearUser();


     if(ValidUser!=2) {

         if(ValidUser==3)    (void)LogOffLog("UUCP feed completed");
         else  {
             if(GI1==STANDARD_LOGOFF)    LogOffLog("N");
              else   LogOffLog("Loss Carrier");
         }
     }
     if(User.Sec_Status!=0 && User.Slot_Number!=0 && ValidUser==1) {

         PagedFlag=0;
         if(SysopStatus) {
             User.Sec_Status=TSI.AccessLevel;
             User.Sec_Board=TSI.RatioType;
             User.Sec_Library=TSI.Ratio;
             User.Time_Total=TSI.TimeTotal;
             memcpy(User.Conference_Access,TSI.ConfAc,10);
             SysopStatus=0;
         }
         StatPrintUser(&User);
        
         strcpy(User_keys.UserName,User.Name);
         strupr(User_keys.UserName);
         User_keys.Number=User.Slot_Number;

         if(NewSinceFlag) {
             User.NewSinceDate=time(NL);
             
         }
          SaveMsgPointers(CN);
          NewSinceFlag=0;
          User.Time_Last_On=time(NULL);
         AddMsgPointers();
         if(loadedmsg) MasterSavePointers();
         Save_Account(&User,&User_keys,0,0);    /* Reseave users account after logoff */


         ReservedName[0]='\0';
         if(relogon) 
         {
           sprintf(GSTR1,"%sCommands/SysCmd/",Cmds->BBSLoc);
         strcpy(GSTR2,"RELOGON");
         CustomCommand(GSTR1,GSTR2,1);
          sprintf(GSTR1,"%sCommands/SysCmd/",Cmds->BBSLoc);
         sprintf(GSTR2,"RELOGON%d",Cmds->AcLvl[LVL_NODE_NUMBER]);
         CustomCommand(GSTR1,GSTR2,1);
        goto Relogon;
         }
         if(KEYIN&&Cmds->AcLvl[LVL_SCREEN_TO_FRONT]&&MYScreen)
         {   ScreenToBack(MYScreen);}
             ModemOffHook();
                
         sprintf(GSTR1,"%sCommands/SysCmd/",Cmds->BBSLoc);
         strcpy(GSTR2,"LOGOFF");
         CustomCommand(GSTR1,GSTR2,1);
         sprintf(GSTR1,"%sCommands/SysCmd/",Cmds->BBSLoc);
         sprintf(GSTR2,"LOGOFF%d",Cmds->AcLvl[LVL_NODE_NUMBER]);
         CustomCommand(GSTR1,GSTR2,1);
         
     }
DownUnder:
     CheckShutDown();
    if(TrapDoor) ShutDown("!");
 }
}

void CheckShutDown(void)
{
 if(ShutDownFlag==1) {
            ReplyMsg((struct Message *) SDReplyRexx);
     ShutDown("!");
 }
 if(ShutDownFlag==2) {
         ReplyMsg((struct Message *) SReplyRexx);
         SuspendBBS();
         Display_Logo();
         ReInitModem();
  }
  ShutDownFlag=0;
}


void SuspendBBS(void)
{
 BYTE LICON;

 Whence_The_Logon=SUSPEND_LOGON;
 LICON=ICON;

 if(!ICON) {
    IconifyAE();
 }

/* ... Skipped ALL thist !!!! DID NOT WAUT */
 if(SEROUT && ReadSerReq) {
     AbortIO(ReadSerReq);
     WaitIO(ReadSerReq);
 }
 CloseSerial();

 Time_system=time(NL);

 sprintf(GSTR3,"BBS has been suspended at %s",ctime(&Time_system));
 StartLog(GSTR3);

 while(Whence_The_Logon==SUSPEND_LOGON) {
     Wait(RexxSig);
     CheckRexxMessage();
 }
 Time_system=time(NL);

 sprintf(GSTR3,"BBS has received resume @ %s",ctime(&Time_system));
 StartLog(GSTR3);

 if(OpenSerial(Cmds->OpeningBaud,(UBYTE)8,(UBYTE)1)!=0) {
     sprintf(GSTR3,"Can't re-open %s!",Cmds->SerDev);
     ShutDown(GSTR3);
 }


 if(!LICON)  {  /* got msg to LICON this (Uniconify this */
    UnIconifyAE(0);
 }


}

static void closelibs(void)
{
 DeAllocateConfs();

 if(IconBase)                CloseLibrary(IconBase);
 if(AslBase)                 CloseLibrary(AslBase);
 if(UtilityBase)             CloseLibrary((struct Library *) UtilityBase);
 if(RexxSysBase)             CloseLibrary((struct Library *) RexxSysBase);
 if(GadToolsBase)            CloseLibrary((struct Library *) GadToolsBase);
 if(GfxBase)                 CloseLibrary((struct Library *) GfxBase);
 if(IntuitionBase)           CloseLibrary((struct Library *) IntuitionBase);
  CloseLibrary(DOSBase);
}

void ShutDown(char *s)
{
 BPTR tempfh;
 struct RexxMsg *rexxmsg=NL;
 Startup_Time=time(NL);
 sprintf(GSTR1,ctime(&Startup_Time));
 GSTR1[strlen(GSTR1)-1]='\0';
 SetEnvStat(ENV_SHUTDOWN); Delay(10L);

 sprintf(GSTR2,"####### BBS Node %d shutdown @ %s#######\n",Cmds->AcLvl[LVL_NODE_NUMBER],GSTR1);
 StartLog(GSTR2);
 if(SHUTBATCH) {
    sprintf(GSTR1,"execute %s %d",Sopt->ShutDown,Cmds->AcLvl[LVL_NODE_NUMBER]);
    if(tempfh=Open("NIL:",MODE_OLDFILE))     {
         Execute(GSTR1,tempfh,tempfh);
         Close(tempfh);
    }
}
 if(ComputerTypes[0]!=NL)     FreeMem(ComputerTypes[0],ComputerEntries*90);
 if(HistoryBuf)               FreeMem(HistoryBuf,MAXHIST*250);

 if(MyRexxPort) {
     while(rexxmsg = (struct RexxMsg *) GetMsg((struct MsgPort *) MyRexxPort))
       ReplyMsg((struct Message *) rexxmsg);
     DeletePort((struct MsgPort *) MyRexxPort);
 }
 FreeDiskObject(ConfObj);

 DeleteServerRP();
 DeleteResControl();

 if(!ICON)  CloseConsole();
 if(SEROUT) CloseSerial();
  CloseTimer();
 FreeSignal(doorextsig);
 if(Iconify){ CloseWindow(Iconify);}
 if(StatusPane && DStatBar) { CloseWindow(StatusPane); }
 if(MYwindow) { CloseWindow(MYwindow);}
 if(BitPlanes!=0)
 {
 if(closeimage) DisposeObject(closeimage);
 if(drinfo) FreeScreenDrawInfo(MYScreen, drinfo);
 if(MYScreen) CloseScreen(MYScreen); 
 }
 FreeMem(SkipdFiles,32000L);
 closelibs();              /* closes All Libraries open */

 exit(0);
}

void ModemOffHook(void)
{
   if(Cmds->SerDev[0]!='\0')
                 {
                   
                  if(Sopt->Toggles[17])
                 {
                   Reset_System(0);
				IntDoReset(Sopt->OffHook);
				IO_Flags[IOFLAG_SER_IN]=0;
				IO_Flags[IOFLAG_SER_OUT]=0;
				IO_Flags[IOFLAG_SCR_OUT]=1;
				IO_Flags[IOFLAG_KBD_IN]=1;
                 }else
                 {
                   DropDTR();Delay(25L);//Reset_System(0);
                   IntDoReset(Sopt->OffHook);
                   Delay(5L);
                   Dropped_Hook=1;
                 IO_Flags[IOFLAG_SER_IN]=0;
                 IO_Flags[IOFLAG_SER_OUT]=0;
                 IO_Flags[IOFLAG_SCR_OUT]=1;
                 IO_Flags[IOFLAG_KBD_IN]=1;
                 }
                 }
}

struct MyConfBase
{
  struct MinNode l;
  struct ConfBase CB;
};

void AllocateConfs(int NumConfs)
{
   register int i;
   char image[100];
   char image1[100];
   struct DiskObject *dobj;
   struct MyConfBase *confbase;
   ConfDBList=AllocMem(sizeof(struct List),MEMF_CLEAR);
   NewList(ConfDBList);
   MemConf=(ULONG *)AllocMem(((ULONG)NumConfs+1L)*(ULONG)sizeof(ULONG),MEMF_CLEAR|MEMF_PUBLIC);
   for(i=0;i<NumConfs;i++)
   {
     confbase=AllocMem(sizeof(struct MyConfBase),MEMF_CLEAR);
     AddHead((struct List *)ConfDBList,(struct Node *)confbase);
     GetConfName(image1,image,i);
       image[strlen(image)-1]='\0';
       dobj=GetDiskObject(image);
       if(dobj==NULL)
       {
         sprintf(GSTR1,"\tError cannot locate conference icon %s\n",image);
         CallersLog(GSTR1);
         SetEnvMsg("FATAL ERROR");
         exit(0);
       }
       
       //*(MemConf+(ULONG)i)=(ULONG)dobj;
       MemConf[i]=(ULONG)dobj;
   }
   //*(MemConf+(ULONG)i)=NULL;
   MemConf[i]=NULL;
}

void DeAllocateConfs(void)
{
   register int i=0;
   struct DiskObject *dobj;
   struct MyConfBase *it;
   struct MyConfBase *tt;
   if(MemConf)
   {
   while(*(MemConf+(ULONG)i)!=NULL)
   {
     //dobj=(struct DiskObject *)*(MemConf+(ULONG)i);
     dobj=(struct DiskObject *)MemConf[i];
     FreeDiskObject(dobj);
     i +=1;
   }
   i +=1;
   FreeMem(MemConf,(ULONG)i*(ULONG)sizeof(ULONG));
   it=(struct MyConfBase *)(ConfDBList->lh_Head);
   while(tt=(struct MyConfBase *)(it->l.mln_Succ))
   {
      FreeMem(it,sizeof(struct MyConfBase));
      it=tt;
   }
   FreeMem(ConfDBList,sizeof(struct List));
  }
}

#define NumVersion 301L
struct EnCode
{
  UBYTE TAG[6];
  ULONG Sysop[40];
  ULONG BBSName[50];
  ULONG RealName[40];
  ULONG Location[40];
  ULONG LocationLength;
  ULONG RealNameLength;
  ULONG SerialNumber;
  ULONG Version;
  ULONG SysopLength;
  ULONG BBSNameLength;
  ULONG RegNum;
  ULONG TotalReg;
};

struct EnCode BBSid;
char seccode[65];
ULONG KeyName[] = { 1100L,1119L,1111L,1113L,1100L,1114L,1114L,1045L,1106L,1100L,1120L,0L };
int DeCode(void)
{
   register int i;
   ULONG totalsize=0L;
   char string[200];
   i=0;
   if(Valer==-1) { dumfunc=(&ConPutStr); return(0); }
   while(i<BBSid.SysopLength)
   {
     //Cmds->SysopName[i]=BBSid.Sysop[i]-BBSid.RegNum;
     totalsize +=BBSid.Sysop[i];
     i++;
   }
   Cmds->SysopName[i]='\0';
   i=0;
   while(i<BBSid.RealNameLength)
   {
     totalsize +=BBSid.RealName[i];
     i++;
   }
   i=0;
   while(i<BBSid.BBSNameLength)
   {
     Cmds->BBSName[i]=BBSid.BBSName[i]-BBSid.RegNum;
     totalsize +=BBSid.BBSName[i];
     i++;
   }
   Cmds->BBSName[i]='\0';
   if(BBSid.Version-BBSid.RegNum!=NumVersion){ dumfunc=(&ConPutStr); return(0); }
   if(totalsize!=BBSid.TotalReg || totalsize==0 )
   {
     dumfunc=(&ConPutStr);
     //secfunc(&dumfunc,&ConPutStr); 
     return(0);
   }
   dumfunc=(&SerPutStr);
   //secfunc(&dumfunc,&SerPutStr); 
   return(1);
}

void LoadKey(void)
{
   FILE *fi;
   register int i;
   char string[200];
   char temp[200];
   i=0;
   while(KeyName[i]!=0L)
   {
     temp[i]=(char)(KeyName[i]-999L);
     i++;
   }
   temp[i]='\0';
   sprintf(string,"%s%s",Cmds->BBSLoc,temp);
   fi=fopen(string,"rb");
   if(fi==NULL) { Valer=-1; return; }

   fread((APTR)&(BBSid.Sysop),sizeof(struct EnCode)-6L,1,fi);
   //fread((APTR)&seccode[0],64,1,fi);
  
   
   BBSid.RegNum -=(ULONG)(sizeof(struct EnCode)+20);
   fclose(fi);
   //CacheClearU();
   //secfunc=&seccode[0];
}
void CheckDeadLine(ULONG num)
{
  if(num>deadtime)
    ShutDown("!");
}