Enigma 1/2 Sysop Module Creation

Enigma 1/2 - A killer BBS System developed by Bryan Ashby that is one of the most customizable BBS products out there today for modern OSes. Think back to days of BBS systems running in pure BASIC language that you could tweak, develop from, remove or move sections of, or just completely outright morph to your own creation, and you’ll understand the interest in Enigma 1/2.

The BBS runs off core files developed in JSON and allows SYSOPs that may not be too privy on how to work with that type of code to do customization by a simplified form, HJSON. For the record, I am one of those type of SYSOPs. I’ve worked with structured language frequently, but for whatever reason, my aging mind has not grasped JSON in it’s totality.

One of the things I really wanted to see was a SYSOP monitoring and maintenance area within the BBS instead of relying on any engine work at the command prompt of the OS. Bryan contributed in large form with the recent addition of “Waiting For Caller” front end; showing the sysop BBS activity occurring at any moment. NICE. But that still leaves SYSOP Maintenance functions to be had, and for me where I operate in the cloud, that’s requires logging into my remote system, getting to the right directory, and executing the various commands. I’d rather be BBS’ing!

Many of the maintenance functions needed to keep the BBS going uses a module called “OPUTIL.JS”, run from the command prompt of the OS the system is installed on. Of course, there are other commands associated with system maintenance that are not part of Enigma build that are also frequently utilized.


Op Util format

Some examples of commands are (shown in Linux form):

  • ./oputil.js user nuke pw IL0veEnigma (changes password)
  • ./oputil.js fb scan ansiart (scans filebase area for storage tag area ansiart)
  • tar -czvf westwood_backup.tar.gz /home/nuke/enigma-bbs (backs up my BBS)
  • poll_bink.sh (forces a message transaction between BBS and FTN)
  • sudo apt install && sudo apt update (linux update refreshment)

So if you’re familiar with LINUX or Windows command prompt use, there is a solution available to make a Front End within the BBS for the SYSOP to run these frequent tasks. All you need is to make a shell (SH) script, or for Windows, a batch (BAT) file.

Enigma offers an awesome little module called Abracadabra, and this is one of the tools available to drive executable system files from within the BBS, and manages the input/output for the user at the screen. Using this with linux or windows scripting solves the dilemma of trying to make a JSON creation of your own (though this is still encouraged to learn)!

One of my key mantras I always tell my subordinates in my line of work: keep it simple stupid. The more complex something gets, the harder it is to manage and easier to break. So let’s keep it simple, shall we?

  • Step 1) Define commands you want to use and create a menu for it - here’s a snapshot of mine and I call it SYSOPMENU.ANS

  • Step 2) Add a command call to your sysop menu to your menu.hjson area

  		{   value: { command: "/SYSOPMENU" }
  		action: [
  			{
  			// SYSOP Privileged Area
  			acs: GM[sysops]
  			action: @menu:sysopMainMenu
  			}
  		]
  • Step 3) Develop your shell scripts to support the commands you’ve identified in your menu. For this example, we will develop resetting a user’s password. This script is for LINUX:

  • Repeat step 3 for all your other commands. ALTERNATIVE: You can execute all your commands within one script and pass an argument to it to definte what the sysop action is, then perhaps use a CASE statement to work the execution flow based on the parameter. Guided by my mantra, I made single scripts for each command, and I will probably revisit that later myself as a clean-up improvement for my system.

  • Step 4) build the menu-driven command functionality in your menu.hjson to execute the command (script) calls via the abracadabra module. Below is my code in totality for all the SYSOP functions. Literally a cut and paste, of each command segment, while changing the name and script portions for each one. I’m sure this could be condensed in some manner with arguments - but this gets things started (remember to change your path names to the correct path for your scripts!):

{
menus: {

  sysopMainMenu: {
  	desc: SysOp Maintenance
  	art: SYSOPMENU
  	prompt: menuCommand
  	config: {
            cls: true
  		art: SYSOPMENU
            interrupt: realtime
  	}
  	submit: [
  			{
  				value: { command: "UL" }
  				action: @menu:sysopUserList
  			}
  			{
  				value: { command: "UI" }
  				action: @menu:sysopUserInformation
  			}
  			{
  				value: { command: "UP" }
  				action: @menu:sysopUpgradeUser
  			}
  			{
  				value: { command: "DD" }
  				action: @menu:sysopUpgradeDahlgrenite
  			}
  			{
  				value: { command: "R" }
  				action: @menu:sysopUserRestrict
  			}
  			{
  				value: { command: "L" }
  				action: @menu:sysopLockUser
  			}
  			{
  				value: { command: "PO" }
  				action: @menu:sysopPollBink
  			}
  			{
  				value: { command: "DU" }
  				action: @menu:sysopDeleteUser
  			}
  			{
  				value: { command: "CP" }
  				action: @menu:sysopUserPassword
  			}
  			{
  				value: { command: "SL" }
  				action: @menu:sysopShowLog
  			}
  			{
  				value: { command: "BU" }
  				action: @menu:sysopBackupWW
  			}
  			{
  				value: { command: "DIR" }
  				action: @menu:sysopShowDir
  			}
  			{
  				value: { command: "NANO" }
  				action: @menu:sysopNANO
  			}
  			{
  				value: { command: "FB" }
  				action: @menu:sysopFB
  			}
  			{
  				value: { command: "DG" }
  				action: @menu:sysopDG
  			}
  			{
  				value: { command: "BL" }
  				action: @menu:sysopBinkLog
  			}
                {
                    value: { command: "Q" }
                    action: @systemMethod:prevMenu
                }
                {
                    value: { command: "G" }
                    action: @menu:fullLogoffSequence
                }
  	]

  } // sysop main menu

  sysopUserList: {
  	desc: Sysop Operations UL
  	module: abracadabra
  	config: {
  		name: User Listing
  		cmd: /home/nuke/enigma-bbs/userlist.sh
  		io: stdio
  	}
  }
  sysopDeleteUser: {
  	desc: Sysop Operations DU
  	module: abracadabra
  	config: {
  		name: delete user
  		cmd: /home/nuke/enigma-bbs/deleteauser.sh
  		io: stdio
  	}
  }
  sysopUserInformation: {
  	desc: Sysop Operations UI
  	module: abracadabra
  	config: {
  		name: user information
  		cmd: /home/nuke/enigma-bbs/userinfo.sh
  		io: stdio
  	}
  }
  sysopUpgradeUser: {
  	desc: Sysop Operations UP
  	module: abracadabra
  	config: {
  		name: user upgrade
  		cmd: /home/nuke/enigma-bbs/upgradeuser.sh
  		io: stdio
  	}
  }
  sysopUpgradeDahlgrenite: {
  	desc: Sysop Operations UP DD
  	module: abracadabra
  	config: {
  		name: user upgrade dahlgrenite
  		cmd: /home/nuke/enigma-bbs/upgradeuserdd.sh
  		io: stdio
  	}
  }
  sysopUserRestrict: {
  	desc: Sysop Operations RE
  	module: abracadabra
  	config: {
  		name: user restrict
  		cmd: /home/nuke/enigma-bbs/restrictuser.sh
  		io: stdio
  	}
  }
  sysopLockUser: {
  	desc: Sysop Operations LK
  	module: abracadabra
  	config: {
  		name: user lock
  		cmd: /home/nuke/enigma-bbs/lockuser.sh
  		io: stdio
  	}
  }
  sysopPollBink: {
  	desc: Sysop Operations POLL
  	module: abracadabra
  	config: {
  		name: execute poll bink
  		cmd: /home/nuke/enigma-bbs/misc/poll_bink.sh
  		io: stdio
  	}
  }
  sysopDeleteUser: {
  	desc: Sysop Operations DEL
  	module: abracadabra
  	config: {
  		name: user delete
  		cmd: /home/nuke/enigma-bbs/removeuser.sh
  		io: stdio
  	}
  }
  sysopUserPassword: {
  	desc: Sysop Operations PSWD
  	module: abracadabra
  	config: {
  		name: user password change
  		cmd: /home/nuke/enigma-bbs/userpassword.sh
  		io: stdio
  	}
  }
  sysopShowLog: {
  	desc: Sysop Operations LOG
  	module: abracadabra
  	config: {
  		name: monitor log
  		cmd: /home/nuke/enigma-bbs/showlog.sh
  		io: stdio
  	}
  }
  sysopBinkLog: {
  	desc: Sysop Operations BINKD LOG
  	module: abracadabra
  	config: {
  		name: monitor bink log
  		cmd: /home/nuke/enigma-bbs/showbinkd.sh
  		io: stdio
  	}
  }
  sysopBackupWW: {
  	desc: Sysop Operations BU
  	module: abracadabra
  	config: {
  		name: backing up system
  		cmd: /home/nuke/backupww.sh
  		io: stdio
  	}
  }
  sysopShowDir: {
  	desc: Sysop maint dir
  	module: abracadabra
  	config: {
  		name: file maintenance
  		cmd: /home/nuke/enigma-bbs/showdir.sh
  		io: stdio
  	}
  }
  sysopNANO: {
  	desc: Sysop maint nano
  	module: abracadabra
  	config: {
  		name: sysop editing files
  		cmd: /home/nuke/enigma-bbs/systemnano.sh
  		io: stdio
  	}
  }
  sysopFB: {
  	desc: Sysop Filebase Maint
  	module: abracadabra
  	config: {
  		name: sysop filebase maint
  		cmd: /home/nuke/enigma-bbs/updatefb.sh
  		io: stdio
  	}
  }
  sysopDG: {
  	desc: Sysop User Maint DG
  	module: abracadabra
  	config: {
  		name: sysop user maint dg
  		cmd: /home/nuke/enigma-bbs/downgradeuser.sh
  		io: stdio
  	}
  }

}
}

Finally, at least for LINUX users, make sure all commands are executable. Go to your directory with your SH commands, and perform CHMOD +X against them all.

Here are some examples of my shell commands:

  • SHOW Enigma BBS Log

#!/bin/sh
tail -F /home/nuke/enigma-bbs/logs/enigma-bbs.log | bunyan

  • Show BINKD Log

#!/bin/sh
tail -F /var/log/binkd/binkd.log | bunyan

  • Show User Information

#!/bin/sh
echo “***************************** SYSOP RETRIEVE USER INFORMATION ****************************”
echo “---------------------------- ---------------------------”
echo " "
echo " "
echo “Enter user name to query:”
read THE_USER
./oputil.js user info “$THE_USER”
echo " "
echo “operation executed. press enter.”
read DUMMY

  • Remove a User

#!/bin/sh
echo “***************************** SYSOP REMOVE USER ****************************”
echo “---------------------------- ---------------------------”
echo " "
echo " "
echo “Enter user name to REMOVE:”
read THE_USER
./oputil.js user rm “$THE_USER”
echo “operation executed. press enter.”
read DUMMY

  • Update FIlebase

#!/bin/bash

echo “enter the following”
echo “1 - Ansi Art”
echo “2 - bbs stuff”
echo “3 - coleco suff”
echo “4 - Commodore”
echo “5 - crap”
echo “6 - dox box stuff”
echo “7 - flight sim stuff”
echo “8 - linux stuff”
echo “9 - mame stuff”
echo “10 - misc stuff”
echo “11 - terminals”
echo “12 - atari”
echo “13 - TIC Files”
echo “14 - All”
echo “don’t forget uploads!”
read text
case $text in
“1”)
./oputil.js fb scan ansi_art “"
;;
“2”)
./oputil.js fb scan bbs_stuff "

;;
“3”)
./oputil.js fb scan coleco_1 ""
;;
“4”)
./oputil.js fb scan commodore
"
;;
“5”)
./oputil.js fb scan crap_1 "

;;
“6”)
./oputil.js fb scan dos_box “"
;;
“7”)
./oputil.js fb scan flight_sim "

;;
“8”)
./oputil.js fb scan linux_stuff “"
;;
“9”)
./oputil.js fb scan mame "

;;
“10”)
./oputil.js fb scan misc_1 “"
;;
“11”)
./oputil.js fb scan terminals_1 "

;;
“12”)
./oputil.js fb scan atari_1 “"
;;
“13”)
./oputil.js fb scan msg_network "

;;
“14”)
./oputil.js fb scan * “*”
;;
*)
echo “incorrect entry”
esac
echo “Press enter to exit”
read DUMMY

Again - play with this idea! Take the simple steps here and make it as complex as you desire, but the baby steps here are REMARKABLY simple; why did it take me two years to think of, don’t ask me.

Another cool feature as a side note: I use the above methods to invoke the use of LYNX web browser for the user to see this Discourse web area from the BBS. I wish I could use the W3M browser, but it doesn’t offer lockdown features that LYNX has. The use of abracadabra as we did above remains exactly the same, calling out a shell script with the following lynx command:

lynx -anonymous -noprint -ftp -homepage=https://westwoodbbs.net -nobrowse -noexec -nolog /
-nolist -rlogin -telnet -restrictions=default,inside_telnet,outside_telnet,inside_news, /
inside_ftp,outside_ftp,inside_rlogin,outside_rlogin,jump,mail,goto https://westwoodbbs.net

If you think about all of the above, you don’t have to become a JSON expert to add killer and unique functionality to your Enigma 1/2 BBS!

I hope this helps - send me your sysop screens when you give it a go!
~-Nuke-~