1 | "use strict";
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 | Object.defineProperty(exports, "__esModule", { value: true });
|
8 | var fs = require("fs");
|
9 | var os = require("os");
|
10 | var path = require("path");
|
11 | var net_1 = require("net");
|
12 | var child_process_1 = require("child_process");
|
13 | var conptyNative;
|
14 | var winptyNative;
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 | var FLUSH_DATA_INTERVAL = 20;
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | var WindowsPtyAgent = (function () {
|
26 | function WindowsPtyAgent(file, args, env, cwd, cols, rows, debug, _useConpty, conptyInheritCursor) {
|
27 | var _this = this;
|
28 | if (conptyInheritCursor === void 0) { conptyInheritCursor = false; }
|
29 | this._useConpty = _useConpty;
|
30 | if (this._useConpty === undefined || this._useConpty === true) {
|
31 | this._useConpty = this._getWindowsBuildNumber() >= 18309;
|
32 | }
|
33 | if (this._useConpty) {
|
34 | if (!conptyNative) {
|
35 | try {
|
36 | conptyNative = require('../build/Release/conpty.node');
|
37 | }
|
38 | catch (outerError) {
|
39 | try {
|
40 | conptyNative = require('../build/Debug/conpty.node');
|
41 | }
|
42 | catch (innerError) {
|
43 | console.error('innerError', innerError);
|
44 |
|
45 | throw outerError;
|
46 | }
|
47 | }
|
48 | }
|
49 | }
|
50 | else {
|
51 | if (!winptyNative) {
|
52 | try {
|
53 | winptyNative = require('../build/Release/pty.node');
|
54 | }
|
55 | catch (outerError) {
|
56 | try {
|
57 | winptyNative = require('../build/Debug/pty.node');
|
58 | }
|
59 | catch (innerError) {
|
60 | console.error('innerError', innerError);
|
61 |
|
62 | throw outerError;
|
63 | }
|
64 | }
|
65 | }
|
66 | }
|
67 | this._ptyNative = this._useConpty ? conptyNative : winptyNative;
|
68 |
|
69 | cwd = path.resolve(cwd);
|
70 |
|
71 | var commandLine = argsToCommandLine(file, args);
|
72 |
|
73 | var term;
|
74 | if (this._useConpty) {
|
75 | term = this._ptyNative.startProcess(file, cols, rows, debug, this._generatePipeName(), conptyInheritCursor);
|
76 | }
|
77 | else {
|
78 | term = this._ptyNative.startProcess(file, commandLine, env, cwd, cols, rows, debug);
|
79 | this._pid = term.pid;
|
80 | this._innerPid = term.innerPid;
|
81 | this._innerPidHandle = term.innerPidHandle;
|
82 | }
|
83 |
|
84 | this._fd = term.fd;
|
85 |
|
86 |
|
87 | this._pty = term.pty;
|
88 |
|
89 | this._outSocket = new net_1.Socket();
|
90 | this._outSocket.setEncoding('utf8');
|
91 | this._outSocket.connect(term.conout, function () {
|
92 |
|
93 |
|
94 | _this._outSocket.emit('ready_datapipe');
|
95 | });
|
96 | var inSocketFD = fs.openSync(term.conin, 'w');
|
97 | this._inSocket = new net_1.Socket({
|
98 | fd: inSocketFD,
|
99 | readable: false,
|
100 | writable: true
|
101 | });
|
102 | this._inSocket.setEncoding('utf8');
|
103 |
|
104 | if (this._useConpty) {
|
105 | var connect = this._ptyNative.connect(this._pty, commandLine, cwd, env, function (c) { return _this._$onProcessExit(c); });
|
106 | this._innerPid = connect.pid;
|
107 | }
|
108 | }
|
109 | Object.defineProperty(WindowsPtyAgent.prototype, "inSocket", {
|
110 | get: function () { return this._inSocket; },
|
111 | enumerable: true,
|
112 | configurable: true
|
113 | });
|
114 | Object.defineProperty(WindowsPtyAgent.prototype, "outSocket", {
|
115 | get: function () { return this._outSocket; },
|
116 | enumerable: true,
|
117 | configurable: true
|
118 | });
|
119 | Object.defineProperty(WindowsPtyAgent.prototype, "fd", {
|
120 | get: function () { return this._fd; },
|
121 | enumerable: true,
|
122 | configurable: true
|
123 | });
|
124 | Object.defineProperty(WindowsPtyAgent.prototype, "innerPid", {
|
125 | get: function () { return this._innerPid; },
|
126 | enumerable: true,
|
127 | configurable: true
|
128 | });
|
129 | Object.defineProperty(WindowsPtyAgent.prototype, "pty", {
|
130 | get: function () { return this._pty; },
|
131 | enumerable: true,
|
132 | configurable: true
|
133 | });
|
134 | WindowsPtyAgent.prototype.resize = function (cols, rows) {
|
135 | if (this._useConpty) {
|
136 | if (this._exitCode !== undefined) {
|
137 | throw new Error('Cannot resize a pty that has already exited');
|
138 | }
|
139 | this._ptyNative.resize(this._pty, cols, rows);
|
140 | return;
|
141 | }
|
142 | this._ptyNative.resize(this._pid, cols, rows);
|
143 | };
|
144 | WindowsPtyAgent.prototype.kill = function () {
|
145 | var _this = this;
|
146 | this._inSocket.readable = false;
|
147 | this._inSocket.writable = false;
|
148 | this._outSocket.readable = false;
|
149 | this._outSocket.writable = false;
|
150 |
|
151 | if (this._useConpty) {
|
152 | this._getConsoleProcessList().then(function (consoleProcessList) {
|
153 | consoleProcessList.forEach(function (pid) {
|
154 | try {
|
155 | process.kill(pid);
|
156 | }
|
157 | catch (e) {
|
158 |
|
159 | }
|
160 | });
|
161 | _this._ptyNative.kill(_this._pty);
|
162 | });
|
163 | }
|
164 | else {
|
165 | this._ptyNative.kill(this._pid, this._innerPidHandle);
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 | var processList = this._ptyNative.getProcessList(this._pid);
|
173 | processList.forEach(function (pid) {
|
174 | try {
|
175 | process.kill(pid);
|
176 | }
|
177 | catch (e) {
|
178 |
|
179 | }
|
180 | });
|
181 | }
|
182 | };
|
183 | WindowsPtyAgent.prototype._getConsoleProcessList = function () {
|
184 | var _this = this;
|
185 | return new Promise(function (resolve) {
|
186 | var agent = child_process_1.fork(path.join(__dirname, 'conpty_console_list_agent'), [_this._innerPid.toString()]);
|
187 | agent.on('message', function (message) {
|
188 | clearTimeout(timeout);
|
189 | resolve(message.consoleProcessList);
|
190 | });
|
191 | var timeout = setTimeout(function () {
|
192 |
|
193 | agent.kill();
|
194 | resolve([_this._innerPid]);
|
195 | }, 5000);
|
196 | });
|
197 | };
|
198 | Object.defineProperty(WindowsPtyAgent.prototype, "exitCode", {
|
199 | get: function () {
|
200 | if (this._useConpty) {
|
201 | return this._exitCode;
|
202 | }
|
203 | return this._ptyNative.getExitCode(this._innerPidHandle);
|
204 | },
|
205 | enumerable: true,
|
206 | configurable: true
|
207 | });
|
208 | WindowsPtyAgent.prototype._getWindowsBuildNumber = function () {
|
209 | var osVersion = (/(\d+)\.(\d+)\.(\d+)/g).exec(os.release());
|
210 | var buildNumber = 0;
|
211 | if (osVersion && osVersion.length === 4) {
|
212 | buildNumber = parseInt(osVersion[3]);
|
213 | }
|
214 | return buildNumber;
|
215 | };
|
216 | WindowsPtyAgent.prototype._generatePipeName = function () {
|
217 | return "conpty-" + Math.random() * 10000000;
|
218 | };
|
219 | |
220 |
|
221 |
|
222 | WindowsPtyAgent.prototype._$onProcessExit = function (exitCode) {
|
223 | var _this = this;
|
224 | this._exitCode = exitCode;
|
225 | this._flushDataAndCleanUp();
|
226 | this._outSocket.on('data', function () { return _this._flushDataAndCleanUp(); });
|
227 | };
|
228 | WindowsPtyAgent.prototype._flushDataAndCleanUp = function () {
|
229 | var _this = this;
|
230 | if (this._closeTimeout) {
|
231 | clearTimeout(this._closeTimeout);
|
232 | }
|
233 | this._closeTimeout = setTimeout(function () { return _this._cleanUpProcess(); }, FLUSH_DATA_INTERVAL);
|
234 | };
|
235 | WindowsPtyAgent.prototype._cleanUpProcess = function () {
|
236 | this._inSocket.readable = false;
|
237 | this._inSocket.writable = false;
|
238 | this._outSocket.readable = false;
|
239 | this._outSocket.writable = false;
|
240 | this._outSocket.destroy();
|
241 | };
|
242 | return WindowsPtyAgent;
|
243 | }());
|
244 | exports.WindowsPtyAgent = WindowsPtyAgent;
|
245 |
|
246 |
|
247 |
|
248 | function argsToCommandLine(file, args) {
|
249 | if (isCommandLine(args)) {
|
250 | if (args.length === 0) {
|
251 | return file;
|
252 | }
|
253 | return argsToCommandLine(file, []) + " " + args;
|
254 | }
|
255 | var argv = [file];
|
256 | Array.prototype.push.apply(argv, args);
|
257 | var result = '';
|
258 | for (var argIndex = 0; argIndex < argv.length; argIndex++) {
|
259 | if (argIndex > 0) {
|
260 | result += ' ';
|
261 | }
|
262 | var arg = argv[argIndex];
|
263 |
|
264 | var hasLopsidedEnclosingQuote = xOr((arg[0] !== '"'), (arg[arg.length - 1] !== '"'));
|
265 | var hasNoEnclosingQuotes = ((arg[0] !== '"') && (arg[arg.length - 1] !== '"'));
|
266 | var quote = arg === '' ||
|
267 | (arg.indexOf(' ') !== -1 ||
|
268 | arg.indexOf('\t') !== -1) &&
|
269 | ((arg.length > 1) &&
|
270 | (hasLopsidedEnclosingQuote || hasNoEnclosingQuotes));
|
271 | if (quote) {
|
272 | result += '\"';
|
273 | }
|
274 | var bsCount = 0;
|
275 | for (var i = 0; i < arg.length; i++) {
|
276 | var p = arg[i];
|
277 | if (p === '\\') {
|
278 | bsCount++;
|
279 | }
|
280 | else if (p === '"') {
|
281 | result += repeatText('\\', bsCount * 2 + 1);
|
282 | result += '"';
|
283 | bsCount = 0;
|
284 | }
|
285 | else {
|
286 | result += repeatText('\\', bsCount);
|
287 | bsCount = 0;
|
288 | result += p;
|
289 | }
|
290 | }
|
291 | if (quote) {
|
292 | result += repeatText('\\', bsCount * 2);
|
293 | result += '\"';
|
294 | }
|
295 | else {
|
296 | result += repeatText('\\', bsCount);
|
297 | }
|
298 | }
|
299 | return result;
|
300 | }
|
301 | exports.argsToCommandLine = argsToCommandLine;
|
302 | function isCommandLine(args) {
|
303 | return typeof args === 'string';
|
304 | }
|
305 | function repeatText(text, count) {
|
306 | var result = '';
|
307 | for (var i = 0; i < count; i++) {
|
308 | result += text;
|
309 | }
|
310 | return result;
|
311 | }
|
312 | function xOr(arg1, arg2) {
|
313 | return ((arg1 && !arg2) || (!arg1 && arg2));
|
314 | }
|
315 |
|
\ | No newline at end of file |