diff --git a/Makefile b/Makefile index 466012e..a98c561 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ install: all mkdir -p ${CHROOT}/var/www cp ${WEBASSETS} ${CHROOT}/var/www cp rlgwebd.service /usr/lib/systemd/system - if test ! -f /etc/rlgwebd.conf; then cp rlgwebd.conf /etc; fi + if test ! -f /etc/rlgwebd.conf; cp rlgwebd.conf /etc; fi # Libraries are not removed. Something else might be using them. uninstall: diff --git a/README.txt b/README.txt index 4098765..391ef53 100644 --- a/README.txt +++ b/README.txt @@ -5,11 +5,12 @@ browser. It is intended to be compatible with dgamelaunch. Node --- -RLGWebD is currently being updated to work with Node v10.x. +RLGWebD currently works with Node v0.10. -It requires the 'posix', 'node-pty', and 'websocket' modules. Currently, -it expects them to be installed in "/var/local/lib/node_modules". It -is not recommended to run npm as root when installing the modules. +It requires the 'posix', 'pty.js', and 'websocket' modules. Currently, +it expects them to be installed in the global location, which is +"/usr/lib/node_modules". It is planned to eventually use a different +location so that npm will not need to run as root. init --- @@ -21,11 +22,14 @@ a proper initscript, but it could form the basis of one. Configuration --- -A configuration file is installed at /etc/rlgwebd.conf. It contains a -list of options. +You can set some options by changing some variables in the first few +lines of the rlgwebd script: -If the domain_name option and the SSL-related options are set, rlgwebd -will use HTTPS instead of insecure HTTP. +Option Variable Default + +Chroot path chrootDir /var/dgl +Username dropToUser rodney +Server port httpPort 8080 If you change the chroot location, change it in the first line of the Makefile too. @@ -55,7 +59,6 @@ Running "make install" will: Copy the C programs and the libraries they need into the chroot Install the main RLGWebD script in /usr/local/bin Place the systemd unit file in the proper directory - Copy a configuration file into /etc If you don't use systemd, or want to change the installation locations, you will have to edit the Makefile. diff --git a/initscript b/initscript index 9df71c7..5b311b9 100644 --- a/initscript +++ b/initscript @@ -1,8 +1,8 @@ #!/bin/sh -NODE_PATH=/var/local/lib/node_modules +NODE_PATH=/usr/lib/node_modules LOGFILE=/var/log/rlgwebd.log -CTLSOCKET=/var/run/rlgwebd/rlgwebd.sock +CTLSOCKET=/var/run/rlgwebd.sock RLGWEBDJS=/usr/local/bin/rlgwebd export NODE_PATH diff --git a/rlgwebd b/rlgwebd index 855caa8..9239d17 100755 --- a/rlgwebd +++ b/rlgwebd @@ -1,38 +1,35 @@ #!/usr/bin/env node -const http = require('http'); -const https = require('https'); -const net = require('net'); -const url = require('url'); -const path = require('path'); -const fs = require('fs'); -const events = require('events'); -const child_process = require('child_process'); +var http = require('http'); +var https = require('https'); +var net = require('net'); +var url = require('url'); +var path = require('path'); +var fs = require('fs'); +var events = require('events'); +var child_process = require('child_process'); // Dependencies -const posix = require("posix"); -const pty = require("node-pty"); -const WebSocketServer = require("websocket").server; - -const errorcodes = [ "Generic Error", "Not logged in", "Invalid data", - "Login failed", "Already playing", "Game launch failed", - "Server shutting down", "Game not in progress" ]; +var posix = require("posix"); +var pty = require("pty.js"); +var WebSocketServer = require("websocket").server; /* Default options */ var rlgwebd_options = { - control_socket: "/var/run/rlgwebd/rlgwebd.sock", - port: 8080, + control_socket: "/var/run/rlgwebd.sock", + http_port: 8080, + https_port: 8081, chrootDir: "/var/dgl/", username: "rodney", static_root: "/var/www/" }; /* Read configuration from a file */ -const config_file = "/etc/rlgwebd.conf"; +var config_file = "/etc/rlgwebd.conf"; var config_lines = read_or_die(config_file, "Configuration file").toString().split('\n'); -for (let conf_line of config_lines) { - if (conf_line.length > 0 && conf_line[0] != '#') { - var config_fields = conf_line.split('='); +for (var i = 0; i < config_lines.length; i++) { + if (config_lines[i].length > 0 && config_lines[i][0] != '#') { + var config_fields = config_lines[i].split('='); if (config_fields.length < 2) continue; var option_name = config_fields[0].trim(); @@ -47,13 +44,13 @@ if ("domain_name" in rlgwebd_options && "keyfile" in rlgwebd_options && "certfile" in rlgwebd_options) rlgwebd_options["use_https"] = true; -const clearbufs = [ - Buffer.from([27, 91, 72, 27, 91, 50, 74]), // xterm: CSI H CSI 2J - Buffer.from([27, 91, 72, 27, 91, 74]) // screen: CSI H CSI J +var clearbufs = [ + new Buffer([27, 91, 72, 27, 91, 50, 74]), // xterm: CSI H CSI 2J + new Buffer([27, 91, 72, 27, 91, 74]) // screen: CSI H CSI J ]; /* Data on the games available. */ -const games = { +var games = { "rogue3": { "name": "Rogue V3", "uname": "rogue3", @@ -113,7 +110,7 @@ function BaseGame() { this.watchers = []; /* replaybuf holds the output since the last screen clear, so watchers can * begin with a complete screen. replaylen is the number of bytes stored. */ - this.replaybuf = Buffer.alloc(1024); + this.replaybuf = new Buffer(1024); this.replaylen = 0; /* Time of last activity. */ this.lasttime = new Date(); @@ -129,12 +126,12 @@ BaseGame.prototype.tag = function () { BaseGame.prototype.framepush = function(chunk) { /* If this chunk resets the screen, discard what preceded it. */ if (isclear(chunk)) { - this.replaybuf = Buffer.alloc(1024); + this.replaybuf = new Buffer(1024); this.replaylen = 0; } /* Make sure there's space. */ while (this.replaybuf.length < chunk.length + this.replaylen) { - var nbuf = Buffer.alloc(this.replaybuf.length * 2); + var nbuf = new Buffer(this.replaybuf.length * 2); this.replaybuf.copy(nbuf, 0, 0, this.replaylen); this.replaybuf = nbuf; if (this.replaybuf.length > 65536) { @@ -214,9 +211,7 @@ function TermSession(gname, pname, wsReq) { var progressdir = path.join("/dgldir/inprogress", this.gname); this.lock = path.join(progressdir, this.pname + ":node:" + ts + ".ttyrec"); var lmsg = this.term.pid.toString() + '\n' + this.h + '\n' + this.w + '\n'; - fs.writeFile(this.lock, lmsg, "utf8", function (err) { - if (err) tslog("Locking failed: %s", err); - }); + fs.writeFile(this.lock, lmsg, "utf8"); var ttyrec = path.join("/dgldir/ttyrec", this.pname, this.gname, ts + ".ttyrec"); this.record = fs.createWriteStream(ttyrec, { mode: 0664 }); @@ -244,8 +239,8 @@ TermSession.prototype = new BaseGame(); /* Currently this also sends to the player and any watchers. */ TermSession.prototype.write_ttyrec = function (datastr) { this.lasttime = new Date(); - var buf = Buffer.from(datastr); - var chunk = Buffer.alloc(buf.length + 12); + var buf = new Buffer(datastr); + var chunk = new Buffer(buf.length + 12); /* TTYREC headers */ chunk.writeUInt32LE(Math.floor(this.lasttime.getTime() / 1000), 0); chunk.writeUInt32LE(1000 * (this.lasttime.getTime() % 1000), 4); @@ -279,7 +274,7 @@ TermSession.prototype.input_msg = function (message) { if (hexstr.length % 2 != 0) { hexstr = hexstr.slice(0, -1); } - var keybuf = Buffer.from(hexstr, "hex"); + var keybuf = new Buffer(hexstr, "hex"); this.write(keybuf); } }; @@ -292,9 +287,7 @@ TermSession.prototype.close = function () { TermSession.prototype.destroy = function () { var tag = this.tag(); - fs.unlink(this.lock, function (err) { - if (err) tslog("Lock removal failed: %s", err); - }); + fs.unlink(this.lock); this.record.end(); var watchsocks = this.watchers; this.watchers = []; @@ -363,7 +356,7 @@ DglSession.prototype.startchunk = function () { if (this.reading) return; this.reading = true; - var header = Buffer.alloc(12); + var header = new Buffer(12); fs.read(this.fd, header, 0, 12, this.rpos, this.datachunk.bind(this)); }; @@ -384,7 +377,7 @@ DglSession.prototype.datachunk = function (err, n, buf) { // Something is probably wrong... tslog("DGL %s: looking for %d bytes", this.tag(), datalen); } - var databuf = Buffer.alloc(datalen); + var databuf = new Buffer(datalen); fs.read(this.fd, databuf, 0, datalen, this.rpos, this.handledata.bind(this)); }; @@ -401,9 +394,9 @@ DglSession.prototype.handledata = function (err, n, buf) { /* Process the data */ this.framepush(buf); var wmsg = JSON.stringify({"t": "d", "d": buf.toString("hex")}); - for (let watcher of this.watchers) { - if (watcher.connected) - watcher.sendUTF(wmsg); + for (var i = 0; i < this.watchers.length; i++) { + if (this.watchers[i].connected) + this.watchers[i].sendUTF(wmsg); } this.emit("data", buf); /* Recurse. */ @@ -418,9 +411,7 @@ DglSession.prototype.notifier = function (ev, finame) { }; DglSession.prototype.close = function () { - /* The watcher might not be open yet. */ - if ("recwatcher" in this) - this.recwatcher.close(); + this.recwatcher.close(); /* Ensure all data is handled before quitting. */ this.startchunk(); var connlist = this.watchers; @@ -429,9 +420,7 @@ DglSession.prototype.close = function () { if (connlist[i].connected) connlist[i].close(); } - fs.close(this.fd, function (err) { - if (err) tslog("PTY close failed: %s", err); - }); + fs.close(this.fd); this.emit("close"); gamemux.emit('end', this.gname, this.pname); tslog("DGL %s: closed", this.tag()); @@ -498,11 +487,8 @@ function checksaved(user, game, callback, args) { var savedirc = game.uname + "save"; var basename = String(pwent.uid) + "-" + user + game.suffix; var savefile = path.join("/var/games/roguelike", savedirc, basename); - fs.access(savefile, function (err) { - if (err) - args.unshift(false); - else - args.unshift(true); + fs.exists(savefile, function (exist) { + args.unshift(exist); callback.apply(null, args); }); } @@ -581,8 +567,8 @@ function bufncmp(buf1, buf2, n) { } function isclear(buf) { - for (let clearer of clearbufs) { - if (bufncmp(buf, clearer, clearer.length)) + for (var i = 0; i < clearbufs.length; i++) { + if (bufncmp(buf, clearbufs[i], clearbufs[i].length)) return true; } return false; @@ -702,15 +688,10 @@ function login(req, res, formdata) { function regsetup(username) { function regsetup_l2(err) { for (var g in games) { - fs.mkdir(path.join("/dgldir/ttyrec", username, games[g].uname), 0755, - function (err) { - if (err) tslog("ttyrec mkdir failed: %s", err); - }); + fs.mkdir(path.join("/dgldir/ttyrec", username, games[g].uname), 0755); } } - fs.mkdir(path.join("/dgldir/userdata", username), 0755, function (err) { - if (err) tslog("Userdata mkdir failed: %s", err); - }); + fs.mkdir(path.join("/dgldir/userdata", username), 0755); fs.mkdir(path.join("/dgldir/ttyrec/", username), 0755, regsetup_l2); } @@ -798,9 +779,7 @@ function stopgame(res, formdata) { if (err.code == "ESRCH") { var nodere = RegExp("^" + pname + ":node:"); if (fname.match(nodere)) { - fs.unlink(fullfile, function (err) { - if (err) tslog("Stale lock removal failed: %s", err); - }); + fs.unlink(fullfile); } } } @@ -853,8 +832,6 @@ function startProgressWatcher() { } function serveStatic(req, res, fname) { - if (fname[0] !== "/") - fname = "/" + fname; var nname = path.normalize(fname); if (nname == "" || nname == "/") nname = "index.html"; @@ -862,9 +839,9 @@ function serveStatic(req, res, fname) { path.join(nname, "index.html"); /* it was a directory */ var realname = path.join(rlgwebd_options.static_root, nname); var extension = path.extname(realname); - fs.access(realname, function (access_err) { + fs.exists(realname, function (exists) { var resheaders = {}; - if (access_err || !extension || extension == ".html") + if (!exists || !extension || extension == ".html") resheaders["Content-Type"] = "text/html; charset=utf-8"; else if (extension == ".png") resheaders["Content-Type"] = "image/png"; @@ -876,7 +853,7 @@ function serveStatic(req, res, fname) { resheaders["Content-Type"] = "image/svg+xml"; else resheaders["Content-Type"] = "application/octet-stream"; - if (!access_err) { + if (exists) { fs.readFile(realname, function (error, data) { if (error) { res.writeHead(500, {}); @@ -1047,6 +1024,10 @@ function setuinfo(req, res, postdata) { } } +var errorcodes = [ "Generic Error", "Not logged in", "Invalid data", + "Login failed", "Already playing", "Game launch failed", + "Server shutting down", "Game not in progress" ]; + function sendError(res, ecode, msg, box) { res.writeHead(200, { "Content-Type": "application/json" }); var edict = {"t": "E"}; @@ -1283,21 +1264,6 @@ if (rlgwebd_options.use_https) { tls_options.ca = read_or_die(rlgwebd_options.cafile, "CA file"); }; -/* Make sure the socket directory is secure. */ -var socket_dir = path.dirname(rlgwebd_options.control_socket); -try { - fs.mkdirSync(socket_dir, 0o700); -} -catch (err) { - if (err.code == "EEXIST") { - fs.chownSync(socket_dir, 0, 0); - fs.chmodSync(socket_dir, 0o700); - } - else { - throw err; - } -} - /* Open the control socket before chrooting where it can't be found */ var ctlServer = net.createServer(function (sock) { sock.on('data', consoleHandler); @@ -1322,22 +1288,20 @@ ctlServer.listen(rlgwebd_options.control_socket, function () { tslog("Could not drop permissions: %s", err); process.exit(1); } + httpServer = http.createServer(webHandler); + httpServer.listen(rlgwebd_options.http_port); + tslog('rlgwebd running on port %d', rlgwebd_options.http_port); + wsServer = new WebSocketServer({"httpServer": httpServer}); + wsServer.on("request", wsHandler); + tslog('WebSockets are online'); if (rlgwebd_options.use_https) { - httpServer = https.createServer(tls_options, webHandler); - httpServer.listen(rlgwebd_options.port); - tslog('rlgwebd running on port %d (TLS)', rlgwebd_options.port); - wsServer = new WebSocketServer({"httpServer": httpServer}); - wsServer.on("request", wsHandler); + var httpsServer = https.createServer(tls_options, webHandler); + httpsServer.listen(rlgwebd_options.https_port); + tslog('TLS running on port %d', rlgwebd_options.https_port); + var wssServer = new WebSocketServer({"httpServer": httpsServer}); + wssServer.on("request", wsHandler); tslog('Secure WebSockets are online'); } - else { - httpServer = http.createServer(webHandler); - httpServer.listen(rlgwebd_options.port); - tslog('rlgwebd running on port %d', rlgwebd_options.port); - wsServer = new WebSocketServer({"httpServer": httpServer}); - wsServer.on("request", wsHandler); - tslog('WebSockets are online'); - } progressWatcher = startProgressWatcher(); setInterval(pushStatus, 40000); }); diff --git a/rlgwebd-stop b/rlgwebd-stop index 5e81ea1..d81b5f5 100755 --- a/rlgwebd-stop +++ b/rlgwebd-stop @@ -1,19 +1,22 @@ #!/usr/bin/env node var net = require('net'); -var sockpath = "/var/run/rlgwebd/rlgwebd.sock"; +var domain = require('domain'); +var sockpath = "/var/run/rlgwebd.sock"; -var sock = new net.Socket(); +var dom = domain.create(); -sock.on('error', function (err) { +dom.on('error', function (err) { console.log("Cannot connect to " + sockpath + ", rlgwebd already stopped."); process.exit(0); }); -sock.connect(sockpath, function () { - sock.on('close', function (had_error) { - if (process.argv[2] == "debug") - console.log("Control socket closed"); +dom.run(function () { + var sock = net.connect(sockpath, function () { + sock.on('close', function () { + if (process.argv[2] == "debug") + console.log("Control socket closed"); + }); + sock.write("quit\n"); }); - sock.write("quit\n"); }); diff --git a/rlgwebd.conf b/rlgwebd.conf index a2ccd44..5d67cd5 100644 --- a/rlgwebd.conf +++ b/rlgwebd.conf @@ -3,9 +3,11 @@ # These values are set by default: # Location of the socket for start/stop commands -#control_socket = /var/run/rlgwebd/rlgwebd.sock +#control_socket = /var/run/rlgwebd.sock # Port number to bind -#port = 8080 +#http_port = 8080 +# Port number for HTTPS +#https_port = 8081 # Path to the dgamelaunch installation to chroot into # If you change this, change the Makefile too #chrootDir = /var/dgl/ diff --git a/rlgwebd.service b/rlgwebd.service index 9014502..ec0ab3a 100644 --- a/rlgwebd.service +++ b/rlgwebd.service @@ -4,7 +4,7 @@ After=network.target syslog.target [Service] Type=simple -Environment=NODE_PATH=/var/local/lib/node_modules +Environment=NODE_PATH=/usr/lib/node_modules ExecStart=/usr/local/bin/rlgwebd ExecStop=/usr/local/bin/rlgwebd-stop Restart=on-failure diff --git a/termemu.js b/termemu.js index 0a4f74d..5e4ad1a 100644 --- a/termemu.js +++ b/termemu.js @@ -71,7 +71,6 @@ var termemu = { scrB: 0, // init() will set this properly c: null, // Contains cursor position and text attributes offedge: false, // Going off the edge doesn't mean adding a new line - lastcode: 0, // Last printed character clearAttrs: function () { /* Make sure to reset ALL attribute properties and NOTHING else. */ this.c.bold = false; @@ -461,7 +460,6 @@ var termemu = { this.screen.replaceChild(this.makeRow(), this.screen.childNodes[i]); } this.flipCursor(); // make it appear in the new row - this.lastcode = 0; return; }, write: function (codes) { @@ -533,10 +531,6 @@ var termemu = { debug(1, "Unrecognized sequence ESC " + codes[i].toString(16)); this.comseq = []; } - if (this.comseq.length == 0) { - // A complete sequence was processed, clear lastcode. - this.lastcode = 0; - } } else if (this.comseq.length == 2 && this.comseq[0] == 27) { /* An ESC C N sequence. Not implemented. Doesn't check validity @@ -561,7 +555,6 @@ var termemu = { String.fromCharCode(this.comseq[1]) + " 0x" + codes[i].toString(16)); this.comseq = []; - this.lastcode = 0; } else if (this.comseq[0] == 157) { /* Commands beginning with OSC */ @@ -573,7 +566,6 @@ var termemu = { debug(0, "Got " + (this.comseq.length - 1) + "-byte OSC sequence"); this.oscProcess(); this.comseq = []; - this.lastcode = 0; } else this.comseq.push(codes[i]); @@ -590,17 +582,15 @@ var termemu = { /* Chars in csiPre can only occur right after the CSI */ debug(1, "Invalid CSI sequence: misplaced prefix"); this.comseq = []; - this.lastcode = 0; } else this.comseq.push(codes[i]); } else if (csiPost.indexOf(this.comseq[this.comseq.length - 1]) >= 0 && !csiFinal(codes[i])) { - /* Chars in csiPost must come right before the final char */ + /* Chars is csiPost must come right before the final char */ debug(1, "Invalid CSI sequence: misplaced postfix"); this.comseq = []; - this.lastcode = 0; } else if ((codes[i] >= 48 && codes[i] <= 57) || codes[i] == 59 || csiPost.indexOf(codes[i]) >= 0) { @@ -615,102 +605,91 @@ var termemu = { else { debug(1, "Invalid CSI sequence: unknown code " + codes[i].toString(16)); this.comseq = []; - this.lastcode = 0; } } else { debug(1, "Unknown sequence with " + this.comseq[0].toString(16)); this.comseq = []; - this.lastcode = 0; + } + continue; + } + /* Treat it as a single character. */ + if (codes[i] == 5) { + sendback("06"); + } + else if (codes[i] == 7) { + /* bell */ + bell(true); + } + else if (codes[i] == 8) { + /* backspace */ + if (this.offedge) + this.offedge = false; + else if (this.c.x > 0) + this.cmove(null, this.c.x - 1); + } + else if (codes[i] == 9) { + /* tab */ + var xnew; + if (this.c.x < this.w - 1) { + xnew = 8 * (Math.floor(this.c.x / 8) + 1); + if (xnew >= this.w) + xnew = this.w - 1; + this.cmove(null, xnew); + } + else { + this.offedge = true; } } - else if ((codes[i] >= 32 && codes[i] < 127) || codes[i] >= 160) { + else if (codes[i] >= 10 && codes[i] <= 12) { + /* newline, vertical tab, form feed */ + if (this.offedge) + this.newline(true); + else + this.newline(false); + } + else if (codes[i] == 13) { + /* carriage return \r */ + this.cmove(null, 0); + } + else if (codes[i] == 14) { + /* shift out */ + // Currently assuming that G1 is DEC Special & Line Drawing + this.c.cset = "0"; + debug(0, "Using DEC graphics charset."); + } + else if (codes[i] == 15) { + /* shift in */ + // Currently assuming that G0 is ASCII + this.c.cset = "B"; + debug(0, "Using ASCII charset."); + } + else if (codes[i] == 27) { + /* escape */ + this.comseq.push(codes[i]); + } + else if (codes[i] < 32 || (codes[i] >= 127 && codes[i] < 160)) { + /* Some kind of control character. */ + debug(1, "Unprintable character 0x" + codes[i].toString(16)); + } + else { /* If it's ASCII, it's printable; take a risk on anything higher */ if ((this.c.cset == "0") && (codes[i] in decChars)) { // DEC special character set - this.lastcode = decChars[codes[i]]; + this.placechar(String.fromCharCode(decChars[codes[i]])); } else { - this.lastcode = codes[i]; + this.placechar(String.fromCharCode(codes[i])); } - this.placechar(String.fromCharCode(this.lastcode)); - } - else { - /* Treat it as a single control character. */ - this.singleCtl(codes[i]); } } return; }, - singleCtl: function (ctlcode) { - if (ctlcode == 5) { - sendback("06"); - } - else if (ctlcode == 7) { - /* bell */ - bell(true); - } - else if (ctlcode == 8) { - /* backspace */ - if (this.offedge) - this.offedge = false; - else if (this.c.x > 0) - this.cmove(null, this.c.x - 1); - } - else if (ctlcode == 9) { - /* tab */ - var xnew; - if (this.c.x < this.w - 1) { - xnew = 8 * (Math.floor(this.c.x / 8) + 1); - if (xnew >= this.w) - xnew = this.w - 1; - this.cmove(null, xnew); - } - else { - this.offedge = true; - } - } - else if (ctlcode >= 10 && ctlcode <= 12) { - /* newline, vertical tab, form feed */ - if (this.offedge) - this.newline(true); - else - this.newline(false); - } - else if (ctlcode == 13) { - /* carriage return \r */ - this.cmove(null, 0); - } - else if (ctlcode == 14) { - /* shift out */ - // Currently assuming that G1 is DEC Special & Line Drawing - this.c.cset = "0"; - debug(0, "Using DEC graphics charset."); - } - else if (ctlcode == 15) { - /* shift in */ - // Currently assuming that G0 is ASCII - this.c.cset = "B"; - debug(0, "Using ASCII charset."); - } - else if (ctlcode == 27) { - /* escape */ - this.comseq.push(27); - } - else { - debug(1, "Unprintable character 0x" + ctlcode.toString(16)); - } - if (ctlcode != 27) { - // Sequences should preserve lastcode until they are completed - this.lastcode = 0; - } - }, csiProcess: function () { /* Processes the CSI sequence in this.comseq */ var c = this.comseq[this.comseq.length - 1]; if (this.comseq[0] != 155 || !csiFinal(c)) return; - var printed = false; var comstr = ""; for (var i = 1; i < this.comseq.length; i++) comstr += String.fromCharCode(this.comseq[i]); @@ -719,7 +698,6 @@ var termemu = { var matchCSI = comstr.match(reCSI); if (!matchCSI) { debug(1, "Unrecognized CSI sequence: " + comstr); - this.lastcode = 0; return; } var prefix = null; @@ -747,7 +725,6 @@ var termemu = { /* @ - insert spaces at cursor */ if (prefix || postfix) { debug(1, "Invalid CSI @ sequence: " + comstr); - this.lastcode = 0; return; } /* The cursor stays still, but characters move out from under it. */ @@ -768,7 +745,6 @@ var termemu = { /* E - next line, F - previous line, G - to column */ if (prefix || postfix) { debug(1, "Invalid CSI sequence: " + comstr); - this.lastcode = 0; return; } /* These may be out of range, but cmove will take care of that. */ @@ -793,7 +769,6 @@ var termemu = { var y = 0; if (prefix || postfix) { debug(1, "Invalid CSI H sequence: " + comstr); - this.lastcode = 0; return; } if (params[0]) @@ -812,7 +787,6 @@ var termemu = { var x = this.c.x; if (prefix || postfix) { debug(1, "Invalid CSI I sequence: " + comstr); - this.lastcode = 0; return; } while (count > 0) { @@ -834,7 +808,6 @@ var termemu = { debug(1, "Warning: CSI ?J not implemented"); else if (prefix || postfix) { debug(1, "Invalid CSI J sequence: " + comstr); - this.lastcode = 0; return; } if (!params[0]) { @@ -855,7 +828,6 @@ var termemu = { } else { debug(1, "Unimplemented parameter in CSI J sequence: " + comstr); - this.lastcode = 0; return; } for (var nrow = start; nrow <= end; nrow++) { @@ -883,7 +855,6 @@ var termemu = { debug(1, "Warning: CSI ?K not implemented"); else if (prefix || postfix) { debug(1, "Invalid CSI K sequence: " + comstr); - this.lastcode = 0; return; } /* 0 (default): right, 1: left, 2: all. Include cursor position. */ @@ -914,14 +885,11 @@ var termemu = { * M - delete current lines */ if (prefix || postfix) { debug(1, "Invalid CSI sequence: " + comstr); - this.lastcode = 0; return; } /* CSI LM have no effect outside of the scrolling region */ - if (this.c.y < this.scrT || this.c.y > this.scrB) { - this.lastcode = 0; + if (this.c.y < this.scrT || this.c.y > this.scrB) return; - } this.flipCursor(); while (count > 0) { var blankrow = this.makeRow(); @@ -947,7 +915,6 @@ var termemu = { /* P - delete at active position, causing cells on the right to shift. */ if (prefix || postfix) { debug(1, "Invalid CSI P sequence: " + comstr); - this.lastcode = 0; return; } var cursrow = this.screen.childNodes[this.c.y]; @@ -963,7 +930,6 @@ var termemu = { /* S - scroll up, T - scroll down */ if (prefix || postfix) { debug(1, "Invalid CSI sequence: " + comstr); - this.lastcode = 0; return; } if (c == 83) @@ -975,7 +941,6 @@ var termemu = { /* X - erase characters */ if (prefix || postfix) { debug(1, "Invalid CSI sequence: " + comstr); - this.lastcode = 0; return; } var row = this.screen.childNodes[this.c.y]; @@ -989,7 +954,6 @@ var termemu = { var x = this.c.x; if (prefix || postfix) { debug(1, "Invalid CSI Z sequence: " + comstr); - this.lastcode = 0; return; } while (count > 0) { @@ -1006,26 +970,14 @@ var termemu = { /* ` - go to col */ if (prefix || postfix) { debug(1, "Invalid CSI ` sequence: " + comstr); - this.lastcode = 0; return; } this.cmove(null, count - 1); } - else if (c == 98) { - /* b - repeat previous character */ - if (this.lastcode !== 0) { - while (count > 0) { - this.placechar(String.fromCharCode(this.lastcode)); - count--; - } - printed = true; - } - } else if (c == 99) { /* c - query terminal attributes */ if (prefix !== null) { debug(1, "Unimplemented CSI sequence: " + comstr); - this.lastcode = 0; return; } /* "CSI ? 1 ; 2 c" - VT100 */ @@ -1035,7 +987,6 @@ var termemu = { /* d - go to row */ if (prefix || postfix) { debug(1, "Invalid CSI d sequence: " + comstr); - this.lastcode = 0; return; } this.cmove(count - 1, null); @@ -1046,7 +997,6 @@ var termemu = { var y = 0; if (prefix || postfix) { debug(1, "Invalid CSI f sequence: " + comstr); - this.lastcode = 0; return; } if (params[0]) @@ -1059,7 +1009,6 @@ var termemu = { /* h - set modes */ if (prefix != '?') { debug(1, "Unimplemented CSI sequence: " + comstr); - this.lastcode = 0; return; } for (var i = 0; i < params.length; i++) { @@ -1098,7 +1047,6 @@ var termemu = { } else { debug(1, "Unimplemented CSI sequence: " + comstr); - this.lastcode = 0; return; } } @@ -1132,7 +1080,6 @@ var termemu = { /* m - character attributes */ if (prefix !== null) { debug(1, "Unimplemented CSI sequence: " + comstr); - this.lastcode = 0; return; } if (params.length == 0) @@ -1186,18 +1133,15 @@ var termemu = { t = params[0] - 1; if (params[1] && params[1] <= this.h) b = params[1] - 1; - if (b > t) { - this.scrT = t; - this.scrB = b; - this.cmove(0, 0); - } + if (b <= t) + return; + this.scrT = t; + this.scrB = b; + this.cmove(0, 0); } else { debug(1, "Unimplemented CSI sequence: " + comstr); } - if (!printed) { - this.lastcode = 0; - } return; }, oscProcess: function () {