From abc7e6c4a5a0acac7d3c84fa6d6669992d1053bb Mon Sep 17 00:00:00 2001 From: Lisa Milne Date: Tue, 28 Nov 2023 11:02:01 +1000 Subject: [PATCH] the system is now multi-user --- clite/commands.js | 9 +- clite/core.js | 515 ++++++++++++++++++++++++++-------------------- clite/libclite.js | 1 - clite/libstd.js | 4 +- clite/libstdio.js | 40 ++-- 5 files changed, 323 insertions(+), 246 deletions(-) diff --git a/clite/commands.js b/clite/commands.js index c8bb11d..ff96797 100644 --- a/clite/commands.js +++ b/clite/commands.js @@ -102,7 +102,12 @@ Options: return; } var st = stdio.fstat(fd); - if (!st || st.type != stdio.types.FT_DIR) { + if (!st) { + stdio.write(io.stderr,'cannot read file: '+dir); + stdio.close(fd); + return; + } + if (st.type != stdio.types.FT_DIR) { writeNodeData(st,fd); stdio.close(fd); return; @@ -690,7 +695,9 @@ Options: if (window.location.protocol == 'file:') clite.commands.load('test',function(args,env,io) { var stdio = io.include('stdio'); + var stdlib = io.include('stdlib'); stdio.printf('Hello world'); + stdio.printf('uid:'+stdlib.getuid()); function rcb(data) { stdio.printf(data); io.exit(0); diff --git a/clite/core.js b/clite/core.js index f572232..83545dd 100644 --- a/clite/core.js +++ b/clite/core.js @@ -1,7 +1,8 @@ var clite = { state:{ version:'0.2-3', - isinit:false + isinit:false, + runlevel:1 }, core:{ execSafe:function(f) { @@ -89,8 +90,8 @@ var clite = { function defaultDevices() { // writing to /dev/local downloads data {name:'filename to save',data:'file content'} - vfsapi.mkFile('/dev/local'); - var n = vfsapi.getNode('/dev/local'); + vfsapi.mkFile(0,'/dev/local'); + var n = vfsapi.getNode(0,'/dev/local'); if (!n) { clite.log.write('local device failure'); return false; @@ -111,8 +112,8 @@ var clite = { n.perms = 'crw-rw-rw-'; n.data.isdev = true; // /dev/null - writing to it goes nowhere, reading from it is always null - vfsapi.mkFile('/dev/null'); - n = vfsapi.getNode('/dev/null'); + vfsapi.mkFile(0,'/dev/null'); + n = vfsapi.getNode(0,'/dev/null'); if (!n) { clite.log.write('null device failure'); return false; @@ -128,8 +129,8 @@ var clite = { n.perms = 'crw-rw-rw-'; n.data.isdev = true; // /dev/random - writing to it goes nowhere, reading from it returns a stringified random number (integer) - vfsapi.mkFile('/dev/random'); - n = vfsapi.getNode('/dev/random'); + vfsapi.mkFile(0,'/dev/random'); + n = vfsapi.getNode(0,'/dev/random'); if (!n) { clite.log.write('random device failure'); return false; @@ -143,8 +144,8 @@ var clite = { n.perms = 'crw-rw-rw-'; n.data.isdev = true; // /dev/initctl - writing to it sets the runlevel, reading from it returns the current runlevel - vfsapi.mkFile('/dev/initctl'); - n = vfsapi.getNode('/dev/initctl'); + vfsapi.mkFile(0,'/dev/initctl'); + n = vfsapi.getNode(0,'/dev/initctl'); if (!n) { clite.log.write('initctl device failure'); return false; @@ -158,6 +159,7 @@ var clite = { var rli = parseInt(rl); switch (rli) { case 0: + clite.state.runlevel = rli; n.data.content.data = 0; setTimeout(function() { var s = Array.from(document.getElementsByTagName('src')); @@ -170,14 +172,16 @@ var clite = { },10); break; case 1: // essentially the booting runlevel + clite.state.runlevel = rli; n.data.content.data = 1; break; case 3: // really just a status change, doesn't "do" anything - clite.init = 3; + clite.state.runlevel = rli; + clite.init = null; n.data.content.data = 3; break; case 6: - clite.init = 6; + clite.state.runlevel = rli; n.data.content.data = 6; clite.core.reboot(); break; @@ -189,8 +193,8 @@ var clite = { n.perms = 'crw-rw-rw-'; n.data.isdev = true; // /dev/tty - the main tty device, writing to it prints to the terminal, reading from it reads keyboard input - vfsapi.mkFile('/dev/tty'); - n = vfsapi.getNode('/dev/tty'); + vfsapi.mkFile(0,'/dev/tty'); + n = vfsapi.getNode(0,'/dev/tty'); if (!n) { clite.log.write('tty failure'); return false; @@ -233,8 +237,8 @@ var clite = { function defaultConfig() { // /etc/env contains the default environment variables - vfsapi.mkFile('/etc/env'); - var n = vfsapi.getNode('/etc/env'); + vfsapi.mkFile(0,'/etc/env'); + var n = vfsapi.getNode(0,'/etc/env'); if (!n) { clite.log.write('environment failure'); return false; @@ -244,8 +248,8 @@ PATH=/bin `; n.perms = '-rw-r--r--'; // /etc/passwd contains user account details - vfsapi.mkFile('/etc/passwd'); - var n = vfsapi.getNode('/etc/passwd'); + vfsapi.mkFile(0,'/etc/passwd'); + var n = vfsapi.getNode(0,'/etc/passwd'); if (!n) { clite.log.write('access config failure'); return false; @@ -257,8 +261,8 @@ guest:x:1:1:guest:/usr/home/guest:/bin/sh // TODO: check cookies for a local user n.perms = '-rw-r--r--'; // /etc/greeting is displayed by the shell after login - vfsapi.mkFile('/etc/greeting'); - var n = vfsapi.getNode('/etc/greeting'); + vfsapi.mkFile(0,'/etc/greeting'); + var n = vfsapi.getNode(0,'/etc/greeting'); if (!n) { clite.log.write('config failure'); return false; @@ -272,8 +276,8 @@ guest:x:1:1:guest:/usr/home/guest:/bin/sh \\_____|______|_____|\\__\\___|`; n.perms = '-rw-r--r--'; // /etc/shrc shell startup file - vfsapi.mkFile('/etc/shrc'); - var n = vfsapi.getNode('/etc/shrc'); + vfsapi.mkFile(0,'/etc/shrc'); + var n = vfsapi.getNode(0,'/etc/shrc'); if (!n) { clite.log.write('shell config failure'); return false; @@ -312,8 +316,8 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; clite.log.write('No Filesystem Found'); return; } - vfsapi.mkFile('/dev/wfs'); - var n = vfsapi.getNode('/dev/wfs'); + vfsapi.mkFile(0,'/dev/wfs'); + var n = vfsapi.getNode(0,'/dev/wfs'); if (!n) { clite.log.write('wfs device failure'); return; @@ -321,9 +325,9 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; n.data.content = data; n.perms = 'cr--r--r--'; n.data.isdev = true; - var fd = clite.io.open('/dev/wfs'); + var fd = clite.io.open(0,'/dev/wfs'); var l; - while ((l = clite.io.readLine(fd)) != null) { + while ((l = clite.io.readLine(0,fd)) != null) { if (l.length <1 || l[0] == '#') continue; var parts = l.split(':'); @@ -335,16 +339,16 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; var gid = parseInt(parts[3]); var perms = parts[4]; - var fn = vfsapi.getNode(path); + var fn = vfsapi.getNode(0,path); if (!fn) { if (perms[0] == 'd') { - vfsapi.mkPath(path); + vfsapi.mkPath(0,path); }else{ var dir = clite.lib.dirname(path); - vfsapi.mkPath(dir); - vfsapi.mkFile(path); + vfsapi.mkPath(0,dir); + vfsapi.mkFile(0,path); } - fn = vfsapi.getNode(path); + fn = vfsapi.getNode(0,path); } if (!fn) continue; @@ -355,7 +359,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; fn.data.remote = url; fn.data.content = null; } - clite.io.close(fd); + clite.io.close(0,fd); // populate /etc (mostly for environment) clite.log.write('Populating /etc'); defaultConfig(); @@ -368,14 +372,14 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; clite.commands = { data:null, load:function(name,fn) { - vfsapi.mkFile('/bin/'+name); - var f = vfsapi.getNode('/bin/'+name); + vfsapi.mkFile(0,'/bin/'+name); + var f = vfsapi.getNode(0,'/bin/'+name); if (!f) return; f.perms = '-rwxr-xr-x'; f.data.content = fn; - vfsapi.mkFile('/usr/src/'+name+'.js'); - f = vfsapi.getNode('/usr/src/'+name+'.js'); + vfsapi.mkFile(0,'/usr/src/'+name+'.js'); + f = vfsapi.getNode(0,'/usr/src/'+name+'.js'); if (!f) return; f.perms = '-rw-rw-r--'; @@ -396,14 +400,14 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; index:[], data:null, load:function(name,header,fn) { - vfsapi.mkFile('/lib/'+name+'.so'); - var f = vfsapi.getNode('/lib/'+name+'.so'); + vfsapi.mkFile(0,'/lib/'+name+'.so'); + var f = vfsapi.getNode(0,'/lib/'+name+'.so'); if (!f) return; f.perms = '-rw-r--r--'; f.data.content = fn; - vfsapi.mkFile('/usr/src/libs/'+name+'.js'); - f = vfsapi.getNode('/usr/src/libs/'+name+'.js'); + vfsapi.mkFile(0,'/usr/src/libs/'+name+'.js'); + f = vfsapi.getNode(0,'/usr/src/libs/'+name+'.js'); if (!f) return; f.perms = '-rw-rw-r--'; @@ -439,10 +443,10 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; return; } - var fd = clite.io.open('/dev/initctl',false); + var fd = clite.io.open(0,'/dev/initctl',false); if (fd) { - clite.io.write(fd,'3'); - clite.io.close(fd); + clite.io.write(0,fd,'3'); + clite.io.close(0,fd); } // check cookies for login clite.log.write('Checking for user session'); @@ -454,12 +458,12 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; clite.user.genGuest(); // create the login shell // should really have init/getty exec the shell with the env data etc - var env = clite.user.getEnv(); + var env = clite.user.getEnv(1); 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), + stdin:clite.io.open(1,'/dev/tty',false), + stdout:clite.io.open(1,'/dev/tty',false), + stderr:clite.io.open(1,'/dev/tty',false), exit:null, // filled in by fork() include:null, // filled in by fork() }; @@ -467,6 +471,7 @@ readme.txt:/usr/clite/readme:0:0:-rw-r--r--`; } } function init9(env,io) { + clite.proc.setLogin(io.pid,1); clite.lib.exec('/bin/sh',['sh'],env,io); } @@ -557,14 +562,21 @@ clite.proc = { if (typeof fn !== 'function') return 0; var proc = Object.create({ - gpid:mapCPID(cpid), - pid:data.nextid++, - func:fn, - waits:[] + uid:0, // the user id this process is running as + gid:0, // the group id this process is running as + gpid:mapCPID(cpid), // the group pid (parent process id) of this process + pid:data.nextid++, // the pid (process id) of this process + func:fn, // the function this process executes + waits:[] // array of wait() calls pending for this process on exit }); + var parent = getProc(proc.gpid); + if (parent) { + proc.uid = parent.uid; + proc.gid = parent.gid; + } data.procs.push(proc); - vfsapi.mkFile('/proc/'+proc.pid); - var n = vfsapi.getNode('/proc/'+proc.pid); + vfsapi.mkFile(0,'/proc/'+proc.pid); + var n = vfsapi.getNode(0,'/proc/'+proc.pid); n.data.content = 'pid: '+proc.pid+'\n'; return proc.pid; } @@ -573,7 +585,7 @@ clite.proc = { if (i<0) return false; var proc = data.procs[i]; - var n = vfsapi.getNode('/proc/'+proc.pid); + var n = vfsapi.getNode(0,'/proc/'+proc.pid); if (!n) return false; n.data.content += 'command: '+cl+'\n'; @@ -587,20 +599,21 @@ clite.proc = { if (!proc) return false; data.procs.splice(i,1); - vfsapi.remove('/proc/'+pid); + vfsapi.remove(0,'/proc/'+pid); proc.waits.forEach(function(w) { clite.core.execSafeAsync(function() {w(pid)}); }); exitGroup(proc.gpid,pid); + // special case, reboot if pid 1 exits if (pid == 1) { clite.core.execSafeAsync(function() { - var fd = clite.io.open('/dev/initctl',false); + var fd = clite.io.open(0,'/dev/initctl',false); if (!fd) { clite.core.reboot(); return; } - clite.io.write(fd,6); - clite.io.close(fd); + clite.io.write(0,fd,6); + clite.io.close(0,fd); }); } return true; @@ -649,18 +662,43 @@ clite.proc = { addGroup(pid); return true; } + clite.proc.getUID = function(pid) { + var proc = getProc(pid); + if (!proc) + return 0; + return proc.uid; + } + clite.proc.getGID = function(pid) { + var proc = getProc(pid); + if (!proc) + return 0; + return proc.gid; + } + clite.proc.setLogin = function(pid,uid) { + var proc = getProc(pid); + if (!proc) + return false; + proc.uid = uid; + proc.gid = clite.user.getGID(uid); + } clite.proc.init = null; return true; }, add:function(cl,fn) {return 0;}, update:function(cl) {return false;}, - exit:function(id) {}, - count:function() {return 0;} + exit:function(pid) {}, + count:function() {return 0;}, + addWait:function() {return false;}, + addWaitGroupAny:function() {return false;}, + addWaitGroupAll:function() {return false;}, + addGroup:function() {return false;}, + getUID:function(pid) {return 0;}, + getGID:function(pid) {return 0;}, }; clite.user = { - init:function(vfs) { // returns true if there's a user login or false for guest - var udata = { + init:function(vfsapi) { // returns true if there's a user login or false for guest + var users = [{ name:'root', uid:0, gid:0, @@ -669,30 +707,22 @@ clite.user = { HOME:'/', USER:this.name, } - }; - clite.user.getUID = function() { - return udata.uid; + }]; + var env = {}; + function getUser(uid) { + for (var i=0; i -1) - return true; - return false; - } - function setLogin(uid) { - var found = false; - - var n = vfs.getFile('/etc/passwd'); + function loadUsers() { + // load in user data from /etc/passwd + var n = vfsapi.getFile(0,'/etc/passwd'); if (!n) return false; var lines = n.split('\n'); lines.forEach(function(line) { - if (found) - return; if (line[0] == '#') return; var sects = line.split(':'); @@ -705,22 +735,27 @@ clite.user = { // 6 shell if (sects.length != 7) return; - if (parseInt(sects[2]) != uid) - return; - found = true; + var uid = parseInt(sects[2]); + var udata = getUser(uid); + if (!udata) { + udata = {}; + users.push(udata); + } + udata.name = sects[0]; - udata.uid = uid; + udata.uid = parseInt(sects[2]); udata.gid = parseInt(sects[3]); + udata.groups = []; + udata.env = {}; udata.env.HOME = sects[5]; udata.env.SHELL = sects[6]; udata.env.USER = udata.name; udata.env.PWD = udata.env.HOME; }); + // TODO: read in data from /etc/groups - if (!found) - return false; - - n = vfs.getFile('/etc/env'); + // load the environment + n = vfsapi.getFile(0,'/etc/env'); if (!n) return false; lines = n.split('\n'); @@ -730,31 +765,51 @@ clite.user = { var sects = line.split('='); if (sects.length != 2) return; - udata.env[sects[0].trim()] = sects[1].trim(); + var name = sects[0].trim(); + var value = sects[1].trim(); + env[name] = value; + users.forEach(function(u) { + u.env[name] = value; + }); }); - // TODO: read in data from /etc/groups - udata.groups = []; - - clite.user.hasLogin = function() { + return true; + } + clite.user.checkGID = function(uid,gid) { + var udata = getUser(uid); + if (!udata) + return false; + if (gid == udata.gid) return true; - } - + if (udata.groups.indexOf(gid) > -1) + return true; + return false; + } + clite.user.getGID = function(uid) { + var udata = getUser(uid); + if (!udata) + return 0; + return udata.gid; + } + function setLogin(uid) { + var udata = getUser(uid); + if (!udata) + return false; return true; } clite.user.genGuest = function() { clite.term.clear(); - vfs.mkDir('/usr/home/guest'); - var n = vfs.getNode('/usr/home/guest'); + vfsapi.mkDir(0,'/usr/home/guest'); + var n = vfsapi.getNode(0,'/usr/home/guest'); if (n) { n.perms = '-rwx------'; n.uid = 1; n.gid = 1; } - vfs.mkLink('/usr/home/guest/web','/usr/share/site'); + vfsapi.mkLink(1,'/usr/home/guest/web','/usr/share/site'); - vfs.mkFile('/usr/home/guest/.shrc'); - n = vfs.getNode('/usr/home/guest/.shrc'); + vfsapi.mkFile(1,'/usr/home/guest/.shrc'); + n = vfsapi.getNode(1,'/usr/home/guest/.shrc'); if (n) { n.perms = '-rwx------'; n.uid = 1; @@ -767,24 +822,24 @@ cat -l /usr/share/introduction setLogin(1); } - clite.user.getEnv = function() { + clite.user.getEnv = function(uid) { + var udata = getUser(uid); + if (!udata) + return structuredClone(env); return structuredClone(udata.env); } + + loadUsers(); + return false; }, - getUID:function() { // get the user's user id + getGID:function(uid) { // get the primary group id of a user return 0; }, - getGID:function() { // get the user's group id - return 0; - }, - checkGID:function(gid) { // check if the user is in a group + checkGID:function(uid,gid) { // check if the user is in a group return true; }, - hasLogin:function() { // check if we're in a user session - return false; - }, - getEnv:function() { // get the current environment (variables) + getEnv:function(uid) { // get the current environment (variables) return {}; }, genGuest:null @@ -796,41 +851,45 @@ clite.io = { var perms = { // -rwxrwxrwx user1-3,group4-6,other7-9 - checkReadable:function(p,uid,gid) { + checkReadable:function(p,nuid,ngid,pid) { + var uid = clite.proc.getUID(pid); if (p[7] == 'r') return true; - if (clite.user.checkGID(gid) && p[4] == 'r') + if (clite.user.checkGID(uid,ngid) && p[4] == 'r') return true; - if (uid == clite.user.getUID() && p[1] == 'r') + if (nuid == uid && p[1] == 'r') return true; return false; }, - checkWritable:function(p,uid,gid) { + checkWritable:function(p,nuid,ngid,pid) { + var uid = clite.proc.getUID(pid); if (p[8] == 'w') return true; - if (clite.user.checkGID(gid) && p[5] == 'w') + if (clite.user.checkGID(uid,ngid) && p[5] == 'w') return true; - if (uid == clite.user.getUID() && p[2] == 'w') + if (nuid == uid && p[2] == 'w') return true; return false; }, - checkExecutable:function(p,uid,gid) { + checkExecutable:function(p,nuid,ngid,pid) { + var uid = clite.proc.getUID(pid); if (p[9] == 'x') return true; - if (clite.user.checkGID(gid) && p[6] == 'x') + if (clite.user.checkGID(uid,ngid) && p[6] == 'x') return true; - if (uid == clite.user.getUID() && p[3] == 'x') + if (nuid == uid && p[3] == 'x') return true; return false; } }; - function getFileDes(path,link,cb) { - var n = vfsapi.getNode(path); + function getFileDes(pid,path,link,cb) { + var uid = clite.proc.getUID(pid); + var n = vfsapi.getNode(uid,path); if (!n) return null; if (n.data.islink && !link) // if link is false, follow links - n = vfsapi.getNode(n.data.content); + n = vfsapi.getNode(uid,n.data.content); var p = (n.data.remote && n.data.content == null); var fd = Object.create({ node:n, @@ -843,6 +902,9 @@ clite.io = { callback:cb } }); + fd.canread = perms.checkReadable(fd.node.perms,fd.node.uid,fd.node.gid,pid); + fd.canwrite = perms.checkWritable(fd.node.perms,fd.node.uid,fd.node.gid,pid); + fd.canexec = perms.checkExecutable(fd.node.perms,fd.node.uid,fd.node.gid,pid); if (cb == false) { fd.remote.callback = null; }else if (p) { @@ -854,42 +916,42 @@ clite.io = { } catch(err) {} }); } - fd.canread = perms.checkReadable(fd.node.perms,fd.node.uid,fd.node.gid); - fd.canwrite = perms.checkWritable(fd.node.perms,fd.node.uid,fd.node.gid); - fd.canexec = perms.checkExecutable(fd.node.perms,fd.node.uid,fd.node.gid); if (!p && fd.remote.callback != null) { clite.core.execSafeAsync(function() {fd.remote.callback(fd);}); } return fd; } - clite.io.creat = function(path,type) { + clite.io.creat = function(pid,path,type) { + var uid = clite.proc.getUID(pid); switch (type) { case 'd': - return vfsapi.mkDir(path); + return vfsapi.mkDir(uid,path); break; case 'l': - return vfsapi.mkLink(path); + return vfsapi.mkLink(uid,path); break; default: - return vfsapi.mkFile(path); + return vfsapi.mkFile(uid,path); } } - clite.io.open = function(path,cb,open_link) { + clite.io.open = function(pid,path,cb,open_link) { if (typeof cb === 'undefined') cb = false; if (typeof open_link === 'undefined') open_link = false; - return getFileDes(path,open_link,cb); + return getFileDes(pid,path,open_link,cb); } - clite.io.close = function(fd) { + clite.io.close = function(pid,fd) { try{ fd.node = null; delete fd; } catch(err) {} } - clite.io.read = function(fd,cb) { + clite.io.read = function(pid,fd,cb) { if (fd.node.data.content == null) return null; + if (!fd.canread) + return null; if (fd.node.data.istty) { try{ if (typeof cb === 'function') { @@ -915,9 +977,11 @@ clite.io = { } return fd.node.data.content[fd.pos++]; } - clite.io.readLine = function(fd,cb) { + clite.io.readLine = function(pid,fd,cb) { if (fd.node.data.content == null) return null; + if (!fd.canread) + return null; if (fd.node.data.istty) { try{ if (typeof cb === 'function') { @@ -950,9 +1014,13 @@ clite.io = { fd.pos += l.length; return l; } - clite.io.readAll = function(fd) { + clite.io.readAll = function(pid,fd) { if (fd.node.data.istty) return false; + if (fd.node.data.content == null) + return null; + if (!fd.canread) + return null; if (fd.node.data.isdev) { if (typeof fd.node.data.content !== 'string') { try{ @@ -964,7 +1032,7 @@ clite.io = { } return fd.node.data.content; } - clite.io.write = function(fd,data) { + clite.io.write = function(pid,fd,data) { if (!fd.canwrite) return false; if (fd.node.data.isdev) { @@ -990,7 +1058,7 @@ clite.io = { } return true; } - clite.io.ftruncate = function(fd,len) { + clite.io.ftruncate = function(pid,fd,len) { if (!fd.canwrite) return false; if (typeof fd.data.content != 'string') @@ -1000,15 +1068,15 @@ clite.io = { fd.pos = len; return true; } - clite.io.truncate = function(path,len) { - var fd = getFileDes(path,false,null); + clite.io.truncate = function(pid,path,len) { + var fd = getFileDes(pid,path,false,null); if (!fd) return false; - var r = clite.io.ftruncate(fd,len); + var r = clite.io.ftruncate(pid,fd,len); close(fd); return r; } - clite.io.seek = function(fd,pos) { + clite.io.seek = function(pid,fd,pos) { if (fd.node.data.content == null) return 0; if (fd.node.data.content.length < 1) @@ -1020,26 +1088,27 @@ clite.io = { fd.pos = fd.node.data.content.length-1; return fd.pos; } - clite.io.remove = function(path) { - var fd = getFileDes(path,true,null); + clite.io.remove = function(pid,path) { + var fd = getFileDes(pid,path,true,null); if (!fd || !fd.canwrite || fd.node.data.isdev) return false; return vfsapi.remove(path); } - clite.io.link = function(path,target) { - if (!getFileDes(target,false,null)) + clite.io.link = function(pid,path,target) { + if (!getFileDes(pid,target,false,null)) return false; - var fd = getFileDes(path,true,null); + var fd = getFileDes(pid,path,true,null); if (fd) { if (!fd.canwrite) return false; fd.node.data.content = target; return true; } - return vfsapi.mkLink(path,target); + var uid = clite.proc.getUID(pid); + return vfsapi.mkLink(uid,path,target); }, - clite.io.fstat = function(fd) { - if (!fd || !fd.node) + clite.io.fstat = function(pid,fd) { + if (!fd || !fd.node || !fd.canread) return null; var stat = Object.create({ @@ -1056,12 +1125,13 @@ clite.io = { return stat; }, - clite.io.stat = function(path) { - var fd = getFileDes(path,true,false); - return clite.io.fstat(fd); + clite.io.stat = function(pid,path) { + var fd = getFileDes(pid,path,true,false); + return clite.io.fstat(pid,fd); }, - clite.io.fchmod = function(fd,mode) { - if (fd.node.uid != clite.user.getUID()) + clite.io.fchmod = function(pid,fd,mode) { + var uid = clite.proc.getUID(pid); + if (fd.node.uid != uid) return false; if (typeof mode !== 'string') return false; @@ -1082,16 +1152,16 @@ clite.io = { } return true; } - clite.io.chmod = function(path,mode) { - var fd = getFileDes(path,true,false); - return clite.io.fchmod(fd,mode); + clite.io.chmod = function(pid,path,mode) { + var fd = getFileDes(pid,path,true,false); + return clite.io.fchmod(pid,fd,mode); } - clite.io.isatty = function(fd) { + clite.io.isatty = function(pid,fd) { return fd.node.data.istty; } - clite.io.vfprintf = function(fd,fmt,args) { + clite.io.vfprintf = function(pid,fd,fmt,args) { // TODO: actually support formatting - return clite.io.write(fd,fmt); + return clite.io.write(pid,fd,fmt); } }, // 0: unknown @@ -1149,14 +1219,14 @@ clite.vfs = { return nn; } } - function checkCanOpen(node) { + function checkCanOpen(uid,node) { + if (!uid) + return true; if (node.perms[7] == 'r') return true; - if (clite.user.checkGID(node.gid) && node.perms[4] == 'r') + if (clite.user.checkGID(uid,node.gid) && node.perms[4] == 'r') return true; - if (node.uid == clite.user.getUID() && node.perms[1] == 'r') - return true; - if (clite.user.getUID() == 0) + if (node.uid == uid && node.perms[1] == 'r') return true; return false; } @@ -1186,19 +1256,19 @@ clite.vfs = { vfsdata.fs.perms = 'drwxr-xr-x'; clite.vfs.getApi = function() { - if (clite.user.getUID() == 0) + if (clite.state.runlevel == 1) return vfsdata.api; return null; } - vfsdata.api.getNode = function(path) { + vfsdata.api.getNode = function(uid,path) { var n = vfsdata.fs; var parts = path.split('/'); while (parts.length > 0) { - if (!checkCanOpen(n)) + if (!checkCanOpen(uid,n)) return null; if (n.data.islink) { - n = vfsdata.api.getNode(n.data.content); + n = vfsdata.api.getNode(uid,n.data.content); } if (!n.data.isdir) return null; @@ -1210,27 +1280,27 @@ clite.vfs = { return null; n = nn; } - if (!checkCanOpen(n)) + if (!checkCanOpen(uid,n)) return null; return n; } - vfsdata.api.getFile = function(path) { - var n = vfsdata.api.getNode(path); + vfsdata.api.getFile = function(uid,path) { + var n = vfsdata.api.getNode(uid,path); if (!n) return null; if (n.data.islink) // get the actual file data, not the link data - return vfsdata.api.getFile(n.data.content); + return vfsdata.api.getFile(uid,n.data.content); return n.data.content; } - vfsdata.api.mkDir = function(path) { - if (vfsdata.api.getNode(path) != null) + vfsdata.api.mkDir = function(uid,path) { + if (vfsdata.api.getNode(0,path) != null) return false; var parts = path.split('/'); var name = parts.pop(); var dir = parts.join('/'); if (dir.length < 1) dir = '/'; - var parent = vfsdata.api.getNode(dir); + var parent = vfsdata.api.getNode(uid,dir); if (!parent || !parent.data.isdir) return false; var n = mkNode(); @@ -1239,20 +1309,20 @@ clite.vfs = { n.data.content = []; n.data.isdir = true; n.perms = 'drwxr-xr-x'; - n.uid = clite.user.getUID(); - n.gid = clite.user.getGID(); + n.uid = uid; + n.gid = clite.user.getGID(uid); parent.data.content.push(n); return true; } - vfsdata.api.mkFile = function(path) { - if (vfsdata.api.getNode(path) != null) + vfsdata.api.mkFile = function(uid,path) { + if (vfsdata.api.getNode(uid,path) != null) return false; var parts = path.split('/'); var name = parts.pop(); var dir = parts.join('/'); if (dir.length < 1) dir = '/'; - var parent = vfsdata.api.getNode(dir); + var parent = vfsdata.api.getNode(0,dir); if (!parent || !parent.data.isdir) return false; var n = mkNode(); @@ -1260,20 +1330,20 @@ clite.vfs = { n.data.parent = parent; n.data.content = ''; n.perms = '-rw-r--r--'; - n.uid = clite.user.getUID(); - n.gid = clite.user.getGID(); + n.uid = uid; + n.gid = clite.user.getGID(uid); parent.data.content.push(n); return true; } - vfsdata.api.mkLink = function(path,target) { - if (vfsdata.api.getNode(path) != null) + vfsdata.api.mkLink = function(uid,path,target) { + if (vfsdata.api.getNode(uid,path) != null) return false; var parts = path.split('/'); var name = parts.pop(); var dir = parts.join('/'); if (dir.length < 1) dir = '/'; - var parent = vfsdata.api.getNode(dir); + var parent = vfsdata.api.getNode(uid,dir); if (!parent || !parent.data.isdir) return false; var n = mkNode(); @@ -1282,59 +1352,59 @@ clite.vfs = { n.data.islink = true; n.data.content = target; n.perms = 'lrw-r--r--'; - n.uid = clite.user.getUID(); - n.gid = clite.user.getGID(); + n.uid = uid; + n.gid = clite.user.getGID(uid); parent.data.content.push(n); return true; } - vfsdata.api.mkPath = function(path) { + vfsdata.api.mkPath = function(uid,path) { var parts = path.split('/'); var p = ''; parts.forEach(function(part) { if (part == '') return; p += '/'+part; - vfsdata.api.mkDir(p); + vfsdata.api.mkDir(uid,p); }); - if (vfsdata.api.getNode(path)) + if (vfsdata.api.getNode(uid,path)) return true; return false; } - vfsdata.api.remove = function(path) { - var n = vfsdata.api.getNode(path); + vfsdata.api.remove = function(uid,path) { + var n = vfsdata.api.getNode(uid,path); if (!n || (n.data.isdir && n.data.content.length > 0)) return false; var dir = clite.lib.dirname(path); - var parent = vfsdata.api.getNode(dir); + var parent = vfsdata.api.getNode(0,dir); if (!parent) return false; var c = []; parent.data.content.forEach(function(nn) { if (nn == n) return; - c.push(nn); + c.push(nn); }); parent.data.content = c; return true; } // make some directories - vfsdata.api.mkDir('/bin'); - vfsdata.api.mkDir('/dev'); - vfsdata.api.mkDir('/etc'); - vfsdata.api.mkDir('/lib'); - vfsdata.api.mkDir('/proc'); - vfsdata.api.mkDir('/usr'); - vfsdata.api.mkDir('/usr/clite'); - vfsdata.api.mkDir('/usr/clite/web'); - vfsdata.api.mkDir('/usr/home'); - vfsdata.api.mkDir('/usr/share'); - vfsdata.api.mkDir('/usr/share/docs'); - vfsdata.api.mkDir('/usr/share/site'); - vfsdata.api.mkDir('/usr/src'); - vfsdata.api.mkDir('/usr/src/libs'); - vfsdata.api.mkDir('/var'); - vfsdata.api.mkFile('/var/logs'); + vfsdata.api.mkDir(0,'/bin'); + vfsdata.api.mkDir(0,'/dev'); + vfsdata.api.mkDir(0,'/etc'); + vfsdata.api.mkDir(0,'/lib'); + vfsdata.api.mkDir(0,'/proc'); + vfsdata.api.mkDir(0,'/usr'); + vfsdata.api.mkDir(0,'/usr/clite'); + vfsdata.api.mkDir(0,'/usr/clite/web'); + vfsdata.api.mkDir(0,'/usr/home'); + vfsdata.api.mkDir(0,'/usr/share'); + vfsdata.api.mkDir(0,'/usr/share/docs'); + vfsdata.api.mkDir(0,'/usr/share/site'); + vfsdata.api.mkDir(0,'/usr/src'); + vfsdata.api.mkDir(0,'/usr/src/libs'); + vfsdata.api.mkDir(0,'/var'); + vfsdata.api.mkFile(0,'/var/logs'); clite.io.init(); vfsdata.api.isinit = true; @@ -1346,19 +1416,19 @@ clite.vfs = { clite.log = { logs:[], - init:function(vfs) { + init:function(vfsapi) { clite.log.write = function(txt) { - if (!clite.user.hasLogin() || (typeof clite.init == 'number' && clite.init != 3)) { + if (clite.state.runlevel != 3) { try { clite.term.writeLine(txt); } catch(e) {} } - var n = vfs.getNode('/var/logs'); + var n = vfsapi.getNode(0,'/var/logs'); if (n) n.data.content += txt+'\n'; console.log(txt); } - var n = vfs.getNode('/var/logs'); + var n = vfsapi.getNode(0,'/var/logs'); if (n) n.data.content = clite.log.logs.join('\n')+'\n'; clite.core.execSafeAsync(function(){clite.log.init = null;}); @@ -1666,6 +1736,7 @@ clite.lib = { io.exit(pid,v); } catch(err) {} } + var nenv = structuredClone(env); // this is esssentially the dynamic linker nio.include = function(name) { var file = ''; @@ -1676,31 +1747,31 @@ clite.lib = { if (file == '') return null; - var fd = clite.io.open('/lib/'+file+'.so',false); + var fd = clite.io.open(0,'/lib/'+file+'.so',false); if (!fd) return null; var lib = null; try{ - lib = fd.node.data.content(nio,env); + lib = fd.node.data.content(nio,nenv); }catch(err) {} - clite.io.close(fd); + clite.io.close(0,fd); if (lib) return lib; return null; } clite.core.execSafeAsync(function() { - call(structuredClone(env),nio); + call(nenv,nio); }); return pid; }, exec:function(path,args,env,io) { - var fd = clite.io.open(path,false); + var fd = clite.io.open(io.pid,path,false); if (!fd) return -1; if (!fd.canexec) { - clite.io.close(fd); + clite.io.close(io.pid,fd); return -3 } @@ -1711,7 +1782,7 @@ clite.lib = { if (typeof rr == 'number') io.exit(rr); }); - clite.io.close(fd); + clite.io.close(io.pid,fd); if (!r) { io.exit(-2); return -2; diff --git a/clite/libclite.js b/clite/libclite.js index 6db0a65..35bb317 100644 --- a/clite/libclite.js +++ b/clite/libclite.js @@ -8,7 +8,6 @@ return Object.create({ resolvePath:function(txt,base) { if (txt == '/') return txt; - var env = clite.user.getEnv(); if (txt[0] == '~') { txt = env.HOME+txt.substring(1); } diff --git a/clite/libstd.js b/clite/libstd.js index d88ea91..50fae43 100644 --- a/clite/libstd.js +++ b/clite/libstd.js @@ -45,12 +45,12 @@ return Object.create({ // returns the current user id getuid:function() { - return clite.user.getUID(); + return clite.proc.getUID(io.pid); }, // returns the current group id getgid:function() { - return clite.user.getGID(); + return clite.proc.getGID(io.pid); }, // wait for any child process to exit diff --git a/clite/libstdio.js b/clite/libstdio.js index 17c9441..84cce3d 100644 --- a/clite/libstdio.js +++ b/clite/libstdio.js @@ -7,85 +7,85 @@ return Object.create({ types:clite.io.types, creat:function(path,type) { - return clite.io.creat(path,type); + return clite.io.creat(io.pid,path,type); }, open:function(path,cb,open_link) { - return clite.io.open(path,cb,open_link); + return clite.io.open(io.pid,path,cb,open_link); }, close:function(fd) { - return clite.io.close(fd); + return clite.io.close(io.pid,fd); }, read:function(fd,cb) { - return clite.io.read(fd,cb); + return clite.io.read(io.pid,fd,cb); }, readLine:function(fd,cb) { - return clite.io.readLine(fd,cb); + return clite.io.readLine(io.pid,fd,cb); }, readAll:function(fd) { - return clite.io.readAll(fd); + return clite.io.readAll(io.pid,fd); }, write:function(fd,data) { - return clite.io.write(fd,data); + return clite.io.write(io.pid,fd,data); }, ftruncate:function(fd,len) { - return clite.io.ftruncate(fd,len); + return clite.io.ftruncate(io.pid,fd,len); }, truncate:function(path,len) { - return clite.io.truncate(path,len); + return clite.io.truncate(io.pid,path,len); }, seek:function(fd,pos) { - return clite.io.seek(fd,pos); + return clite.io.seek(io.pid,fd,pos); }, remove:function(path) { - return clite.io.remove(path); + return clite.io.remove(io.pid,path); }, link:function(path,target) { - return clite.io.link(path,target); + return clite.io.link(io.pid,path,target); }, stat:function(path) { - return clite.io.stat(path); + return clite.io.stat(io.pid,path); }, fstat:function(fd) { - return clite.io.fstat(fd); + return clite.io.fstat(io.pid,fd); }, chmod:function(path,mode) { - return clite.io.chmod(path,mode); + return clite.io.chmod(io.pid,path,mode); }, fchmod:function(fd,mode) { - return clite.io.fchmod(fd,mode); + return clite.io.fchmod(io.pid,fd,mode); }, isatty:function(fd) { - return clite.io.isatty(fd); + return clite.io.isatty(io.pid,fd); }, vfprintf:function(fd,fmt,args) { - return clite.io.vfprintf(fd,fmt,args); + return clite.io.vfprintf(io.pid,fd,fmt,args); }, fprintf:function(fd,fmt) { var args = []; - return clite.io.vfprintf(fd,fmt,args); + return clite.io.vfprintf(io.pid,fd,fmt,args); }, printf:function(fmt) { var args = []; - return clite.io.vfprintf(io.stdout,fmt,args); + return clite.io.vfprintf(io.pid,io.stdout,fmt,args); }