move libraries to actual libraries (/lib/lib*.so)

This commit is contained in:
Lisa Milne 2023-11-27 19:01:52 +10:00
parent ccbb4fa408
commit 1f2c8d85f3
7 changed files with 439 additions and 237 deletions

View file

@ -39,6 +39,7 @@ clite.commands.load('ls',function(args,env,io) {
var all = false;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var clite = io.include('clite');
function help() {
stdio.printf(`
ls - list directory contents
@ -85,7 +86,7 @@ Options:
}
}
}else{
dirs.push(stdlib.resolvePath(args[i],false));
dirs.push(clite.resolvePath(args[i],false));
}
}
@ -137,6 +138,7 @@ clite.commands.load('cat',function(args,env,io) {
var pending = 0;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var clite = io.include('clite');
function help() {
stdio.printf(`
@ -169,7 +171,7 @@ Options:
}
}
}else{
files.push(stdlib.resolvePath(args[i],false));
files.push(clite.resolvePath(args[i],false));
}
}
@ -259,6 +261,7 @@ clite.commands.load('touch',function(args,env,io) {
var file = null;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var clite = io.include('clite');
function help() {
stdio.printf(`
touch - create a new empty file
@ -282,7 +285,7 @@ Options:
}
}
}else if (file == null) {
file = stdlib.resolvePath(args[i],false);
file = clite.resolvePath(args[i],false);
}else{
stdio.write(io.stderr,'unknown argument: '+args[i]);
}
@ -314,6 +317,7 @@ clite.commands.load('less',function(args,env,io) {
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var term = io.include('term');
var clite = io.include('clite');
var file = null;
function help() {
@ -339,7 +343,7 @@ Options:
}
}
}else if (file == null) {
file = stdlib.resolvePath(args[i],false);
file = clite.resolvePath(args[i],false);
}else{
stdio.write(io.stderr,'unknown argument: '+args[i]);
}
@ -476,6 +480,7 @@ clite.commands.load('file',function(args,env,io) {
var file = null;
var stdlib = io.include('stdlib');
var stdio = io.include('stdio');
var clite = io.include('clite');
function help() {
stdio.printf(`
file - determine type of FILE
@ -500,7 +505,7 @@ Options:
}
}else if (file == null) {
short = args[i];
file = stdlib.resolvePath(args[i],false);
file = clite.resolvePath(args[i],false);
}else{
stdio.write(io.stderr,'unknown argument: '+args[i]);
}
@ -598,6 +603,7 @@ Options:
});
clite.commands.load('uname',function(args,env,io) {
var stdio = io.include('stdio');
var stdlib = io.include('stdlib');
var sysname = false;
var nodename = false;

View file

@ -372,7 +372,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
var f = vfsapi.getNode('/bin/'+name);
if (!f)
return;
f.perms = '-r-xr-xr-x';
f.perms = '-rwxr-xr-x';
f.data.content = fn;
vfsapi.mkFile('/usr/src/'+name+'.js');
f = vfsapi.getNode('/usr/src/'+name+'.js');
@ -391,6 +391,48 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
function init4(data) {
clite.core.execSafe(clite.commands.data);
clite.commands = null;
clite.log.write('Populating /lib');
clite.libs = {
index:[],
data:null,
load:function(name,header,fn) {
vfsapi.mkFile('/lib/'+name+'.so');
var f = vfsapi.getNode('/lib/'+name+'.so');
if (!f)
return;
f.perms = '-rw-r--r--';
f.data.content = fn;
vfsapi.mkFile('/usr/src/libs/'+name+'.js');
f = vfsapi.getNode('/usr/src/libs/'+name+'.js');
if (!f)
return;
f.perms = '-rw-rw-r--';
f.data.content = 'function init'+fn.toString().substring(8);
clite.libs.index.push({header:header,file:name});
}
}
clite.core.load.script('clite/libstd.js',init5);
}
function init5(data) {
clite.core.execSafe(clite.libs.data);
clite.core.load.script('clite/libclite.js',init6);
}
function init6(data) {
clite.core.execSafe(clite.libs.data);
clite.core.load.script('clite/libstdio.js',init7);
}
function init7(data) {
clite.core.execSafe(clite.libs.data);
clite.core.load.script('clite/libterm.js',init8);
}
function init8(data) {
clite.core.execSafe(clite.libs.data);
clite.libs.data = null;
clite.libs.load = null;
clite.log.write('Bringing up the process manager');
if (!clite.proc.init(vfsapi)) {
clite.log.write('failed');
@ -421,10 +463,10 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`;
exit:null, // filled in by fork()
include:null, // filled in by fork()
};
clite.lib.fork(env,io,init5);
clite.lib.fork(env,io,init9);
}
}
function init5(env,io) {
function init9(env,io) {
clite.lib.exec('/bin/sh',['sh'],env,io);
}
@ -495,6 +537,7 @@ clite.proc = {
group.waitAny.forEach(function(w) {
w(pid);
});
group.waitAny = [];
var c = 0;
data.procs.forEach(function(p) {
// we want a count of child processes, so ignore the controlling process
@ -506,6 +549,7 @@ clite.proc = {
group.waitAll.forEach(function(w) {
w(pid);
});
group.waitAll = [];
return true;
}
@ -1034,7 +1078,7 @@ clite.io = {
clite.io.isatty = function(fd) {
return fd.node.data.istty;
}
clite.io.fprintf = function(fd,fmt) {
clite.io.vfprintf = function(fd,fmt,args) {
// TODO: actually support formatting
return clite.io.write(fd,fmt);
}
@ -1076,7 +1120,7 @@ clite.io = {
chmod:null,
fchmod:null,
isatty:null,
fprintf:null
vfprintf:null
};
clite.vfs = {
@ -1267,6 +1311,7 @@ clite.vfs = {
vfsdata.api.mkDir('/bin');
vfsdata.api.mkDir('/dev');
vfsdata.api.mkDir('/etc');
vfsdata.api.mkDir('/lib');
vfsdata.api.mkDir('/proc');
vfsdata.api.mkDir('/usr');
vfsdata.api.mkDir('/usr/clite');
@ -1275,6 +1320,7 @@ clite.vfs = {
vfsdata.api.mkDir('/usr/share');
vfsdata.api.mkDir('/usr/share/site');
vfsdata.api.mkDir('/usr/src');
vfsdata.api.mkDir('/usr/src/libs');
vfsdata.api.mkDir('/var');
vfsdata.api.mkFile('/var/logs');
@ -1433,41 +1479,37 @@ clite.term = {
return clite.term.data.type.type;
return 'text';
},
api:{
// clears the terminal
clear:function() {
clite.term.clear();
},
ttyctrl:function(fn,v) {
switch (fn) {
case 'iget': // returns the current input string - bypassing tty read
try{
return clite.term.data.buff;
} catch(err) {
return '';
}
break;
case 'iset': // sets the current input string
try{
if (typeof v !== 'string')
v = '';
clite.term.data.field.value = v;
clite.term.data.buff = v;
return true;
} catch(err) {
return false;
}
break;
case 'prompt': // sets the prompt for input
ttyctrl:function(fn,v) {
switch (fn) {
case 'iget': // returns the current input string - bypassing tty read
try{
return clite.term.data.buff;
} catch(err) {
return '';
}
break;
case 'iset': // sets the current input string
try{
if (typeof v !== 'string')
v = '';
clite.term.data.prompt = v;
clite.term.data.field.value = v;
clite.term.data.buff = v;
return true;
break;
default:
} catch(err) {
return false;
}
},
break;
case 'prompt': // sets the prompt for input
if (typeof v !== 'string')
v = '';
clite.term.data.prompt = v;
return true;
break;
default:
return false;
}
},
api:{
// gets an empty element with key events (allows view/less to display content in a clean element)
opentty:function() {
var tty = {
@ -1557,101 +1599,6 @@ clite.lib = {
parts.pop();
return parts.join('/');
},
// returns an absolute path: ('foo','/etc') -> '/etc/foo': ('foo','bar') -> $PWD/bar/foo
resolvePath:function(txt,base) {
if (txt == '/')
return txt;
var env = clite.user.getEnv();
if (txt[0] == '~') {
txt = env.HOME+txt.substring(1);
}
var path = txt;
if (txt[0] != '/') {
if (typeof base != 'string')
base = env.PWD;
if (base[0] != '/')
base = env.PWD+'/'+base;
path = base+'/'+txt;
}
var parts = path.split('/');
path = '';
var i;
while ((i = parts.indexOf('.')) != -1) {
parts.splice(i,1);
}
while ((i = parts.indexOf('')) != -1) {
parts.splice(i,1);
}
while ((i = parts.indexOf('..')) != -1) {
parts.splice(i-1,2);
}
path = '/'+parts.join('/');
return path;
},
// convert a string into an argument array: 'ls /etc' -> ['ls','/etc'], supports "quoted arguments" and `command substitutions`
strToArgs:function(txt) {
var parts = [];
var sp = '';
var s = '';
var e = false;
var q = false;
var c = false;
for (var i=0; i<txt.length; i++) {
switch (txt[i]) {
case '//':
if (e) {
s+='//';
}else{
e = true;
}
break;
case '`':
if (!e) {
if (!c) {
c = true;
s += '`';
}else{
s += '`';
c = false;
}
}else{
s += txt[i];
e = false;
}
break;
case '"':
case "'":
if (!e) {
if (!q) {
sp = txt[i];
q = true;
}else if (txt[i] == sp) {
sp = '';
q = false;
}
}else{
s += txt[i];
e = false;
}
break;
case ' ':
if (!q && !c) {
parts.push(s);
s = '';
e = false;
q = false;
break;
}
default:
s+=txt[i];
e = false;
}
}
if (s.length > 0)
parts.push(s);
// TODO: resolve all paths passed as arguments? - catches ~ and * etc
return parts;
},
// returns an int identifier for the file type
getFileType:function(fd) {
if (fd.node.data.content == null) {
@ -1690,42 +1637,6 @@ clite.lib = {
}
return clite.io.types.FT_UNKOWN;
},
getBuffer:function() {
var buff = Object.create({
buffer:{
data:'',
pos:0
},
read:function() {
if (this.buffer.pos >= this.buffer.data.length)
return null;
var b = this.data.buffer.substring(this.buffer.pos,this.buffer.data.length-this.buffer.pos);
var i = b.indexOf('\n');
if (b < 0)
return b;
this.buffer.pos += i;
return b.substring(0,i);
},
write:function(txt) {
this.buffer.data += txt;
}
});
return buff;
},
uname:function() {
var o = Object.create({
sysname:'CLIte',
nodename:'localhost',
release:clite.state.version,
version:clite.state.version,
machine:navigator.userAgent
});
if (window.location.protocol != 'file:')
o.nodename = window.location.hostname;
return o;
},
fork:function(env,io,call) {
var pid = clite.proc.add(io.pid,call);
if (!pid)
@ -1738,36 +1649,27 @@ clite.lib = {
io.exit(pid,v);
} catch(err) {}
}
// this is esssentially the dynamic linker
nio.include = function(name) {
switch (name) {
case 'stdlib':
var stdlib = Object.create(clite.lib.api);
stdlib.wait = function(cb) {
return clite.lib.wait(nio.pid,cb);
}
stdlib.waitpid = function(pid,cb) {
return clite.lib.waitpid(nio.pid,pid,cb);
}
stdlib.waitall = function(cb) {
return clite.lib.waitall(nio.pid,cb);
}
return stdlib;
break;
case 'stdio':
var stdio = Object.create(clite.io);
stdio.printf = function(fmt) {
// TODO: pass arguments through
return stdio.fprintf(nio.stdout,fmt);
}
return stdio;
break;
case 'term':
return Object.create(clite.term.api);
break;
default:
var file = '';
clite.libs.index.forEach(function(e) {
if (e.header == name)
file = e.file;
});
if (file == '')
return null;
break;
}
var fd = clite.io.open('/lib/'+file+'.so',false);
if (!fd)
return null;
var lib = null;
try{
lib = fd.node.data.content(nio,env);
}catch(err) {}
clite.io.close(fd);
if (lib)
return lib;
return null;
}
clite.core.execSafeAsync(function() {
@ -1780,6 +1682,11 @@ clite.lib = {
if (!fd)
return -1;
if (!fd.canexec) {
clite.io.close(fd);
return -3
}
clite.proc.update(args.join(' '));
var r = clite.core.execSafe(function() {
@ -1799,36 +1706,5 @@ clite.lib = {
clite.proc.exit(pid);
if (clite.term.tty.data != null)
clite.term.api.closetty(clite.term.tty.data);
},
getuid:function() {
return clite.user.getUID();
},
getgid:function() {
return clite.user.getGID();
},
// wait for any child process to exit
wait:function(cpid,cb) {
return clite.proc.addWaitGroupAny(cpid,cb);
},
// wait for the process 'pid' to exit
waitpid:function(cpid,pid,cb) {
if (pid < 0)
return clite.lib.wait(cpid,cb);
return clite.proc.addWait(pid,cb);
},
// wait for all child processes to exit
waitall:function(cpid,cb) {
return clite.proc.addWaitGroupAll(cpid,cb);
}
}
clite.lib.api = { // this is passed to programs via include('stdlib')
basename:clite.lib.basename,
dirname:clite.lib.dirname,
resolvePath:clite.lib.resolvePath,
strToArgs:clite.lib.strToArgs,
uname:clite.lib.uname,
fork:clite.lib.fork,
exec:clite.lib.exec,
getuid:clite.lib.getuid,
getgid:clite.lib.getgid
};

107
clite/libclite.js Normal file
View file

@ -0,0 +1,107 @@
clite.libs.data = function() {
clite.libs.load('libclite','clite',function(io,env) {
return Object.create({
// returns an absolute path: ('foo','/etc') -> '/etc/foo': ('foo','bar') -> $PWD/bar/foo
resolvePath:function(txt,base) {
if (txt == '/')
return txt;
var env = clite.user.getEnv();
if (txt[0] == '~') {
txt = env.HOME+txt.substring(1);
}
var path = txt;
if (txt[0] != '/') {
if (typeof base != 'string')
base = env.PWD;
if (base[0] != '/')
base = env.PWD+'/'+base;
path = base+'/'+txt;
}
var parts = path.split('/');
path = '';
var i;
while ((i = parts.indexOf('.')) != -1) {
parts.splice(i,1);
}
while ((i = parts.indexOf('')) != -1) {
parts.splice(i,1);
}
while ((i = parts.indexOf('..')) != -1) {
parts.splice(i-1,2);
}
path = '/'+parts.join('/');
return path;
},
// convert a string into an argument array: 'ls /etc' -> ['ls','/etc'], supports "quoted arguments" and `command substitutions`
strToArgs:function(txt) {
var parts = [];
var sp = '';
var s = '';
var e = false;
var q = false;
var c = false;
for (var i=0; i<txt.length; i++) {
switch (txt[i]) {
case '//':
if (e) {
s+='//';
}else{
e = true;
}
break;
case '`':
if (!e) {
if (!c) {
c = true;
s += '`';
}else{
s += '`';
c = false;
}
}else{
s += txt[i];
e = false;
}
break;
case '"':
case "'":
if (!e) {
if (!q) {
sp = txt[i];
q = true;
}else if (txt[i] == sp) {
sp = '';
q = false;
}
}else{
s += txt[i];
e = false;
}
break;
case ' ':
if (!q && !c) {
parts.push(s);
s = '';
e = false;
q = false;
break;
}
default:
s+=txt[i];
e = false;
}
}
if (s.length > 0)
parts.push(s);
// TODO: resolve all paths passed as arguments? - catches ~ and * etc
return parts;
}
});
});
}

77
clite/libstd.js Normal file
View file

@ -0,0 +1,77 @@
clite.libs.data = function() {
clite.libs.load('libstd','stdlib',function(io,env) {
return Object.create({
// returns the file name of a path /tmp/test/foo = foo
basename:function(txt) {
var parts = txt.split('/');
return parts[parts.length-1];
},
// returns the directory name of a path /tmp/test/foo = /tmp/test
dirname:function(txt) {
var parts = txt.split('/');
parts.pop();
return parts.join('/');
},
// returns system info
uname:function() {
return Object.create({
sysname:'CLIte',
nodename:clite.core.hostname(),
release:clite.state.version,
version:clite.state.version,
machine:navigator.userAgent
});
},
// creates a new process
fork:function(env,io,call) {
return clite.lib.fork(env,io,call);
},
// executes a new program, replacing the current one
exec:function(path,args,env,io) {
return clite.lib.exec(path,args,env,io);
},
// exits the current program
exit:function(pid,v) {
io.exit(pid,v);
},
// returns the current user id
getuid:function() {
return clite.user.getUID();
},
// returns the current group id
getgid:function() {
return clite.user.getGID();
},
// wait for any child process to exit
wait:function(cb) {
return clite.proc.addWaitGroupAny(io.pid,cb);
},
// wait for the process 'pid' to exit
waitpid:function(pid,cb) {
if (pid < 0)
return clite.proc.addWaitGroupAny(io.pid,cb);
return clite.proc.addWait(pid,cb);
},
// wait for all child processes to exit
waitall:function(cb) {
return clite.proc.addWaitGroupAll(io.pid,cb);
}
});
});
}

96
clite/libstdio.js Normal file
View file

@ -0,0 +1,96 @@
clite.libs.data = function() {
clite.libs.load('libio','stdio',function(io,env) {
return Object.create({
types:clite.io.types,
creat:function(path,type) {
return clite.io.creat(path,type);
},
open:function(path,cb,open_link) {
return clite.io.open(path,cb,open_link);
},
close:function(fd) {
return clite.io.close(fd);
},
read:function(fd,cb) {
return clite.io.read(fd,cb);
},
readLine:function(fd,cb) {
return clite.io.readLine(fd,cb);
},
readAll:function(fd) {
return clite.io.readAll(fd);
},
write:function(fd,data) {
return clite.io.write(fd,data);
},
ftruncate:function(fd,len) {
return clite.io.ftruncate(fd,len);
},
truncate:function(path,len) {
return clite.io.truncate(path,len);
},
seek:function(fd,pos) {
return clite.io.seek(fd,pos);
},
remove:function(path) {
return clite.io.remove(path);
},
link:function(path,target) {
return clite.io.link(path,target);
},
stat:function(path) {
return clite.io.stat(path);
},
fstat:function(fd) {
return clite.io.fstat(fd);
},
chmod:function(path,mode) {
return clite.io.chmod(path,mode);
},
fchmod:function(fd,mode) {
return clite.io.fchmod(fd,mode);
},
isatty:function(fd) {
return clite.io.isatty(fd);
},
vfprintf:function(fd,fmt,args) {
return clite.io.vfprintf(fd,fmt,args);
},
fprintf:function(fd,fmt) {
var args = [];
return clite.io.vfprintf(fd,fmt,args);
},
printf:function(fmt) {
var args = [];
return clite.io.vfprintf(io.stdout,fmt,args);
}
});
});
}

26
clite/libterm.js Normal file
View file

@ -0,0 +1,26 @@
clite.libs.data = function() {
clite.libs.load('libterm','term',function(io,env) {
return Object.create({
// clears the terminal
clear:function() {
clite.term.clear();
},
ttyctrl:function(fn,v) {
return clite.term.ttyctrl(fn,v);
},
// gets an empty element with key events (allows view/less to display content in a clean element)
opentty:function() {
return clite.term.api.opentty();
},
closetty:function(tty) {
return clite.term.api.closetty(tty);
}
});
});
}

View file

@ -5,6 +5,7 @@ clite.commands.load('sh',function(args,env,io) {
var stdio = io.include('stdio');
var stdlib = io.include('stdlib');
var term = io.include('term');
var clite = io.include('clite');
var active_pid = 0;
var prompt = '$ ';
var macro = {
@ -14,7 +15,7 @@ clite.commands.load('sh',function(args,env,io) {
cd:function(args,io) {
var dir = env.HOME;
if (args.length > 1) {
dir = stdlib.resolvePath(args[1]);
dir = clite.resolvePath(args[1]);
}
var fd = stdio.open(dir,false);
if (!fd) {
@ -99,7 +100,7 @@ clite.commands.load('sh',function(args,env,io) {
term.ttyctrl('iset',history.getCurrent());
},
down:function() {
if (history.index == history.data.length)
if (history.index >= history.data.length)
return;
history.index++;
term.ttyctrl('iset',history.getCurrent());
@ -108,13 +109,18 @@ clite.commands.load('sh',function(args,env,io) {
history.current = txt;
},
getCurrent:function() {
if (history.index == history.data.length)
if (history.index >= history.data.length)
return history.current;
return history.data[history.index];
},
resetCurrent:function() {
history.current = '';
history.index = history.data.length;
},
clear:function() {
history.data = [];
history.current = '';
history.index = 0;
}
}
@ -132,7 +138,7 @@ clite.commands.load('sh',function(args,env,io) {
paths.forEach(function(p) {
if (path)
return;
var rp = stdlib.resolvePath(txt,p);
var rp = clite.resolvePath(txt,p);
var fd = stdio.open(rp,false);
if (fd) {
stdio.close(fd);
@ -197,7 +203,7 @@ clite.commands.load('sh',function(args,env,io) {
function tabfill() {
var c = term.ttyctrl('iget');
var parts = stdlib.strToArgs(c);
var parts = clite.strToArgs(c);
var ai = parts.length-1;
if (ai < 0)
return;
@ -258,7 +264,7 @@ clite.commands.load('sh',function(args,env,io) {
// clear the tty prompt
term.ttyctrl('prompt','');
// split command line into arguments
var args = stdlib.strToArgs(txt);
var args = clite.strToArgs(txt);
args.forEach(function(val,i) {
args[i] = preprocess(val);
});
@ -303,6 +309,11 @@ clite.commands.load('sh',function(args,env,io) {
stdio.write(io.stderr,'Shell: error in command:'+args[0]);
io.exit(-1);
}
if (r == -3) {
stdio.write(io.stderr,'Shell: not an executable file:'+args[0]);
io.exit(-3);
}
}
active_pid = stdlib.fork(env,fio,execFunc);
if (active_pid == 0) {
@ -375,7 +386,10 @@ clite.commands.load('sh',function(args,env,io) {
}
}
stdlib.waitall(inputRead);
stdlib.waitall(function() {
history.clear();
inputRead();
});
return null;
});