Mon 21 Jul 22:43:21 CEST 2025
This commit is contained in:
parent
bd72de8968
commit
7511972ed0
507
js/dos/appl/shell.js
Normal file
507
js/dos/appl/shell.js
Normal file
|
@ -0,0 +1,507 @@
|
|||
/**
|
||||
** ==============================
|
||||
** O O O OOOO
|
||||
** O O O O O O
|
||||
** O O O O O O
|
||||
** OOOO OOOO O OOO OOOO
|
||||
** O O O O O O O
|
||||
** O O O O O O O
|
||||
** OOOO OOOO O O OOOO
|
||||
** ==============================
|
||||
** Dr. Stefan Bosse http://www.bsslab.de
|
||||
**
|
||||
** COPYRIGHT: THIS SOFTWARE, EXECUTABLE AND SOURCE CODE IS OWNED
|
||||
** BY THE AUTHOR(S).
|
||||
** THIS SOURCE CODE MAY NOT BE COPIED, EXTRACTED,
|
||||
** MODIFIED, OR OTHERWISE USED IN A CONTEXT
|
||||
** OUTSIDE OF THE SOFTWARE SYSTEM.
|
||||
**
|
||||
** $AUTHORS: Stefan Bosse
|
||||
** $INITIAL: (C) 2015-2017 bLAB
|
||||
** $CREATED: 26-5-15.
|
||||
** $VERSION: 1.2.17
|
||||
**
|
||||
** $INFO:
|
||||
**
|
||||
** DOS: DOS Terminal Shell
|
||||
**
|
||||
** $ENDOFINFO
|
||||
*/
|
||||
"use strict";
|
||||
var log = 0;
|
||||
var version = "1.2"
|
||||
var Io = Require('com/io');
|
||||
//Io.trace_open('/tmp/shell.trace');
|
||||
|
||||
var Net = Require('dos/network');
|
||||
var Buf = Require('dos/buf');
|
||||
var Sch = Require('dos/scheduler');
|
||||
var Conn = Require('dos/connection');
|
||||
var Rpc = Require('dos/rpc');
|
||||
var Std = Require('dos/std');
|
||||
var Router = Require('dos/router');
|
||||
var util = Require('util');
|
||||
var Comp = Require('com/compat');
|
||||
var assert = Comp.assert;
|
||||
var String = Comp.string;
|
||||
var Array = Comp.array;
|
||||
var Perv = Comp.pervasives;
|
||||
var Printf = Comp.printf;
|
||||
var Filename = Comp.filename;
|
||||
var Obj = Comp.obj;
|
||||
var Args = Comp.args;
|
||||
var Status = Net.Status;
|
||||
var Command = Net.Command;
|
||||
var Fs = Require('fs');
|
||||
var Dns = Require('dos/dns');
|
||||
var Cs = Require('dos/capset');
|
||||
var Getenv = Require('com/getenv');
|
||||
var Ash = Require('dos/ash');
|
||||
var HostSrv = Require('dos/hostsrv');
|
||||
|
||||
var trace = Io.tracing;
|
||||
|
||||
var options = {
|
||||
bip:'localhost',
|
||||
bport:3001,
|
||||
broker: true,
|
||||
default:false,
|
||||
dip : 'localhost',
|
||||
dports : [],
|
||||
env:{},
|
||||
hostport:undefined,
|
||||
hostsrv:false,
|
||||
http:false,
|
||||
keepalive:true,
|
||||
links:[],
|
||||
myip:'localhost',
|
||||
monitor:false,
|
||||
servmode:false,
|
||||
tcpnet:1,
|
||||
verbose:0
|
||||
};
|
||||
|
||||
options.privhostport = Net.uniqport();
|
||||
options.pubhostport = Net.prv2pub(options.privhostport);
|
||||
|
||||
var env = Ash.Env();
|
||||
var help=false;
|
||||
var argv = Io.getargs();
|
||||
|
||||
options.env = env;
|
||||
|
||||
var readline = Require('dos/ext/readline');
|
||||
|
||||
Args.parse(argv, [
|
||||
[['-help','-h'],0,function() {help=true;}],
|
||||
['-broker',1,function(val){
|
||||
var tokens = Comp.string.split(':',val);
|
||||
if (tokens.length==1)
|
||||
options.bip=val;
|
||||
else {
|
||||
options.bip=tokens[0];
|
||||
options.bport=Perv.int_of_string(tokens[1])
|
||||
}
|
||||
}],
|
||||
['-dip',1,function(val){options.dip=val}],
|
||||
['-D',1,function(val){options.dports.push(Perv.int_of_string(val))}],
|
||||
['-L',2,function(val1,val2){options.links.push([Perv.int_of_string(val1),getip(val2),getipport(val2)])}],
|
||||
['-nokeepalive',0,function(val){options.keepalive=false;}],
|
||||
['-T',0,function(val){options.tcpnet=1;options.http=false;}],
|
||||
['-T2',0,function(val){options.tcpnet=2;options.http=false;}],
|
||||
['-H',0,function(val){options.http=true;options.tcpnet=0;}],
|
||||
['-server',0,function(val){options.servmode=true;}],
|
||||
[['-default','-d'],0,function(val){options.default=true;}],
|
||||
['-monitor',0,function () {options.monitor++; out('Setting monitor to level '+options.monitor); }],
|
||||
[['-v','-verbose'],0,function(val){options.verbose++; out('Setting verbosity to level '+options.verbose);}]
|
||||
]);
|
||||
|
||||
if (help) {
|
||||
Io.out('usage: '+argv[0]+' '+argv[1]);
|
||||
Io.out(' [-H -T -T2] Enable connection service');
|
||||
Io.out(' T: TCPIP, 1-ch H:HTTP T2: TCPIP, 2-ch');
|
||||
Io.out(' H: bport, T: bport+100');
|
||||
Io.out(' (Default: -T)');
|
||||
Io.out(' [-D <port>] UDP Server Port');
|
||||
Io.out(' [-L <src port> <UDP dst [address:]port] UDP P2P Connection');
|
||||
Io.out(' [-nokeepalive] Establish a new conncetion for each message.');
|
||||
Io.out(' [-broker <ip[:ipport]>] Broker URL (Default: '+options.bip+': HTTP '+options.bport+' TCPNET '+(options.bport+100)+')');
|
||||
Io.out(' [-dip <VLC UDP server IP>] (Default: '+options.dip+')');
|
||||
Io.out(' [-host <port>] Set Host Port');
|
||||
Io.out(' [-root <cap|capfile>] Set Root Cap.');
|
||||
Io.out(' [+root <cap|capfile>] Appennd Root Cap.');
|
||||
Io.out(' [-default, -d] Ask broker server for default DNS => DNS root => Shell root!');
|
||||
Io.out(' [-help -h -v -verbose -monitor]');
|
||||
Io.out(' [-e <script>] Execute a script');
|
||||
return;
|
||||
}
|
||||
function fail(msg) {
|
||||
Io.stderr('[JASH]: Fatal error: '+msg+'\n');
|
||||
Io.exit(0);
|
||||
}
|
||||
function out(msg) {
|
||||
Io.stdout('[JASH]: '+msg+'\n');
|
||||
}
|
||||
function warn(msg) {
|
||||
Io.stderr('[JASH]: Warning: '+msg+'\n');
|
||||
}
|
||||
var scheduler = Sch.TaskScheduler();
|
||||
scheduler.Init();
|
||||
|
||||
// Set-up the network environment ..
|
||||
// typeof options : {http,tcpnet,dports,bip,bport,myip,verbose}
|
||||
var network = Conn.setup(options);
|
||||
|
||||
|
||||
var todo=[];
|
||||
|
||||
var router = network.router;
|
||||
var rpc = network.rpc;
|
||||
|
||||
|
||||
|
||||
var StdInt = Std.StdInt(rpc);
|
||||
var DnsInt = Dns.DnsInt(rpc);
|
||||
var CsInt = Cs.CsInt(rpc);
|
||||
var ash = Ash.Ash(rpc,scheduler,env);
|
||||
|
||||
if (!Comp.isNodeJS()) {
|
||||
fail('Shell can only be executed on the node.js platform.');
|
||||
}
|
||||
|
||||
|
||||
var cap;
|
||||
if (Obj.isString(env.rootdir)) {
|
||||
cap=Net.Parse.capability(env.rootdir,0);
|
||||
if(cap!=undefined) {
|
||||
env.rootdir=CsInt.cs_singleton(cap.cap);
|
||||
DnsInt.set_rootdir(env.rootdir);
|
||||
}
|
||||
} else env.rootdir=undefined;
|
||||
if (Obj.isString(env.workdir)) {
|
||||
cap=Net.Parse.capability(env.workdir,0);
|
||||
if(cap!=undefined) {
|
||||
env.workdir=CsInt.cs_singleton(cap.cap);
|
||||
}
|
||||
} else env.workdir=undefined;
|
||||
|
||||
|
||||
var stat=Status.STD_OK;
|
||||
Args.parse(argv, [
|
||||
[['-root','-r'],1,function(val) {
|
||||
cap = Net.Parse.capability(val, 0);
|
||||
if (cap != undefined) {
|
||||
env.rootdir = CsInt.cs_singleton(cap.cap);
|
||||
if (env.workdir == undefined) env.workdir = env.rootdir;
|
||||
} else {
|
||||
/*
|
||||
** Capabiliy file path?
|
||||
*/
|
||||
cap = Net.cap_of_file(val);
|
||||
env.rootdir = CsInt.cs_singleton(cap);
|
||||
if (env.workdir == undefined) env.workdir = env.rootdir;
|
||||
}
|
||||
}],
|
||||
[['+root','+r'],1,function(val) {
|
||||
var dnscap,dnscs;
|
||||
dnscap = Net.Parse.capability(val, 0);
|
||||
if (dnscap == undefined) {
|
||||
/*
|
||||
** Capabiliy file path?
|
||||
*/
|
||||
dnscap = Net.cap_of_file(val);
|
||||
} else dnscap=dnscap.cap;
|
||||
if (dnscap != undefined) {
|
||||
todo.push([
|
||||
function () {
|
||||
var name = Net.Print.port(dnscap.cap_port);
|
||||
dnscs = CsInt.cs_singleton(dnscap);
|
||||
out('Append DNS ROOT: ' + Net.Print.capability(dnscap));
|
||||
hostsrv.append('dns/'+name, dnscs, function (_stat) {stat=_stat});
|
||||
if (stat != Status.STD_OK) out('Cannot append ' + name + ': ' + Status.print(stat));
|
||||
stat = hostsrv.append('dns/default', dnscs);
|
||||
},
|
||||
function () {
|
||||
if (dnscs != undefined && env.defafs==undefined) {
|
||||
DnsInt.dns_getdefafs(dnscs,function(_stat,_cap) {
|
||||
out('Default AFS: '+Status.print(_stat)+' is '+ Net.Print.capability(_cap));
|
||||
if (_stat==Status.STD_OK) {
|
||||
env.defafs=_cap;
|
||||
var name=Net.Print.port(_cap.cap_port);
|
||||
var afscs = CsInt.cs_singleton(_cap);
|
||||
out('Append AFS: ' + Net.Print.capability(_cap));
|
||||
hostsrv.append('afs/'+name,afscs, function (_stat) {stat=_stat});
|
||||
if (stat!=Status.STD_OK) out('Cannot append '+name+': '+Status.print(stat));
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
])
|
||||
} else {
|
||||
out('DNS_ROOT: invalid capability (or file) ' + val);
|
||||
}
|
||||
}],
|
||||
[['-host','-h'],1,function(val) {
|
||||
var port = Net.Parse.port(val, 0);
|
||||
if (port != undefined) {
|
||||
options.hostport = port.port;
|
||||
todo.push([
|
||||
function () {
|
||||
DnsInt.dns_getrootcap(options.hostport, function (_stat, _cap) {
|
||||
stat = _stat;
|
||||
if (stat==Status.STD_OK) {
|
||||
env.rootdir = CsInt.cs_singleton(_cap);
|
||||
}
|
||||
})
|
||||
},
|
||||
function () {
|
||||
if (stat != Status.STD_OK) {
|
||||
Io.out('DNS_ROOT: DNS_GETROOT failed for host ' +
|
||||
Net.Print.port(options.hostport) + ': ' +
|
||||
Status.print(stat));
|
||||
rl.setPrompt(env.prompt());
|
||||
rl.prompt();
|
||||
} else {
|
||||
Io.out('DNS ROOT: '+Net.Print.capability(CsInt.cs_to_cap(env.rootdir)));
|
||||
if (env.workdir == undefined) env.workdir = env.rootdir;
|
||||
}
|
||||
}
|
||||
]);
|
||||
}
|
||||
|
||||
}],
|
||||
[['-exec','-e'],1,function(val) {
|
||||
if (!Io.exists(val)) {
|
||||
fail('file not found: '+val);
|
||||
} else {
|
||||
var file=Io.read_file(val);
|
||||
if (file==undefined) fail('can\'t read file '+val);
|
||||
var lines=String.split('\n',file);
|
||||
Array.concat(env.script,lines);
|
||||
}
|
||||
}]
|
||||
]);
|
||||
|
||||
var action=false;
|
||||
/**
|
||||
*
|
||||
* @type {undefined|hostserver}
|
||||
*/
|
||||
var hostsrv=undefined;
|
||||
if (options.hostport==undefined)
|
||||
hostsrv=HostSrv.HostServer(scheduler,rpc,options);
|
||||
|
||||
todo.push([
|
||||
function () {
|
||||
/*
|
||||
** Was the root DNS root already set?
|
||||
*/
|
||||
if (env.rootdir==undefined && hostsrv!=undefined) {
|
||||
action=true;
|
||||
/*
|
||||
** Get the DNS root from our embedded host server...
|
||||
*/
|
||||
Io.out('Using local host server DNS ..');
|
||||
env.rootdir = Cs.Copy.capset(hostsrv.rootcs);
|
||||
env.hostname = Net.Print.port(options.pubhostport);
|
||||
stat=Status.STD_OK;
|
||||
}
|
||||
},
|
||||
function () {
|
||||
if (action) {
|
||||
action=false;
|
||||
if (stat != Status.STD_OK) {
|
||||
Io.out('DNS_ROOT: failed for host ' +
|
||||
Net.Print.port(options.pubhostport) + ': ' +
|
||||
Status.print(stat));
|
||||
} else {
|
||||
if (env.workdir == undefined) env.workdir = env.rootdir;
|
||||
}
|
||||
}
|
||||
out('DNS ROOT: ' + Net.Print.capability(CsInt.cs_to_cap(env.rootdir)));
|
||||
},
|
||||
function () {
|
||||
if (env.rootdir != undefined) {
|
||||
DnsInt.dns_getdefafs(env.rootdir,function(_stat,_cap) {
|
||||
out('Default AFS: '+Status.print(_stat)+' is '+ Net.Print.capability(_cap));
|
||||
if (_stat==Status.STD_OK) {
|
||||
env.defafs=_cap;
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
function () {
|
||||
ash.dns.env.rootdir=env.rootdir;
|
||||
ash.dns.env.workdir=env.workdir;
|
||||
}
|
||||
]);
|
||||
|
||||
|
||||
var rl = readline.createInterface({
|
||||
input: process.stdin,
|
||||
output: process.stdout,
|
||||
completer : function (cmdline) {
|
||||
var args = Array.filter(String.split(' ', cmdline), function (str) {
|
||||
return str != '';
|
||||
});
|
||||
var completed=cmdline;
|
||||
var choices=[];
|
||||
var argi = 0;
|
||||
if (args.length>0) {
|
||||
if (String.equal(args[0],'cd') ||
|
||||
String.equal(args[0],'dir') ||
|
||||
String.equal(args[0],'del')) {
|
||||
choices=env.workrows;
|
||||
Array.iter(args,function (arg,index) {
|
||||
if (String.get(arg,0)!='-') argi=index;
|
||||
});
|
||||
if (args.length==1 || argi==0) {
|
||||
choices=env.workrows;
|
||||
if (choices.length==1) completed='';
|
||||
} else {
|
||||
var matches=Array.filter(choices,function (choice) {
|
||||
return (choice.indexOf(args[argi])!=-1);
|
||||
});
|
||||
completed = args[argi];
|
||||
choices = matches;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [choices,completed];
|
||||
}
|
||||
});
|
||||
|
||||
if (Array.empty(env.script))
|
||||
Io.stdout(
|
||||
' +------------------------------------------------+\n' +
|
||||
' | JASH ' + Printf.sprintf2(['v. ',['%7s',version],['%32s','']]) + '|\n'+
|
||||
' | JS Distributed Amoeba Virtual Machine Shell |\n' +
|
||||
' +------------------------------------------------+\n\n');
|
||||
|
||||
|
||||
|
||||
stat=Status.STD_OK;
|
||||
var cmdline='';
|
||||
var line;
|
||||
/*
|
||||
** Main interpreter loop
|
||||
*/
|
||||
Sch.ScheduleBlock([],function (e) {
|
||||
Io.out('[SHELL] uncaught exception:');
|
||||
if (typeof e != 'number') Io.printstack(e,'Shell.top');
|
||||
else Io.out(Status.print(e));
|
||||
process.exit(0);
|
||||
});
|
||||
|
||||
if (!options.servmode) {
|
||||
var context = Sch.GetCurrent();
|
||||
rl.on('line', function (line) {
|
||||
Sch.Wakeup(context);
|
||||
cmdline = line;
|
||||
});
|
||||
|
||||
rl.on('close', function () {
|
||||
Sch.Wakeup(context);
|
||||
stat = Status.STD_INTR;
|
||||
});
|
||||
Sch.ScheduleLoop(function () {
|
||||
return (stat == Status.STD_OK);
|
||||
}, [
|
||||
function () {
|
||||
if (!Array.empty(env.script)) {
|
||||
env.in_script = true;
|
||||
cmdline = Array.head(env.script);
|
||||
env.script = Array.tail(env.script);
|
||||
} else {
|
||||
Sch.Suspend();
|
||||
cmdline = '';
|
||||
rl.setPrompt(env.prompt());
|
||||
rl.prompt();
|
||||
}
|
||||
},
|
||||
function () {
|
||||
var path;
|
||||
if (stat != Status.STD_OK) throw stat;
|
||||
ash.exec(cmdline);
|
||||
}
|
||||
], [
|
||||
function () {
|
||||
if (!env.in_script) Io.out('\nHave a great day!');
|
||||
process.exit(0);
|
||||
}
|
||||
], function (e) {
|
||||
if (typeof e != 'number') {
|
||||
Io.out('[SHELL] uncaught exception:');
|
||||
Io.printstack(e);
|
||||
}
|
||||
else if (e != Status.STD_INTR) {
|
||||
Io.out('[SHELL] uncaught error:');
|
||||
Io.out(Status.print(e));
|
||||
}
|
||||
if (!env.in_script) Io.out('\nHave a great day!');
|
||||
process.exit(0);
|
||||
});
|
||||
}
|
||||
|
||||
ash.register_action('import',function (args) {
|
||||
var path;
|
||||
args=Array.tail(args);
|
||||
var len=args.length;
|
||||
Sch.ScheduleLoop(function(index) {
|
||||
path=args[index];
|
||||
return index<len;
|
||||
}, [
|
||||
function() {
|
||||
var file = Filename.basename(path);
|
||||
var data = Io.read_file(path);
|
||||
if (data!=undefined) {
|
||||
var size = data.length;
|
||||
var buf = Buf.Buffer();
|
||||
Buf.buf_of_str(buf, data);
|
||||
Io.out('Importing file ' + file + ' [' + size + '] ... ');
|
||||
ash.writefile(file, buf, function (stat, cap) {
|
||||
Io.out(Status.print(stat));
|
||||
});
|
||||
} else {
|
||||
Io.out(Status.print(Status.STD_IOERR));
|
||||
}
|
||||
}]);
|
||||
});
|
||||
|
||||
ash.register_action('export',function (args) {
|
||||
var file;
|
||||
var stat;
|
||||
var data,buf;
|
||||
args=Array.tail(args);
|
||||
var len=args.length;
|
||||
Sch.ScheduleLoop(function(index) {
|
||||
file=args[index];
|
||||
return index<len;
|
||||
}, [
|
||||
function() {
|
||||
Io.out('Exporting file ' + file + ' ... ');
|
||||
ash.readfile(file, function (_stat, _buf) {
|
||||
stat=_stat;
|
||||
buf=_buf;
|
||||
Io.out(Status.print(stat)+' '+buf.data.length);
|
||||
if (stat==Status.STD_OK)
|
||||
data = Buf.buf_to_str(buf);
|
||||
});
|
||||
},
|
||||
function () {
|
||||
if (stat==Status.STD_OK) {
|
||||
stat = Io.write_file(file,data);
|
||||
if (stat<=0) Io.out(Status.print(Status.STD_IOERR));
|
||||
}
|
||||
|
||||
}
|
||||
]);
|
||||
});
|
||||
|
||||
Sch.ScheduleBlock(Array.flatten(todo));
|
||||
|
||||
// Start up the network ..
|
||||
network.init(network.start);
|
||||
|
||||
scheduler.Run();
|
Loading…
Reference in New Issue
Block a user