MainFormUnit.cpp 129 KB
Newer Older
1 2 3 4 5 6
/* Synchronet Control Panel (GUI Borland C++ Builder Project for Win32) */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
7
 * Copyright Rob Swindell - http://www.synchro.net/copyright.html			*
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *																			*
 * This program 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 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

//---------------------------------------------------------------------------
deuce's avatar
deuce committed
23
#include "sbbs.h"           // unixtodstr()
24
#include <vcl.h>
rswindell's avatar
rswindell committed
25
#include <vcl/Registry.hpp>	/* TRegistry */
26 27 28 29 30
#pragma hdrstop
#include <winsock.h>		// IPPORT_TELNET, INADDR_ANY
#include <process.h> 		// _beginthread()
#include <io.h>
#include <stdio.h>
rswindell's avatar
rswindell committed
31 32
#include <sys/stat.h>
#include <sys/locking.h>
33 34 35 36 37
#include <fcntl.h>
#include <share.h>

#include "MainFormUnit.h"
#include "TelnetFormUnit.h"
38
#include "EventsFormUnit.h"
39
#include "ServicesFormUnit.h"
40
#include "FtpFormUnit.h"
41
#include "WebFormUnit.h"
42 43
#include "MailFormUnit.h"
#include "NodeFormUnit.h"
44

45 46 47 48 49 50
#include "StatsFormUnit.h"
#include "ClientFormUnit.h"
#include "CtrlPathDialogUnit.h"
#include "TelnetCfgDlgUnit.h"
#include "MailCfgDlgUnit.h"
#include "FtpCfgDlgUnit.h"
51
#include "WebCfgDlgUnit.h"
52
#include "ServicesCfgDlgUnit.h"
53 54 55
#include "AboutBoxFormUnit.h"
#include "CodeInputFormUnit.h"
#include "TextFileEditUnit.h"
56
#include "UserListFormUnit.h"
57
#include "PropertiesDlgUnit.h"
58
#include "ConfigWizardUnit.h"
59
#include "PreviewFormUnit.h"
60
#include "LoginAttemptsFormUnit.h"
61

62
#include "sbbs_ini.h"		// sbbs_read_ini()
63
#include "userdat.h"		// lastuser()
64
#include "ntsvcs.h"			// NTSVC_NAME_*
65 66 67

//---------------------------------------------------------------------------
#pragma package(smart_init)
rswindell's avatar
rswindell committed
68
#pragma link "trayicon"
69
#pragma link "Trayicon"
70 71 72 73
#pragma resource "*.dfm"
TMainForm *MainForm;

#define LOG_TIME_FMT "  m/d  hh:mm:ssa/p"
74
#define STATUSBAR_LAST_PANEL  6
75

76 77 78 79 80 81
/* Service functions are NT-only, must call dynamically :-( */
typedef WINADVAPI SC_HANDLE (WINAPI *OpenSCManager_t)(LPCTSTR,LPCTSTR,DWORD);
typedef WINADVAPI SC_HANDLE (WINAPI *OpenService_t)(SC_HANDLE,LPCTSTR,DWORD);
typedef WINADVAPI BOOL (WINAPI *StartService_t)(SC_HANDLE,DWORD,LPCTSTR*);
typedef WINADVAPI BOOL (WINAPI *ControlService_t)(SC_HANDLE,DWORD,LPSERVICE_STATUS);
typedef WINADVAPI BOOL (WINAPI *QueryServiceStatus_t)(SC_HANDLE,LPSERVICE_STATUS);
82
typedef WINADVAPI BOOL (WINAPI *QueryServiceConfig_t)(SC_HANDLE,LPQUERY_SERVICE_CONFIG,DWORD,LPDWORD);
83 84 85 86 87 88 89
typedef WINADVAPI BOOL (WINAPI *CloseServiceHandle_t)(SC_HANDLE);

OpenSCManager_t 		openSCManager;
OpenService_t 			openService;
StartService_t  		startService;
ControlService_t    	controlService;
QueryServiceStatus_t    queryServiceStatus;
90
QueryServiceConfig_t    queryServiceConfig;
91 92 93 94 95
CloseServiceHandle_t	closeServiceHandle;

SC_HANDLE       hSCManager;
SC_HANDLE	    bbs_svc;
SC_HANDLE	    ftp_svc;
rswindell's avatar
rswindell committed
96
SC_HANDLE	    web_svc;
97 98 99 100
SC_HANDLE	    mail_svc;
SC_HANDLE	    services_svc;
SERVICE_STATUS	bbs_svc_status;
SERVICE_STATUS	ftp_svc_status;
rswindell's avatar
rswindell committed
101
SERVICE_STATUS	web_svc_status;
102 103
SERVICE_STATUS	mail_svc_status;
SERVICE_STATUS	services_svc_status;
104 105 106 107
QUERY_SERVICE_CONFIG*	bbs_svc_config;
DWORD					bbs_svc_config_size;
QUERY_SERVICE_CONFIG*	ftp_svc_config;
DWORD					ftp_svc_config_size;
rswindell's avatar
rswindell committed
108 109
QUERY_SERVICE_CONFIG*	web_svc_config;
DWORD					web_svc_config_size;
110 111 112 113
QUERY_SERVICE_CONFIG*	mail_svc_config;
DWORD					mail_svc_config_size;
QUERY_SERVICE_CONFIG*	services_svc_config;
DWORD					services_svc_config_size;
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
const char* LogLevelDesc[] = {   "Emergency"
                                ,"Alert"
                                ,"Critical"
                                ,"Error"
                                ,"Warning"
                                ,"Notice"
                                ,"Normal"
                                ,"Debug"
                            };
const TColor LogLevelColor[] = {
                                 clRed
                                ,clRed
                                ,clRed
                                ,clRed
                                ,clFuchsia	
Rob Swindell's avatar
Rob Swindell committed
130
                                ,clSkyBlue
131
                                ,clBlack    /* not used */
Rob Swindell's avatar
Rob Swindell committed
132
                                ,clLime
133 134
                                };

135 136 137 138 139 140
link_list_t bbs_log_list;
link_list_t event_log_list;
link_list_t mail_log_list;
link_list_t ftp_log_list;
link_list_t web_log_list;
link_list_t services_log_list;
141
link_list_t	login_attempt_list;
142

143 144
bool clearLoginAttemptList = false;

145
DWORD	MaxLogLen=20000;
146
int     threads=1;
147 148 149
time_t  initialized=0;
static	str_list_t recycle_semfiles;
static  str_list_t shutdown_semfiles;
150
bool    terminating=false;
151 152
ulong   errors;
AnsiString ErrorSoundFile;
153

154 155 156
static void errormsg(void* p, int level, const char* msg)
{
    errors++;
157

158 159 160
    if(MainForm->SoundToggle->Checked)
        PlaySound(ErrorSoundFile.c_str(), NULL, SND_ASYNC|SND_FILENAME);
}
161

162
static void thread_up(void* p, BOOL up, BOOL setuid)
163
{
164 165
	char str[128];
	static HANDLE mutex;
166

167 168 169
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
170 171 172 173
    if(up)
	    threads++;
    else if(threads>0)
    	threads--;
174
    ReleaseMutex(mutex);
175 176 177 178
}

int sockets=0;

179
void socket_open(void* p, BOOL open)
180 181
{
	char 	str[128];
182
	static HANDLE mutex;
183

184 185 186
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
187 188 189 190
    if(open)
	    sockets++;
    else if(sockets>0)
    	sockets--;
191
    ReleaseMutex(mutex);
192 193 194 195 196
}

int clients=0;
int total_clients=0;

197
static void client_add(void* p, BOOL add)
198 199 200 201 202 203 204 205 206 207
{
	char 	str[128];

    if(add) {
	    clients++;
        total_clients++;
    } else if(clients>0)
    	clients--;
}

208
static void client_on(void* p, BOOL on, int sock, client_t* client, BOOL update)
209 210 211 212
{
    char    str[128];
    int     i,j;
    time_t  t;
213
	static  HANDLE mutex;
214 215
    TListItem*  Item;

216 217 218 219
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
    WaitForSingleObject(ClientForm->ListMutex,INFINITE);
220 221 222 223 224 225

    /* Search for exising entry for this socket */
    for(i=0;i<ClientForm->ListView->Items->Count;i++) {
        if(ClientForm->ListView->Items->Item[i]->Caption.ToIntDef(0)==sock)
            break;
    }
226
    if(i>=ClientForm->ListView->Items->Count) {
227 228 229
		if(update)	{ /* Can't update a non-existing entry */
			ReleaseMutex(mutex);
			ReleaseMutex(ClientForm->ListMutex);
230
			return;
231
		}
232
        i=-1;
233
	}
234

235 236
    if(on) {
	    if(!update)
237
	        client_add(NULL, TRUE);
238
    } else { // Off
239
        client_add(NULL, FALSE);
240 241
        if(i>=0)
            ClientForm->ListView->Items->Delete(i);
242 243
        ReleaseMutex(mutex);
        ReleaseMutex(ClientForm->ListMutex);
244 245 246
        return;
    }
    if(client!=NULL && client->size==sizeof(client_t)) {
247
        t=time(NULL);
248 249 250 251
        if(i>=0) {
            Item=ClientForm->ListView->Items->Item[i];
        } else {
            Item=ClientForm->ListView->Items->Add();
252
            Item->Data=(void*)t;
253 254 255 256 257 258 259 260
            Item->Caption=sock;
        }
        Item->SubItems->Clear();
        Item->SubItems->Add(client->protocol);
        Item->SubItems->Add(client->user);
        Item->SubItems->Add(client->addr);
        Item->SubItems->Add(client->host);
        Item->SubItems->Add(client->port);
261
        t-=(time_t)Item->Data;
262 263 264
        sprintf(str,"%d:%02d",t/60,t%60);
        Item->SubItems->Add(str);
    }
265 266
    ReleaseMutex(mutex);
    ReleaseMutex(ClientForm->ListMutex);
267 268
}

269
static int lputs(void* p, int level, const char *str)
270
{
271
    log_msg_t   msg;
272 273
	link_list_t* list = (link_list_t*)p;
	log_msg_t*	last;
274

275
	msg.repeated = 0;
276
    msg.level = level;
277
    GetLocalTime(&msg.time);
278
    SAFECOPY(msg.buf, str);
279 280 281 282 283 284 285 286 287 288 289 290
	listLock(list);
	BOOL unique = TRUE;
	if(list->last != NULL) {
		last = (log_msg_t*)list->last->data;
		if(strcmp(last->buf, msg.buf) == 0) {
			last->repeated++;
			unique = FALSE;
		}
	}
	if(unique)
		listPushNodeData(list, &msg, sizeof(msg));
	listUnlock(list);
291
    return strlen(msg.buf);
292
}
293

294
static void log_msg(TRichEdit* Log, log_msg_t* msg)
295
{
296 297
    AnsiString Line=SystemTimeToDateTime(msg->time).FormatString(LOG_TIME_FMT)+"  ";
    Line+=AnsiString(msg->buf).Trim();
298
	if(msg->repeated)
299
		Line += " [x" + AnsiString(msg->repeated + 1) + "]";
300
    Log->SelLength=0;
301
	Log->SelStart=-1;
302 303 304
    Log->SelAttributes->Assign(
        MainForm->LogAttributes(msg->level, Log->Color, Log->Font));
	Log->Lines->Add(Line);
305 306 307 308 309 310 311
}

static void logged_msgs(TRichEdit* Log)
{
    while(MaxLogLen && Log->Lines->Count >= MaxLogLen)
        Log->Lines->Delete(0);
	SendMessage(Log->Handle, WM_VSCROLL, SB_BOTTOM, NULL);
312 313 314 315 316
}

static void bbs_log_msg(log_msg_t* msg)
{
	log_msg(TelnetForm->Log, msg);
317 318
}

319
static void bbs_status(void* p, const char *str)
320
{
321
	static HANDLE mutex;
322

323 324 325
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
326 327 328

	TelnetForm->Status->Caption=AnsiString(str);

329
    ReleaseMutex(mutex);
330 331
}

332
static void bbs_clients(void* p, int clients)
333
{
334
	static HANDLE mutex;
335 336 337 338
    static save_clients;

    save_clients=clients;

339 340 341
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
342 343 344 345 346 347

    TelnetForm->ProgressBar->Max
    	=(MainForm->bbs_startup.last_node
	    -MainForm->bbs_startup.first_node)+1;
	TelnetForm->ProgressBar->Position=clients;

348
    ReleaseMutex(mutex);
349 350
}

351
static void bbs_terminated(void* p, int code)
352 353 354 355
{
	Screen->Cursor=crDefault;
	MainForm->TelnetStart->Enabled=true;
	MainForm->TelnetStop->Enabled=false;
356
	MainForm->TelnetRecycle->Enabled=false;
357 358
    MainForm->TelnetPause->Enabled=false;
    MainForm->TelnetPause->Checked=false;    
359
    Application->ProcessMessages();
360
}
361
static void bbs_started(void* p)
362 363 364 365
{
	Screen->Cursor=crDefault;
	MainForm->TelnetStart->Enabled=false;
    MainForm->TelnetStop->Enabled=true;
366
    MainForm->TelnetRecycle->Enabled=true;
367 368
    MainForm->TelnetPause->Enabled=true;
    MainForm->TelnetPause->Checked=false;        
369
    Application->ProcessMessages();
370 371 372 373
}
static void bbs_start(void)
{
	Screen->Cursor=crAppStart;
374
    bbs_status(NULL,"Starting");
375 376

    FILE* fp=fopen(MainForm->ini_file,"r");
377
    sbbs_read_ini(fp, MainForm->ini_file
378 379 380 381 382 383 384 385 386
        ,&MainForm->global
        ,NULL   ,&MainForm->bbs_startup
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,NULL
        );
    if(fp!=NULL)
        fclose(fp);
387

388
	_beginthread((void(*)(void*))bbs_thread,0,&MainForm->bbs_startup);
389
    Application->ProcessMessages();
390 391
}

392
static void event_log_msg(log_msg_t* msg)
393
{
394
	log_msg(EventsForm->Log, msg);
395 396
}

397
static void services_log_msg(log_msg_t* msg)
398
{
399
	log_msg(ServicesForm->Log, msg);
400 401
}

402
static void services_status(void* p, const char *str)
rswindell's avatar
rswindell committed
403
{
404
	static HANDLE mutex;
rswindell's avatar
rswindell committed
405

406 407 408
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
rswindell's avatar
rswindell committed
409 410 411

	ServicesForm->Status->Caption=AnsiString(str);

412
    ReleaseMutex(mutex);
rswindell's avatar
rswindell committed
413 414
}

415
static void services_terminated(void* p, int code)
rswindell's avatar
rswindell committed
416 417 418 419
{
	Screen->Cursor=crDefault;
	MainForm->ServicesStart->Enabled=true;
	MainForm->ServicesStop->Enabled=false;
420
    MainForm->ServicesRecycle->Enabled=false;
421 422
    MainForm->ServicesPause->Enabled=false;
    MainForm->ServicesPause->Checked=false;
rswindell's avatar
rswindell committed
423 424
    Application->ProcessMessages();
}
425
static void services_started(void* p)
rswindell's avatar
rswindell committed
426 427 428 429
{
	Screen->Cursor=crDefault;
	MainForm->ServicesStart->Enabled=false;
    MainForm->ServicesStop->Enabled=true;
430
    MainForm->ServicesRecycle->Enabled=true;
431 432
    MainForm->ServicesPause->Enabled=true;
    MainForm->ServicesPause->Checked=false;
rswindell's avatar
rswindell committed
433 434 435
    Application->ProcessMessages();
}

436
static void services_clients(void* p, int clients)
437 438 439
{
}

440
static void mail_log_msg(log_msg_t* msg)
441 442 443
{
	static FILE* LogStream;

444
    if(msg==NULL) {
445 446 447
        if(LogStream!=NULL)
            fclose(LogStream);
        LogStream=NULL;
448
        return;
449
    }
450

451
	log_msg(MailForm->Log, msg);
452 453 454

    if(MainForm->MailLogFile && MainForm->MailStop->Enabled) {
        AnsiString LogFileName
455
            =AnsiString(MainForm->cfg.logs_dir)
456
            +"LOGS\\MS"
457
            +SystemTimeToDateTime(msg->time).FormatString("mmddyy")
458 459 460 461 462 463 464 465 466
            +".LOG";

        if(!FileExists(LogFileName)) {
            if(LogStream!=NULL) {
            	fclose(LogStream);
                LogStream=NULL;
            }
        }
        if(LogStream==NULL)
467
            LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE);
468 469

        if(LogStream!=NULL) {
470
			AnsiString Line=SystemTimeToDateTime(msg->time).FormatString("hh:mm:ss")+"  ";
471
		    Line+=AnsiString(msg->buf).Trim();
472
			if(msg->repeated)
473
				Line += " [x" + AnsiString(msg->repeated + 1) + "]";
474 475 476 477 478 479
	        Line+="\n";
        	fwrite(AnsiString(Line).c_str(),1,Line.Length(),LogStream);
        }
	}
}

480
static void mail_status(void* p, const char *str)
481
{
482
	static HANDLE mutex;
483

484 485 486
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
487 488 489

	MailForm->Status->Caption=AnsiString(str);

490
    ReleaseMutex(mutex);
491 492
}

493
static void mail_clients(void* p, int clients)
494
{
495
	static HANDLE mutex;
496

497 498 499
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
500 501 502 503

    MailForm->ProgressBar->Max=MainForm->mail_startup.max_clients;
	MailForm->ProgressBar->Position=clients;

504
    ReleaseMutex(mutex);
505 506
}

507
static void mail_terminated(void* p, int code)
508 509 510 511
{
	Screen->Cursor=crDefault;
	MainForm->MailStart->Enabled=true;
	MainForm->MailStop->Enabled=false;
512
    MainForm->MailRecycle->Enabled=false;
513 514
    MainForm->MailPause->Enabled=false;
    MainForm->MailPause->Checked=false;
515
    Application->ProcessMessages();
516
}
517
static void mail_started(void* p)
518 519 520 521
{
	Screen->Cursor=crDefault;
	MainForm->MailStart->Enabled=false;
    MainForm->MailStop->Enabled=true;
522
    MainForm->MailRecycle->Enabled=true;
523 524
    MainForm->MailPause->Enabled=true;
    MainForm->MailPause->Checked=false;    
525
    Application->ProcessMessages();
526 527 528 529
}
static void mail_start(void)
{
	Screen->Cursor=crAppStart;
530
    mail_status(NULL, "Starting");
531 532

    FILE* fp=fopen(MainForm->ini_file,"r");
533
    sbbs_read_ini(fp, MainForm->ini_file
534 535 536 537 538 539 540 541 542 543
        ,&MainForm->global
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,&MainForm->mail_startup
        ,NULL   ,NULL
        );
    if(fp!=NULL)
        fclose(fp);

544
	_beginthread((void(*)(void*))mail_server,0,&MainForm->mail_startup);
545
    Application->ProcessMessages();
546 547
}

548
static void ftp_log_msg(log_msg_t* msg)
549 550 551
{
	static FILE* LogStream;

552
    if(msg==NULL) {
553 554 555
        if(LogStream!=NULL)
            fclose(LogStream);
        LogStream=NULL;
556
        return;
557
    }
558

559
	log_msg(FtpForm->Log, msg);
560

561 562
    if(MainForm->FtpLogFile && MainForm->FtpStop->Enabled) {
        AnsiString LogFileName
563
            =AnsiString(MainForm->cfg.logs_dir)
564
            +"LOGS\\FS"
565
            +SystemTimeToDateTime(msg->time).FormatString("mmddyy")
566 567 568 569 570 571 572 573 574 575
            +".LOG";

        if(!FileExists(LogFileName)) {
            FileClose(FileCreate(LogFileName));
            if(LogStream!=NULL) {
                fclose(LogStream);
                LogStream=NULL;
            }
        }
        if(LogStream==NULL)
576
            LogStream=_fsopen(LogFileName.c_str(),"a",SH_DENYNONE);
577 578

        if(LogStream!=NULL) {
579
            AnsiString Line=SystemTimeToDateTime(msg->time).FormatString("hh:mm:ss")+"  ";
580
            Line+=AnsiString(msg->buf).Trim();
581
			if(msg->repeated)
582
				Line += " [x" + AnsiString(msg->repeated + 1) + "]";
583 584 585 586 587 588
            Line+="\n";
        	fwrite(AnsiString(Line).c_str(),1,Line.Length(),LogStream);
        }
	}
}

589
static void ftp_status(void* p, const char *str)
590
{
591
	static HANDLE mutex;
592

593 594 595
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
596 597 598

	FtpForm->Status->Caption=AnsiString(str);

599
    ReleaseMutex(mutex);
600 601
}

602
static void ftp_clients(void* p, int clients)
603
{
604
	static HANDLE mutex;
605

606 607 608
    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);
609 610 611 612

    FtpForm->ProgressBar->Max=MainForm->ftp_startup.max_clients;
	FtpForm->ProgressBar->Position=clients;

613
    ReleaseMutex(mutex);
614 615
}

616
static void ftp_terminated(void* p, int code)
617 618 619 620
{
	Screen->Cursor=crDefault;
	MainForm->FtpStart->Enabled=true;
	MainForm->FtpStop->Enabled=false;
621
    MainForm->FtpRecycle->Enabled=false;
622 623
    MainForm->FtpPause->Enabled=false;
    MainForm->FtpPause->Checked=false;
624
    Application->ProcessMessages();
625
}
626
static void ftp_started(void* p)
627 628 629 630
{
	Screen->Cursor=crDefault;
	MainForm->FtpStart->Enabled=false;
    MainForm->FtpStop->Enabled=true;
631
    MainForm->FtpRecycle->Enabled=true;
632 633
    MainForm->FtpPause->Enabled=true;
    MainForm->FtpPause->Checked=false;    
634
    Application->ProcessMessages();
635 636 637 638
}
static void ftp_start(void)
{
	Screen->Cursor=crAppStart;
639
    ftp_status(NULL, "Starting");
640 641

    FILE* fp=fopen(MainForm->ini_file,"r");
642
    sbbs_read_ini(fp, MainForm->ini_file
643 644 645 646 647 648 649 650 651
        ,&MainForm->global
        ,NULL   ,NULL
        ,NULL   ,&MainForm->ftp_startup
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,NULL
        );
    if(fp!=NULL)
        fclose(fp);
652

653
	_beginthread((void(*)(void*))ftp_server,0,&MainForm->ftp_startup);
654
    Application->ProcessMessages();
655 656
}
//---------------------------------------------------------------------------
657
static void web_log_msg(log_msg_t* msg)
rswindell's avatar
rswindell committed
658 659 660
{
	static FILE* LogStream;

661
    if(msg==NULL) {
rswindell's avatar
rswindell committed
662 663 664
        if(LogStream!=NULL)
            fclose(LogStream);
        LogStream=NULL;
665
        return;
rswindell's avatar
rswindell committed
666 667
    }

668
	log_msg(WebForm->Log, msg);
rswindell's avatar
rswindell committed
669 670
}

671
static void web_status(void* p, const char *str)
rswindell's avatar
rswindell committed
672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691
{
	static HANDLE mutex;

    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);

	WebForm->Status->Caption=AnsiString(str);

    ReleaseMutex(mutex);
}

static void web_clients(void* p, int clients)
{
	static HANDLE mutex;

    if(!mutex)
    	mutex=CreateMutex(NULL,false,NULL);
	WaitForSingleObject(mutex,INFINITE);

692
    WebForm->ProgressBar->Max=MainForm->web_startup.max_clients;
rswindell's avatar
rswindell committed
693 694 695 696 697 698 699 700 701 702 703
	WebForm->ProgressBar->Position=clients;

    ReleaseMutex(mutex);
}

static void web_terminated(void* p, int code)
{
	Screen->Cursor=crDefault;
	MainForm->WebStart->Enabled=true;
	MainForm->WebStop->Enabled=false;
    MainForm->WebRecycle->Enabled=false;
704
    MainForm->WebPause->Enabled=false;  // caused exception
705
    MainForm->WebPause->Checked=false;
rswindell's avatar
rswindell committed
706 707 708 709 710 711 712 713
    Application->ProcessMessages();
}
static void web_started(void* p)
{
	Screen->Cursor=crDefault;
	MainForm->WebStart->Enabled=false;
    MainForm->WebStop->Enabled=true;
    MainForm->WebRecycle->Enabled=true;
714 715
    MainForm->WebPause->Enabled=true;
    MainForm->WebPause->Checked=false;    
rswindell's avatar
rswindell committed
716 717 718 719 720 721 722
    Application->ProcessMessages();
}
static void web_start(void)
{
	Screen->Cursor=crAppStart;
    web_status(NULL, "Starting");

723
    FILE* fp=fopen(MainForm->ini_file,"r");
724
    sbbs_read_ini(fp, MainForm->ini_file
725 726 727 728 729 730 731 732 733
        ,&MainForm->global
        ,NULL   ,NULL
        ,NULL   ,NULL
        ,NULL   ,&MainForm->web_startup
        ,NULL   ,NULL
        ,NULL   ,NULL
        );
    if(fp!=NULL)
        fclose(fp);
rswindell's avatar
rswindell committed
734 735 736 737 738

	_beginthread((void(*)(void*))web_server,0,&MainForm->web_startup);
    Application->ProcessMessages();
}
//---------------------------------------------------------------------------
739 740 741 742 743 744 745 746 747 748 749 750
/* Server recycle callback (read relevant startup .ini file section)		*/
static void recycle(void* cbdata)
{
    char            str[MAX_PATH*2];
    FILE*           fp=NULL;
	bbs_startup_t*  bbs=NULL;
	ftp_startup_t*  ftp=NULL;
	web_startup_t*  web=NULL;
	mail_startup_t* mail=NULL;
	services_startup_t* services=NULL;

    SAFEPRINTF(str,"Reading %s",MainForm->ini_file);
751
	if(cbdata==(void*)&bbs_log_list) {
752
		bbs=&MainForm->bbs_startup;
753 754
        lputs(cbdata,LOG_INFO,str);
	} else if(cbdata==(void*)&ftp_log_list) {
755
		ftp=&MainForm->ftp_startup;
756 757
        lputs(cbdata,LOG_INFO,str);
    } else if(cbdata==(void*)&web_log_list) {
758
		web=&MainForm->web_startup;
759 760
        lputs(cbdata,LOG_INFO,str);
    } else if(cbdata==(void*)&mail_log_list) {
761
		mail=&MainForm->mail_startup;
762 763
        lputs(cbdata,LOG_INFO,str);
	} else if(cbdata==(void*)&services_log_list) {
764
		services=&MainForm->services_startup;
765
        lputs(cbdata,LOG_INFO,str);
766
    }
767

768
    fp=fopen(MainForm->ini_file,"r");
769
    sbbs_read_ini(fp, MainForm->ini_file
770 771 772 773 774 775 776 777 778
        ,&MainForm->global
        ,NULL   ,bbs
        ,NULL   ,ftp
        ,NULL   ,web
        ,NULL   ,mail
        ,NULL   ,services
        );
    if(fp!=NULL)
        fclose(fp);
779
	MainForm->SetControls();
780
}
781 782 783 784
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
        : TForm(Owner)
{
785
    /* Defaults */
786
    memset(&global,0,sizeof(global));
787 788
    SAFECOPY(global.ctrl_dir,"c:\\sbbs\\ctrl\\");
    global.js.max_bytes=JAVASCRIPT_MAX_BYTES;
789
    global.js.time_limit=JAVASCRIPT_TIME_LIMIT;
790 791
    global.js.gc_interval=JAVASCRIPT_GC_INTERVAL;
    global.js.yield_interval=JAVASCRIPT_YIELD_INTERVAL;
792
    global.sem_chk_freq=DEFAULT_SEM_CHK_FREQ;		/* seconds */
793 794

    /* These are SBBSCTRL-specific */
795
    LoginCommand="telnet://127.0.0.1";
796
    ConfigCommand="%sscfg.exe %s -l25";
797 798
    MinimizeToSysTray=false;
    UndockableForms=false;
799
    UseFileAssociations=true;
800
    Initialized=false;
801

802 803
	loginAttemptListInit(&login_attempt_list);

804 805
    char* p;
    if((p=getenv("SBBSCTRL"))!=NULL)
806 807 808 809 810
        SAFECOPY(global.ctrl_dir,p);
   	p=lastchar(global.ctrl_dir);
	if(*p!='/' && *p!='\\')
    	strcat(global.ctrl_dir,"\\");
        
811 812
    memset(&bbs_startup,0,sizeof(bbs_startup));
    bbs_startup.size=sizeof(bbs_startup);
813 814
    bbs_startup.cbdata=&bbs_log_list;
    bbs_startup.event_cbdata=&event_log_list;    
815 816
    bbs_startup.first_node=1;
    bbs_startup.last_node=4;
817
	bbs_startup.options=BBS_OPT_XTRN_MINIMIZED;
818
	bbs_startup.telnet_port=IPPORT_TELNET;
819
    bbs_startup.rlogin_port=513;
820 821
	bbs_startup.lputs=lputs;
    bbs_startup.event_lputs=lputs;
822
    bbs_startup.errormsg=errormsg;
823 824 825
    bbs_startup.status=bbs_status;
    bbs_startup.clients=bbs_clients;
    bbs_startup.started=bbs_started;
826
    bbs_startup.recycle=recycle;
827 828 829 830
    bbs_startup.terminated=bbs_terminated;
    bbs_startup.thread_up=thread_up;
    bbs_startup.client_on=client_on;
    bbs_startup.socket_open=socket_open;
831
	bbs_startup.login_attempt_list=&login_attempt_list;
832 833 834

    memset(&mail_startup,0,sizeof(mail_startup));
    mail_startup.size=sizeof(mail_startup);
835
    mail_startup.cbdata=&mail_log_list;
836
    mail_startup.smtp_port=IPPORT_SMTP;
837
    mail_startup.relay_port=IPPORT_SMTP;
838
    mail_startup.pop3_port=110;
839
	mail_startup.lputs=lputs;
840
    mail_startup.errormsg=errormsg;
841 842 843
    mail_startup.status=mail_status;
    mail_startup.clients=mail_clients;
    mail_startup.started=mail_started;
844
    mail_startup.recycle=recycle;
845 846 847 848 849
    mail_startup.terminated=mail_terminated;
    mail_startup.options=MAIL_OPT_ALLOW_POP3;
    mail_startup.thread_up=thread_up;
    mail_startup.client_on=client_on;
    mail_startup.socket_open=socket_open;
850 851
    mail_startup.max_delivery_attempts=50;
    mail_startup.rescan_frequency=3600;  /* 60 minutes */
852
    mail_startup.lines_per_yield=10;