// --------------------------------------------------------------------
//        F t r a c k . c p p
//
//        Fido messages tracker
//        Main module
// --------------------------------------------------------------------
//        Copyright (c) 1998-2000 by Fyodor Ustinov
//                                FIDONet 2:5020/79
//
//        All rights reserved.
// --------------------------------------------------------------------

#include <locale.h>
#ifndef UNIX
#include <io.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#if !defined (UNIX) && !defined(__DJGPP__)
#include <sys/utime.h>
#else
#include <sys/types.h>
#include <utime.h>
#include <errno.h>
#include <unistd.h>
#endif

#include "constant.hpp"
#include "vars.hpp"
#include "help.hpp"
#include "getopt.hpp"
#include "configure.hpp"
#include "log.hpp"
#include "nodelist.hpp"
#include "msg.hpp"
#include "msgbase.hpp"
#include "scandir.hpp"
#include "aka.hpp"
#include "passwd.hpp"
#include "parsetpl.hpp"
#include "tmstamp.hpp"
#include "script.hpp"
#include <iostream>
#include <fstream>
#include <smapi/msgapi.h>

static struct utimbuf ut;
static struct _minf mnf;

// --------------------------------------------------------------------
//                         Signals catch functions
// --------------------------------------------------------------------
void AbrtHndl(int Sign) {
fstream fh ("FTrack.err", ios::app);

   cerr << "Internal Error!!! Please, read report.err in documentation.\n";
   cerr << "---------------------------------------\n";
   cerr << Date() << " FTrack " << FVersion << "\n";
   cerr << "Check point: " << (long int)CHP << "\n";
   cerr << "Signal: " << Sign << "\n";
   cerr << "---------------------------------------\n";
   cerr << flush;
   if (!fh.bad()) {
      fh << "Internal Error!!! Please, read report.err in documentation.\n";
      fh << "---------------------------------------\n";
      fh << Date() << " FTrack " << FVersion << "\n";
      fh << "Check point: " << (long int)CHP << "\n";
      fh << "Signal: " << Sign << "\n";
      fh << "---------------------------------------\n";
      fh << flush;
   } else {
      cerr << "Oops... Unable to create FTrack.err and information about error missed.\n";
   }
   ReleaseSemaphore();
   exit(-1);
}

// --------------------------------------------------------------------
//                            Init all subsystems.
// --------------------------------------------------------------------
int InitSystem(void) {

#ifndef _DEBUG
   CHP = 99100;
   signal(SIGSEGV,&AbrtHndl);
   signal(SIGILL,&AbrtHndl);
#endif

   if (sizeof(int) != 4 || sizeof(long) != 4) {
      fprintf(stderr,"FTrack compiled for wrong platform.\nPlease, call to author.\n");
      if (sizeof(long) == 8 && sizeof(void *) == 8 && sizeof(int) == 4) {
          fprintf(stderr,"Continue at your own risk! This software is not 64-bit ready yet!\n");
      } else {
          return FALSE;
      }
   }
   CHP = 99101;
   tzset();
   CHP = 99102;
   Log.LogLevel(2);
   memset(&mnf, '\0', sizeof (mnf));
   CHP = 99103;
   mnf.req_version = 1;
   MsgOpenApi(&mnf);
   CHP = 99104;


   if (InitScriptSystem() != TRUE) {
      Log.Level(LOGE) << "Unable to start script system" << EOL;
	  return FALSE;
   }
   if (ConfigFile == NULL) {
      ConfigFile = strdup(DefaultConfig);
   }
   CHP = 99105;

   if (ParseConfig(ConfigFile) != 0) {
      CHP = 9910501;
      return FALSE;
   }

   CHP = 99106;
   if (!MyAddr.Valid()) {
      Log.Level(LOGE) << "Error. Own Address is not defined." << EOL;
      return FALSE;
   }
   if (ForceINTL) {
      UseOwnZone = TRUE;
   }

   if (!Ndl.Load()) {
      return FALSE;
   }

   if (!InitOutbound()) {
      return FALSE;
   }

   if (!SetSemaphore()) {
      return FALSE;
   }

   InitScriptValues();

   switch (DoSomeWordRc("BeforeWork")) {
      case SS_ERROR: return FALSE;
      default: break;
   }

   return TRUE;
}

// --------------------------------------------------------------------
//                         Shutdown all subsystems.
// --------------------------------------------------------------------
void DoneSystem(void) {
int i;

//   ScanDirs.clearAndDestroy();
   DoSomeWord("AfterWork");
   CHP = 99200;
   DestroyAka();
   CHP = 99201;
   DestroyPasswd();
   CHP = 99202;
   StopScriptSystem();
   if (Log.Opened() && LogLevel != 0) {
      CHP = 99203;
      Log.Level(LOGE) << "--- FTrack " << FVersion << " stopped." << EOL;
      Log.Close();
   }
   CHP = 99204;
   if (TimeStampFile != NULL) {
      CHP = 99205;
      if (utime(TimeStampFile,&ut) != 0) {
         CHP = 99206;
         i = errno;
         Log.Level(LOGE) << "Unable to set modification time for file '" << TimeStampFile << "'. Errno: " << i << EOL;
         CHP = 99207;
      }
      CHP = 99208;
   }
   ReleaseSemaphore();
   CHP = 99209;
}

// --------------------------------------------------------------------
//                              M A I N
// --------------------------------------------------------------------
int main (int argc, char *argv[]) {
int Option;
int DoScan;

   setlocale(LC_CTYPE, "");
   CHP = 99000;
   ut.actime = time(NULL);
   ut.modtime = time(NULL);
   Hello();

   DoScan = FALSE;
   CHP = 99001;
   while ((Option = getopt(argc, argv, "c:uh?t")) != EOF) {
      switch (Option) {
         case 'u' : UnpackNeed = TRUE;
                    break;
         case 'c' : /* Kill all mail */
                    ConfigFile = strdup(optarg);
                    break;
         case 't' : DoScan = TRUE;
                    break;
         case '?' :
         case 'h' : Help(); exit(0);
      } /* switch */
   } /* while */

// ---
   atexit(&DoneSystem);

   CHP = 99002;
   if (!InitSystem()) {
      return (-1);
   }
   CHP = 99003;
   if (DoScan) {
      LastTime = 0;
   }
// ---

   if (UnpackNeed) {
      if (!DoRepack()) {
         return (-1);
      }
   }

   if (LogLevel >= 5) {
      PrintScanDirs();
   }

   DoScanDirs();

#if 0
//   Ndl.Print();
   FA a;
   char *ff;
   ff = "8:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/234";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/607";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/608";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/622";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

   ff = "2:5020/1667";
   a.Parse(ff);
   Log.Level(LOGD) << a << " "  << Ndl.GetFlags(a)<< EOL;
   SayNodelistFlags(a); Log.Level(LOGD) << EOL;

#endif
#if 0
//   Ndl.Print();
   FA a;
   char *ff;
   ff = "8:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "8:50/2";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.3";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.4";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.12";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.13";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.14";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a) != -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1079";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:5030/6";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:5030/6.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:5030/6.33";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:2/1";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:2/5000";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:20/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:20/10";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:20/11";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:20/999";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:20/1079";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/1";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/2";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/100";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/101";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;
   ff = "2:201/111";
   a.Parse(ff);
   Log.Level(LOGD) << a << (Ndl.ExistInNodelist(a)!= -1?" Exist":" Not Exist") << EOL;

   FA b;
   char *mm;
   mm = "2:5020/238.&";
   b.Parse(mm);
   ff = "2:5020/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1079";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;

   mm = "2:5020/79.&";
   b.Parse(mm);
   ff = "2:5020/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1079";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/2.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;

   mm = "2:50/0.&";
   b.Parse(mm);
   ff = "2:5020/0";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:50/128";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/1079";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:201/101";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.1";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
   ff = "2:5020/79.2";
   a.Parse(ff);
   Log.Level(LOGD) << a << " " << b << (Ndl.InSubHubs(a,b) == TRUE?" Exist":" Not Exist") << EOL;
#endif
// ---

   return (0);
}

// ---------------------------- END --------------------------------------


syntax highlighted by Code2HTML, v. 0.9.1