/*
  Adverts
  =======

    Lets the sysop add adverts to archives, depending on the file type.

  Version
  =======

    Source code last changed for release V1.04

  Docs
  ====

    Not written yet

  Notes
  =====

    Source code based on Check_Corrupt from HydraBBS V1.04

  ToDo
  ====

    Nothing

  Params
  ======

    FileName (no path)
    FileName (with no .extension)
    File Extension (with no leading .)
    [NOUSER] (to enable quiet mode!)

*/

/* **** Includes *********************************************************** */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>

#include <HBBS/ANSI_Codes.h>
#include <HBBS/Defines.h>
#include <HBBS/Access.h>
#include <HBBS/types.h>
#include <HBBS/structures.h>

#include <HBBS/Hbbscommon_protos.h>
#include <HBBS/hbbscommon_pragmas_sas.h>

#include <HBBS/Hbbsnode_protos.h>
#include <HBBS/Hbbsnode_pragmas_sas.h>

#include <HBBS/release.h>
char *versionstr="$VER: Adverts "RELEASE_STR;

/* **** Variables ********************************************************** */


struct Library *HBBSCommonBase  = NULL;
struct Library *HBBSNodeBase    = NULL;

struct BBSGlobalData *BBSGlobal = NULL;
struct NodeData *N_ND           = NULL;
int    N_NodeNum                = -1;
char   outstr[1024];

long __stack=16*1024; // increse this in 4k incrments if you suffer from
                      // random/suprious crashings after or during the running
                      // of your door. (16k default)

int    gargc;         // these are just copies of main()'s argc and argv..
char   **gargv;

struct AdderData
{
  V_STRING Extension;
  V_STRING TypeDescription;
  V_STRING Command;
  V_STRING Params;
  V_BOOL ShowOutput;
};

/* **** Functions ********************************************************** */


#ifdef __SASC
int CXBRK(void) { return(0); }
int _CXBRK(void) { return(0); }
void chkabort(void) {}
#endif

#define INITERR_NOERROR 0
#define INITERR_NOPARAMS 1
#define INITERR_NOHBBSCOMMON 2
#define INITERR_INITCOMMONFAILED 3
#define INITERR_NOHBBSNODE 4
#define INITERR_INITDOORFAILED 5

static VOID CleanUp(ULONG num)
{
  if (HBBSNodeBase)
  {
    HBBS_CleanUpDoor();
    CloseLibrary (HBBSNodeBase);
  }

  if (HBBSCommonBase)
  {
    HBBS_CleanUpCommon();
    CloseLibrary (HBBSCommonBase);
  }

  switch(num)
  {
    case INITERR_NOERROR:
      exit(0);

    case INITERR_NOPARAMS:
      puts("Bad or no paramaters specified, check your config files\n"
           "(Don't try starting doors from the CLI!)");
      break;

    case INITERR_NOHBBSCOMMON:
      puts("Could not open HBBSCommon.library, check your assign's");
      break;

    case INITERR_INITCOMMONFAILED:
      puts("Could not initialise HBBSCommon.library functions\n"
           "Is HBBS Running ?");
      break;

    case INITERR_NOHBBSNODE:
      puts("Could not open HBBSNode.library, check your assign's");
      break;

    case INITERR_INITDOORFAILED:
      puts("The node specified is either not running or did not want to\n"
           "start this door now. (Don't run doors from the CLI!)");
      break;
  }
  exit(20);
}

static VOID Init(char *name)
{
  if(!(HBBSCommonBase = OpenLibrary("HBBSCommon.library",0)))
  {
    CleanUp(INITERR_NOHBBSCOMMON);
  }

  if (!(HBBS_InitCommon()))
  {
    CleanUp(INITERR_INITCOMMONFAILED);
  }

  if(!(HBBSNodeBase = OpenLibrary("HBBSNode.library",0)))
  {
    CleanUp(INITERR_NOHBBSNODE);
  }

  if (!(HBBS_InitDoor(N_NodeNum,name)))
  {
    CleanUp(INITERR_INITDOORFAILED);
  }
  SetProgramName(name);
}

/* **** DoorMain *********************************************************** */

BOOL ChangeDir( char *path)
{
  BPTR FL,NFL;

  if (PathOK(path))
  {
    if (FL = Lock(path,ACCESS_READ))
    {
      NFL=CurrentDir(FL);
      UnLock(NFL);
      return(TRUE);
    }
  }
  return(FALSE);
}

#define FILE_BUFFER_SIZE 1024*32 // *C* make smaller (see below)

void DoorMain( void )
{
  struct CfgFileData *Cfg;
  BOOL ConfigOK = TRUE,
       UserAround = TRUE;
  struct AdderData *Adder;
  V_STRING FileName;
  V_STRING FileNameNoExt;
  char commandline[1024];
  char optionname[1024];
  char tempfilename[20];
  char tmpstr[1024];

  if (Adder = AllocVec(sizeof (struct AdderData), MEMF_CLEAR))
  {
    if (stricmp("NOUSER",gargv[gargc-1])==0) UserAround=FALSE;

    if (gargc >= 2) FileName = gargv[2];
    if (gargc >= 3) FileNameNoExt = gargv[3];
    if (gargc >= 4) Adder -> Extension = gargv[4];

    // tmpstr is used twice below, then overwritten later.
    sprintf(tmpstr,"File type unknown for file \"%s\"",FileName);

    if (UserAround) DOOR_DisplaySpecialScreen("Adverts_TOP");

    if ( ! Adder -> Extension)
    {
      if (UserAround) DOOR_WriteText(ANSI_FG_YELLOW "Unknown file type, file not checked!\r\n");
      HBBS_AddToCallersLog(tmpstr);
    }
    else
    {
      // check extension length (255 max filename length on most systems)
      if (strlen (Adder -> Extension) > 255) Adder -> Extension[255] = 0; // truncate the string.

      if (Cfg = HBBS_LoadConfig( "Progdir:Adverts.CFG",LCFG_NONE))
      {

        sprintf(optionname,"FileTypeDesc_%s",Adder->Extension);
        if (!HBBS_GetSetting(Cfg,(void *)&Adder -> TypeDescription,VTYPE_STRING,optionname,OPT_SINGLE))
          ConfigOK=FALSE;
        else
        {
          sprintf(optionname,"AdderCMD_%s",Adder->Extension);
          if (!HBBS_GetSetting(Cfg,(void *)&Adder -> Command,VTYPE_STRING,optionname,OPT_SINGLE))
            ConfigOK=FALSE;
          else
          {
            sprintf(optionname,"AdderParams_%s",Adder->Extension);
            if (!HBBS_GetSetting(Cfg,(void *)&Adder -> Params,VTYPE_STRING,optionname,OPT_SINGLE))
              ConfigOK=FALSE;
            else
            {
              sprintf(optionname,"ShowOutput_%s",Adder->Extension);
              if (!HBBS_GetSetting(Cfg,(void *)&Adder -> ShowOutput,VTYPE_BOOL,optionname,OPT_SINGLE))
                ConfigOK=FALSE;
            }
          }
        }

        HBBS_FlushConfig(Cfg);
      }
      else
      {
        ConfigOK=FALSE;
        // add an extra bit to the error message
        sprintf(tmpstr+strlen(tmpstr)," extension unknown \"%s\"",Adder -> Extension);
        HBBS_AddToCallersLog(tmpstr);

        HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,"Adverts door could not load it's config \"Adverts.CFG\"",TYPE_IMPORTANT);
      }

      if (ConfigOK)
      {
        if (ChangeDir(N_ND->NodeSettings.NodePlayPen))
        {
          if (UserAround)
          {
            sprintf(tmpstr,ANSI_FG_YELLOW "Adding Adverts to: "ANSI_FG_CYAN"%s "ANSI_FG_WHITE"- "ANSI_FG_CYAN"%s"ANSI_FG_YELLOW" ... ",
                    FileName,Adder -> TypeDescription);
            DOOR_WriteText(tmpstr);
          }

          sprintf(tempfilename,"T:HBBS/FC%ld.TMP",N_ND->NodeNum);

          // build the command line to run.
          sprintf(commandline,"%s %s",Adder -> Command, Adder -> Params);

          replace(commandline,commandline,"@F@",FileName);
          replace(commandline,commandline,"@N@",FileNameNoExt);
          replace(commandline,commandline,"@E@",Adder -> Extension);
          replace(commandline,commandline,"@P@",N_ND->NodeSettings.NodePlayPen);

          // run the command

          DeleteFile(tempfilename); // remove the file, in case one exists and our Adder doesn't run..

          HBBS_DosCommand(commandline,RDC_NONE,tempfilename);

          if (UserAround) DOOR_WriteText("\r\n");

          if (Adder->ShowOutput && UserAround) DOOR_DisplayScreen(tempfilename);

          DeleteFile(tempfilename);


        } // changedir OK
      } // configOK

      FreeStr(Adder -> TypeDescription);
      FreeStr(Adder -> Command);
      FreeStr(Adder -> Params);
    }

    FreeVec(Adder);

    if (UserAround) DOOR_DisplaySpecialScreen("Adverts_BOT");
  }
}

int main(int argc,char **argv)
{

  /* set these so that we can access the paramaters in the rest of the program */

  gargc=argc;
  gargv=argv;

  /* Check to see if we've got any paramaters */

  if (argc <= 1)
  {
    CleanUp(INITERR_NOPARAMS);
  }

  /* Get the node number from the paramaters */

  if (sscanf(argv[1],"%d",&N_NodeNum)==0)
  {
    CleanUp(INITERR_NOPARAMS);
  }

  /* Initialise and set the door/program name */

  Init("Adverts");

  /* if the init() didn't fail then we need to ask HBBS for the pointer to
     it's data structures */

  if (BBSGlobal=HBBS_GimmeBBS())
  {
    /* Then we need to get the node's data structures for the node this door is going to run on */

    if (N_ND=HBBS_NodeDataPtr(N_NodeNum))
    {

      /* Now that's done, you can put the rest of your code here, or in the DoorMain() function */

      DoorMain();
    }
  }

  /* Cleanup and close libraries */

  CleanUp(INITERR_NOERROR);
}

/* **** End Of File ******************************************************** */
