Ray Rocker describes how Linux was used to facilitate the development of one popular bulletin board system.
It all started as a port of Pirates Bulletin Board System (PBBS) version 1.6 to ESIX/System V. Pirates BBS was written by Ed Luke at Mississippi State University in the summer of 1989, and earned its place in Internet legend through the now-defunct Mars Hotel BBS. Two friends from high school, then students at the University of Southern Mississippi (which is my alma mater as well), generated enough interest in an Internet BBS to get space on a machine in the Computer Science Department. Together we ported Pirates, which was strictly BSD code at the time, to ESIX. The Eagle's Nest BBS was born April 14, 1992.
It wasn't easy or pretty, as any early user of the Eagle's Nest will tell you, but it eventually worked. Along the way I added a lot of features from other BBSes that Pirates 1.6 didn't have, brought in things from later Pirates revisions, and even had a few original ideas. It wasn't meant to be anything but a simple PBBS port, but people started taking an interest in our “enhanced Pirates”, so we gave it our own name—Eagles BBS—in honor of the Eagle's Nest, and of our school's mascot from which that name is derived.
We released Eagles BBS 1.0 in August 1992, and I've updated it four times since then. My partners have since dropped out of the project. Thanks to a lot of gracious folks across the Net, I received ports of it to quite a few other operating systems. None of these received more than casual attention, until we discovered Linux. Before I get into that, I should give a little technical information about the software itself.
Eagles BBS is a self-contained, multifunction bulletin board package that is accessed by logging in to a special account, either through telnet, dial-in, or a terminal. Three executables comprise the EBBS system: bbsrf, bbs, and bbs.chatd.
bbsrf is a special setuid root login shell. A user “bbs” is placed in /etc/passwd with bbsrf as its login shell. bbsrf optionally erases the login from /etc/utmp, making it invisible to the “finger” and “who” commands. It then does a chroot to the bbs home directory, does a setuid back to “bbs”, and execs the bbs program.
The chroot is done for security purposes. With it, anyone who might break out of the bbs program into a shell will only have access to the bbs home directory, not the rest of the host system. Because of the chroot, the BBS is completely self-contained underneath the bbs account's home directory, except for the record in /etc/passwd. All files needed by the BBS at run time are copied under ~bbs; for example the /etc/termcap file is copied to ~bbs/etc, the shared C library is copied to ~bbs/lib, and so on. This is a major portability headache. More on this later.
The bbs program does most of the work. First it prompts the user for a userid and password, which are validated by a lookup in the ~bbs/.PASSWDS file. This is much like how the standard system login program works, except ~bbs/.PASSWDS is a binary file. Once logged in, the user navigates through a series of menus accessing the features of the BBS.
The menu system is full-screen, and uses the terminal capability database (~bbs/etc/termcap) for efficient manipulation of the terminal. EBBS does not use
libcurses but a stripped-down, simplified curses look-alike dating from the Pirates days. Because the user is usually coming in through telnet, the BBS cannot always tell what terminal type the user has; there is a menu option for the user to specify this, however. The menu system is hierarchical; from the top level Main Menu one can access submenus, such as the Talk Menu, Xyz Menu, File Menu, and Mail Menu. The functions available from the menus can be roughly divided into seven categories, which I'll briefly describe:
Sending/reading mail: Mail may be sent to other users of the BBS. In addition, a facility for forwarding BBS mail (and posts) to a remote Internet mailbox is included. Receiving mail from Internet is not supported; since users do not have real accounts insofar as the operating system is concerned, this would be a little tricky.
Posting/reading messages: Up to 80 boards may be set up by the operator on which users may post public messages. The operator may restrict boards to certain groups of users with permission masks. The BBS boards do not interface with outside message services like Usenet or Fido.
File upload/download: The BBS has a facility for file uploading and downloading with serial-line protocols like Zmodem and Kermit, allowing files to be transferred straight from home computers to the BBS. Using these protocols across a slow Internet link usually does not work very well, however. Most sites also offer ftp access to their file bases since it's more suited to long-distance network transfers.
Talk: An emulation of the Unix “talk” utility is available, allowing one-on-one talk sessions with other BBS users. The talk facility does not allow connections to remote systems like Unix talk does.
Chat: A local chat system is built into the BBS. Up to four separate rooms may be configured. A chat daemon (bbs.chatd, the third program making up the BBS) process is spawned when the first user enters a room, and serves to relay messages to all users in the room. A number of IRC-like features have been hacked into the chat facility, like private messages, actions, and commands to show who's logged on.
User utilities: For setting things like your nickname (not login userid), terminal type, and address for mail/post forwarding. These are on the Xyz Menu.
Administrator utilities: These are only accessible by privileged users. This includes things like account and board creation and removal, setting permission flags on accounts, mail cleans, and welcome screen editing.
As you can see, EBBS, like its Pirates predecessor, stands on its own for the most part—hooks to other services are few and far between. Much of this is necessary because of the chroot. Some sites have integrated Internet Relay Chat clients into their BBSes, but even then the built-in chat system is quite popular. EBBS seems to be popular among computing neophytes because of the simple menu system and builtin editor. On the same token, power users sometimes get frustrated by its limitations.
The isolated nature of a PBBS or EBBS system encourages some interesting relationships among its regular users, especially after a system has been around for a while. Some of the things that go on would surprise even the most ardent soap opera fan! I'll leave that topic open for another article, though.
Back at the Eagle's Nest, in late 1993, the decision was made to switch its host machine (a 1990 vintage 25 MHz Cheetah Gold 486 PC) from ESIX to Linux, because Linux simply had more to offer. So, I was called upon to do another port. This was the kick in the pants I needed to finally buy a new hard disk and put a real operating system on my own PC. Armed with the 0.99.12 kernel and SLS 1.03 distribution, I tackled the task before me, and found it to be quite easy to go from my System V Release 4 ported code to Linux. Here is a list of the issues I ran up against, which should make an initial “gotcha” list for anyone porting a network application to Linux. You'll notice many of the same things mentioned in Michael K. Johnson's excellent “Porting To Linux” article in Linux Journal, Vol. 1 Edition 1.
Signal handling. BSD, and SVR4 via the signal(2) call, have restartable signals. In Linux you must explicitly ask for BSD signal handling or use the somewhat different sigaction interface. [Editor's Note: See the last section of Linux Programming Hints on page 33.] For me, it was just easier to change the code to assume signal handlers need to be reset.
select(2) and the timeout parameter. Like so many apps, EBBS assumed that select(2) leaves the contents of the timeval struct alone. You've got to reset the timeout if you're calling select in a loop.
the FD_SET macro and its kin live in <sys/time.h>. Not that this should bog down anyone's porting, but it's worth mentioning since most Unixes put these macros in <sys/types.h> or <sys/select.h>.
Terminal I/O. A lot of BSD source relies on gtty(2) and stty(2) and obscure ioctl flags. When I realized they weren't in the base C library, I changed it all over to termio. Probably a good idea anyway, even if I did have to put the BSD source from PBBS back for the NeXT port.
The Eagle's Nest went online with Linux in October 1993 and we've been faithfully keeping step with the latest revisions ever since. Compared to our experience running on ESIX, Linux has been both good and bad.
The good: the ext2 filesystem and kernel proper. Some BBS operations requiring lots of file access, notably the scan for new messages and the “visit” function (to mark all messages as read) were excruciatingly slow under ESIX, but lightning fast under Linux - with the exact same hardware, of course. A new message scan that might take ten seconds before will get done in one or two now. All the buffering Linux does really made a difference for us.
The bad: the TCP/IP networking. The Eagle's Nest sometimes gets a couple of hundred logins a day, and it shares bandwidth with anonymous ftp service and a WWW server. Hence, the kernel gets battered pretty badly network-wise. Through the releases from 0.99 pl13 to the present 1.1.8, we've seen lots of strange things like dying inetds, frequent reboots to revive the network, and connections hanging both on connect and close. Luckily, it keeps getting better, and as of 1.1.8 the only annoying problem left is occasional hanging at connect time, and only when it has to deal with long delays or lost packets. Unfortunately such conditions are not at all uncommon on Internet.
That aside, we at the Eagle's Nest are pretty happy with Linux, and I now use it almost exclusively myself. I have another operating system on my disk, but it's just a faint memory. Its name starts with D I think. Doom! Yeah, that's it!
As I mentioned already, no port of EBBS has generated anywhere close to the interest the Linux port has received. The worldwide scope of Linux is especially evident. Interest in EBBS for Linux has sprouted on every continent except Antarctica, all with very little promotion on my part! See sidebar for a partial list of Linux EBBS systems available on Internet.
Not too long after the Linux port was done, I decided that the current code was getting too messy for any more nontrivial additions or enhancements. Here are a few of the things holding advancement of the present incarnation of EBBS back:
The chroot. It's a security feature but also a portability nightmare. Every flavor of Unix requires a different set of system files under ~bbs to allow the system to work, and indeed some haven't been figured out yet. It also makes the install script a big mess. Consider shared libraries. On some systems they're in /lib, some in /usr/lib, some in /usr/shlib. On some systems all you need is libc.so.*, on others (like Solaris) you need a half dozen or more shared libraries. It's a huge mess. In the latest version (2.2) I have added a compile time option to turn off the chroot if desired. To get rid of it safely would be even better.
Because of the chroot, it's nearly impossible to add hooks to the outside system into the BBS. Many BBS operators have expressed the need for two-way Internet mail and Usenet, and with the chroot this is impractical if not impossible to do with EBBS. A few hooks outside the BBS proper have been successfully done, for example the outgoing mail/post forwarding, and IRC, 4m, and Gopher clients.
Keeping track of read posts, and the .DIR files. The Pirates BBS way of keeping track of which user has read which post involves each post having a record in a .DIR file associated with each board. These records have things like the owner and title of the post, and one byte for each possible account on the system. When the user reads the post, their byte in the post's record in the .DIR is marked as such. The race conditions involved with simultaneous updates of these files are rampant and tricky to guard against. Also, since each .DIR record must be a known size, the numbers of BBS accounts is fixed at compile time, not a desirable feature.
So last November, I embarked on a complete rewrite, with the goal of keeping all or most of the existing EBBS features but a completely new foundation. Five months later I'm almost done with the first cut. The fact that this is a spare-time venture, plus a couple of rewrites from scratch when I got frustrated, have made it slow going.
The development of the new version is being done 100% on Linux, and I'm making a point to stay as POSIX-compliant as possible so ports can be done without too much hassle. These are some of the features under development:
No more chroot. See above. I am going to get rid of the Shell Escape menu function for this reason, as it's risky, and disallow the system(3) C library call anywhere in my code, since it spawns a shell as well. In short, I'm trying to make it impossible to break out.
Run time configuration, to allow binary distribution (the Linux way!). Right now, all EBBS optional features and access permissions must be configured at compile time. A set of initialization files that the BBS reads at run time will be a major improvement. In particular I am trying to make configurable anything that may vary between distributions, such as the mail program to use for forwarding. In addition, I plan to make all files used by the BBS ASCII rather than binary, so they may be easily patched with an editor if something goes awry. This includes the passwds file and boards file.
No more .DIR files. I will be storing the bits showing which posts/mail a user has read in a per-user config file, eliminating the need for the .DIR files. And, it eliminates the restriction on the number of accounts.
Separation of the user interface and BBS core, only interacting via a carefully defined API set. This will allow anyone who wants to build their own user interface, for example an X-Windows GUI, to do so easily, with only knowledge of the APIs for accessing the BBS core functions. I plan to write a network API set which will allow clients to connect to remote BBS servers via a yet-undefined TCP/IP-based protocol. This way, things like menu movements and editing may be done on the client, with none of the lag that has become all too common on the increasingly crowded “information highway”.
And a few more features which aren't present now: group mailing, replies by mail to post authors, per-board managers, added chat features like private rooms, and more.
At the time of this writing, this rewrite is very nearly ready for initial testing, with only a few features yet to be added. If all goes well, something will be publicly available by the time you read this. I'm tentatively calling it Eagles BBS 3.0 and plan to distribute under the GNU copyleft or something similar; everything is subject to change at this point of course.
I hope this work culminates in a useful addition to the already-impressive array of software for Linux. The demand for Linux bulletin board software is there, it seems. It's been an enlightening and educational experience for me, however time consuming. The development environment offered by gcc, gdb, and the myriad of other tools is as good as any, I think. At first the documentation left a bit to be desired but that has improved markedly. I'd like to encourage other programmers to do the same with their favorite spare-time projects-the Linux community is very responsive and helpful with everything from suggestions to development to distribution. I'm proud to be involved with it.