linbpq/LinBPQ.c

2088 lines
41 KiB
C
Raw Normal View History

2022-08-28 09:35:46 +01:00
/*
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>
2023-10-10 22:07:04 +01:00
#include <errno.h>
2022-08-28 09:35:46 +01:00
#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();
2024-06-09 21:48:39 +01:00
VOID GetPGConfig();
2022-08-28 09:35:46 +01:00
2023-10-10 22:07:04 +01:00
extern uint64_t timeLoadedMS;
2022-08-28 09:35:46 +01:00
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 */
2023-10-10 22:07:04 +01:00
extern UCHAR BPQDirectory[260];
extern UCHAR LogDirectory[260];
extern UCHAR ConfigDirectory[260];
// overrides from params
UCHAR LogDir[260] = "";
UCHAR ConfigDir[260] = "";
UCHAR DataDir[260] = "";
2022-08-28 09:35:46 +01:00
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();
2023-06-21 08:21:04 +01:00
static config_t cfg;
static config_setting_t * group;
2022-08-28 09:35:46 +01:00
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;
2023-06-21 08:21:04 +01:00
// 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};
2022-08-28 09:35:46 +01:00
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;
2023-06-21 08:21:04 +01:00
uint64_t MMASK;
2022-08-28 09:35:46 +01:00
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];
2022-11-18 17:03:39 +00:00
BOOL EventsEnabled = 0;
2022-08-28 09:35:46 +01:00
UCHAR * GetBPQDirectory()
{
return BPQDirectory;
}
UCHAR * GetLogDirectory()
{
return LogDirectory;
}
2023-06-21 08:21:04 +01:00
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(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;
}
2023-10-10 22:07:04 +01:00
#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";
2023-06-21 08:21:04 +01:00
int Redirected = 0;
2022-08-28 09:35:46 +01:00
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
2023-06-21 08:21:04 +01:00
// Disable Console Terminal if stdout redirected
2023-07-29 07:23:11 +01:00
// printf("STDOUT %d\n",isatty(STDOUT_FILENO));
// printf("STDIN %d\n",isatty(STDIN_FILENO));
if (!isatty(STDOUT_FILENO) || !isatty(STDIN_FILENO))
2023-06-21 08:21:04 +01:00
Redirected = 1;
2023-10-10 22:07:04 +01:00
timeLoadedMS = GetTickCount();
2022-08-28 09:35:46 +01:00
#endif
2023-10-10 22:07:04 +01:00
printf("G8BPQ AX25 Packet Switch System Version %s %s\n", TextVerstring, Datestring);
printf("%s\n", VerCopyright);
2022-08-28 09:35:46 +01:00
2023-10-10 22:07:04 +01:00
// 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(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;
}
}
}
2022-08-28 09:35:46 +01:00
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
2023-10-10 22:07:04 +01:00
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++)
2022-08-28 09:35:46 +01:00
{
if (_memicmp(argv[i], "logdir=", 7) == 0)
{
strcpy(LogDirectory, &argv[i][7]);
2023-10-10 22:07:04 +01:00
Consoleprintf("Log Directory is %s\n", LogDirectory);
2022-08-28 09:35:46 +01:00
break;
}
}
2023-10-10 22:07:04 +01:00
Consoleprintf("Log Directory is %s", LogDirectory);
2022-08-28 09:35:46 +01:00
// Make sure logs directory exists
sprintf(LogDir, "%s/logs", LogDirectory);
#ifdef WIN32
CreateDirectory(LogDir, NULL);
#else
2023-10-10 22:07:04 +01:00
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;
}
2022-08-28 09:35:46 +01:00
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
2023-10-10 22:07:04 +01:00
for (i = optind; i < argc; i++)
2022-08-28 09:35:46 +01:00
{
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
2023-10-10 22:07:04 +01:00
for (i = optind; i < argc; i++)
2022-08-28 09:35:46 +01:00
{
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);
2024-08-30 10:14:56 +01:00
// See if we need to warn of possible problem with BaseDir moved by installer
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
sprintf(BaseDir, "%s", BPQDirectory);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// Set up file and directory names
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(UserDatabasePath, BaseDir);
strcat(UserDatabasePath, "/");
strcat(UserDatabasePath, UserDatabaseName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(MsgDatabasePath, BaseDir);
strcat(MsgDatabasePath, "/");
strcat(MsgDatabasePath, MsgDatabaseName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(BIDDatabasePath, BaseDir);
strcat(BIDDatabasePath, "/");
strcat(BIDDatabasePath, BIDDatabaseName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(WPDatabasePath, BaseDir);
strcat(WPDatabasePath, "/");
strcat(WPDatabasePath, WPDatabaseName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(BadWordsPath, BaseDir);
strcat(BadWordsPath, "/");
strcat(BadWordsPath, BadWordsName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(NTSAliasesPath, BaseDir);
strcat(NTSAliasesPath, "/");
strcat(NTSAliasesPath, NTSAliasesName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(MailDir, BaseDir);
strcat(MailDir, "/");
strcat(MailDir, "Mail");
2022-08-28 09:35:46 +01:00
#ifdef WIN32
2024-08-30 10:14:56 +01:00
CreateDirectory(MailDir, NULL); // Just in case
2022-08-28 09:35:46 +01:00
#else
2024-08-30 10:14:56 +01:00
mkdir(MailDir, S_IRWXU | S_IRWXG | S_IRWXO);
chmod(MailDir, S_IRWXU | S_IRWXG | S_IRWXO);
2022-08-28 09:35:46 +01:00
#endif
2024-08-30 10:14:56 +01:00
// Make backup copies of Databases
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// CopyConfigFile(ConfigName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
CopyBIDDatabase();
CopyMessageDatabase();
CopyUserDatabase();
CopyWPDatabase();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
SetupMyHA();
SetupFwdAliases();
SetupNTSAliases(NTSAliasesPath);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
GetWPDatabase();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
GetMessageDatabase();
GetUserDatabase();
GetBIDDatabase();
GetBadWordFile();
GetHTMLForms();
GetPGConfig();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// Make sure there is a user record for the BBS, with BBS bit set.
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
user = LookupCall(BBSName);
2022-08-28 09:35:46 +01:00
if (user == NULL)
{
2024-08-30 10:14:56 +01:00
user = AllocateUserRecord(BBSName);
2022-08-28 09:35:46 +01:00
user->Temp = zalloc(sizeof (struct TempUserInfo));
}
if ((user->flags & F_BBS) == 0)
{
// Not Defined as a BBS
2024-08-30 10:14:56 +01:00
if(SetupNewBBS(user))
2022-08-28 09:35:46 +01:00
user->flags |= F_BBS;
}
2024-08-30 10:14:56 +01:00
// if forwarding AMPR mail make sure User/BBS AMPR exists
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (SendAMPRDirect)
{
BOOL NeedSave = FALSE;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
user = LookupCall("AMPR");
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (user == NULL)
{
user = AllocateUserRecord("AMPR");
user->Temp = zalloc(sizeof (struct TempUserInfo));
NeedSave = TRUE;
}
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if ((user->flags & F_BBS) == 0)
{
// Not Defined as a BBS
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (SetupNewBBS(user))
user->flags |= F_BBS;
NeedSave = TRUE;
}
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (NeedSave)
SaveUserDatabase();
}
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// Make sure SYSOPCALL is set
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (SYSOPCall[0] == 0)
strcpy(SYSOPCall, BBSName);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// See if just want to add user (mainly for setup scripts)
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (argc == 5 && _stricmp(argv[1], "--adduser") == 0)
{
BOOL isBBS = FALSE;
char * response;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (_stricmp(argv[4], "TRUE") == 0)
isBBS = TRUE;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
printf("Adding User %s\r\n", argv[2]);
response = AddUser(argv[2], argv[3], isBBS);
printf("%s", response);
exit(0);
}
// Allocate Streams
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(pgm, "BBS");
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
for (i=0; i < MaxStreams; i++)
{
conn = &Connections[i];
conn->BPQStream = FindFreeStream();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (conn->BPQStream == 255) break;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
NumberofStreams++;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// BPQSetHandle(conn->BPQStream, hWnd);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
SetAppl(conn->BPQStream, (i == 0 && EnableUI) ? 0x82 : 2, BBSApplMask);
Disconnect(conn->BPQStream);
}
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
strcpy(pgm, "LINBPQ");
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
InitialiseTCP();
InitialiseNNTP();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
SetupListenSet(); // Master set of listening sockets
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (EnableUI || MailForInterval)
SetupUIInterface();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (MailForInterval)
_beginthread(SendMailForThread, 0, 0);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
// Calulate time to run Housekeeping
{
struct tm *tm;
time_t now;
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
now = time(NULL);
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
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)
2022-08-28 09:35:46 +01:00
{
2024-08-30 10:14:56 +01:00
if ((now - LastHouseKeepingTime) > MaintInterval * 3600)
{
DoHouseKeeping(FALSE);
}
2022-08-28 09:35:46 +01:00
}
2024-08-30 10:14:56 +01:00
for (i = optind; i < argc; i++)
2024-11-05 21:03:15 +00:00
2024-08-30 10:14:56 +01:00
{
if (_stricmp(argv[i], "tidymail") == 0)
DeleteRedundantMessages();
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
if (_stricmp(argv[i], "nohomebbs") == 0)
DontNeedHomeBBS = TRUE;
}
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
printf("Mail Started\n");
Logprintf(LOG_BBS, NULL, '!', "Mail Starting");
2022-08-28 09:35:46 +01:00
2024-08-30 10:14:56 +01:00
}
2022-08-28 09:35:46 +01:00
}
if (NUMBEROFTNCPORTS)
InitializeTNCEmulator();
AGWActive = AGWAPIInit();
2024-11-05 21:03:15 +00:00
if (Redirected == 0)
ConTerm.BPQStream = FindFreeStream();
2022-08-28 09:35:46 +01:00
#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);
2023-06-21 08:21:04 +01:00
if (Redirected == 0)
ConTermPoll();
2022-08-28 09:35:46 +01:00
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();
2024-06-09 21:48:39 +01:00
if ((Slowtimer % 20) == 0)
FWDTimerProc();
2022-08-28 09:35:46 +01:00
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);
}
tm = gmtime(&NOW);
if (tm->tm_wday == 0) // Sunday
{
if (GenerateTrafficReport && (LastTrafficTime + 86400) < NOW)
{
CreateBBSTrafficReport();
2023-12-08 12:26:52 +00:00
LastTrafficTime = NOW;
2022-08-28 09:35:46 +01:00
}
}
}
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);
2023-01-25 10:12:51 +00:00
void * KISSHFExtInit(EXTPORTDATA * PortEntry);
2022-08-28 09:35:46 +01:00
void * InitializeExtDriver(PEXTPORTDATA PORTVEC)
{
// Only works with built in drivers
UCHAR Value[20];
strcpy(Value,PORTVEC->PORT_DLL_NAME);
_strupr(Value);
#ifndef FREEBSD
2023-04-06 13:41:09 +01:00
#ifndef MACBPQ
2022-08-28 09:35:46 +01:00
if (strstr(Value, "BPQETHER"))
return ETHERExtInit;
2023-04-06 13:41:09 +01:00
#endif
2022-08-28 09:35:46 +01:00
#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;
2023-01-25 10:12:51 +00:00
if (strstr(Value, "KISSHF"))
return KISSHFExtInit;
2022-08-28 09:35:46 +01:00
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>
2023-04-06 13:41:09 +01:00
#ifndef MACBPQ
2022-08-28 09:35:46 +01:00
#ifdef __MACH__
#include <mach/mach_time.h>
#define CLOCK_REALTIME 0
#define CLOCK_MONOTONIC 0
2023-10-10 22:07:04 +01:00
2022-08-28 09:35:46 +01:00
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
2023-04-06 13:41:09 +01:00
#endif
2022-08-28 09:35:46 +01:00
2023-10-10 22:07:04 +01:00
uint64_t GetTickCount()
2022-08-28 09:35:46 +01:00
{
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