commit fbd7ede70021e85360a0f4e14327abb58469ba6b Author: overflowerror Date: Sat Jul 20 16:09:10 2013 +0200 first commit diff --git a/BIOS.js b/BIOS.js new file mode 100644 index 0000000..6d138ae --- /dev/null +++ b/BIOS.js @@ -0,0 +1,95 @@ +var BIOS = function() { +} +BIOS.logo = "\033[32m" + +" .__ .__ \n" + +"__ _ _|__| _____| |__ \n" + +"\\ \\/ \\/ / |/ ___/ | \\ \n" + +" \\ /| |\\___ \\| Y \\\n" + +" \\/\\_/ |__/____ >___| /\n" + +" \\/ \\/ \033[31mBIOS\033[0m\n"; +BIOS.hdds; +BIOS.lastKey; +BIOS.tickid; +BIOS.state; +BIOS.bootDevice; +BIOS.init = function() { + console.log("BIOS: init"); + BIOS.lastKey = 0; + console.log("BIOS: register key interrupt"); + Emulator.interrupts['key'] = BIOS.key; +} +BIOS.main = function() { + console.log("BIOS: main"); + console.log("BIOS: register 100ms-timer"); + this.tickid = Emulator.registerTimer(100, BIOS.tick); + console.log("BIOS: get hdds"); + this.hdds = Emulator.Devices.getHarddisks(); + var text = this.logo + "\n" + + "Keyboard: found at name=" + Emulator.input.name + "\n" + + "Monitor: found at id=" + Emulator.Output.screen.parentElement.id + "\n\n" + + "Harddisks: \n"; + for (var i = 0; i < this.hdds.length; i++) { + text += " " + i + ": "+ this.hdds[i].name + "\n"; + } + Emulator.output(text); + if (this.hdds.length == 0) { + Emulator.output("No harddisks found. Please insert a bootable device and restart the computer..\n\n"); + Emulator.output("\033[31msystem halt\033[0m"); + console.log("BIOS: remove all event handlers"); + Emulator.interrupts = new Array(); + Emulator.unregisterTimer(this.tickid); + return; + } + if (this.hdds.length > 1) { + Emulator.output("\nPlease select booting device by pressing the device nr. "); + this.state = 0; + } else { + this.state = 1; + } +} +BIOS.key = function(keycode) { + BIOS.lastKey = keycode; +} +BIOS.tick = function() { + switch(BIOS.state) { + case 0: + if (isNumber(KeyCodes.normalKey(BIOS.lastKey))) { + if (BIOS.hdds[BIOS.bootDevice = parseInt(KeyCodes.normalKey(BIOS.lastKey))]) + BIOS.state = 2; + } + break; + case 1: + BIOS.bootDevice = 0; + BIOS.state = 2; + break; + case 2: + Emulator.output("\n\nSearching for MBR on " + BIOS.hdds[BIOS.bootDevice].name + "...\n"); + if (!(mbr = BIOS.hdds[BIOS.bootDevice].mbr)) { + console.log(mbr); + Emulator.output("No MBR found. Please insert a bootable device and restart the computer...\n\n"); + Emulator.output("\033[31msystem halt\033[0m"); + console.log("BIOS: remove all event handlers"); + Emulator.interrupts = new Array(); + Emulator.unregisterTimer(BIOS.tickid); + } + Emulator.Request.include(BIOS.hdds[BIOS.bootDevice].name + "/" + mbr + "/init.js", BIOS.load); + BIOS.state = 3; + break; + default: + break; + } +} +BIOS.load = function() { + console.log("BIOS: stop BIOS"); + console.log("BIOS: remove all event handlers"); + Emulator.interrupts = new Array(); + Emulator.unregisterTimer(BIOS.tickid); + console.log("BIOS: start MBR"); + try { + MBR.main(BIOS.hdds[BIOS.bootDevice]); + } catch (exception) { + console.dir(exception); + Emulator.output("MBR is not bootable. Please insert a bootable device and restart the computer...\n\n"); + Emulator.output("\033[31msystem halt\033[0m"); + } +} diff --git a/Emulator.js b/Emulator.js new file mode 100644 index 0000000..bd3b393 --- /dev/null +++ b/Emulator.js @@ -0,0 +1,603 @@ +var Emulator = function() { +} +Emulator.running = false; +Emulator.startable = false; +Emulator.input; +Emulator.interrupts; +Emulator.mainTickId; +Emulator.init = function(output, input, xsize, ysize) { + console.log("Emulator: define output screen"); + this.Output.screen = output; + console.log("Emulator: init output"); + this.Output.init(xsize, ysize); + console.log("Emulator: define input"); + this.input = input; + console.log("Emulator: define interrupt array"); + this.interrupts = new Array(); + console.log("Emulator: adding event-handlers"); + this.addEventHandlers(); + console.log("Emulator: init finished"); + this.startable = true; +} +Emulator.main = function() { + if (!Emulator.startable) { + console.log("Emulator: not startable"); + return; + } + Emulator.running = true; + Emulator.Output.cursorOn(); + console.log("Emulator: init bios"); + BIOS.init(); + console.log("Emulator: running bios"); + BIOS.main(); +} +Emulator.kill = function() { + console.log("Emulator: got hardware kill signal (powersw)"); + if (Emulator.interrupts['powersw']) + Emulator.interrupts['powersw'](); + else { + Emulator.running = false; + Emulator.startable = false; + console.log("Emulator: no powersw-event defined -> killing"); + Emulator.interrupts = new Array(); + Emulator.output("\n\n\033[31mPOWER BUTTON PRESSED - SYSTEM HALT\nKill in 5s"); + window.setTimeout(function(){Emulator.output("\033[2D4s");}, 1000); + window.setTimeout(function(){Emulator.output("\033[2D3s");}, 2000); + window.setTimeout(function(){Emulator.output("\033[2D2s");}, 3000); + window.setTimeout(function(){Emulator.output("\033[2D1s");}, 4000); + window.setTimeout(function(){Emulator.shutdown()}, 5000); + } +} +Emulator.shutdown = function() { + Emulator.running = false; + Emulator.startable = true; + Emulator.output("\033[0m\033[2J\033[0:0H"); + Emulator.Output.cursorOff() +} +Emulator.addEventHandlers = function() { + console.log("Emulator: adding unfocus-event"); + this.input.onblur = this.refocus; + console.log("Emulator: adding key-press-event"); + this.input.onkeypress = this.handleKeyPress; + console.log("Emulator: adding key-down-event"); + this.input.onkeydown = this.handleKeyDown; + var timerid = window.setInterval(function() {/*for (var i = 0; i < 10; i++)*/ Emulator.tick(0);}, 1); + Emulator.mainTickId = timerid; + console.log("Emulator: adding default 1ms (or cheated 0.1 ms) tick with tid=" + timerid); + this.refocus(); +} +Emulator.getKeyCode = function(e) { + return window.event ? event.keyCode : e.which; +} +Emulator.genericKeyHandler = function(keycode) { + if (Emulator.interrupts['key']) + Emulator.interrupts['key'](keycode); +} +Emulator.handleKeyPress = function(e) { + Emulator.genericKeyHandler(Emulator.getKeyCode(e)); +} +Emulator.handleKeyDown = function(e) { + var keycode = Emulator.getKeyCode(e); + if (keycode == 8 || keycode == 46) { + Emulator.handleKeyPress(e); + return false; + } + return true; +} +Emulator.refocus = function () { + window.setTimeout(function() {Emulator.input.focus();}, 1); + console.log("Emulator: refocus input") +} +Emulator.tick = function (time) { + if (Emulator.interrupts[time]) + Emulator.interrupts[time](); +} +Emulator.registerTimer = function (time, routine) { + var timerid = window.setInterval(routine, time); + console.log("Emulator: timer startet t=" + time + " with tid=" + timerid); + return timerid; +} +Emulator.unregisterTimer = function(timerid) { + console.log("Emulator: timer cleared tid=" + timerid); + window.clearInterval(timerid); +} +Emulator.output = function(text) { + Emulator.ANSISequences.output(text); +} +Emulator.ANSISequences = function() { +} +Emulator.ANSISequences.ESC = "\033"; +Emulator.ANSISequences.output = function(text) { + var normalText = ""; + var specialText = ""; + var specialText2 = ""; + var state = 0; + for(var i = 0; i < text.length; i++) { + switch(state) { + case 0: + specialText = ""; + speacielText2 = ""; + if (text[i] != Emulator.ANSISequences.ESC) + normalText += text[i]; + else + state = 3; + break; + case 3: + if (text[i] == "[") + state = 1; + else { + normalText += " " + text[i]; + state = 0; + } + break; + case 1: + if (isNumber(text[i])) { + specialText += text[i]; + break; + } else { + if (text[i] == '?') { + state = 4; + break; + } + if (text[i] == 's') { + Emulator.Output.sxpos = Emulator.Output.xpos; + Emulator.Output.sypos = Emulator.Output.ypos; + state = 0; + break; + } + if (text[i] == 'u') { + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.xpos = Emulator.Output.sxpos; + Emulator.Output.ypos = Emulator.Output.sypos; + Emulator.Output.cursorOn(); + normalText = ""; + state = 0; + break; + } + if (specialText.length < 1) { + normalText += " [" + ((specialText2.length > 0) ? (specialText2 + ":") : "") + specialText; + state = 0; + break; + } + state = 2; + } + case 2: + switch(text[i]) { + case 'A': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.moveCursor(0, - parseInt(specialText), false); + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'B': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.moveCursor(0, parseInt(specialText), false); + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'C': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.moveCursor(parseInt(specialText), 0, false); + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'D': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.moveCursor(- parseInt(specialText), 0, false); + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'E': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.moveCursor(parseInt(specialText), 0, false); + Emulator.Output.xpos = 0; + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'F': + Emulator.Output.cursorOff(); + Emulator.Output.normalOutput(normalText); + Emulator.Output.moveCursor( - parseInt(specialText), 0, false); + Emulator.Output.xpos = 0; + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case 'G': + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.xpos = (parseInt(specialText) >= Emulator.Output.xsize) ? (Emulator.Output.xsize - 1) : parseInt(specialText); + Emulator.Output.cursorOn(); + normalText = ""; + specialText = ""; + specialText2 = ""; + state = 0; + break; + case ':': + // TODO Wrong! + specialText2 = specialText; + specialText = ""; + state = 1; + break; + case 'H': + if (specialText2.length == 0) { + normalText += " [" + specialText + 'G'; + state = 0; + break; + } + Emulator.Output.normalOutput(normalText); + Emulator.Output.cursorOff(); + Emulator.Output.xpos = (parseInt(specialText2) >= Emulator.Output.xsize) ? (Emulator.Output.xsize - 1) : parseInt(specialText2); + Emulator.Output.ypos = (parseInt(specialText) >= Emulator.Output.ysize) ? (Emulator.Output.ysize - 1) : parseInt(specialText); + Emulator.Output.cursorOn(); + specialText = ""; + specialText2 = ""; + normalText = ""; + state = 0; + break; + case 'J': + Emulator.Output.normalOutput(normalText); + normalText = ""; + switch(parseInt(specialText)) { + case 0: + var oldx = Emulator.Output.xpos; + var oldy = Emulator.Output.ypos; + var number = (Emulator.Output.ysize - oldy - 1) * Emulator.Output.xsize + (Emulator.Output.xsize - oldx - 1); + var itext = ""; + for (var j = 0; j < number; j++) + itext += " "; + Emulator.Output.normalOutput(itext); + Emulator.Output.cursorOff(); + Emulator.Output.xpos = oldx; + Emulator.Output.ypos = oldy; + Emulator.Output.cursorOn(); + break; + case 1: + var oldx = Emulator.Output.xpos; + var oldy = Emulator.Output.ypos; + Emulator.Output.cursorOff(); + Emulator.Output.xpos = 0; + Emulator.Output.ypos = 0; + Emulator.Output.cursorOn(); + var number = (oldy) * Emulator.Output.xsize + oldx; + var itext = ""; + for (var j = 0; j < number; j++) + itext += " "; + Emulator.Output.normalOutput(itext); + break; + case 2: + var oldx = Emulator.Output.xpos; + var oldy = Emulator.Output.ypos; + Emulator.Output.cursorOff(); + Emulator.Output.xpos = 0; + Emulator.Output.ypos = 0; + var itext = ""; + for (var j = 0; j < (Emulator.Output.xsize * Emulator.Output.ysize); j++) + itext += " "; + Emulator.Output.normalOutput(itext); + Emulator.Output.cursorOff(); + Emulator.Output.xpos = oldx; + Emulator.Output.ypos = oldy; + Emulator.Output.cursorOn(); + break; + default: + normalText = " [" + ((specialText2.length > 0) ? (specialText2 + ":") : "") + specialText; + break; + } + specialText = ""; + specialText2 = ""; + state = 0; + break; + // TODO + case 'm': + Emulator.Output.normalOutput(normalText); + normalText = ""; + + switch(parseInt(specialText)) { + case 0: + Emulator.Output.color = "#fff"; + Emulator.Output.backgroundColor = "#000"; + break; + case 30: + Emulator.Output.color = "#000"; + break; + case 31: + Emulator.Output.color = "#f00"; + break; + case 32: + Emulator.Output.color = "#0f0"; + break; + case 33: + Emulator.Output.color = "#ff0"; + break; + case 34: + Emulator.Output.color = "#00f"; + break; + case 35: + Emulator.Output.color = "#f0f"; + break; + case 36: + Emulator.Output.color = "#0ff"; + break; + case 37: + Emulator.Output.color = "#fff"; + break; + + case 40: + Emulator.Output.backgroundColor = "#000"; + break; + case 41: + Emulator.Output.backgroundColor = "#f00"; + break; + case 42: + Emulator.Output.backgroundColor = "#0f0"; + break; + case 43: + Emulator.Output.backgroundColor = "#ff0"; + break; + case 44: + Emulator.Output.backgroundColor = "#00f"; + break; + case 45: + Emulator.Output.backgroundColor = "#f0f"; + break; + case 46: + Emulator.Output.backgroundColor = "#0ff"; + break; + case 47: + Emulator.Output.backgroundColor = "#fff"; + break; + default: + normalText += " [" + ((specialText2.length > 0) ? (specialText2 + ":") : "") + specialText; + state = 0; + break; + } + specialText = ""; + specialText2 = ""; + state = 0; + break; + default: + normalText += " [" + ((specialText2.length > 0) ? (specialText2 + ":") : "") + specialText; + state = 0; + break; + } + break; + case 4: + if (text[i] == '2') + state = 5; + else { + normalText += " [?" + text[i]; + state = 0; + } + break; + case 5: + if (text[i] == '5') + state = 6; + else { + normalText += " [?2" + text[i]; + state = 0; + } + break; + case 6: + if (text[i] == 'l') { + Emulator.Output.displayCursor = false; + state = 0; + break; + } + if (text[i] == 'h') { + Emulator.Output.displayCursor = true; + state = 0; + break; + } + normalText += " [25" + text[i]; + state = 0; + break; + default: + break; + } + } + if ((specialText2.length || specialText.length) > 0) + normalText += " [" + ((specialText2.length > 0) ? (specialText2 + ":") : "") + specialText; + Emulator.Output.normalOutput(normalText); +} + +Emulator.Output = function() { +} +Emulator.Output.screen; +Emulator.Output.xsize; +Emulator.Output.ysize; +Emulator.Output.xpos; +Emulator.Output.ypos; +Emulator.Output.sxpos; +Emulator.Output.sypos; +Emulator.Output.color; +Emulator.Output.backgroundColor; +Emulator.Output.displayCursor; +Emulator.Output.shiftKey = 1; +Emulator.Output.init = function(xsize, ysize) { + console.log("Emulator: define matrix size"); + this.xsize = xsize; + this.ysize = ysize; + console.log("Emulator: reseting cursor position"); + this.xpos = 0; + this.ypos = 0; + this.displayCursor = true; + console.log("Emulator: seting default colors"); + this.color = "#fff"; + this.backgroundColor = "#000"; + console.log("Emulator: generating matrix"); + this.generateMatrix(); +} +Emulator.Output.generateMatrix = function() { + var matrix = ""; + for (var i = 0; i < this.ysize; i++) { + matrix += ""; + for (var j = 0; j < this.xsize; j++) { + matrix += ""; + } + matrix += ""; + } + matrix += "
"; + this.screen.innerHTML = matrix; + this.screen = document.getElementById("matrix"); +} +Emulator.Output.getCursor = function() { + return Emulator.Output.screen.getElementsByTagName("tr")[Emulator.Output.ypos].getElementsByTagName("td")[Emulator.Output.xpos]; +} +Emulator.Output.cursorOff = function() { // fix by Jonas + if(document.getElementById("cursor") != undefined) + document.getElementById("cursor").remove(); +} +Emulator.Output.cursorOn = function() { // fix by Jonas + if (Emulator.Output.displayCursor) { + var cursorElement=document.createElement("div"); + var att=document.createAttribute("id"); + att.value = "cursor"; + cursorElement.setAttributeNode(att); + cursorElement.style.background = "#000"; + cursorElement.style.height = "100%"; + cursorElement.style.border = "1px solid #fff"; + Emulator.Output.getCursor().appendChild(cursorElement); + } +} +Emulator.Output.insert = function(char) { + var cell = Emulator.Output.getCursor(); + cell.style.color = Emulator.Output.color; + cell.style.backgroundColor = Emulator.Output.backgroundColor; + Emulator.Output.getCursor().innerHTML = char; +} +Emulator.Output.moveCursor = function(x, y, lbreak) { + Emulator.Output.xpos += x; + Emulator.Output.ypos += y; + if (lbreak) { + if (Emulator.Output.xpos >= Emulator.Output.xsize) + Emulator.Output.ypos++; + if (Emulator.Output.xpos < 0) + Emulator.Output.ypos--; + Emulator.Output.xpos %= Emulator.Output.xsize; + while (Emulator.Output.ypos >= Emulator.Output.ysize) { + Emulator.Output.lineShift(); + } + } else { + if (Emulator.Output.xpos >= Emulator.Output.xsize) + Emulator.Output.xpos = Emulator.Output.xsize - 1; + if (Emulator.Output.xpos < 0) + Emulator.Output.xpos = 0; + if (Emulator.Output.ypos >= Emulator.Output.ysize) + Emulator.Output.ypos = Emulator.Output.ysize - 1; + if (Emulator.Output.ypos < 0) + Emulator.Output.ypos = 0; + } +} +Emulator.Output.lineShift = function() { + for (var i = Emulator.Output.shiftKey; i < Emulator.Output.ysize; i++) { + for (var j = 0; j < Emulator.Output.xsize; j++) { + var to = Emulator.Output.screen.getElementsByTagName("tr")[i - 1].getElementsByTagName("td")[j]; + var from = Emulator.Output.screen.getElementsByTagName("tr")[i].getElementsByTagName("td")[j]; + to.innerHTML = from.innerHTML; + to.style.color = from.style.color; + to.style.backgroundColor = from.style.backgroundColor; + } + } + for (var j = 0; j < Emulator.Output.xsize; j++) { + var to = Emulator.Output.screen.getElementsByTagName("tr")[Emulator.Output.ysize - 1].getElementsByTagName("td")[j]; + to.innerHTML = ""; + to.style.color = Emulator.Output.color; + to.style.backgroundColor = Emulator.Output.backgroundColor; + } + if (--Emulator.Output.ypos < 0) + Emulator.Output.ypos = 0; +} +Emulator.Output.normalOutput = function(text) { + Emulator.Output.cursorOff(); + for(var i = 0; i < text.length; i++) { + if (text[i] == "\n") { + Emulator.Output.moveCursor(0, 1, true); + Emulator.Output.xpos = 0; + } else { + Emulator.Output.insert(text[i]); + Emulator.Output.moveCursor(1, 0, true); + } + } + Emulator.Output.cursorOn(); +} + +Emulator.Request = function() { +} +Emulator.Request.get = function(file, parameter, background, after) { + var http = new XMLHttpRequest(); + http.open("GET", file + "?" + parameter, background); + if (background) { + http.onreadystatechange = function() { + if (http.readyState == 4) { + if (http.status != 200) + after(http.status); + else + after(http.responseText); + } + }; + } + http.send(null); + if (!background) + if (http.status != 200) + return after(http.status); + else + return after(http.responseText); +} +Emulator.Request.post = function(file, getParameters, postParameters, background, after) { + var http = new XMLHttpRequest(); + http.open("POST", file + "?" + getParameter, background); + http.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); + http.setRequestHeader("Content-length", postParameters.length); + http.setRequestHeader("Connection", "close") + if (background) { + http.onreadystatechange = function() { + if (http.readyState == 4) { + after(http.responseText); + } + }; + } + http.send(postParameters); + if (!background) + return after(http.responseText); +} +Emulator.Request.include = function(file, loaded) { + console.log("Emulator: including file: " + file); + var script = document.createElement("script"); + script.type = "text/javascript"; + script.onload = loaded; + script.src = file; + document.head.appendChild(script); +} + +Emulator.Devices = function() { +} +Emulator.Devices.getAll = function() { + return JSON.parse(Emulator.Request.get("devices.json", "", false, ret)); +} +Emulator.Devices.getHarddisks = function() { + return Emulator.Devices.getAll().harddisks; +} diff --git a/KeyCodes.js b/KeyCodes.js new file mode 100644 index 0000000..b87d8a1 --- /dev/null +++ b/KeyCodes.js @@ -0,0 +1,20 @@ +var KeyCodes = function() { +} +KeyCodes.normalKey = function(code) { + return String.fromCharCode(code); +} +KeyCodes.isBackspace = function(code) { + if (code == 8) + return true; + return false; +} +KeyCodes.isDelete = function(code) { + if (code == 46) + return true; + return false; +} +KeyCodes.isEnter = function(code) { + if (code == 13) + return true; + return false; +} diff --git a/README b/README new file mode 100644 index 0000000..e69de29 diff --git a/devices.json b/devices.json new file mode 100644 index 0000000..0f7b706 --- /dev/null +++ b/devices.json @@ -0,0 +1,15 @@ +{ + "harddisks": [ + { + "name": "wish-sys", + "manufacturers": "wish-admin", + "serialNr": 31415926545, + "mbr": "mbr", + "partitions": [ + { + "name": "sys-part" + } + ] + } + ] +} diff --git a/index.html b/index.html new file mode 100644 index 0000000..8abc69c --- /dev/null +++ b/index.html @@ -0,0 +1,41 @@ + + + + + + + + + +
+ + +
+ +
+ + diff --git a/main.js b/main.js new file mode 100644 index 0000000..9f692a5 --- /dev/null +++ b/main.js @@ -0,0 +1,33 @@ +Array.prototype.diff = function(a) { + return this.filter(function(i) {return !(a.indexOf(i) > -1);}); +} + +String.prototype.reverse = function() { + return this.split("").reverse().join(""); +} + +Math.sign = function(x) { + return (x > 0) ? 1 : (x < 0) ? -1 : 0; +} + +function nothing() { + +} + +function ret(v) { + return v; +} +function isNumber(n) { + return (parseInt(n) + "" == n); +} + +var main = function () { + Emulator.init(document.getElementById("output"), document.forms['form'].elements['input'], 80, 24); +} + +var powerOn = function() { + if (Emulator.running) + Emulator.kill(); + else + Emulator.main(); +} diff --git a/wish-sys/mbr/config.json b/wish-sys/mbr/config.json new file mode 100644 index 0000000..6d24146 --- /dev/null +++ b/wish-sys/mbr/config.json @@ -0,0 +1,13 @@ +{ + "sleep": 10, + "default": 0, + "systems": [ + { + "hdd": 0, + "partition": 0, + "label": "wish os", + "kernel": "kernel0.1.js", + "parameters": "" + } + ] +} diff --git a/wish-sys/mbr/init.js b/wish-sys/mbr/init.js new file mode 100644 index 0000000..bbeaf8a --- /dev/null +++ b/wish-sys/mbr/init.js @@ -0,0 +1,107 @@ +var MBR = function() { +} +MBR.main = function(device) { + console.log("MBR: main"); + console.log("MBR: start Boot Loader"); + Loader.main(device); +} + +var Loader = function() { +} +Loader.logo = "\033[32m" + +" .__ .__ \n" + +"__ _ _|__| _____| |__ \n" + +"\\ \\/ \\/ / |/ ___/ | \\ \n" + +" \\ /| |\\___ \\| Y \\\n" + +" \\/\\_/ |__/____ >___| /\n" + +" \\/ \\/ \033[31mLoader\033[0m\n"; +Loader.tickid; +Loader.state; +Loader.device; +Loader.config; +Loader.main = function(device) { + console.log("Loader: main"); + console.log("Loader: register 100ms-timer"); + Loader.tickid = Emulator.registerTimer(100, Loader.tick); + console.log("Loader: register key interrupt"); + Emulator.interrupts['key'] = Loader.key; + Loader.device = device; + var text = "\033[2J\033[0:0H\033[?25l" + Loader.logo + "\033[s"; + Emulator.output(text); + Loader.state = 0; +} +Loader.key = function(keycode) { + if (KeyCodes.isEnter(keycode)) { + Loader.boot(); + return; + } + var char = KeyCodes.normalKey(keycode); + if (char == 'w') Loader.selected--; + if (char == 's') Loader.selected++; + Loader.selected %= Loader.config.systems.length; + if (Loader.selected < 0) + Loader.selected += Loader.config.systems.length; + Loader.outputSystems(); +} +Loader.tick = function() { + switch(Loader.state) { + case 0: + console.log("Loader: load config"); + Loader.config = JSON.parse(Emulator.Request.get(Loader.device.name + "/" + Loader.device.mbr + "/config.json", "", false, ret)) + Loader.selected = Loader.config.default; + Loader.state++; + break; + case 1: + Loader.outputSystems(); + Loader.state++; + break; + case 2: + break; + case 3: + Emulator.output("."); + break; + default: + break; + } +} +Loader.outputSystems = function() { + console.log("Loader: display menu"); + var systems = Loader.config.systems; + var text = "\033[u\n\n\n\n"; + for(var i = 0; i < systems.length; i++) { + var string = "-> " + systems[i].label + " " + systems[i].kernel; + var length = Emulator.Output.xsize - string.length - 10 + text += "\033[5C\033[46m\033[31m" + ((i == Loader.selected) ? "->" : " ") + " \033[30m" + systems[i].label + " \033[34m" + systems[i].kernel; + for (var j = 0; j < length; j++) + text += " "; + text += "\033[0m\n"; + } + text += "\n\nSelect OS to boot... [w, s]"; + Emulator.output(text); +} +Loader.boot = function() { + var device = Emulator.Devices.getHarddisks(); + var system = Loader.config.systems[Loader.selected]; + device = device[system.hdd]; + var partition = device.partitions[system.partition]; + var loadstring = device.name + "/" + partition.name + "/" + system.kernel + Emulator.output("\n\nTrying to boot " + loadstring + ".."); + Loader.state = 3; + Emulator.Request.include(loadstring, Loader.finished); +} +Loader.finished = function() { + console.log("Loader: stop BIOS"); + console.log("loader: remove all event handlers"); + Emulator.interrupts = new Array(); + Emulator.unregisterTimer(Loader.tickid); + console.log("Loader: start OS"); + var system = Loader.config.systems[Loader.selected]; + try { + OS.main(system); + Emulator.output("\nKernel loaded successfully."); + } catch (exception) { + console.dir(exception); + Emulator.output("\nFailed to load kernel...\n\n"); + Emulator.output("\033[31msystem halt\033[0m"); + } +} diff --git a/wish-sys/sys-part/bin/hallo.js b/wish-sys/sys-part/bin/hallo.js new file mode 100644 index 0000000..d355301 --- /dev/null +++ b/wish-sys/sys-part/bin/hallo.js @@ -0,0 +1,8 @@ +var HalloClass = function() { +} +HalloClass.prototype = new Process(); +HalloClass.prototype.main = function() { + var stdout = this.files['stdout']; + stdout.write("Hallo Welt\n"); + this.exit(0); +} diff --git a/wish-sys/sys-part/bin/wsh.js b/wish-sys/sys-part/bin/wsh.js new file mode 100644 index 0000000..ce8ffe4 --- /dev/null +++ b/wish-sys/sys-part/bin/wsh.js @@ -0,0 +1,190 @@ +WshClass = function() { +} +WshClass.prototype = new Process(); +WshClass.prototype.state = 0; +WshClass.prototype.Environment = function() { +} +WshClass.prototype.Environment.array = new Array(); +WshClass.prototype.input = new Array(); +WshClass.prototype.lastExitCode = 0; +WshClass.prototype.childList = new Array(); +WshClass.prototype.main = function(args) { + console.log("wsh: adding to scheduler job list"); + Kernel.Scheduler.add(this); + this.username = args['1']; + this.Environment.array['HOME'] = args[2]; + this.Environment.array['PWD'] = args[2]; + +} +WshClass.prototype.tick = function() { + var stdout = this.files['stdout']; + var stdin = this.files['stdin']; + switch(this.state) { + case 0: + stdout.write("Welcome to WishOS 0.1 (WOSKernel 0.1)\n\n"); + this.files['profile.d'] = new File("/etc/profile.d/env.json"); + var array = JSON.parse(this.files['profile.d'].read()); + for (var i = 0; i < array.length; i++) { + while(array[i][1].indexOf("\\033") != -1) + array[i][1] = array[i][1].replace("\\033", "\033"); + this.Environment.array[array[i][0]] = array[i][1]; + } + this.state++; + break; + case 1: + var prompt = this.Environment.array['PS1']; + while (prompt.indexOf("\\w") != -1) + prompt = prompt.replace("\\w", (this.Environment.array['PWD'] == this.Environment.array['HOME']) ? "~" : this.Environment.array['PWD']); + while (prompt.indexOf("\\u") != -1) + prompt = prompt.replace("\\u", this.username); + while (prompt.indexOf("\\u") != -1) + prompt = prompt.replace("\\u", OS.hostname); + while (prompt.indexOf("\\$") != -1) + prompt = prompt.replace("\\$", (this.username == "root") ? "#" : "$"); + while (prompt.indexOf("\\#") != -1) + prompt = prompt.replace("\\#", (this.lastExitCode == 0) ? "" : this.lastExitCode); + stdout.write(prompt); + this.state++; + break; + case 2: + var code = stdin.read(); + if (!code) + break; + if (KeyCodes.isBackspace(code)) { + if (!this.input.length) + break; + this.input.pop(); + stdout.write("\033[1D \033[1D"); + break; + } + if (KeyCodes.isEnter(code)) { + stdout.write("\n"); + this.parseLine(); + break; + } + var char = KeyCodes.normalKey(code); + this.input.push(char); + stdout.write(char); + break; + case 3: + break; + case 4: + this.state = 1; + var params = this.input.join("").split(" "); + for (var i = 0; i < params.length; i++) + if (params[i].length == 0) + params.splice(i, 1); + stdout.write("wsh: command not found: " + params[0] + "\n"); + this.lastExitCode = 127; + this.input = new Array(); + break; + default: + break; + } +} +WshClass.prototype.parseLine = function() { + this.state = 1; + var command = this.input.join(""); + var params = command.split(" "); + for(var i = 0; i < params.length; i++) + if (params[i].length == 0) + params.splice(i, 1); + if (params.length == 0) { + return; + } + var ok = false; + var name = params[0]; + var file = ""; + if (name.substring(0, 1) == "/") + file = name + ".js"; + else if (name.indexOf("/") != -1) + file = this.Environment.array['PWD'] + name + ".js"; + else { + var paths = this.Environment.array['PATH'].split(":"); + for (var i = 0; i < paths.length; i++) { + file = paths[i] + "/" + name + ".js"; + console.log("wsh: trying: " + file); + if (this.tryFile(file)) { + ok = true; + break; + } + } + + } + if (this.tryFile(file)) { + console.log("wsh: files exists... yay...."); + ok = true; + } + if (!ok) { + this.state = 4; + return; + } + this.input = new Array(); + + this.state = 3; + var pathArray = new Array(); + pathArray[0] = ["stdout", this.files['stdout'].path]; + pathArray[1] = ["stdin", this.files['stdin'].path]; + var s = ""; + s += "var func = function () { "; + s += " try {"; + s += " var prog = new " + Kernel.ProcessManager.getClassNameFromFileName(command) + "();"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += " prog.init(" + this.pid + ");"; + s += " var paths = JSON.parse('" + JSON.stringify(pathArray) + "');"; + s += " for(var i = 0; i < paths.length; i++) {"; + s += " prog.files[paths[i][0]] = Kernel.Filesystem.getFile(paths[i][1]);"; + s += " }"; + s += " Kernel.ProcessManager.add(prog);"; + s += " console.log(\"wsh: start command '" + file + "'...\");"; + s += " try {"; + s += " prog.main(JSON.parse('" + JSON.stringify(params) + "'));"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += "}"; + eval(s); + Kernel.ProcessManager.load(file, func); +} +WshClass.prototype.tryFile = function(name) { + var file = new File(name); + return file.exists(); +} +WshClass.prototype.signalHandler = function(signal) { + switch(signal) { + case SIGCHLD: + var newChildList = Kernel.ProcessManager.getAllChilds(this.pid); + var oldChilds = this.childList.diff(newChildList); + var newChilds = newChildList.diff(this.childList); + if (newChilds.length) + console.log("wsh: we got " + newChilds.length + " new kid(s)... : )") + if (oldChilds.length) { + console.log("wsh: we lost " + oldChilds.length + " kid(s)"); + this.state = 1; + } + for (var i = 0; i < oldChilds.length; i++) { + this.lastExitCode = oldChilds[i].exitCode; + Kernel.ProcessManager.remove(oldChilds[i]); + } + this.childList = newChildList; + break; + case SIGHUP: + //break; + case SIGALRM: + //break; + case SIGTERM: + //break; + case SIGXCPU: + //break; + case SIGUSR1: + //break; + case SIGUSR2: + //break; + default: //SIGKILL + console.log("PID " + this.pid + " got Signal " + signal); + this.exit(1); + break; + } +} diff --git a/wish-sys/sys-part/etc/inittab.json b/wish-sys/sys-part/etc/inittab.json new file mode 100644 index 0000000..8f296d1 --- /dev/null +++ b/wish-sys/sys-part/etc/inittab.json @@ -0,0 +1,14 @@ +{ + "initdefault": 3, + "sysinit": [ + ], + "l3": [ + { + "command": "/sbin/login.js", + "files": [ + "stdout", + "stdin" + ] + } + ] +} diff --git a/wish-sys/sys-part/etc/passwd.json b/wish-sys/sys-part/etc/passwd.json new file mode 100644 index 0000000..846d1ca --- /dev/null +++ b/wish-sys/sys-part/etc/passwd.json @@ -0,0 +1,9 @@ +[ + { + "id": 0, + "username": "root", + "password": "ce5ca673d13b36118d54a7cf13aeb0ca012383bf771e713421b4d1fd841f539a", + "home": "/root/", + "shell": "/bin/wsh.js" + } +] diff --git a/wish-sys/sys-part/etc/profile.d/env.json b/wish-sys/sys-part/etc/profile.d/env.json new file mode 100644 index 0000000..96887ec --- /dev/null +++ b/wish-sys/sys-part/etc/profile.d/env.json @@ -0,0 +1,4 @@ +[ + ["PATH", "/bin:/sbin:/usr/bin:/usr/sbin"], + ["PS1", "\\033[31m\\#\\033[36m\\w \\$\\033[0m "] +] diff --git a/wish-sys/sys-part/kernel0.1.js b/wish-sys/sys-part/kernel0.1.js new file mode 100644 index 0000000..e542f2b --- /dev/null +++ b/wish-sys/sys-part/kernel0.1.js @@ -0,0 +1,414 @@ +const SIGHUP = 1; +const SIGKILL = 9; +const SIGALRM = 14; +const SIGTERM = 15; +const SIGCHLD = 20; +const SIGXCPU = 24; +const SIGUSR1 = 30; +const SIGUSR2 = 31; + +const APPND = 1; +const OVWRT = 2; + +const SYSHALT = 31415926 + +var OS = function() { +} +OS.system; +OS.runlevel; +OS.staticShift = 7; +OS.hostname = "wish"; +OS.logo = "\033[32m" + +" .__ .__ \n" + +"__ _ _|__| _____| |__ \n" + +"\\ \\/ \\/ / |/ ___/ | \\ \n" + +" \\ /| |\\___ \\| Y \\\n" + +" \\/\\_/ |__/____ >___| /\n" + +" \\/ \\/ \033[31mOS\033[0m\n"; +OS.main = function(system) { + console.log("OS: main"); + OS.system = system; + console.log("OS: init Kernel"); + Kernel.init(); +} + +var Kernel = function() { +} +Kernel.time; +Kernel.state; +Kernel.machineTimerId; +Kernel.globalLog; +Kernel.init = function() { + console.log("Kernel: init"); + Kernel.state = 0; + console.log("Kernel: main timer (100ms)"); + Kernel.machineTimerId = Emulator.registerTimer(100, Kernel.machine); + Kernel.globalLog = ""; +} +Kernel.machine = function() { + switch(Kernel.state) { + case 0: + Emulator.Output.shiftKey = OS.staticShift; + Emulator.output("\033[2J\033[0:0H" + OS.logo); + Kernel.msgOut("reseting kernel timer", true); + Kernel.time = 0; + Kernel.msgOut("register main timer (100ms)", true); // pre + Kernel.msgOut("init filesystem", true); + Kernel.Filesystem.init(); + Kernel.msgOut("init process manager", true); + Kernel.ProcessManager.init(); + Kernel.msgOut("init scheduler", true); + Kernel.Scheduler.init(); + Kernel.msgOut("init kernel io", true); + Kernel.IO.init(); + Kernel.msgOut(" register keyboard interrupt", true); + Emulator.interrupts['key'] = Kernel.IO.key; + Kernel.msgOut(" register power switch interrupt", true); + Emulator.interrupts['powersw'] = Kernel.IO.powersw; + Kernel.msgOut("loading /sbin/init.js"); + Kernel.ProcessManager.load("/sbin/init.js", Kernel.next); + Kernel.state++; + break; + case 1: + break; + case 2: + Kernel.msgSuccess(true); + Kernel.msgOut(" creating class instance", true); + var init = new InitClass(); + init.init(1); + Kernel.msgOut(" adding handler for stdio on /dev/tty1", true); + init.files['stdin'] = Kernel.Filesystem.getFile("/dev/tty1/i"); + init.files['stdout'] = Kernel.Filesystem.getFile("/dev/tty1/o"); + Kernel.msgOut(" adding to process list", true); + Kernel.ProcessManager.add(init); + Kernel.msgOut(" starting init", true); + init.main(); + Kernel.msgOut("register scheduler timer (1ms)", true); + Kernel.msgOut("starting scheduler", true); + Emulator.interrupts[0] = Kernel.Scheduler.tick; + Kernel.state++; + break; + case 3: + break; + default: + break; + } +} +Kernel.next = function() { + Kernel.state++; +} +Kernel.msgOut = function(text, success, color) { + while (text.length < Emulator.Output.xsize - 12) + text += " "; + text = "\n" + text; + if (color) { + text = color + text; + text += "\033[0m" + } + Kernel.globalLog += text; + Emulator.output(text); + Kernel.msgSuccess(success); +} +Kernel.msgSuccess = function(success) { + var text = ""; + if (success == true) + text = "[ \033[32msuccess\033[0m ]"; + else if (success == false) + text = "[ \033[31mfailed\033[0m ]"; + else + text = ""; + Kernel.globalLog += text; + Emulator.output(text); +} + +Kernel.Scheduler = function() { +} +Kernel.Scheduler.jobs; +Kernel.Scheduler.activ; +Kernel.Scheduler.working; +Kernel.Scheduler.init = function() { + Kernel.msgOut(" init job list", true); + Kernel.Scheduler.jobs = new Array(); + Kernel.Scheduler.activ = 0; + Kernel.Scheduler.working = false; +} +Kernel.Scheduler.tick = function() { + if (Kernel.Scheduler.working) { + Kernel.Scheduler.jobs[Kernel.Scheduler.activ].signalHandler(SIGXCPU); + Kernel.Scheduler.activ %= Kernel.Scheduler.jobs.length; + return; + } + Kernel.Scheduler.working = true; + Kernel.Scheduler.activ++; + Kernel.Scheduler.activ %= Kernel.Scheduler.jobs.length; + Kernel.Scheduler.jobs[Kernel.Scheduler.activ].tick(); + Kernel.time++; + Kernel.Scheduler.working = false; +} +Kernel.Scheduler.add = function(process) { + if (!process.tick) + return 2; // no tick method + for (var i = 0; i < this.jobs.length; i++) { + if (this.jobs[i].pid == process.pid) + return 3; // no double processes + } + this.jobs.push(process); + return 0; +} +Kernel.Scheduler.remove = function(process) { + for (var i = 0; i < this.jobs.length; i++) { + if (this.jobs[i].pid == process.pid) { + if (this.activ == i) + this.working = false; + this.jobs.splice(i, i); + return 0; // success + } + } + return 1; // not in list +} + +Kernel.ProcessManager = function() { +} +Kernel.ProcessManager.nextPid; +Kernel.ProcessManager.processList; +Kernel.ProcessManager.loadedList; +Kernel.ProcessManager.init = function() { + Kernel.msgOut(" init process list", true); + Kernel.ProcessManager.processList = new Array(); + Kernel.ProcessManager.loadedList = new Array(); + Kernel.ProcessManager.nextPid = 1; +} +Kernel.ProcessManager.add = function(process) { + this.processList[process.pid] = process; + if (process.pid != process.parentId) + this.processList[process.parentId].signalHandler(SIGCHLD); +} +Kernel.ProcessManager.quit = function(process) { + var parentId = process.parentId; + var pid = process.pid; + console.log("Kernel: quiting pid: " + pid); + Kernel.Scheduler.remove(process); + if (pid != parentId) + this.processList[parentId].signalHandler(SIGCHLD); +} +Kernel.ProcessManager.remove = function(process) { + this.processList.splice(process.pid, 1); + var childs = this.getAllChilds(process.pid); + for (var i = 0; i < childs.length; i++) + childs[i].parentId = 1; + if (childs.length > 0) + this.processList[1].signalHandler(SIGCHLD); +} +Kernel.ProcessManager.load = function(path, loaded) { + if (Kernel.ProcessManager.loadedList[path]) { + loaded(); + return; + } + Kernel.ProcessManager.loadedList[path] = true; + Emulator.Request.include(Kernel.Filesystem.getRealPath(path), loaded); +} +Kernel.ProcessManager.getAllChilds = function(pid) { + var kids = new Array(); + for(var index in Kernel.ProcessManager.processList) { + var proc = Kernel.ProcessManager.processList[index]; + if (proc.parentId == pid) { + if (proc.exitCode === undefined) + kids.push(proc); + } + } + return kids; +} +Kernel.ProcessManager.getPid = function() { + return Kernel.ProcessManager.nextPid++; +} +Kernel.ProcessManager.getClassNameFromFileName = function(name) { + name = name.split("/"); + name = name[name.length - 1]; + name = name[0].toUpperCase() + name.substring(1); + name = name.split(".")[0]; + name += "Class"; + return name; +} + +var Process = function(parentId) { +} +Process.prototype.pid; +Process.prototype.userId; +Process.prototype.parentId; +Process.prototype.files; +Process.prototype.exitCode; +Process.prototype.init = function(parentId) { + // DO NOT OVERWRITE + this.pid = Kernel.ProcessManager.getPid(); + this.parentId = parentId; + this.files = new Array(); +} +Process.prototype.main = function(args) { + +} +Process.prototype.tick = function() { +} +Process.prototype.exit = function(code) { + this.exitCode = code; + Kernel.ProcessManager.quit(this); +} +Process.prototype.signalHandler = function(signal) { + switch(signal) { + case SIGCHLD: + break; + case SIGHUP: + //break; + case SIGALRM: + //break; + case SIGTERM: + //break; + case SIGXCPU: + //break; + case SIGUSR1: + //break; + case SIGUSR2: + //break; + default: //SIGKILL + console.log("PID " + this.pid + " got Signal " + signal); + this.exit(1); + break; + } +} + +var File = function(path) { + this.path = path; +} +File.prototype.path; +File.prototype.position = 0; +File.prototype.writeMode = APPND; +File.prototype.forceUpdate = function() { + Kernel.Filesystem.update(this.path); +} +File.prototype.exists = function() { + return Kernel.Filesystem.getFile(this.path).exists() +} +File.prototype.read = function(length) { + var val = Kernel.Filesystem.getFile(this.path).read(this.position, length); + if (length) + this.position += length; + return val; +} +File.prototype.write = function(string) { + this.writeFIFO(string); +} +File.prototype.writeFIFO = function(string) { + Kernel.Filesystem.getFile(this.path).writeFIFO(string, writeMode); +} +File.prototype.writeLIFO = function(string) { + Kernel.Filesystem.getFile(this.path).writeLIFO(string, writeMode); +} + +var InnerFile = function(path) { + this.path = path; +} +InnerFile.prototype = new File; +InnerFile.prototype.content; +InnerFile.prototype.exists = function() { + return ((typeof this.content) != "number"); +} +InnerFile.prototype.read = function(position, length) { + if (!length) + return this.content; + return this.content.substring(position, position + length) +} +InnerFile.prototype.writeFIFO = function(string, mode) { + if (mode == APPND) + this.content += string; + if (mode == OVWRT) + this.content = string; +} +InnerFile.prototype.writeLIFO = function(string, mode) { + if (mode == APPND) + this.content = text + this.content; + if (mode == OVWRT) + this.content = string; +} + +Kernel.Filesystem = function() { +} +Kernel.Filesystem.devices; +Kernel.Filesystem.root; +Kernel.Filesystem.files; +Kernel.Filesystem.init = function() { + Kernel.msgOut(" geting device list", true); + Kernel.Filesystem.devices = Emulator.Devices.getAll(); + var hdd = Kernel.Filesystem.devices.harddisks[OS.system.hdd]; + var partition = hdd.partitions[OS.system.partition]; + Kernel.msgOut(" generating root path", true); + Kernel.Filesystem.root = hdd.name + "/" + partition.name; + Kernel.Filesystem.files = new Array(); + +} +Kernel.Filesystem.getFile = function(path) { + if (Kernel.Filesystem.files[path]) + return Kernel.Filesystem.files[path]; + return Kernel.Filesystem.update(path); + console.log("Kernel: get file " + path); +} +Kernel.Filesystem.update = function(path) { + var file = new InnerFile(path); + file.content = Emulator.Request.get(Kernel.Filesystem.getRealPath(path), "", false, ret); + Kernel.Filesystem.files[path] = file; + return file; +} +Kernel.Filesystem.getRealPath = function(name) { + return Kernel.Filesystem.root + name; +} +Kernel.Filesystem.addTTY = function(path, output, input) { + var out = new InnerFile(path + "/o"); + out.output = output; + out.writeFIFO = function(string) { + this.output(string); + } + out.writeLIFI = function(string) { + this.output(string.reverse()); + } + out.read = function() { + return ""; + } + var inp = new InnerFile(path + "/i"); + inp.input = input; + inp.writeFIFO = function(string) { + var input = this.input(); + input.reverse(); + for (var i = 0; i < string.length; i++) + input.push(char); + input.reverse(); + } + inp.writeLIFI = function(string) { + for(var i = 0; i < string.length; i++) + this.input().push(string[i]); + } + inp.read = function() { + return this.input().pop(); + } + Kernel.Filesystem.files[path + "/o"] = out; + Kernel.Filesystem.files[path + "/i"] = inp +} + + +Kernel.IO = function() { +} +Kernel.IO.inputBuffer; +Kernel.IO.init = function() { + Kernel.msgOut(" generating /dev/tty1", true); + Kernel.Filesystem.addTTY("/dev/tty1", Kernel.IO.output, Kernel.IO.input); + Kernel.IO.inputBuffer = new Array(); +} +Kernel.IO.key = function(code) { + Kernel.IO.inputBuffer.push(code); +} +Kernel.IO.powersw = function() { + console.log("Kernel: power switch pressed, but no action defined"); +} +Kernel.IO.input = function() { + return Kernel.IO.inputBuffer; +} +Kernel.IO.output = function(string) { + Emulator.output(string); +} diff --git a/wish-sys/sys-part/lib/sha256.js b/wish-sys/sys-part/lib/sha256.js new file mode 100644 index 0000000..d90f2a5 --- /dev/null +++ b/wish-sys/sys-part/lib/sha256.js @@ -0,0 +1,116 @@ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* SHA-256 implementation in JavaScript | (c) Chris Veness 2002-2010 | www.movable-type.co.uk */ +/* - see http://csrc.nist.gov/groups/ST/toolkit/secure_hashing.html */ +/* http://csrc.nist.gov/groups/ST/toolkit/examples.html */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +var Sha256 = {}; // Sha256 namespace + +/** + * Generates SHA-256 hash of string + * + * @param {String} msg String to be hashed + * @param {Boolean} [utf8encode=true] Encode msg as UTF-8 before generating hash + * @returns {String} Hash of msg as hex character string + */ +Sha256.hash = function(msg, utf8encode) { + utf8encode = (typeof utf8encode == 'undefined') ? true : utf8encode; + + // convert string to UTF-8, as SHA only deals with byte-streams + if (utf8encode) msg = Utf8.encode(msg); + + // constants [§4.2.2] + var K = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, + 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, + 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, + 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, + 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, + 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, + 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, + 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2]; + // initial hash value [§5.3.1] + var H = [0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19]; + + // PREPROCESSING + + msg += String.fromCharCode(0x80); // add trailing '1' bit (+ 0's padding) to string [§5.1.1] + + // convert string msg into 512-bit/16-integer blocks arrays of ints [§5.2.1] + var l = msg.length/4 + 2; // length (in 32-bit integers) of msg + ‘1’ + appended length + var N = Math.ceil(l/16); // number of 16-integer-blocks required to hold 'l' ints + var M = new Array(N); + + for (var i=0; i>> 32, but since JS converts + // bitwise-op args to 32 bits, we need to simulate this by arithmetic operators + M[N-1][14] = ((msg.length-1)*8) / Math.pow(2, 32); M[N-1][14] = Math.floor(M[N-1][14]) + M[N-1][15] = ((msg.length-1)*8) & 0xffffffff; + + + // HASH COMPUTATION [§6.1.2] + + var W = new Array(64); var a, b, c, d, e, f, g, h; + for (var i=0; i>> n) | (x << (32-n)); } +Sha256.Sigma0 = function(x) { return Sha256.ROTR(2, x) ^ Sha256.ROTR(13, x) ^ Sha256.ROTR(22, x); } +Sha256.Sigma1 = function(x) { return Sha256.ROTR(6, x) ^ Sha256.ROTR(11, x) ^ Sha256.ROTR(25, x); } +Sha256.sigma0 = function(x) { return Sha256.ROTR(7, x) ^ Sha256.ROTR(18, x) ^ (x>>>3); } +Sha256.sigma1 = function(x) { return Sha256.ROTR(17, x) ^ Sha256.ROTR(19, x) ^ (x>>>10); } +Sha256.Ch = function(x, y, z) { return (x & y) ^ (~x & z); } +Sha256.Maj = function(x, y, z) { return (x & y) ^ (x & z) ^ (y & z); } + +// +// hexadecimal representation of a number +// (note toString(16) is implementation-dependant, and +// in IE returns signed numbers when used on full words) +// +Sha256.toHexStr = function(n) { + var s="", v; + for (var i=7; i>=0; i--) { v = (n>>>(i*4)) & 0xf; s += v.toString(16); } + return s; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ diff --git a/wish-sys/sys-part/lib/utf8.js b/wish-sys/sys-part/lib/utf8.js new file mode 100644 index 0000000..a80563b --- /dev/null +++ b/wish-sys/sys-part/lib/utf8.js @@ -0,0 +1,63 @@ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ +/* Utf8 class: encode / decode between multi-byte Unicode characters and UTF-8 multiple */ +/* single-byte character encoding (c) Chris Veness 2002-2011 */ +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ + +/* changelog + * 2010-09-29: fixed decode order of operation to avoid falsely recognising decoded string as 3-byte + * utf-8 charaacter + */ + +var Utf8 = {}; // Utf8 namespace + +/** + * Encode multi-byte Unicode string into utf-8 multiple single-byte characters + * (BMP / basic multilingual plane only) + * + * Chars in range U+0080 - U+07FF are encoded in 2 chars, U+0800 - U+FFFF in 3 chars + * + * @param {String} strUni Unicode string to be encoded as UTF-8 + * @returns {String} encoded string + */ +Utf8.encode = function(strUni) { + // use regular expressions & String.replace callback function for better efficiency + // than procedural approaches + var strUtf = strUni.replace( + /[\u0080-\u07ff]/g, // U+0080 - U+07FF => 2 bytes 110yyyyy, 10zzzzzz + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xc0 | cc>>6, 0x80 | cc&0x3f); } + ); + strUtf = strUtf.replace( + /[\u0800-\uffff]/g, // U+0800 - U+FFFF => 3 bytes 1110xxxx, 10yyyyyy, 10zzzzzz + function(c) { + var cc = c.charCodeAt(0); + return String.fromCharCode(0xe0 | cc>>12, 0x80 | cc>>6&0x3F, 0x80 | cc&0x3f); } + ); + return strUtf; +} + +/** + * Decode utf-8 encoded string back into multi-byte Unicode characters + * + * @param {String} strUtf UTF-8 string to be decoded back to Unicode + * @returns {String} decoded string + */ +Utf8.decode = function(strUtf) { + // note: decode 3-byte chars first as decoded 2-byte strings could appear to be 3-byte char! + var strUni = strUtf.replace( + /[\u00e0-\u00ef][\u0080-\u00bf][\u0080-\u00bf]/g, // 3-byte chars + function(c) { // (note parentheses for precence) + var cc = ((c.charCodeAt(0)&0x0f)<<12) | ((c.charCodeAt(1)&0x3f)<<6) | ( c.charCodeAt(2)&0x3f); + return String.fromCharCode(cc); } + ); + strUni = strUni.replace( + /[\u00c0-\u00df][\u0080-\u00bf]/g, // 2-byte chars + function(c) { // (note parentheses for precence) + var cc = (c.charCodeAt(0)&0x1f)<<6 | c.charCodeAt(1)&0x3f; + return String.fromCharCode(cc); } + ); + return strUni; +} + +/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ diff --git a/wish-sys/sys-part/sbin/init.js b/wish-sys/sys-part/sbin/init.js new file mode 100644 index 0000000..19a7bee --- /dev/null +++ b/wish-sys/sys-part/sbin/init.js @@ -0,0 +1,189 @@ +var InitClass = function() { +} +InitClass.prototype = new Process(); +InitClass.prototype.childList; +InitClass.prototype.state = 0; +InitClass.prototype.inittab; +InitClass.prototype.destLevel; +InitClass.prototype.Start = function() { +} +InitClass.prototype.Start.array; +InitClass.prototype.Start.index; +InitClass.prototype.modifyLevel = false; +InitClass.prototype.main = function(args) { + this.childList = new Array(); + var stdout = this.files['stdout']; + if (this.pid == 1) { + stdout.write("\ninit: we are pid 1"); + stdout.write("\n trying to daemonize"); + stdout.write("\n adding to scheduler job list"); + Kernel.Scheduler.add(this); + } else { + + } +} +InitClass.prototype.tick = function() { + var stdout = this.files['stdout']; + var stdin = this.files['stdin']; + switch(this.state) { + case 0: + this.state++; + stdout.write("\ninit: we are a daemon now ... yay ..."); + stdout.write("\nreseting system runlevel"); + OS.runlevel = 0; + stdout.write("\nloading /etc/inittab.json ..."); + var file = Kernel.Filesystem.getFile("/etc/inittab.json"); + this.files[file.path] = file; + this.inittab = JSON.parse(file.read()); + break; + case 1: + this.state++; + if (this.destLevel = this.inittab.initdefault) + break; + this.state = 100; + break; + case 2: + this.state++; + stdout.write("\033[?25l\n"); + stdout.write("destination runlevel=" + this.destLevel); + break; + case 3: + this.Start.array = this.inittab.sysinit; + this.Start.index = 0; + this.state++; + break; + case 4: + if (this.Start.index >= this.Start.array.length) { + this.state = 5; + } else { + this.execProgram(); + this.Start.index++; + } + break; + case 5: + if (OS.runlevel == this.destLevel) { + this.state = 30; + break; + } else + this.state = 6; + OS.runlevel += Math.sign(this.destLevel - OS.runlevel); + console.log("init: entering runlevel " + OS.runlevel); + break; + case 6: + this.Start.array = this.getProgramsForRunlevel(OS.runlevel); + this.Start.index = 0; + this.state = 4; + break; + + case 30: + console.log("init: we are finished"); + this.state = 31; + break; + case 31: + break; + case 100: // input runlevel + this.state++; + stdout.write("\nno default runlevel defined"); + stdout.write("\ntype in destination level: \033[?25h"); + case 101: + var keycode = stdin.read(); + var char = KeyCodes.normalKey(keycode); + if (isNumber(char)) { + this.destLevel = parseInt(char); + this.state = 2; + } + break; + case SYSHALT: + break; + default: + break; + } +} +InitClass.prototype.changeRunlevel = function() { + Kernel.Filesystem.update("/tmp/destLevel.1"); + var runlevel = Kernel.Filesystem.getFile("/tmp/destLevel.1").read(); + this.destLevel = parseInt(runlevel); + this.state = 5; +} +InitClass.prototype.getProgramsForRunlevel = function(level) { + var array = eval("this.inittab.l" + level); + if (array) + return array; + return new Array(); +} +InitClass.prototype.execProgram = function() { + var command = this.Start.array[this.Start.index].command; + var params = command.split(" "); + var name = params[0]; + var files = this.Start.array[this.Start.index].files; + var pathArray = new Array(); + if (files) + for (var i = 0; i < files.length; i++) { + pathArray.push([files[i], this.files[files[i]].path]); + } + var s = ""; + s += "var func = function () { "; + s += " try {"; + s += " var prog = new " + Kernel.ProcessManager.getClassNameFromFileName(name) + "();"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += " prog.init(1);"; + s += " var paths = JSON.parse('" + JSON.stringify(pathArray) + "');"; + s += " for(var i = 0; i < paths.length; i++) {"; + s += " prog.files[paths[i][0]] = Kernel.Filesystem.getFile(paths[i][1]);"; + s += " }"; + s += " Kernel.ProcessManager.add(prog);"; + s += " console.log(\"init: start command '" + command + "'...\");"; + s += " try {"; + s += " prog.main(JSON.parse('" + JSON.stringify(params) + "'));"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += "}"; + eval(s); + Kernel.ProcessManager.load(name, func); +} +InitClass.prototype.signalHandler = function(signal) { + switch(signal) { + case SIGCHLD: + var newChildList = Kernel.ProcessManager.getAllChilds(this.pid); + var oldChilds = this.childList.diff(newChildList); + var newChilds = newChildList.diff(this.childList); + var logText = "init: We lost " + oldChilds.length + " kids and got " + newChilds.length + " new orphans (or selfmade kids)... : ("; + console.log(logText); + for (var i = 0; i < oldChilds; i++) + Kernel.ProcessManager.remove(oldChilds[i]); + this.childList = newChildList; + break; + case SIGHUP: + console.log("init: we lost File for stdout or stdin"); + break; + case SIGALRM: + console.log("init: we got alert signal, but we haven't set it") + break; + case SIGXCPU: + console.log("init: we need too much time"); + break; + case SIGUSR1: + console.log("init: Got usr1 signal. Looking up new runlevel from env"); + this.changeRunlevel(); + break; + case SIGUSR2: + console.log("init: Got usr2 signal. why??"); + break; + case SIGTERM: + console.log("init: They want us to terminale! D:"); + console.log("init: Let's kill the kernel... Muahahahaha..."); + Kernel.shutdown(); + break; + case SIGKILL: + console.log("init: Got kill signal, shuting down."); + Kernel.shutdown(); + break; + default: + console.log("PID " + this.pid + " got Signal " + signal); + // Kernel.ProcessManager.remove(this); + break; + } +} diff --git a/wish-sys/sys-part/sbin/init.old b/wish-sys/sys-part/sbin/init.old new file mode 100644 index 0000000..32f7fc6 --- /dev/null +++ b/wish-sys/sys-part/sbin/init.old @@ -0,0 +1,213 @@ +var InitClass = function() { +} +InitClass.prototype = new Process(); +InitClass.prototype.childList; +InitClass.prototype.state = 0; +InitClass.prototype.inittab; +InitClass.prototype.destLevel; +InitClass.prototype.Wait = function() { +} +InitClass.prototype.Wait.state = -1; +InitClass.prototype.Wait.array; + +InitClass.prototype.main = function(args) { + var stdout = this.files['stdout']; + if (this.pid == 1) { + stdout.write("\ninit: we are pid 1"); + stdout.write("\n setting runlvel 0 (we are not running yet)"); + OS.runlevel = 0; + stdout.write("\n trying to daemonize"); + stdout.write("\n adding to scheduler job list"); + Kernel.Scheduler.add(this); + } else { + + } +} +InitClass.prototype.tick = function() { + var stdout = this.files['stdout']; + var stdin = this.files['stdin']; + switch(this.state) { + case 0: + this.state++; + stdout.write("\ninit: we are a daemon now ... yay ..."); + stdout.write("\nloading /etc/inittab.json ..."); + var file = Kernel.Filesystem.getFile("/etc/inittab.json"); + this.files[file.path] = file; + this.inittab = JSON.parse(file.read()); + break; + case 1: + this.state++; + for (var i = 0; i < this.inittab.length; i++) { + if (this.inittab[i].action == "initdefault") { + this.destLevel = this.inittab[i].runlevels; + break; + } + } + if (this.destLevel) { + this.destLevel = parseInt(this.destLevel); + stdout.write("\nfound initdefault"); + stdout.write("\ndestination runlevel: " + this.destLevel + "\n"); + } else { + stdout.write("\nno initdefault"); + stdout.write("\nType in destination runlevel:\033[?25h "); + this.state = 25; + } + break; + case 2: + this.state++; + var array = new Array(); + stdout.write("looking for sysinit entrys...\n"); + for (var i = 0; i < this.inittab.length; i++) { + if (this.inittab[i].action == "sysinit") { + array.push(this.inittab[i].process); + } + } + if (array.length > 0) + stdout.write(" found: \n"); + for (var i = 0; i < array.length; i++) { + stdout.write(" " + array[i] + "\n"); + } + InitClass.execAll(array); + break; + case 3: + this.state++; + var array = new Array(); + stdout.write("looking for boot entrys...\n"); + for (var i = 0; i < this.inittab.length; i++) { + if (this.inittab[i].action == "boot") { + array.push(this.inittab[i].process); + } + } + if (array.length > 0) + stdout.write(" found: \n"); + for (var i = 0; i < array.length; i++) { + stdout.write(" " + array[i] + "\n"); + } + InitClass.execAll(array); + break; + case 4: + switch(this.Wait.state) { + case -1: + this.Wait.state = 0; + this.Wait.array = new Array(); + stdout.write("looking for bootwait entrys...\n"); + for (var i = 0; i < this.inittab.length; i++) { + if (this.inittab[i].action == "bootwait") { + this.Wait.array.push(this.inittab[i].process); + } + } + if (this.Wait.array.length > 0) + stdout.write(" found: \n"); + for (var i = 0; i < this.Wait.array.length; i++) { + stdout.write(" " + this.Wait.array[i] + "\n"); + } + break; + case -2: + this.Wait.state = 0; + this.state++; + break; + default: + if (this.Wait.state >= this.Wait.array.length) { + this.Wait.state = -2; + break; + } + InitClass.execWait(this.Wait.array[this.Wait.state], this.Wait); + } + break; + case 5: + break; + case 25: + var code = stdin.read(); + if (!code) + break; + var char = KeyCodes.normalKey(code); + if (isNumber(char)) { + this.destLevel = parseInt(char); + this.state = 2; + stdout.write("\n\033[?25ldestination runlevel: " + this.destLevel + "\n"); + } + break; + + case SYSHALT: + break; + default: + break; + } +} +InitClass.prototype.getStartScripts = function() { + +} +InitClass.prototype.getStopScripts = function() { + +} +InitClass.execAll = function(array) { + for (var i = 0; i < array.length; i++) { + var params = InitClass.splitParameter(array[i]); + var path = params[0]; + params.splice(0, 1); + var func; + eval("func = function() {InitClass.okay('" + path + "', '" + JSON.stringify(params) + "');}") + Kernel.ProcessManager.exec(path, func); + } +} +InitClass.okay = function(path, params) { + params = JSON.parse(params); + var name = path.split("/"); + name = name[name.length - 1]; + name = name[0].toUpperCase() + name.substring(1); + var prog = eval("new " + name + "Class(1)"); + Kernel.ProcessManager.add(prog); + prog.main(params); +} +InitClass.wait; +InitClass.execWait = function(line, wait) { + InitClass.wait = wait; + var params = InitClass.splitParameter(line); + var path = params[0]; + params.splice(0, 1); + var func; + eval("func = function() {InitClass.okayWait('" + path + "', '" + JSON.stringify(params) + "');}"); + Kernel.ProcessManager.exec(path, func); +} +InitClass.okayWait = function(path, params) { + InitClass.okay(path, params); + InitClass.wait.state++; +} +InitClass.splitParameter = function(line) { + var paramArray = line.split(" "); + for (var i = 0; i < paramArray.length; i++) { + if (paramArray[i] == "") { + paramArray.splice(i, 1); + i--; + } + } + return paramArray; +} +InitClass.prototype.signalHandler = function(signal) { + switch(signal) { + case SIGCHLD: + var newChildList = Kernel.ProcessManager.getAllChilds(this.pid); + var oldChilds = this.childList.diff(newChildList); + var newChilds = newChildList.diff(this.childList); + var logText = "init: We lost " + oldChilds.length + " kids and got " + newChilds.length + " new orphans... : ("; + console.log(logText); + this.childList = newChildList; + break; + case SIGHUP: + //break; + case SIGALRM: + //break; + case SIGTERM: + //break; + case SIGXCPU: + //break; + case SIGUSR1: + //break; + case SIGUSR2: + //break; + default: //SIGKILL + console.log("PID " + this.pid + " got Signal " + signal); + // Kernel.ProcessManager.remove(this); + break; + } +} diff --git a/wish-sys/sys-part/sbin/login.js b/wish-sys/sys-part/sbin/login.js new file mode 100644 index 0000000..0d104a1 --- /dev/null +++ b/wish-sys/sys-part/sbin/login.js @@ -0,0 +1,176 @@ +var LoginClass = function() { +} +LoginClass.prototype = new Process(); +LoginClass.prototype.state = 0; +LoginClass.prototype.childList = new Array(); +LoginClass.prototype.username; +LoginClass.prototype.password; +LoginClass.prototype.users; +LoginClass.prototype.user; +LoginClass.prototype.main = function(args) { + console.log("login: loading /lib/sha256.js"); + Kernel.ProcessManager.load("/lib/sha256.js", nothing); + console.log("login: loading /lib/utf8.js"); + Kernel.ProcessManager.load("/lib/utf8.js", nothing); + console.log("login: adding to scheduler job list"); + Kernel.Scheduler.add(this); +} +LoginClass.prototype.tick = function() { + var stdout = this.files['stdout']; + var stdin = this.files['stdin']; + switch(this.state) { + case 0: + stdout.write("\033[?25h\033[0:0H"); + if (OS.staticShift) + stdout.write("\033[0:" + (OS.staticShift - 1) + "H"); + stdout.write("\033[0J"); + this.state++; + break; + case 1: + this.username = new Array(); + this.password = new Array(); + stdout.write(OS.hostname + " login: "); + this.state++; + break; + case 2: + var code = stdin.read(); + if (!code) + break; + if (KeyCodes.isEnter(code)) { + this.state++; + stdout.write("\n"); + break; + } + if (KeyCodes.isBackspace(code)) { + if (!this.username.length) + break; + this.username.pop(); + stdout.write("\033[1D \033[1D"); + break; + } + var char = KeyCodes.normalKey(code); + this.username.push(char); + stdout.write(char); + break; + case 3: + stdout.write("password: "); + this.state++; + break; + case 4: + var code = stdin.read(); + if (!code) + break; + if (KeyCodes.isEnter(code)) { + this.state++; + stdout.write("\n"); + break; + } + if (KeyCodes.isBackspace(code)) { + if (!this.password.length) + break; + this.password.pop(); + break; + } + var char = KeyCodes.normalKey(code); + this.password.push(char); + break; + case 5: + this.username = this.username.join(""); + this.password = Sha256.hash(this.password.join("")); + this.files['passwd'] = Kernel.Filesystem.getFile("/etc/passwd.json"); + Kernel.Filesystem.update("/etc/passwd.json"); + this.users = JSON.parse(this.files['passwd'].read()); + this.state++; + break; + case 6: + for (var i = 0; i < this.users.length; i++) { + if (this.users[i].username == this.username) { + if (this.users[i].password == this.password) { + this.state = 7; + this.user = this.users[i]; + } + } + } + if (this.state == 6) { + this.state = 1; + stdout.write("\n"); + stdout.write("Login incorrect\n"); + } + break; + case 7: + stdout.write("\n"); + console.log("login: okay, user='" + this.user.username + "' shell='" + this.user.shell + "' dir='" + this.user.home + "'"); + this.execProgram(this.user); + this.state++; + break; + case 8: + break; + default: + break; + } +} +LoginClass.prototype.execProgram = function(user) { + var name = user.shell; + params = [name, user.username, user.home]; + var pathArray = new Array(); + pathArray[0] = ["stdout", this.files['stdout'].path]; + pathArray[1] = ["stdin", this.files['stdin'].path]; + var s = ""; + s += "var func = function () { "; + s += " try {"; + s += " var prog = new " + Kernel.ProcessManager.getClassNameFromFileName(name) + "();"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += " prog.init(" + this.pid + ");"; + s += " var paths = JSON.parse('" + JSON.stringify(pathArray) + "');"; + s += " for(var i = 0; i < paths.length; i++) {"; + s += " prog.files[paths[i][0]] = Kernel.Filesystem.getFile(paths[i][1]);"; + s += " }"; + s += " Kernel.ProcessManager.add(prog);"; + s += " console.log(\"login: start shell '" + name + "'...\");"; + s += " try {"; + s += " prog.main(JSON.parse('" + JSON.stringify(params) + "'));"; + s += " } catch (exception) {"; + s += " console.dir(exception);"; + s += " }"; + s += "}"; + eval(s); + Kernel.ProcessManager.load(name, func); +} +LoginClass.prototype.signalHandler = function(signal) { + switch(signal) { + case SIGCHLD: + var newChildList = Kernel.ProcessManager.getAllChilds(this.pid); + var oldChilds = this.childList.diff(newChildList); + var newChilds = newChildList.diff(this.childList); + if (newChilds.length) + console.log("login: we got " + newChilds.length + " new kid(s)... : )") + if (oldChilds.length) { + console.log("login: we lost " + oldChilds.length + " kid(s) (should be client shell)"); + console.log("login: trying to restart"); + this.state = 0; + } + for (var i = 0; i < oldChilds; i++) + Kernel.ProcessManager.remove(oldChilds[i]); + this.childList = newChildList; + break; + case SIGHUP: + //break; + case SIGALRM: + //break; + case SIGTERM: + //break; + case SIGXCPU: + //break; + case SIGUSR1: + //break; + case SIGUSR2: + //break; + default: //SIGKILL + console.log("PID " + this.pid + " got Signal " + signal); + Kernel.ProcessManager.remove(this); + break; + } +} +