Synchronet - Source Code


Availability

The Synchronet source code is freely available:
  • Anonymous FTP (for official source code releases):

  • Anonymous CVS (for current source code or previous releases by label):
    • Repository: cvs.synchro.net:/cvsroot/sbbs
    • Mirror: cvs-mirror.synchro.net:/cvsroot/sbbs
    • Required modules for building Synchronet:
      • src-sbbs3 (alias for several modules)
      • lib/mozilla/js/os.release (or .debug)
        example: lib/mozilla/js/linux.release
      • lib/mozilla/nspr/os.release (or .debug)
        example: lib/mozilla/nspr/win32.release
      • Or you may use one of the following module aliases
        (for all required libraries for the specified OS and build type):
        • lib-linux.debug
        • lib-linux.release
        • lib-win32.debug
        • lib-win32.release
    • Required modules for running Synchronet (if you don't already have Synchronet installed):
      • run-sbbs3 (alias for several modules)
    • Example labels (for checking-out a specific release):
      • sbbs300c
      • sbbs310k
    • CVS command-line example:
      • cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs co src/sbbs3
    • Win32 batch file to get/update required modules using the Win32 command-line CVS client:

  • Web-based CVS access, particularly useful for browsing the repository and visually comparing revisions of files ("diff'ing")
    http://cvs.synchro.net/cgi-bin/viewcvs.cgi

  • Log of recent commits (changes/additions) to the CVS repository
    http://vert.synchro.net/commitlog.ssjs

  • Rob's to-do list
    http://vert.synchro.net/todolist.ssjs

  • Step-by-step instructions on how to download, build, and run the current source code on Unix (Linux, FreeBSD, and OpenBSD), see
    http://www.synchro.net/docs/sbbsunix.txt



Building on Windows

Unlike on Unix, a combination of compilers may be utilized to build Synchronet for Win32. If you have Borland's free command-line C++ compiler (v5.5) installed, you can build almost everything except the GUI portions (e.g. Synchronet Control Panel), which require Borland C++ Builder, and the FOSSIL drivers, which require Microsoft Visual C++.

I use Microsoft Visual C++ 6 for most of the non-GUI portions of Synchronet because it has a better debugger and more solid IDE (in my opinion). However, Borland provides a much better GUI framework (VCL) with C++ Builder and a handy console I/O library (conio) not present in Microsoft's C run-time library (Note: Stephen Hurd has created a portable conio-compatible library for Win32, so this Microsoft omission is no longer a factor).

Even though I use Microsoft Visual C++ to build most of the Synchronet command-line utilities and all the DLLs, you may use Borland C++ or C++ Builder instead, if you prefer. But note: if you rebuild any of the DLLs, you must also re-link sbbsctrl.exe with the Borland import libraries for those DLLs (see src/sbbs3/ctrl/makelibs.bat for details).

Caveat: There is a known limitation with the Borland C run-time library (RTL) which may effect any Synchronet system built soley with Borland C++: The Borland C RTL is limited to 50 open files. Microsoft's C RTL does not have this limitation. The solution requires you have the source code to the Borland C RTL (normally in the Source\rtl directory):

  • Increase the value for the _NFILE definition in include/_nfile.h
  • Compile rtl\Source\io\files.c and files2.c
  • Link files.obj and files2.obj with your Synchronet executable (i.e. sbbs.exe or sbbsmono.exe)

As for the build files: the .dsp and .dsw files are used by Microsoft Visual C++, the Makefiles are used by Borland C++ 5.5 (or C++ Builder), and the .bpr files are used by C++ Builder.

ProjectBuild FileCompiler
sbbs.exe, ftpsrvr.dll, mailsrvr.dll, services.dll, and most utilities (e.g. addfiles.exe, baja.exe, etc.) src/sbbs3/build.bat
src/sbbs3/sbbs3.dsw
src/sbbs3/*.dsp
msvc6
src/sbbs3/Makefilebcc32
scfg.exesrc/sbbs3/scfg/build.bat
src/sbbs3/scfg/scfg.dsw
src/sbbs3/scfg/scfg.dsp
msvc6
src/sbbs3/scfg/Makefilebcc32
echocfg.exesrc/sbbs3/Makefilebcc32
sbbsctrl.exesrc/sbbs3/ctrl/build.bat
src/sbbs3/ctrl/sbbsctrl.bpr
bcb6
chat.exesrc/sbbs3/chat/chat.bprbcb6
useredit.exesrc/sbbs3/useredit/useredit.dprdelphi6
dosxtrn.exesrc/sbbs3/dosxtrn/make.batmsvc15
sbbsexec.dllsrc/sbbs3/sbbsexec.dspmsvc6
sbbsexec.vxdsrc/sbbs3/execvxd/makefilemsvc6 and VtoolsD

Compiler legend:
AbbreviationFull Product Name
bcb6Borland C++ Builder 6
bcc32 Borland C++ Compiler 5.5 (Free!) or Borland C++ Builder
delphi6Borland Delphi 6
msvc6Microsoft Visual C++ 6 or Visual C++ Express with the Platform SDK (Free!)
msvc15Microsoft Visual C++ 1.5 (16-bit)

Step-by-step Instructions (using Microsoft Visual C++ 6.0)

  1. Install Visual C++ (if you haven't already)
  2. Get the Synchronet source and library files (if you haven't already)
  3. Edit src\sbbs3\build.bat (if necessary) to point to your MSVC installation directory
  4. At a command prompt, go to the Synchronet src\sbbs3 directory and run build.bat
  5. At a command prompt, go to the Synchronet src\sbbs3\scfg directory and run build.bat
You can now copy the DLL and executables from the following directories into your Synchronet EXEC directory:
  • src\sbbs3\msvc.win32.dll.release
  • src\sbbs3\msvc.win32.exe.release
  • src\sbbs3\scfg\msvc.win32.exe.release
  • src\sbbs3\scfg\msvc.win32.exe.release\scfghelp.*

If the DLLs you just built are from a more recent version of Synchronet than your Synchronet Control Panel executable (sbbsctrl.exe), you will need to use sbbs.exe or sbbsNTsvcs.exe instead of sbbsctrl.exe to run Synchronet.

See docs\sbbscon.txt for more details on using the console mode version of Synchronet.
See docs\sbbsNTsvcs.txt for more details on using the NT services version of Synchronet.

Step-by-step Instructions (using Borland C++ Builder)

  1. Install C++ Builder (if you haven't already)
  2. Make sure your C++ Builder bin\bcc32.cfg file (create the file if necessary) contains the correct include and lib paths.
    Example:
    -Ic:\borland\bcc55\include
    -Lc:\borland\bcc55\lib
  3. Get the Synchronet source and library files (if you haven't already)
  4. At a command prompt, go to the Synchronet src\sbbs3 directory and run make
  5. At a command prompt, go to the Synchronet src\sbbs3\scfg directory and run make
  6. At a command prompt, go to the Synchronet src\sbbs3\ctrl directory and run build.bat
You can now copy the DLL and executables from the following directories into your Synchronet EXEC directory:
  • src\sbbs3\bcc.win32.dll.release
  • src\sbbs3\bcc.win32.exe.release
  • src\sbbs3\scfg\bcc.win32.release
  • src\sbbs3\ctrl
  • lib\mozilla\js\win32.release
  • lib\mozilla\nspr\win32.release
If you wish to build binaries with debugging information, add DEBUG=1 to your make command-lines and copy the binaries from the .debug instead of .release directories.

If you only have the free Borland command-line C++ compiler, all of the above steps still apply except for those referencing the src\sbbs3\ctrl directory. Also, if the DLLs you built are from a more recent version of Synchronet than your Synchronet Control Panel executable (sbbsctrl.exe), you will need to use sbbs.exe (or sbbsNTsvcs.exe) to run Synchronet.

See docs\sbbscon.txt for more details on using the console mode version of Synchronet.
See docs\sbbsNTsvcs.txt for more details on using the NT services version of Synchronet.


History (as of October 2000)

The Beginning

I, Rob Swindell, started writing Synchronet BBS Software from scratch in 1990 (at the age of 20). At that time, I had been programming in C for about a year and a half. Needless to say, some of the early design decisions, I would've made differently today (hindsight is always 20/20). When browsing the code, keep in mind there are still portions of the source that have remained unchanged for the past ten years (a virtual eternity in modern software). This should also explain any perceived inconsistencies in programming style or design approach.

Version 1

Synchronet v1 was written almost entirely in C with a couple of small portions written in x86 assembler. Synchronet was an entirely "hard-coded" BBS, that is, the user menu structure and command key sequences were hard-coded into the source code (the ASCII/ANSI/RIP menu files themselves were sysop replaceable/customizable). Synchronet v1 was a copyrighted commercial software package, and as such, was not distributed with source code. Synchronet v1 utilized an inefficient message storage method, using a separate file for each message (for both private e-mail and public message forums). Synchronet v1 was available as a 16-bit console-mode DOS program only.

Multi-node features (chat, multi-user games, etc) were abundant from the very first release, but each node required a separate instance of the program. Because of this requirement, local area networks (LANs) were often utilized for connecting multiple PCs as part of a single BBS as well as DESQview, Windows, and OS/2 for their DOS multi-tasking abilities.

Version 2

Synchronet v2 incorporated a programmable command and menu structure (PCMS), mostly doing away with hard-coded user commands. This allowed emulation of competing BBS packages (from the user's perspective) as well as sysop-customizable menus and dynamically loaded modules. A module/script compiler called Baja was included that utilized a high-level BASIC-like programming language.

Synchronet v2 also incorporated a new database-style message base format called SMB (Synchronet Message Base). The specifications and C library were released free to the public in hopes of encouraging competing BBS packages and utility authors to adopt SMB as a favorable alternative to the prolific Hudson, JAM, and Squish message base formats.

A binary configuration file format (.cnf) was introduced in v2 to speed up the loading of configuration files and improve extensibility.

Although a 32-bit console-mode OS/2 version of Synchronet v2 was released in 1995, it retained the same multi-node design as its DOS counterpart and required a separate instance of the program for each node. It was also during the active development life of Synchronet v2 that I began to release 32-bit extended DOS (DPMI), OS/2, and Win32 flavors of many of the utilities included with Synchronet.

Synchronet v2 remained commercial software until it was released as Freeware in early 1997 and the source code was documented, packaged, and released to the Public Domain later that same year (the Digital Dynamics' copyright was officially relinquished at this time). In December of 1999, I released a public beta of v2.30c for DOS and OS/2 (in binary form) that fixed a few millennium bugs and introduced some of the minor features I had incorporated thus far in my development of Synchronet v3.

Version 3

Synchronet was significantly redesigned in the fall of 1999 as a multi-threaded/multi-user telnet server for Win32 platforms. To aid the transition from the single-node-per-process model to a single-node-per-thread model, most of the source modules were converted from C to C++ so they could automatically inherit the current node's properties (previously implemented as global variables). Serial/modem/dial-up user support was not migrated from v2 to v3, so only telnet logins were supported. Configuration and database file compatibility with v2 was consciously maintained to allow mixing v2 and v3 nodes on the same live BBS. The main BBS module and telnet server was implemented as a single Win32 dynamic link library (DLL) built with Microsoft Visual C++.

Integrated FTP and Mail (SMTP/POP3) servers were also created for v3. The FTP and Mail servers were implemented as individual Win32 DLLs built with Microsoft Visual C++.

A GUI front-end called the Synchronet Control Panel was created using Borland C++ Builder and the VCL visual framework. The Synchronet Control Panel (SBBSCTRL.EXE) married the separate server DLLs and provided a uniform place for the sysop to view the various log files, real-time status and statistics, and perform system configuration and maintenance functions. It provided the functional equivalent of the "Wait for call screen" in v2.

A GUI user editor was also created using Borland Delphi and the VCL. Delphi was chosen for this project in anticipation of the Borland Kylix release and it represents my very first Pascal programming effort.

Synchronet v3 still has some reliance on some of the v2 utilities (most notably, SCFG.EXE), but moving as much code as possible to 32-bit (GUI where appropriate) is an increasing priority. Additionally, keeping as much of the code base as modular and portable as possible is a high priority. Reliance on the 16-bit assembler modules used in v2 has been eliminated.

The first official release of Synchronet v3 was v3.00b for Win32 (Windows 95-OSR2, 98, 98-SE, NT4, 2000, and Millennium Edition), released on June 25th, 2000. This release was simply Freeware, was not copyrighted, and did not include source code or any implied licensing (GNU GPL or otherwise). At this point, no proper revision control system had ever been utilized for Synchronet development.

Today (October 2000)

Synchronet for Unix is considered by myself and many others to be a potentially highly-desirable "product". From the onset of v3 design and development I have kept an eye towards GNU/Linux (and other free Unix-like OSes). The Unix/Linux community is increasingly biased towards free/open-source software, so I've been planning for some time to make Synchronet an open-source project, but was leaning towards waiting until after the Unix/Linux port was complete. In the mean-time, I've been getting increasingly frequent offers from Linux developers to assist in the porting effort. Since I had no proper revision control system in place, it would've been a logistical nightmare to co-develop Synchronet with anyone in a geographically undesirable location. Additionally, I had no copyright or licensing in place to protect the Synchronet source code from proprietary software developers.

This is not to suggest that only Unix/Linux sysops would potentially benefit from Synchronet becoming an open-source project. It's just that Unix users are traditionally more likely to be willing (and able) to mess with the source code, and hence, more likely to submit useful modifications to the project. In addition, development tools (i.e. C/C++ compiler, Make utility, CVS, etc) are usually included free with Unix-like operating systems, while they are not typically as readily available to Windows users.

So I created a revision control database (repository) using CVS and checked-in the v2.3 and v3 source code trees along with all the various menus, text files, and documents included in Synchronet distributions. I chose CVS as the revision control system because it is free software and is the tool of choice among most free/open-source software developers. I would've preferred to use one of the commercial revision control systems I've become accustomed to using in my professional development career, but their price and status as proprietary software would have potentially deterred valued open-source developers from contributing to the project.

I also copyrighted all of the source code (as Rob Swindell) and put the majority of the v3 source code files under the GNU General Public License to protect them from inclusion in proprietary projects. I put the XSDK and SMBLIB modules under the GNU Lesser General Public License, which allows them to be linked with proprietary projects.


Modifications

Presumably, you are reading this file because you want access to the source code. And you want access to the source code because you plan on making modifications (or maybe you just want to verify there aren't any "back doors"). In any case, if and when you make useful modifications to the source code, you are encouraged to submit those changes to mods@synchro.net for possible inclusion in a future Synchronet release. Frequent contributors may become official co-developers and be given direct read/write access to the CVS repository by me, the maintainer of the project.

Custom Modifications

If you are modifying the code for use on a single BBS and do not wish to give those modifications to anyone else, you have that right. To make synchronization of your version with the official Synchronet releases easier, it is highly recommended that you predefine a preprocessor symbol (e.g. MYMODS) and then wrap your modifications in a conditional compilation statement. Example:

#ifdef MYMODS
    bprintf("You are experiencing my custom modification.\r\n");
#endif

If you are changing existing lines of code, it is recommended that you include both the original and modified versions in your source and use conditional compilation statements to determine which version will be used. Example:

#ifdef MYMODS
	i = j/100;
#else /* Original code */
	i = j/50;
#endif	

This allows you to easily "undo" your modifications for testing purposes (by simply undefining MYMODS) as well as clearly marking, for future reference, which parts of the code were modified by you.

Coding Style

If you'd like to submit your modifications for possible inclusion in a future Synchronet release, it would be beneficial if the programming style was consistent with the style of the existing code base. Consistency of style helps improve readability and maintainability of the source code.

Prior to Synchronet v3, I used a form of "condensed" K&R style to get as much code in an 80x25 character display as possible while maintaining some degree of readability. 

Example (K&R style):

main()
{
    char line[MAXLINE];
    int found = 0;

    while (getline(line, MAXLINE) > 0)
	if (strindex(line, pattern) >= 0) {
	    printf("%s", line);
	    found++;
	}
    return found;
}

Example (Synchronet v2 style):

main()
{
    char line[MAXLINE];
    int  found=0;

while(getline(line,MAXLINE)>0)
    if(strindex(line,pattern)>=0) {
	printf("%s",line);
	found++; }
return(found);
}

As you've probably noticed, in the Synchronet v2 style, the body of the function is not indented and the closing curly brace is not on its own line. Additionally, unnecessary white-space characters have been removed from within the body of the expressions. While the above examples do not demonstrate the potential advantages of compressing white-space in a C coding style, you can imagine how the limitations of an 80 column display could make heavily nested expressions difficult without resulting to such measures.

In Synchronet v3, I've taken advantage of modern GUI text editors capable of displaying more than 80 characters on a line and have  "uncompressed" the style to a degree:

Example (Synchronet v3 style):

main()
{
    char line[MAXLINE];
    int  found=0;

    while(getline(line,MAXLINE)>0)
        if(strindex(line,pattern)>=0) {
	    printf("%s",line);
	    found++; 
	}
    return(found);
}

Now the body of the function is indented and the closing curly brace has been placed on its own line (as in the K&R style), but the unnecessary white-space characters remain compressed (eliminated from the body of the expressions). You may still find v2 style closing braces in some of the v3 source files, but indentation and all other style elements should be consistent with the v3 style shown above.

Style Guidelines

  1. Use the Synchronet v3 indentation, white-space, and brace style (as described above).
  2. Configure your text editor for 4 space tab stops and keep the physical tabs in the files (do not replace them with spaces).
  3. Use the Synchronet copyright comment block (including the PT/SC headers) when creating new source files.
  4. Do not extend lines beyond column 100.
  5. Add comments around or near any code you add or modify explaining the rationale behind the modification.
  6. Use descriptive symbol (function and variable) and pre-processor macro names.
  7. Use symbol and macro naming styles consistent with those already used in the project/source file you are modifying.
  8. Do not use unnecessary global variables (use class members or function parameters to pass values).
  9. Use return types and variable types consistent with the data to be stored or returned (e.g. use bool/BOOL for true/false type values).
  10. Do not embed important numeric constants in your code; use macros (e.g. #define SPECIAL_VALUE 128) or configurable variables instead.

Backwards Compatibility

There are two very important areas of compatibility that must be maintained when modifying the code:

  1. Data and configuration file compatibility with older Synchronet versions (v2+)
  2. Builds for other compilers and platforms

On the first point, you must take care not to alter structure definitions or file formats that will cause the resulting file not to operate in a compatible way with Synchronet v2. If you need additional data storage, try to use unused or reserved elements, bit-fields, or data fields in existing structure or file definitions (without changing the overall size of the structure or data record) or create auxiliary data files that contain the additional required data. All binary words and double-words are to be stored in little endian (Intel) byte-order and there are currently no provisions in the source code to account for byte-order translations on big endian systems.

On the second point, it is critical that you do not add system calls or system-dependant functionality in a non-portable fashion. If you are adding code that is only supported on a specific platform and when built with a specific compiler or run-time library, be sure to wrap that code in  conditional compilation statements that test for the appropriate pre-processor definitions. In addition, take care to add error conditions, warnings, or alternate behavior when the code is built on an unsupported platform or with an unsupported tool. For example:

#if defined(__MSDOS__)
	mswait(1);
#elif defined(__OS2__)
	DosSleep(1);
#elif defined (_WIN32)
	Sleep(1);
#else
	#error "No Sleep Function for target platform!"
#endif

Portability

To maintain as much compiler and platform compatibility as possible, do not unnecessarily restrict code portions to a specific Unix-like operating system (Linux for example) when the code will (or should) compile with most Unix-like operating systems. For example:

#if defined(__unix__)
	this_code_for_any_unix_variant;
#endif

#if defined(__linux__)
	this_code_only_for_linux;
#endif

Also, be sure to separate compiler dependancies from platform dependancies. For example:

#if defined(__GNUC__)
	this_code_only_for_gcc;
#else
	this_code_for_all_others;
#endif

Please use the following pre-processor symbols to determine the target platform:

SymbolTarget Platform

__unix__

Any Unix-like OS

__linux__

GNU/Linux (use sparingly)

__FreeBSD__

FreeBSD (use sparingly)

BSD

Any BSD-based Unix

_WIN32

Win32-based OS

__OS2__

OS/2

__MSDOS__

MS-DOS

__DOS4G__

Rational 32-bit DOS extender

__FLAT__

Other 32-bit DOS extender

Please use the following pre-processor symbols to determine the compiler:

SymbolCompiler

__GNUC__

GNU C/C++ Compiler

__BORLANDC__

Borland C++ or C++ Builder Compiler

__WATCOM__

Watcom C++

_MSC_VER

Microsoft Visual C++

Little-endian/80386-class target CPUs are assumed, so no testing for CPU-type is required at this time.

Submissions

When you've created a modification that you think other Synchronet sysops or users may find useful, you are encouraged to submit this modification to mods@synchro.net. Modifications should be submitted in the Unix diff format. Currently, I am the sole judge of which submissions will be merged into the code base and which ones will not. If I determine that a submission should not be merged into the code base for any reason, I will make my best effort to explain to the submitting developer the reasons why and offer advice on how to remedy the situation, if at all possible.

Copyright 2009 Rob Swindell
$Id: source.html,v 1.18 2009/01/31 21:27:29 rswindell Exp $