From fbd7ede70021e85360a0f4e14327abb58469ba6b Mon Sep 17 00:00:00 2001 From: overflowerror Date: Sat, 20 Jul 2013 16:09:10 +0200 Subject: [PATCH] first commit --- BIOS.js | 95 ++++ Emulator.js | 603 +++++++++++++++++++++++ KeyCodes.js | 20 + README | 0 devices.json | 15 + index.html | 41 ++ main.js | 33 ++ wish-sys/mbr/config.json | 13 + wish-sys/mbr/init.js | 107 ++++ wish-sys/sys-part/bin/hallo.js | 8 + wish-sys/sys-part/bin/wsh.js | 190 +++++++ wish-sys/sys-part/etc/inittab.json | 14 + wish-sys/sys-part/etc/passwd.json | 9 + wish-sys/sys-part/etc/profile.d/env.json | 4 + wish-sys/sys-part/kernel0.1.js | 414 ++++++++++++++++ wish-sys/sys-part/lib/sha256.js | 116 +++++ wish-sys/sys-part/lib/utf8.js | 63 +++ wish-sys/sys-part/sbin/init.js | 189 +++++++ wish-sys/sys-part/sbin/init.old | 213 ++++++++ wish-sys/sys-part/sbin/login.js | 176 +++++++ 20 files changed, 2323 insertions(+) create mode 100644 BIOS.js create mode 100644 Emulator.js create mode 100644 KeyCodes.js create mode 100644 README create mode 100644 devices.json create mode 100644 index.html create mode 100644 main.js create mode 100644 wish-sys/mbr/config.json create mode 100644 wish-sys/mbr/init.js create mode 100644 wish-sys/sys-part/bin/hallo.js create mode 100644 wish-sys/sys-part/bin/wsh.js create mode 100644 wish-sys/sys-part/etc/inittab.json create mode 100644 wish-sys/sys-part/etc/passwd.json create mode 100644 wish-sys/sys-part/etc/profile.d/env.json create mode 100644 wish-sys/sys-part/kernel0.1.js create mode 100644 wish-sys/sys-part/lib/sha256.js create mode 100644 wish-sys/sys-part/lib/utf8.js create mode 100644 wish-sys/sys-part/sbin/init.js create mode 100644 wish-sys/sys-part/sbin/init.old create mode 100644 wish-sys/sys-part/sbin/login.js 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; + } +} +