My dotfiles
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

162 lines
6.3 KiB

  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. let net = require('net');
  6. let fs = require('fs');
  7. let ENABLE_LOGGING = false;
  8. let log = (function () {
  9. if (!ENABLE_LOGGING) {
  10. return function () { }; // tslint:disable-line
  11. }
  12. let isFirst = true;
  13. let LOG_LOCATION = 'C:\\stdFork.log';
  14. return function log(str) {
  15. if (isFirst) {
  16. isFirst = false;
  17. fs.writeFileSync(LOG_LOCATION, str + '\n');
  18. return;
  19. }
  20. fs.appendFileSync(LOG_LOCATION, str + '\n');
  21. };
  22. })();
  23. let stdInPipeName = process.env['STDIN_PIPE_NAME']; // tslint:disable-line
  24. let stdOutPipeName = process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
  25. let stdErrPipeName = process.env['STDERR_PIPE_NAME']; // tslint:disable-line
  26. log('STDIN_PIPE_NAME: ' + stdInPipeName);
  27. log('STDOUT_PIPE_NAME: ' + stdOutPipeName);
  28. log('STDERR_PIPE_NAME: ' + stdErrPipeName);
  29. (function () {
  30. log('Beginning stdout redirection...');
  31. // Create a writing stream to the stdout pipe
  32. let stdOutStream = net.connect(stdOutPipeName);
  33. // unref stdOutStream to behave like a normal standard out
  34. stdOutStream.unref();
  35. process.__defineGetter__('stdout', function () {
  36. return stdOutStream;
  37. });
  38. // Create a writing stream to the stderr pipe
  39. let stdErrStream = net.connect(stdErrPipeName);
  40. // unref stdErrStream to behave like a normal standard out
  41. stdErrStream.unref();
  42. process.__defineGetter__('stderr', function () {
  43. return stdErrStream;
  44. });
  45. let fsWriteSyncString = function (// tslint:disable-line
  46. fd, str, _position, encoding) {
  47. // fs.writeSync(fd, string[, position[, encoding]])
  48. let buf = Buffer.from(str, encoding || 'utf8');
  49. return fsWriteSyncBuffer(fd, buf, 0, buf.length); // tslint:disable-line
  50. };
  51. let fsWriteSyncBuffer = function (// tslint:disable-line
  52. fd, buffer, off, len) {
  53. off = Math.abs(off | 0);
  54. len = Math.abs(len | 0);
  55. // fs.writeSync(fd, buffer, offset, length[, position])
  56. let buffer_length = buffer.length;
  57. if (off > buffer_length) {
  58. throw new Error('offset out of bounds');
  59. }
  60. if (len > buffer_length) {
  61. throw new Error('length out of bounds');
  62. }
  63. if (((off + len) | 0) < off) {
  64. throw new Error('off + len overflow');
  65. }
  66. if (buffer_length - off < len) {
  67. // Asking for more than is left over in the buffer
  68. throw new Error('off + len > buffer.length');
  69. }
  70. let slicedBuffer = buffer;
  71. if (off !== 0 || len !== buffer_length) {
  72. slicedBuffer = buffer.slice(off, off + len);
  73. }
  74. if (fd === 1) {
  75. stdOutStream.write(slicedBuffer);
  76. }
  77. else {
  78. stdErrStream.write(slicedBuffer);
  79. }
  80. return slicedBuffer.length;
  81. };
  82. // handle fs.writeSync(1, ...)
  83. let originalWriteSync = fs.writeSync;
  84. fs.writeSync = function (// tslint:disable-line
  85. fd, data, _position, _encoding) {
  86. if (fd !== 1 && fd !== 2) {
  87. return originalWriteSync.apply(fs, arguments);
  88. }
  89. // usage:
  90. // fs.writeSync(fd, buffer, offset, length[, position])
  91. // OR
  92. // fs.writeSync(fd, string[, position[, encoding]])
  93. if (data instanceof Buffer) {
  94. return fsWriteSyncBuffer.apply(null, arguments);
  95. }
  96. // For compatibility reasons with fs.writeSync, writing null will write "null", etc
  97. if (typeof data !== 'string') {
  98. data += '';
  99. }
  100. return fsWriteSyncString.apply(null, arguments);
  101. };
  102. log('Finished defining process.stdout, process.stderr and fs.writeSync');
  103. })();
  104. (function () {
  105. // Begin listening to stdin pipe
  106. let server = net.createServer(function (stream) {
  107. // Stop accepting new connections, keep the existing one alive
  108. server.close();
  109. log('Parent process has connected to my stdin. All should be good now.');
  110. process.__defineGetter__('stdin', function () {
  111. return stream;
  112. });
  113. // Remove myself from process.argv
  114. process.argv.splice(1, 1);
  115. // Load the actual program
  116. let program = process.argv[1];
  117. log('Loading program: ' + program);
  118. // Unset the custom environmental variables that should not get inherited
  119. delete process.env['STDIN_PIPE_NAME']; // tslint:disable-line
  120. delete process.env['STDOUT_PIPE_NAME']; // tslint:disable-line
  121. delete process.env['STDERR_PIPE_NAME']; // tslint:disable-line
  122. require(program);
  123. log('Finished loading program.');
  124. let stdinIsReferenced = true;
  125. let timer = setInterval(function () {
  126. let listenerCount = stream.listeners('data').length +
  127. stream.listeners('end').length +
  128. stream.listeners('close').length +
  129. stream.listeners('error').length;
  130. // log('listenerCount: ' + listenerCount)
  131. if (listenerCount <= 1) {
  132. // No more "actual" listeners, only internal node
  133. if (stdinIsReferenced) {
  134. stdinIsReferenced = false;
  135. // log('unreferencing stream!!!')
  136. stream.unref();
  137. }
  138. }
  139. else {
  140. // There are "actual" listeners
  141. if (!stdinIsReferenced) {
  142. stdinIsReferenced = true;
  143. stream.ref();
  144. }
  145. }
  146. // log(
  147. // '' + stream.listeners('data').length +
  148. // ' ' + stream.listeners('end').length +
  149. // ' ' + stream.listeners('close').length +
  150. // ' ' + stream.listeners('error').length
  151. // )
  152. }, 1000);
  153. if (timer.unref) { // tslint:disable-line
  154. timer.unref(); // tslint:disable-line
  155. }
  156. });
  157. server.listen(stdInPipeName, function () {
  158. // signal via stdout that the parent process can now begin writing to stdin pipe
  159. process.stdout.write('ready');
  160. });
  161. })();