mirror of
https://codeberg.org/TicklishHoneyBee/CLIte.git
synced 2026-03-11 09:04:37 +00:00
699 lines
14 KiB
JavaScript
699 lines
14 KiB
JavaScript
clite.commands.data = function() {
|
|
// insert commands below this line
|
|
|
|
clite.commands.load('help',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
if (args.length > 1) {
|
|
// TODO: implement command help lookup
|
|
stdio.printf('help with arguments is a work in progress');
|
|
}
|
|
stdio.printf(`
|
|
Welcome to CLIte (pronounced like 'site' with an added L).
|
|
|
|
Various unix-like commands are available for navigating the CLIte shell:
|
|
|
|
ls - list directory contents
|
|
cat - concatenate files and print to std output or local file
|
|
touch - create a new file
|
|
less - simple text file viewer
|
|
file - determines the file type
|
|
|
|
Under Development:
|
|
view - file viewer
|
|
edit - text file editor
|
|
|
|
Running any command with the argument -? will give you help for that program.
|
|
Or you can run help <command> to get the same info.
|
|
|
|
As a basic guide for guests:
|
|
Use ls to see what content is available, eg: ls web
|
|
Use view or less to view the content, eg: view web/about
|
|
|
|
`);
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('ls',function(args,env,io) {
|
|
var dirs = [];
|
|
var long = false;
|
|
var all = false;
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
function help() {
|
|
stdio.printf(`
|
|
ls - list directory contents
|
|
Usage: ls [OPTION] [FILE]
|
|
|
|
Options:
|
|
-? Print this help information
|
|
-l Display data in long format
|
|
-a Do not ignore entries starting with .
|
|
`);
|
|
}
|
|
|
|
function writeNodeData(st,fd) {
|
|
if (long) {
|
|
if (st.type == stdio.types.FT_LINK) {
|
|
var d = stdio.readAll(fd);
|
|
if (!d)
|
|
d = '?';
|
|
stdio.printf(st.perms+'\t'+st.uid+'\t'+st.gid+'\t'+st.name+' -> '+d);
|
|
}else{
|
|
stdio.printf(st.perms+'\t'+st.uid+'\t'+st.gid+'\t'+st.name);
|
|
}
|
|
}else{
|
|
stdio.printf(st.name);
|
|
}
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'l':
|
|
long = true;
|
|
break;
|
|
case 'a':
|
|
all = true;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
dirs.push(stdlib.resolvePath(args[i],false));
|
|
}
|
|
}
|
|
|
|
if (dirs.length < 1)
|
|
dirs.push(env.PWD);
|
|
|
|
dirs.forEach(function(dir,index) {
|
|
if (dirs.length > 1)
|
|
stdio.printf(dir+':');
|
|
var fd = stdio.open(dir,false);
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'cannot open directory: '+dir);
|
|
return;
|
|
}
|
|
var st = stdio.fstat(fd);
|
|
if (!st || st.type != stdio.types.FT_DIR) {
|
|
writeNodeData(st,fd);
|
|
stdio.close(fd);
|
|
return;
|
|
}
|
|
var e;
|
|
while ((e = stdio.read(fd)) != null) {
|
|
if (e[0] == '.' && !all)
|
|
continue;
|
|
var efd = stdio.open(dir+'/'+e,false,true);
|
|
if (!efd) {
|
|
stdio.write(io.stderr,'cannot read contents: '+dir);
|
|
break;
|
|
}
|
|
var est = stdio.fstat(efd);
|
|
if (!est) {
|
|
stdio.close(efd);
|
|
stdio.write(io.stderr,'cannot read content: '+dir);
|
|
break;
|
|
}
|
|
writeNodeData(est,efd);
|
|
stdio.close(efd);
|
|
}
|
|
stdio.close(fd);
|
|
});
|
|
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('cat',function(args,env,io) {
|
|
var files = [];
|
|
var download = false;
|
|
var remote = true;
|
|
var pending = 0;
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
cat - concatenate files and print to std output or local file
|
|
Usage: cat [OPTION] <FILE> [FILE]
|
|
|
|
Options:
|
|
-? Print this help information
|
|
-d Download the file data, instead of printing it
|
|
-l Only display files if remote data is loaded
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'd':
|
|
download = true;
|
|
break;
|
|
case 'l':
|
|
remote = false;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
files.push(stdlib.resolvePath(args[i],false));
|
|
}
|
|
}
|
|
|
|
if (files.length < 1)
|
|
return 1;
|
|
pending = files.length;
|
|
|
|
// check if we're on a webserver
|
|
if (!remote) {
|
|
var u = stdlib.uname();
|
|
if (u && u.nodename != 'localhost')
|
|
remote = true;
|
|
}
|
|
|
|
function fcb(fd) {
|
|
var st = stdio.fstat(fd);
|
|
// check if it's a directory or link
|
|
if (
|
|
!st
|
|
|| st.type == stdio.types.FT_DIR
|
|
|| st.type == stdio.types.FT_LINK
|
|
|| st.type == stdio.types.FT_BINARY
|
|
|| st.type == stdio.types.FT_UNKOWN
|
|
|| st.type == stdio.types.FT_IMAGE
|
|
) {
|
|
if (st) {
|
|
stdio.write(io.stderr,'not a normal file: '+st.name);
|
|
}else{
|
|
stdio.write(io.stderr,'not a normal file');
|
|
}
|
|
}else{
|
|
var d = stdio.readAll(fd);
|
|
if (d != null) {
|
|
if (download) {
|
|
var ld = stdio.open('/dev/local',false);
|
|
if (ld) {
|
|
stdio.write(ld,{name:st.name,data:d});
|
|
stdio.close(ld);
|
|
}else{
|
|
stdio.write(io.stderr,'can not write to local device');
|
|
}
|
|
}else{
|
|
stdio.printf(d);
|
|
}
|
|
}
|
|
}
|
|
pending--;
|
|
stdio.close(fd);
|
|
if (pending <1)
|
|
io.exit(0);
|
|
}
|
|
|
|
files.forEach(function(file,index) {
|
|
var st = stdio.stat(file);
|
|
// check if it's a directory or link
|
|
if (
|
|
!st
|
|
|| st.type == stdio.types.FT_DIR
|
|
|| st.type == stdio.types.FT_LINK
|
|
|| st.type == stdio.types.FT_BINARY
|
|
|| st.type == stdio.types.FT_UNKOWN
|
|
|| st.type == stdio.types.FT_IMAGE
|
|
) {
|
|
stdio.write(io.stderr,'not a normal file: '+file);
|
|
pending--;
|
|
return;
|
|
}
|
|
if (!remote && st.type == stdio.types.FT_REMOTE) {
|
|
pending--;
|
|
return;
|
|
}
|
|
var fd = stdio.open(file,fcb);
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'cannot open file: '+file);
|
|
pending--;
|
|
return;
|
|
}
|
|
});
|
|
|
|
if (pending <1)
|
|
return 0;
|
|
|
|
return null;
|
|
});
|
|
|
|
clite.commands.load('touch',function(args,env,io) {
|
|
var file = null;
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
function help() {
|
|
stdio.printf(`
|
|
touch - create a new empty file
|
|
Usage: touch [OPTION] <FILE>
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
file = stdlib.resolvePath(args[i],false);
|
|
}else{
|
|
stdio.write(io.stderr,'unknown argument: '+args[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.write(io.stderr,'no file specified');
|
|
return 1;
|
|
}
|
|
|
|
function loadRemote(fd) {
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'unable to create file: '+file);
|
|
io.exit(1);
|
|
return;
|
|
}
|
|
io.exit(0);
|
|
}
|
|
|
|
if (!stdio.creat(file)) {
|
|
var fd = stdio.open(file,loadRemote);
|
|
return null;
|
|
}
|
|
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('less',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
var term = io.include('term');
|
|
var file = null;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
less - text file viewer
|
|
Usage: less [OPTION] <FILE>
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
file = stdlib.resolvePath(args[i],false);
|
|
}else{
|
|
stdio.write(io.stderr,'unknown argument: '+args[i]);
|
|
}
|
|
}
|
|
|
|
var lines = [];
|
|
var topLine = 0;
|
|
var bottomLine = 0;
|
|
|
|
function showAt(line) {
|
|
var start = line;
|
|
var end = line+tty.lines;
|
|
if (end > lines.length)
|
|
end = lines.length;
|
|
tty.clear();
|
|
for (var i=start; i<end; i++) {
|
|
tty.draw(lines[i]+'\n');
|
|
}
|
|
}
|
|
|
|
function prepFile(fd) {
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'could not open file: '+file);
|
|
io.exit(1);
|
|
return;
|
|
}
|
|
var st = stdio.fstat(fd);
|
|
if ( !st || (st.type != stdio.types.FT_TEXT && st.type != stdio.types.FT_SCRIPT)) {
|
|
stdio.write(io.stderr,'can not read files of this type');
|
|
io.exit(1);
|
|
return;
|
|
}
|
|
var txt = stdio.readAll(fd);
|
|
stdio.close(fd);
|
|
|
|
var parts = txt.split('\n');
|
|
parts.forEach(function(line) {
|
|
if (line.length > tty.chars) {
|
|
var sects = line.match(new RegExp('(.{1,'+tty.chars+'})','g'));
|
|
lines.push.apply(lines,sects);
|
|
return;
|
|
}
|
|
lines.push(line);
|
|
});
|
|
|
|
bottomLine = (lines.length-tty.lines);
|
|
|
|
showAt(0);
|
|
}
|
|
|
|
var fd = null;
|
|
|
|
if (file == null) {
|
|
if (isatty(io.stdin)) {
|
|
stdio.write(io.stderr,'no file specified');
|
|
return 1;
|
|
}
|
|
fd = io.stdin;
|
|
}else{
|
|
fd = stdio.open(file,prepFile);
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'could not open file: '+file);
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
var tty = term.opentty();
|
|
tty.setRaw(false);
|
|
|
|
tty.handleKeys(function(e) {
|
|
switch (e.key) {
|
|
case 'Escape':
|
|
case 'q':
|
|
term.closetty(tty);
|
|
io.exit(0);
|
|
break;
|
|
case 'Up':
|
|
case 'ArrowUp':
|
|
if (topLine > 0) {
|
|
topLine--;
|
|
showAt(topLine);
|
|
}
|
|
break;
|
|
case 'Down':
|
|
case 'ArrowDown':
|
|
if (topLine < bottomLine) {
|
|
topLine++;
|
|
showAt(topLine);
|
|
}
|
|
break;
|
|
case 'PageUp':
|
|
if (topLine > 0) {
|
|
topLine -= tty.lines-1;
|
|
if (topLine < 0)
|
|
topLine = 0;
|
|
showAt(topLine);
|
|
}
|
|
break;
|
|
case 'PageDown':
|
|
if (topLine < bottomLine) {
|
|
topLine += tty.lines-1;
|
|
if (topLine >= bottomLine)
|
|
topLine = bottomLine;
|
|
showAt(topLine);
|
|
}
|
|
break;
|
|
case 'Home':
|
|
topLine = 0;
|
|
showAt(topLine);
|
|
break;
|
|
case 'End':
|
|
topLine = bottomLine;
|
|
showAt(topLine);
|
|
break;
|
|
}
|
|
});
|
|
tty.draw('Loading...');
|
|
|
|
return null;
|
|
});
|
|
|
|
clite.commands.load('view',function(args,env,io) {
|
|
stdio.printf('view is under development');
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('edit',function(args,env,io) {
|
|
stdio.printf('edit is under development');
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('file',function(args,env,io) {
|
|
var short = '';
|
|
var file = null;
|
|
var stdlib = io.include('stdlib');
|
|
var stdio = io.include('stdio');
|
|
function help() {
|
|
stdio.printf(`
|
|
file - determine type of FILE
|
|
Usage: touch [OPTION] [FILE]
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else if (file == null) {
|
|
short = args[i];
|
|
file = stdlib.resolvePath(args[i],false);
|
|
}else{
|
|
stdio.write(io.stderr,'unknown argument: '+args[i]);
|
|
}
|
|
}
|
|
|
|
if (file == null) {
|
|
stdio.write(io.stderr,'no file specified');
|
|
return 1;
|
|
}
|
|
|
|
var fd = stdio.open(file,false);
|
|
if (!fd) {
|
|
stdio.write(io.stderr,'cannot open file: '+file);
|
|
return 1;
|
|
}
|
|
|
|
var st = stdio.fstat(fd);
|
|
stdio.close(fd);
|
|
|
|
var txt = short+': ';
|
|
if (!st) {
|
|
txt += 'Unknown';
|
|
}else{
|
|
switch (st.type) {
|
|
case stdio.types.FT_TEXT:
|
|
txt += 'Plain Text';
|
|
break;
|
|
case stdio.types.FT_BINARY:
|
|
txt += 'CLIte Executable';
|
|
break;
|
|
case stdio.types.FT_DIR:
|
|
txt += 'Directory';
|
|
break;
|
|
case stdio.types.FT_LINK:
|
|
txt += 'Link';
|
|
break;
|
|
case stdio.types.FT_DEV:
|
|
txt += 'Device File';
|
|
break;
|
|
case stdio.types.FT_REMOTE:
|
|
txt += 'Unloaded Remote Data';
|
|
break;
|
|
case stdio.types.FT_SCRIPT:
|
|
txt += 'Shell Script';
|
|
break;
|
|
case stdio.types.FT_IMAGE:
|
|
txt += 'Image';
|
|
break;
|
|
default:
|
|
txt += 'Unknown Data';
|
|
break;
|
|
}
|
|
}
|
|
|
|
stdio.printf(txt);
|
|
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('reboot',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
function help() {
|
|
stdio.printf(`
|
|
reboot - reboot the system, forcing reload of all code
|
|
|
|
Options:
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
stdio.write(io.stderr,'unknown argument: '+args[i]);
|
|
}
|
|
}
|
|
|
|
var fd = stdio.open('/dev/initctl',false);
|
|
if (!fd)
|
|
return 1;
|
|
stdio.write(fd,'6'); // switch to runlevel 6, reboot
|
|
stdio.close(fd);
|
|
|
|
return 0;
|
|
});
|
|
|
|
clite.commands.load('uname',function(args,env,io) {
|
|
var stdlib = io.include('stdlib');
|
|
var sysname = false;
|
|
var nodename = false;
|
|
var release = false;
|
|
var version = false;
|
|
var machine = false;
|
|
|
|
function help() {
|
|
stdio.printf(`
|
|
uname - print system information
|
|
|
|
Options:
|
|
-a All, equivalent to -mnrsv
|
|
-m Print the hardware info (User Agent)
|
|
-n Print the network name
|
|
-r Print the operating system release
|
|
-s Print the operating system name
|
|
-v Print the operating system version
|
|
-? Print this help information
|
|
`);
|
|
}
|
|
|
|
for (var i=1; i<args.length; i++) {
|
|
if (args[i][0] == '-') {
|
|
for (var j=1; j<args[i].length; j++) {
|
|
switch (args[i][j]) {
|
|
case '?':
|
|
help();
|
|
return 0;
|
|
break;
|
|
case 'a':
|
|
machine = true;
|
|
nodename = true;
|
|
release = true;
|
|
sysname = true;
|
|
version = true;
|
|
break;
|
|
case 'm':
|
|
machine = true;
|
|
break;
|
|
case 'n':
|
|
nodename = true;
|
|
break;
|
|
case 'r':
|
|
release = true;
|
|
break;
|
|
case 's':
|
|
sysname = true;
|
|
break;
|
|
case 'v':
|
|
version = true;
|
|
break;
|
|
default:
|
|
stdio.write(io.stderr,'unknown argument: -'+args[i][j]);
|
|
}
|
|
}
|
|
}else{
|
|
stdio.write(io.stderr,'unknown argument: '+args[i]);
|
|
}
|
|
}
|
|
|
|
if (!machine && !nodename && !release && !sysname && !version)
|
|
sysname = true;
|
|
|
|
var ut = stdlib.uname();
|
|
|
|
var txt = '';
|
|
if (sysname)
|
|
txt += ut.sysname+' ';
|
|
if (nodename)
|
|
txt += ut.nodename+' ';
|
|
if (release)
|
|
txt += ut.release+' ';
|
|
if (version)
|
|
txt += ut.version+' ';
|
|
if (machine)
|
|
txt += ut.machine;
|
|
|
|
stdio.printf(txt);
|
|
|
|
return 0;
|
|
});
|
|
|
|
if (window.location.protocol == 'file:')
|
|
clite.commands.load('test',function(args,env,io) {
|
|
var stdio = io.include('stdio');
|
|
stdio.printf('Hello world');
|
|
function rcb(data) {
|
|
stdio.printf(data);
|
|
io.exit(0);
|
|
}
|
|
|
|
stdio.read(io.stdin,rcb);
|
|
|
|
return null;
|
|
});
|
|
|
|
// insert commands above this line
|
|
}
|