enigma-bbs/docs/_docs/modding/local-doors.md

252 lines
11 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
layout: page
title: Local Doors
---
## Local Doors
ENiGMA½ has many ways to add doors to your system. In addition to the [many built in door server modules](door-servers.md), local doors are of course also supported using the ! The `abracadabra` module!
> :information_source: See also [Lets add a DOS door to Enigma½ BBS](https://medium.com/retro-future/lets-add-a-dos-game-to-enigma-1-2-41f257deaa3c) 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.
### Configuration
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](#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](#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](#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](#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 |
| `DOOR` | [DOOR.SYS](https://web.archive.org/web/20160325192739/http://goldfndr.home.mindspring.com/dropfile/doorsys.htm)
| `DOOR32` | [DOOR32.SYS](https://raw.githubusercontent.com/NuSkooler/ansi-bbs/master/docs/dropfile_formats/door32_sys.txt)
| `DORINFO` | [DORINFOx.DEF](https://web.archive.org/web/20160321190038/http://goldfndr.home.mindspring.com/dropfile/dorinfo.htm)
#### 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](https://www.npmjs.com/package/sanitize-filename) 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:
```hjson
args: [
"-D", "{dropFilePath}",
"-N", "{node}"
"-U", "{userId}"
]
```
### DOSEMU with abracadabra
[DOSEMU](http://www.dosemu.org/) 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](http://www.pcmicro.com/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:
```hjson
doorPimpWars: {
desc: Playing PimpWars
module: abracadabra
config: {
name: PimpWars
dropFileType: DORINFO
cmd: /usr/bin/dosemu
args: [
"-quiet",
"-f",
"/path/to/dosemu.conf",
"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!](https://github.com/NuSkooler/bivrost) can be used. bivrost! is available for Windows and Linux x86/i686 and x86_64/AMD64. Other platforms where [Rust](https://www.rust-lang.org/) builds are likely to work as well.
#### Example configuration
Below is an example `menu.hjson` entry using bivrost! to launch a door:
```hjson
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!](https://github.com/NuSkooler/bivrost) documentation for more information.
#### Phenom Productions Releases
Pre-built binaries of bivrost! have been released under [Phenom Productions](https://www.phenomprod.com/) and can be found on various boards.
#### Alternative Workarounds
Alternative workarounds include [Telnet Bridge module](telnet-bridge.md) to hook up Telnet-accessible (including local) door servers -- It may also be possible bridge via [NET2BBS](http://pcmicro.com/netfoss/guide/net2bbs.html).
### QEMU with abracadabra
[QEMU](http://wiki.qemu.org/Main_Page) 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](http://www.freedos.org/) is a free mostly MS-DOS compatible DOS package that works well for running 16bit doors. Follow the [QEMU/FreeDOS](https://en.wikibooks.org/wiki/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:
```bash
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`:
```bat
CALL E:\GO.BAT
```
#### Step 2: Create a bootstrap script
Our bootstrap script will prepare `GO.BAT` and launch FreeDOS. Below is an example:
```bash
#!/bin/bash
NODE=$1
DROPFILE=D:\\$2
SRVPORT=$3
mkdir -p /home/enigma/dos/go/node$NODE
cat > /home/enigma/dos/go/node$NODE/GO.BAT <<EOF
C:
CD \FOSSIL\BNU
BNU.COM
CD \DOORS\LORD
COPY /Y $DROPFILE
CALL START.BAT $NODE
FDAPM POWEROFF
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:
```hjson
doorLORD: {
desc: Playing L.O.R.D.
module: abracadabra
config: {
name: LORD
dropFileType: DOOR
cmd: /home/enigma/dos/scripts/lord.sh
args: [
"{node}",
"{dropFile}",
"{srvPort}",
],
nodeMax: 1
tooManyArt: DOORMANY
io: socket
}
}
```
## See Also
* [Telnet Bridge](telnet-bridge.md)
* [Door Servers](door-servers.md)
## Additional Resources
### DOS Emulation
* [DOSEMU](http://www.dosemu.org/)
* [DOSBox-X](https://github.com/joncampbell123/dosbox-x)
### Door Downloads & Support Sites
#### General
* http://bbsfiles.com/
* http://bbstorrents.bbses.info/
#### L.O.R.D.
* http://lord.lordlegacy.com/