Swindell</a>, 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.
<H3>Version 1</H3>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.<BR><BR>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.
<H3>Version 2</H3>Synchronet v2 incorporated a programmable command and menu
structure (<i>PCMS</i>), 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 <I>Baja</I> was included that utilized a high-level BASIC-like
programming language.<BR><BR>Synchronet v2 also incorporated a new
database-style message base format called <I>SMB</I> (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.
<p>A binary configuration file format (.cnf) was introduced in v2 to speed up
the loading of configuration files and improve extensibility.<BR><BR>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.<BR><BR>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 <ahref="http://www.fsf.org/philosophy/categories.html#PublicDomainSoftware">Public
Domain</a> 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.</p>
<H3>Version 3</H3>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 <ahref="http://msdn.microsoft.com/visualc/"> Microsoft Visual
C++</a>.<BR><BR>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++.<BR><BR>A GUI front-end called the
<I>Synchronet Control Panel</I> was created using <ahref="http://www.borland.com/bcppbuilder/"> Borland C++ Builder</a> 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.<BR><BR>A GUI user editor was also created using
<ahref="http://www.borland.com/delphi/"> Borland
Delphi</a> and the VCL. Delphi was chosen for this project in anticipation of the
Borland <Ahref="http://www.borland.com/kylix/">Kylix</A> release and it
represents my very first Pascal programming effort.<BR><BR>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.<BR><BR>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.
<H3>Today (October 2000)</H3>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 <ahref="http://www.gnu.org/gnu/linux-and-gnu.html">GNU</a>/<ahref="http://www.linux.org/">Linux</a> (and other free Unix-like OSes). The
Unix/Linux community is increasingly biased towards <ahref="http://www.fsf.org/philosophy/free-sw.html">free</a>/<ahref="http://www.opensource.org/osd.html">open-source</a> 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 <ahref="http://www.fsf.org/philosophy/categories.html#ProprietarySoftware"> proprietary
software</a> developers.
<p>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.<BR><BR>So I created a revision control database (repository) using
<Ahref="http://www.cvshome.org/">CVS</A> 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.<BR><BR>I also <ahref="copyright.html"> copyrighted</a> all of the source code (as Rob Swindell) and put the majority of the v3 source code files under the
<Ahref="http://www.fsf.org/copyleft/gpl.html">GNU General Public License</A> to
protect them from inclusion in proprietary projects. I put the XSDK and SMBLIB
modules under the <Ahref="http://www.fsf.org/copyleft/lesser.html">GNU Lesser
General Public License</A>, which allows them to be linked with proprietary
projects.</p>
<hr>
<h2>Modifications</h2>
<p>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 <ahref="mailto:mods@synchro.net">mods@synchro.net</a>
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 <ahref="http://synchro.net/docs/author.html">me</a>, the maintainer of the project.</p>
<h3>Custom Modifications</h3>
<p>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:</p>
<pre>#ifdef MYMODS
bprintf("You are experiencing my custom modification.\r\n");
#endif</pre>
<p>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:</p>
<pre>#ifdef MYMODS
i = j/100;
#else /* Original code */
i = j/50;
#endif </pre>
<p>This allows you to easily <i>"</i>undo<i>"</i> 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.</p>
<h3>Coding Style</h3>
<p>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.</p>
<p>Prior to Synchronet v3, I used a form of "condensed"<ahref="http://cm.bell-labs.com/cm/cs/cbook/index.html">K&R</a>
style to get as much code in an 80x25 character display as possible while
maintaining some degree of readability. </p>
<pre><b>Example (K&R style):</b>
main()
{
char line[MAXLINE];
int found = 0;
while (getline(line, MAXLINE) > 0)
if (strindex(line, pattern) >= 0) {
printf("%s", line);
found++;
}
return found;
}
<b>Example (Synchronet v2 style):</b>
main()
{
char line[MAXLINE];
int found=0;
while(getline(line,MAXLINE)>0)
if(strindex(line,pattern)>=0) {
printf("%s",line);
found++; }
return(found);
}
</pre>
<p>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.</p>
<p>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:</p>
<pre><b>Example (Synchronet v3 style):</b>
main()
{
char line[MAXLINE];
int found=0;
while(getline(line,MAXLINE)>0)
if(strindex(line,pattern)>=0) {
printf("%s",line);
found++;
}
return(found);
}
</pre>
<p>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.</p>
<h4>Style Guidelines</h4>
<ol>
<li>Use the Synchronet v3 indentation, white-space, and brace style (as
described above).</li>
<li>Configure your text editor for 4 space tab stops and keep the physical
tabs in the files (do not replace them with spaces).</li>
<li>Use the Synchronet copyright comment block (including the
<ahref="http://synchro.net/ptsc_hdr.html">PT/SC
headers</a>) when creating new source files.</li>
<li>Do not extend lines beyond column 100.</li>
<li>Add comments around or near any code you add or modify explaining the
rationale behind the modification.</li>
<li>Use descriptive symbol (function and variable) and pre-processor macro names.</li>
<li>Use symbol and macro naming styles consistent with those already used in
the project/source file you are modifying.</li>
<li>Do not use unnecessary global variables (use class members or function
parameters to pass values).</li>
<li>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).</li>
<li>Do not embed important numeric constants in your code; use macros (e.g.
#define SPECIAL_VALUE 128) or configurable variables instead.</li>
</ol>
<h3>Backwards Compatibility</h3>
<p>There are two very important areas of compatibility that must be maintained
when modifying the code:</p>
<ol>
<li>Data and configuration file compatibility with older Synchronet versions
(v2+)</li>
<li>Builds for other compilers and platforms</li>
</ol>
<p>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.</p>
<p>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:</p>
<pre>#if defined(__MSDOS__)
mswait(1);
#elif defined(__OS2__)
DosSleep(1);
#elif defined (_WIN32)
Sleep(1);
#else
#error "No Sleep Function for target platform!"
#endif</pre>
<h3>Portability</h3>
<p>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:</p>
<pre>#if defined(__unix__)
this_code_for_any_unix_variant;
#endif
#if defined(__linux__)
this_code_only_for_linux;
#endif</pre>
<p>Also, be sure to separate <b>compiler</b> dependancies from <b>platform</b> dependancies. For example:</P>
<pre>#if defined(__GNUC__)
this_code_only_for_gcc;
#else
this_code_for_all_others;
#endif</pre>
<p><b>Please use the following pre-processor symbols to determine the target platform:</b></p>
<table>
<COLGROUPalign=center>
<COLGROUPalign=left>
<thwidth="150">Symbol<th>Target Platform
<tr><td>
<palign="center"><b><code>__unix__</code></b><td>Any Unix-like OS