Skip to content

Scripts & Native Binaries

The abracadabra module provides a generic solution for launching any local process as a door: native terminal applications, shell scripts, Python scripts, and more. Any process that communicates over stdio works. I/O is bridged through standard I/O (stdio) or a temporary TCP socket server.


The abracadabra config block supports the following fields:

ItemRequiredDescription
nameYesUsed as a key for tracking the number of clients using this door.
dropFileTypeNoType of drop file to generate. See Drop File Types. Can be omitted or none.
cmdYesPath to the executable to launch.
argsNoArray of arguments to pass to cmd. See Argument Variables below.
preCmdNoPath to a pre-command executable or script. Executes before cmd.
preCmdArgsNoArguments to pass to preCmd. See Argument Variables below.
cwdNoWorking directory for cmd. Defaults to the directory containing cmd.
envNoEnvironment variables as a map: { SOME_VAR: "value" }
nodeMaxNoMax concurrent sessions for this door. Uses name as the tracking key.
tooManyArtNoArt spec to display when nodeMax is exceeded.
ioNoI/O mode: stdio (default) or socket. When socket, ENiGMA½ spawns a temporary TCP server on {srvPort} that the door process connects back to.
commTypeNoWhat the drop file tells the door it is talking to: local, serial, or socket. Defaults to socket when io: socket, otherwise local. See Comm Type below.
encodingNoThe door process’s text encoding. Defaults to cp437. Linux-native binaries often use utf8.

io says how ENiGMA½ talks to the process it spawns; commType says how the door talks to the caller. They are the same thing only when the process ENiGMA½ spawns is the door, which is why the default is derived from io:

commTypeReported asUse when
local (default)DOOR32.SYS comm type 0, DOOR.SYS COM0:, DORINFO 0The door reads stdin and writes stdout. This covers io: stdio, which is nearly every native or scripted door.
serialDOOR32.SYS comm type 1, DOOR.SYS COM1:, DORINFO COM1An emulator sits between ENiGMA½ and the door and presents it a COM port — QEMU bridging {srvPort} onto isa-serial, for example.
socketDOOR32.SYS comm type 2, DOOR.SYS COM1:, DORINFO COM1Descriptor sharing by way of bivrost!.

Doors that ignore these fields entirely — most DOS-era games under an emulator — are unaffected by any of this.

The following variables can be used in args and preCmdArgs:

VariableDescriptionExample
{node}Current node number1
{dropFile}Drop file filename onlyDOOR.SYS
{dropFilePath}Full path to the generated drop file/home/enigma/drop/node1/DOOR.SYS
{dropFileDir}Full path to the drop file directory/home/enigma/drop/node1/
{userAreaDir}User-specific save directory/home/enigma/drop/node1/NuSkooler/lord/
{userId}Current user ID42
{userName}Sanitized username (safe for filenames)nuskooler
{userNameRaw}Raw username (may not be filename-safe)\/\/izard
{srvPort}Temporary TCP server port (when io: socket)1234
{cwd}Working directory/home/enigma/doors/foo/
{termHeight}Terminal height25
{termWidth}Terminal width80
args: [
"-D", "{dropFilePath}",
"-N", "{node}",
"-U", "{userId}"
]

A simple wrapper script that launches a native binary:

doorMyGame: {
desc: My Door Game
module: abracadabra
config: {
name: MyGame
dropFileType: DOOR
cmd: /home/enigma/doors/mygame/launch.sh
args: [ "{node}", "{dropFilePath}" ]
nodeMax: 4
tooManyArt: DOORMANY
io: stdio
}
}
doorPythonGame: {
desc: Python Door
module: abracadabra
config: {
name: PythonGame
dropFileType: DORINFO
cmd: /usr/bin/python3
args: [ "/home/enigma/doors/pydoor/main.py", "{node}", "{dropFilePath}" ]
encoding: utf8
nodeMax: 8
io: stdio
}
}

Some doors require a socket connection rather than stdio. ENiGMA½ starts a temporary TCP server and passes the port to your script:

doorSocketGame: {
desc: Socket Door
module: abracadabra
config: {
name: SocketGame
dropFileType: DOOR
cmd: /home/enigma/doors/socketgame/launch.sh
args: [ "{node}", "{dropFile}", "{srvPort}" ]
nodeMax: 1
io: socket
}
}

Due to Node.js limitations, ENiGMA½ does not directly support DOOR32.SYS-style socket descriptor sharing. However, bivrost! bridges this gap. bivrost! is available for Windows and Linux x86/x86_64 (and buildable from Rust on other platforms).

doorWithBivrost: {
desc: Bivrost Example
module: abracadabra
config: {
name: BivrostExample
dropFileType: DOOR32
cmd: /home/enigma/utils/bivrost
args: [
"--port", "{srvPort}",
"--dropfile", "{dropFilePath}",
"--out", "/home/enigma/doors/jezebel",
"/home/enigma/doors/jezebel/door.exe /home/enigma/doors/jezebel/door32.sys"
]
nodeMax: 1
tooManyArt: DOORMANY
io: socket
}
}

See the bivrost! documentation for details. Pre-built binaries are also available via Phenom Productions on various boards.

Alternative workarounds: Telnet Bridge, or NET2BBS.