Local Doors

Local Doors

ENiGMA½ has many ways to add doors to your system. In addition to the many built in door server modules, local doors are of course also supported using the ! The abracadabra module!

:information_source: See also Let’s add a DOS door to Enigma½ BBS by Robbie Whiting for a great writeup on adding doors!

The abracadabra Module

The abracadabra module provides a generic and flexible solution for many door types. Through this module you can execute native processes & scripts directly, and perform I/O through standard I/O (stdio) or a temporary TCP server.


The abracadabra config block can contain the following members:

Item Required Description
name :+1: Used as a key for tracking number of clients using a particular door.
dropFileType :-1: Specifies the type of dropfile to generate (See Dropfile Types below). Can be omitted or set to none.
cmd :+1: Path to executable to launch.
args :-1: Array of argument(s) to pass to cmd. See Argument Variables below for information on variables that can be utilized here.
preCmd :-1: Path to a pre-command executable or script to launch. Executes before cmd.
preCmdArgs :-1: Array of argument(s) to pass to preCmd. See Argument Variables below for information on variables that can be utilized here.
cwd :-1: Sets the Current Working Directory (CWD) for cmd. Defaults to the directory of cmd.
env :-1: Sets the environment. Supplied in the form of an map: { SOME_VAR: "value" }
nodeMax :-1: Max number of nodes that can access this door at once. Uses name as a tracking key.
tooManyArt :-1: Art spec to display if too many instances are already in use.
io :-1: How to process input/output (I/O). Can be stdio or socket. When using stdio, I/O is handled via standard stdin/stdout. When using socket a temporary socket server is spawned that can be connected back to. The server listens on localhost on {srvPort} (See Argument Variables below for more information). Default value is stdio.
encoding :-1: Sets the door’s encoding. Defaults to cp437. Linux binaries often produce utf8.

Dropfile Types

Dropfile types specified by dropFileType:

Value Description
none No door file is needed

Argument Variables

The following variables may be used in args and preCmdArgs entries:

Variable Description Example
{node} Current node number. 1
{dropFile} Dropfile filename only. DOOR.SYS
{dropFilePath} Full path to generated dropfile. The system places dropfiles in the path set by paths.dropFiles in config.hjson. C:\enigma-bbs\drop\node1\DOOR.SYS
{dropFileDir} Full path to directory containing the generated dropfile. /home/enigma-bbs/drop/node1/
{userAreaDir} Full path to a directory safe for user-specific save files/etc. /home/enigma-bbs/drop/node1/NuSkooler/lord/
{userId} Current user ID. 420
{userName} Sanitized username. Safe for filenames, etc. If the full username is sanitized away, this will resolve to something like “user_1234”. izard
{userNameRaw} Raw username. May not be safe for filenames! \/\/izard
{srvPort} Temporary server port when io is set to socket. 1234
{cwd} Current Working Directory. /home/enigma-bbs/doors/foo/
{termHeight} Current client term height 25
{termWidth} Current client term width 80

Example args member using some variables described above:

args: [
    "-D", "{dropFilePath}",
    "-N", "{node}"
    "-U", "{userId}"

DOSEMU with abracadabra

DOSEMU can provide a good solution for running legacy DOS doors when running on Linux systems. For this, we will create a virtual serial port (COM1) that communicates via stdio.

As an example, here are the steps for setting up Pimp Wars:

First, create a dosemu.conf file with the following contents:

$_cpu = "80486"
$_cpu_emu = "vm86"
$_external_char_set = "utf8"
$_internal_char_set = "cp437"
$_term_updfreq = (8)
$_layout = "us"
$_rawkeyboard = (0)
$_com1 = "virtual"

The line $_com1 = "virtual" tells DOSEMU to use stdio as a virtual serial port on COM1.

Next, we create a virtual X drive for Pimp Wars to live such as /enigma-bbs/DOS/X/PW and map it with a custom AUTOEXEC.BAT file within DOSEMU:

@echo off
path d:\bin;d:\gnu;d:\dosemu
set TEMP=c:\tmp
prompt $P$G
REM http://www.pcmicro.com/bnu/
C:\BNU\BNU.COM /L0:57600,8N1 /F
lredir.com x: linux\fs\enigma-bbs\DOS\X
unix -e

Note that we also have the BNU FOSSIL driver installed at C:\BNU\\. Another option would be to install this to X: somewhere as well.

Finally, let’s create a menu.hjson entry to launch the game:

doorPimpWars: {
    desc: Playing PimpWars
    module: abracadabra
    config: {
        name: PimpWars
        dropFileType: DORINFO
        cmd: /usr/bin/dosemu
        args: [
            "X:\\PW\\START.BAT {dropFile} {node}"
        nodeMax: 1
        tooManyArt: DOORMANY
        io: stdio

Shared Socket Descriptors

Due to Node.js limitations, ENiGMA½ does not directly support DOOR32.SYS style socket descriptor sharing (other DOOR32.SYS features are fully supported). However, a separate binary called bivrost! can be used. bivrost! is available for Windows and Linux x86/i686 and x86_64/AMD64. Other platforms where Rust builds are likely to work as well.

Example configuration

Below is an example menu.hjson entry using bivrost! to launch a door:

doorWithBivrost: {
    desc: Bivrost Example
    module: abracadabra
    config: {
        name: BivrostExample
        dropFileType: DOOR32
        cmd: "C:\\enigma-bbs\\utils\\bivrost.exe"
        args: [
            "--port", "{srvPort}",          //  bivrost! will connect this port on localhost
            "--dropfile", "{dropFilePath}", //  ...and read this DOOR32.SYS produced by ENiGMA½
            "--out", "C:\\doors\\jezebel",  //  ...and produce a NEW DOOR32.SYS here.

            //  Note that the final <target> params bivrost! will use to
            //  launch the door are grouped here. The {fd} variable could
            //  also be supplied here if needed.
            "C:\\door\\door.exe C:\\door\\door32.sys"
        nodeMax: 1
        tooManyArt: DOORMANY
        io: socket

Please see the bivrost! documentation for more information.

Phenom Productions Releases

Pre-built binaries of bivrost! have been released under Phenom Productions and can be found on various boards.

Alternative Workarounds

Alternative workarounds include Telnet Bridge module to hook up Telnet-accessible (including local) door servers – It may also be possible bridge via NET2BBS.

QEMU with abracadabra

QEMU provides a robust, cross platform solution for launching doors under many platforms (likely anywhere Node.js is supported and ENiGMA½ can run). Note however that there is an important and major caveat: Multiple instances of a particular door/OS image should not be run at once! Being more flexible means being a bit more complex. Let’s look at an example for running L.O.R.D. under a UNIX like system such as Linux or FreeBSD.

Basically we’ll be creating a bootstrap shell script that generates a temporary node specific GO.BAT to launch our door. This will be called from AUTOEXEC.BAT within our QEMU FreeDOS partition.

Step 1: Create a FreeDOS image

FreeDOS is a free mostly MS-DOS compatible DOS package that works well for running 16bit doors. Follow the QEMU/FreeDOS guide for creating an freedos_c.img. This will contain FreeDOS itself and installed BBS doors.

After this is complete, copy LORD to C:\DOORS\LORD within FreeDOS. An easy way to tranfer files from host to DOS is to use QEMU’s vfat as a drive. For example:

qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -hdb fat:/path/to/downloads

With the above you can now copy files from D: to C: within FreeDOS and add the following to it’s autoexec.bat:


Step 2: Create a bootstrap script

Our bootstrap script will prepare GO.BAT and launch FreeDOS. Below is an example:



mkdir -p /home/enigma/dos/go/node$NODE

cat > /home/enigma/dos/go/node$NODE/GO.BAT <<EOF

unix2dos /home/enigma/dos/go/node$NODE/GO.BAT

qemu-system-i386 -localtime /home/enigma/dos/images/freedos_c.img -chardev socket,port=$SRVPORT,nowait,host=localhost,id=s0 -device isa-serial,chardev=s0 -hdb fat:/home/enigma/xibalba/dropfiles/node$NODE -hdc fat:/home/enigma/dos/go/node$NODE -nographic

Note the qemu-system-i386 line. We’re telling QEMU to launch and use localtime for the clock, create a character device that connects to our temporary server port on localhost and map that to a serial device. The -hdb entry will represent the D: drive where our dropfile is generated, while -hdc is the path that GO.BAT is generated in (E:\GO.BAT). Finally we specify -nographic to run headless.

For doors that do not require a FOSSIL driver, it is recommended to not load or use one unless you are having issues.

Step 3: Create a menu entry

Finally we can create a menu.hjson entry using the abracadabra module:

doorLORD: {
    desc: Playing L.O.R.D.
    module: abracadabra
    config: {
        name: LORD
        dropFileType: DOOR
        cmd: /home/enigma/dos/scripts/lord.sh
        args: [
        nodeMax: 1
        tooManyArt: DOORMANY
        io: socket

See Also

Additional Resources

DOS Emulation

Door Downloads & Support Sites


  • http://bbsfiles.com/
  • http://bbstorrents.bbses.info/


  • http://lord.lordlegacy.com/