|
"use strict"; |
|
var __extends = (this && this.__extends) || (function () { |
|
var extendStatics = function (d, b) { |
|
extendStatics = Object.setPrototypeOf || |
|
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || |
|
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; |
|
return extendStatics(d, b); |
|
}; |
|
return function (d, b) { |
|
extendStatics(d, b); |
|
function __() { this.constructor = d; } |
|
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); |
|
}; |
|
})(); |
|
Object.defineProperty(exports, "__esModule", { value: true }); |
|
|
|
|
|
|
|
|
|
|
|
var net = require("net"); |
|
var terminal_1 = require("./terminal"); |
|
var utils_1 = require("./utils"); |
|
var pty; |
|
try { |
|
pty = require('../build/Release/pty.node'); |
|
} |
|
catch (outerError) { |
|
try { |
|
pty = require('../build/Debug/pty.node'); |
|
} |
|
catch (innerError) { |
|
console.error('innerError', innerError); |
|
|
|
throw outerError; |
|
} |
|
} |
|
var DEFAULT_FILE = 'sh'; |
|
var DEFAULT_NAME = 'xterm'; |
|
var DESTROY_SOCKET_TIMEOUT_MS = 200; |
|
var UnixTerminal = (function (_super) { |
|
__extends(UnixTerminal, _super); |
|
function UnixTerminal(file, args, opt) { |
|
var _this = _super.call(this, opt) || this; |
|
if (typeof args === 'string') { |
|
throw new Error('args as a string is not supported on unix.'); |
|
} |
|
|
|
args = args || []; |
|
file = file || DEFAULT_FILE; |
|
opt = opt || {}; |
|
opt.env = opt.env || process.env; |
|
_this._cols = opt.cols || terminal_1.DEFAULT_COLS; |
|
_this._rows = opt.rows || terminal_1.DEFAULT_ROWS; |
|
var uid = opt.uid || -1; |
|
var gid = opt.gid || -1; |
|
var env = utils_1.assign({}, opt.env); |
|
if (opt.env === process.env) { |
|
_this._sanitizeEnv(env); |
|
} |
|
var cwd = opt.cwd || process.cwd(); |
|
var name = opt.name || env.TERM || DEFAULT_NAME; |
|
env.TERM = name; |
|
var parsedEnv = _this._parseEnv(env); |
|
var encoding = (opt.encoding === undefined ? 'utf8' : opt.encoding); |
|
var onexit = function (code, signal) { |
|
|
|
|
|
if (!_this._emittedClose) { |
|
if (_this._boundClose) { |
|
return; |
|
} |
|
_this._boundClose = true; |
|
|
|
|
|
|
|
var timeout_1 = setTimeout(function () { |
|
timeout_1 = null; |
|
|
|
_this._socket.destroy(); |
|
}, DESTROY_SOCKET_TIMEOUT_MS); |
|
_this.once('close', function () { |
|
if (timeout_1 !== null) { |
|
clearTimeout(timeout_1); |
|
} |
|
_this.emit('exit', code, signal); |
|
}); |
|
return; |
|
} |
|
_this.emit('exit', code, signal); |
|
}; |
|
|
|
var term = pty.fork(file, args, parsedEnv, cwd, _this._cols, _this._rows, uid, gid, (encoding === 'utf8'), onexit); |
|
_this._socket = new PipeSocket(term.fd); |
|
if (encoding !== null) { |
|
_this._socket.setEncoding(encoding); |
|
} |
|
|
|
_this._socket.on('error', function (err) { |
|
|
|
if (err.code) { |
|
if (~err.code.indexOf('EAGAIN')) { |
|
return; |
|
} |
|
} |
|
|
|
_this._close(); |
|
|
|
if (!_this._emittedClose) { |
|
_this._emittedClose = true; |
|
_this.emit('close'); |
|
} |
|
|
|
|
|
|
|
|
|
if (err.code) { |
|
if (~err.code.indexOf('errno 5') || ~err.code.indexOf('EIO')) { |
|
return; |
|
} |
|
} |
|
|
|
if (_this.listeners('error').length < 2) { |
|
throw err; |
|
} |
|
}); |
|
_this._pid = term.pid; |
|
_this._fd = term.fd; |
|
_this._pty = term.pty; |
|
_this._file = file; |
|
_this._name = name; |
|
_this._readable = true; |
|
_this._writable = true; |
|
_this._socket.on('close', function () { |
|
if (_this._emittedClose) { |
|
return; |
|
} |
|
_this._emittedClose = true; |
|
_this._close(); |
|
_this.emit('close'); |
|
}); |
|
_this._forwardEvents(); |
|
return _this; |
|
} |
|
Object.defineProperty(UnixTerminal.prototype, "master", { |
|
get: function () { return this._master; }, |
|
enumerable: true, |
|
configurable: true |
|
}); |
|
Object.defineProperty(UnixTerminal.prototype, "slave", { |
|
get: function () { return this._slave; }, |
|
enumerable: true, |
|
configurable: true |
|
}); |
|
UnixTerminal.prototype._write = function (data) { |
|
this._socket.write(data); |
|
}; |
|
|
|
|
|
|
|
UnixTerminal.open = function (opt) { |
|
var self = Object.create(UnixTerminal.prototype); |
|
opt = opt || {}; |
|
if (arguments.length > 1) { |
|
opt = { |
|
cols: arguments[1], |
|
rows: arguments[2] |
|
}; |
|
} |
|
var cols = opt.cols || terminal_1.DEFAULT_COLS; |
|
var rows = opt.rows || terminal_1.DEFAULT_ROWS; |
|
var encoding = (opt.encoding === undefined ? 'utf8' : opt.encoding); |
|
|
|
var term = pty.open(cols, rows); |
|
self._master = new PipeSocket(term.master); |
|
if (encoding !== null) { |
|
self._master.setEncoding(encoding); |
|
} |
|
self._master.resume(); |
|
self._slave = new PipeSocket(term.slave); |
|
if (encoding !== null) { |
|
self._slave.setEncoding(encoding); |
|
} |
|
self._slave.resume(); |
|
self._socket = self._master; |
|
self._pid = null; |
|
self._fd = term.master; |
|
self._pty = term.pty; |
|
self._file = process.argv[0] || 'node'; |
|
self._name = process.env.TERM || ''; |
|
self._readable = true; |
|
self._writable = true; |
|
self._socket.on('error', function (err) { |
|
self._close(); |
|
if (self.listeners('error').length < 2) { |
|
throw err; |
|
} |
|
}); |
|
self._socket.on('close', function () { |
|
self._close(); |
|
}); |
|
return self; |
|
}; |
|
UnixTerminal.prototype.destroy = function () { |
|
var _this = this; |
|
this._close(); |
|
|
|
|
|
this._socket.once('close', function () { |
|
_this.kill('SIGHUP'); |
|
}); |
|
this._socket.destroy(); |
|
}; |
|
UnixTerminal.prototype.kill = function (signal) { |
|
try { |
|
process.kill(this.pid, signal || 'SIGHUP'); |
|
} |
|
catch (e) { } |
|
}; |
|
Object.defineProperty(UnixTerminal.prototype, "process", { |
|
|
|
|
|
|
|
get: function () { |
|
return pty.process(this._fd, this._pty) || this._file; |
|
}, |
|
enumerable: true, |
|
configurable: true |
|
}); |
|
|
|
|
|
|
|
UnixTerminal.prototype.resize = function (cols, rows) { |
|
if (cols <= 0 || rows <= 0 || isNaN(cols) || isNaN(rows) || cols === Infinity || rows === Infinity) { |
|
throw new Error('resizing must be done using positive cols and rows'); |
|
} |
|
pty.resize(this._fd, cols, rows); |
|
this._cols = cols; |
|
this._rows = rows; |
|
}; |
|
UnixTerminal.prototype._sanitizeEnv = function (env) { |
|
|
|
delete env['TMUX']; |
|
delete env['TMUX_PANE']; |
|
|
|
|
|
delete env['STY']; |
|
delete env['WINDOW']; |
|
|
|
delete env['WINDOWID']; |
|
delete env['TERMCAP']; |
|
delete env['COLUMNS']; |
|
delete env['LINES']; |
|
}; |
|
return UnixTerminal; |
|
}(terminal_1.Terminal)); |
|
exports.UnixTerminal = UnixTerminal; |
|
|
|
|
|
|
|
|
|
|
|
var PipeSocket = (function (_super) { |
|
__extends(PipeSocket, _super); |
|
function PipeSocket(fd) { |
|
var _this = this; |
|
var _a = process.binding('pipe_wrap'), Pipe = _a.Pipe, constants = _a.constants; |
|
|
|
var handle = new Pipe(constants.SOCKET); |
|
handle.open(fd); |
|
_this = _super.call(this, { handle: handle }) || this; |
|
return _this; |
|
} |
|
return PipeSocket; |
|
}(net.Socket)); |
|
|