diff --git a/clite/core.js b/clite/core.js index e079c4c..6857bf9 100644 --- a/clite/core.js +++ b/clite/core.js @@ -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') diff --git a/readme.txt b/readme.txt index 5ce58c7..5098cc9 100644 --- a/readme.txt +++ b/readme.txt @@ -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