Skip to content
Snippets Groups Projects
sbbscon.c 12.71 KiB
/* sbbscon.c */

/* Synchronet vanilla/console-mode "front-end" */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
 * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html		*
 *																			*
 * 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										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

/* Synchronet-specific headers */
#include "conwrap.h"	/* kbhit/getch */
#include "sbbs.h"
#include "ftpsrvr.h"	/* ftp_startup_t, ftp_server */
#include "mailsrvr.h"	/* mail_startup_t, mail_server */
#include "services.h"	/* services_startup_t, services_thread */

/* Constants */
#define SBBSCON_VERSION		"1.10"

/* Global variables */
BOOL				bbs_running=FALSE;
bbs_startup_t		bbs_startup;
BOOL				ftp_running=FALSE;
ftp_startup_t		ftp_startup;
BOOL				mail_running=FALSE;
mail_startup_t		mail_startup;
BOOL				services_running=FALSE;
services_startup_t	services_startup;

static const char* prompt = "Command (?=Help): ";

static const char* usage  = "\nusage: %s [[option] [...]]\n"
							"\noptions:\n\n"
							"defaults   show default settings\n"
							"tf<node>   set First Telnet Node Number\n"
							"tl<node>   set Last Telnet Node Number\n"
							"tp<port>   set Telnet Server Port\n"
							"rp<port>   set RLogin Server Port (and enable RLogin Server)\n"
							"fp<port>   set FTP Server Port\n"
							"sp<port>   set SMTP Server Port\n"
							"sr<port>   set SMTP Relay Port\n"
							"pp<port>   set POP3 Server Port\n"
							"\n"
							;

static void lputs(char *str)
{
	static pthread_mutex_t mutex;
	static BOOL mutex_initialized;

	if(!mutex_initialized) {
		pthread_mutex_init(&mutex,NULL);
		mutex_initialized=TRUE;
	}

	pthread_mutex_lock(&mutex);
	printf("\r%*s\r%s\n",strlen(prompt),"",str);
	printf(prompt);
	fflush(stdout);
	pthread_mutex_unlock(&mutex);
}

/************************************************/
/* Truncates white-space chars off end of 'str' */
/************************************************/
static void truncsp(char *str)
{
	uint c;

	c=strlen(str);
	while(c && (uchar)str[c-1]<=' ') c--;
	str[c]=0;
}

/****************************************************************************/
/* BBS local/log print routine												*/
/****************************************************************************/
static int bbs_lputs(char *str)
{
	char		logline[512];
	char		tstr[64];
	time_t		t;
	struct tm*	tm_p;

	t=time(NULL);
	tm_p=localtime(&t);
	if(tm_p==NULL)
		tstr[0]=0;
	else
		sprintf(tstr,"%d/%d %02d:%02d:%02d "
			,tm_p->tm_mon+1,tm_p->tm_mday
			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);

	sprintf(logline,"%sbbs  %.*s",tstr,sizeof(logline)-2,str);
	truncsp(logline);
	lputs(logline);
	
    return(strlen(logline)+1);
}

static void bbs_started(void)
{
	bbs_running=TRUE;
}

static void bbs_terminated(int code)
{
	bbs_running=FALSE;
}

/****************************************************************************/
/* FTP local/log print routine												*/
/****************************************************************************/
static int ftp_lputs(char *str)
{
	char		logline[512];
	char		tstr[64];
	time_t		t;
	struct tm*	tm_p;

	t=time(NULL);
	tm_p=localtime(&t);
	if(tm_p==NULL)
		tstr[0]=0;
	else
		sprintf(tstr,"%d/%d %02d:%02d:%02d "
			,tm_p->tm_mon+1,tm_p->tm_mday
			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);

	sprintf(logline,"%sftp  %.*s",tstr,sizeof(logline)-2,str);
	truncsp(logline);
	lputs(logline);
	
    return(strlen(logline)+1);
}

static void ftp_started(void)
{
	ftp_running=TRUE;
}

static void ftp_terminated(int code)
{
	ftp_running=FALSE;
}

/****************************************************************************/
/* Mail Server local/log print routine										*/
/****************************************************************************/
static int mail_lputs(char *str)
{
	char		logline[512];
	char		tstr[64];
	time_t		t;
	struct tm*	tm_p;

	t=time(NULL);
	tm_p=localtime(&t);
	if(tm_p==NULL)
		tstr[0]=0;
	else
		sprintf(tstr,"%d/%d %02d:%02d:%02d "
			,tm_p->tm_mon+1,tm_p->tm_mday
			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);

	sprintf(logline,"%smail %.*s",tstr,sizeof(logline)-2,str);
	truncsp(logline);
	lputs(logline);
	
    return(strlen(logline)+1);
}

static void mail_started(void)
{
	mail_running=TRUE;
}

static void mail_terminated(int code)
{
	mail_running=FALSE;
}
/****************************************************************************/
/* Services local/log print routine											*/
/****************************************************************************/
static int services_lputs(char *str)
{
	char		logline[512];
	char		tstr[64];
	time_t		t;
	struct tm*	tm_p;

	t=time(NULL);
	tm_p=localtime(&t);
	if(tm_p==NULL)
		tstr[0]=0;
	else
		sprintf(tstr,"%d/%d %02d:%02d:%02d "
			,tm_p->tm_mon+1,tm_p->tm_mday
			,tm_p->tm_hour,tm_p->tm_min,tm_p->tm_sec);

	sprintf(logline,"%ssrvc %.*s",tstr,sizeof(logline)-2,str);
	truncsp(logline);
	lputs(logline);
	
    return(strlen(logline)+1);
}

static void services_started(void)
{
	services_running=TRUE;
}

static void services_terminated(int code)
{
	services_running=FALSE;
}


#ifdef __unix__
void _sighandler_quit(int sig)
{
        // Close threads
        bbs_terminate();
        ftp_terminate();
        mail_terminate();
        while(bbs_running || ftp_running || mail_running)
        mswait(1);

        exit(0);
}
#endif


/****************************************************************************/
/* Main Entry Point															*/
/****************************************************************************/
int main(int argc, char** argv)
{
	int		i;
	char	ch;
	char*	arg;
	char*	ctrl_dir;
	BOOL	quit=FALSE;

	printf("\nSynchronet BBS Console Version %s  Copyright 2001 Rob Swindell\n"
		,SBBSCON_VERSION);

	ctrl_dir=getenv("SBBSCTRL");	/* read from environment variable */
	if(ctrl_dir==NULL)
		ctrl_dir="/sbbs/ctrl/";		/* Not set? Use default */
	/* Initialize BBS startup structure */
    memset(&bbs_startup,0,sizeof(bbs_startup));
    bbs_startup.size=sizeof(bbs_startup);
    bbs_startup.first_node=1;
    bbs_startup.last_node=4;
    bbs_startup.telnet_interface=INADDR_ANY;
	bbs_startup.options|=BBS_OPT_NO_QWK_EVENTS;

#ifdef USE_RLOGIN
	bbs_startup.options|=BBS_OPT_ALLOW_RLOGIN;
#endif

	bbs_startup.lputs=bbs_lputs;
    bbs_startup.started=bbs_started;
    bbs_startup.terminated=bbs_terminated;
/*	These callbacks haven't been created yet
    bbs_startup.status=bbs_status;
    bbs_startup.clients=bbs_clients;
    bbs_startup.thread_up=thread_up;
    bbs_startup.client_on=client_on;
    bbs_startup.socket_open=socket_open;
*/
    strcpy(bbs_startup.ctrl_dir,ctrl_dir);

	/* Initialize FTP startup structure */
    memset(&ftp_startup,0,sizeof(ftp_startup));
    ftp_startup.size=sizeof(ftp_startup);
	ftp_startup.lputs=ftp_lputs;
    ftp_startup.started=ftp_started;
    ftp_startup.terminated=ftp_terminated;
	ftp_startup.options=FTP_OPT_INDEX_FILE|FTP_OPT_ALLOW_QWK;
    strcpy(ftp_startup.index_file_name,"00index");
    strcpy(ftp_startup.ctrl_dir,ctrl_dir);

	/* Initialize Mail Server startup structure */
    memset(&mail_startup,0,sizeof(mail_startup));
    mail_startup.size=sizeof(mail_startup);
	mail_startup.lputs=mail_lputs;
    mail_startup.started=mail_started;
    mail_startup.terminated=mail_terminated;
	mail_startup.options|=MAIL_OPT_ALLOW_POP3;
	/* Spam filtering */
	mail_startup.options|=MAIL_OPT_USE_RBL;	/* Realtime Blackhole List */
	mail_startup.options|=MAIL_OPT_USE_RSS;	/* Relay Spam Stopper */
    strcpy(mail_startup.ctrl_dir,ctrl_dir);

#ifdef __unix__	/* Look up DNS server address */
	{
		FILE*	fp;
		char*	p;
		char	str[128];

		if((fp=fopen("/etc/resolv.conf","r"))!=NULL) {
			while(!feof(fp)) {
				if(fgets(str,sizeof(str),fp)==NULL)
					break;
				truncsp(str);
				p=str;
				while(*p && *p<=' ') p++;	/* skip white-space */
				if(strnicmp(p,"nameserver",10)!=0) /* no match */
					continue;
				p+=10;	/* skip "nameserver" */
				while(*p && *p<=' ') p++;	/* skip more white-space */
				sprintf(mail_startup.dns_server,"%.*s"
					,sizeof(mail_startup.dns_server)-1,p);
				break;
			}
			fclose(fp);
		}
	}
#endif /* __unix__ */

	/* Initialize Services startup structure */
    memset(&services_startup,0,sizeof(services_startup));
    services_startup.size=sizeof(services_startup);
	services_startup.lputs=services_lputs;
    services_startup.started=services_started;
    services_startup.terminated=services_terminated;
    strcpy(services_startup.ctrl_dir,ctrl_dir);

	/* Process arguments */
	for(i=1;i<argc;i++) {
		arg=argv[i];
		if(*arg=='-')/* ignore prepended slashes */
			arg++;
		if(!stricmp(arg,"defaults")) {
			printf("default settings\n");
			return(0);
		}
		switch(toupper(*(arg++))) {
			case 'T':	/* Telnet settings */
				switch(toupper(*(arg++))) {
					case 'P':
						bbs_startup.telnet_port=atoi(arg);
						break;
					case 'F':
						bbs_startup.first_node=atoi(arg);
						break;
					case 'L':
						bbs_startup.last_node=atoi(arg);
						break;
					default:
						printf(usage,argv[0]);
						return(0);
				}
				break;
			case 'R':	/* RLogin */
				bbs_startup.options|=BBS_OPT_ALLOW_RLOGIN;
				switch(toupper(*(arg++))) {
					case 'P':
						bbs_startup.rlogin_port=atoi(arg);
						break;
					default:
						printf(usage,argv[0]);
						return(0);
				}
				break;
			case 'F':	/* FTP */
				switch(toupper(*(arg++))) {
					case 'P':
						ftp_startup.port=atoi(arg);
						break;
					default:
						printf(usage,argv[0]);
						return(0);
				}
				break;
			case 'S':	/* SMTP */
				switch(toupper(*(arg++))) {
					case 'P':
						mail_startup.smtp_port=atoi(arg);
						break;
					case 'R':
					    mail_startup.relay_port=atoi(arg);
						break;
					default:
						printf(usage,argv[0]);
						return(0);
				}
				break;
			case 'P':	/* POP3 */
				switch(toupper(*(arg++))) {
					case 'P':
						mail_startup.pop3_port=atoi(arg);
						break;
					default:
						printf(usage,argv[0]);
						return(0);
				}
				break;
			default:
				printf(usage,argv[0]);
				return(0);
		}
	}

	_beginthread((void(*)(void*))bbs_thread,0,&bbs_startup);
	_beginthread((void(*)(void*))ftp_server,0,&ftp_startup);
	_beginthread((void(*)(void*))mail_server,0,&mail_startup);
	_beginthread((void(*)(void*))services_thread,0,&services_startup);

#ifdef __unix__
	// Set up QUIT-type signals so they clean up properly.
	signal(SIGHUP, _sighandler_quit);
	signal(SIGINT, _sighandler_quit);
	signal(SIGQUIT, _sighandler_quit);
	signal(SIGABRT, _sighandler_quit);
	signal(SIGTERM, _sighandler_quit);
#endif

	if(!isatty(fileno(stdin)))			/* redirected */
		select(0,NULL,NULL,NULL,NULL);	/* so wait here until signaled */
	else								/* interactive */
		while(!quit) {
			ch=getch();
			printf("%c\n",ch);
			switch(ch) {
				case 'q':
					quit=TRUE;
					break;
				default:
					printf("\nSynchronet BBS Console Version %s Help\n\n",SBBSCON_VERSION);
					printf("q   = quit\n");
#if 0	/* to do */	
					printf("n   = node list\n");
					printf("w   = who's online\n");
					printf("l#  = lock node #\n");
					printf("d#  = down node #\n");
					printf("i#  = interrupt node #\n");
					printf("c#  = chat with node #\n");
					printf("s#  = spy on node #\n");
#endif
					lputs("");	/* redisplay prompt */
					break;
			}
		}

	bbs_terminate();
	ftp_terminate();
	mail_terminate();
	services_terminate();

	while(bbs_running || ftp_running || mail_running || services_running)
		mswait(1);

	/* erase the prompt */
	printf("\r%*s\r",strlen(prompt),"");

	return(0);
}