mirror of
https://codeberg.org/TicklishHoneyBee/CLIte.git
synced 2026-03-11 09:04:37 +00:00
shell piping and io redirects
This commit is contained in:
parent
55b557be42
commit
9ec6e0e26a
7 changed files with 473 additions and 121 deletions
|
|
@ -445,6 +445,10 @@ Options:
|
|||
return 1;
|
||||
}
|
||||
fd = io.stdin;
|
||||
io.stdin = stdio.open('/dev/tty',stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
|
||||
stdlib.sleep(2,function() {
|
||||
prepFile(fd);
|
||||
});
|
||||
}else{
|
||||
fd = stdio.open(file,stdio.flags.O_RDONLY,prepFile);
|
||||
if (!fd) {
|
||||
|
|
@ -1360,6 +1364,10 @@ Options:
|
|||
}
|
||||
|
||||
if (file == null) {
|
||||
if (!stdio.isatty(io.stdin)) {
|
||||
writeFile(io.stdin);
|
||||
return null;
|
||||
}
|
||||
stdio.write(io.stderr,'no file specified\n');
|
||||
return 1;
|
||||
}
|
||||
|
|
@ -1474,6 +1482,10 @@ Options:
|
|||
}
|
||||
|
||||
if (file == null) {
|
||||
if (!stdio.isatty(io.stdin)) {
|
||||
writeFile(io.stdin);
|
||||
return null;
|
||||
}
|
||||
stdio.write(io.stderr,'no file specified\n');
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
var clite = {
|
||||
state:{
|
||||
version:'0.5.1',
|
||||
version:'0.5.2',
|
||||
isinit:false,
|
||||
runlevel:1,
|
||||
bios:null,
|
||||
|
|
@ -1106,6 +1106,10 @@ clite.io = {
|
|||
read = true;
|
||||
if ((flags&clite.io.flags.O_WRONLY) == clite.io.flags.O_WRONLY)
|
||||
write = true;
|
||||
if ((flags&clite.io.flags.O_RDWR) == clite.io.flags.O_RDWR) {
|
||||
read = true;
|
||||
write = true;
|
||||
}
|
||||
if ((flags&clite.io.flags.O_EXEC) == clite.io.flags.O_EXEC)
|
||||
exec = true;
|
||||
if ((flags&clite.io.flags.O_SEARCH) == clite.io.flags.O_SEARCH)
|
||||
|
|
@ -1116,7 +1120,7 @@ clite.io = {
|
|||
return null;
|
||||
|
||||
if ((flags&clite.io.flags.O_APPEND) == clite.io.flags.O_APPEND) {
|
||||
if (!read)
|
||||
if (!read && !write)
|
||||
return null;
|
||||
append = true;
|
||||
}
|
||||
|
|
@ -1180,6 +1184,8 @@ clite.io = {
|
|||
return null; // cannot truncate unloaded remote data
|
||||
}
|
||||
}
|
||||
if (append && write)
|
||||
fd.pos = fd.node.data.content.length;
|
||||
|
||||
return getFileDesPost(fd,cb);
|
||||
}
|
||||
|
|
@ -2674,9 +2680,6 @@ clite.lib = {
|
|||
nio.pid = pid;
|
||||
nio.exit = function(v) {
|
||||
clite.lib.exit(pid,v);
|
||||
try{
|
||||
io.exit(pid,v);
|
||||
} catch(err) {}
|
||||
}
|
||||
var nenv = structuredClone(env);
|
||||
// this is esssentially the dynamic linker
|
||||
|
|
|
|||
|
|
@ -96,7 +96,6 @@ return Object.create({
|
|||
}
|
||||
if (s.length > 0)
|
||||
parts.push(s);
|
||||
// TODO: resolve all paths passed as arguments? - catches ~ and * etc
|
||||
return parts;
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ return Object.create({
|
|||
|
||||
initscr:function() {
|
||||
// curses only works on a tty
|
||||
if (!clite.io.isatty(io.pid,io.stdin))
|
||||
if (!clite.io.isatty(io.pid,io.stdin) || !clite.io.isatty(io.pid,io.stdout))
|
||||
return false;
|
||||
this.ctty = clite.proc.getTTY(io.pid);
|
||||
this.size.rows = clite.tty.ttyctrl(this.ctty,'rows');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
clite.libs.data = function() {
|
||||
|
||||
clite.libs.load('libio','stdio',function(io,env) {
|
||||
function randChar() {
|
||||
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
return characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
}
|
||||
|
||||
return Object.create({
|
||||
|
||||
|
|
@ -93,6 +97,32 @@ return Object.create({
|
|||
return clite.io.mkdir(io.pid,path,mode);
|
||||
},
|
||||
|
||||
mkstemp:function(template,rc) {
|
||||
if (typeof template === 'undefined')
|
||||
template = '/tmp/tmpfileXXXXXX';
|
||||
if (typeof rc === 'undefined')
|
||||
rc = 0;
|
||||
|
||||
if (rc > 4 || template[0] != '/')
|
||||
return null;
|
||||
|
||||
var path = template;
|
||||
var ind;
|
||||
while ((ind = path.lastIndexOf('X')) > 4) {
|
||||
var t = path.substring(0,ind)+randChar()+path.substring(ind+1);
|
||||
path = t;
|
||||
}
|
||||
|
||||
if (path == template)
|
||||
return this.mkstemp(template+'XXXXXX',rc+1);
|
||||
|
||||
var fd = clite.io.open(io.pid,path,clite.io.flags.O_RDWR|clite.io.flags.O_CREAT|clite.io.flags.O_EXCL|clite.io.flags.O_SYNC);
|
||||
if (!fd)
|
||||
return this.mkstemp(template,rc+1);
|
||||
|
||||
return fd;
|
||||
},
|
||||
|
||||
vfprintf:function(fd,fmt,args) {
|
||||
return clite.io.vfprintf(io.pid,fd,fmt,args);
|
||||
},
|
||||
|
|
|
|||
534
clite/shell.js
534
clite/shell.js
|
|
@ -183,18 +183,19 @@ clite.commands.load('sh',function(args,env,io) {
|
|||
parser.internal.parseLine();
|
||||
return;
|
||||
}
|
||||
run(l,parser.internal.parseLine);
|
||||
exec.setCommand(l);
|
||||
exec.run(parser.internal.parseLine);
|
||||
}
|
||||
},
|
||||
exit:function() {
|
||||
if (typeof parser.callback === 'function') {
|
||||
try{
|
||||
parser.callback();
|
||||
} catch(err) {
|
||||
stdio.write(io.stderr,'Shell: internal error in parser\n');
|
||||
io.exit(1);
|
||||
return;
|
||||
}
|
||||
if (typeof parser.callback !== 'function')
|
||||
return;
|
||||
try{
|
||||
parser.callback();
|
||||
} catch(err) {
|
||||
stdio.write(io.stderr,'Shell: internal error in parser\n');
|
||||
io.exit(1);
|
||||
return;
|
||||
}
|
||||
},
|
||||
run:function(cb) {
|
||||
|
|
@ -215,6 +216,411 @@ clite.commands.load('sh',function(args,env,io) {
|
|||
}
|
||||
};
|
||||
|
||||
var exec = {
|
||||
callback:null,
|
||||
cmds:[],
|
||||
active:null,
|
||||
bufferout:null,
|
||||
bufferin:null,
|
||||
cfg:{closout:false,closin:false,closerr:false},
|
||||
last:0,
|
||||
io:{},
|
||||
internal:{
|
||||
doCommand:function(cmd) {
|
||||
exec.active = cmd;
|
||||
if ((cmd.onlastsuccess && exec.last != 0) || (cmd.onlastfail && exec.last == 0)) {
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
var usebi = false;
|
||||
var usebo = false;
|
||||
if (cmd.stdin != '&0') {
|
||||
switch (cmd.stdin) {
|
||||
case '|':
|
||||
exec.stdin.setOut();
|
||||
usebi = true;
|
||||
break;
|
||||
case null:
|
||||
exec.stdin.setNull();
|
||||
break;
|
||||
default:
|
||||
exec.stdin.setFile(cmd.stdin);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
if (exec.cfg.closin) {
|
||||
stdio.close(exec.io.stdin);
|
||||
exec.cfg.closin = false;
|
||||
}
|
||||
exec.io.stdin = io.stdin;
|
||||
}
|
||||
if (cmd.stdout != '&1') {
|
||||
switch (cmd.stdout) {
|
||||
case '|':
|
||||
exec.stdout.setBuffered();
|
||||
usebo = true;
|
||||
break;
|
||||
case null:
|
||||
exec.stdout.setNull();
|
||||
break;
|
||||
default:
|
||||
exec.stdout.setFile(cmd.stdout);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
if (exec.cfg.closout) {
|
||||
stdio.close(exec.io.stdout);
|
||||
exec.cfg.closout = false;
|
||||
}
|
||||
exec.io.stdout = io.stdout;
|
||||
}
|
||||
if (cmd.stderr != '&2') {
|
||||
switch (cmd.stderr) {
|
||||
case '&1':
|
||||
exec.stderr.setOut();
|
||||
break;
|
||||
case null:
|
||||
exec.stderr.setNull();
|
||||
break;
|
||||
default:
|
||||
exec.stderr.setFile(cmd.stderr);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
if (exec.cfg.closerr) {
|
||||
stdio.close(exec.io.stderr);
|
||||
exec.cfg.closerr = false;
|
||||
}
|
||||
exec.io.stderr = io.stderr;
|
||||
}
|
||||
if (exec.io.stdin == null) {
|
||||
stdio.write(io.stderr,'could not open standard input for reading\n');
|
||||
exec.setLast(1);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
if (exec.io.stdout == null) {
|
||||
stdio.write(io.stderr,'could not open standard output for writing\n');
|
||||
exec.setLast(1);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
if (exec.io.stderr == null) {
|
||||
stdio.write(io.stderr,'could not open standard error for writing\n');
|
||||
exec.setLast(1);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
if (typeof macro[cmd.args[0]] != 'undefined') {
|
||||
exec.io.exit = io.exit;
|
||||
var r = macro[cmd.args[0]](cmd.args,exec.io);
|
||||
exec.setLast(r);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!cmd.path) {
|
||||
stdio.fprintf(io.stderr,'Shell: unknown command: %s\n',cmd.args[0]);
|
||||
exec.setLast(1);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
var pid = stdlib.fork(env,exec.io,exec.internal.doExec);
|
||||
if (pid == 0) {
|
||||
stdio.write(io.stderr,'Shell: internal error\n');
|
||||
exec.setLast(1);
|
||||
exec.run();
|
||||
return;
|
||||
}
|
||||
|
||||
stdlib.waitpid(pid,function(pid,ev) {
|
||||
exec.setLast(ev);
|
||||
exec.run();
|
||||
});
|
||||
},
|
||||
doExec:function(env,io) {
|
||||
var r = stdlib.exec(exec.active.path,exec.active.args,env,io);
|
||||
if (r > 0)
|
||||
return;
|
||||
|
||||
if (r == -1) {
|
||||
stdlib.fprintf(io.stderr,'Shell: unknown command: %s\n',exec.active.args[0]);
|
||||
io.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -2) {
|
||||
stdio.fprintf(io.stderr,'Shell: error in command: %s\n',exec.active.args[0]);
|
||||
io.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -3 || r == -4) {
|
||||
stdio.fprintf(io.stderr,'Shell: not an executable file: %s\n',exec.active.args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -5) {
|
||||
stdio.fprintf(io.stderr,'Shell: invalid parser for file: %s\n',exec.active.args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -6) {
|
||||
stdio.fprintf(io.stderr,'Shell: no valid parser for file: %s\n',exec.active.args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r<0) {
|
||||
stdio.fprintf(io.stderr,'Shell: could not exec file: %s\n',exec.active.args[0]);
|
||||
io.exit(-3);
|
||||
}
|
||||
}
|
||||
},
|
||||
setLast:function(v) {
|
||||
exec.last = parseInt(v);
|
||||
env['?'] = exec.last.toString();
|
||||
},
|
||||
setCommand:function(txt) {
|
||||
var args = clite.strToArgs(txt);
|
||||
if (args.length < 1)
|
||||
return;
|
||||
args.forEach(function(val,i) {
|
||||
args[i] = preprocess(val);
|
||||
});
|
||||
var cmd = {
|
||||
args:[],
|
||||
path:null,
|
||||
stdin:'&0',
|
||||
stdout:'&1',
|
||||
stderr:'&2',
|
||||
onlastsuccess:false,
|
||||
onlastfail:false
|
||||
};
|
||||
var c = structuredClone(cmd);
|
||||
exec.cmds = [];
|
||||
for (var i=0; i<args.length; i++) {
|
||||
if (args[i] == '|') {
|
||||
c.stdout = '|';
|
||||
exec.cmds.push(c);
|
||||
c = structuredClone(cmd);
|
||||
c.stdin = '|';
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '||') {
|
||||
exec.cmds.push(c);
|
||||
c = structuredClone(cmd);
|
||||
c.onlastfail = true;
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '&&') {
|
||||
exec.cmds.push(c);
|
||||
c = structuredClone(cmd);
|
||||
c.onlastsuccess = true;
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '>') {
|
||||
i++;
|
||||
c.stdout = clite.resolvePath(args[i]);
|
||||
if (c.stdout == '/dev/null')
|
||||
c.stdout = null;
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '2>&1') {
|
||||
c.stderr = '&1';
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '>>') {
|
||||
i++;
|
||||
c.stdout = clite.resolvePath(args[i]);
|
||||
if (c.stdout == '/dev/null') {
|
||||
c.stdout = null;
|
||||
}else{
|
||||
c.stdout = '+'+c.stdout;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (args[i] == '<') {
|
||||
i++;
|
||||
c.stdin = clite.resolvePath(args[i]);
|
||||
if (c.stdin == '/dev/null')
|
||||
c.stdin = null;
|
||||
continue;
|
||||
}
|
||||
c.args.push(args[i]);
|
||||
}
|
||||
if (c.args.length > 0)
|
||||
exec.cmds.push(c);
|
||||
var fault = false;
|
||||
exec.cmds.forEach(function(c) {
|
||||
if (c.args.length < 1) {
|
||||
fault = true;
|
||||
return;
|
||||
}
|
||||
c.path = resolvePATH(c.args[0]);
|
||||
});
|
||||
if (fault) {
|
||||
stdio.write(io.stderr,'Shell: unable to pass command\n');
|
||||
exec.exit();
|
||||
return;
|
||||
}
|
||||
exec.io.pid = io.pid;
|
||||
exec.io.stdin = io.stdin;
|
||||
exec.io.stdout = io.stdout;
|
||||
exec.io.stderr = io.stderr;
|
||||
exec.io.exit = null; // filled in by fork()
|
||||
exec.io.include = null; // filled in by fork()
|
||||
exec.last = 0;
|
||||
},
|
||||
stdin:{
|
||||
setFile:function(path) {
|
||||
if (exec.cfg.closin) {
|
||||
stdio.close(exec.io.stdin);
|
||||
exec.cfg.closin = false;
|
||||
}
|
||||
exec.io.stdin = stdio.open(path,stdio.flags.O_RDONLY);
|
||||
exec.cfg.closin = true;
|
||||
},
|
||||
setNull:function() {
|
||||
if (exec.cfg.closin) {
|
||||
stdio.close(exec.io.stdin);
|
||||
exec.cfg.closin = false;
|
||||
}
|
||||
exec.io.stdin = stdio.open('/dev/null',stdio.flags.O_RDONLY);
|
||||
exec.cfg.closin = true;
|
||||
},
|
||||
setOut:function() {
|
||||
if (exec.cfg.closin) {
|
||||
stdio.close(exec.io.stdin);
|
||||
exec.cfg.closin = false;
|
||||
}
|
||||
if (exec.bufferout) {
|
||||
exec.io.stdout = null;
|
||||
exec.cfg.closout = false;
|
||||
exec.bufferin = exec.bufferout;
|
||||
exec.bufferout = null;
|
||||
exec.io.stdin = exec.bufferin;
|
||||
stdio.seek(exec.io.stdin,0);
|
||||
exec.cfg.closin = true;
|
||||
}else{
|
||||
exec.stdin.setNull();
|
||||
}
|
||||
}
|
||||
},
|
||||
stdout:{
|
||||
setBuffered:function() {
|
||||
if (exec.cfg.closout) {
|
||||
stdio.close(exec.io.stdout);
|
||||
exec.cfg.closout = false;
|
||||
if (exec.bufferout)
|
||||
exec.bufferout = null;
|
||||
}
|
||||
exec.bufferout = stdio.mkstemp('/tmp/shell-XXXXXX');
|
||||
exec.io.stdout = exec.bufferout;
|
||||
exec.cfg.closout = false;
|
||||
},
|
||||
setFile:function(path) {
|
||||
if (exec.cfg.closout) {
|
||||
stdio.close(exec.io.stdout);
|
||||
exec.cfg.closout = false;
|
||||
}
|
||||
var flags = stdio.flags.O_WRONLY|stdio.flags.O_CREAT|stdio.flags.O_SYNC;
|
||||
var p = path;
|
||||
if (path[0] == '+') {
|
||||
flags |= stdio.flags.O_APPEND;
|
||||
p = path.substring(1);
|
||||
}else{
|
||||
flags |= stdio.flags.O_TRUNC;
|
||||
}
|
||||
exec.io.stdout = stdio.open(p,flags);
|
||||
exec.cfg.closout = true;
|
||||
},
|
||||
setNull:function() {
|
||||
if (exec.cfg.closout) {
|
||||
stdio.close(exec.io.stdout);
|
||||
exec.cfg.closout = false;
|
||||
}
|
||||
exec.io.stdout = stdio.open('/dev/null',stdio.flags.O_WRONLY);
|
||||
exec.cfg.closin = true;
|
||||
}
|
||||
},
|
||||
stderr:{
|
||||
setFile:function(path) {
|
||||
if (exec.cfg.closerr) {
|
||||
stdio.close(exec.io.stderr);
|
||||
exec.cfg.closerr = false;
|
||||
}
|
||||
var flags = stdio.flags.O_WRONLY|stdio.flags.O_CREAT|stdio.flags.O_SYNC;
|
||||
var p = path;
|
||||
if (path[0] == '+') {
|
||||
flags |= stdio.flags.O_APPEND;
|
||||
p = path.substring(1);
|
||||
}else{
|
||||
flags |= stdio.flags.O_TRUNC;
|
||||
}
|
||||
exec.io.stderr = stdio.open(p,flags);
|
||||
exec.cfg.closerr = true;
|
||||
},
|
||||
setNull:function() {
|
||||
if (exec.cfg.closerr) {
|
||||
stdio.close(exec.io.stderr);
|
||||
exec.cfg.closerr = false;
|
||||
}
|
||||
exec.io.stderr = stdio.open('/dev/null',stdio.flags.O_WRONLY);
|
||||
exec.cfg.closerr = true;
|
||||
},
|
||||
setOut:function() {
|
||||
if (exec.cfg.closerr) {
|
||||
stdio.close(exec.io.stderr);
|
||||
exec.cfg.closerr = false;
|
||||
}
|
||||
exec.io.stderr = exec.io.stdout;
|
||||
exec.cfg.closerr = exec.cfg.closout;
|
||||
}
|
||||
},
|
||||
exit:function() {
|
||||
if (exec.cfg.closin) {
|
||||
stdio.close(exec.io.stdin);
|
||||
exec.cfg.closin = false;
|
||||
}
|
||||
var out = '';
|
||||
if (exec.bufferout)
|
||||
out = stdio.readAll(exec.bufferout);
|
||||
if (exec.cfg.closout) {
|
||||
stdio.close(exec.io.stdout);
|
||||
exec.cfg.closout = false;
|
||||
}
|
||||
if (exec.cfg.closerr) {
|
||||
stdio.close(exec.io.stderr);
|
||||
exec.cfg.closerr = false;
|
||||
}
|
||||
exec.active = null;
|
||||
exec.cmds = [];
|
||||
if (typeof exec.callback !== 'function')
|
||||
return;
|
||||
try{
|
||||
exec.callback(out);
|
||||
} catch(err) {
|
||||
console.log(err.fileName+':'+err.lineNumber+':'+err.columnNumber+':'+err.message);
|
||||
stdio.write(io.stderr,'Shell: internal error in command execution\n');
|
||||
io.exit(1);
|
||||
return;
|
||||
}
|
||||
},
|
||||
run:function(cb) {
|
||||
if (typeof cb === 'function')
|
||||
exec.callback = cb;
|
||||
var c = exec.cmds.shift();
|
||||
if (!c) {
|
||||
exec.exit();
|
||||
return;
|
||||
}
|
||||
exec.internal.doCommand(c);
|
||||
}
|
||||
};
|
||||
|
||||
function help() {
|
||||
stdio.write(io.stdout,`
|
||||
sh - command interpreter (shell)
|
||||
|
|
@ -235,7 +641,7 @@ Options:
|
|||
if (path)
|
||||
return;
|
||||
var rp = clite.resolvePath(txt,p);
|
||||
var st = stdio.stat(rp);//open(rp,stdio.flags.O_RDONLY|stdio.flags.O_SYNC);
|
||||
var st = stdio.stat(rp);
|
||||
if (st) {
|
||||
path = rp;
|
||||
}
|
||||
|
|
@ -335,108 +741,6 @@ Options:
|
|||
return c+add;
|
||||
}
|
||||
|
||||
function run(txt,cb) {
|
||||
if (txt.length < 1) {
|
||||
if (typeof cb === 'function')
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
history.add(txt);
|
||||
history.resetCurrent();
|
||||
// split command line into arguments
|
||||
var args = clite.strToArgs(txt);
|
||||
args.forEach(function(val,i) {
|
||||
args[i] = preprocess(val);
|
||||
});
|
||||
// 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,
|
||||
exit:null, // filled in by fork()
|
||||
include:null, // filled in by fork()
|
||||
};
|
||||
// check for a macro
|
||||
// then either run the macro or expand the program to be executed via PATH
|
||||
if (typeof macro[args[0]] != 'undefined') {
|
||||
fio.exit = io.exit;
|
||||
var r = macro[args[0]](args,fio);
|
||||
env['?'] = r.toString();
|
||||
if (typeof cb === 'function')
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
var path = resolvePATH(args[0]);
|
||||
if (!path) {
|
||||
stdio.fprintf(io.stderr,'Shell: unknown command: %s\n',args[0]);
|
||||
env['?'] = '1';
|
||||
if (typeof cb === 'function')
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
var shenv = env;
|
||||
|
||||
function execFunc(env,io) {
|
||||
var r = stdlib.exec(path,args,env,io);
|
||||
if (r > 0)
|
||||
return;
|
||||
shenv['?'] = '1';
|
||||
|
||||
if (r == -1) {
|
||||
stdlib.fprintf(io.stderr,'Shell: unknown command: %s\n',args[0]);
|
||||
io.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -2) {
|
||||
stdio.fprintf(io.stderr,'Shell: error in command: %s\n',args[0]);
|
||||
io.exit(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -3 || r == -4) {
|
||||
stdio.fprintf(io.stderr,'Shell: not an executable file: %s\n',args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -5) {
|
||||
stdio.fprintf(io.stderr,'Shell: invalid parser for file: %s\n',args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r == -6) {
|
||||
stdio.fprintf(io.stderr,'Shell: no valid parser for file: %s\n',args[0]);
|
||||
io.exit(-3);
|
||||
return;
|
||||
}
|
||||
|
||||
if (r<0) {
|
||||
stdio.fprintf(io.stderr,'Shell: could not exec file: %s\n',args[0]);
|
||||
io.exit(-3);
|
||||
}
|
||||
}
|
||||
var pid = stdlib.fork(env,fio,execFunc);
|
||||
if (pid == 0) {
|
||||
stdio.write(io.stderr,'Shell: internal error\n');
|
||||
env['?'] = '1';
|
||||
if (typeof cb === 'function')
|
||||
cb();
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof cb === 'function')
|
||||
stdlib.waitpid(pid,function(pid,ev) {
|
||||
env['?'] = ev.toString();
|
||||
cb();
|
||||
});
|
||||
}
|
||||
|
||||
function writePrompt() {
|
||||
// generate the prompt
|
||||
var p = env.PS1;
|
||||
|
|
@ -472,7 +776,10 @@ Options:
|
|||
break;
|
||||
case '\n': // enter
|
||||
term.ttyctrl('raw',false);
|
||||
run(c,inputRead);
|
||||
history.add(c);
|
||||
history.resetCurrent();
|
||||
exec.setCommand(c);
|
||||
exec.run(inputRead);
|
||||
c = '';
|
||||
cc = 0;
|
||||
return;
|
||||
|
|
@ -551,6 +858,7 @@ Options:
|
|||
}
|
||||
|
||||
// TODO: hacks r uglee
|
||||
// if args[0] isn't the shell itself, then we're running a shell script
|
||||
if (!f && args[0] != '/bin/sh' && args[0] != 'sh') {
|
||||
f = clite.resolvePath(args[0]);
|
||||
if (!f)
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ The shell supports arguments in "quotes" and 'single quotes', as well as
|
|||
dot (.) and dot dot (..) for current and parent directories. The
|
||||
asterisk (*) wildcard is not currently supported
|
||||
The shell maintains a command history, use up and down arrows to access.
|
||||
Piping and io redirects are not currently supported, yet.
|
||||
Piping and io redirects are supported, however they may be buggy.
|
||||
Minimal shell scripting is supported, essentially a line parser, no
|
||||
conditional or loop support (yet).
|
||||
The following shell builtin commands or macros are available:
|
||||
|
|
|
|||
Loading…
Reference in a new issue