#include <CrashTick.h>

#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>

#include <rexx/rxslib.h>
#include <rexx/errors.h>

#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/locale_protos.h>
#include <clib/alib_protos.h>
#include <clib/rexxsyslib_protos.h>

#define STACKSIZE 10000

const UBYTE ver[]="\0$VER: CrashTick "VERSION" ("__COMMODORE_DATE__")";

uchar *config_version="CrashTick "VERSION;
struct Config config;

/* Prototypes */

short Init(uchar *errbuf);

/* Variables */

#define ARG_TICK         0
#define ARG_HATCH        1
#define ARG_MAINT        2
#define ARG_RAID         3

#define ARG_SETTINGS     4
#define ARG_WAIT         5
#define ARG_QUIT         6

#define ARG_AREA         7
#define ARG_DESCRIPTION  8
#define ARG_REPLACE      9
#define ARG_MAGIC       10


#define ARG_SENDQUERY    11
#define ARG_SENDUNLINKED 12
#define ARG_SENDLIST     13
#define ARG_SENDHELP     14
#define ARG_SENDINFO     15

#define MAXARG           16

LONG argarray[MAXARG];
UBYTE argstr[]   = "TICK/S,HATCH/K,MAINT/S,RAID/K,SETTINGS/K,WAIT/S,QUIT/S,AREA/K,"
                   "DESCRIPTION=DESC/K,REPLACE/K,MAGIC/K,"
                   "SENDQUERY=NOTIFY/K,SENDUNLINKED/K,SENDLIST/K,SENDHELP/K,SENDINFO/K";

struct RDArgs *rdargs;

struct Library *LocaleBase;
struct Catalog *catalog;

void *mempool;

extern struct ExecBase *SysBase;

struct RxsLib *RexxSysBase;
struct MsgPort *rexxport;

short initlogtask,initconfig,initunattended;

void RexxPort(void);
void HandleRexxMessages(void);
short SendRexx(uchar *port,uchar *command);

ulong DayStatsWritten;

uchar hatcharea[100],hatchdesc[100],hatchreplace[100],hatchmagic[30];

__asm void (*own_StackSwap)(register __A0 struct StackSwapStruct *newstack,register __A6 struct Library *library);
struct StackSwapStruct stackswapstruct;

short input(uchar *prompt,uchar *dest,ulong maxlen)
{
   Printf("%s: ",prompt);
   Flush(Output());
   FGets(Input(),dest,maxlen-1);
   dest[maxlen-1]=0;

   if(dest[strlen(dest)-1] == '\n')
      dest[strlen(dest)-1]=0;

   return (short)strlen(dest);
}

void realmain(void)
{
   short res;
   uchar errorbuf[100];

   initlogtask=FALSE;
   initconfig=FALSE;
   initunattended=FALSE;

   if(!(rdargs=(struct RDArgs *)ReadArgs(argstr,argarray,NULL)))
   {
      PrintFault(IoErr(),NULL);
      CleanUp(10);
   }

   if(LocaleBase=OpenLibrary("locale.library",37))
   {
      catalog=OpenCatalog(NULL,"crashtick.catalog",OC_BuiltInLanguage, "english",
                                                                       OC_Version,  2L,
                                                                       TAG_DONE );
   }

   if(!(mempool=LibCreatePool(MEMF_ANY,10000,1000)))
   {
      printf("%s\n",getString(ERR_NO_MEMORYPOOL));
      CleanUp(10);
   }

   if(!(RexxSysBase=(struct RxsLib *)OpenLibrary(RXSNAME,0)))
   {
      printf("%s\n",getString(ERR_NO_REXXSYSLIB));
      CleanUp(10);
   }

   if(argarray[ARG_HATCH] && !argarray[ARG_AREA])
   {
      printf("\n");
      printf(getString(TXT_HATCH_HATCHING),argarray[ARG_HATCH]);
      printf("\n\n");

      if(!input(getString(TXT_HATCH_AREA),hatcharea,100))
      {
         printf("%s\n",getString(TXT_HATCH_ABORTED));
         CleanUp(0);
      }

      if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
         CleanUp(0);

      input(getString(TXT_HATCH_DESCRIPTION),hatchdesc,100);

      if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
         CleanUp(0);

      input(getString(TXT_HATCH_REPLACE),hatchreplace,100);

      if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
         CleanUp(0);

      input(getString(TXT_HATCH_MAGIC),hatchmagic,30);

      if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
         CleanUp(0);

      printf("\n");
   }
   else if(argarray[ARG_HATCH])
   {
      strncpy(hatcharea,(uchar *)argarray[ARG_AREA],99);

      if(argarray[ARG_DESCRIPTION])
         strncpy(hatchdesc,(uchar *)argarray[ARG_DESCRIPTION],99);

      if(argarray[ARG_REPLACE])
         strncpy(hatchreplace,(uchar *)argarray[ARG_REPLACE],99);

      if(argarray[ARG_MAGIC])
         strncpy(hatchmagic,(uchar *)argarray[ARG_MAGIC],30);

      hatcharea[99]=0;
      hatchdesc[99]=0;
      hatchreplace[99]=0;
   }

   if(hatchdesc[0] == 0)
      strcpy(hatchdesc,"No description");

   Forbid();

   if(rexxport=(struct MsgPort *)FindPort("CRASHTICK"))
   {
      short res;
      uchar sendbuf[300],buf[200];

      Permit();

      printf("%s\n",getString(TXT_PASSING_ON_COMMANDS));
      rexxport=NULL;

      res=0;

      if(argarray[ARG_QUIT])
      {
         res=SendRexx("CRASHTICK","QUIT");
      }
      else if(argarray[ARG_TICK])
      {
         res=SendRexx("CRASHTICK","TICK");
      }
      else if(argarray[ARG_MAINT])
      {
         res=SendRexx("CRASHTICK","MAINT");
      }
      else if(argarray[ARG_HATCH])
      {
         sprintf(sendbuf,"HATCH \"%s\" AREA \"%s\"",argarray[ARG_HATCH],hatcharea);

         if(hatchdesc[0])
         {
            sprintf(buf," DESC \"%s\"",hatchdesc);
            strcat(sendbuf,buf);
         }

         if(hatchreplace[0])
         {
            sprintf(buf," REPLACE \"%s\"",hatchreplace);
            strcat(sendbuf,buf);
         }

         if(hatchreplace[0])
         {
            sprintf(buf," MAGIC \"%s\"",hatchmagic);
            strcat(sendbuf,buf);
         }

         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_SENDQUERY])
      {
         sprintf(sendbuf,"SENDQUERY %s",argarray[ARG_SENDQUERY]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_SENDLIST])
      {
         sprintf(sendbuf,"SENDLIST %s",argarray[ARG_SENDLIST]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_SENDUNLINKED])
      {
         sprintf(sendbuf,"SENDUNLINKED %s",argarray[ARG_SENDUNLINKED]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_SENDINFO])
      {
         sprintf(sendbuf,"SENDINFO %s",argarray[ARG_SENDINFO]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_SENDHELP])
      {
         sprintf(sendbuf,"SENDHELP %s",argarray[ARG_SENDHELP]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else if(argarray[ARG_RAID])
      {
         sprintf(sendbuf,"RAID %s",argarray[ARG_RAID]);
         res=SendRexx("CRASHTICK",sendbuf);
      }
      else
      {
         printf("%s\n",getString(ERR_NOTHING_TO_PASS_ON));
      }

      Permit();
      CleanUp(res);
   }

   if(argarray[ARG_QUIT])
   {
      printf("%s\n",getString(ERR_NO_OTHER_COPY_IS_RUNNING));
      Permit();
      CleanUp(10);
   }

   if(!(rexxport=(struct MsgPort *)CreatePort("CRASHTICK",0)))
   {
      printf("%s\n",getString(ERR_OUT_OF_MEMORY));
      Permit();
      CleanUp(10);
   }

   Permit();

   InitConfig(&config);
   initconfig=TRUE;

   if(!argarray[ARG_SETTINGS])
   {
      ulong cfgline;
      short res,seconderr;

      if(!(res=ReadConfig("PROGDIR:CrashTick.prefs",&config,&seconderr,&cfgline,errorbuf)))
      {
         if(seconderr == READCONFIG_NOT_FOUND)
            res=ReadConfig("MAIL:CrashTick.prefs",&config,&seconderr,&cfgline,errorbuf);
      }

      if(!res)
      {
         if(seconderr == READCONFIG_INVALID)
         {
            printf(getString(CFG_ERR_CONFIG_ERR_IN_LINE),cfgline);
            printf(": %s\n",errorbuf);
         }
         else if(seconderr == READCONFIG_NO_MEM)
         {
            printf("%s\n",getString(ERR_OUT_OF_MEMORY));
         }
         else
         {
            printf("%s\n",getString(CFG_ERR_NO_CONFIG));
         }
         CleanUp(10);
      }
   }
   else
   {
      short seconderr;
      ulong cfgline;

      if(!ReadConfig((uchar *)argarray[ARG_SETTINGS],&config,&seconderr,&cfgline,errorbuf))
      {
         if(seconderr == READCONFIG_INVALID)
         {
            printf(getString(CFG_ERR_CONFIG_ERR_IN_LINE),cfgline);
            printf(": %s\n",errorbuf);
         }
         else if(seconderr == READCONFIG_NO_MEM)
         {
            printf("%s\n",getString(ERR_OUT_OF_MEMORY));
         }
         else
         {
            printf(getString(CFG_ERR_NO_CONFIG_NAME),argarray[ARG_SETTINGS]);
            printf("\n");
         }
         CleanUp(10);
      }
   }

   if(!CheckConfig(&config,errorbuf))
   {
      printf("%s",getString(CFG_ERR_CONFIG_ERROR));
      printf(": %s\n",errorbuf);
      CleanUp(10);
   }

   if(!(Init(errorbuf)))
   {
      printf("%s\n",errorbuf);
      CleanUp(10);
   }

   if(!ReadStats())
   {
      /* Error is logged inside ReadStats() */
      CleanUp(10);
   }

   LogWrite(2,SYSTEMINFO,getString(TXT_CRASHTICK_STARTED),VERSION);

   res=0;

   if(argarray[ARG_HATCH])
      res=Hatch((uchar *)argarray[ARG_HATCH],hatcharea,hatchdesc,hatchreplace,hatchmagic);

   if(argarray[ARG_RAID])
      res=Raid((uchar *)argarray[ARG_RAID]);

   if(argarray[ARG_SENDINFO])
      res=SendAFList(SENDLIST_INFO,(uchar *)argarray[ARG_SENDINFO]);

   if(argarray[ARG_SENDQUERY])
      res=SendAFList(SENDLIST_QUERY,(uchar *)argarray[ARG_SENDQUERY]);

   if(argarray[ARG_SENDLIST])
      res=SendAFList(SENDLIST_FULL,(uchar *)argarray[ARG_SENDLIST]);

   if(argarray[ARG_SENDUNLINKED])
      res=SendAFList(SENDLIST_UNLINKED,(uchar *)argarray[ARG_SENDUNLINKED]);

   if(argarray[ARG_SENDHELP])
      res=SendAFList(SENDLIST_HELP,(uchar *)argarray[ARG_SENDHELP]);

   if(argarray[ARG_TICK])
      res=Tick();

   if(argarray[ARG_MAINT])
      res=Maint();

   /* If any have arrived already... */

   HandleRexxMessages();

   if(argarray[ARG_WAIT])
   {
      RexxPort();
      HandleRexxMessages(); /* Just to be on the safe side */
   }

   CleanUp(res);
}

void main(void)
{
   struct Process *myproc;

   if(SysBase->LibNode.lib_Version<37)
   {
      printf("Sorry, you need at least Kickstart 2.04 to run CrashTick\n");
      exit(10);
   }

   myproc=FindTask(NULL);

   if(myproc->pr_Task.tc_SPUpper-myproc->pr_Task.tc_SPLower < STACKSIZE)
   {
      /* Only allocate new stack if original stack smaller */

      if(!(stackswapstruct.stk_Lower = AllocMem(STACKSIZE,MEMF_PUBLIC)))
      {
         Printf("Failed to allocate memory for new stack\n");
         exit(10);
      }

      stackswapstruct.stk_Upper   = (ULONG)stackswapstruct.stk_Lower + STACKSIZE;
      stackswapstruct.stk_Pointer = (APTR)stackswapstruct.stk_Upper;

      /* This trick is needed, otherwise DICE will use stack when swapping... */

      own_StackSwap=(void *)((ULONG)SysBase-(ULONG)732);
      (*own_StackSwap)(&stackswapstruct,(struct Library *)SysBase);
   }
   
   realmain();
}

APTR oldwinptr;

short Init(uchar *errbuf)
{
   oldwinptr=NULL;

   if(config.cfg_Flags & CFG_UNATTENDED)
   {
      struct Process *myproc;

      initunattended=TRUE;
      myproc=(struct Process *)FindTask(NULL);
      oldwinptr=myproc->pr_WindowPtr;
      myproc->pr_WindowPtr=(APTR)-1;
   }

   if(!(initlogtask=InitLogWrite()))
   {
      strcpy(errbuf,getString(ERR_FAILED_TO_INIT_LOGTASK));
      return(FALSE);
   }

   return(TRUE);
}

void Free(void)
{
   if(initunattended)
   {
      struct Process *myproc;

      myproc=(struct Process *)FindTask(NULL);
      myproc->pr_WindowPtr=oldwinptr;
      initunattended=FALSE;
   }

   if(initlogtask)
   {
      CloseLogWrite();
      initlogtask=FALSE;
   }
}

void CleanUp(short err)
{
   if(SetSignal(0L,0L) & SIGBREAKF_CTRL_C)
   {
      if(initlogtask)
         LogWrite(2,SYSTEMERR,getString(ERR_USER_BREAK));

      else
         printf("%s\n",getString(ERR_USER_BREAK));
   }

   if(initlogtask)
      LogWrite(2,SYSTEMINFO,getString(TXT_CRASHTICK_END));

   Free();

   if(initconfig)
   {
      FreeAnnounces();
      FreeConfig(&config);
   }

   if(rexxport)
      DeletePort(rexxport);

   if(RexxSysBase)
      CloseLibrary((struct Library *)RexxSysBase);

   if(catalog)
      CloseCatalog(catalog);

   if(LocaleBase)
      CloseLibrary(LocaleBase);

   if(mempool)
      LibDeletePool(mempool);

   if(rdargs)
      FreeArgs(rdargs);

   if(stackswapstruct.stk_Lower)
   {
      /* This trick is needed, otherwise DICE will use stack... */

      own_StackSwap=(void *)((ULONG)SysBase-(ULONG)732);
      (*own_StackSwap)(&stackswapstruct,(struct Library *)SysBase);

      FreeMem(stackswapstruct.stk_Lower,STACKSIZE);
   }

   exit(err);
}

short SendRexx(uchar *portname,uchar *command)
{
   struct MsgPort *replyport;
   struct RexxMsg *RexxMsg;
   struct MsgPort *port;
   UBYTE res;

   if(!(port=FindPort(portname)))
      return(10);

   if(!(replyport=(struct MsgPort *)CreatePort(NULL,0)))
   {
      printf("%s\n",getString(ERR_OUT_OF_MEMORY));
      return(10);
   }

   if(!(RexxMsg=(struct RexxMsg *)CreateRexxMsg(replyport,NULL,port->mp_Node.ln_Name)))
   {
      DeletePort(replyport);
      printf("%s\n",getString(ERR_OUT_OF_MEMORY));
      return(10);
   }

   if(!(RexxMsg->rm_Args[0]=(UBYTE *)CreateArgstring(command,strlen(command))))
   {
      DeleteRexxMsg(RexxMsg);
      DeletePort(replyport);
      printf("%s\n",getString(ERR_OUT_OF_MEMORY));
      return(10);
   }

   Printf(getString(TXT_REXX_WAITING),command);
   Flush(Output());

   RexxMsg->rm_Action = RXCOMM;

   Forbid();
   PutMsg(port,(struct Message *)RexxMsg);
   Permit();

   WaitPort(replyport);

   while(RexxMsg=(struct RexxMsg *)GetMsg(replyport))
   {
      if(RexxMsg->rm_Node.mn_Node.ln_Type == NT_REPLYMSG)
      {
         res=RexxMsg->rm_Result1;
         DeleteArgstring(RexxMsg->rm_Args[0]);
         DeleteRexxMsg(RexxMsg);
      }
   }

   Printf("\x0d");
   
   if(res == 0)
      Printf(getString(TXT_REXX_OK),command);

   else
      Printf(getString(TXT_REXX_ERROR),command,res);

   Printf("                          \n");

   DeletePort(replyport);
   return(res);
}

short reloadconfig;

void ReplyRexxCmd(struct RexxMsg *Msg,LONG rc,UBYTE *s)
{
   Msg->rm_Result1=rc;

   if((Msg->rm_Action & (1<< RXFB_RESULT)) && s)
      Msg->rm_Result2=(LONG)CreateArgstring(s,strlen(s));

   else
      Msg->rm_Result2=0;
}

short keepgoing;

void HandleRexxMessages(void)
{
   struct RexxMsg *RexxMsg;
   UBYTE buf[100];
   short res;

   while(RexxMsg=(struct RexxMsg *)GetMsg(rexxport))
   {
      RexxMsg->rm_Result1=0;
      RexxMsg->rm_Result2=0;

      jbcpos=0;

      if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
      {
         if(stricmp(buf,"QUIT")==0)
         {
            keepgoing=FALSE;
            res=0;
         }
         else if(stricmp(buf,"TICK")==0)
         {
            res=Tick();
         }
         else if(stricmp(buf,"MAINT")==0)
         {
            res=Maint();
         }
         else if(stricmp(buf,"RAID")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=Raid(buf);
            }
         }
         else if(stricmp(buf,"SENDINFO")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=SendAFList(SENDLIST_INFO,buf);
            }
         }
         else if(stricmp(buf,"SENDQUERY")==0 || stricmp(buf,"NOTIFY")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=SendAFList(SENDLIST_QUERY,buf);
            }
         }
         else if(stricmp(buf,"SENDLIST")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=SendAFList(SENDLIST_FULL,buf);
            }
         }
         else if(stricmp(buf,"SENDUNLINKED")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=SendAFList(SENDLIST_UNLINKED,buf);
            }
         }
         else if(stricmp(buf,"SENDHELP")==0)
         {
            res=RC_ERROR;

            if(jbstrcpy(buf,RexxMsg->rm_Args[0],100))
            {
               res=SendAFList(SENDLIST_HELP,buf);
            }
         }
         else if(stricmp(buf,"HATCH")==0)
         {
            uchar hatchfile[100];
            uchar hatcharea[100];
            uchar hatchdesc[200];
            uchar hatchreplace[100];
            uchar hatchmagic[30];

            res=RC_ERROR;

            if(jbstrcpy(hatchfile,RexxMsg->rm_Args[0],100))
            {
               hatchdesc[0]=0;
               hatcharea[0]=0;
               hatchreplace[0]=0;
               hatchmagic[0]=0;

               res=0;

               while(jbstrcpy(buf,RexxMsg->rm_Args[0],20))
               {
                  if(stricmp(buf,"AREA")==0)
                  {
                     if(!jbstrcpy(hatcharea,RexxMsg->rm_Args[0],100))
                        res=10;
                  }
                  else if(stricmp(buf,"DESC")==0)
                  {
                     if(!jbstrcpy(hatchdesc,RexxMsg->rm_Args[0],200))
                        res=10;
                  }
                  else if(stricmp(buf,"REPLACE")==0)
                  {
                     if(!jbstrcpy(hatchreplace,RexxMsg->rm_Args[0],100))
                        res=10;
                  }
                  else if(stricmp(buf,"REPLACE")==0)
                  {
                     if(!jbstrcpy(hatchmagic,RexxMsg->rm_Args[0],30))
                        res=10;
                  }
                  else
                  {
                     res=10;
                  }
               }

               if(res == 0)
                  res=Hatch(hatchfile,hatcharea,hatchdesc,hatchreplace,hatchmagic);

            }
         }
         else if(stricmp(buf,"RELOADCONFIG")==0)
         {
            reloadconfig=TRUE;
            res=0;
         }
         else
         {
            LogWrite(3,SYSTEMERR,getString(ERR_UNKNOWN_REXX_COMMAND),buf);
            res=RC_ERROR;
         }

         ReplyRexxCmd(RexxMsg,res,NULL);
         ReplyMsg((struct Message *)RexxMsg);
      }
   }
}

void RexxPort(void)
{
   ULONG sigs,notifysignal;
   BPTR l;
   short startnotify;
   uchar configname[200];
   struct NotifyRequest notifyrequest;

   keepgoing=TRUE;
   reloadconfig=FALSE;

   strcpy(configname,config.filename);

   if(!(notifysignal=AllocSignal(-1)))
   {
      LogWrite(1,SYSTEMERR,getString(ERR_NO_SIGNAL));
      CleanUp(10);
   }

   notifyrequest.nr_Name=configname;
   notifyrequest.nr_Flags=NRF_SEND_SIGNAL;
   notifyrequest.nr_stuff.nr_Signal.nr_Task=FindTask(NULL);
   notifyrequest.nr_stuff.nr_Signal.nr_SignalNum=notifysignal;

   startnotify=FALSE;

   if(StartNotify(&notifyrequest))
      startnotify=TRUE;

   while(keepgoing)
   {
      sigs=Wait((1<<rexxport->mp_SigBit) | (1<<notifysignal) | SIGBREAKF_CTRL_C);

      reloadconfig=FALSE;

      if(sigs & SIGBREAKF_CTRL_C)
         keepgoing=FALSE;

      if(sigs & (1<<notifysignal))
      {
         if(l=Lock(configname,SHARED_LOCK))
         {
            UnLock(l);
            reloadconfig=TRUE;
         }
      }

      if(sigs & (1<<rexxport->mp_SigBit))
      {
         HandleRexxMessages();
         SetSignal(0L,SIGBREAKF_CTRL_C); /* Nollställa Ctrl-C */
      }

      if(reloadconfig)
      {
         BPTR fh;

         LogWrite(2,SYSTEMINFO,getString(TXT_RELOADING_CONFIG));

         if(fh=Open(configname,MODE_OLDFILE))
         {
            uchar errorbuf[100];
            short seconderr;
            ulong cfgline;

            Free();
            FreeConfig(&config);
            InitConfig(&config);

            if(!ReadConfig(configname,&config,&seconderr,&cfgline,errorbuf))
            {
               if(seconderr == READCONFIG_INVALID)
               {
                  printf(getString(CFG_ERR_CONFIG_ERR_IN_LINE),cfgline);
                  printf(": %s\n",errorbuf);
               }
               else if(seconderr == READCONFIG_NO_MEM)
               {
                  printf("%s\n",getString(ERR_OUT_OF_MEMORY));
               }
               else
               {
                  printf(getString(CFG_ERR_NO_CONFIG_NAME),configname);
                  printf("\n");
               }

               EndNotify(&notifyrequest);
               FreeSignal(notifysignal);
               Close(fh);
               CleanUp(10);
            }

            Close(fh);

            if(!CheckConfig(&config,errorbuf))
            {
               printf("%s",getString(CFG_ERR_CONFIG_ERROR));
               printf(": %s\n",errorbuf);
               EndNotify(&notifyrequest);
               FreeSignal(notifysignal);
               CleanUp(10);
            }

            if(!(Init(errorbuf)))
            {
               printf("%s\n",errorbuf);
               EndNotify(&notifyrequest);
               FreeSignal(notifysignal);
               CleanUp(10);
            }
         }
         else
         {
            LogWrite(2,SYSTEMERR,getString(CFG_ERR_NO_CONFIG_NAME),configname);
         }
      }
   }
}

void PrepareTickHatch(void)
{
   struct ConfigNode *cnode;
   struct Announce *announce;
   struct Area *area;

   for(cnode=(struct ConfigNode *)config.CNodeList.First;cnode;cnode=cnode->Next)
      cnode->ArchiveName[0]=0;

   for(area=(struct Area *)config.AreaList.First;area;area=area->Next)
   {
      area->NewFiles=0;
      area->NewBytes=0;
   }

   for(announce=(struct Announce *)config.AnnounceList.First;announce;announce=announce->Next)
      jbNewList(&announce->LineList);

   DoLater();
}

