get fork() and exec() working

This commit is contained in:
Lisa Milne 2023-11-21 19:08:33 +10:00
parent 05d29e37cf
commit dec325f8b2
2 changed files with 97 additions and 57 deletions

View file

@ -14,7 +14,13 @@ var clite = {
return true;
},
execSafeAsync:function(f) {
setTimeout(f,10);
try{
setTimeout(f,10);
} catch(e) {
clite.log.write(e.message);
return false;
}
return true;
},
load:{
script:function(name,callback) {
@ -349,6 +355,8 @@ clite.proc = {
}
function getProcIndex(pid) {
var index = -1;
if (pid < 0)
return data.procs.length-1;
data.procs.forEach(function(p,i) {
if (index > -1)
return;
@ -358,18 +366,30 @@ clite.proc = {
return index;
}
clite.proc.add = function(cl,fn) {
clite.proc.add = function(fn) {
if (typeof fn !== 'function')
return 0;
var proc = Object.create({
pid:data.nextid++,
command:cl,
func:fn
});
data.procs.push(proc);
vfsapi.mkFile('/proc/'+proc.pid);
var n = vfsapi.getNode('/proc/'+proc.pid);
n.data.content = 'command: '+proc.command+'\npid: '+proc.pid;
n.data.content = 'pid: '+proc.pid+'\n';
return proc.pid;
}
clite.proc.update = function(cl) {
var i = getProcIndex(-1);
if (i<0)
return false;
var proc = data.procs[i];
var n = vfsapi.getNode('/proc/'+proc.pid);
if (!n)
return false;
n.data.content += 'command: '+cl+'\n';
return true;
}
clite.proc.exit = function(pid) {
var i = getProcIndex(pid);
if (i<0)
@ -388,6 +408,7 @@ clite.proc = {
return true;
},
add:function(cl,fn) {return 0;},
update:function(cl) {return false;},
exit:function(id) {},
count:function() {return 0;}
};
@ -1267,7 +1288,8 @@ clite.shell = {
}
},
exit:function(pid,v) {
clite.proc.exit(pid);
if (pid > -1)
clite.proc.exit(pid);
if (clite.term.tty.data != null)
clite.term.api.closeTTY(clite.term.tty.data);
clite.shell.prompt.pop();
@ -1302,31 +1324,30 @@ clite.shell = {
var path = clite.shell.resolvePath(args[0]);
if (!path) {
clite.term.writeLine('Shell: unknown command: '+args[0]);
io.exit(-1);
return;
}
var fd = clite.io.open(path);
if (!fd) {
clite.term.writeLine('Shell: unknown command: '+args[0]);
io.exit(-1);
clite.shell.exit(-1,-1);
return;
}
var pid = clite.proc.add(args.join(' '),fd.node.data.content);
io.exit = function(v) {
clite.shell.exit(pid,v);
}
function execFunc(env,io) {
var r = clite.lib.exec(path,args,env,io);
if (r == 0)
return;
var r = clite.core.execSafe(function() {
var rr = fd.node.data.content(args,Object.create(clite.shell.env),io);
if (typeof rr == 'number')
io.exit(rr);
});
if (!r) {
clite.term.writeLine('Shell: error in command:'+args[0]);
io.exit(-1);
if (r == -1) {
clite.term.writeLine('Shell: unknown command: '+args[0]);
clite.shell.exit(-1,-2);
return;
}
if (r == -2) {
clite.term.writeLine('Shell: error in command:'+args[0]);
clite.shell.exit(-1,-3);
}
}
if (!clite.lib.fork(clite.shell.env,io,execFunc)) {
clite.term.writeLine('Shell: internal error');
clite.shell.exit(-1,-1);
}
clite.io.close(fd);
},
include:function(name) {
switch (name) {
@ -1729,17 +1750,8 @@ clite.lib = {
// TODO: resolve all paths passed as arguments? - catches ~ and * etc
return parts;
},
// returns an int identifier for the file type
getFileType:function(fd) {
// returns an int identifier for the file type:
// 0: unknown
// 1: text file
// 2: executable/binary (function)
// 3: directory
// 4: link
// 5: device
// 6: unloaded remote file
// 7: shell script
// 8: image
if (fd.node.data.content == null) {
if (fd.node.data.remote != null)
return clite.io.types.FT_REMOTE;
@ -1798,33 +1810,36 @@ clite.lib = {
});
return buff;
},
fork:function(io) {
},
exec:function(path,args,io) {
var fd = clite.io.open(path);
if (!fd) {
clite.term.writeLine('Shell: unknown command: '+args[0]);
io.exit(-1);
return false;
}
var pid = clite.proc.add(args.join(' '),fd.node.data.content);
fork:function(env,io,call) {
var pid = clite.proc.add(call);
if (!pid)
return 0;
io.exit = function(v) {
clite.shell.exit(pid,v);
}
clite.core.execSafeAsync(function() {
call(Object.create(env),io);
});
return pid;
},
exec:function(path,args,env,io) {
var fd = clite.io.open(path);
if (!fd)
return -1;
clite.proc.update(args.join(' '));
var r = clite.core.execSafe(function() {
var rr = fd.node.data.content(args,Object.create(clite.shell.env),io);
var rr = fd.node.data.content(args,env,io);
if (typeof rr == 'number')
io.exit(rr);
});
if (!r) {
clite.term.writeLine('Shell: error in command:'+args[0]);
io.exit(-2);
return false;
}
clite.io.close(fd);
return true;
if (!r) {
io.exit(-2);
return -2;
}
return 0;
}
}
clite.lib.api = { // this is passed to programs via include('stdlib')

View file

@ -158,11 +158,36 @@ stdlib: io.include('stdlib')
for passing to exec(), supports quotes and so on:
'ls -l /var' -> ['ls','-l','var']
fork()
work in progress
fork(env,io,call)
Creates a new process, with environment and io data passed to it.
Returns the pid of the new process, or 0 on failure.
call should be a function that accepts the env and io as
arguments, this is where the new process begins.
exec(path,args,io)
work in progress
function newProc(env,io) {
io.write('this is a new process!');
io.exit(0);
}
var pid = fork(env,io,newProc);
exec(path,args,env,io)
Executes a new program, replacing the current one.
Returns 0 on success, non-zero on failure.
Unlike typical unix exec(), this always returns. On success the
original program should do nothing more, including not exiting.
path is the fully resolved file path of the program to be
executed, such as '/bin/ls'.
args is the argument array created by passing a command line to
strToArgs, see above.
env and io, are the current environment and io data.
var command = "ls -l";
var args = stdlib.strToArgs(command);
var path = stdlib.resolvePath(args[0],'/bin');
var r = stdlib.exec(path,args,env,io);
if (r == 0)
return;
stdio: io.include('stdio')
Provides access to io functions and types for file access