2100 lines
42 KiB
C
2100 lines
42 KiB
C
/*
|
|
Copyright 2001-2018 John Wiseman G8BPQ
|
|
|
|
This file is part of LinBPQ/BPQ32.
|
|
|
|
LinBPQ/BPQ32 is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
LinBPQ/BPQ32 is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with LinBPQ/BPQ32. If not, see http://www.gnu.org/licenses
|
|
*/
|
|
|
|
// Control Routine for LinBPQ
|
|
|
|
#define _CRT_SECURE_NO_DEPRECATE
|
|
|
|
#include "CHeaders.h"
|
|
#include "bpqmail.h"
|
|
#ifdef WIN32
|
|
#include <Iphlpapi.h>
|
|
//#include "C:\Program Files (x86)\GnuWin32\include\iconv.h"
|
|
#else
|
|
#include <iconv.h>
|
|
#include <errno.h>
|
|
#ifndef MACBPQ
|
|
#ifndef FREEBSD
|
|
#include <sys/prctl.h>
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
#include "time.h"
|
|
|
|
#define Connect(stream) SessionControl(stream,1,0)
|
|
#define Disconnect(stream) SessionControl(stream,2,0)
|
|
#define ReturntoNode(stream) SessionControl(stream,3,0)
|
|
#define ConnectUsingAppl(stream, appl) SessionControl(stream, 0, appl)
|
|
|
|
BOOL APIENTRY Rig_Init();
|
|
|
|
void GetSemaphore(struct SEM * Semaphore, int ID);
|
|
void FreeSemaphore(struct SEM * Semaphore);
|
|
VOID CopyConfigFile(char * ConfigName);
|
|
VOID SendMailForThread(VOID * Param);
|
|
VOID GetUIConfig();
|
|
Dll BOOL APIENTRY Init_IP();
|
|
VOID OpenReportingSockets();
|
|
VOID SetupNTSAliases(char * FN);
|
|
int DeleteRedundantMessages();
|
|
BOOL InitializeTNCEmulator();
|
|
VOID FindLostBuffers();
|
|
VOID IPClose();
|
|
DllExport BOOL APIENTRY Rig_Close();
|
|
Dll BOOL APIENTRY Poll_IP();
|
|
BOOL Rig_Poll();
|
|
BOOL Rig_Poll();
|
|
VOID CheckWL2KReportTimer();
|
|
VOID TNCTimer();
|
|
VOID SendLocation();
|
|
int ChatPollStreams();
|
|
void ChatTrytoSend();
|
|
VOID BBSSlowTimer();
|
|
int GetHTMLForms();
|
|
char * AddUser(char * Call, char * password, BOOL BBSFlag);
|
|
VOID SaveChatConfigFile(char * ConfigName);
|
|
VOID SaveMH();
|
|
int upnpClose();
|
|
void SaveAIS();
|
|
void initAIS();
|
|
void DRATSPoll();
|
|
VOID GetPGConfig();
|
|
void SendBBSDataToPktMap();
|
|
|
|
extern uint64_t timeLoadedMS;
|
|
|
|
BOOL IncludesMail = FALSE;
|
|
BOOL IncludesChat = FALSE;
|
|
|
|
BOOL RunMail = FALSE;
|
|
BOOL RunChat = FALSE;
|
|
BOOL needAIS= FALSE;
|
|
BOOL needADSB = FALSE;
|
|
|
|
int CloseOnError = 0;
|
|
|
|
VOID Poll_AGW();
|
|
BOOL AGWAPIInit();
|
|
int AGWAPITerminate();
|
|
|
|
BOOL AGWActive = FALSE;
|
|
|
|
extern int AGWPort;
|
|
|
|
BOOL RigActive = FALSE;
|
|
|
|
extern ULONG ChatApplMask;
|
|
extern char Verstring[];
|
|
|
|
extern char SignoffMsg[];
|
|
extern char AbortedMsg[];
|
|
extern char InfoBoxText[]; // Text to display in Config Info Popup
|
|
|
|
extern int LastVer[4]; // In case we need to do somthing the first time a version is run
|
|
|
|
extern HWND MainWnd;
|
|
extern char BaseDir[];
|
|
extern char BaseDirRaw[];
|
|
extern char MailDir[];
|
|
extern char WPDatabasePath[];
|
|
extern char RlineVer[50];
|
|
|
|
extern BOOL LogBBS;
|
|
extern BOOL LogCHAT;
|
|
extern BOOL LogTCP;
|
|
extern BOOL ForwardToMe;
|
|
|
|
extern int LatestMsg;
|
|
extern char BBSName[];
|
|
extern char SYSOPCall[];
|
|
extern char BBSSID[];
|
|
extern char NewUserPrompt[];
|
|
|
|
extern int NumberofStreams;
|
|
extern int MaxStreams;
|
|
extern ULONG BBSApplMask;
|
|
extern int BBSApplNum;
|
|
extern int ChatApplNum;
|
|
extern int MaxChatStreams;
|
|
|
|
extern int NUMBEROFTNCPORTS;
|
|
|
|
extern int EnableUI;
|
|
|
|
extern BOOL AUTOSAVEMH;
|
|
|
|
extern FILE * LogHandle[4];
|
|
|
|
#define MaxSockets 64
|
|
|
|
extern ConnectionInfo Connections[MaxSockets+1];
|
|
|
|
time_t LastTrafficTime;
|
|
extern int MaintTime;
|
|
|
|
#define LOG_BBS 0
|
|
#define LOG_CHAT 1
|
|
#define LOG_TCP 2
|
|
#define LOG_DEBUG_X 3
|
|
|
|
int _MYTIMEZONE = 0;
|
|
|
|
// flags equates
|
|
|
|
#define F_Excluded 0x0001
|
|
#define F_LOC 0x0002
|
|
#define F_Expert 0x0004
|
|
#define F_SYSOP 0x0008
|
|
#define F_BBS 0x0010
|
|
#define F_PAG 0x0020
|
|
#define F_GST 0x0040
|
|
#define F_MOD 0x0080
|
|
#define F_PRV 0x0100
|
|
#define F_UNP 0x0200
|
|
#define F_NEW 0x0400
|
|
#define F_PMS 0x0800
|
|
#define F_EMAIL 0x1000
|
|
#define F_HOLDMAIL 0x2000
|
|
#define F_POLLRMS 0x4000
|
|
#define F_SYSOP_IN_LM 0x8000
|
|
#define F_Temp_B2_BBS 0x00010000
|
|
|
|
/* #define F_PWD 0x1000 */
|
|
|
|
|
|
extern UCHAR BPQDirectory[260];
|
|
extern UCHAR LogDirectory[260];
|
|
extern UCHAR ConfigDirectory[260];
|
|
|
|
// overrides from params
|
|
UCHAR LogDir[260] = "";
|
|
UCHAR ConfigDir[260] = "";
|
|
UCHAR DataDir[260] = "";
|
|
|
|
|
|
BOOL GetConfig(char * ConfigName);
|
|
VOID DecryptPass(char * Encrypt, unsigned char * Pass, unsigned int len);
|
|
int EncryptPass(char * Pass, char * Encrypt);
|
|
int APIENTRY FindFreeStream();
|
|
int PollStreams();
|
|
int APIENTRY SetAppl(int stream, int flags, int mask);
|
|
int APIENTRY SessionState(int stream, int * state, int * change);
|
|
int APIENTRY SessionControl(int stream, int command, int Mask);
|
|
|
|
BOOL ChatInit();
|
|
VOID CloseChat();
|
|
VOID CloseTNCEmulator();
|
|
|
|
static config_t cfg;
|
|
static config_setting_t * group;
|
|
|
|
BOOL MonBBS = TRUE;
|
|
BOOL MonCHAT = TRUE;
|
|
BOOL MonTCP = TRUE;
|
|
|
|
BOOL LogBBS = TRUE;
|
|
BOOL LogCHAT = TRUE;
|
|
BOOL LogTCP = TRUE;
|
|
|
|
extern BOOL LogAPRSIS;
|
|
|
|
BOOL UIEnabled[33];
|
|
BOOL UINull[33];
|
|
char * UIDigi[33];
|
|
|
|
extern struct UserInfo ** UserRecPtr;
|
|
extern int NumberofUsers;
|
|
|
|
extern struct UserInfo * BBSChain; // Chain of users that are BBSes
|
|
|
|
extern struct MsgInfo ** MsgHddrPtr;
|
|
extern int NumberofMessages;
|
|
|
|
extern int FirstMessageIndextoForward; // Lowest Message wirh a forward bit set - limits search
|
|
|
|
extern char UserDatabaseName[MAX_PATH];
|
|
extern char UserDatabasePath[MAX_PATH];
|
|
|
|
extern char MsgDatabasePath[MAX_PATH];
|
|
extern char MsgDatabaseName[MAX_PATH];
|
|
|
|
extern char BIDDatabasePath[MAX_PATH];
|
|
extern char BIDDatabaseName[MAX_PATH];
|
|
|
|
extern char WPDatabasePath[MAX_PATH];
|
|
extern char WPDatabaseName[MAX_PATH];
|
|
|
|
extern char BadWordsPath[MAX_PATH];
|
|
extern char BadWordsName[MAX_PATH];
|
|
|
|
extern char NTSAliasesPath[MAX_PATH];
|
|
extern char NTSAliasesName[MAX_PATH];
|
|
|
|
extern char BaseDir[MAX_PATH];
|
|
extern char BaseDirRaw[MAX_PATH]; // As set in registry - may contain %NAME%
|
|
extern char ProperBaseDir[MAX_PATH]; // BPQ Directory/BPQMailChat
|
|
|
|
extern char MailDir[MAX_PATH];
|
|
|
|
extern time_t MaintClock; // Time to run housekeeping
|
|
|
|
#ifdef WIN32
|
|
BOOL KEEPGOING = 30; // 5 secs to shut down
|
|
#else
|
|
BOOL KEEPGOING = 50; // 5 secs to shut down
|
|
#endif
|
|
BOOL Restarting = FALSE;
|
|
BOOL CLOSING = FALSE;
|
|
|
|
int ProgramErrors;
|
|
int Slowtimer = 0;
|
|
|
|
#define REPORTINTERVAL 15 * 549; // Magic Ticks Per Minute for PC's nominal 100 ms timer
|
|
int ReportTimer = 0;
|
|
|
|
// Console Terminal Support
|
|
|
|
struct ConTermS
|
|
{
|
|
int BPQStream;
|
|
BOOL Active;
|
|
int Incoming;
|
|
|
|
char kbbuf[INPUTLEN];
|
|
int kbptr;
|
|
|
|
char * KbdStack[MAXSTACK];
|
|
int StackIndex;
|
|
|
|
BOOL CONNECTED;
|
|
int SlowTimer;
|
|
};
|
|
|
|
struct ConTermS ConTerm = {0, 0};
|
|
|
|
|
|
VOID CheckProgramErrors()
|
|
{
|
|
if (Restarting)
|
|
exit(0); // Make sure can't loop in restarting
|
|
|
|
ProgramErrors++;
|
|
|
|
if (ProgramErrors > 25)
|
|
{
|
|
Restarting = TRUE;
|
|
|
|
Logprintf(LOG_DEBUG_X, NULL, '!', "Too Many Program Errors - Closing");
|
|
|
|
/*
|
|
SInfo.cb=sizeof(SInfo);
|
|
SInfo.lpReserved=NULL;
|
|
SInfo.lpDesktop=NULL;
|
|
SInfo.lpTitle=NULL;
|
|
SInfo.dwFlags=0;
|
|
SInfo.cbReserved2=0;
|
|
SInfo.lpReserved2=NULL;
|
|
|
|
GetModuleFileName(NULL, ProgName, 256);
|
|
|
|
Debugprintf("Attempting to Restart %s", ProgName);
|
|
|
|
CreateProcess(ProgName, "MailChat.exe WAIT", NULL, NULL, FALSE, 0, NULL, NULL, &SInfo, &PInfo);
|
|
*/
|
|
exit(0);
|
|
}
|
|
}
|
|
|
|
#ifdef WIN32
|
|
|
|
BOOL CtrlHandler(DWORD fdwCtrlType)
|
|
{
|
|
switch( fdwCtrlType )
|
|
{
|
|
// Handle the CTRL-C signal.
|
|
case CTRL_C_EVENT:
|
|
printf( "Ctrl-C event\n\n" );
|
|
CLOSING = TRUE;
|
|
Beep( 750, 300 );
|
|
return( TRUE );
|
|
|
|
// CTRL-CLOSE: confirm that the user wants to exit.
|
|
case CTRL_CLOSE_EVENT:
|
|
|
|
CLOSING = TRUE;
|
|
printf( "Ctrl-Close event\n\n" );
|
|
Sleep(20000);
|
|
Beep( 750, 300 );
|
|
return( TRUE );
|
|
|
|
// Pass other signals to the next handler.
|
|
case CTRL_BREAK_EVENT:
|
|
Beep( 900, 200 );
|
|
printf( "Ctrl-Break event\n\n" );
|
|
CLOSING = TRUE;
|
|
Beep( 750, 300 );
|
|
return FALSE;
|
|
|
|
case CTRL_LOGOFF_EVENT:
|
|
Beep( 1000, 200 );
|
|
printf( "Ctrl-Logoff event\n\n" );
|
|
return FALSE;
|
|
|
|
case CTRL_SHUTDOWN_EVENT:
|
|
Beep( 750, 500 );
|
|
printf( "Ctrl-Shutdown event\n\n" );
|
|
CLOSING = TRUE;
|
|
Beep( 750, 300 );
|
|
return FALSE;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
#else
|
|
|
|
// Linux Signal Handlers
|
|
|
|
static void sigterm_handler(int sig)
|
|
{
|
|
syslog(LOG_INFO, "terminating on SIGTERM\n");
|
|
CLOSING = TRUE;
|
|
}
|
|
|
|
static void sigint_handler(int sig)
|
|
{
|
|
printf("terminating on SIGINT\n");
|
|
CLOSING = TRUE;
|
|
}
|
|
|
|
|
|
static void sigusr1_handler(int sig)
|
|
{
|
|
signal(SIGUSR1, sigusr1_handler);
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
BOOL CopyFile(char * In, char * Out, BOOL Failifexists)
|
|
{
|
|
FILE * Handle;
|
|
DWORD FileSize;
|
|
char * Buffer;
|
|
struct stat STAT;
|
|
|
|
if (stat(In, &STAT) == -1)
|
|
return FALSE;
|
|
|
|
FileSize = STAT.st_size;
|
|
|
|
Handle = fopen(In, "rb");
|
|
|
|
if (Handle == NULL)
|
|
return FALSE;
|
|
|
|
Buffer = malloc(FileSize+1);
|
|
|
|
FileSize = fread(Buffer, 1, STAT.st_size, Handle);
|
|
|
|
fclose(Handle);
|
|
|
|
if (FileSize != STAT.st_size)
|
|
{
|
|
free(Buffer);
|
|
return FALSE;
|
|
}
|
|
|
|
Handle = fopen(Out, "wb");
|
|
|
|
if (Handle == NULL)
|
|
{
|
|
free(Buffer);
|
|
return FALSE;
|
|
}
|
|
|
|
FileSize = fwrite(Buffer, 1, STAT.st_size, Handle);
|
|
|
|
fclose(Handle);
|
|
free(Buffer);
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
|
|
int RefreshMainWindow()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int LastSemGets = 0;
|
|
|
|
extern int SemHeldByAPI;
|
|
|
|
VOID MonitorThread(void * x)
|
|
{
|
|
// Thread to detect stuck semaphore
|
|
|
|
do
|
|
{
|
|
if ((Semaphore.Gets == LastSemGets) && Semaphore.Flag)
|
|
{
|
|
// It is stuck - try to release
|
|
|
|
Debugprintf ("Semaphore locked - Process ID = %d, Held By %d",
|
|
Semaphore.SemProcessID, SemHeldByAPI);
|
|
|
|
Semaphore.Flag = 0;
|
|
}
|
|
|
|
LastSemGets = Semaphore.Gets;
|
|
|
|
Sleep(30000);
|
|
// Debugprintf("Monitor Thread Still going %d %d %d %x %d", LastSemGets, Semaphore.Gets, Semaphore.Flag, Semaphore.SemThreadID, SemHeldByAPI);
|
|
|
|
}
|
|
while (TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
VOID TIMERINTERRUPT();
|
|
|
|
BOOL Start();
|
|
VOID INITIALISEPORTS();
|
|
Dll BOOL APIENTRY Init_APRS();
|
|
VOID APRSClose();
|
|
Dll VOID APIENTRY Poll_APRS();
|
|
VOID HTTPTimer();
|
|
|
|
|
|
#define CKernel
|
|
#include "Versions.h"
|
|
|
|
extern struct SEM Semaphore;
|
|
|
|
int SemHeldByAPI = 0;
|
|
BOOL IGateEnabled = TRUE;
|
|
BOOL APRSActive = FALSE;
|
|
BOOL ReconfigFlag = FALSE;
|
|
BOOL APRSReconfigFlag = FALSE;
|
|
BOOL RigReconfigFlag = FALSE;
|
|
|
|
BOOL IPActive = FALSE;
|
|
extern BOOL IPRequired;
|
|
|
|
extern struct WL2KInfo * WL2KReports;
|
|
|
|
int InitDone;
|
|
char pgm[256] = "LINBPQ";
|
|
|
|
char SESSIONHDDR[80] = "";
|
|
int SESSHDDRLEN = 0;
|
|
|
|
|
|
// Next 3 should be uninitialised so they are local to each process
|
|
|
|
UCHAR MCOM;
|
|
UCHAR MUIONLY;
|
|
UCHAR MTX;
|
|
uint64_t MMASK;
|
|
|
|
|
|
UCHAR AuthorisedProgram; // Local Variable. Set if Program is on secure list
|
|
|
|
int SAVEPORT = 0;
|
|
|
|
VOID SetApplPorts();
|
|
|
|
char VersionString[50] = Verstring;
|
|
char VersionStringWithBuild[50]=Verstring;
|
|
int Ver[4] = {Vers};
|
|
char TextVerstring[50] = Verstring;
|
|
|
|
extern UCHAR PWLen;
|
|
extern char PWTEXT[];
|
|
extern int ISPort;
|
|
|
|
extern char ChatConfigName[250];
|
|
|
|
BOOL EventsEnabled = 0;
|
|
|
|
UCHAR * GetBPQDirectory()
|
|
{
|
|
return BPQDirectory;
|
|
}
|
|
UCHAR * GetLogDirectory()
|
|
{
|
|
return LogDirectory;
|
|
}
|
|
extern int POP3Timer;
|
|
|
|
// Console Terminal Stuff
|
|
|
|
#ifndef WIN32
|
|
|
|
#define _getch getchar
|
|
|
|
/**
|
|
Linux (POSIX) implementation of _kbhit().
|
|
Morgan McGuire, morgan@cs.brown.edu
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <sys/select.h>
|
|
#include <termios.h>
|
|
|
|
int _kbhit() {
|
|
static const int STDIN = 0;
|
|
static int initialized = 0;
|
|
|
|
if (! initialized) {
|
|
// Use termios to turn off line buffering
|
|
struct termios term;
|
|
tcgetattr(STDIN, &term);
|
|
term.c_lflag &= ~ICANON;
|
|
|
|
tcsetattr(STDIN, TCSANOW, &term);
|
|
setbuf(stdin, NULL);
|
|
initialized = 1;
|
|
}
|
|
|
|
int bytesWaiting;
|
|
ioctl(STDIN, FIONREAD, &bytesWaiting);
|
|
return bytesWaiting;
|
|
}
|
|
|
|
#endif
|
|
|
|
void ConTermInput(char * Msg)
|
|
{
|
|
int i;
|
|
|
|
if (ConTerm.BPQStream == 0)
|
|
{
|
|
ConTerm.BPQStream = FindFreeStream();
|
|
|
|
if (ConTerm.BPQStream == 255)
|
|
{
|
|
ConTerm.BPQStream = 0;
|
|
printf("No Free Streams\n");
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (!ConTerm.CONNECTED)
|
|
SessionControl(ConTerm.BPQStream, 1, 0);
|
|
|
|
ConTerm.StackIndex = 0;
|
|
|
|
// Stack it
|
|
|
|
if (ConTerm.KbdStack[19])
|
|
free(ConTerm.KbdStack[19]);
|
|
|
|
for (i = 18; i >= 0; i--)
|
|
{
|
|
ConTerm.KbdStack[i+1] = ConTerm.KbdStack[i];
|
|
}
|
|
|
|
ConTerm.KbdStack[0] = _strdup(ConTerm.kbbuf);
|
|
|
|
ConTerm.kbbuf[ConTerm.kbptr]=13;
|
|
|
|
SendMsg(ConTerm.BPQStream, ConTerm.kbbuf, ConTerm.kbptr+1);
|
|
}
|
|
|
|
void ConTermPoll()
|
|
{
|
|
int port, sesstype, paclen, maxframe, l4window, len;
|
|
int state, change, InputLen, count;
|
|
char callsign[11] = "";
|
|
char Msg[300];
|
|
|
|
// Get current Session State. Any state changed is ACK'ed
|
|
// automatically. See BPQHOST functions 4 and 5.
|
|
|
|
SessionState(ConTerm.BPQStream, &state, &change);
|
|
|
|
if (change == 1)
|
|
{
|
|
if (state == 1)
|
|
{
|
|
// Connected
|
|
|
|
ConTerm.CONNECTED = TRUE;
|
|
ConTerm.SlowTimer = 0;
|
|
}
|
|
else
|
|
{
|
|
ConTerm.CONNECTED = FALSE;
|
|
printf("*** Disconnected\n");
|
|
}
|
|
}
|
|
|
|
GetMsg(ConTerm.BPQStream, Msg, &InputLen, &count);
|
|
|
|
if (InputLen)
|
|
{
|
|
char * ptr = Msg;
|
|
char * ptr2 = ptr;
|
|
Msg[InputLen] = 0;
|
|
|
|
while (ptr)
|
|
{
|
|
ptr2 = strlop(ptr, 13);
|
|
|
|
// Replace CR with CRLF
|
|
|
|
printf("%s", ptr);
|
|
|
|
if (ptr2)
|
|
printf("\r\n");
|
|
|
|
ptr = ptr2;
|
|
}
|
|
}
|
|
|
|
if (_kbhit())
|
|
{
|
|
unsigned char c = _getch();
|
|
|
|
if (c == 0xe0)
|
|
{
|
|
// Cursor control
|
|
|
|
c = _getch();
|
|
|
|
if (c == 75) // cursor left
|
|
c = 8;
|
|
}
|
|
|
|
#ifdef WIN32
|
|
printf("%c", c);
|
|
#endif
|
|
if (c == 8)
|
|
{
|
|
if (ConTerm.kbptr)
|
|
ConTerm.kbptr--;
|
|
printf(" \b"); // Already echoed bs - clear typed char from screen
|
|
return;
|
|
}
|
|
|
|
if (c == 13 || c == 10)
|
|
{
|
|
ConTermInput(ConTerm.kbbuf);
|
|
ConTerm.kbptr = 0;
|
|
return;
|
|
}
|
|
|
|
ConTerm.kbbuf[ConTerm.kbptr++] = c;
|
|
fflush(NULL);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#include <getopt.h>
|
|
|
|
static struct option long_options[] =
|
|
{
|
|
{"logdir", required_argument, 0 , 'l'},
|
|
{"configdir", required_argument, 0 , 'c'},
|
|
{"datadir", required_argument, 0 , 'd'},
|
|
{"help", no_argument, 0 , 'h'},
|
|
{ NULL , no_argument , NULL , no_argument }
|
|
};
|
|
|
|
char HelpScreen[] =
|
|
"Usage:\n"
|
|
"Optional Paramters\n"
|
|
"-l path or --logdir path Path for log files\n"
|
|
"-c path or --configdir path Path to Config file bpq32.cfg\n"
|
|
"-d path or --datadir path Path to Data Files\n"
|
|
"-v Show version and exit\n";
|
|
|
|
int Redirected = 0;
|
|
|
|
int main(int argc, char * argv[])
|
|
{
|
|
int i;
|
|
struct UserInfo * user = NULL;
|
|
ConnectionInfo * conn;
|
|
struct stat STAT;
|
|
PEXTPORTDATA PORTVEC;
|
|
|
|
#ifdef WIN32
|
|
|
|
WSADATA WsaData; // receives data from WSAStartup
|
|
HWND hWnd = GetForegroundWindow();
|
|
|
|
WSAStartup(MAKEWORD(2, 0), &WsaData);
|
|
SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE);
|
|
|
|
// disable the [x] button.
|
|
|
|
if (hWnd != NULL)
|
|
{
|
|
HMENU hMenu = GetSystemMenu(hWnd, 0);
|
|
if (hMenu != NULL)
|
|
{
|
|
DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
|
|
DrawMenuBar(hWnd);
|
|
}
|
|
}
|
|
|
|
#else
|
|
setlinebuf(stdout);
|
|
struct sigaction act;
|
|
openlog("LINBPQ", LOG_PID, LOG_DAEMON);
|
|
#ifndef MACBPQ
|
|
#ifndef FREEBSD
|
|
prctl(PR_SET_DUMPABLE, 1); // Enable Core Dumps even with setcap
|
|
#endif
|
|
#endif
|
|
|
|
// Disable Console Terminal if stdout redirected
|
|
|
|
// printf("STDOUT %d\n",isatty(STDOUT_FILENO));
|
|
// printf("STDIN %d\n",isatty(STDIN_FILENO));
|
|
|
|
if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO))
|
|
Redirected = 1;
|
|
|
|
timeLoadedMS = GetTickCount();
|
|
|
|
#endif
|
|
|
|
printf("G8BPQ AX25 Packet Switch System Version %s %s\n", TextVerstring, Datestring);
|
|
printf("%s\n", VerCopyright);
|
|
|
|
|
|
// look for optarg format parameters
|
|
|
|
{
|
|
int val;
|
|
UCHAR * ptr1;
|
|
UCHAR * ptr2;
|
|
int c;
|
|
|
|
while (1)
|
|
{
|
|
int option_index = 0;
|
|
|
|
c = getopt_long(argc, argv, "l:c:d:hv", long_options, &option_index);
|
|
|
|
// Check for end of operation or error
|
|
|
|
if (c == -1)
|
|
break;
|
|
|
|
// Handle options
|
|
switch (c)
|
|
{
|
|
case 'h':
|
|
|
|
printf("%s", HelpScreen);
|
|
exit (0);
|
|
|
|
case 'l':
|
|
strcpy(LogDir, optarg);
|
|
printf("cc %s\n", LogDir);
|
|
break;
|
|
|
|
case 'c':
|
|
strcpy(ConfigDir, optarg);
|
|
break;
|
|
|
|
case 'd':
|
|
strcpy(DataDir, optarg);
|
|
break;
|
|
|
|
|
|
case '?':
|
|
/* getopt_long already printed an error message. */
|
|
break;
|
|
|
|
case 'v':
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
sprintf(RlineVer, "LinBPQ%d.%d.%d", Ver[0], Ver[1], Ver[2]);
|
|
|
|
|
|
Debugprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring);
|
|
|
|
#ifndef MACBPQ
|
|
_MYTIMEZONE = _timezone;
|
|
#endif
|
|
|
|
if (_MYTIMEZONE < -86400 || _MYTIMEZONE > 86400)
|
|
_MYTIMEZONE = 0;
|
|
|
|
#ifdef WIN32
|
|
GetCurrentDirectory(256, BPQDirectory);
|
|
#else
|
|
getcwd(BPQDirectory, 256);
|
|
#endif
|
|
|
|
strcpy(ConfigDirectory, BPQDirectory);
|
|
strcpy(LogDirectory, BPQDirectory);
|
|
|
|
Consoleprintf("Current Directory is %s", BPQDirectory);
|
|
|
|
if (LogDir[0])
|
|
{
|
|
strcpy(LogDirectory, LogDir);
|
|
}
|
|
if (DataDir[0])
|
|
{
|
|
strcpy(BPQDirectory, DataDir);
|
|
Consoleprintf("Working Directory is %s", BPQDirectory);
|
|
}
|
|
if (ConfigDir[0])
|
|
{
|
|
strcpy(ConfigDirectory, ConfigDir);
|
|
Consoleprintf("Config Directory is %s", ConfigDirectory);
|
|
}
|
|
|
|
for (i = optind; i < argc; i++)
|
|
{
|
|
if (_memicmp(argv[i], "logdir=", 7) == 0)
|
|
{
|
|
strcpy(LogDirectory, &argv[i][7]);
|
|
Consoleprintf("Log Directory is %s\n", LogDirectory);
|
|
break;
|
|
}
|
|
}
|
|
|
|
Consoleprintf("Log Directory is %s", LogDirectory);
|
|
|
|
// Make sure logs directory exists
|
|
|
|
sprintf(LogDir, "%s/logs", LogDirectory);
|
|
|
|
#ifdef WIN32
|
|
CreateDirectory(LogDir, NULL);
|
|
#else
|
|
printf("Making Directory %s\n", LogDir);
|
|
i = mkdir(LogDir, S_IRWXU | S_IRWXG | S_IRWXO);
|
|
if (i == -1 && errno != EEXIST)
|
|
{
|
|
perror("Couldn't create log directory\n");
|
|
return 0;
|
|
}
|
|
chmod(LogDir, S_IRWXU | S_IRWXG | S_IRWXO);
|
|
#endif
|
|
|
|
if (!ProcessConfig())
|
|
{
|
|
WritetoConsoleLocal("Configuration File Error\n");
|
|
return (0);
|
|
}
|
|
|
|
SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for Linux (", TextVerstring);
|
|
|
|
#ifdef MACBPQ
|
|
SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for MAC (", TextVerstring);
|
|
#endif
|
|
#ifdef FREEBSD
|
|
SESSHDDRLEN = sprintf(SESSIONHDDR, "G8BPQ Network System %s for FreeBSD (", TextVerstring);
|
|
#endif
|
|
|
|
|
|
GetSemaphore(&Semaphore, 0);
|
|
|
|
if (Start() != 0)
|
|
{
|
|
FreeSemaphore(&Semaphore);
|
|
return (0);
|
|
}
|
|
|
|
for (i=0;PWTEXT[i] > 0x20;i++); //Scan for cr or null
|
|
|
|
PWLen=i;
|
|
|
|
SetApplPorts();
|
|
|
|
GetUIConfig();
|
|
|
|
INITIALISEPORTS();
|
|
|
|
if (IPRequired) IPActive = Init_IP();
|
|
|
|
APRSActive = Init_APRS();
|
|
|
|
if (ISPort == 0)
|
|
IGateEnabled = 0;
|
|
|
|
if (needAIS)
|
|
initAIS();
|
|
|
|
RigActive = Rig_Init();
|
|
|
|
FreeSemaphore(&Semaphore);
|
|
|
|
OpenReportingSockets();
|
|
|
|
initUTF8();
|
|
|
|
InitDone = TRUE;
|
|
|
|
Debugprintf("Monitor Thread ID %x", _beginthread(MonitorThread, 0, 0));
|
|
|
|
|
|
#ifdef WIN32
|
|
#else
|
|
openlog("LINBPQ", LOG_PID, LOG_DAEMON);
|
|
|
|
memset (&act, '\0', sizeof(act));
|
|
|
|
act.sa_handler = &sigint_handler;
|
|
if (sigaction(SIGINT, &act, NULL) < 0)
|
|
perror ("SIGINT");
|
|
|
|
act.sa_handler = &sigterm_handler;
|
|
if (sigaction(SIGTERM, &act, NULL) < 0)
|
|
perror ("sigaction");
|
|
|
|
act.sa_handler = SIG_IGN;
|
|
if (sigaction(SIGHUP, &act, NULL) < 0)
|
|
perror ("SIGHUP");
|
|
|
|
if (sigaction(SIGPIPE, &act, NULL) < 0)
|
|
perror ("SIGPIPE");
|
|
|
|
#endif
|
|
|
|
for (i = optind; i < argc; i++)
|
|
{
|
|
if (_stricmp(argv[i], "chat") == 0)
|
|
IncludesChat = TRUE;
|
|
}
|
|
|
|
if (IncludesChat)
|
|
{
|
|
RunChat = TRUE;
|
|
|
|
printf("Starting Chat\n");
|
|
|
|
sprintf (ChatConfigName, "%s/chatconfig.cfg", BPQDirectory);
|
|
printf("Config File is %s\n", ChatConfigName);
|
|
|
|
if (stat(ChatConfigName, &STAT) == -1)
|
|
{
|
|
printf("Chat Config File not found - creating a default config\n");
|
|
ChatApplNum = 2;
|
|
MaxChatStreams = 10;
|
|
SaveChatConfigFile(ChatConfigName);
|
|
}
|
|
|
|
if (GetChatConfig(ChatConfigName) == EXIT_FAILURE)
|
|
{
|
|
printf("Chat Config File seems corrupt - check before continuing\n");
|
|
return -1;
|
|
}
|
|
|
|
if (ChatApplNum)
|
|
{
|
|
if (ChatInit() == 0)
|
|
{
|
|
printf("Chat Init Failed\n");
|
|
RunChat = 0;
|
|
}
|
|
else
|
|
{
|
|
printf("Chat Started\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
printf("Chat APPLNUM not defined\n");
|
|
RunChat = 0;
|
|
}
|
|
CopyConfigFile(ChatConfigName);
|
|
}
|
|
|
|
// Start Mail if requested by command line or config
|
|
|
|
for (i = optind; i < argc; i++)
|
|
{
|
|
if (_stricmp(argv[i], "mail") == 0)
|
|
IncludesMail = TRUE;
|
|
}
|
|
|
|
|
|
if (IncludesMail)
|
|
{
|
|
RunMail = TRUE;
|
|
|
|
printf("Starting Mail\n");
|
|
|
|
sprintf (ConfigName, "%s/linmail.cfg", BPQDirectory);
|
|
printf("Config File is %s\n", ConfigName);
|
|
|
|
if (stat(ConfigName, &STAT) == -1)
|
|
{
|
|
printf("Config File not found - creating a default config\n");
|
|
strcpy(BBSName, MYNODECALL);
|
|
strlop(BBSName, '-');
|
|
strlop(BBSName, ' ');
|
|
BBSApplNum = 1;
|
|
MaxStreams = 10;
|
|
SaveConfig(ConfigName);
|
|
}
|
|
|
|
if (GetConfig(ConfigName) == EXIT_FAILURE)
|
|
{
|
|
printf("BBS Config File seems corrupt - check before continuing\n");
|
|
return -1;
|
|
}
|
|
|
|
printf("Config Processed\n");
|
|
|
|
BBSApplMask = 1<<(BBSApplNum-1);
|
|
|
|
// See if we need to warn of possible problem with BaseDir moved by installer
|
|
|
|
sprintf(BaseDir, "%s", BPQDirectory);
|
|
|
|
|
|
// Set up file and directory names
|
|
|
|
strcpy(UserDatabasePath, BaseDir);
|
|
strcat(UserDatabasePath, "/");
|
|
strcat(UserDatabasePath, UserDatabaseName);
|
|
|
|
strcpy(MsgDatabasePath, BaseDir);
|
|
strcat(MsgDatabasePath, "/");
|
|
strcat(MsgDatabasePath, MsgDatabaseName);
|
|
|
|
strcpy(BIDDatabasePath, BaseDir);
|
|
strcat(BIDDatabasePath, "/");
|
|
strcat(BIDDatabasePath, BIDDatabaseName);
|
|
|
|
strcpy(WPDatabasePath, BaseDir);
|
|
strcat(WPDatabasePath, "/");
|
|
strcat(WPDatabasePath, WPDatabaseName);
|
|
|
|
strcpy(BadWordsPath, BaseDir);
|
|
strcat(BadWordsPath, "/");
|
|
strcat(BadWordsPath, BadWordsName);
|
|
|
|
strcpy(NTSAliasesPath, BaseDir);
|
|
strcat(NTSAliasesPath, "/");
|
|
strcat(NTSAliasesPath, NTSAliasesName);
|
|
|
|
strcpy(MailDir, BaseDir);
|
|
strcat(MailDir, "/");
|
|
strcat(MailDir, "Mail");
|
|
|
|
#ifdef WIN32
|
|
CreateDirectory(MailDir, NULL); // Just in case
|
|
#else
|
|
mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO);
|
|
chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO);
|
|
#endif
|
|
|
|
// Make backup copies of Databases
|
|
|
|
// CopyConfigFile(ConfigName);
|
|
|
|
CopyBIDDatabase();
|
|
CopyMessageDatabase();
|
|
CopyUserDatabase();
|
|
CopyWPDatabase();
|
|
|
|
SetupMyHA();
|
|
SetupFwdAliases();
|
|
SetupNTSAliases(NTSAliasesPath);
|
|
|
|
GetWPDatabase();
|
|
|
|
GetMessageDatabase();
|
|
GetUserDatabase();
|
|
GetBIDDatabase();
|
|
GetBadWordFile();
|
|
GetHTMLForms();
|
|
GetPGConfig();
|
|
|
|
// Make sure there is a user record for the BBS, with BBS bit set.
|
|
|
|
user = LookupCall(BBSName);
|
|
|
|
if (user == NULL)
|
|
{
|
|
user = AllocateUserRecord(BBSName);
|
|
user->Temp = zalloc(sizeof (struct TempUserInfo));
|
|
}
|
|
|
|
if ((user->flags & F_BBS) == 0)
|
|
{
|
|
// Not Defined as a BBS
|
|
|
|
if(SetupNewBBS(user))
|
|
user->flags |= F_BBS;
|
|
}
|
|
|
|
// if forwarding AMPR mail make sure User/BBS AMPR exists
|
|
|
|
if (SendAMPRDirect)
|
|
{
|
|
BOOL NeedSave = FALSE;
|
|
|
|
user = LookupCall("AMPR");
|
|
|
|
if (user == NULL)
|
|
{
|
|
user = AllocateUserRecord("AMPR");
|
|
user->Temp = zalloc(sizeof (struct TempUserInfo));
|
|
NeedSave = TRUE;
|
|
}
|
|
|
|
if ((user->flags & F_BBS) == 0)
|
|
{
|
|
// Not Defined as a BBS
|
|
|
|
if (SetupNewBBS(user))
|
|
user->flags |= F_BBS;
|
|
NeedSave = TRUE;
|
|
}
|
|
|
|
if (NeedSave)
|
|
SaveUserDatabase();
|
|
}
|
|
|
|
|
|
// Make sure SYSOPCALL is set
|
|
|
|
if (SYSOPCall[0] == 0)
|
|
strcpy(SYSOPCall, BBSName);
|
|
|
|
// See if just want to add user (mainly for setup scripts)
|
|
|
|
if (argc == 5 && _stricmp(argv[1], "--adduser") == 0)
|
|
{
|
|
BOOL isBBS = FALSE;
|
|
char * response;
|
|
|
|
if (_stricmp(argv[4], "TRUE") == 0)
|
|
isBBS = TRUE;
|
|
|
|
printf("Adding User %s\r\n", argv[2]);
|
|
response = AddUser(argv[2], argv[3], isBBS);
|
|
printf("%s", response);
|
|
exit(0);
|
|
}
|
|
// Allocate Streams
|
|
|
|
strcpy(pgm, "BBS");
|
|
|
|
for (i=0; i < MaxStreams; i++)
|
|
{
|
|
conn = &Connections[i];
|
|
conn->BPQStream = FindFreeStream();
|
|
|
|
if (conn->BPQStream == 255) break;
|
|
|
|
NumberofStreams++;
|
|
|
|
// BPQSetHandle(conn->BPQStream, hWnd);
|
|
|
|
SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask);
|
|
Disconnect(conn->BPQStream);
|
|
}
|
|
|
|
strcpy(pgm, "LINBPQ");
|
|
|
|
InitialiseTCP();
|
|
InitialiseNNTP();
|
|
|
|
SetupListenSet(); // Master set of listening sockets
|
|
|
|
if (EnableUI || MailForInterval)
|
|
SetupUIInterface();
|
|
|
|
if (MailForInterval)
|
|
_beginthread(SendMailForThread, 0, 0);
|
|
|
|
|
|
// Calulate time to run Housekeeping
|
|
{
|
|
struct tm *tm;
|
|
time_t now;
|
|
|
|
now = time(NULL);
|
|
|
|
tm = gmtime(&now);
|
|
|
|
tm->tm_hour = MaintTime / 100;
|
|
tm->tm_min = MaintTime % 100;
|
|
tm->tm_sec = 0;
|
|
|
|
MaintClock = mktime(tm) - (time_t)_MYTIMEZONE;
|
|
|
|
while (MaintClock < now)
|
|
MaintClock += MaintInterval * 3600;
|
|
|
|
Debugprintf("Maint Clock %lld NOW %lld Time to HouseKeeping %lld", (long long)MaintClock, (long long)now, (long long)(MaintClock - now));
|
|
|
|
if (LastHouseKeepingTime)
|
|
{
|
|
if ((now - LastHouseKeepingTime) > MaintInterval * 3600)
|
|
{
|
|
DoHouseKeeping(FALSE);
|
|
}
|
|
}
|
|
for (i = optind; i < argc; i++)
|
|
|
|
{
|
|
if (_stricmp(argv[i], "tidymail") == 0)
|
|
DeleteRedundantMessages();
|
|
|
|
if (_stricmp(argv[i], "nohomebbs") == 0)
|
|
DontNeedHomeBBS = TRUE;
|
|
}
|
|
|
|
printf("Mail Started\n");
|
|
Logprintf(LOG_BBS, NULL, '!', "Mail Starting");
|
|
|
|
APIClock = 0;
|
|
|
|
SendBBSDataToPktMap();
|
|
|
|
}
|
|
}
|
|
|
|
if (NUMBEROFTNCPORTS)
|
|
InitializeTNCEmulator();
|
|
|
|
AGWActive = AGWAPIInit();
|
|
|
|
if (Redirected == 0)
|
|
ConTerm.BPQStream = FindFreeStream();
|
|
|
|
|
|
#ifndef WIN32
|
|
|
|
for (i = 1; i < argc; i++)
|
|
{
|
|
if (_stricmp(argv[i], "daemon") == 0)
|
|
{
|
|
|
|
// Convert to daemon
|
|
|
|
pid_t pid, sid;
|
|
|
|
/* Fork off the parent process */
|
|
pid = fork();
|
|
|
|
if (pid < 0)
|
|
exit(EXIT_FAILURE);
|
|
|
|
if (pid > 0)
|
|
exit(EXIT_SUCCESS);
|
|
|
|
/* Change the file mode mask */
|
|
|
|
umask(0);
|
|
|
|
/* Create a new SID for the child process */
|
|
|
|
sid = setsid();
|
|
|
|
if (sid < 0)
|
|
exit(EXIT_FAILURE);
|
|
|
|
/* Change the current working directory */
|
|
|
|
if ((chdir("/")) < 0)
|
|
exit(EXIT_FAILURE);
|
|
|
|
/* Close out the standard file descriptors */
|
|
|
|
printf("Entering daemon mode\n");
|
|
|
|
close(STDIN_FILENO);
|
|
close(STDOUT_FILENO);
|
|
close(STDERR_FILENO);
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
while (KEEPGOING)
|
|
{
|
|
Sleep(100);
|
|
GetSemaphore(&Semaphore, 2);
|
|
|
|
if (QCOUNT < 10)
|
|
{
|
|
if (CLOSING == FALSE)
|
|
FindLostBuffers();
|
|
CLOSING = TRUE;
|
|
}
|
|
|
|
if (CLOSING)
|
|
{
|
|
if (RunChat)
|
|
{
|
|
CloseChat();
|
|
RunChat = FALSE;
|
|
}
|
|
|
|
if (RunMail)
|
|
{
|
|
int BPQStream, n;
|
|
|
|
RunMail = FALSE;
|
|
|
|
for (n = 0; n < NumberofStreams; n++)
|
|
{
|
|
BPQStream = Connections[n].BPQStream;
|
|
|
|
if (BPQStream)
|
|
{
|
|
SetAppl(BPQStream, 0, 0);
|
|
Disconnect(BPQStream);
|
|
DeallocateStream(BPQStream);
|
|
}
|
|
}
|
|
|
|
// SaveUserDatabase();
|
|
SaveMessageDatabase();
|
|
SaveBIDDatabase();
|
|
SaveConfig(ConfigName);
|
|
}
|
|
|
|
KEEPGOING--; // Give time for links to close
|
|
setbuf(stdout, NULL);
|
|
printf("Closing... %d \r", KEEPGOING);
|
|
}
|
|
|
|
|
|
if (RigReconfigFlag)
|
|
{
|
|
RigReconfigFlag = FALSE;
|
|
Rig_Close();
|
|
Sleep(2000); // Allow CATPTT threads to close
|
|
RigActive = Rig_Init();
|
|
|
|
Consoleprintf("Rigcontrol Reconfiguration Complete");
|
|
}
|
|
|
|
if (APRSReconfigFlag)
|
|
{
|
|
APRSReconfigFlag = FALSE;
|
|
APRSClose();
|
|
APRSActive = Init_APRS();
|
|
|
|
Consoleprintf("APRS Reconfiguration Complete");
|
|
}
|
|
|
|
if (ReconfigFlag)
|
|
{
|
|
int i;
|
|
BPQVECSTRUC * HOSTVEC;
|
|
PEXTPORTDATA PORTVEC=(PEXTPORTDATA)PORTTABLE;
|
|
|
|
ReconfigFlag = FALSE;
|
|
|
|
// SetupBPQDirectory();
|
|
|
|
WritetoConsoleLocal("Reconfiguring ...\n\n");
|
|
OutputDebugString("BPQ32 Reconfiguring ...\n");
|
|
|
|
|
|
for (i=0;i<NUMBEROFPORTS;i++)
|
|
{
|
|
if (PORTVEC->PORTCONTROL.PORTTYPE == 0x10) // External
|
|
{
|
|
if (PORTVEC->PORT_EXT_ADDR)
|
|
{
|
|
// SaveWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER);
|
|
// SaveAXIPWindowPos(PORTVEC->PORTCONTROL.PORTNUMBER);
|
|
// CloseDriverWindow(PORTVEC->PORTCONTROL.PORTNUMBER);
|
|
PORTVEC->PORT_EXT_ADDR(5,PORTVEC->PORTCONTROL.PORTNUMBER, NULL); // Close External Ports
|
|
}
|
|
}
|
|
PORTVEC->PORTCONTROL.PORTCLOSECODE(&PORTVEC->PORTCONTROL);
|
|
PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER;
|
|
}
|
|
|
|
IPClose();
|
|
APRSClose();
|
|
Rig_Close();
|
|
CloseTNCEmulator();
|
|
|
|
if (AGWActive)
|
|
AGWAPITerminate();
|
|
|
|
WL2KReports = NULL;
|
|
|
|
// Sleep(2000);
|
|
|
|
Consoleprintf("G8BPQ AX25 Packet Switch System Version %s %s", TextVerstring, Datestring);
|
|
Consoleprintf(VerCopyright);
|
|
|
|
Start();
|
|
|
|
INITIALISEPORTS();
|
|
|
|
SetApplPorts();
|
|
|
|
GetUIConfig();
|
|
|
|
FreeConfig();
|
|
|
|
for (i=1; i<68; i++) // Include Telnet, APRS, IP Vec
|
|
{
|
|
HOSTVEC=&BPQHOSTVECTOR[i-1];
|
|
|
|
HOSTVEC->HOSTTRACEQ=0;
|
|
|
|
if (HOSTVEC->HOSTSESSION !=0)
|
|
{
|
|
// Had a connection
|
|
|
|
HOSTVEC->HOSTSESSION=0;
|
|
HOSTVEC->HOSTFLAGS |=3; // Disconnected
|
|
|
|
// PostMessage(HOSTVEC->HOSTHANDLE, BPQMsg, i, 4);
|
|
}
|
|
}
|
|
|
|
OpenReportingSockets();
|
|
|
|
WritetoConsoleLocal("\n\nReconfiguration Complete\n");
|
|
|
|
if (IPRequired) IPActive = Init_IP();
|
|
|
|
APRSActive = Init_APRS();
|
|
|
|
if (ISPort == 0)
|
|
IGateEnabled = 0;
|
|
|
|
RigActive = Rig_Init();
|
|
|
|
if (NUMBEROFTNCPORTS)
|
|
{
|
|
FreeSemaphore(&Semaphore);
|
|
InitializeTNCEmulator();
|
|
GetSemaphore(&Semaphore, 2);
|
|
}
|
|
|
|
FreeSemaphore(&Semaphore);
|
|
AGWActive = AGWAPIInit();
|
|
GetSemaphore(&Semaphore, 2);
|
|
|
|
OutputDebugString("BPQ32 Reconfiguration Complete\n");
|
|
}
|
|
|
|
if (IPActive) Poll_IP();
|
|
if (RigActive) Rig_Poll();
|
|
if (APRSActive) Poll_APRS();
|
|
CheckWL2KReportTimer();
|
|
|
|
TIMERINTERRUPT();
|
|
|
|
FreeSemaphore(&Semaphore);
|
|
|
|
if (Redirected == 0)
|
|
ConTermPoll();
|
|
|
|
if (NUMBEROFTNCPORTS)
|
|
TNCTimer();
|
|
|
|
if (AGWActive)
|
|
Poll_AGW();
|
|
|
|
DRATSPoll();
|
|
|
|
HTTPTimer();
|
|
|
|
if (ReportTimer)
|
|
{
|
|
ReportTimer--;
|
|
|
|
if (ReportTimer == 0)
|
|
{
|
|
ReportTimer = REPORTINTERVAL;
|
|
SendLocation();
|
|
}
|
|
}
|
|
|
|
Slowtimer++;
|
|
|
|
if (RunChat)
|
|
{
|
|
ChatPollStreams();
|
|
ChatTrytoSend();
|
|
|
|
if (Slowtimer > 100) // 10 secs
|
|
{
|
|
ChatTimer();
|
|
}
|
|
}
|
|
|
|
if (RunMail)
|
|
{
|
|
PollStreams();
|
|
|
|
if ((Slowtimer % 20) == 0)
|
|
FWDTimerProc();
|
|
|
|
if (Slowtimer > 100) // 10 secs
|
|
{
|
|
time_t NOW = time(NULL);
|
|
struct tm * tm;
|
|
|
|
TCPTimer();
|
|
BBSSlowTimer();
|
|
|
|
if (MaintClock < NOW)
|
|
{
|
|
while (MaintClock < NOW) // in case large time step
|
|
MaintClock += MaintInterval * 3600;
|
|
|
|
Debugprintf("|Enter HouseKeeping");
|
|
DoHouseKeeping(FALSE);
|
|
}
|
|
|
|
if (APIClock < NOW)
|
|
{
|
|
SendBBSDataToPktMap();
|
|
APIClock = NOW + 7200; // Every 2 hours
|
|
}
|
|
|
|
|
|
tm = gmtime(&NOW);
|
|
|
|
if (tm->tm_wday == 0) // Sunday
|
|
{
|
|
if (GenerateTrafficReport && (LastTrafficTime + 86400) < NOW)
|
|
{
|
|
CreateBBSTrafficReport();
|
|
LastTrafficTime = NOW;
|
|
}
|
|
}
|
|
}
|
|
TCPFastTimer();
|
|
TrytoSend();
|
|
}
|
|
|
|
if (Slowtimer > 100)
|
|
Slowtimer = 0;
|
|
}
|
|
|
|
printf("Closing Ports\n");
|
|
|
|
CloseTNCEmulator();
|
|
|
|
if (AGWActive)
|
|
AGWAPITerminate();
|
|
|
|
if (needAIS)
|
|
SaveAIS();
|
|
|
|
// Close Ports
|
|
|
|
PORTVEC=(PEXTPORTDATA)PORTTABLE;
|
|
|
|
for (i=0;i<NUMBEROFPORTS;i++)
|
|
{
|
|
if (PORTVEC->PORTCONTROL.PORTTYPE == 0x10) // External
|
|
{
|
|
if (PORTVEC->PORT_EXT_ADDR)
|
|
{
|
|
PORTVEC->PORT_EXT_ADDR(5, PORTVEC->PORTCONTROL.PORTNUMBER, NULL);
|
|
}
|
|
}
|
|
PORTVEC=(PEXTPORTDATA)PORTVEC->PORTCONTROL.PORTPOINTER;
|
|
}
|
|
|
|
if (AUTOSAVE)
|
|
SaveNodes();
|
|
|
|
if (AUTOSAVEMH)
|
|
SaveMH();
|
|
|
|
if (IPActive)
|
|
IPClose();
|
|
|
|
if (RunMail)
|
|
FreeWebMailMallocs();
|
|
|
|
upnpClose();
|
|
|
|
// Close any open logs
|
|
|
|
for (i = 0; i < 4; i++)
|
|
{
|
|
if (LogHandle[i])
|
|
fclose(LogHandle[i]);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int APIENTRY WritetoConsole(char * buff)
|
|
{
|
|
return WritetoConsoleLocal(buff);
|
|
}
|
|
|
|
int WritetoConsoleLocal(char * buff)
|
|
{
|
|
return printf("%s", buff);
|
|
}
|
|
|
|
#ifdef WIN32
|
|
void * VCOMExtInit(struct PORTCONTROL * PortEntry);
|
|
void * V4ExtInit(EXTPORTDATA * PortEntry);
|
|
#endif
|
|
//UINT SoundModemExtInit(EXTPORTDATA * PortEntry);
|
|
//UINT BaycomExtInit(EXTPORTDATA * PortEntry);
|
|
|
|
void * AEAExtInit(struct PORTCONTROL * PortEntry);
|
|
void * MPSKExtInit(EXTPORTDATA * PortEntry);
|
|
void * HALExtInit(struct PORTCONTROL * PortEntry);
|
|
|
|
void * AGWExtInit(struct PORTCONTROL * PortEntry);
|
|
void * KAMExtInit(struct PORTCONTROL * PortEntry);
|
|
void * WinmorExtInit(EXTPORTDATA * PortEntry);
|
|
void * SCSExtInit(struct PORTCONTROL * PortEntry);
|
|
void * TrackerExtInit(EXTPORTDATA * PortEntry);
|
|
void * TrackerMExtInit(EXTPORTDATA * PortEntry);
|
|
|
|
void * TelnetExtInit(EXTPORTDATA * PortEntry);
|
|
void * UZ7HOExtInit(EXTPORTDATA * PortEntry);
|
|
void * FLDigiExtInit(EXTPORTDATA * PortEntry);
|
|
void * ETHERExtInit(struct PORTCONTROL * PortEntry);
|
|
void * AXIPExtInit(struct PORTCONTROL * PortEntry);
|
|
void * ARDOPExtInit(EXTPORTDATA * PortEntry);
|
|
void * VARAExtInit(EXTPORTDATA * PortEntry);
|
|
void * SerialExtInit(EXTPORTDATA * PortEntry);
|
|
void * WinRPRExtInit(EXTPORTDATA * PortEntry);
|
|
void * HSMODEMExtInit(EXTPORTDATA * PortEntry);
|
|
void * FreeDataExtInit(EXTPORTDATA * PortEntry);
|
|
void * KISSHFExtInit(EXTPORTDATA * PortEntry);
|
|
|
|
void * InitializeExtDriver(PEXTPORTDATA PORTVEC)
|
|
{
|
|
// Only works with built in drivers
|
|
|
|
UCHAR Value[20];
|
|
|
|
strcpy(Value,PORTVEC->PORT_DLL_NAME);
|
|
|
|
_strupr(Value);
|
|
|
|
#ifndef FREEBSD
|
|
#ifndef MACBPQ
|
|
if (strstr(Value, "BPQETHER"))
|
|
return ETHERExtInit;
|
|
#endif
|
|
#endif
|
|
if (strstr(Value, "BPQAXIP"))
|
|
return AXIPExtInit;
|
|
|
|
if (strstr(Value, "BPQTOAGW"))
|
|
return AGWExtInit;
|
|
|
|
if (strstr(Value, "AEAPACTOR"))
|
|
return AEAExtInit;
|
|
|
|
if (strstr(Value, "HALDRIVER"))
|
|
return HALExtInit;
|
|
|
|
#ifdef WIN32
|
|
|
|
if (strstr(Value, "BPQVKISS"))
|
|
return VCOMExtInit;
|
|
|
|
if (strstr(Value, "V4"))
|
|
return V4ExtInit;
|
|
|
|
#endif
|
|
/*
|
|
if (strstr(Value, "SOUNDMODEM"))
|
|
return (UINT) SoundModemExtInit;
|
|
|
|
if (strstr(Value, "BAYCOM"))
|
|
return (UINT) BaycomExtInit;
|
|
*/
|
|
if (strstr(Value, "MULTIPSK"))
|
|
return MPSKExtInit;
|
|
|
|
if (strstr(Value, "KAMPACTOR"))
|
|
return KAMExtInit;
|
|
|
|
if (strstr(Value, "WINMOR"))
|
|
return WinmorExtInit;
|
|
|
|
if (strstr(Value, "SCSPACTOR"))
|
|
return SCSExtInit;
|
|
|
|
if (strstr(Value, "SCSTRACKER"))
|
|
return TrackerExtInit;
|
|
|
|
if (strstr(Value, "TRKMULTI"))
|
|
return TrackerMExtInit;
|
|
|
|
if (strstr(Value, "UZ7HO"))
|
|
return UZ7HOExtInit;
|
|
|
|
if (strstr(Value, "FLDIGI"))
|
|
return FLDigiExtInit;
|
|
|
|
if (strstr(Value, "TELNET"))
|
|
return TelnetExtInit;
|
|
|
|
if (strstr(Value, "ARDOP"))
|
|
return ARDOPExtInit;
|
|
|
|
if (strstr(Value, "VARA"))
|
|
return VARAExtInit;
|
|
|
|
if (strstr(Value, "KISSHF"))
|
|
return KISSHFExtInit;
|
|
|
|
if (strstr(Value, "SERIAL"))
|
|
return SerialExtInit;
|
|
|
|
if (strstr(Value, "WINRPR"))
|
|
return WinRPRExtInit;
|
|
|
|
if (strstr(Value, "HSMODEM"))
|
|
return HSMODEMExtInit;
|
|
|
|
if (strstr(Value, "FREEDATA"))
|
|
return FreeDataExtInit;
|
|
|
|
return(0);
|
|
}
|
|
|
|
int APIENTRY Restart()
|
|
{
|
|
CLOSING = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
int APIENTRY Reboot()
|
|
{
|
|
// Run sudo shutdown -r -f
|
|
#ifdef WIN32
|
|
STARTUPINFO SInfo;
|
|
PROCESS_INFORMATION PInfo;
|
|
char Cmd[] = "shutdown -r -f";
|
|
|
|
|
|
SInfo.cb=sizeof(SInfo);
|
|
SInfo.lpReserved=NULL;
|
|
SInfo.lpDesktop=NULL;
|
|
SInfo.lpTitle=NULL;
|
|
SInfo.dwFlags=0;
|
|
SInfo.cbReserved2=0;
|
|
SInfo.lpReserved2=NULL;
|
|
|
|
return CreateProcess(NULL, Cmd, NULL, NULL, FALSE,0 ,NULL ,NULL, &SInfo, &PInfo);
|
|
return 0;
|
|
#else
|
|
|
|
char * arg_list[] = {NULL, NULL, NULL, NULL, NULL};
|
|
pid_t child_pid;
|
|
char * Context;
|
|
signal(SIGCHLD, SIG_IGN); // Silently (and portably) reap children.
|
|
|
|
arg_list[0] = "sudo";
|
|
arg_list[1] = "shutdown";
|
|
arg_list[2] = "now";
|
|
arg_list[3] = "-r";
|
|
|
|
// Fork and Exec shutdown
|
|
|
|
// Duplicate this process.
|
|
|
|
child_pid = fork();
|
|
|
|
if (child_pid == -1)
|
|
{
|
|
printf ("Reboot fork() Failed\n");
|
|
return 0;
|
|
}
|
|
|
|
if (child_pid == 0)
|
|
{
|
|
execvp (arg_list[0], arg_list);
|
|
|
|
/* The execvp function returns only if an error occurs. */
|
|
|
|
printf ("Failed to run shutdown\n");
|
|
exit(0); // Kill the new process
|
|
}
|
|
return TRUE;
|
|
#endif
|
|
|
|
}
|
|
|
|
int APIENTRY Reconfig()
|
|
{
|
|
if (!ProcessConfig())
|
|
{
|
|
return (0);
|
|
}
|
|
SaveNodes();
|
|
WritetoConsoleLocal("Nodes Saved\n");
|
|
ReconfigFlag=TRUE;
|
|
WritetoConsoleLocal("Reconfig requested ... Waiting for Timer Poll\n");
|
|
return 1;
|
|
}
|
|
|
|
int APRSWriteLog(char * msg);
|
|
|
|
VOID MonitorAPRSIS(char * Msg, size_t MsgLen, BOOL TX)
|
|
{
|
|
char Line[300];
|
|
char Copy[300];
|
|
int Len;
|
|
struct tm * TM;
|
|
time_t NOW;
|
|
|
|
if (LogAPRSIS == 0)
|
|
return;
|
|
|
|
if (MsgLen > 250)
|
|
return;
|
|
|
|
// Mustn't change Msg
|
|
|
|
memcpy(Copy, Msg, MsgLen);
|
|
Copy[MsgLen] = 0;
|
|
|
|
NOW = time(NULL);
|
|
TM = gmtime(&NOW);
|
|
|
|
Len = sprintf_s(Line, 299, "%02d:%02d:%02d%c %s", TM->tm_hour, TM->tm_min, TM->tm_sec, (TX)? 'T': 'R', Copy);
|
|
|
|
APRSWriteLog(Line);
|
|
|
|
}
|
|
|
|
struct TNCINFO * TNC;
|
|
|
|
#ifndef WIN32
|
|
|
|
#include <time.h>
|
|
#include <sys/time.h>
|
|
|
|
#ifndef MACBPQ
|
|
#ifdef __MACH__
|
|
|
|
#include <mach/mach_time.h>
|
|
|
|
#define CLOCK_REALTIME 0
|
|
#define CLOCK_MONOTONIC 0
|
|
|
|
|
|
|
|
int clock_gettime(int clk_id, struct timespec *t){
|
|
mach_timebase_info_data_t timebase;
|
|
mach_timebase_info(&timebase);
|
|
uint64_t time;
|
|
time = mach_absolute_time();
|
|
double nseconds = ((double)time * (double)timebase.numer)/((double)timebase.denom);
|
|
double seconds = ((double)time * (double)timebase.numer)/((double)timebase.denom * 1e9);
|
|
t->tv_sec = seconds;
|
|
t->tv_nsec = nseconds;
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
|
|
uint64_t GetTickCount()
|
|
{
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_REALTIME, &ts);
|
|
return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
|
|
}
|
|
|
|
|
|
|
|
void SetWindowText(HWND hWnd, char * lpString)
|
|
{
|
|
return;
|
|
};
|
|
|
|
BOOL SetDlgItemText(HWND hWnd, int item, char * lpString)
|
|
{
|
|
return 0;
|
|
};
|
|
|
|
#endif
|
|
|
|
int GetListeningPortsPID(int Port)
|
|
{
|
|
#ifdef WIN32
|
|
|
|
MIB_TCPTABLE_OWNER_PID * TcpTable = NULL;
|
|
PMIB_TCPROW_OWNER_PID Row;
|
|
int dwSize = 0;
|
|
unsigned int n;
|
|
|
|
// Get PID of process for this TCP Port
|
|
|
|
// Get Length of table
|
|
|
|
GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);
|
|
|
|
TcpTable = malloc(dwSize);
|
|
GetExtendedTcpTable(TcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_LISTENER, 0);
|
|
|
|
for (n = 0; n < TcpTable->dwNumEntries; n++)
|
|
{
|
|
Row = &TcpTable->table[n];
|
|
|
|
if (Row->dwLocalPort == Port && Row->dwState == MIB_TCP_STATE_LISTEN)
|
|
{
|
|
return Row->dwOwningPid;
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
return 0; // Not found
|
|
}
|
|
|
|
|
|
|
|
VOID Check_Timer()
|
|
{
|
|
}
|
|
|
|
VOID POSTDATAAVAIL(){};
|
|
|
|
COLORREF Colours[256] = {0,
|
|
RGB(0,0,0), RGB(0,0,128), RGB(0,0,192), RGB(0,0,255), // 1 - 4
|
|
RGB(0,64,0), RGB(0,64,128), RGB(0,64,192), RGB(0,64,255), // 5 - 8
|
|
RGB(0,128,0), RGB(0,128,128), RGB(0,128,192), RGB(0,128,255), // 9 - 12
|
|
RGB(0,192,0), RGB(0,192,128), RGB(0,192,192), RGB(0,192,255), // 13 - 16
|
|
RGB(0,255,0), RGB(0,255,128), RGB(0,255,192), RGB(0,255,255), // 17 - 20
|
|
|
|
RGB(6425,0,0), RGB(64,0,128), RGB(64,0,192), RGB(0,0,255), // 21
|
|
RGB(64,64,0), RGB(64,64,128), RGB(64,64,192), RGB(64,64,255),
|
|
RGB(64,128,0), RGB(64,128,128), RGB(64,128,192), RGB(64,128,255),
|
|
RGB(64,192,0), RGB(64,192,128), RGB(64,192,192), RGB(64,192,255),
|
|
RGB(64,255,0), RGB(64,255,128), RGB(64,255,192), RGB(64,255,255),
|
|
|
|
RGB(128,0,0), RGB(128,0,128), RGB(128,0,192), RGB(128,0,255), // 41
|
|
RGB(128,64,0), RGB(128,64,128), RGB(128,64,192), RGB(128,64,255),
|
|
RGB(128,128,0), RGB(128,128,128), RGB(128,128,192), RGB(128,128,255),
|
|
RGB(128,192,0), RGB(128,192,128), RGB(128,192,192), RGB(128,192,255),
|
|
RGB(128,255,0), RGB(128,255,128), RGB(128,255,192), RGB(128,255,255),
|
|
|
|
RGB(192,0,0), RGB(192,0,128), RGB(192,0,192), RGB(192,0,255), // 61
|
|
RGB(192,64,0), RGB(192,64,128), RGB(192,64,192), RGB(192,64,255),
|
|
RGB(192,128,0), RGB(192,128,128), RGB(192,128,192), RGB(192,128,255),
|
|
RGB(192,192,0), RGB(192,192,128), RGB(192,192,192), RGB(192,192,255),
|
|
RGB(192,255,0), RGB(192,255,128), RGB(192,255,192), RGB(192,255,255),
|
|
|
|
RGB(255,0,0), RGB(255,0,128), RGB(255,0,192), RGB(255,0,255), // 81
|
|
RGB(255,64,0), RGB(255,64,128), RGB(255,64,192), RGB(255,64,255),
|
|
RGB(255,128,0), RGB(255,128,128), RGB(255,128,192), RGB(255,128,255),
|
|
RGB(255,192,0), RGB(255,192,128), RGB(255,192,192), RGB(255,192,255),
|
|
RGB(255,255,0), RGB(255,255,128), RGB(255,255,192), RGB(255,255,255)
|
|
};
|
|
|
|
|
|
//VOID SendRPBeacon(struct TNCINFO * TNC)
|
|
//{
|
|
//}
|
|
|
|
int PollStreams()
|
|
{
|
|
int state,change;
|
|
ConnectionInfo * conn;
|
|
int n;
|
|
struct UserInfo * user = NULL;
|
|
char ConnectedMsg[] = "*** CONNECTED ";
|
|
|
|
for (n = 0; n < NumberofStreams; n++)
|
|
{
|
|
conn = &Connections[n];
|
|
|
|
DoReceivedData(conn->BPQStream);
|
|
DoBBSMonitorData(conn->BPQStream);
|
|
|
|
SessionState(conn->BPQStream, &state, &change);
|
|
|
|
if (change == 1)
|
|
{
|
|
if (state == 1) // Connected
|
|
{
|
|
GetSemaphore(&ConSemaphore, 0);
|
|
Connected(conn->BPQStream);
|
|
FreeSemaphore(&ConSemaphore);
|
|
}
|
|
else
|
|
{
|
|
GetSemaphore(&ConSemaphore, 0);
|
|
Disconnected(conn->BPQStream);
|
|
FreeSemaphore(&ConSemaphore);
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
VOID CloseConsole(int Stream)
|
|
{
|
|
}
|
|
|
|
#ifndef WIN32
|
|
|
|
int V4ProcessReceivedData(struct TNCINFO * TNC)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef FREEBSD
|
|
|
|
char * gcvt(double _Val, int _NumOfDigits, char * _DstBuf)
|
|
{
|
|
sprintf(_DstBuf, "%f", _Val);
|
|
return _DstBuf;
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|