From 39ebcdc04974c0634c0f57e8ad534d6d6b2729d4 Mon Sep 17 00:00:00 2001 From: Lisa Milne Date: Sun, 26 Nov 2023 14:24:37 +1000 Subject: [PATCH] wait, waitpid, waitall, and get the shell using them --- clite/commands.js | 6 +- clite/core.js | 139 +++++++++++++++++++++++++++++++++++++++++----- clite/shell.js | 5 +- 3 files changed, 134 insertions(+), 16 deletions(-) diff --git a/clite/commands.js b/clite/commands.js index c12c027..35ca466 100644 --- a/clite/commands.js +++ b/clite/commands.js @@ -173,7 +173,7 @@ Options: // check if we're on a webserver if (!remote) { var u = stdlib.uname(); - if (u && u.hostname != 'localhost') + if (u && u.nodename != 'localhost') remote = true; } @@ -230,8 +230,10 @@ Options: pending--; return; } - if (!remote && st.type == stdio.types.FT_REMOTE) + 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); diff --git a/clite/core.js b/clite/core.js index ebff4c0..d47fb86 100644 --- a/clite/core.js +++ b/clite/core.js @@ -8,7 +8,7 @@ var clite = { try{ f(); } catch(e) { - clite.log.write(e.message); + clite.log.write(e.message+':'+e.lineNumber); return false; } return true; @@ -17,7 +17,7 @@ var clite = { try{ setTimeout(f,10); } catch(e) { - clite.log.write(e.message); + clite.log.write(e.message+':'+e.lineNumber); return false; } return true; @@ -409,6 +409,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; // should really have init/getty exec the shell with the env data etc var env = clite.user.getEnv(); var io = { + pid:0, stdin:clite.io.open('/dev/tty',false), stdout:clite.io.open('/dev/tty',false), stderr:clite.io.open('/dev/tty',false), @@ -433,7 +434,8 @@ clite.proc = { var vfsapi = vfs; var data = { nextid:1, - procs:[] + procs:[], + groups:[] }; function getProc(pid) { @@ -458,13 +460,58 @@ clite.proc = { }); return index; } + function mapCPID(cpid) { + //clite.log.write('mapCPID('+cpid+') -> '+data.groups.length); + if (data.groups.length < 1) { + addGroup(1); + return 1; + } + var parent = getProc(cpid); + if (parent && parent.gpid != cpid) + return parent.gpid; + return cpid; + } + function getGroup(cpid) { + for (var i=0; i 0) + return true; + group.waitAll.forEach(function(w) { + w(pid); + }); + return true; + } - clite.proc.add = function(fn) { + clite.proc.add = function(cpid,fn) { if (typeof fn !== 'function') return 0; var proc = Object.create({ + gpid:mapCPID(cpid), pid:data.nextid++, - func:fn + func:fn, + waits:[] }); data.procs.push(proc); vfsapi.mkFile('/proc/'+proc.pid); @@ -492,11 +539,56 @@ clite.proc = { return false; data.procs.splice(i,1); vfsapi.remove('/proc/'+pid); + proc.waits.forEach(function(w) { + clite.core.execSafeAsync(function() {w(pid)}); + }); + exitGroup(proc.gpid,pid); return true; } clite.proc.count = function() { return data.procs.length; } + clite.proc.addWait = function(pid,w) { + var proc = getProc(pid); + if (!proc) { + clite.core.execSafeAsync(function() {w(pid)}); + return false; + } + proc.waits.push(w); + return true; + } + clite.proc.addWaitGroupAny = function(pid,w) { + var cpid = mapCPID(pid); + var group = getGroup(cpid); + if (!group) { + clite.core.execSafeAsync(function() {w(pid)}); + return true; + } + group.waitAny.push(w); + return true; + } + clite.proc.addWaitGroupAll = function(pid,w) { + var cpid = mapCPID(pid); + var group = getGroup(cpid); + if (!group) { + clite.core.execSafeAsync(function() {w(pid)}); + return false; + } + group.waitAll.push(w); + return true; + } + clite.proc.addGroup = function(pid) { + var proc = getProc(pid); + if (!proc) + return false; + if (proc.gpid == pid) + return true; + proc.gpid = pid; + if (getGroup(pid)) + return true; + addGroup(pid); + return true; + } clite.proc.init = null; return true; }, @@ -1273,12 +1365,6 @@ clite.term = { return; f.parentNode.removeChild(f); }, - hasInput:function() { - var f = document.getElementById('form'); - if (!f) - return false; - return true; - }, writeLine:function(txt) { var a = document.createElement('article'); a.innerHTML = clite.lib.htmlEncode(txt); @@ -1286,6 +1372,8 @@ clite.term = { if (!t) return; t.appendChild(a); + if (document.getElementById('form')) + clite.term.genForm(); t.scrollTop = t.scrollHeight; }, genForm:function() { @@ -1640,10 +1728,11 @@ clite.lib = { return o; }, fork:function(env,io,call) { - var pid = clite.proc.add(call); + var pid = clite.proc.add(io.pid,call); if (!pid) return 0; var nio = Object.create(io); + nio.pid = pid; nio.exit = function(v) { clite.lib.exit(pid,v); try{ @@ -1653,7 +1742,17 @@ clite.lib = { nio.include = function(name) { switch (name) { case 'stdlib': - return Object.create(clite.lib.api); + 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); @@ -1707,6 +1806,20 @@ clite.lib = { }, 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') diff --git a/clite/shell.js b/clite/shell.js index 097e303..3446408 100644 --- a/clite/shell.js +++ b/clite/shell.js @@ -188,6 +188,7 @@ clite.commands.load('sh',function(args,env,io) { // prepare io (stdin,stdout,stderr) // TODO: check for io redirects and piping, then setup stdio accordingly var fio = { + pid:io.pid, stdin:io.stdin, stdout:io.stdout, stderr:io.stderr, @@ -303,7 +304,9 @@ clite.commands.load('sh',function(args,env,io) { } } - inputRead(); + // TODO: something something waitall() + stdlib.waitall(inputRead); + //inputRead(); return null; });