| | "use strict"; |
| | |
| | |
| | |
| | |
| | |
| | Object.defineProperty(exports, "__esModule", { value: true }); |
| | var os = require("os"); |
| | var path = require("path"); |
| | var net_1 = require("net"); |
| | var child_process_1 = require("child_process"); |
| | var conptyNative; |
| | var winptyNative; |
| | |
| | |
| | |
| | |
| | |
| | var FLUSH_DATA_INTERVAL = 20; |
| | |
| | |
| | |
| | |
| | var WindowsPtyAgent = (function () { |
| | function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConpty, conptyInheritCursor) { |
| | var _this = this; |
| | if (conptyInheritCursor === void 0) { conptyInheritCursor = false; } |
| | this._useConpty = _useConpty; |
| | if (this._useConpty === undefined || this._useConpty === true) { |
| | this._useConpty = this._getWindowsBuildNumber() >= 18309; |
| | } |
| | if (this._useConpty) { |
| | if (!conptyNative) { |
| | try { |
| | conptyNative = require('../build/Release/conpty.node'); |
| | } |
| | catch (outerError) { |
| | try { |
| | conptyNative = require('../build/Debug/conpty.node'); |
| | } |
| | catch (innerError) { |
| | console.error('innerError', innerError); |
| | |
| | throw outerError; |
| | } |
| | } |
| | } |
| | } |
| | else { |
| | if (!winptyNative) { |
| | try { |
| | winptyNative = require('../build/Release/pty.node'); |
| | } |
| | catch (outerError) { |
| | try { |
| | winptyNative = require('../build/Debug/pty.node'); |
| | } |
| | catch (innerError) { |
| | console.error('innerError', innerError); |
| | |
| | throw outerError; |
| | } |
| | } |
| | } |
| | } |
| | this._ptyNative = this._useConpty ? conptyNative : winptyNative; |
| | |
| | cwd = path.resolve(cwd); |
| | |
| | var commandLine = argsToCommandLine(file, args); |
| | |
| | var term; |
| | if (this._useConpty) { |
| | term = this._ptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor); |
| | } |
| | else { |
| | term = this._ptyNative.startProcess(file, commandLine, env, cwd, cols, rows, debug); |
| | this._pid = term.pid; |
| | this._innerPid = term.innerPid; |
| | this._innerPidHandle = term.innerPidHandle; |
| | } |
| | |
| | this._fd = term.fd; |
| | |
| | |
| | this._pty = term.pty; |
| | |
| | this._outSocket = new net_1.Socket(); |
| | this._outSocket.setEncoding('utf8'); |
| | this._outSocket.connect(term.conout, function () { |
| | |
| | |
| | _this._outSocket.emit('ready_datapipe'); |
| | }); |
| | this._inSocket = new net_1.Socket(); |
| | this._inSocket.setEncoding('utf8'); |
| | this._inSocket.connect(term.conin); |
| | |
| | if (this._useConpty) { |
| | var connect = this._ptyNative.connect(this._pty, commandLine, cwd, env, function (c) { return _this._$onProcessExit(c); }); |
| | this._innerPid = connect.pid; |
| | } |
| | } |
| | Object.defineProperty(WindowsPtyAgent.prototype, "inSocket", { |
| | get: function () { return this._inSocket; }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | Object.defineProperty(WindowsPtyAgent.prototype, "outSocket", { |
| | get: function () { return this._outSocket; }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | Object.defineProperty(WindowsPtyAgent.prototype, "fd", { |
| | get: function () { return this._fd; }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | Object.defineProperty(WindowsPtyAgent.prototype, "innerPid", { |
| | get: function () { return this._innerPid; }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | Object.defineProperty(WindowsPtyAgent.prototype, "pty", { |
| | get: function () { return this._pty; }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | WindowsPtyAgent.prototype.resize = function (cols, rows) { |
| | if (this._useConpty) { |
| | if (this._exitCode !== undefined) { |
| | throw new Error('Cannot resize a pty that has already exited'); |
| | } |
| | this._ptyNative.resize(this._pty, cols, rows); |
| | return; |
| | } |
| | this._ptyNative.resize(this._pid, cols, rows); |
| | }; |
| | WindowsPtyAgent.prototype.kill = function () { |
| | var _this = this; |
| | this._inSocket.readable = false; |
| | this._inSocket.writable = false; |
| | this._outSocket.readable = false; |
| | this._outSocket.writable = false; |
| | |
| | if (this._useConpty) { |
| | this._getConsoleProcessList().then(function (consoleProcessList) { |
| | consoleProcessList.forEach(function (pid) { |
| | try { |
| | process.kill(pid); |
| | } |
| | catch (e) { |
| | |
| | } |
| | }); |
| | _this._ptyNative.kill(_this._pty); |
| | }); |
| | } |
| | else { |
| | this._ptyNative.kill(this._pid, this._innerPidHandle); |
| | |
| | |
| | |
| | |
| | |
| | |
| | var processList = this._ptyNative.getProcessList(this._pid); |
| | processList.forEach(function (pid) { |
| | try { |
| | process.kill(pid); |
| | } |
| | catch (e) { |
| | |
| | } |
| | }); |
| | } |
| | }; |
| | WindowsPtyAgent.prototype._getConsoleProcessList = function () { |
| | var _this = this; |
| | return new Promise(function (resolve) { |
| | var agent = child_process_1.fork(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]); |
| | agent.on('message', function (message) { |
| | clearTimeout(timeout); |
| | resolve(message.consoleProcessList); |
| | }); |
| | var timeout = setTimeout(function () { |
| | |
| | agent.kill(); |
| | resolve([_this._innerPid]); |
| | }, 5000); |
| | }); |
| | }; |
| | Object.defineProperty(WindowsPtyAgent.prototype, "exitCode", { |
| | get: function () { |
| | if (this._useConpty) { |
| | return this._exitCode; |
| | } |
| | return this._ptyNative.getExitCode(this._innerPidHandle); |
| | }, |
| | enumerable: true, |
| | configurable: true |
| | }); |
| | WindowsPtyAgent.prototype._getWindowsBuildNumber = function () { |
| | var osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release()); |
| | var buildNumber = 0; |
| | if (osVersion && osVersion.length === 4) { |
| | buildNumber = parseInt(osVersion[3]); |
| | } |
| | return buildNumber; |
| | }; |
| | WindowsPtyAgent.prototype._generatePipeName = function () { |
| | return "conpty-" + Math.random() * 10000000; |
| | }; |
| | |
| | |
| | |
| | WindowsPtyAgent.prototype._$onProcessExit = function (exitCode) { |
| | var _this = this; |
| | this._exitCode = exitCode; |
| | this._flushDataAndCleanUp(); |
| | this._outSocket.on('data', function () { return _this._flushDataAndCleanUp(); }); |
| | }; |
| | WindowsPtyAgent.prototype._flushDataAndCleanUp = function () { |
| | var _this = this; |
| | if (this._closeTimeout) { |
| | clearTimeout(this._closeTimeout); |
| | } |
| | this._closeTimeout = setTimeout(function () { return _this._cleanUpProcess(); }, FLUSH_DATA_INTERVAL); |
| | }; |
| | WindowsPtyAgent.prototype._cleanUpProcess = function () { |
| | this._inSocket.readable = false; |
| | this._inSocket.writable = false; |
| | this._outSocket.readable = false; |
| | this._outSocket.writable = false; |
| | this._outSocket.destroy(); |
| | }; |
| | return WindowsPtyAgent; |
| | }()); |
| | exports.WindowsPtyAgent = WindowsPtyAgent; |
| | |
| | |
| | |
| | function argsToCommandLine(file, args) { |
| | if (isCommandLine(args)) { |
| | if (args.length === 0) { |
| | return file; |
| | } |
| | return argsToCommandLine(file, []) + " " + args; |
| | } |
| | var argv = [file]; |
| | Array.prototype.push.apply(argv, args); |
| | var result = ''; |
| | for (var argIndex = 0; argIndex < argv.length; argIndex++) { |
| | if (argIndex > 0) { |
| | result += ' '; |
| | } |
| | var arg = argv[argIndex]; |
| | |
| | var hasLopsidedEnclosingQuote = xOr((arg[0] !== '"'), (arg[arg.length - 1] !== '"')); |
| | var hasNoEnclosingQuotes = ((arg[0] !== '"') && (arg[arg.length - 1] !== '"')); |
| | var quote = arg === '' || |
| | (arg.indexOf(' ') !== -1 || |
| | arg.indexOf('\t') !== -1) && |
| | ((arg.length > 1) && |
| | (hasLopsidedEnclosingQuote || hasNoEnclosingQuotes)); |
| | if (quote) { |
| | result += '\"'; |
| | } |
| | var bsCount = 0; |
| | for (var i = 0; i < arg.length; i++) { |
| | var p = arg[i]; |
| | if (p === '\\') { |
| | bsCount++; |
| | } |
| | else if (p === '"') { |
| | result += repeatText('\\', bsCount * 2 + 1); |
| | result += '"'; |
| | bsCount = 0; |
| | } |
| | else { |
| | result += repeatText('\\', bsCount); |
| | bsCount = 0; |
| | result += p; |
| | } |
| | } |
| | if (quote) { |
| | result += repeatText('\\', bsCount * 2); |
| | result += '\"'; |
| | } |
| | else { |
| | result += repeatText('\\', bsCount); |
| | } |
| | } |
| | return result; |
| | } |
| | exports.argsToCommandLine = argsToCommandLine; |
| | function isCommandLine(args) { |
| | return typeof args === 'string'; |
| | } |
| | function repeatText(text, count) { |
| | var result = ''; |
| | for (var i = 0; i < count; i++) { |
| | result += text; |
| | } |
| | return result; |
| | } |
| | function xOr(arg1, arg2) { |
| | return ((arg1 && !arg2) || (!arg1 && arg2)); |
| | } |
| | |