* DOOR.SYS support
* LORD now works via DOOR.SYS at least * Abracadabra: nodeMax, tooManyArt support, etc. * Abracadabra: Exit back to menu * Some code cleanup
This commit is contained in:
parent
144aa6b351
commit
608d4dc094
45
core/door.js
45
core/door.js
|
@ -4,6 +4,7 @@
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('child_process').spawn;
|
||||||
var events = require('events');
|
var events = require('events');
|
||||||
|
|
||||||
|
var _ = require('lodash');
|
||||||
var pty = require('pty');
|
var pty = require('pty');
|
||||||
|
|
||||||
exports.Door = Door;
|
exports.Door = Door;
|
||||||
|
@ -14,6 +15,8 @@ function Door(client, exeInfo) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.exeInfo = exeInfo;
|
this.exeInfo = exeInfo;
|
||||||
|
|
||||||
|
this.exeInfo.encoding = this.exeInfo.encoding || 'cp437';
|
||||||
|
|
||||||
// exeInfo.cmd
|
// exeInfo.cmd
|
||||||
// exeInfo.args[]
|
// exeInfo.args[]
|
||||||
// exeInfo.env{}
|
// exeInfo.env{}
|
||||||
|
@ -30,44 +33,36 @@ Door.prototype.run = function() {
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
var doorProc = spawn(this.exeInfo.cmd, this.exeInfo.args);
|
var door = pty.spawn(self.exeInfo.cmd, self.exeInfo.args, {
|
||||||
|
|
||||||
/*
|
|
||||||
doorProc.stderr.pipe(self.client.term.output);
|
|
||||||
doorProc.stdout.pipe(self.client.term.output);
|
|
||||||
doorProc.stdout.on('data', function stdOutData(data) {
|
|
||||||
console.log('got data')
|
|
||||||
self.client.term.write(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
doorProc.stderr.on('data', function stdErrData(data) {
|
|
||||||
console.log('got error data')
|
|
||||||
self.client.term.write(data);
|
|
||||||
});
|
|
||||||
|
|
||||||
doorProc.on('close', function closed(exitCode) {
|
|
||||||
console.log('closed')
|
|
||||||
self.emit('closed', exitCode); // just fwd on
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
var door = pty.spawn(this.exeInfo.cmd, this.exeInfo.args, {
|
|
||||||
cols : self.client.term.termWidth,
|
cols : self.client.term.termWidth,
|
||||||
rows : self.client.term.termHeight,
|
rows : self.client.term.termHeight,
|
||||||
|
// :TODO: cwd
|
||||||
|
env : self.exeInfo.env,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// :TODO: can we pause the stream, write our own "Loading...", then on resume?
|
||||||
|
|
||||||
//door.pipe(self.client.term.output);
|
//door.pipe(self.client.term.output);
|
||||||
self.client.term.output.pipe(door);
|
self.client.term.output.pipe(door);
|
||||||
|
|
||||||
// :TODO: do this with pluggable pipe/filter classes
|
// :TODO: do this with pluggable pipe/filter classes
|
||||||
|
|
||||||
door.setEncoding('cp437');
|
door.setEncoding(this.exeInfo.encoding);
|
||||||
|
|
||||||
door.on('data', function doorData(data) {
|
door.on('data', function doorData(data) {
|
||||||
self.client.term.write(data);
|
self.client.term.write(data);
|
||||||
//console.log(data);
|
|
||||||
});
|
});
|
||||||
//*/
|
|
||||||
|
|
||||||
door.on('close', function closed() {
|
door.on('close', function closed() {
|
||||||
console.log('closed...')
|
self.client.term.output.unpipe(door);
|
||||||
|
self.client.term.output.resume();
|
||||||
|
});
|
||||||
|
|
||||||
|
door.on('exit', function exited(code) {
|
||||||
|
self.client.log.info( { code : code }, 'Door exited');
|
||||||
|
|
||||||
|
door.removeAllListeners();
|
||||||
|
|
||||||
|
self.emit('finished');
|
||||||
});
|
});
|
||||||
};
|
};
|
110
core/dropfile.js
110
core/dropfile.js
|
@ -7,6 +7,7 @@ var fs = require('fs');
|
||||||
var paths = require('path');
|
var paths = require('path');
|
||||||
var _ = require('lodash');
|
var _ = require('lodash');
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
|
var moment = require('moment');
|
||||||
|
|
||||||
exports.DropFile = DropFile;
|
exports.DropFile = DropFile;
|
||||||
|
|
||||||
|
@ -55,7 +56,9 @@ function DropFile(client, fileType) {
|
||||||
Object.defineProperty(this, 'dropFileContents', {
|
Object.defineProperty(this, 'dropFileContents', {
|
||||||
get : function() {
|
get : function() {
|
||||||
return {
|
return {
|
||||||
DORINFO : self.getDoorInfoBuffer(),
|
DOOR : self.getDoorSysBuffer(),
|
||||||
|
|
||||||
|
DORINFO : self.getDoorInfoDefBuffer(),
|
||||||
}[self.fileType];
|
}[self.fileType];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -73,7 +76,76 @@ function DropFile(client, fileType) {
|
||||||
return 'DORINFO' + x + '.DEF';
|
return 'DORINFO' + x + '.DEF';
|
||||||
};
|
};
|
||||||
|
|
||||||
this.getDoorInfoBuffer = function() {
|
this.getDoorSysBuffer = function() {
|
||||||
|
var up = self.client.user.properties;
|
||||||
|
var now = moment();
|
||||||
|
var secLevel = self.client.user.getLegacySecurityLevel().toString();
|
||||||
|
|
||||||
|
// :TODO: fix time remaining
|
||||||
|
// :TODO: fix default protocol -- user prop: transfer_protocol
|
||||||
|
|
||||||
|
return new Buffer( [
|
||||||
|
'COM1:', // "Comm Port - COM0: = LOCAL MODE"
|
||||||
|
'57600', // "Baud Rate - 300 to 38400" (Note: set as 57600 instead!)
|
||||||
|
'8', // "Parity - 7 or 8"
|
||||||
|
self.client.node.toString(), // "Node Number - 1 to 99"
|
||||||
|
'57600', // "DTE Rate. Actual BPS rate to use. (kg)"
|
||||||
|
'Y', // "Screen Display - Y=On N=Off (Default to Y)"
|
||||||
|
'Y', // "Printer Toggle - Y=On N=Off (Default to Y)"
|
||||||
|
'Y', // "Page Bell - Y=On N=Off (Default to Y)"
|
||||||
|
'Y', // "Caller Alarm - Y=On N=Off (Default to Y)"
|
||||||
|
up.realName || self.client.user.username, // "User Full Name"
|
||||||
|
up.location || 'Anywhere', // "Calling From"
|
||||||
|
'123-456-7890', // "Home Phone"
|
||||||
|
'123-456-7890', // "Work/Data Phone"
|
||||||
|
'NOPE', // "Password" (Note: this is never given out or even stored plaintext)
|
||||||
|
secLevel, // "Security Level"
|
||||||
|
up.login_count.toString(), // "Total Times On"
|
||||||
|
now.format('MM/DD/YY'), // "Last Date Called"
|
||||||
|
'15360', // "Seconds Remaining THIS call (for those that particular)"
|
||||||
|
'256', // "Minutes Remaining THIS call"
|
||||||
|
'GR', // "Graphics Mode - GR=Graph, NG=Non-Graph, 7E=7,E Caller"
|
||||||
|
self.client.term.termHeight.toString(), // "Page Length"
|
||||||
|
'N', // "User Mode - Y = Expert, N = Novice"
|
||||||
|
'1,2,3,4,5,6,7', // "Conferences/Forums Registered In (ABCDEFG)"
|
||||||
|
'1', // "Conference Exited To DOOR From (G)"
|
||||||
|
'01/01/99', // "User Expiration Date (mm/dd/yy)"
|
||||||
|
self.client.user.userId.toString(), // "User File's Record Number"
|
||||||
|
'Z', // "Default Protocol - X, C, Y, G, I, N, Etc."
|
||||||
|
// :TODO: fix up, down, etc. form user properties
|
||||||
|
'0', // "Total Uploads"
|
||||||
|
'0', // "Total Downloads"
|
||||||
|
'0', // "Daily Download "K" Total"
|
||||||
|
'999999', // "Daily Download Max. "K" Limit"
|
||||||
|
moment(up.birthdate).format('MM/DD/YY'), // "Caller's Birthdate"
|
||||||
|
'X:\\MAIN\\', // "Path to the MAIN directory (where User File is)"
|
||||||
|
'X:\\GEN\\', // "Path to the GEN directory"
|
||||||
|
Config.general.sysOp.username, // "Sysop's Name (name BBS refers to Sysop as)"
|
||||||
|
self.client.user.username, // "Alias name"
|
||||||
|
'00:05', // "Event time (hh:mm)" (note: wat?)
|
||||||
|
'Y', // "If its an error correcting connection (Y/N)"
|
||||||
|
'Y', // "ANSI supported & caller using NG mode (Y/N)"
|
||||||
|
'Y', // "Use Record Locking (Y/N)"
|
||||||
|
'7', // "BBS Default Color (Standard IBM color code, ie, 1-15)"
|
||||||
|
// :TODO: fix minutes here also:
|
||||||
|
'256', // "Time Credits In Minutes (positive/negative)"
|
||||||
|
'07/07/90', // "Last New Files Scan Date (mm/dd/yy)"
|
||||||
|
// :TODO: fix last vs now times:
|
||||||
|
now.format('hh:mm'), // "Time of This Call"
|
||||||
|
now.format('hh:mm'), // "Time of Last Call (hh:mm)"
|
||||||
|
'9999', // "Maximum daily files available"
|
||||||
|
// :TODO: fix these stats:
|
||||||
|
'0', // "Files d/led so far today"
|
||||||
|
'0', // "Total "K" Bytes Uploaded"
|
||||||
|
'0', // "Total "K" Bytes Downloaded"
|
||||||
|
up.user_comment || 'None', // "User Comment"
|
||||||
|
'0', // "Total Doors Opened"
|
||||||
|
'0', // "Total Messages Left"
|
||||||
|
|
||||||
|
].join('\r\n') + '\r\n', 'cp437');
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getDoorInfoDefBuffer = function() {
|
||||||
// :TODO: fix time remaining
|
// :TODO: fix time remaining
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -82,22 +154,24 @@ function DropFile(client, fileType) {
|
||||||
//
|
//
|
||||||
// Note that usernames are just used for first/last names here
|
// Note that usernames are just used for first/last names here
|
||||||
//
|
//
|
||||||
var opUn = /[^\s]*/.exec(Config.general.sysOp.username)[0];
|
var opUn = /[^\s]*/.exec(Config.general.sysOp.username)[0];
|
||||||
var un = /[^\s]*/.exec(self.client.user.username)[0];
|
var un = /[^\s]*/.exec(self.client.user.username)[0];
|
||||||
return new Buffer([
|
var secLevel = self.client.user.getLegacySecurityLevel().toString();
|
||||||
Config.general.boardName, // "The name of the system."
|
|
||||||
opUn, // "The sysop's name up to the first space."
|
return new Buffer( [
|
||||||
opUn, // "The sysop's name following the first space."
|
Config.general.boardName, // "The name of the system."
|
||||||
'COM1', // "The serial port the modem is connected to, or 0 if logged in on console."
|
opUn, // "The sysop's name up to the first space."
|
||||||
'57600', // "The current port (DTE) rate."
|
opUn, // "The sysop's name following the first space."
|
||||||
'0', // "The number "0""
|
'COM1', // "The serial port the modem is connected to, or 0 if logged in on console."
|
||||||
un, // "The current user's name, up to the first space."
|
'57600', // "The current port (DTE) rate."
|
||||||
un, // "The current user's name, following the first space."
|
'0', // "The number "0""
|
||||||
self.client.user.properties.location || '', // "Where the user lives, or a blank line if unknown."
|
un, // "The current user's name, up to the first space."
|
||||||
'1', // "The number "0" if TTY, or "1" if ANSI."
|
un, // "The current user's name, following the first space."
|
||||||
self.client.user.isSysOp() ? '100' : '30', // "The number 5 for problem users, 30 for regular users, 80 for Aides, and 100 for Sysops."
|
self.client.user.properties.location || '', // "Where the user lives, or a blank line if unknown."
|
||||||
'546', // "The number of minutes left in the current user's account, limited to 546 to keep from overflowing other software."
|
'1', // "The number "0" if TTY, or "1" if ANSI."
|
||||||
'-1' // "The number "-1" if using an external serial driver or "0" if using internal serial routines."
|
secLevel, // "The number 5 for problem users, 30 for regular users, 80 for Aides, and 100 for Sysops."
|
||||||
|
'546', // "The number of minutes left in the current user's account, limited to 546 to keep from overflowing other software."
|
||||||
|
'-1' // "The number "-1" if using an external serial driver or "0" if using internal serial routines."
|
||||||
].join('\r\n') + '\r\n', 'cp437');
|
].join('\r\n') + '\r\n', 'cp437');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,10 @@ function User() {
|
||||||
return _.isString(self.groups[groupIdOrName]);
|
return _.isString(self.groups[groupIdOrName]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.getLegacySecurityLevel = function() {
|
||||||
|
return self.isRoot() ? 100 : 30;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
User.PBKDF2 = {
|
User.PBKDF2 = {
|
||||||
|
|
|
@ -4,53 +4,97 @@
|
||||||
var MenuModule = require('../core/menu_module.js').MenuModule;
|
var MenuModule = require('../core/menu_module.js').MenuModule;
|
||||||
var DropFile = require('../core/dropfile.js').DropFile;
|
var DropFile = require('../core/dropfile.js').DropFile;
|
||||||
var door = require('../core/door.js');
|
var door = require('../core/door.js');
|
||||||
|
var theme = require('../core/theme.js');
|
||||||
|
var ansi = require('../core/ansi_term.js');
|
||||||
|
|
||||||
var async = require('async');
|
var async = require('async');
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var mkdirp = require('mkdirp');
|
var mkdirp = require('mkdirp');
|
||||||
var paths = require('path');
|
var paths = require('path');
|
||||||
|
var _ = require('lodash');
|
||||||
|
|
||||||
// :TODO: This should really be a system module... needs a little work to allow for such
|
// :TODO: This should really be a system module... needs a little work to allow for such
|
||||||
|
|
||||||
exports.getModule = AbracadabraModule;
|
exports.getModule = AbracadabraModule;
|
||||||
|
|
||||||
|
var activeDoorNodeInstances = {};
|
||||||
|
|
||||||
exports.moduleInfo = {
|
exports.moduleInfo = {
|
||||||
name : 'Abracadabra',
|
name : 'Abracadabra',
|
||||||
desc : 'External BBS Door Module',
|
desc : 'External BBS Door Module',
|
||||||
author : 'NuSkooler',
|
author : 'NuSkooler',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Example configuration for LORD under DOSEMU:
|
||||||
|
|
||||||
|
{
|
||||||
|
"config" : {
|
||||||
|
"name" : "LORD",
|
||||||
|
"dropFileType" : "DOOR",
|
||||||
|
"cmd" : "/usr/bin/dosemu",
|
||||||
|
"args" : [ "-quiet", "-f", "/etc/dosemu/dosemu.conf", "X:\\PW\\START.BAT {dropfile} {node}" ] ],
|
||||||
|
"nodeMax" : 32,
|
||||||
|
"tooManyArt" : "toomany-lord.ans"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
function AbracadabraModule(options) {
|
function AbracadabraModule(options) {
|
||||||
MenuModule.call(this, options);
|
MenuModule.call(this, options);
|
||||||
|
|
||||||
var self = this;
|
var self = this;
|
||||||
this.config = options.menuConfig.config || {
|
|
||||||
dropFileType : 'DORINFO',
|
|
||||||
};
|
|
||||||
|
|
||||||
this.config.args = this.config.args || [];
|
this.config = options.menuConfig.config;
|
||||||
|
|
||||||
|
assert(_.isString(this.config.name, 'Config \'name\' is required'));
|
||||||
|
assert(_.isString(this.config.dropFileType, 'Config \'dropFileType\' is required'));
|
||||||
|
assert(_.isString(this.config.cmd, 'Config \'cmd\' is required'));
|
||||||
|
|
||||||
|
this.config.nodeMax = this.config.nodeMax || 0;
|
||||||
|
this.config.args = this.config.args || [];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
{
|
:TODO:
|
||||||
"config" : {
|
* disconnecting wile door is open leaves dosemu
|
||||||
"name" : "LORD",
|
|
||||||
"cmd" : "...",
|
|
||||||
"args" : [ ... ],
|
|
||||||
"dropFileType" : "dorinfo",
|
|
||||||
"maxNodes" : 32, default=unlimited
|
|
||||||
"tooManyArt" : "..." (optional); default = "Too many active" message
|
|
||||||
...
|
|
||||||
"dropFilePath" : "/.../LORD/", || Config.paths.dropFiles
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
this.initSequence = function() {
|
this.initSequence = function() {
|
||||||
async.series(
|
async.series(
|
||||||
[
|
[
|
||||||
function validateNodeCount(callback) {
|
function validateNodeCount(callback) {
|
||||||
// :TODO: Check that node count for this door has not been reached
|
if(self.config.nodeMax > 0 &&
|
||||||
callback(null);
|
_.isNumber(activeDoorNodeInstances[self.config.name]) &&
|
||||||
|
activeDoorNodeInstances[self.config.name] + 1 > self.config.nodeMax)
|
||||||
|
{
|
||||||
|
self.client.log.info(
|
||||||
|
{
|
||||||
|
name : self.config.name,
|
||||||
|
activeCount : activeDoorNodeInstances[self.config.name]
|
||||||
|
},
|
||||||
|
'Too many active instances');
|
||||||
|
|
||||||
|
if(_.isString(self.config.tooManyArt)) {
|
||||||
|
theme.displayThemeArt( { client : self.client, name : self.config.tooManyArt }, function displayed() {
|
||||||
|
callback(new Error('Too many active instances'));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
self.client.term.write('\nToo many active instances. Try again later.\n');
|
||||||
|
|
||||||
|
setTimeout(function timeout() {
|
||||||
|
callback(new Error('Too many active instances'));
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// :TODO: JS elegant way to do this?
|
||||||
|
if(activeDoorNodeInstances[self.config.name]) {
|
||||||
|
activeDoorNodeInstances[self.config.name] += 1;
|
||||||
|
} else {
|
||||||
|
activeDoorNodeInstances[self.config.name] = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
function generateDropfile(callback) {
|
function generateDropfile(callback) {
|
||||||
self.dropFile = new DropFile(self.client, self.config.dropFileType);
|
self.dropFile = new DropFile(self.client, self.config.dropFileType);
|
||||||
|
@ -68,14 +112,46 @@ function AbracadabraModule(options) {
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
function complete(err) {
|
function complete(err) {
|
||||||
self.finishedLoading();
|
if(err) {
|
||||||
|
self.fallbackModule();
|
||||||
|
} else {
|
||||||
|
self.finishedLoading();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.runDOSEmuDoor = function() {
|
this.runDosEmuDoor = function() {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.runDoor = function() {
|
||||||
|
|
||||||
|
var exeInfo = {
|
||||||
|
cmd : this.config.cmd,
|
||||||
|
args : this.config.args,
|
||||||
|
};
|
||||||
|
|
||||||
|
// :TODO: this system should probably be generic
|
||||||
|
for(var i = 0; i < exeInfo.args.length; ++i) {
|
||||||
|
exeInfo.args[i] = exeInfo.args[i].replace(/\{dropfile\}/g, self.dropFile.fileName);
|
||||||
|
exeInfo.args[i] = exeInfo.args[i].replace(/\{node\}/g, self.client.node.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
var doorInstance = new door.Door(this.client, exeInfo);
|
||||||
|
|
||||||
|
doorInstance.on('finished', function doorFinished() {
|
||||||
|
self.fallbackModule();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.client.term.write(ansi.resetScreen());
|
||||||
|
|
||||||
|
doorInstance.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fallbackModule = function() {
|
||||||
|
self.client.gotoMenuModule( { name : self.menuConfig.fallback } );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
require('util').inherits(AbracadabraModule, MenuModule);
|
require('util').inherits(AbracadabraModule, MenuModule);
|
||||||
|
@ -86,24 +162,12 @@ AbracadabraModule.prototype.enter = function(client) {
|
||||||
};
|
};
|
||||||
|
|
||||||
AbracadabraModule.prototype.leave = function() {
|
AbracadabraModule.prototype.leave = function() {
|
||||||
Abracadabra.super_.prototype.leave.call(this);
|
AbracadabraModule.super_.prototype.leave.call(this);
|
||||||
|
|
||||||
|
activeDoorNodeInstances[this.config.name] -= 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
AbracadabraModule.prototype.finishedLoading = function() {
|
AbracadabraModule.prototype.finishedLoading = function() {
|
||||||
var self = this;
|
|
||||||
|
this.runDoor();
|
||||||
var exeInfo = {
|
|
||||||
cmd : this.config.cmd,
|
|
||||||
args : this.config.args,
|
|
||||||
};
|
|
||||||
|
|
||||||
// :TODO: this system should probably be generic
|
|
||||||
for(var i = 0; i < exeInfo.args.length; ++i) {
|
|
||||||
exeInfo.args[i] = exeInfo.args[i].replace(/\{dropfile\}/g, self.dropFile.fileName);
|
|
||||||
exeInfo.args[i] = exeInfo.args[i].replace(/\{node\}/g, self.client.node.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
var doorInstance = new door.Door(this.client, exeInfo);
|
|
||||||
doorInstance.run();
|
|
||||||
};
|
};
|
|
@ -50,7 +50,7 @@ LastCallersModule.prototype.enter = function(client) {
|
||||||
|
|
||||||
// we need the client to init this for theming
|
// we need the client to init this for theming
|
||||||
if(!_.isString(this.dateTimeFormat)) {
|
if(!_.isString(this.dateTimeFormat)) {
|
||||||
this.dateTimeFormat = this.client.currentTheme.helpers.getDateFormat('short') +
|
this.dateTimeFormat = this.client.currentTheme.helpers.getDateFormat('short') + ' ' +
|
||||||
this.client.currentTheme.helpers.getTimeFormat('short');
|
this.client.currentTheme.helpers.getTimeFormat('short');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -197,6 +197,9 @@
|
||||||
"module" : "last_callers",
|
"module" : "last_callers",
|
||||||
"art" : "LASTCALL",
|
"art" : "LASTCALL",
|
||||||
"options" : { "cls" : true, "pause" : true },
|
"options" : { "cls" : true, "pause" : true },
|
||||||
|
"config" : {
|
||||||
|
"dateTimeFormat" : "ddd MMM Do h:mm a"
|
||||||
|
},
|
||||||
"action" : "@menu:fullLoginSequenceUserStats"
|
"action" : "@menu:fullLoginSequenceUserStats"
|
||||||
},
|
},
|
||||||
"fullLoginSequenceUserStats" : {
|
"fullLoginSequenceUserStats" : {
|
||||||
|
@ -211,8 +214,8 @@
|
||||||
},
|
},
|
||||||
"currentUserStats" : {
|
"currentUserStats" : {
|
||||||
"art" : "userstats",
|
"art" : "userstats",
|
||||||
"options" : { "cls" : true, "pause" : true },
|
"options" : { "cls" : true, "pause" : true }
|
||||||
"action" : "@menu:lastCallers"
|
//"action" : "@menu:lastCallers"
|
||||||
},
|
},
|
||||||
"mainMenu" : {
|
"mainMenu" : {
|
||||||
"art" : "MAINMENU",
|
"art" : "MAINMENU",
|
||||||
|
@ -239,6 +242,10 @@
|
||||||
"value" : { "1" : "d" },
|
"value" : { "1" : "d" },
|
||||||
"action" : "@menu:doorPimpWars"
|
"action" : "@menu:doorPimpWars"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"value" : { "1" : "l" },
|
||||||
|
"action" : "@menu:doorLORD"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"value" : 1,
|
"value" : 1,
|
||||||
"action" : "@menu:mainMenu"
|
"action" : "@menu:mainMenu"
|
||||||
|
@ -251,10 +258,27 @@
|
||||||
},
|
},
|
||||||
"doorPimpWars" : {
|
"doorPimpWars" : {
|
||||||
"module" : "abracadabra",
|
"module" : "abracadabra",
|
||||||
|
"fallback" : "mainMenu",
|
||||||
"config" : {
|
"config" : {
|
||||||
"name" : "PimpWars",
|
"name" : "PimpWars",
|
||||||
"cmd" : "/usr/bin/dosemu",
|
"dropFileType" : "DORINFO",
|
||||||
"args" : [ "-quiet", "-f", "/home/nuskooler/DOS/X/LORD/dosemu.conf", "X:\\PW\\START.BAT {dropfile} {node}" ]//, "X:\\PW\\PIMPWARS.EXE", "X:\\DROP\\{dropfile}", "{node}" ]
|
"cmd" : "/usr/bin/dosemu",
|
||||||
|
"args" : [
|
||||||
|
"-quiet", "-f", "/home/nuskooler/DOS/X/LORD/dosemu.conf", "X:\\PW\\START.BAT {dropfile} {node}"
|
||||||
|
],
|
||||||
|
"nodeMax" : 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"doorLORD" : {
|
||||||
|
"module" : "abracadabra",
|
||||||
|
"fallback" : "mainMenu",
|
||||||
|
"config" : {
|
||||||
|
"name" : "LORD",
|
||||||
|
"dropFileType" : "DOOR",
|
||||||
|
"cmd" : "/usr/bin/dosemu",
|
||||||
|
"args" : [
|
||||||
|
"-quiet", "-f", "/home/nuskooler/DOS/X/LORD/dosemu.conf", "X:\\LORD\\START.BAT {node}"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Reference in New Issue