Skip to content
Snippets Groups Projects
Commit 56ad94b9 authored by Rob Swindell's avatar Rob Swindell :speech_balloon:
Browse files

Remove SBL (Synchronet BBS List) - replaced by sbbslist.js years ago

No need to keep this around, someone might try to build or run it!
parent f778a144
No related branches found
No related tags found
1 merge request!463MRC mods by Codefenix (2024-10-20)
Showing with 0 additions and 4143 deletions
This project (Synchronet BBS List, SBL, the native C version) has been
retired and deprecated in favor of the new Synchronet BBS List (v4,
JavaScript version), a.k.a. exec/sbbslist.js.
See http://wiki.synchro.net/module:sbbslist for details about migrating to the
new Synchronet BBS List.
# Makefile.gnu
#########################################################################
# Makefile for Synchronet BBS List #
# For use with GNU make and GNU C Compiler #
# @format.tab-size 4, @format.use-tabs true #
# #
# Linux: make -f Makefile.gnu #
# Win32: make -f Makefile.gnu os=win32 #
# FreeBSD: make -f Makefile.gnu os=freebsd #
#########################################################################
# $Id: GNUmakefile,v 1.28 2019/08/06 17:06:32 deuce Exp $
# Macros
XSDK = ../sdk
SRC_ROOT ?= ../../src
include $(SRC_ROOT)/build/Common.gmake
ifeq ($(os),sunos)
LDFLAGS += -lnsl -lrt
endif
LDFLAGS += $(XPDEV_LDFLAGS)
vpath %.c $(XSDK)
CFLAGS += -I$(SRC_ROOT)$(DIRSEP)sbbs3 -I$(XSDK) -DUSE_XPDEV $(XPDEV_CFLAGS) $(SMBLIB_CFLAGS) $(HASH_CFLAGS) $(ENCODE_CFLAGS)
$(SBL): $(OBJS)
@echo Linking $@
$(QUIET)$(CC) $(MT_LDFLAGS) $(LDFLAGS) $^ -o $@ $(XPDEV-MT_LIBS)
$(SBL2SMB): $(OBJODIR)$(DIRSEP)sbl2smb$(OFILE) $(HASH_LIB) $(ENCODE_LIB)
@echo Linking $@
$(QUIET)$(CC) $(LDFLAGS) $(SMBLIB_LDFLAGS) $(HASH_LDFLAGS) $(ENCODE_LDFLAGS) $^ -o $@ $(LIBS) $(SMBLIB_LIBS) $(XPDEV_LIBS) $(HASH_LIBS) $(ENCODE_LIBS)
$(SMB2SBL): $(OBJODIR)$(DIRSEP)smb2sbl$(OFILE) $(HASH_LIB) $(ENCODE_LIB)
@echo Linking $@
$(QUIET)$(CC) $(LDFLAGS) $(SMBLIB_LDFLAGS) $(HASH_LDFLAGS) $(ENCODE_LDFLAGS) $^ -o $@ $(SMBLIB_LIBS) $(XPDEV_LIBS) $(HASH_LIBS) $(ENCODE_LIBS)
$(SBLPACK): $(OBJODIR)$(DIRSEP)sblpack$(OFILE)
@echo Linking $@
$(QUIET)$(CC) $(LDFLAGS) $(SMBLIB_LDFLAGS) $^ -o $@ $(XPDEV_LIBS)
$(SBBSLIST): $(OBJODIR)$(DIRSEP)sbbslist$(OFILE)
@echo Linking $@
$(QUIET)$(CC) $(LDFLAGS) $(SMBLIB_LDFLAGS) $^ -o $@ $(XPDEV_LIBS)
##################################################################
# Makefile for SBL (Synchronet BBS List Online External Program) #
# For use with Borland C++ or C++ Builder (for Win32) #
# Tabstop=8 #
##################################################################
# Macros
CC = bcc32
LD = ilink32
XSDK = ..\sdk
!ifndef SRC_ROOT
SRC_ROOT= ..\..\src
!endif
!ifndef XPDEV
XPDEV = $(SRC_ROOT)\xpdev
!endif
!ifndef SBBS_SRC
SBBS_SRC = $(SRC_ROOT)\sbbs3
!endif
!ifndef SMBLIB_SRC
SMBLIB_SRC = $(SRC_ROOT)\smblib
!endif
CFLAGS = -WM -I$(XSDK);$(XPDEV);$(SBBS_SRC);$(SMBLIB_SRC)
CFLAGS = $(CFLAGS) -q -d -H -X- -w-csu -w-pch -w-ccc -w-rch -w-par -w-8004
OBJS = xsdk.obj xsdkvars.obj xsdkwrap.obj
.path.c = .;$(XSDK);$(XPDEV);$(SBBS_SRC)
# Enable auto-dependency checking
.autodepend
.cacheautodepend
# Implicit C Compile Rule
.c.obj:
@$(CC) $(CFLAGS) -c $<
all: sbl.exe smb2sbl.exe sbl2smb.exe sblpack.exe
# Main EXE Link Rule
sbl.exe: $(OBJS) sbl.obj
@echo Linking $@
@$(CC) $(CFLAGS) -e$@ $**
SMBIO = $(XPDEV)/bcc.win32.lib.debug/xpdev_mt.lib $(SMBLIB_SRC)/bcc.win32.lib.debug/smb.lib
sbl2smb.exe: sbl2smb.obj $(SMBIO)
@echo Linking $@
@$(CC) $(CFLAGS) -e$@ $**
smb2sbl.exe: smb2sbl.obj $(SMBIO)
@echo Linking $@
@$(CC) $(CFLAGS) -e$@ $**
sblpack.exe: sblpack.obj
@echo Linking $@
@$(CC) $(CFLAGS) -e$@ $**
clean:
del $(OBJS) $(SMBIO)
\ No newline at end of file
OBJS = $(MTOBJODIR)$(DIRSEP)sbl$(OFILE) \
$(MTOBJODIR)$(DIRSEP)xsdk$(OFILE) \
$(MTOBJODIR)$(DIRSEP)xsdkvars$(OFILE)
/* SBBSLIST.C */
/* Developed 1990-2003 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
/* Converts Synchronet BBS List (SBL.DAB) to HTML file */
#include <stdlib.h> /* realloc */
#include <time.h> /* localtime */
#include "genwrap.h"
#include "telnet.h"
#include "sbldefs.h"
#include "filewrap.h"
#include "sockwrap.h"
char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
,"Jul","Aug","Sep","Oct","Nov","Dec"};
char *nulstr="";
char tmp[256];
#ifdef _WIN32
extern int daylight=0;
extern long timezone=0L;
#endif
#define SORT TRUE
#define VERIFY TRUE
typedef struct {
time_t date;
ulong count;
ulong attempts;
short offset;
} sort_t;
int sort_cmp(sort_t **str1, sort_t **str2)
{
int diff;
/* sort descending by date */
diff=((*str2)->date&0xffff0000)-((*str1)->date&0xffff0000);
if(diff)
return(diff);
/* sort descending by verfication counter */
diff=(((*str2)->count)-((*str1)->count));
if(diff)
return(diff);
/* sort ascending by verification attempts */
return(((*str1)->attempts)-((*str2)->attempts));
}
/****************************************************************************/
/* Generates a 24 character ASCII string that represents the time_t pointer */
/* Used as a replacement for ctime() */
/****************************************************************************/
char *timestr(time_t *intime)
{
static char str[256];
char mer[3],hour;
struct tm *gm;
gm=localtime(intime);
if(gm==NULL) {
sprintf(str,"Invalid time: %08lX",*intime);
return(str);
}
if(gm->tm_hour>=12) {
if(gm->tm_hour==12)
hour=12;
else
hour=gm->tm_hour-12;
strcpy(mer,"pm"); }
else {
if(gm->tm_hour==0)
hour=12;
else
hour=gm->tm_hour;
strcpy(mer,"am"); }
sprintf(str,"%s %s %02d %4d %02d:%02d %s"
,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
,hour,gm->tm_min,mer);
return(str);
}
/****************************************************************************/
/* Converts unix time format (long - time_t) into a char str MM/DD/YY */
/****************************************************************************/
char *unixtodstr(time_t t, char *str)
{
struct tm* tm;
if(!t)
strcpy(str,"00/00/00");
else {
tm=gmtime(&t);
if(tm==NULL)
strcpy(str,"00/00/00");
else {
if(tm->tm_mon>11) { /* DOS leap year bug */
tm->tm_mon=0;
tm->tm_year++; }
if(tm->tm_mday>31)
tm->tm_mday=1;
sprintf(str,"%02u/%02u/%02u",tm->tm_mon+1,tm->tm_mday
,tm->tm_year%100); }
}
return(str);
}
char* html_encode(char *src)
{
static char buf[1024];
int i;
for(i=0;*src;src++)
i+=sprintf(buf+i,"&#%u;",*src);
return(buf);
}
void long_bbs_info(FILE *out, bbs_t bbs)
{
int i;
fprintf(out,"BBS Name: %s since %s\r\n"
,bbs.name,unixtodstr(bbs.birth,tmp));
fprintf(out,"Operator: ");
for(i=0;i<bbs.total_sysops && i<MAX_SYSOPS;i++) {
if(i) {
if(bbs.total_sysops>2)
fprintf(out,", ");
else
fputc(' ',out);
if(!(i%4))
fprintf(out,"\r\n ");
if(i+1==bbs.total_sysops)
fprintf(out,"and "); }
fprintf(out,"%s",bbs.sysop[i]); }
fprintf(out,"\r\n");
fprintf(out,"Software: %-15.15s Nodes: %-5u "
"Users: %-5u Doors: %u\r\n"
,bbs.software,bbs.nodes,bbs.users,bbs.xtrns);
fprintf(out,"Download: %lu files in %u directories of "
"%luMB total space\r\n"
,bbs.files,bbs.dirs,bbs.megs);
fprintf(out,"Messages: %lu messages in %u sub-boards\r\n"
,bbs.msgs,bbs.subs);
fprintf(out,"Networks: ");
for(i=0;i<bbs.total_networks && i<MAX_NETS;i++) {
if(i) {
if(bbs.total_networks>2)
fprintf(out,", ");
else
fputc(' ',out);
if(!(i%3))
fprintf(out,"\r\n ");
if(i+1==bbs.total_networks)
fprintf(out,"and "); }
fprintf(out,"%s [%s]",bbs.network[i],bbs.address[i]); }
fprintf(out,"\r\n");
fprintf(out,"Terminal: ");
for(i=0;i<bbs.total_terminals && i<MAX_TERMS;i++) {
if(i) {
if(bbs.total_terminals>2)
fprintf(out,", ");
else
fputc(' ',out);
if(i+1==bbs.total_terminals)
fprintf(out,"and "); }
fprintf(out,"%s",bbs.terminal[i]); }
fprintf(out,"\r\n\r\n");
for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
fprintf(out,"%-30.30s "
,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
? nulstr : bbs.number[i].modem.location);
if(bbs.number[i].modem.min_rate==0xffff)
fprintf(out,"%s:%d\r\n"
,bbs.number[i].telnet.addr
,bbs.number[i].telnet.port);
else
fprintf(out,"%12.12s %5u %-15.15s "
"Minimum: %u\r\n"
,bbs.number[i].modem.number
,bbs.number[i].modem.max_rate,bbs.number[i].modem.desc
,bbs.number[i].modem.min_rate);
}
fprintf(out,"\r\n");
for(i=0;i<5;i++) {
if(!bbs.desc[i][0])
break;
fprintf(out,"%15s%s\r\n",nulstr,bbs.desc[i]); }
fprintf(out,"\r\n");
fprintf(out,"Entry created on %s by %s\r\n"
,timestr(&bbs.created),bbs.user);
if(bbs.updated && bbs.userupdated[0])
fprintf(out," Last updated on %s by %s\r\n"
,timestr(&bbs.updated),bbs.userupdated);
if(bbs.verified && bbs.userverified[0])
fprintf(out,"Last verified on %s by %s\r\n"
,timestr(&bbs.verified),bbs.userverified);
}
#if 0 /* old way */
u_long resolve_ip(char *addr)
{
HOSTENT* host;
if(isdigit(addr[0]))
return(inet_addr(addr));
if ((host=gethostbyname(addr))==NULL) {
// printf("!ERROR resolving hostname: %s\n",addr);
return(0);
}
return(*((ulong*)host->h_addr_list[0]));
}
#else
u_long resolve_ip(char *addr)
{
HOSTENT* host;
char* p;
if(*addr==0)
return(INADDR_NONE);
for(p=addr;*p;p++)
if(*p!='.' && !isdigit(*p))
break;
if(!(*p))
return(inet_addr(addr));
if((host=gethostbyname(addr))==NULL)
return(INADDR_NONE);
return(*((ulong*)host->h_addr_list[0]));
}
#endif
int telnet_negotiate(SOCKET sock, uchar* buf, int rd, int max_rd)
{
int i;
int rsplen;
uchar rsp[512];
return(rd);
do {
rsplen=0;
for(i=0; i<rd && rsplen<sizeof(rsp)-2;i++) {
if(buf[i]!=TELNET_IAC)
continue;
i++;
printf("telnet cmd: %02X %02X\n"
,buf[i],buf[i+1]);
if(buf[i]==TELNET_DO) {
rsp[rsplen++]=TELNET_IAC;
rsp[rsplen++]=TELNET_WILL;
rsp[rsplen++]=buf[i+1];
}
if(buf[i]==TELNET_DONT) {
rsp[rsplen++]=TELNET_IAC;
rsp[rsplen++]=TELNET_WONT;
rsp[rsplen++]=buf[i+1];
}
i++;
}
if(!rsplen)
break;
printf("telnet rsp: ");
for(i=0; i<rsplen; i++)
printf("%02X ",rsp[i]);
printf("\n");
send(sock,rsp,rsplen,0);
SLEEP(3000);
rd=recv(sock,buf,max_rd,0);
} while(rd>0);
return(rd);
}
int sockreadline(SOCKET socket, char* buf, int len, int timeout)
{
char ch;
int i,rd=0;
time_t start;
fd_set socket_set;
struct timeval tv;
start=time(NULL);
while(rd<len-1) {
tv.tv_sec=0;
tv.tv_usec=0;
FD_ZERO(&socket_set);
FD_SET(socket,&socket_set);
i=select(socket+1,&socket_set,NULL,NULL,&tv);
if(i<1) {
if(i==0) {
if((time(NULL)-start)>=timeout)
return(0);
SLEEP(1);
continue;
}
return(0);
}
i=recv(socket, &ch, 1, 0);
if(i<1)
return(0);
if(ch=='\n' && rd>=1) {
break;
}
buf[rd++]=ch;
}
buf[rd-1]=0;
return(rd);
}
BOOL check_imsg_support(ulong ip_addr)
{
char buf[128];
BOOL success=FALSE;
int rd;
SOCKET sock;
SOCKADDR_IN addr;
printf("\r\nFinger: ");
if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP)) == INVALID_SOCKET) {
printf("!Error %d opening socket\n",ERROR_VALUE);
return(FALSE);
}
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
if(bind(sock, (struct sockaddr *) &addr, sizeof (addr))!=0) {
printf("!bind error %d\n",ERROR_VALUE);
closesocket(sock);
return(FALSE);
}
memset(&addr,0,sizeof(addr));
addr.sin_addr.s_addr = ip_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(79); /* finger */
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr))!=0) {
printf("!connect error %d\n",ERROR_VALUE);
closesocket(sock);
return(FALSE);
}
/* Send query */
strcpy(buf,"?ver\r\n");
send(sock,buf,strlen(buf),0);
/* Get response */
while((rd=sockreadline(sock,buf,sizeof(buf),60))>0) {
printf("%s\n",buf);
if(strstr(buf,"Synchronet")) {
success=TRUE;
break;
}
}
closesocket(sock);
if(success==FALSE)
return(FALSE);
/* Check SMTP server */
printf("SMTP: ");
success=FALSE;
if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP)) == INVALID_SOCKET) {
printf("!Error %d opening socket\n",ERROR_VALUE);
return(FALSE);
}
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
if(bind(sock, (struct sockaddr *) &addr, sizeof (addr))!=0) {
printf("!bind error %d\n",ERROR_VALUE);
closesocket(sock);
return(FALSE);
}
memset(&addr,0,sizeof(addr));
addr.sin_addr.s_addr = ip_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(25); /* SMTP */
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr))!=0) {
printf("!connect error %d\n",ERROR_VALUE);
closesocket(sock);
return(FALSE);
}
/* Get response */
while((rd=sockreadline(sock,buf,sizeof(buf),60))>0) {
printf("%s\r\n",buf);
if(strstr(buf,"Synchronet")) {
success=TRUE;
break;
}
}
closesocket(sock);
return(success);
}
int main(int argc, char **argv)
{
char str[128],name[128],*location,nodes[32],*sysop;
char* mail_to = "&#109;&#97;&#105;&#108;&#116;&#111;&#58;"; /* encoded "mailto:" */
char sysop_email[1024];
char buf[256];
char verify_result[128];
char version[128];
char* p;
char* sp;
char* tp;
char* for_os;
char* fontstr="<FONT FACE=\"Arial\" SIZE=\"-1\">";
char telnet_addr_buf[128];
char* telnet_addr;
char telnet_portstr[32];
ushort telnet_port;
BOOL fingered;
BOOL verified;
ushort index;
int i,j,file,ff,rd;
long l;
ulong ip_addr;
ulong total_systems;
ulong total_attempts=0;
ulong total_verified=0;
FILE *in,*shrt,*lng,*html,*mail,*syncterm;
FILE* ibbs;
ulong ip_list[1000];
ulong ip_total=0;
ulong ip;
bbs_t bbs;
sort_t **sort=NULL;
time_t now;
/* socket stuff */
SOCKET sock;
SOCKADDR_IN addr;
int status; /* Status Code */
#ifdef _WIN32
WSADATA WSAData;
if((status = WSAStartup(MAKEWORD(1,1), &WSAData))!=0) {
printf("!WinSock startup ERROR %d\n", status);
return(1);
}
#endif
#if 0
if(_putenv("TZ=UCT0"))
printf("!putenv() FAILED");
tzset();
#endif
now=time(NULL);
if((i=sopen("sbl.dab",O_RDWR|O_BINARY,SH_DENYNO,S_IREAD|S_IWRITE))==-1) {
printf("error opening SBL.DAB\n");
return(1); }
if((in=fdopen(i,"rb"))==NULL) {
printf("error opening SBL.DAB\n");
return(1); }
if((shrt=fopen("sbbs.lst","wb"))==NULL) {
printf("error opening/creating SBBS.LST\n");
return(1); }
if((lng=fopen("sbbs_det.lst","wb"))==NULL) {
printf("error opening/creating SBBS_DET.LST\n");
return(1); }
if((html=fopen("sbbslist.html","w"))==NULL) {
printf("error opening/creating sbbslist.html\n");
return(1); }
if((ibbs=fopen("sbbsimsg.lst","w"))==NULL) {
printf("error opening/creating sbbsimsg.lst\n");
return(1); }
if((mail=fopen("sysop.lst","w"))==NULL) {
printf("error opening/creating sysop.lst\n");
return(1); }
if((syncterm=fopen("syncterm.lst","w"))==NULL) {
printf("error opening/creating syncterm.lst\n");
return(1); }
fprintf(shrt,"Synchronet BBS List exported from Vertrauen on %s\r\n"
"======================================================="
"\r\n\r\n"
,unixtodstr(time(NULL),str));
fprintf(lng,"Detailed Synchronet BBS List exported from Vertrauen on %s\r\n"
"================================================================"
"\r\n\r\n"
,unixtodstr(time(NULL),str));
fprintf(html,"<HTML><HEAD><TITLE>Synchronet BBS List</TITLE></HEAD>\n");
fprintf(html,"<BODY><FONT FACE=\"Arial\" SIZE=\"-1\">\n");
printf("Sorting...");
fseek(in,0L,SEEK_SET);
i=j=0;
while(1) {
if(!fread(&bbs,sizeof(bbs_t),1,in))
break;
j++;
printf("%4u\b\b\b\b",j);
if(!bbs.name[0] || strnicmp(bbs.software,"SYNCHRONET",10)) {
// printf("%s\n",bbs.software);
continue;
}
i++;
if((sort=(sort_t **)realloc(sort
,sizeof(sort_t *)*i))==NULL) {
printf("\r\n\7Memory allocation error\r\n");
return(1); }
if((sort[i-1]=(sort_t *)malloc(sizeof(sort_t)
))==NULL) {
printf("\r\n\7Memory allocation error\r\n");
return(1); }
sort[i-1]->date=bbs.verified;
sort[i-1]->count=bbs.verification_count;
sort[i-1]->attempts=bbs.verification_attempts;
sort[i-1]->offset=j-1;
}
total_systems=i;
#if SORT
qsort((void *)sort,total_systems,sizeof(sort[0])
,(int(*)(const void *, const void *))sort_cmp);
#endif
printf(" Done.\n");
printf("Creating index...");
sprintf(str,"SBBSSORT.NDX");
if((file=open(str,O_RDWR|O_CREAT|O_TRUNC|O_BINARY,S_IWRITE|S_IREAD))==-1) {
printf("\n\7Error creating %s\n",str);
return(1); }
for(j=0;j<(int)total_systems;j++)
write(file,&sort[j]->offset,2);
lseek(file,0L,SEEK_SET);
printf(" Done.\n");
printf("Creating lists...\n");
fprintf(html,"<CENTER>");
fprintf(html,"<H1><I><A HREF=http://www.synchro.net>Synchronet"
"</A> BBS List</H1></I>\n");
fprintf(html,"(%d systems) exported from "
"<B><A HREF=http://vert.synchro.net>Vertrauen</A></B> on %s\n"
,total_systems ,timestr(&now));
fprintf(html,"<P></CENTER>\n");
fprintf(html,"<TABLE WIDTH=\"100%%\">\n");
fprintf(html,"<COLGROUP ALIGN=LEFT><COLGROUP ALIGN=LEFT>"
"<COLGROUP ALIGN=CENTER><COLGROUP ALIGN=CENTER>"
"<COLGROUP ALIGN=RIGHT><COLGROUP ALIGN=CENTER>\n");
fprintf(html,"<TR BGCOLOR=\"#000000\">\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">BBS Name\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Sysop\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Location\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Nodes\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Modem/Telnet Address\n");
fprintf(html,"<TH><FONT FACE=\"Arial\" SIZE=\"-1\" COLOR=\"#FFFFFF\">Verification Results\n");
ff=0;
while(1) {
if(read(file,&index,2)!=2)
break;
fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
if(!fread(&bbs,sizeof(bbs_t),1,in))
break;
long_bbs_info(lng,bbs);
if(ff)
fprintf(lng,"\x0c\r\n");
else
fprintf(lng,"\r\n---------------------------------------------"
"----------------------------------\r\n\r\n");
ff=!ff;
verified=FALSE;
fingered=FALSE;
total_attempts++;
for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
if(!i) {
if(strchr(bbs.sysop_email,'@')) {
sprintf(sysop_email,"<A HREF=%s%s>%s</A>"
,mail_to,html_encode(bbs.sysop_email),bbs.sysop[0]);
sysop=sysop_email;
} else
sysop=bbs.sysop[0];
sprintf(nodes,"%u",bbs.nodes);
} else {
sysop="";
nodes[0]=0;
}
if(bbs.number[i].modem.min_rate==0xffff) {
telnet_port=bbs.number[i].telnet.port;
if(telnet_port==0)
telnet_port=23;
strcpy(telnet_addr_buf,bbs.number[i].telnet.addr);
telnet_addr=telnet_addr_buf;
if(!strnicmp(telnet_addr,"TELNET:",7))
telnet_addr+=7;
if(!strnicmp(telnet_addr,"//",2))
telnet_addr+=2;
p=strchr(telnet_addr,':');
if(p!=NULL) {
*p=0;
telnet_port=atoi(p+1);
}
printf("Resolving IP address for: %s",telnet_addr);
ip_addr=resolve_ip(telnet_addr);
printf("\n");
if(i) {
if(ip_addr==0 || ip_addr==INADDR_NONE)
continue; /* bad hostname/IP, ignore */
for(ip=0;ip<ip_total;ip++)
if(ip_addr==ip_list[ip])
break;
if(ip<ip_total) /* already verified, ignore */
continue;
}
}
if(i && !stricmp(bbs.number[i].modem.number,bbs.number[i-1].modem.number))
continue; // duplicate
if(i && !stricmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location))
location="";
else
location=bbs.number[i].modem.location;
fprintf(shrt,"%-25.25s %-25.25s %s\r\n"
,i ? "" : bbs.name, location
,bbs.number[i].modem.number);
if(!i) {
fprintf(html,"<A NAME=\"%s.index\">",bbs.name);
fprintf(html,"<TR BGCOLOR=\"#EEEEEE\">");
} else
fprintf(html,"<TR>");
sprintf(name,"<A HREF=\"#%s\">%s</A>",bbs.name,bbs.name);
if(bbs.number[i].modem.min_rate==0xffff) {
#if 0 // moved
telnet_port=bbs.number[i].telnet.port;
if(telnet_port==0)
telnet_port=23;
strcpy(telnet_addr_buf,bbs.number[i].telnet.addr);
telnet_addr=telnet_addr_buf;
if(!strnicmp(telnet_addr,"TELNET:",7))
telnet_addr+=7;
if(!strnicmp(telnet_addr,"//",2))
telnet_addr+=2;
p=strchr(telnet_addr,':');
if(p!=NULL) {
*p=0;
telnet_port=atoi(p+1);
}
#endif
#if !VERIFY /* set to 1 for no-verification */
verified=TRUE;
strcpy(verify_result,"<B>v3.00x for Win32</B>");
#else
printf("Verifying %d/%d %s:%d "
,total_attempts,total_systems,telnet_addr,telnet_port);
// ip_addr=resolve_ip(telnet_addr); /* already done above */
if(!ip_addr || ip_addr==INADDR_NONE)
strcpy(verify_result,"bad hostname");
else {
if((sock = socket(AF_INET,SOCK_STREAM,IPPROTO_IP)) == INVALID_SOCKET) {
printf("\n\7Error %d opening socket",ERROR_VALUE);
return(1);
}
memset(&addr,0,sizeof(addr));
addr.sin_family = AF_INET;
if(bind(sock, (struct sockaddr *) &addr, sizeof (addr))!=0) {
closesocket(sock);
printf("!ERROR %d binding to socket %d",ERROR_VALUE, sock);
return(1);
}
memset(&addr,0,sizeof(addr));
addr.sin_addr.s_addr = ip_addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(telnet_port);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr))!=0)
sprintf(verify_result,"no connect (%ld)"
,ERROR_VALUE);
else {
l=1;
ioctlsocket(sock, FIONBIO, &l);
SLEEP(3000);
buf[0]=0;
rd=recv(sock,buf,sizeof(buf)-1,0);
if((rd=telnet_negotiate(sock,buf,rd,sizeof(buf)-1))<1)
sprintf(verify_result,"no data (%ld)"
,rd==SOCKET_ERROR ? ERROR_VALUE : rd);
else {
buf[rd]=0;
sp=buf+(rd-1);
while(*sp && sp!=buf) sp--; // Skip garbage (with null)
if(*sp==0)
sp++;
p=strstr(sp,"Synchronet");
if(p!=NULL && (for_os=strstr(sp," for "))!=NULL) {
verified=TRUE;
p=strstr(sp,"Version ");
if(p==NULL)
version[0]=0;
else {
for_os[12]=0;
p+=8; /* skip "version" */
tp=strchr(p,'\r');
if(tp!=NULL) *tp=0;
truncsp(p);
tp=strchr(for_os+5,' ');
if(tp!=NULL) *tp=0;
truncsp(for_os);
sprintf(version,"v%s%s",p,for_os);
}
sprintf(verify_result,"<B>%s</B>"
,version[0] ? version : "Verified");
} else {
printf("rd=%d buf='%s' sp='%s'\n",rd,buf,sp);
sprintf(verify_result,"non-Synchronet");
}
/* Check Finger */
if(!fingered) { /* not already checked */
for(ip=0;ip<ip_total;ip++)
if(ip_addr==ip_list[ip])
break;
if(ip>=ip_total && check_imsg_support(ip_addr)) {
fingered=TRUE;
printf("[IM]");
fprintf(ibbs,"%-63s %s\n"
,telnet_addr, inet_ntoa(addr.sin_addr));
}
}
}
}
ip_list[ip_total++]=ip_addr;
closesocket(sock);
}
printf("%s\n",verify_result);
bbs.verification_attempts++;
#endif
if(telnet_port==23)
telnet_portstr[0]=0;
else
sprintf(telnet_portstr,":%d",telnet_port);
if(verified && i==0) {
fprintf(syncterm,"[%s]\nConnectionType=Telnet\nPort=%d\nAddress=%s\n\n"
,bbs.name
,telnet_port
,telnet_addr);
}
fprintf(html,"<TD><B>%s%s</B><TD>%s%s<TD>%s%s<TD>%s%s<TD%s>"
"<A HREF=telnet://%s%s>%s%s%s%s%s</A><TD%s>%s%s\n"
,fontstr,i ? "":name
,fontstr,sysop
,fontstr,location
,fontstr,nodes
,i ? " BGCOLOR=\"#EEEEEE\"":""
,telnet_addr, telnet_portstr
,fontstr
,verified ? "<B>":"", telnet_addr, telnet_portstr
, verified ? "</B>":""
,i ? " BGCOLOR=\"#EEEEEE\"":""
,fontstr,verify_result);
} else {
fprintf(syncterm,"[%s (%s)]\nConnectionType=Modem\nAddress=1-%s\n\n"
,bbs.name
,bbs.number[i].modem.number
,bbs.number[i].modem.number);
fprintf(html,"<TD><B>%s%s</B><TD>%s%s<TD>%s%s<TD>%s%s<TD%s>%s%s"
"<TD%s>%s%s\n"
,fontstr,i ? "":name
,fontstr,sysop
,fontstr,location
,fontstr,nodes
,i ? " BGCOLOR=\"#EEEEEE\"":""
,fontstr,bbs.number[i].modem.number
,i ? " BGCOLOR=\"#EEEEEE\"":""
,fontstr,"N/A");
}
} /* for(numbers) */
#if VERIFY
if(verified) {
total_verified++;
bbs.verified=time(NULL);
bbs.verification_count++;
strcpy(bbs.userverified,"SBBS List Verifier");
}
fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
fwrite(&bbs,sizeof(bbs_t),1,in);
#endif
}
fprintf(html,"</TABLE>\n");
now=time(NULL);
fprintf(html,"<CENTER>\n");
fprintf(html,"%d systems verified from "
"<B><A HREF=http://vert.synchro.net>Vertrauen</A></B> on %s\n"
,total_verified ,timestr(&now));
fprintf(html,"<H1><I>Detailed Synchronet BBS List</I></H1>\n");
fprintf(html,"</CENTER>\n");
/* Generate Detailed List */
lseek(file,0L,SEEK_SET);
while(1) {
if(read(file,&index,2)!=2)
break;
fseek(in,(long)index*sizeof(bbs_t),SEEK_SET);
if(!fread(&bbs,sizeof(bbs_t),1,in))
break;
fprintf(html,"<P><A NAME=\"%s\">\n",bbs.name);
fprintf(html,"<H2><A HREF=\"#%s.index\">%s</A></H2>",bbs.name,bbs.name);
fprintf(html,"<FONT FACE=\"Arial\" SIZE=\"-1\">\n");
fprintf(html,"Online since: %s<BR>\n",unixtodstr(bbs.birth,tmp));
if(strchr(bbs.sysop_email,'@')) {
fprintf(mail,"%s\n",bbs.sysop_email);
sprintf(sysop_email,"<A HREF=%s%s>%s</A>"
,mail_to,html_encode(bbs.sysop_email),bbs.sysop[0]);
sysop=sysop_email;
} else
sysop=bbs.sysop[0];
fprintf(html,"Operator: %s", sysop);
for(i=1;i<bbs.total_sysops && i<MAX_SYSOPS;i++) {
if(bbs.total_sysops>2)
fprintf(html,", ");
else
fputc(' ',html);
if(i+1==bbs.total_sysops)
fprintf(html,"and ");
fprintf(html,"%s",bbs.sysop[i]);
}
fprintf(html,"<BR>\n");
if(bbs.web_url[0])
fprintf(html,"Web-site: <A HREF=http://%s>%s</A><BR>\n",bbs.web_url,bbs.web_url);
fprintf(html,"Nodes: %u, "
"Users: %u, Doors: %u<BR>\n"
,bbs.nodes,bbs.users,bbs.xtrns);
fprintf(html,"Download: %lu files in %u directories of "
"%luMB total space<BR>\n"
,bbs.files,bbs.dirs,bbs.megs);
fprintf(html,"Messages: %lu messages in %u sub-boards<BR>\n"
,bbs.msgs,bbs.subs);
if(bbs.total_networks) {
fprintf(html,"Networks: ");
for(i=0;i<bbs.total_networks && i<MAX_NETS;i++) {
if(i) {
if(bbs.total_networks>2)
fprintf(html,", ");
else
fputc(' ',html);
if(!(i%2))
fprintf(html,"<BR>");
if(i+1==bbs.total_networks)
fprintf(html,"and ");
}
fprintf(html,"%s [%s]",bbs.network[i],bbs.address[i]); }
fprintf(html,"<BR>\n");
}
if(bbs.total_terminals) {
fprintf(html,"Terminal: ");
for(i=0;i<bbs.total_terminals && i<MAX_TERMS;i++) {
if(i) {
if(bbs.total_terminals>2)
fprintf(html,", ");
else
fputc(' ',html);
if(i+1==bbs.total_terminals)
fprintf(html,"and "); }
fprintf(html,"%s",bbs.terminal[i]); }
fprintf(html,"<BR>\n");
}
fprintf(html,"<BR>\n");
for(i=0;i<bbs.total_numbers && i<MAX_NUMBERS;i++) {
if(bbs.number[i].modem.min_rate==0xffff) {
telnet_port=bbs.number[i].telnet.port;
if(telnet_port==0)
telnet_port=23;
strcpy(telnet_addr_buf,bbs.number[i].telnet.addr);
telnet_addr=telnet_addr_buf;
if(!strnicmp(telnet_addr,"TELNET:",7))
telnet_addr+=7;
if(!strnicmp(telnet_addr,"//",2))
telnet_addr+=2;
p=strchr(telnet_addr,':');
if(p!=NULL) {
*p=0;
telnet_port=atoi(p+1);
}
if(telnet_port==23)
telnet_portstr[0]=0;
else
sprintf(telnet_portstr,":%d",telnet_port);
fprintf(html,"<A HREF=telnet://%s%s>telnet://%s%s</A>"
,telnet_addr
,telnet_portstr
,telnet_addr
,telnet_portstr);
} else
fprintf(html,"%s %u %s "
"Minimum: %u"
,bbs.number[i].modem.number
,bbs.number[i].modem.max_rate,bbs.number[i].modem.desc
,bbs.number[i].modem.min_rate);
fprintf(html," %s<BR>\n"
,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
? nulstr : bbs.number[i].modem.location);
}
fprintf(html,"<BR>\n");
fprintf(html,"<BLOCKQUOTE>\n");
for(i=0;i<5;i++) {
if(!bbs.desc[i][0])
break;
fprintf(html,"%s<BR>\n",bbs.desc[i]);
}
fprintf(html,"</BLOCKQUOTE>\n");
fprintf(html,"<PRE>\n");
fprintf(html,"Entry created on %s by %s\n"
,timestr(&bbs.created),bbs.user);
if(bbs.updated && bbs.userupdated[0])
fprintf(html," Last updated on %s by %s\n"
,timestr(&bbs.updated),bbs.userupdated);
if(bbs.verified && bbs.userverified[0])
fprintf(html,"Last verified on %s by %s\n"
,timestr(&bbs.verified),bbs.userverified);
fprintf(html,"</PRE></P>\n");
}
fprintf(html,"<CENTER><H1>End</H1></CENTER>\n");
fprintf(html,"<P>If you are a sysop of a <B>Synchronet BBS</B> and you would "
"like to add your system to this list, please do one of the following:\n");
fprintf(html,"<UL>\n");
fprintf(html,"<LI>Install <I>Synchronet BBS List <B>v2.00+</B></I> on your BBS and "
"link it into the <B>SYNCDATA</B> message conference (on <B>DOVE-Net</B> or <B>FidoNet</B>)\n");
fprintf(html,"<LI><B>OR</B> log on to <A HREF=telnet://vert.synchro.net>Vertrauen</A> and "
"manually add your system into the online BBS List database.\n");
fprintf(html,"</UL>\n");
fprintf(html,"</BODY></HTML>\n");
printf(" Done.\n");
return(0);
}
#!/bin/sh
. ${SBBSEXEC}unixstub.sh
USEUNIT("Sbl.c");
USEUNIT("..\SDK\Xsdkvars.c");
USEUNIT("..\SDK\Xsdk.c");
USELIB("D:\Borland\CBuilder5\Lib\ws2_32.lib");
USEUNIT("..\sdk\xsdkwrap.c");
//---------------------------------------------------------------------------
This file is used by the project manager only and should be treated like the project file
main
\ No newline at end of file
<?xml version='1.0' encoding='utf-8' ?>
<!-- C++Builder XML Project -->
<PROJECT>
<MACROS>
<VERSION value="BCB.05.03"/>
<PROJECT value="sbl.exe"/>
<OBJFILES value="Sbl.obj ..\SDK\Xsdkvars.obj ..\SDK\Xsdk.obj ..\sdk\xsdkwrap.obj"/>
<RESFILES value=""/>
<IDLFILES value=""/>
<IDLGENFILES value=""/>
<DEFFILE value=""/>
<RESDEPEN value="$(RESFILES)"/>
<LIBFILES value="D:\Borland\CBuilder5\Lib\ws2_32.lib"/>
<LIBRARIES value=""/>
<SPARELIBS value=""/>
<PACKAGES value="VCL50.bpi VCLX50.bpi bcbsmp50.bpi VCLDB50.bpi VCLADO50.bpi ibsmp50.bpi
VCLBDE50.bpi VCLDBX50.bpi QRPT50.bpi TEEUI50.bpi TEEDB50.bpi TEE50.bpi
DSS50.bpi TEEQR50.bpi VCLIB50.bpi VCLMID50.bpi VCLIE50.bpi INETDB50.bpi
INET50.bpi NMFAST50.bpi WEBMID50.bpi bcbie50.bpi dclocx50.bpi"/>
<PATHCPP value=".;..\SDK"/>
<PATHPAS value=".;"/>
<PATHRC value=".;"/>
<PATHASM value=".;"/>
<DEBUGLIBPATH value="$(BCB)\lib\debug"/>
<RELEASELIBPATH value="$(BCB)\lib\release"/>
<LINKER value="tlink32"/>
<USERDEFINES value="_DEBUG"/>
<SYSDEFINES value="NO_STRICT;_NO_VCL"/>
<MAINSOURCE value="sbl.bpf"/>
<INCLUDEPATH value="$(BCB)\include;$(BCB)\include\vcl;..\sdk"/>
<LIBPATH value="..\SDK;$(BCB)\lib\obj;$(BCB)\lib"/>
<WARNINGS value="-w-par"/>
</MACROS>
<OPTIONS>
<IDLCFLAGS value="-I$(BCB)\include -I$(BCB)\include\vcl -I..\sdk -src_suffix cpp -D_DEBUG -boa"/>
<CFLAG1 value="-Od -H=$(BCB)\lib\vcl50.csm -Hc -Vx -Ve -X- -r- -a8 -b- -k -y -v -vi- -tWC
-tWM -c"/>
<PFLAGS value="-$YD -$W -$O- -v -JPHNE -M"/>
<RFLAGS value=""/>
<AFLAGS value="/mx /w2 /zd"/>
<LFLAGS value="-D&quot;&quot; -ap -Tpe -x -Gn -v"/>
</OPTIONS>
<LINKER>
<ALLOBJ value="c0x32.obj $(OBJFILES)"/>
<ALLRES value="$(RESFILES)"/>
<ALLLIB value="$(LIBFILES) $(LIBRARIES) import32.lib cw32mt.lib"/>
</LINKER>
<IDEOPTIONS>
[Version Info]
IncludeVerInfo=0
AutoIncBuild=0
MajorVer=1
MinorVer=0
Release=0
Build=0
Debug=0
PreRelease=0
Special=0
Private=0
DLL=0
Locale=1033
CodePage=1252
[Version Info Keys]
CompanyName=
FileDescription=
FileVersion=1.0.0.0
InternalName=
LegalCopyright=
LegalTrademarks=
OriginalFilename=
ProductName=
ProductVersion=1.0.0.0
Comments=
[HistoryLists\hlIncludePath]
Count=3
Item0=$(BCB)\include;$(BCB)\include\vcl;..\sdk
Item1=$(BCB)\include;$(BCB)\include\vcl;c:\sbbs\xtrn\sdk
Item2=$(BCB)\include;$(BCB)\include\vcl
[HistoryLists\hlLibraryPath]
Count=2
Item0=..\SDK;$(BCB)\lib\obj;$(BCB)\lib
Item1=$(BCB)\lib\obj;$(BCB)\lib
[HistoryLists\hlDebugSourcePath]
Count=1
Item0=$(BCB)\source\vcl
[HistoryLists\hlConditionals]
Count=1
Item0=_DEBUG
[Debugging]
DebugSourceDirs=$(BCB)\source\vcl
[Parameters]
RunParams=
HostApplication=
RemoteHost=
RemotePath=
RemoteDebug=0
[Compiler]
ShowInfoMsgs=0
LinkDebugVcl=0
LinkCGLIB=0
[CORBA]
AddServerUnit=1
AddClientUnit=1
PrecompiledHeaders=1
[Language]
ActiveLang=
ProjectLang=
RootDir=
</IDEOPTIONS>
</PROJECT>
\ No newline at end of file
/* sbl.c */
/* Synchronet BBS List Door */
/* $Id: sbl.c,v 1.25 2013/09/15 19:10:46 deuce Exp $ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2013 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. *
****************************************************************************/
/***********
* History *
***********
******************
* RELEASE: v1.00 *
******************
07/03/93 03:16am
Fixed bug with "Auto-deleting" already deleted entries. This would cause a
long list of "Auto-deletion" messages once a day.
07/03/93 03:30am
The name of the user who last updated the entry is now stored and displayed.
07/03/93 03:45am
Adding/Updating entries is now much easier and user friendly.
07/03/93 04:00am
Added support for user "verification" of BBS entries.
07/03/93 04:10am
Users may now update or remove entries using partial system names.
07/03/93 04:30am
Sysops may now un-delete purged entries with the '*' key.
******************
* RELEASE: v1.10 *
******************
10/18/93 06:04pm
Fixed bug that would cause entries to be purged almost immediately.
10/18/93 07:01pm
(F)ind text now searches user names who last updated and verified.
10/19/93 01:34am
Added option for users to change the format of BBS listings.
******************
* RELEASE: v1.20 *
******************
10/20/93 04:44pm
Fixed cosmetic problem with opening menu (for users, not sysop).
******************
* RELEASE: v1.21 *
******************
11/29/93 09:40pm
More cosmetic changes. Added "Saving..." message.
******************
* RELEASE: v1.22 *
******************
02/02/94
Added warning for pending auto-deletion of BBS entries.
02/02/94
Added option for turning screen pause off/on.
02/03/94
Added option in SBL.CFG for sysop/co-sysop notification of changes made to
BBS list by users.
02/03/94
Converted all file operations from handles to streams for buffered i/o (speed).
02/09/94
Added options for generating a sort index and displaying sorted list based on
various criteria.
02/09/94
Added nodesync() calls to display any messages waiting for this user/node.
02/10/94
Added search for duplicate names when adding new BBS entries.
02/10/94
Notification notice of actual auto-deletion sent to author of BBS entry upon
auto-deletion.
******************
* RELEASE: v1.30 *
******************
03/14/94
Added /M switch to force daily maintenance.
03/22/94
Fixed occasional double pause after listings.
03/22/94
Added total entries found to find text listings.
03/22/94
If a user verifies an entry, the user who created the entry is notified.
03/29/94
Sysop can define/change the "owner" of an entry when adding or updating.
04/18/94
Fixed bug in the sort-by-string functions that caused lock-ups when sorting
more than 312 entries.
04/18/94
Lowered memory requirements for all sort functions.
******************
* RELEASE: v1.31 *
******************
08/23/94
BBS entries now know whether they were created by a user or by SMB2SBL (via
message base).
08/23/94
Fixed problem with hitting Ctrl-C locally during regular (not extended)
listing. Returning to main menu would not clear screen or have correct colors.
'aborted' variable is now reset in main() loop.
******************
* RELEASE: v1.32 *
******************
08/30/94
Fixed stack overflow that would cause periodic lock-ups on some systems.
******************
* RELEASE: v1.33 *
******************
09/08/94
When deleting an entry, the name of the BBS deleted wasn't being printed.
02/01/95
Import utility made mistake of ignoring READ messages to SBL. This has been
fixed.
12/16/99
Fixed Y2K window bug in dstrtounix().
12/16/99
Fixed bug that caused SMB imported entries to never be autodeleted.
06/01/00
Added support for XSDK 3.0
06/01/00
Added support for MSVC 5+
06/01/00
Changed cosmetic appearance of main menu a bit
06/14/99
Added support for C++Builder 5
*/
#include <stddef.h> /* offsetof() macro */
#include <xsdk.h>
#include "sbldefs.h"
unsigned _stklen = 16000; /* Set stack size in code, not header */
#define Y2K_2DIGIT_WINDOW 70
#define VERIFICATION_MOD FALSE
typedef struct {
char str[32];
short offset;
} sortstr_t;
typedef struct {
long i;
short offset;
} sortint_t;
char *nulstr = "";
char *wday[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char *mon[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun"
,"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
char tmp[256];
char list_fmt[128];
uint del_days, add_ml, update_ml, remove_ml, verify_ml, sbl_pause = 1,
notify_user;
time_t now;
/****************************************************************************/
/* Generates a 24 character ASCII string that represents the 32b-ti time_t */
/* Used as a replacement for ctime() */
/****************************************************************************/
char *timestr(uint32_t intime)
{
static char str[256];
char mer[3], hour;
struct tm *gm;
time_t t = intime;
gm = localtime(&t);
if (gm == NULL)
return "invalid date/time";
if (gm->tm_hour >= 12) {
if (gm->tm_hour == 12)
hour = 12;
else
hour = gm->tm_hour - 12;
strcpy(mer, "pm");
}
else {
if (gm->tm_hour == 0)
hour = 12;
else
hour = gm->tm_hour;
strcpy(mer, "am");
}
sprintf(str, "%s %s %02d %4d %02d:%02d %s"
,wday[gm->tm_wday], mon[gm->tm_mon], gm->tm_mday, 1900 + gm->tm_year
,hour, gm->tm_min, mer);
return (str);
}
/****************************************************************************/
/* Converts a date string in format MM/DD/YY into unix time format */
/****************************************************************************/
time_t dstrtounix(char *str)
{
struct tm tm;
if (!strncmp(str, "00/00/00", 8))
return (0);
memset(&tm, 0, sizeof(tm));
tm.tm_year = ((str[6] & 0xf) * 10) + (str[7] & 0xf);
if (tm.tm_year < Y2K_2DIGIT_WINDOW)
tm.tm_year += 100;
tm.tm_mon = ((str[0] & 0xf) * 10) + (str[1] & 0xf);
tm.tm_mday = ((str[3] & 0xf) * 10) + (str[4] & 0xf);
if (tm.tm_mon)
tm.tm_mon--; /* zero-based month field */
return (mktime(&tm));
}
/****************************************************************************/
/* Converts unix time format (long - time_t) into a char str MM/DD/YY */
/****************************************************************************/
char *unixtodstr(time_t t, char *str)
{
struct tm *tm;
if (t == 0)
strcpy(str, "00/00/00");
else {
tm = gmtime(&t);
if (tm == NULL) {
strcpy(str, "00/00/00");
return (str);
}
if (tm->tm_mon > 11) { /* DOS leap year bug */
tm->tm_mon = 0;
tm->tm_year++;
}
if (tm->tm_mday > 31)
tm->tm_mday = 1;
sprintf(str, "%02u/%02u/%02u", tm->tm_mon + 1, tm->tm_mday
,tm->tm_year % 100);
}
return (str);
}
void dots(int show)
{
static int i;
if (!show) { /* reset */
i = 0;
return;
}
if (++i > 5) {
bputs("\b\b\b\b\b \b\b\b\b\b");
i = 0;
return;
}
outchar('.');
}
/* Displays short information about BBS. Returns 0 if aborted. */
char short_bbs_info(bbs_t bbs)
{
char str[128];
int i, j;
for (i = 0; i < bbs.total_numbers && i < MAX_NUMBERS; i++) {
for (j = 0; list_fmt[j]; j++) {
if (j)
bputs(" ");
switch (toupper(list_fmt[j])) {
case 'N':
bprintf("\1h\1m%-25.25s", i ? nulstr : bbs.name);
break;
case 'S':
bprintf("\1h\1c%-15.15s", i ? nulstr : bbs.software);
break;
case 'P':
if (bbs.number[i].modem.min_rate == 0xffff) {
if (bbs.number[i].telnet.port != 0
&& bbs.number[i].telnet.port != IPPORT_TELNET)
sprintf(str, "%s:%hu"
,bbs.number[i].telnet.addr
,bbs.number[i].telnet.port);
else
strcpy(str, bbs.number[i].telnet.addr);
bprintf("\1h\1b%-28.28s", str);
}
else
bprintf("\1n\1g%12.12s", bbs.number[i].modem.number);
break;
case 'B':
if (bbs.number[i].modem.min_rate != 0xffff)
bprintf("\1h\1g%5u", bbs.number[i].modem.max_rate);
break;
case 'M':
if (bbs.number[i].modem.min_rate != 0xffff)
bprintf("\1h\1b%-15.15s", bbs.number[i].modem.desc);
break;
case 'Y':
bprintf("\1h\1y%-25.25s", i ? nulstr : bbs.sysop[0]);
break;
case 'T':
if (i)
bputs(" ");
else
bprintf("\1y\1h%3u", bbs.nodes);
break;
case 'U':
if (i)
bputs(" ");
else
bprintf("\1n\1r%5u", bbs.users);
break;
case 'H':
if (i)
bprintf("%10.10s", nulstr);
else
bprintf("\1h\1r%10u", bbs.megs);
break;
case 'L':
bprintf("\1n\1c%-20.20s", bbs.number[i].modem.location);
break;
case 'F':
bprintf("\1n\1b%s", i ? nulstr : unixtodstr(bbs.birth, tmp));
break;
case 'V':
bprintf("\1n\1m%s", i ? nulstr : unixtodstr(bbs.verified, tmp));
break;
case 'D':
bprintf("\1n%s", i ? nulstr : unixtodstr(bbs.updated, tmp));
break;
case 'C':
bprintf("\1n\1y%s", i ? nulstr : unixtodstr(bbs.created, tmp));
break;
default:
bprintf("%c", list_fmt[j]);
break;
}
}
bputs("\r\n");
}
#if 0
if (kbhit())
return (0);
#endif
return (1);
}
char long_bbs_info(bbs_t bbs)
{
int i;
cls();
bprintf("\1n\1gBBS Name: \1h%s \1n\1gsince \1h%s\r\n"
,bbs.name, unixtodstr(bbs.birth, tmp));
bprintf("\1n\1gOperator: ");
for (i = 0; i < bbs.total_sysops && i < MAX_SYSOPS; i++) {
if (i) {
if (bbs.total_sysops > 2)
bputs(", ");
else
outchar(' ');
if (!(i % 4))
bputs("\r\n ");
if (i + 1 == bbs.total_sysops)
bputs("and ");
}
bprintf("\1h%s\1n\1g", bbs.sysop[i]);
if (!i && bbs.sysop_email[0])
bprintf(" <\1h%s\1n\1g>", bbs.sysop_email);
}
CRLF;
bprintf("\1n\1gSoftware: \1h%-15.15s \1n\1gNodes: \1h%-5u \1n\1g"
"Users: \1h%-5u \1n\1gDoors: \1h%u\r\n"
,bbs.software, bbs.nodes, bbs.users, bbs.xtrns);
bprintf("\1n\1gDownload: \1h%lu \1n\1gfiles in \1h%u \1n\1gdirectories of \1h"
"%luMB \1n\1gtotal space\r\n"
,bbs.files, bbs.dirs, bbs.megs);
bprintf("Messages: \1h%lu \1n\1gmessages in \1h%u \1n\1gsub-boards\r\n"
,bbs.msgs, bbs.subs);
bprintf("Networks: ");
for (i = 0; i < bbs.total_networks && i < MAX_NETS; i++) {
if (i) {
if (bbs.total_networks > 2)
bputs(", ");
else
outchar(' ');
if (!(i % 3))
bputs("\r\n ");
if (i + 1 == bbs.total_networks)
bputs("and ");
}
bprintf("\1h%s [%s]\1n\1g", bbs.network[i], bbs.address[i]);
}
CRLF;
bprintf("Terminal: ");
for (i = 0; i < bbs.total_terminals && i < MAX_TERMS; i++) {
if (i) {
if (bbs.total_terminals > 2)
bputs(", ");
else
outchar(' ');
if (i + 1 == bbs.total_terminals)
bputs("and ");
}
bprintf("\1h%s\1n\1g", bbs.terminal[i]);
}
CRLF;
if (bbs.web_url[0])
bprintf("Web-site: http://\1h%s\r\n", bbs.web_url);
CRLF;
for (i = 0; i < bbs.total_numbers && i < MAX_NUMBERS; i++) {
bprintf("\1h\1b%-30.30s "
,i && !strcmp(bbs.number[i].modem.location, bbs.number[i - 1].modem.location)
? nulstr : bbs.number[i].modem.location);
if (bbs.number[i].modem.min_rate == 0xffff) {
if (bbs.number[i].telnet.port != 0
&& bbs.number[i].telnet.port != IPPORT_TELNET)
bprintf("\1n\1mtelnet://\1h%s:%hu\r\n"
,bbs.number[i].telnet.addr
,bbs.number[i].telnet.port);
else
bprintf("\1n\1mtelnet://\1h%s\r\n"
,bbs.number[i].telnet.addr);
}
else
bprintf("\1n\1g%12.12s \1h%5u \1b%-15.15s \1n\1cMinimum: \1h%u\r\n"
,bbs.number[i].modem.number
,bbs.number[i].modem.max_rate
,bbs.number[i].modem.desc
,bbs.number[i].modem.min_rate);
}
bputs("\r\n\1w\1h");
for (i = 0; i < DESC_LINES; i++) {
if (!bbs.desc[i][0])
break;
bprintf("%15s%s\r\n", nulstr, bbs.desc[i]);
}
CRLF;
if (bbs.misc & FROM_SMB)
bputs("\1r\1hImported from message base.\r\n");
bprintf("\1n\1cEntry created on \1h%s\1n\1c by \1h%s\r\n"
,timestr(bbs.created), bbs.user);
if (bbs.updated && bbs.userupdated[0])
bprintf("\1n\1c Last updated on \1h%s\1n\1c by \1h%s\r\n"
,timestr(bbs.updated), bbs.userupdated);
if (bbs.verified && bbs.userverified[0])
bprintf("\1n\1cLast verified on \1h%s\1n\1c by \1h%s"
#if VERIFICATION_MOD
" \1y(%d/%d)"
#endif
"\r\n"
,timestr(bbs.verified), bbs.userverified
,bbs.verification_count, bbs.verification_attempts);
CRLF;
if (aborted) {
aborted = 0;
return (0);
}
if (!sbl_pause) {
#if 0
if (kbhit())
return (0);
#endif
return (1);
}
nodesync();
#if VERIFICATION_MOD
bputs("More? Y/N/V ");
switch (getkeys("YNV\r", 0)) {
case '\r':
case 'Y':
return (1);
case 'V':
return (2);
default:
return (0);
}
#else
return (yesno("More"));
#endif
}
/* Gets/updates BBS info from user. Returns 0 if aborted. */
char get_bbs_info(bbs_t * bbs)
{
char str[128];
int i;
aborted = 0;
if (!(bbs->user[0]))
strcpy(bbs->user, user_name);
if (SYSOP) {
bputs("\1y\1hUser Name (Creator/Owner of Entry): ");
if (!getstr(bbs->user, 25, K_EDIT | K_LINE | K_AUTODEL))
return (0);
}
bputs("\1y\1hSystem Name: ");
if (getstr(bbs->name, 25, K_EDIT | K_LINE | K_AUTODEL) < 2)
return (0);
if (!bbs->software[0])
strcpy(bbs->software, "Synchronet");
bprintf("\1y\1hSoftware: \1w", bbs->software);
if (!getstr(bbs->software, 15, K_AUTODEL | K_EDIT))
return (0);
for (i = 0; i < MAX_SYSOPS && !aborted; i++) {
bprintf("\1y\1hName of System Operator #%d [\1wNone\1y]: ", i + 1);
if (!getstr(bbs->sysop[i], 25, K_EDIT | K_LINE | K_AUTODEL))
break;
if (!i) {
bprintf("\1y\1hInternet E-mail Address [\1wNone\1y]:\1w ");
getstr(bbs->sysop_email, 40, K_EDIT | K_AUTODEL);
}
}
bbs->total_sysops = i;
if (aborted)
return (0);
unixtodstr(bbs->birth, str);
bprintf("\1y\1hFirst Day Online (MM/DD/YY): \1w");
if (getstr(str, 8, K_UPPER | K_EDIT | K_AUTODEL))
bbs->birth = dstrtounix(str);
if (aborted)
return (0);
for (i = 0; i < MAX_NETS && !aborted; i++) {
bprintf("\1y\1hName of Message Network #%d [\1wNone\1y]: ", i + 1);
if (!getstr(bbs->network[i], 15, K_EDIT | K_AUTODEL | K_LINE))
break;
bprintf("\1y\1hNetwork Message \1wAddress\1y #%d [\1wNone\1y]: \1w", i + 1);
getstr(bbs->address[i], 25, K_EDIT | K_AUTODEL);
}
bbs->total_networks = i;
if (aborted)
return (0);
for (i = 0; i < MAX_TERMS && !aborted; i++) {
bprintf("\1y\1hSupported Terminal Type #%d (i.e. TTY, ANSI, RIP) "
"[\1wNone\1y]: ", i + 1);
if (!getstr(bbs->terminal[i], 15, K_EDIT | K_AUTODEL | K_LINE))
break;
}
bbs->total_terminals = i;
if (aborted)
return (0);
bprintf("\1y\1hWeb-site [\1wNone\1y] http://\1w");
getstr(bbs->web_url, 60, K_EDIT | K_AUTODEL);
if (!bbs->nodes)
bbs->nodes = 1;
bprintf("\1y\1hNodes (maximum number of simultaneous REMOTE users): \1w");
sprintf(str, "%u", bbs->nodes);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->nodes = atoi(str);
if (!bbs->nodes)
bbs->nodes = 1;
if (aborted)
return (0);
for (i = 0; i < MAX_NUMBERS; i++) {
#if 0
if (!i && !bbs->number[i].modem.number[0])
sprintf(bbs->number[i].modem.number, "%.8s", user_phone);
#endif
bprintf("\1y\1hPhone Number or \1mTelnet address\1y #%d [\1wNone\1y]: ", i + 1);
if (!getstr(bbs->number[i].telnet.addr, 28, K_EDIT | K_LINE))
break;
if (!bbs->number[i].modem.location[0]) {
if (!i)
strcpy(bbs->number[i].modem.location, user_location);
else
strcpy(bbs->number[i].modem.location, bbs->number[i - 1].modem.location);
}
if (aborted)
return (0);
if (isalpha(bbs->number[i].telnet.addr[0])
|| yesno("Is the above a Telnet address")) {
bbs->number[i].modem.min_rate = 0xffff;
if (bbs->number[i].telnet.port == 0)
bbs->number[i].telnet.port = IPPORT_TELNET;
bprintf("\1y\1hTCP Port: \1w");
sprintf(str, "%u", bbs->number[i].telnet.port);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->number[i].telnet.port = atoi(str);
if (aborted)
return (0);
}
else {
if (bbs->number[i].modem.min_rate == 0xffff)
bbs->number[i].modem.min_rate = 300;
bbs->number[i].modem.number[13] = 0;
if (!bbs->number[i].modem.min_rate) {
if (i)
bbs->number[i].modem.min_rate = bbs->number[i - 1].modem.min_rate;
else
bbs->number[i].modem.min_rate = 300;
}
bprintf("\1y\1hMinimum Connect Rate: \1w");
sprintf(str, "%u", bbs->number[i].modem.min_rate);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->number[i].modem.min_rate = atoi(str);
if (aborted)
return (0);
if (!bbs->number[i].modem.max_rate) {
if (i)
bbs->number[i].modem.max_rate = bbs->number[i - 1].modem.max_rate;
else
bbs->number[i].modem.max_rate = 2400;
}
if (bbs->number[i].modem.max_rate < bbs->number[i].modem.min_rate)
bbs->number[i].modem.max_rate = bbs->number[i].modem.min_rate;
bprintf("\1y\1hMaximum Connect Rate (i.e. 2400, 9600, 14400, etc): \1w");
sprintf(str, "%u", bbs->number[i].modem.max_rate);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->number[i].modem.max_rate = atoi(str);
if (aborted)
return (0);
bprintf("\1y\1hModem Description (i.e. Hayes, HST, V.32, etc): \1w");
getstr(bbs->number[i].modem.desc, 15, K_EDIT | K_AUTODEL);
}
bprintf("\1y\1hLocation (City, State): \1w");
if (!getstr(bbs->number[i].modem.location, 30, K_EDIT | K_AUTODEL))
break;
}
if (!i)
return (0);
bbs->total_numbers = i;
if (aborted)
return (0);
if (!bbs->users)
bbs->users = 100;
bprintf("\1y\1hTotal Number of Users: \1w");
sprintf(str, "%u", bbs->users);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->users = atoi(str);
if (aborted)
return (0);
if (!bbs->subs)
bbs->subs = 10;
bprintf("\1y\1hTotal Number of Sub-boards (Message Areas): \1w");
sprintf(str, "%u", bbs->subs);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->subs = atoi(str);
if (aborted)
return (0);
if (!bbs->msgs)
bbs->msgs = 500;
bprintf("\1y\1hTotal Number of Public Messages: \1w");
sprintf(str, "%"PRIu32, bbs->msgs);
if (getstr(str, 10, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->msgs = atol(str);
if (aborted)
return (0);
if (!bbs->dirs)
bbs->dirs = 5;
bprintf("\1y\1hTotal Number of Directories (File Areas): \1w");
sprintf(str, "%u", bbs->dirs);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->dirs = atoi(str);
if (aborted)
return (0);
if (!bbs->files)
bbs->files = 250;
bprintf("\1y\1hTotal Number of Downloadable Files: \1w");
sprintf(str, "%"PRIu32, bbs->files);
if (getstr(str, 10, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->files = atol(str);
if (aborted)
return (0);
if (!bbs->xtrns)
bbs->xtrns = 5;
bprintf("\1y\1hTotal Number of External Programs (Doors): \1w");
sprintf(str, "%u", bbs->xtrns);
if (getstr(str, 5, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->xtrns = atoi(str);
if (aborted)
return (0);
if (!bbs->megs)
bbs->megs = 40;
bprintf("\1y\1hTotal Storage Space (in Megabytes): \1w");
sprintf(str, "%"PRIu32, bbs->megs);
if (getstr(str, 10, K_NUMBER | K_EDIT | K_AUTODEL))
bbs->megs = atol(str);
if (aborted)
return (0);
for (i = 0; i < DESC_LINES; i++) {
bprintf("\1y\1hBBS Description (%d of %d): ", i + 1, DESC_LINES);
if (!getstr(bbs->desc[i], 50, K_EDIT | K_AUTODEL | K_LINE))
break;
}
return (1);
}
char partname(char *inname, char *inpart)
{
char name[128], part[128], str[256];
strcpy(name, inname);
strupr(name);
strcpy(part, inpart);
strupr(part);
if (inname[0] && (strstr(name, part) || strstr(part, name))) {
sprintf(str, "\r\nDo you mean %s", inname);
if (yesno(str))
return (1);
}
return (0);
}
int sortint_cmp(sortint_t * int1, sortint_t * int2)
{
if (int1->i > int2->i)
return (-1);
if (int1->i < int2->i)
return (1);
return (0);
}
int sortstr_cmp(sortstr_t * str1, sortstr_t * str2)
{
return (stricmp(str1->str, str2->str));
}
int main(int argc, char **argv)
{
char str[512], name[128], *p, ch;
char *database = "sbl.dab";
short i, j, file, done, sort_by_str;
int maint = 0;
long l, found;
bbs_t bbs, tmpbbs;
FILE *stream;
sortstr_t *sortstr;
sortint_t *sortint;
for (i = 1; i < argc; i++)
if (
#ifndef __unix__
argv[i][0] == '/' ||
#endif
argv[i][0] == '-') {
switch (toupper(argv[i][1])) {
case 'M':
maint = 1;
xsdk_mode &= ~XSDK_MODE_NOCONSOLE;
break;
case 'W':
xsdk_mode &= ~XSDK_MODE_NOCONSOLE;
break;
}
}
else
database = argv[i];
p = getenv("SBBSNODE");
if (p)
strcpy(node_dir, p);
else {
printf("\nSBBSNODE environment variable must be set\n");
exit(0);
}
if (node_dir[strlen(node_dir) - 1] != '\\' && node_dir[strlen(node_dir) - 1] != '/')
strcat(node_dir, "/");
strcpy(str, "sbl.cfg");
if ((file = sopen(str, O_RDONLY, SH_DENYNO)) == -1) {
printf("error opening %s\r\n", str);
exit(1);
}
if ((stream = fdopen(file, "rb")) == NULL) {
printf("fdopen error with %s\r\n", str);
exit(1);
}
fgets(str, 81, stream);
del_days = atoi(str);
fgets(str, 81, stream);
add_ml = atoi(str);
fgets(str, 81, stream);
update_ml = atoi(str);
fgets(str, 81, stream);
remove_ml = atoi(str);
fgets(str, 81, stream);
verify_ml = atoi(str);
fgets(str, 81, stream);
notify_user = atoi(str);
fclose(stream);
initdata();
if (maint)
client_socket = INVALID_SOCKET;
mnehigh = HIGH | LIGHTGRAY;
mnelow = HIGH | YELLOW;
if (maint)
user_misc = (ANSI | COLOR);
if ((file = sopen(database, O_RDWR | O_BINARY | O_CREAT, SH_DENYNO, S_IREAD | S_IWRITE)) == -1) {
bprintf("\r\n\7Error opening/creating %s\r\n", database);
exit(1);
}
if ((stream = fdopen(file, "w+b")) == NULL) {
bprintf("\r\n\7Error converting %s file handle to stream\r\n", database);
exit(1);
}
setvbuf(stream, 0L, _IOFBF, 2048);
if (del_days) {
now = time(NULL);
strcpy(str, "sblpurge.dab");
if ((file = nopen(str, O_RDWR | O_CREAT)) == -1) {
printf("Error creating %s\r\n", str);
exit(1);
}
l = 0;
read(file, &l, 4);
if (now - l > (24L * 60L * 60L) || maint) { /* more than a day since
* update */
bputs("\r\n\1n\1hRunning daily maintenance for Synchronet BBS List...");
lseek(file, 0L, SEEK_SET);
write(file, &now, 4);
close(file);
fseek(stream, 0L, SEEK_SET);
while (!feof(stream)) {
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (bbs.name[0]) {
if ((now - bbs.updated) / (24L * 60L * 60L) > (time_t) del_days
&& (now - bbs.created) / (24L * 60L * 60L) > (time_t) del_days
&& (now - bbs.verified) / (24L * 60L * 60L) > (time_t) del_days) {
lncntr = 0;
bprintf("\r\n\1n\1hAuto-deleting \1m%s\r\n", bbs.name);
if (!(bbs.misc & FROM_SMB)) {
sprintf(str, "\1n\1hSBL: \1mYour BBS entry for \1y%s\1m\r\n"
" was auto-deleted from the \1cSynchronet BBS "
"List\r\n", bbs.name);
i = usernumber(bbs.user);
if (i)
putsmsg(i, str);
}
bbs.name[0] = 0;
fseek(stream, -(long)(sizeof(bbs_t)), SEEK_CUR);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
}
else if (!(bbs.misc & FROM_SMB)) { /* Warn user */
l = bbs.created;
if (l < bbs.updated)
l = bbs.updated;
if (l < bbs.verified)
l = bbs.verified;
if ((now - l) / (24L * 60L * 60L) >= (time_t) (del_days / 2)) {
bprintf("\r\n\1n\1hWarning \1y%s\r\n", bbs.user);
lncntr = 0;
sprintf(str, "\1n\1hSBL: \1mPlease verify your BBS "
"entry for \1y%s\1m\r\n "
"in the \1cSynchronet BBS List "
"\1mor it will be deleted in \1i\1r%lu "
"\1n\1h\1mdays.\r\n"
,bbs.name
,del_days - ((now - l) / (24L * 60L * 60L)));
i = usernumber(bbs.user);
if (i)
putsmsg(i, str);
}
}
}
}
}
else
close(file);
}
if (maint)
return (0);
strcpy(list_fmt, DEF_LIST_FMT);
while (1) {
aborted = 0;
attr(LIGHTGRAY);
cls();
COMPILER_DESC(str);
bprintf("\1n\1m\1hSynchronet \1wBBS List \1mv3.20 for %s\r\n (XSDK v%s %s %s) "
"\r\n\r\n"
,PLATFORM_DESC
,xsdk_ver
,str
,__DATE__
);
#define SBL_INDENT " "
sprintf(str, SBL_INDENT "~List all systems (condensed)\r\n"
SBL_INDENT "~Change list format\r\n"
SBL_INDENT "~Extended information on all systems\r\n"
SBL_INDENT "~Turn screen pause %s\r\n"
SBL_INDENT "~Find text in BBS entries\r\n"
SBL_INDENT "~Generate sorted list\r\n"
SBL_INDENT "~Display sorted list\r\n"
SBL_INDENT "~New entry scan\r\n"
SBL_INDENT "~Add a BBS entry\r\n"
SBL_INDENT "~Update a BBS entry\r\n"
SBL_INDENT "~Verify a BBS entry\r\n"
SBL_INDENT "~Remove a BBS entry\r\n"
SBL_INDENT "~Quit back to BBS\r\n"
,sbl_pause ? "OFF" : "ON");
mnemonics(str);
if (SYSOP)
mnemonics(SBL_INDENT "~* Undelete entries\r\n");
bputs("\r\n");
l = filelength(fileno(stream));
if (l > 0)
bprintf(SBL_INDENT "\1n\1cThere are \1h%lu\1n\1c entries in the online BBS list "
"database.\r\n", l / (long)sizeof(bbs_t));
if (del_days) {
bprintf(SBL_INDENT "\1n\1cEntries are auto-deleted \1h%u\1n\1c days after "
"last update or verification.\r\n", del_days);
bputs(SBL_INDENT "Users are encouraged to \1hV\1n\1cerify (vouch for) any listed "
"systems they call.\r\n");
}
nodesync(); /* Display any waiting messages */
bputs("\r\n" SBL_INDENT "\1y\1hWhich: \1w");
switch (getkeys("CLGDEFSNAURTQV!*", 0)) {
case '!':
bprintf("\r\nsizeof(bbs_t)=%u\r\n", sizeof(bbs_t));
bprintf("\r\noffsetof(verification_count=%x)\r\n", offsetof(bbs_t, verification_count));
pause();
break;
case '*':
cls();
if (!SYSOP)
break;
fseek(stream, 0L, SEEK_SET);
while (!feof(stream) && !aborted) {
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] && bbs.total_numbers > 0) {
bbs.name[0] = '?';
bbs.verified = time(NULL);
sprintf(bbs.userverified, "%.25s", user_name);
if (yesno(bbs.name)) {
bprintf("\1n\1gFirst char: \1h");
bbs.name[0] = getkey(0);
bprintf("%s\r\n", bbs.name);
fseek(stream, -(long)sizeof(bbs_t), SEEK_CUR);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
}
}
}
break;
case 'L':
cls();
fseek(stream, 0L, SEEK_SET);
i = 0;
while (!feof(stream) && !aborted) {
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] || bbs.total_numbers < 1)
continue;
i++;
if (!short_bbs_info(bbs))
break;
if (!sbl_pause)
lncntr = 0;
}
bprintf("\r\n\1n\1h%u systems listed.\r\n", i);
#if 0
if (kbhit())
getch();
#endif
if (lncntr)
pause();
break;
case 'C':
cls();
bputs("\1n\1c\1hList Format Specifier Definitions:\1n\r\n\r\n");
bputs("\1h\1w(\1mN\1w) \1n\1mName of System\r\n");
bputs("\1h\1w(\1mS\1w) \1n\1mSoftware Used\r\n");
bputs("\1h\1w(\1mP\1w) \1n\1mPhone Number\r\n");
bputs("\1h\1w(\1mB\1w) \1n\1mMaximum Connect Rate (in bps)\r\n");
bputs("\1h\1w(\1mM\1w) \1n\1mModem Type\r\n");
bputs("\1h\1w(\1mY\1w) \1n\1mSysop's Name\r\n");
bputs("\1h\1w(\1mT\1w) \1n\1mTotal Number of Nodes\r\n");
bputs("\1h\1w(\1mU\1w) \1n\1mTotal Number of Users\r\n");
bputs("\1h\1w(\1mH\1w) \1n\1mTotal Storage Capacity (in megabytes)\r\n");
bputs("\1h\1w(\1mL\1w) \1n\1mLocation (City, State)\r\n");
bputs("\1h\1w(\1mF\1w) \1n\1mDate System was First Online\r\n");
bputs("\1h\1w(\1mC\1w) \1n\1mDate Entry was Created\r\n");
bputs("\1h\1w(\1mV\1w) \1n\1mDate Entry was Last Verified\r\n");
bputs("\1h\1w(\1mD\1w) \1n\1mDate Entry was Last Updated\r\n");
bprintf("\r\n\1n\1gDefault Format: \1h%s", DEF_LIST_FMT);
bprintf("\r\n\1n\1gCurrent Format: \1h%s\r\n", list_fmt);
bprintf("\r\n\1y\1hNew Format: ");
if (getstr(tmp, 10, K_UPPER | K_LINE)) {
if (!strchr(tmp, 'P') || !strchr(tmp, 'N')) {
bputs("\r\n\1h\1mP\1n\1mhone and \1hN\1n\1mame specifiers "
"must be present in format.\r\n\r\n");
pause();
}
else
strcpy(list_fmt, tmp);
}
break;
case 'E':
fseek(stream, 0L, SEEK_SET);
while (!feof(stream) && !aborted) {
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] || bbs.total_numbers < 1)
continue;
i = long_bbs_info(bbs);
if (bbs.name[0] && !i)
break;
#if VERIFICATION_MOD
if (i == 2) {
bbs.verification_count++;
fseek(stream, -(int)sizeof(bbs_t), SEEK_CUR);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
fseek(stream, -(int)sizeof(bbs_t), SEEK_CUR);
}
#endif
if (!sbl_pause)
lncntr = 0;
}
break;
case 'F': /* Find text */
cls();
bputs("\1y\1hText to search for: ");
if (!getstr(name, 25, K_UPPER | K_LINE))
break;
ch = yesno("\r\nDisplay extended information");
found = 0;
bputs("\1n\1h\r\nSearching...\r\n\r\n");
fseek(stream, 0L, SEEK_SET);
while (!feof(stream) && !aborted) {
if (!sbl_pause)
lncntr = 0;
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] || bbs.total_numbers < 1)
continue;
tmpbbs = bbs;
strupr(tmpbbs.name);
strupr(tmpbbs.user);
strupr(tmpbbs.software);
strupr(tmpbbs.userverified);
strupr(tmpbbs.userupdated);
strupr(tmpbbs.web_url);
for (i = 0; i < DESC_LINES; i++) {
strupr(tmpbbs.desc[i]);
if (strstr(tmpbbs.desc[i], name))
break;
}
if (i < DESC_LINES
|| strstr(tmpbbs.name, name)
|| strstr(tmpbbs.user, name)
|| strstr(tmpbbs.software, name)
|| strstr(tmpbbs.userverified, name)
|| strstr(tmpbbs.userupdated, name)
|| strstr(tmpbbs.web_url, name)
) {
found++;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
continue;
}
for (i = 0; i < tmpbbs.total_sysops; i++) {
strupr(tmpbbs.sysop[i]);
if (strstr(tmpbbs.sysop[i], name))
break;
}
if (i < tmpbbs.total_sysops) {
found++;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
continue;
}
for (i = 0; i < tmpbbs.total_networks; i++) {
strupr(tmpbbs.network[i]);
strupr(tmpbbs.address[i]);
if (strstr(tmpbbs.network[i], name)
|| strstr(tmpbbs.address[i], name))
break;
}
if (i < tmpbbs.total_networks) {
found++;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
continue;
}
for (i = 0; i < tmpbbs.total_terminals; i++) {
strupr(tmpbbs.terminal[i]);
if (strstr(tmpbbs.terminal[i], name))
break;
}
if (i < tmpbbs.total_terminals) {
found++;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
continue;
}
for (i = 0; i < tmpbbs.total_numbers; i++) {
strupr(tmpbbs.number[i].modem.number);
strupr(tmpbbs.number[i].modem.desc);
strupr(tmpbbs.number[i].modem.location);
if (strstr(tmpbbs.number[i].modem.number, name)
|| strstr(tmpbbs.number[i].modem.desc, name)
|| strstr(tmpbbs.number[i].modem.location, name))
break;
}
if (i < tmpbbs.total_numbers) {
found++;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
continue;
}
}
if (!ch || !found) {
CRLF;
#if 0
if (kbhit())
getch();
#endif
if (found)
bprintf("\1n\1h%u systems listed.\r\n", found);
pause();
}
break;
case 'G': /* Generated sorted list */
cls();
if (!filelength(fileno(stream))) {
bprintf("No BBS list exists.\r\n");
pause();
break;
}
bputs("\1n\1c\1hSort Options:\1n\r\n\r\n");
bputs("\1h\1w(\1mN\1w) \1n\1mName of System\r\n");
bputs("\1h\1w(\1mS\1w) \1n\1mSoftware Used\r\n");
bputs("\1h\1w(\1mP\1w) \1n\1mPhone Number\r\n");
bputs("\1h\1w(\1mB\1w) \1n\1mMaximum Connect Rate (in bps)\r\n");
bputs("\1h\1w(\1mM\1w) \1n\1mModem Type\r\n");
bputs("\1h\1w(\1mY\1w) \1n\1mSysop's Name\r\n");
bputs("\1h\1w(\1mT\1w) \1n\1mTotal Number of Nodes\r\n");
bputs("\1h\1w(\1mU\1w) \1n\1mTotal Number of Users\r\n");
bputs("\1h\1w(\1mH\1w) \1n\1mTotal Storage Capacity (in megabytes)\r\n");
bputs("\1h\1w(\1mL\1w) \1n\1mLocation (City, State)\r\n");
bputs("\1h\1w(\1mF\1w) \1n\1mDate System was First Online\r\n");
bputs("\1h\1w(\1mC\1w) \1n\1mDate Entry was Created\r\n");
bputs("\1h\1w(\1mV\1w) \1n\1mDate Entry was Last Verified\r\n");
bputs("\1h\1w(\1mD\1w) \1n\1mDate Entry was Last Updated\r\n");
bprintf("\r\n\1y\1hSort by (\1wQ\1y=Quit): \1w");
ch = getkeys("NSPBMYTUHLFCVDQ", 0);
if (!ch || ch == 'Q')
break;
cls();
bputs("\1n\1hSorting... \1m");
fseek(stream, 0L, SEEK_SET);
i = j = done = 0;
sort_by_str = 0;
sortstr = NULL;
sortint = NULL;
while (!feof(stream) && !done) {
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
j++;
bprintf("\b\b\b\b%4u", j);
if (!bbs.name[0]) /* don't sort deleted
* entries */
continue;
if (bbs.total_numbers < 1) /* don't sort corrupted
* entries */
continue;
i++;
switch (ch) {
case 'N':
sprintf(str, "%.30s", bbs.name);
sort_by_str = 1;
break;
case 'S':
sprintf(str, "%.30s", bbs.software);
sort_by_str = 1;
break;
case 'P':
sprintf(str, "%.30s", bbs.number[0].modem.number);
sort_by_str = 1;
break;
case 'M':
sprintf(str, "%.30s", bbs.number[0].modem.desc);
sort_by_str = 1;
break;
case 'Y':
sprintf(str, "%.30s", bbs.sysop[0]);
sort_by_str = 1;
break;
case 'L':
sprintf(str, "%.30s", bbs.number[0].modem.location);
sort_by_str = 1;
break;
case 'B':
l = bbs.number[0].modem.max_rate;
break;
case 'T':
l = bbs.nodes;
break;
case 'U':
l = bbs.users;
break;
case 'H':
l = bbs.megs;
break;
case 'F':
l = bbs.birth;
break;
case 'C':
l = bbs.created;
break;
case 'V':
l = bbs.verified;
break;
case 'D':
l = bbs.updated;
break;
}
if (sort_by_str) {
if ((sortstr = (sortstr_t *) realloc(sortstr
,sizeof(sortstr_t) * i)) == NULL) {
bprintf("\r\n\7Memory allocation error\r\n");
free(sortstr);
done = 1;
continue;
}
strcpy(sortstr[i - 1].str, str);
sortstr[i - 1].offset = j - 1;
}
else {
if ((sortint = (sortint_t *) realloc(sortint
,sizeof(sortint_t) * i)) == NULL) {
bprintf("\r\n\7Memory allocation error\r\n");
free(sortint);
done = 1;
continue;
}
sortint[i - 1].i = l;
sortint[i - 1].offset = j - 1;
}
}
if (done) {
pause();
break;
}
if (sort_by_str)
qsort((void *)sortstr, i, sizeof(sortstr[0])
,(int (*) (const void *, const void *))sortstr_cmp);
else
qsort((void *)sortint, i, sizeof(sortint[0])
,(int (*) (const void *, const void *))sortint_cmp);
bprintf("\r\n\r\n\1h\1gCreating index...");
sprintf(str, "sort_%03d.ndx", node_num);
if ((file = nopen(str, O_WRONLY | O_CREAT | O_TRUNC)) == -1) {
bprintf("\r\n\7Error creating %s\r\n", str);
if (sort_by_str)
free(sortstr);
else
free(sortint);
pause();
break;
}
for (j = 0; j < i; j++)
if (sort_by_str)
write(file, &sortstr[j].offset, 2);
else
write(file, &sortint[j].offset, 2);
close(file);
if (sort_by_str)
free(sortstr);
else
free(sortint);
bputs("\r\n\r\n\1n\1hDone.\r\n");
pause();
break;
case 'D':
cls();
sprintf(str, "sort_%03d.ndx", node_num);
if ((file = nopen(str, O_RDONLY)) == -1) {
bputs("\1n\1r\1hSorted list not generated.\r\n");
pause();
}
ch = yesno("Display extended information");
cls();
while ( /* !eof(file) && not on unix */ !aborted) {
if (read(file, &i, 2) != 2)
break;
fseek(stream, (long)i * sizeof(bbs_t), SEEK_SET);
if (!sbl_pause)
lncntr = 0;
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] || bbs.total_numbers < 1)
continue;
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
}
close(file);
#if 0
if (kbhit())
getch();
#endif
if (lncntr)
pause();
break;
case 'N': /* New (updated) entry scan */
cls();
bputs("\1y\1hLast update (MM/DD/YY): ");
if (!getstr(str, 8, K_UPPER | K_LINE))
break;
l = dstrtounix(str);
ch = yesno("\r\nDisplay extended information");
found = 0;
bputs("\1n\1h\r\nSearching...\r\n\r\n");
fseek(stream, 0L, SEEK_SET);
while (!feof(stream) && !aborted) {
if (!sbl_pause)
lncntr = 0;
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!bbs.name[0] || bbs.total_numbers < 1)
continue;
if (bbs.updated >= l || bbs.created >= l) {
if (ch && !long_bbs_info(bbs))
break;
if (!ch && !short_bbs_info(bbs))
break;
found++;
continue;
}
}
if (!ch || !found) {
CRLF;
pause();
}
break;
case 'A':
cls();
if ((uint) user_level < add_ml) {
bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
pause();
break;
}
bputs("\1g\1hAdding a BBS entry:\1n\r\n\r\n");
bputs("\1n\1gHit ENTER for unknown data items.\r\n\r\n");
memset(&bbs, 0, sizeof(bbs_t));
if (!get_bbs_info(&bbs))
break;
bputs("\1n\1h\r\nSearching for duplicates...");
fseek(stream, 0L, SEEK_SET);
i = 0;
dots(0);
while (!feof(stream) && !i) {
dots(1);
if (!fread(&tmpbbs, sizeof(bbs_t), 1, stream))
break;
if (!stricmp(tmpbbs.name, bbs.name))
i = 1;
}
if (i) {
bprintf("\7\1n\1h\1r\1i\r\n\r\n%s \1n\1h\1ralready exists!"
"\r\n\r\n"
,bbs.name);
pause();
break;
}
bputs("\1n\1h\r\nSaving...");
fseek(stream, 0L, SEEK_SET);
dots(0);
while (!feof(stream)) {
dots(1);
if (!fread(&ch, 1, 1, stream))
break;
if (!ch) { /* first byte is null */
fseek(stream, -1L, SEEK_CUR);
break;
}
fseek(stream, (long)sizeof(bbs_t) - 1L, SEEK_CUR);
}
bbs.created = time(NULL);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
if (notify_user && notify_user != user_number) {
sprintf(str, "\1n\1hSBL: \1y%s \1madded \1c%s\1m "
"to the BBS List\r\n", user_name, bbs.name);
putsmsg(notify_user, str);
}
break;
case 'R': /* Remove an entry */
cls();
if ((uint) user_level < remove_ml) {
bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
pause();
break;
}
bprintf("\1y\1hRemove which system: ");
if (!getstr(name, 25, K_LINE | K_UPPER))
break;
bputs("\1n\1h\r\nSearching...");
fseek(stream, 0L, SEEK_SET);
found = 0;
dots(0);
while (!feof(stream) && !aborted) {
dots(1);
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!stricmp(bbs.name, name) || partname(bbs.name, name)) {
found = 1;
for (i = 0; i < bbs.total_sysops && i < MAX_SYSOPS; i++)
if (!stricmp(bbs.sysop[i], user_name))
break;
if (SYSOP || !stricmp(bbs.user, user_name)
|| i < bbs.total_sysops) {
fseek(stream, -(long)(sizeof(bbs_t)), SEEK_CUR);
strcpy(tmp, bbs.name);
bbs.name[0] = 0;
bbs.updated = time(NULL);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
bprintf("\r\n\r\n\1m%s\1c deleted."
,tmp);
if (notify_user && notify_user != user_number) {
sprintf(str, "\1n\1hSBL: \1y%s \1mremoved \1c%s\1m "
"from the BBS List\r\n", user_name, tmp);
putsmsg(notify_user, str);
}
}
else
bprintf("\r\n\r\n\1rYou did not create \1m%s\1n."
,bbs.name);
break;
}
}
if (!found)
bprintf("\r\n\r\n\1m%s\1c not found.", name);
CRLF;
CRLF;
pause();
break;
case 'T':
sbl_pause = !sbl_pause;
break;
case 'V': /* Verify an entry */
cls();
if ((uint) user_level < verify_ml) {
bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
pause();
break;
}
bprintf("\1y\1hVerify which system: ");
if (!getstr(name, 25, K_LINE | K_UPPER))
break;
bputs("\1n\1h\r\nSearching...");
fseek(stream, 0L, SEEK_SET);
found = 0;
dots(0);
while (!feof(stream) && !aborted) {
dots(1);
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!stricmp(bbs.name, name) || partname(bbs.name, name)) {
found = 1;
bbs.verified = time(NULL);
sprintf(bbs.userverified, "%.25s", user_name);
fseek(stream, -(long)(sizeof(bbs_t)), SEEK_CUR);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
bprintf("\r\n\r\n\1m%s\1c verified. \1r\1h\1iThank you!"
,bbs.name);
sprintf(str, "\1n\1hSBL: \1y%s \1mverified \1c%s\1m "
"in the BBS List\r\n", user_name, bbs.name);
if (notify_user && notify_user != user_number)
putsmsg(notify_user, str);
if (stricmp(bbs.user, user_name)) {
i = usernumber(bbs.user);
if (i && i != (int)user_number)
putsmsg(i, str);
}
break;
}
}
if (!found)
bprintf("\r\n\r\n\1m%s\1c not found.", name);
CRLF;
CRLF;
pause();
break;
case 'U': /* Update an entry */
cls();
if ((uint) user_level < update_ml) {
bprintf("\1h\1rYou have insufficient access.\r\n\r\n");
pause();
break;
}
bprintf("\1y\1hUpdate which system: ");
if (!getstr(name, 25, K_LINE | K_UPPER))
break;
bputs("\1n\1h\r\nSearching...");
fseek(stream, 0L, SEEK_SET);
found = 0;
dots(0);
while (!feof(stream) && !aborted) {
dots(1);
l = ftell(stream);
if (!fread(&bbs, sizeof(bbs_t), 1, stream))
break;
if (!stricmp(bbs.name, name) || partname(bbs.name, name)) {
found = 1;
break;
}
}
if (found) {
for (i = 0; i < bbs.total_sysops && i < MAX_SYSOPS; i++)
if (!bbs.sysop[i][0] || !stricmp(bbs.sysop[i], user_name))
break;
if (SYSOP || !stricmp(bbs.user, user_name)
|| i < bbs.total_sysops) {
CRLF;
CRLF;
if (get_bbs_info(&bbs)) {
bbs.misc &= ~FROM_SMB;
bbs.updated = time(NULL);
sprintf(bbs.userupdated, "%.25s", user_name);
fseek(stream, l, SEEK_SET);
fwrite(&bbs, sizeof(bbs_t), 1, stream);
fflush(stream);
bprintf("\r\n\1h\1m%s\1c updated.", bbs.name);
if (notify_user && notify_user != user_number) {
sprintf(str, "\1n\1hSBL: \1y%s \1mupdated \1c%s\1m "
"in the BBS List\r\n", user_name, bbs.name);
putsmsg(notify_user, str);
}
}
}
else
bprintf("\r\n\r\n\1h\1rYou did not create \1m%s\1n."
,bbs.name);
}
else
bprintf("\r\n\r\n\1h\1m%s\1c not found.", name);
CRLF;
CRLF;
pause();
break;
case 'Q':
return (0);
}
}
return (-1);
}
/* End of SBL.C */
30 Days to keep non-updated entries
50 Minimum security level to add
50 Minimum security level to update
50 Minimum security level to remove
10 Minimum security level to verify
1 User to notify of changes (0=none)
Synchronet BBS List v3.20 (native 32-bit for Win32 and Unix)
=========================
Create the directory: SBL off of your Synchronet XTRN directory.
(Example: C:\SBBS\XTRN\SBL)
Make sure SBL.CFG are is this directory.
Use an ASCII editor to edit the Synchronet BBS List config file (SBL.CFG) to
your liking.
Under SCFG->External Programs->Online Programs->Main, hit INS (if it doesn't
already exist) and add Synchronet BBS List with the following configuration:
Name Synchronet BBS List
Internal Code SBL
Start-up Directory ..\xtrn\sbl
Command Line sbl%.
Clean-up Command Line
Execution Cost None
Access Requirements
Execution Requirements
Multiple Concurrent Users Yes
Intercept Standard I/O No
Native (32-bit) Executable Yes
Use Shell to Execute No
Modify User Data No
Execute on Event No
BBS Drop File Type Synchronet XTRN.DAT
Place Drop File In Node Directory
SBL Utilities
=============
SBLPACK Remove deleted entries to save disk space and speed up listings
Networking the Synchronet BBS List
==================================
If you wish to link your SBL database with other Synchronet BBSes, you must
carry the Synchronet Data echo via DOVE-Net, FidoNet, or RIME and add
the following two events in SCFG->External Programs->Timed Events:
Internal Code SMB2SBL
Start-up Directory ..\xtrn\sbl
Command Line smb2sbl%. %jsubs\syncdata sbl.dab
Execution Node 1
Execution Days of Month Any
Execution Days of Week All
Execution Time 00:00
Requires Exclusive Execution No
Force Users Off-line For Event No
Native (32-bit) Executable Yes
Use Shell to Execute No
Background Execution No
Internal Code SBL2SMB
Start-up Directory ..\xtrn\sbl
Command Line sbl2smb%. sbl.dab %jsubs\syncdata
Execution Node 11
Execution Days of Month Any
Execution Days of Week All
Execution Time 00:00
Requires Exclusive Execution No
Force Users Off-line For Event No
Native (32-bit) Executable Yes
Use Shell to Execute No
Background Execution No
Change "SYNCDATA" to the internal code of the Synchronet Data sub-board on
your BBS. We used SYNCDATA, since that is the example given in the Synchronet
manual for the DOVE-Net Synchronet Data sub-board internal code. It is okay
if you used a completely different internal code, as long as you specify that
code instead of "SYNCDATA" on the above command lines.
Make note that all networked SBL entries will be deleted from Vertrauen
(Home of the Synchronet BBS List) after 90 days unless the entry is
retransmitted in the message base or updated manually on Vertrauen in that
time. To cause a retransmission from your BBS, you must (U)pdate the entry
using SBL and then SBL2SMB will re-export it automatically next time it is run
(via Timed Event). (V)erified entries are not re-exported by SBL2SMB, only new
and updated entries. You can also create a BBS entry message by hand (not
using SBL). Download SBBSLIST.ZIP from Vertrauen for more details.
Source Code
===========
If you are a C programmer, you may find the included source code interesting
and/or useful as an example for writing your own XSDK and/or SMB utilities.
Makefile is for use with Borland C++ or C++Builder and the Synchronet XSDK
to create SBL.EXE. GNUmakefile is for use with the GNU C Compiler.
And sbl.dsp is for use with Microsoft Visual C++ v6.0.
/* End of SBL.DOC */
\ No newline at end of file
# Microsoft Developer Studio Project File - Name="sbl" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=sbl - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sbl.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sbl.mak" CFG="sbl - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "sbl - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "sbl - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "sbl - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "sbl___Win32_Release"
# PROP BASE Intermediate_Dir "sbl___Win32_Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "sbl - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "sbl___Win32_Debug"
# PROP BASE Intermediate_Dir "sbl___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.debug"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib wsock32.lib /nologo /subsystem:console /map /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "sbl - Win32 Release"
# Name "sbl - Win32 Debug"
# Begin Source File
SOURCE=.\sbl.c
# End Source File
# Begin Source File
SOURCE=.\sbldefs.h
# End Source File
# Begin Source File
SOURCE=..\Sdk\xsdk.c
# End Source File
# Begin Source File
SOURCE=..\Sdk\xsdkvars.c
# End Source File
# Begin Source File
SOURCE=..\sdk\xsdkwrap.c
# End Source File
# End Target
# End Project
#!/bin/sh
. ${SBBSEXEC}unixstub.sh
/* sbl2smb.c */
/* Scans SBL database and posts any additions/updates into the an SMB base */
/* $Id: sbl2smb.c,v 1.14 2019/08/06 17:06:32 deuce Exp $ */
/****************************************************************************
* @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 xtrn *
* *
* 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. *
****************************************************************************/
#ifdef _WIN32
#include <windows.h>
#include <io.h> /* access */
#include <share.h>
#endif
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "md5.h"
#include "genwrap.h"
#include "filewrap.h"
#include "dirwrap.h"
#include "sbbsdefs.h"
#include "smblib.h"
#include "sbldefs.h"
smb_t smb;
char revision[16];
/****************************************************************************/
/* Converts unix time format (long - time_t) into a char str MM/DD/YY */
/****************************************************************************/
char* unixtodstr(time_t unix_time, char *str)
{
struct tm* tm;
if(!unix_time)
strcpy(str,"00/00/00");
else {
tm=gmtime(&unix_time);
if(tm==NULL) {
strcpy(str,"00/00/00");
return(str);
}
if(tm->tm_mon>11) { /* DOS leap year bug */
tm->tm_mon=0;
tm->tm_year++; }
if(tm->tm_mday>31)
tm->tm_mday=1;
sprintf(str,"%02u/%02u/%02u",tm->tm_mday,tm->tm_mon+1
,TM_YEAR(tm->tm_year));
}
return(str);
}
#define BUF_LEN (32*1024)
int main(int argc, char **argv)
{
uchar str[128],tmp[128],*buf,*p,software[128];
int i,file;
ushort xlat;
long length;
ulong offset;
time_t last,now;
bbs_t bbs;
smbmsg_t msg;
FILE *stream;
sscanf("$Revision: 1.14 $" + 11, "%s", revision);
fprintf(stderr,"\nSBL2SMB v2.%s-%s - Write SBL to SMB - Coyright 2002 "
"Rob Swindell\n\n",revision,PLATFORM_DESC);
if(argc<3) {
fprintf(stderr,"usage: sbl2smb <sbl.dab> <smb_file> [/s:software]\n\n");
fprintf(stderr,"ex: sbl2smb /sbbs/xtrn/sbl/sbl.dab "
"/sbbs/data/subs/syncdata\n");
return(1);
}
if((buf = malloc(BUF_LEN)) == NULL) {
fprintf(stderr,"!malloc failure\n");
return(2);
}
now=time(NULL);
software[0]=0;
if(argc>3 && !strnicmp(argv[3],"/S:",3))
SAFECOPY(software,argv[3]+3);
SAFECOPY(smb.file,argv[2]);
SAFECOPY(str,argv[1]);
if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
printf("error opening %s\n",str);
return(1); }
if((stream=fdopen(file,"rb"))==NULL) {
printf("error fdopening %s\n",str);
return(1); }
strcpy(tmp,str);
p=strrchr(tmp,'.');
if(p) {
(*p)=0;
strcat(tmp,"2smb.dab");
if((file=open(tmp,O_RDWR|O_BINARY|O_CREAT,S_IWRITE|S_IREAD))==-1) {
printf("error opening %s\n",str);
return(1); }
if(read(file,&last,sizeof(time_t))!=sizeof(time_t))
last=0;
lseek(file,0L,SEEK_SET);
write(file,&now,sizeof(now));
close(file); }
sprintf(str,"%s.shd",smb.file);
if(!fexist(str)) {
printf("%s doesn't exist\n",smb.file);
return(0); }
fprintf(stderr,"Opening %s\n",smb.file);
smb.retry_time=30;
if((i=smb_open(&smb))!=0) {
printf("smb_open returned %d\n",i);
return(1); }
i=smb_locksmbhdr(&smb);
if(i) {
printf("smb_locksmbhdr returned %d\n",i);
return(1); }
i=smb_getstatus(&smb);
smb_unlocksmbhdr(&smb);
if(i) {
printf("smb_getstatus returned %d\n",i);
return(1); }
while(!feof(stream)) {
if(!fread(&bbs,sizeof(bbs_t),1,stream))
break;
if(bbs.total_numbers<1 /* corrupted? */
|| bbs.total_numbers>MAX_NUMBERS)
continue;
truncsp(bbs.name);
if(bbs.name[0]<=' ' /* corrupted? */
|| bbs.misc&FROM_SMB
|| (bbs.updated<last && bbs.created<last
&& bbs.verified<last))
continue;
if(software[0] && strnicmp(software,bbs.software,strlen(software)))
continue;
truncsp(bbs.user);
if(bbs.user[0]<=' ') /* corrupted? */
continue;
truncsp(bbs.software);
if(bbs.software[0]<=' ') /* corrupted? */
continue;
printf("%s\r\n",bbs.name);
memset(buf,0,BUF_LEN);
sprintf(str,"%-15.15s%s\r\n"
,"Name:",bbs.name);
strcat(buf,str);
sprintf(str,"%-15.15s%s\r\n"
,"Birth:",unixtodstr(bbs.birth,tmp));
strcat(buf,str);
sprintf(str,"%-15.15s%s\r\n"
,"Software:",bbs.software);
strcat(buf,str);
for(i=0;i<bbs.total_sysops;i++) {
truncsp(bbs.sysop[i]);
sprintf(str,"%-15.15s%s\r\n"
,"Sysop:",bbs.sysop[i]);
strcat(buf,str); }
strcat(buf,"\r\n");
truncsp(bbs.sysop_email);
if(bbs.sysop_email[0]) {
sprintf(str,"%-15.15s%s\r\n"
,"E-mail:",bbs.sysop_email);
strcat(buf,str);
}
truncsp(bbs.web_url);
if(bbs.web_url[0]) {
sprintf(str,"%-15.15s%s\r\n"
,"Web-site:",bbs.web_url);
strcat(buf,str);
}
strcat(buf,"\r\n");
for(i=0;i<bbs.total_numbers;i++) {
truncsp(bbs.number[i].modem.number);
sprintf(str,"%-15.15s%s\r\n"
,"Number:",bbs.number[i].modem.number);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"MinRate:",bbs.number[i].modem.min_rate);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"MaxRate:",bbs.number[i].modem.max_rate);
strcat(buf,str);
if(bbs.number[i].modem.min_rate!=0xffff) {
sprintf(str,"%-15.15s%s\r\n"
,"Modem:",bbs.number[i].modem.desc);
strcat(buf,str);
}
truncsp(bbs.number[i].modem.location);
sprintf(str,"%-15.15s%s\r\n"
,"Location:",bbs.number[i].modem.location);
strcat(buf,str);
if(i+1<bbs.total_numbers)
strcat(buf,"\r\n"); }
if(bbs.total_networks)
strcat(buf,"\r\n");
for(i=0;i<bbs.total_networks;i++) {
sprintf(str,"%-15.15s%s\r\n"
,"Network:",bbs.network[i]);
strcat(buf,str);
sprintf(str,"%-15.15s%s\r\n"
,"Address:",bbs.address[i]);
strcat(buf,str);
if(i+1<bbs.total_networks)
strcat(buf,"\r\n"); }
strcat(buf,"\r\n");
for(i=0;i<bbs.total_terminals;i++) {
sprintf(str,"%-15.15s%s\r\n"
,"Terminal:",bbs.terminal[i]);
strcat(buf,str); }
strcat(buf,"\r\n");
sprintf(str,"%-15.15s%lu\r\n"
,"Megs:",bbs.megs);
strcat(buf,str);
sprintf(str,"%-15.15s%lu\r\n"
,"Msgs:",bbs.msgs);
strcat(buf,str);
sprintf(str,"%-15.15s%lu\r\n"
,"Files:",bbs.files);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"Nodes:",bbs.nodes);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"Users:",bbs.users);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"Subs:",bbs.subs);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"Dirs:",bbs.dirs);
strcat(buf,str);
sprintf(str,"%-15.15s%u\r\n"
,"Xtrns:",bbs.xtrns);
strcat(buf,str);
if(bbs.desc[0][0])
strcat(buf,"\r\n");
for(i=0;i<5;i++) {
if(!bbs.desc[i][0])
break;
sprintf(str,"%-15.15s%s\r\n"
,"Desc:",bbs.desc[i]);
strcat(buf,str); }
sprintf(buf+strlen(buf),"\r\n--- SBL2SMB 2.%s-%s",revision,PLATFORM_DESC);
length=strlen(buf); /* +2 for translation string */
if(smb.status.attr&SMB_HYPERALLOC)
offset=smb_hallocdat(&smb);
else {
i=smb_open_da(&smb);
if(i) {
printf("smb_open_da returned %d\n",i);
exit(1); }
offset=smb_allocdat(&smb,length+2,1);
fclose(smb.sda_fp); }
fseek(smb.sdt_fp,offset,SEEK_SET);
xlat=XLAT_NONE;
fwrite(&xlat,2,1,smb.sdt_fp);
fwrite(buf,length,1,smb.sdt_fp);
length+=2;
memset(&msg,0,sizeof(smbmsg_t));
memcpy(msg.hdr.msghdr_id,"SHD\x1a",4);
msg.hdr.version=smb_ver();
msg.hdr.when_written.time=now;
msg.hdr.when_imported.time=now;
msg.hdr.offset=offset;
strcpy(str,"SBL");
i=smb_hfield(&msg,RECIPIENT,(ushort)strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
strlwr(str);
msg.idx.to=crc16(str);
strcpy(str,bbs.user);
i=smb_hfield(&msg,SENDER,(ushort)strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
strlwr(str);
msg.idx.from=crc16(str);
strcpy(str,bbs.name);
i=smb_hfield(&msg,SUBJECT,(ushort)strlen(str),str);
if(i) {
printf("smb_hfield returned %d\n",i);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
strlwr(str);
msg.idx.subj=crc16(str);
i=smb_dfield(&msg,TEXT_BODY,length);
if(i) {
printf("smb_dfield returned %d\n",i);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
if(i) {
printf("smb_addmsghdr returned %d\n",i);
smb_freemsgdat(&smb,offset,length,1);
exit(1); }
smb_freemsgmem(&msg); }
return(0);
}
/* End of SBL2SMB.C */
# Microsoft Developer Studio Project File - Name="sbl2smb" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=sbl2smb - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sbl2smb.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sbl2smb.mak" CFG="sbl2smb - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "sbl2smb - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "sbl2smb - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "sbl2smb - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.release"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "c:\src\sbbs3" /I "c:\src\xpdev" /I "..\sdk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "sbl2smb - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "sbl2smb___Win32_Debug"
# PROP BASE Intermediate_Dir "sbl2smb___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "c:\src\sbbs3" /I "c:\src\xpdev" /I "..\sdk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "sbl2smb - Win32 Release"
# Name "sbl2smb - Win32 Debug"
# Begin Source File
SOURCE=c:\src\xpdev\dirwrap.c
# End Source File
# Begin Source File
SOURCE=c:\src\xpdev\filewrap.c
# End Source File
# Begin Source File
SOURCE=c:\src\xpdev\genwrap.c
# End Source File
# Begin Source File
SOURCE=.\sbl2smb.c
# End Source File
# Begin Source File
SOURCE=C:\src\sbbs3\smblib.c
# End Source File
# End Target
# End Project
/* SBL2TXT.C */
/* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
/* Converts Synchronet BBS List (SBL.DAB) to text file */
#include "xsdk.h"
#include "sbldefs.h"
char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
,"Jul","Aug","Sep","Oct","Nov","Dec"};
char *nulstr="";
char tmp[256];
struct date date;
struct time curtime;
extern int daylight=0;
extern long timezone=0L;
/****************************************************************************/
/* Generates a 24 character ASCII string that represents the time_t pointer */
/* Used as a replacement for ctime() */
/****************************************************************************/
char *timestr(time_t *intime)
{
static char str[256];
char mer[3],hour;
struct tm *gm;
gm=localtime(intime);
if(gm->tm_hour>=12) {
if(gm->tm_hour==12)
hour=12;
else
hour=gm->tm_hour-12;
strcpy(mer,"pm"); }
else {
if(gm->tm_hour==0)
hour=12;
else
hour=gm->tm_hour;
strcpy(mer,"am"); }
sprintf(str,"%s %s %02d %4d %02d:%02d %s"
,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,gm->tm_year%100
,hour,gm->tm_min,mer);
return(str);
}
/****************************************************************************/
/* Converts unix time format (long - time_t) into a char str MM/DD/YY */
/****************************************************************************/
char *unixtodstr(time_t unix, char *str)
{
if(!unix)
strcpy(str,"00/00/00");
else {
unixtodos(unix,&date,&curtime);
if((unsigned)date.da_mon>12) { /* DOS leap year bug */
date.da_mon=1;
date.da_year++; }
if((unsigned)date.da_day>31)
date.da_day=1;
sprintf(str,"%02u/%02u/%02u",date.da_mon,date.da_day
,date.da_year>=2000 ? date.da_year-2000 : date.da_year-1900); }
return(str);
}
void long_bbs_info(FILE *out, bbs_t bbs)
{
int i;
fprintf(out,"BBS Name: %s since %s\r\n"
,bbs.name,unixtodstr(bbs.birth,tmp));
fprintf(out,"Operator: ");
for(i=0;i<bbs.total_sysops;i++) {
if(i) {
if(bbs.total_sysops>2)
fprintf(out,", ");
else
fputc(' ',out);
if(!(i%4))
fprintf(out,"\r\n ");
if(i+1==bbs.total_sysops)
fprintf(out,"and "); }
fprintf(out,"%s",bbs.sysop[i]); }
fprintf(out,"\r\n");
fprintf(out,"Software: %-15.15s Nodes: %-5u "
"Users: %-5u Doors: %u\r\n"
,bbs.software,bbs.nodes,bbs.users,bbs.xtrns);
fprintf(out,"Download: %lu files in %u directories of "
"%luMB total space\r\n"
,bbs.files,bbs.dirs,bbs.megs);
fprintf(out,"Messages: %lu messages in %u sub-boards\r\n"
,bbs.msgs,bbs.subs);
fprintf(out,"Networks: ");
for(i=0;i<bbs.total_networks;i++) {
if(i) {
if(bbs.total_networks>2)
fprintf(out,", ");
else
fputc(' ',out);
if(!(i%3))
fprintf(out,"\r\n ");
if(i+1==bbs.total_networks)
fprintf(out,"and "); }
fprintf(out,"%s [%s]",bbs.network[i],bbs.address[i]); }
fprintf(out,"\r\n");
fprintf(out,"Terminal: ");
for(i=0;i<bbs.total_terminals;i++) {
if(i) {
if(bbs.total_terminals>2)
fprintf(out,", ");
else
fputc(' ',out);
if(i+1==bbs.total_terminals)
fprintf(out,"and "); }
fprintf(out,"%s",bbs.terminal[i]); }
fprintf(out,"\r\n\r\n");
for(i=0;i<bbs.total_numbers;i++)
fprintf(out,"%-30.30s %12.12s %5u %-15.15s "
"Minimum: %u\r\n"
,i && !strcmp(bbs.number[i].modem.location,bbs.number[i-1].modem.location)
? nulstr : bbs.number[i].modem.location
,bbs.number[i].modem.number
,bbs.number[i].modem.max_rate
,bbs.number[i].modem.desc
,bbs.number[i].modem.min_rate);
fprintf(out,"\r\n");
for(i=0;i<5;i++) {
if(!bbs.desc[i][0])
break;
fprintf(out,"%15s%s\r\n",nulstr,bbs.desc[i]); }
fprintf(out,"\r\n");
fprintf(out,"Entry created on %s by %s\r\n"
,timestr(&bbs.created),bbs.user);
fprintf(out," Last updated on %s\r\n\r\n",timestr(&bbs.updated));
}
void main(int argc, char **argv)
{
char software[16]="";
char telnet_port[16];
int i,in;
FILE *out;
bbs_t bbs;
for(i=1;i<argc;i++)
if(argv[i][0]=='s' && argv[i][1]=='=')
sprintf(software,"%.15s",argv[i]+2);
if((in=open("SBL.DAB",O_RDONLY|O_BINARY))==-1) {
printf("error opening SBL.DAB\n");
return; }
if((out=fopen("SBL.TXT","wb"))==NULL) {
printf("error opening/creating SBL.TXT\n");
return; }
while(!eof(in)) {
read(in,&bbs,sizeof(bbs_t));
if(!bbs.name[0])
continue;
if(software[0] && strnicmp(bbs.software,software,strlen(software)))
continue;
// long_bbs_info(out,bbs);
for(i=0;i<bbs.total_numbers;i++)
if(bbs.number[i].modem.min_rate==0xffff) {
if(bbs.number[i].telnet.port && bbs.number[i].telnet.port!=23)
sprintf(telnet_port,":%u",bbs.number[i].telnet.port);
else
telnet_port[0]=0;
fprintf(out,"%-25.25s telnet://%s%s\r\n"
,bbs.name
,bbs.number[i].telnet.addr
,telnet_port);
} else
fprintf(out,"%-25.25s %12.12s %5u %s\r\n"
,bbs.name,bbs.number[i].modem.number
,bbs.number[i].modem.max_rate
,bbs.number[i].modem.desc);
}
close(in);
fclose(out);
}
/* sbldefs.h */
/* Synchronet BBS List Macros, constants, and type definitions */
/* $Id: sbldefs.h,v 1.11 2013/09/15 09:16:47 rswindell Exp $ */
/****************************************************************************
* @format.tab-size 4 (Plain Text/Source Code File Header) *
* @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
* *
* Copyright 2013 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. *
****************************************************************************/
#include "gen_defs.h"
#define MAX_SYSOPS 5
#define MAX_NUMBERS 20
#define MAX_NETS 10
#define MAX_TERMS 5
#define DESC_LINES 5
#define DEF_LIST_FMT "NSTP"
#ifndef IPPORT_TELNET
#define IPPORT_TELNET 23
#endif
#define Y2K_2DIGIT_WINDOW 70
/* Misc bits */
#define FROM_SMB (1L<<0) /* BBS info imported from message base */
#ifdef _WIN32 /* necessary for compatibility with SBL */
#pragma pack(push)
#pragma pack(1)
#endif
#ifndef _PACK
#ifdef __GNUC__
#define _PACK __attribute__ ((packed))
#else
#define _PACK
#endif
#endif
typedef union _PACK {
struct {
char number[13]; /* Phone number */
char desc[16]; /* Modem description */
char location[31]; /* Location of phone number */
uint16_t min_rate; /* Minimum connect rate */
uint16_t max_rate; /* Maximum connect rate */
} modem;
struct {
char addr[29]; /* Telnet address */
char location[31]; /* Location */
uint16_t unused; /* 0xffff */
uint16_t port; /* TCP port number */
} telnet;
} number_t;
typedef struct _PACK {
char name[26] /* System name */
,user[26] /* User who created entry */
,software[16] /* BBS software */
,total_sysops
,sysop[MAX_SYSOPS][26] /* Sysop names */
,total_numbers
,total_networks
,network[MAX_NETS][16] /* Network names */
,address[MAX_NETS][26] /* Network addresses */
,total_terminals
,terminal[MAX_TERMS][16] /* Terminals supported */
,desc[DESC_LINES][51] /* 5 line description */
;
uint16_t nodes /* Total nodes */
,users /* Total users */
,subs /* Total sub-boards */
,dirs /* Total file dirs */
,xtrns /* Total external programs */
;
uint32_t created /* Time/date entry was created */
,updated /* Time/date last updated */
,birth /* Birthdate of BBS */
;
uint32_t megs /* Storage space in megabytes */
,msgs /* Total messages */
,files /* Total files */
,misc /* Miscellaneous bits */
;
number_t number[MAX_NUMBERS]; /* Access numbers */
char userupdated[26]; /* User who last updated */
uint32_t verified; /* Time/Date last vouched for */
char userverified[26]; /* User who last vouched */
char web_url[61]; /* Web-site address */
char sysop_email[61]; /* Sysop's e-mail address */
uint32_t exported; /* Date last exported to SMB */
uint32_t verification_count; /* Number of successful auto-verifications */
uint32_t verification_attempts; /* Number of auto-verification attempts */
char unused[310]; /* Unused space */
} bbs_t;
#ifdef _WIN32
#pragma pack(pop) /* original packing */
#endif
/* End of SBL.H */
#!/bin/sh
. ${SBBSEXEC}unixstub.sh
/* sblpack.c */
/* Synchronet BBS List Database Packer */
/* $Id: sblpack.c,v 1.5 2004/07/16 18:02:41 deuce Exp $ */
/****************************************************************************
* @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 xtrn *
* *
* 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. *
****************************************************************************/
#include <stdio.h>
#include <stdlib.h> /* exit() */
#include <time.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "filewrap.h" /* sopen() */
#include "genwrap.h" /* PLATFORM_DESC */
#include "sbldefs.h"
int main(void)
{
int file;
FILE * in;
FILE * out;
bbs_t bbs;
ulong records=0;
ulong deleted=0;
char revision[16];
sscanf("$Revision: 1.5 $", "%*s %s", revision);
printf("\nSBLPACK %s-%s Copyright 2003 Rob Swindell\n\n"
,revision,PLATFORM_DESC);
if((file=sopen("sbl.dab",O_RDWR|O_BINARY,SH_DENYNO))==-1) {
printf("\n\7Error opening/creating sbl.dab\n");
exit(1); }
if((in=fdopen(file,"w+b"))==NULL) {
printf("\n\7Error converting sbl.dab file handle to stream\n");
exit(1); }
setvbuf(in,0L,_IOFBF,2048);
if((out=fopen("sbl.tmp","wb"))==NULL) {
printf("\n\7Error opening sbl.tmp file\n");
exit(1); }
while(!feof(in)) {
if(!fread(&bbs,sizeof(bbs_t),1,in))
break;
records++;
putchar('.');
if(bbs.name[0]==0
|| bbs.user[0]==0
|| bbs.total_numbers<1) {
deleted++;
continue;
}
fwrite(&bbs,sizeof(bbs_t),1,out);
}
fclose(in);
fclose(out);
putchar('\n');
if(remove("sbl.dab")) {
printf("\n\7Data file in use, can't remove.\n");
remove("sbl.tmp");
exit(1);
}
rename("sbl.tmp","sbl.dab");
printf("\nDone.\n");
printf("\n%lu records in original file, %lu deleted (packed), new total = %lu.\n"
,records,deleted,records-deleted);
return(0);
}
# Microsoft Developer Studio Project File - Name="sblpack" - Package Owner=<4>
# Microsoft Developer Studio Generated Build File, Format Version 6.00
# ** DO NOT EDIT **
# TARGTYPE "Win32 (x86) Console Application" 0x0103
CFG=sblpack - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE NMAKE /f "sblpack.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE NMAKE /f "sblpack.mak" CFG="sblpack - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE "sblpack - Win32 Release" (based on "Win32 (x86) Console Application")
!MESSAGE "sblpack - Win32 Debug" (based on "Win32 (x86) Console Application")
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
# PROP Scc_ProjName ""
# PROP Scc_LocalPath ""
CPP=cl.exe
RSC=rc.exe
!IF "$(CFG)" == "sblpack - Win32 Release"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 0
# PROP BASE Output_Dir "Release"
# PROP BASE Intermediate_Dir "Release"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 0
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.release"
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD CPP /nologo /W3 /GX /O2 /I "..\sdk" /I "c:\src\xpdev" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
# ADD BASE RSC /l 0x409 /d "NDEBUG"
# ADD RSC /l 0x409 /d "NDEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
!ELSEIF "$(CFG)" == "sblpack - Win32 Debug"
# PROP BASE Use_MFC 0
# PROP BASE Use_Debug_Libraries 1
# PROP BASE Output_Dir "sblpack___Win32_Debug"
# PROP BASE Intermediate_Dir "sblpack___Win32_Debug"
# PROP BASE Target_Dir ""
# PROP Use_MFC 0
# PROP Use_Debug_Libraries 1
# PROP Output_Dir ""
# PROP Intermediate_Dir "msvc.win32.debug"
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\sdk" /I "c:\src\xpdev" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
# ADD BASE RSC /l 0x409 /d "_DEBUG"
# ADD RSC /l 0x409 /d "_DEBUG"
BSC32=bscmake.exe
# ADD BASE BSC32 /nologo
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
!ENDIF
# Begin Target
# Name "sblpack - Win32 Release"
# Name "sblpack - Win32 Debug"
# Begin Source File
SOURCE=.\sblpack.c
# End Source File
# End Target
# End Project
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment