some improvements to shell scripting

This commit is contained in:
Lisa Milne 2023-12-14 18:59:15 +10:00
parent 162d63f4e1
commit e719b8686a
2 changed files with 55 additions and 19 deletions

View file

@ -600,7 +600,7 @@ clite.proc = {
return;
data.groups.push({gpid:cpid,waitAny:[],waitAll:[]});
}
function exitGroup(cpid,pid) {
function exitGroup(cpid,pid,ev) {
var group = getGroup(cpid);
if (!group)
return false;
@ -617,7 +617,7 @@ clite.proc = {
if (c > 0)
return true;
group.waitAll.forEach(function(w) {
w(pid);
w(pid,ev);
});
group.waitAll = [];
return true;
@ -658,7 +658,7 @@ clite.proc = {
n.data.content += 'command: '+cl+'\n';
return true;
}
clite.proc.exit = function(pid) {
clite.proc.exit = function(pid,ev) {
var i = getProcIndex(pid);
if (i<0)
return false;
@ -668,9 +668,9 @@ clite.proc = {
data.procs.splice(i,1);
vfsapi.remove(0,'/proc/'+pid);
proc.waits.forEach(function(w) {
clite.core.execSafeAsync(function() {w(pid)});
clite.core.execSafeAsync(function() {w(pid,ev)});
});
exitGroup(proc.gpid,pid);
exitGroup(proc.gpid,pid,ev);
// special case, reboot if pid 1 exits
if (pid == 1) {
clite.core.execSafeAsync(function() {
@ -2727,7 +2727,6 @@ clite.lib = {
fd = clite.io.open(io.pid,e,clite.io.flags.O_RDONLY|clite.io.flags.O_EXEC|clite.io.flags.O_SYNC);
if (!fd)
return -6;
args = [args[0],path];
ft = clite.lib.getFileType(fd);
}
if (ft != clite.io.types.FT_BINARY) {
@ -2751,7 +2750,7 @@ clite.lib = {
},
exit:function(pid,v) {
if (pid > -1)
clite.proc.exit(pid);
clite.proc.exit(pid,v);
}
}

View file

@ -10,6 +10,7 @@ clite.commands.load('sh',function(args,env,io) {
var macro = {
clear:function(args,io) {
term.clear();
return 0;
},
cd:function(args,io) {
var dir = env.HOME;
@ -18,60 +19,68 @@ clite.commands.load('sh',function(args,env,io) {
var fd = stdio.open(dir,stdio.flags.O_SEARCH|stdio.flags.O_DIRECTORY);
if (!fd) {
stdio.fprintf(io.stderr,'invalid directory: %s\n',dir);
return;
return 1;
}
stdio.close(fd);
env.PWD = dir;
return 0;
},
pwd:function(args,io) {
stdio.fprintf(io.stdout,'%s\n',env.PWD);
return 0;
},
echo:function(args,io) {
args.shift();
var txt = args.join(' ')+'\n';
stdio.write(io.stdout,txt);
return 0;
},
which:function(args,io) {
if (args.length <2)
return;
return 1;
if (typeof macro[args[1]] != 'undefined') {
return;
return 1;
}else{
var path = resolvePATH(args[1]);
if (!path)
return;
return 1;
stdio.fprintf(io.stdout,'%s is %s\n',args[1],path);
}
return 0;
},
type:function(args,io) {
if (args.length <2)
return;
return 1;
if (typeof macro[args[1]] != 'undefined') {
stdio.fprintf(io.stdout,'%s is a shell builtin\n',args[1]);
}else{
var path = resolvePATH(args[1]);
if (!path)
return;
return 1;
stdio.fprintf(io.stdout,'%s is %s\n',args[1],path);
}
return 0;
},
whoami:function(args,io) {
stdio.fprintf(io.stdout,'%s\n',env.USER);
return 0;
},
alias:function(args,io) {
stdio.fprintf(io.stdout,'unimplemented\n');
return 0;
},
export:function(args,io) {
if (args.length == 1) {
Object.keys(env).forEach(function(key) {
stdio.fprintf(io.stdout,'%s=%s\n',key,env[key]);
});
return;
return 0;
}
var parts = args[1].split('=');
if (parts.length != 2)
return;
return 0;
env[parts[0]] = parts[1];
return 0;
},
exit:function(args,io) {
has_exited = true;
@ -79,6 +88,7 @@ clite.commands.load('sh',function(args,env,io) {
if (args.length > 1)
ev = parseInt(args[1]);
io.exit(ev);
return 0;
}
};
@ -150,7 +160,8 @@ clite.commands.load('sh',function(args,env,io) {
},
prepFile:function(fd) {
var data = stdio.readAll(fd);
stdio.close(fd);
if (fd != io.stdin)
stdio.close(fd);
if (!data) {
parser.run();
return;
@ -195,6 +206,12 @@ clite.commands.load('sh',function(args,env,io) {
return;
}
parser.internal.parseFile(f);
},
stdin:function() {
parser.callback = function() {
io.exit(0);
}
parser.internal.prepFile(io.stdin);
}
};
@ -346,6 +363,7 @@ Options:
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;
@ -354,15 +372,19 @@ Options:
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]);
@ -402,13 +424,17 @@ Options:
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,cb);
stdlib.waitpid(pid,function(pid,ev) {
env['?'] = ev.toString();
cb();
});
}
function writePrompt() {
@ -524,6 +550,18 @@ Options:
}
}
// TODO: hacks r uglee
if (!f && args[0] != '/bin/sh' && args[0] != 'sh') {
f = clite.resolvePath(args[0]);
if (!f)
return 1;
// make the arguments readable by the shell script
env['#'] = args.length.toString();
for (var i=0; i<args.length; i++) {
env[i.toString()] = args[i];
}
}
// run a shell script if one is specified
if (f != null) {
parser.queue(f);
@ -534,8 +572,7 @@ Options:
}else if (!stdio.isatty(io.stdin)) {
if (!s)
return 0;
// TODO: parser stdin support
return 1;
parser.stdin();
// otherwise we have an interactive shell
// so run /etc/shrc and ~/.shrc
}else{