@shitiandmw/node-pty 1.1.0-agent.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/LICENSE +69 -0
  2. package/README.md +170 -0
  3. package/binding.gyp +111 -0
  4. package/deps/.editorconfig +2 -0
  5. package/deps/winpty/.drone.yml +17 -0
  6. package/deps/winpty/.gitattributes +19 -0
  7. package/deps/winpty/LICENSE +21 -0
  8. package/deps/winpty/Makefile +166 -0
  9. package/deps/winpty/README.md +151 -0
  10. package/deps/winpty/RELEASES.md +280 -0
  11. package/deps/winpty/VERSION.txt +1 -0
  12. package/deps/winpty/configure +167 -0
  13. package/deps/winpty/misc/BufferResizeTests.cc +90 -0
  14. package/deps/winpty/misc/ChangeScreenBuffer.cc +53 -0
  15. package/deps/winpty/misc/ClearConsole.cc +72 -0
  16. package/deps/winpty/misc/ConinMode.cc +117 -0
  17. package/deps/winpty/misc/ConinMode.ps1 +116 -0
  18. package/deps/winpty/misc/ConoutMode.cc +113 -0
  19. package/deps/winpty/misc/DebugClient.py +42 -0
  20. package/deps/winpty/misc/DebugServer.py +63 -0
  21. package/deps/winpty/misc/DumpLines.py +5 -0
  22. package/deps/winpty/misc/EnableExtendedFlags.txt +46 -0
  23. package/deps/winpty/misc/Font-Report-June2016/CP437-Consolas.txt +528 -0
  24. package/deps/winpty/misc/Font-Report-June2016/CP437-Lucida.txt +633 -0
  25. package/deps/winpty/misc/Font-Report-June2016/CP932.txt +630 -0
  26. package/deps/winpty/misc/Font-Report-June2016/CP936.txt +630 -0
  27. package/deps/winpty/misc/Font-Report-June2016/CP949.txt +630 -0
  28. package/deps/winpty/misc/Font-Report-June2016/CP950.txt +630 -0
  29. package/deps/winpty/misc/Font-Report-June2016/MinimumWindowWidths.txt +16 -0
  30. package/deps/winpty/misc/Font-Report-June2016/Results.txt +4 -0
  31. package/deps/winpty/misc/Font-Report-June2016/Windows10SetFontBugginess.txt +144 -0
  32. package/deps/winpty/misc/FontSurvey.cc +100 -0
  33. package/deps/winpty/misc/FormatChar.h +21 -0
  34. package/deps/winpty/misc/FreezePerfTest.cc +62 -0
  35. package/deps/winpty/misc/GetCh.cc +20 -0
  36. package/deps/winpty/misc/GetConsolePos.cc +41 -0
  37. package/deps/winpty/misc/GetFont.cc +261 -0
  38. package/deps/winpty/misc/IdentifyConsoleWindow.ps1 +51 -0
  39. package/deps/winpty/misc/IsNewConsole.cc +87 -0
  40. package/deps/winpty/misc/MouseInputNotes.txt +90 -0
  41. package/deps/winpty/misc/MoveConsoleWindow.cc +34 -0
  42. package/deps/winpty/misc/Notes.txt +219 -0
  43. package/deps/winpty/misc/OSVersion.cc +27 -0
  44. package/deps/winpty/misc/ScreenBufferFreezeInactive.cc +101 -0
  45. package/deps/winpty/misc/ScreenBufferTest.cc +671 -0
  46. package/deps/winpty/misc/ScreenBufferTest2.cc +151 -0
  47. package/deps/winpty/misc/SelectAllTest.cc +45 -0
  48. package/deps/winpty/misc/SetBufferSize.cc +32 -0
  49. package/deps/winpty/misc/SetCursorPos.cc +10 -0
  50. package/deps/winpty/misc/SetFont.cc +145 -0
  51. package/deps/winpty/misc/SetWindowRect.cc +36 -0
  52. package/deps/winpty/misc/ShowArgv.cc +12 -0
  53. package/deps/winpty/misc/ShowConsoleInput.cc +40 -0
  54. package/deps/winpty/misc/Spew.py +5 -0
  55. package/deps/winpty/misc/TestUtil.cc +172 -0
  56. package/deps/winpty/misc/UnicodeDoubleWidthTest.cc +102 -0
  57. package/deps/winpty/misc/UnicodeWideTest1.cc +246 -0
  58. package/deps/winpty/misc/UnicodeWideTest2.cc +130 -0
  59. package/deps/winpty/misc/UnixEcho.cc +89 -0
  60. package/deps/winpty/misc/Utf16Echo.cc +46 -0
  61. package/deps/winpty/misc/VeryLargeRead.cc +122 -0
  62. package/deps/winpty/misc/VkEscapeTest.cc +56 -0
  63. package/deps/winpty/misc/Win10ResizeWhileFrozen.cc +52 -0
  64. package/deps/winpty/misc/Win10WrapTest1.cc +57 -0
  65. package/deps/winpty/misc/Win10WrapTest2.cc +30 -0
  66. package/deps/winpty/misc/Win32Echo1.cc +26 -0
  67. package/deps/winpty/misc/Win32Echo2.cc +19 -0
  68. package/deps/winpty/misc/Win32Test1.cc +46 -0
  69. package/deps/winpty/misc/Win32Test2.cc +70 -0
  70. package/deps/winpty/misc/Win32Test3.cc +78 -0
  71. package/deps/winpty/misc/Win32Write1.cc +44 -0
  72. package/deps/winpty/misc/WindowsBugCrashReader.cc +27 -0
  73. package/deps/winpty/misc/WriteConsole.cc +106 -0
  74. package/deps/winpty/misc/build32.sh +9 -0
  75. package/deps/winpty/misc/build64.sh +9 -0
  76. package/deps/winpty/misc/color-test.sh +212 -0
  77. package/deps/winpty/misc/font-notes.txt +300 -0
  78. package/deps/winpty/misc/winbug-15048.cc +201 -0
  79. package/deps/winpty/ship/build-pty4j-libpty.bat +36 -0
  80. package/deps/winpty/ship/common_ship.py +53 -0
  81. package/deps/winpty/ship/make_msvc_package.py +165 -0
  82. package/deps/winpty/ship/ship.py +108 -0
  83. package/deps/winpty/src/agent/Agent.cc +613 -0
  84. package/deps/winpty/src/agent/Agent.h +103 -0
  85. package/deps/winpty/src/agent/AgentCreateDesktop.cc +84 -0
  86. package/deps/winpty/src/agent/AgentCreateDesktop.h +28 -0
  87. package/deps/winpty/src/agent/ConsoleFont.cc +632 -0
  88. package/deps/winpty/src/agent/ConsoleFont.h +28 -0
  89. package/deps/winpty/src/agent/ConsoleInput.cc +852 -0
  90. package/deps/winpty/src/agent/ConsoleInput.h +109 -0
  91. package/deps/winpty/src/agent/ConsoleInputReencoding.cc +121 -0
  92. package/deps/winpty/src/agent/ConsoleInputReencoding.h +36 -0
  93. package/deps/winpty/src/agent/ConsoleLine.cc +152 -0
  94. package/deps/winpty/src/agent/ConsoleLine.h +41 -0
  95. package/deps/winpty/src/agent/Coord.h +87 -0
  96. package/deps/winpty/src/agent/DebugShowInput.cc +239 -0
  97. package/deps/winpty/src/agent/DebugShowInput.h +32 -0
  98. package/deps/winpty/src/agent/DefaultInputMap.cc +422 -0
  99. package/deps/winpty/src/agent/DefaultInputMap.h +28 -0
  100. package/deps/winpty/src/agent/DsrSender.h +30 -0
  101. package/deps/winpty/src/agent/EventLoop.cc +99 -0
  102. package/deps/winpty/src/agent/EventLoop.h +47 -0
  103. package/deps/winpty/src/agent/InputMap.cc +246 -0
  104. package/deps/winpty/src/agent/InputMap.h +114 -0
  105. package/deps/winpty/src/agent/LargeConsoleRead.cc +71 -0
  106. package/deps/winpty/src/agent/LargeConsoleRead.h +68 -0
  107. package/deps/winpty/src/agent/NamedPipe.cc +378 -0
  108. package/deps/winpty/src/agent/NamedPipe.h +125 -0
  109. package/deps/winpty/src/agent/Scraper.cc +699 -0
  110. package/deps/winpty/src/agent/Scraper.h +103 -0
  111. package/deps/winpty/src/agent/SimplePool.h +75 -0
  112. package/deps/winpty/src/agent/SmallRect.h +143 -0
  113. package/deps/winpty/src/agent/Terminal.cc +535 -0
  114. package/deps/winpty/src/agent/Terminal.h +69 -0
  115. package/deps/winpty/src/agent/UnicodeEncoding.h +157 -0
  116. package/deps/winpty/src/agent/UnicodeEncodingTest.cc +189 -0
  117. package/deps/winpty/src/agent/Win32Console.cc +107 -0
  118. package/deps/winpty/src/agent/Win32Console.h +67 -0
  119. package/deps/winpty/src/agent/Win32ConsoleBuffer.cc +193 -0
  120. package/deps/winpty/src/agent/Win32ConsoleBuffer.h +99 -0
  121. package/deps/winpty/src/agent/main.cc +114 -0
  122. package/deps/winpty/src/agent/subdir.mk +61 -0
  123. package/deps/winpty/src/configurations.gypi +60 -0
  124. package/deps/winpty/src/debugserver/DebugServer.cc +117 -0
  125. package/deps/winpty/src/debugserver/subdir.mk +41 -0
  126. package/deps/winpty/src/include/winpty.h +242 -0
  127. package/deps/winpty/src/include/winpty_constants.h +131 -0
  128. package/deps/winpty/src/libwinpty/AgentLocation.cc +75 -0
  129. package/deps/winpty/src/libwinpty/AgentLocation.h +28 -0
  130. package/deps/winpty/src/libwinpty/LibWinptyException.h +54 -0
  131. package/deps/winpty/src/libwinpty/WinptyInternal.h +72 -0
  132. package/deps/winpty/src/libwinpty/subdir.mk +46 -0
  133. package/deps/winpty/src/libwinpty/winpty.cc +970 -0
  134. package/deps/winpty/src/shared/AgentMsg.h +38 -0
  135. package/deps/winpty/src/shared/BackgroundDesktop.cc +122 -0
  136. package/deps/winpty/src/shared/BackgroundDesktop.h +73 -0
  137. package/deps/winpty/src/shared/Buffer.cc +103 -0
  138. package/deps/winpty/src/shared/Buffer.h +102 -0
  139. package/deps/winpty/src/shared/DebugClient.cc +187 -0
  140. package/deps/winpty/src/shared/DebugClient.h +38 -0
  141. package/deps/winpty/src/shared/GenRandom.cc +138 -0
  142. package/deps/winpty/src/shared/GenRandom.h +55 -0
  143. package/deps/winpty/src/shared/GetCommitHash.bat +13 -0
  144. package/deps/winpty/src/shared/Mutex.h +54 -0
  145. package/deps/winpty/src/shared/OsModule.h +63 -0
  146. package/deps/winpty/src/shared/OwnedHandle.cc +36 -0
  147. package/deps/winpty/src/shared/OwnedHandle.h +45 -0
  148. package/deps/winpty/src/shared/PrecompiledHeader.h +43 -0
  149. package/deps/winpty/src/shared/StringBuilder.h +227 -0
  150. package/deps/winpty/src/shared/StringBuilderTest.cc +114 -0
  151. package/deps/winpty/src/shared/StringUtil.cc +55 -0
  152. package/deps/winpty/src/shared/StringUtil.h +80 -0
  153. package/deps/winpty/src/shared/TimeMeasurement.h +63 -0
  154. package/deps/winpty/src/shared/UnixCtrlChars.h +45 -0
  155. package/deps/winpty/src/shared/UpdateGenVersion.bat +20 -0
  156. package/deps/winpty/src/shared/WindowsSecurity.cc +460 -0
  157. package/deps/winpty/src/shared/WindowsSecurity.h +104 -0
  158. package/deps/winpty/src/shared/WindowsVersion.cc +252 -0
  159. package/deps/winpty/src/shared/WindowsVersion.h +29 -0
  160. package/deps/winpty/src/shared/WinptyAssert.cc +55 -0
  161. package/deps/winpty/src/shared/WinptyAssert.h +64 -0
  162. package/deps/winpty/src/shared/WinptyException.cc +57 -0
  163. package/deps/winpty/src/shared/WinptyException.h +43 -0
  164. package/deps/winpty/src/shared/WinptyVersion.cc +42 -0
  165. package/deps/winpty/src/shared/WinptyVersion.h +27 -0
  166. package/deps/winpty/src/shared/winpty_snprintf.h +99 -0
  167. package/deps/winpty/src/subdir.mk +5 -0
  168. package/deps/winpty/src/tests/subdir.mk +28 -0
  169. package/deps/winpty/src/tests/trivial_test.cc +158 -0
  170. package/deps/winpty/src/unix-adapter/InputHandler.cc +114 -0
  171. package/deps/winpty/src/unix-adapter/InputHandler.h +56 -0
  172. package/deps/winpty/src/unix-adapter/OutputHandler.cc +80 -0
  173. package/deps/winpty/src/unix-adapter/OutputHandler.h +53 -0
  174. package/deps/winpty/src/unix-adapter/Util.cc +86 -0
  175. package/deps/winpty/src/unix-adapter/Util.h +31 -0
  176. package/deps/winpty/src/unix-adapter/WakeupFd.cc +70 -0
  177. package/deps/winpty/src/unix-adapter/WakeupFd.h +42 -0
  178. package/deps/winpty/src/unix-adapter/main.cc +729 -0
  179. package/deps/winpty/src/unix-adapter/subdir.mk +41 -0
  180. package/deps/winpty/src/winpty.gyp +234 -0
  181. package/deps/winpty/vcbuild.bat +83 -0
  182. package/lib/conpty_console_list_agent.js +16 -0
  183. package/lib/conpty_console_list_agent.js.map +1 -0
  184. package/lib/eventEmitter2.js +47 -0
  185. package/lib/eventEmitter2.js.map +1 -0
  186. package/lib/eventEmitter2.test.js +30 -0
  187. package/lib/eventEmitter2.test.js.map +1 -0
  188. package/lib/index.js +52 -0
  189. package/lib/index.js.map +1 -0
  190. package/lib/interfaces.js +7 -0
  191. package/lib/interfaces.js.map +1 -0
  192. package/lib/shared/conout.js +11 -0
  193. package/lib/shared/conout.js.map +1 -0
  194. package/lib/terminal.js +190 -0
  195. package/lib/terminal.js.map +1 -0
  196. package/lib/terminal.test.js +139 -0
  197. package/lib/terminal.test.js.map +1 -0
  198. package/lib/testUtils.test.js +28 -0
  199. package/lib/testUtils.test.js.map +1 -0
  200. package/lib/types.js +7 -0
  201. package/lib/types.js.map +1 -0
  202. package/lib/unixTerminal.js +346 -0
  203. package/lib/unixTerminal.js.map +1 -0
  204. package/lib/unixTerminal.test.js +351 -0
  205. package/lib/unixTerminal.test.js.map +1 -0
  206. package/lib/utils.js +39 -0
  207. package/lib/utils.js.map +1 -0
  208. package/lib/windowsConoutConnection.js +125 -0
  209. package/lib/windowsConoutConnection.js.map +1 -0
  210. package/lib/windowsPtyAgent.js +320 -0
  211. package/lib/windowsPtyAgent.js.map +1 -0
  212. package/lib/windowsPtyAgent.test.js +90 -0
  213. package/lib/windowsPtyAgent.test.js.map +1 -0
  214. package/lib/windowsTerminal.js +199 -0
  215. package/lib/windowsTerminal.js.map +1 -0
  216. package/lib/windowsTerminal.test.js +219 -0
  217. package/lib/windowsTerminal.test.js.map +1 -0
  218. package/lib/worker/conoutSocketWorker.js +22 -0
  219. package/lib/worker/conoutSocketWorker.js.map +1 -0
  220. package/package.json +68 -0
  221. package/prebuilds/darwin-arm64/pty.node +0 -0
  222. package/prebuilds/darwin-arm64/spawn-helper +0 -0
  223. package/prebuilds/darwin-x64/pty.node +0 -0
  224. package/prebuilds/darwin-x64/spawn-helper +0 -0
  225. package/prebuilds/win32-arm64/conpty/OpenConsole.exe +0 -0
  226. package/prebuilds/win32-arm64/conpty/conpty.dll +0 -0
  227. package/prebuilds/win32-arm64/conpty.node +0 -0
  228. package/prebuilds/win32-arm64/conpty.pdb +0 -0
  229. package/prebuilds/win32-arm64/conpty_console_list.node +0 -0
  230. package/prebuilds/win32-arm64/conpty_console_list.pdb +0 -0
  231. package/prebuilds/win32-arm64/pty.node +0 -0
  232. package/prebuilds/win32-arm64/pty.pdb +0 -0
  233. package/prebuilds/win32-arm64/winpty-agent.exe +0 -0
  234. package/prebuilds/win32-arm64/winpty-agent.pdb +0 -0
  235. package/prebuilds/win32-arm64/winpty.dll +0 -0
  236. package/prebuilds/win32-arm64/winpty.pdb +0 -0
  237. package/prebuilds/win32-x64/conpty/OpenConsole.exe +0 -0
  238. package/prebuilds/win32-x64/conpty/conpty.dll +0 -0
  239. package/prebuilds/win32-x64/conpty.node +0 -0
  240. package/prebuilds/win32-x64/conpty.pdb +0 -0
  241. package/prebuilds/win32-x64/conpty_console_list.node +0 -0
  242. package/prebuilds/win32-x64/conpty_console_list.pdb +0 -0
  243. package/prebuilds/win32-x64/pty.node +0 -0
  244. package/prebuilds/win32-x64/pty.pdb +0 -0
  245. package/prebuilds/win32-x64/winpty-agent.exe +0 -0
  246. package/prebuilds/win32-x64/winpty-agent.pdb +0 -0
  247. package/prebuilds/win32-x64/winpty.dll +0 -0
  248. package/prebuilds/win32-x64/winpty.pdb +0 -0
  249. package/scripts/gen-compile-commands.js +8 -0
  250. package/scripts/increment-version.js +54 -0
  251. package/scripts/post-install.js +99 -0
  252. package/scripts/prebuild.js +39 -0
  253. package/scripts/sync-prebuild.js +31 -0
  254. package/scripts/verify-darwin-fd-leak.js +63 -0
  255. package/src/conpty_console_list_agent.ts +15 -0
  256. package/src/eventEmitter2.test.ts +30 -0
  257. package/src/eventEmitter2.ts +48 -0
  258. package/src/index.ts +52 -0
  259. package/src/interfaces.ts +130 -0
  260. package/src/native.d.ts +54 -0
  261. package/src/shared/conout.ts +15 -0
  262. package/src/terminal.test.ts +119 -0
  263. package/src/terminal.ts +211 -0
  264. package/src/testUtils.test.ts +23 -0
  265. package/src/tsconfig.json +22 -0
  266. package/src/types.ts +15 -0
  267. package/src/unix/pty.cc +808 -0
  268. package/src/unix/spawn-helper.cc +23 -0
  269. package/src/unixTerminal.test.ts +367 -0
  270. package/src/unixTerminal.ts +388 -0
  271. package/src/utils.ts +29 -0
  272. package/src/win/conpty.cc +583 -0
  273. package/src/win/conpty.h +41 -0
  274. package/src/win/conpty_console_list.cc +44 -0
  275. package/src/win/path_util.cc +95 -0
  276. package/src/win/path_util.h +26 -0
  277. package/src/win/winpty.cc +333 -0
  278. package/src/windowsConoutConnection.ts +82 -0
  279. package/src/windowsPtyAgent.test.ts +94 -0
  280. package/src/windowsPtyAgent.ts +321 -0
  281. package/src/windowsTerminal.test.ts +229 -0
  282. package/src/windowsTerminal.ts +203 -0
  283. package/src/worker/conoutSocketWorker.ts +22 -0
  284. package/third_party/conpty/1.23.251008001/win10-arm64/OpenConsole.exe +0 -0
  285. package/third_party/conpty/1.23.251008001/win10-arm64/conpty.dll +0 -0
  286. package/third_party/conpty/1.23.251008001/win10-x64/OpenConsole.exe +0 -0
  287. package/third_party/conpty/1.23.251008001/win10-x64/conpty.dll +0 -0
  288. package/typings/node-pty.d.ts +211 -0
@@ -0,0 +1,808 @@
1
+ /**
2
+ * Copyright (c) 2012-2015, Christopher Jeffrey (MIT License)
3
+ * Copyright (c) 2017, Daniel Imms (MIT License)
4
+ *
5
+ * pty.cc:
6
+ * This file is responsible for starting processes
7
+ * with pseudo-terminal file descriptors.
8
+ *
9
+ * See:
10
+ * man pty
11
+ * man tty_ioctl
12
+ * man termios
13
+ * man forkpty
14
+ */
15
+
16
+ /**
17
+ * Includes
18
+ */
19
+
20
+ #define NODE_ADDON_API_DISABLE_DEPRECATED
21
+ #include <napi.h>
22
+ #include <assert.h>
23
+ #include <errno.h>
24
+ #include <string.h>
25
+ #include <stdlib.h>
26
+ #include <unistd.h>
27
+ #include <thread>
28
+
29
+ #include <sys/types.h>
30
+ #include <sys/stat.h>
31
+ #include <sys/ioctl.h>
32
+ #include <sys/wait.h>
33
+ #include <fcntl.h>
34
+ #include <signal.h>
35
+
36
+ /* forkpty */
37
+ /* http://www.gnu.org/software/gnulib/manual/html_node/forkpty.html */
38
+ #if defined(__linux__)
39
+ #include <pty.h>
40
+ #elif defined(__APPLE__)
41
+ #include <util.h>
42
+ #elif defined(__FreeBSD__)
43
+ #include <libutil.h>
44
+ #include <termios.h>
45
+ #elif defined(__OpenBSD__)
46
+ #include <util.h>
47
+ #include <termios.h>
48
+ #endif
49
+
50
+ /* Some platforms name VWERASE and VDISCARD differently */
51
+ #if !defined(VWERASE) && defined(VWERSE)
52
+ #define VWERASE VWERSE
53
+ #endif
54
+ #if !defined(VDISCARD) && defined(VDISCRD)
55
+ #define VDISCARD VDISCRD
56
+ #endif
57
+
58
+ /* for pty_getproc */
59
+ #if defined(__linux__)
60
+ #include <stdio.h>
61
+ #include <stdint.h>
62
+ #elif defined(__APPLE__)
63
+ #include <libproc.h>
64
+ #include <os/availability.h>
65
+ #include <paths.h>
66
+ #include <spawn.h>
67
+ #include <sys/event.h>
68
+ #include <sys/sysctl.h>
69
+ #include <termios.h>
70
+ #endif
71
+
72
+ /* NSIG - macro for highest signal + 1, should be defined */
73
+ #ifndef NSIG
74
+ #define NSIG 32
75
+ #endif
76
+
77
+ /* macOS 10.14 back does not define this constant */
78
+ #ifndef POSIX_SPAWN_SETSID
79
+ #define POSIX_SPAWN_SETSID 1024
80
+ #endif
81
+
82
+ /* environ for execvpe */
83
+ /* node/src/node_child_process.cc */
84
+ #if !defined(__APPLE__)
85
+ extern char **environ;
86
+ #endif
87
+
88
+ #if defined(__APPLE__)
89
+ extern "C" {
90
+ // Changes the current thread's directory to a path or directory file
91
+ // descriptor. libpthread only exposes a syscall wrapper starting in
92
+ // macOS 10.12, but the system call dates back to macOS 10.5. On older OSes,
93
+ // the syscall is issued directly.
94
+ int pthread_chdir_np(const char* dir) API_AVAILABLE(macosx(10.12));
95
+ int pthread_fchdir_np(int fd) API_AVAILABLE(macosx(10.12));
96
+ }
97
+
98
+ #define HANDLE_EINTR(x) ({ \
99
+ int eintr_wrapper_counter = 0; \
100
+ decltype(x) eintr_wrapper_result; \
101
+ do { \
102
+ eintr_wrapper_result = (x); \
103
+ } while (eintr_wrapper_result == -1 && errno == EINTR && \
104
+ eintr_wrapper_counter++ < 100); \
105
+ eintr_wrapper_result; \
106
+ })
107
+ #endif
108
+
109
+ struct ExitEvent {
110
+ int exit_code = 0, signal_code = 0;
111
+ };
112
+
113
+ void SetupExitCallback(Napi::Env env, Napi::Function cb, pid_t pid) {
114
+ std::thread *th = new std::thread;
115
+ // Don't use Napi::AsyncWorker which is limited by UV_THREADPOOL_SIZE.
116
+ auto tsfn = Napi::ThreadSafeFunction::New(
117
+ env,
118
+ cb, // JavaScript function called asynchronously
119
+ "SetupExitCallback_resource", // Name
120
+ 0, // Unlimited queue
121
+ 1, // Only one thread will use this initially
122
+ [th](Napi::Env) { // Finalizer used to clean threads up
123
+ th->join();
124
+ delete th;
125
+ });
126
+ *th = std::thread([tsfn = std::move(tsfn), pid] {
127
+ auto callback = [](Napi::Env env, Napi::Function cb, ExitEvent *exit_event) {
128
+ cb.Call({Napi::Number::New(env, exit_event->exit_code),
129
+ Napi::Number::New(env, exit_event->signal_code)});
130
+ delete exit_event;
131
+ };
132
+
133
+ int ret;
134
+ int stat_loc;
135
+ #if defined(__APPLE__)
136
+ // Based on
137
+ // https://source.chromium.org/chromium/chromium/src/+/main:base/process/kill_mac.cc;l=35-69?
138
+ int kq = HANDLE_EINTR(kqueue());
139
+ struct kevent change = {0};
140
+ EV_SET(&change, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
141
+ ret = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
142
+ if (ret == -1) {
143
+ if (errno == ESRCH) {
144
+ // At this point, one of the following has occurred:
145
+ // 1. The process has died but has not yet been reaped.
146
+ // 2. The process has died and has already been reaped.
147
+ // 3. The process is in the process of dying. It's no longer
148
+ // kqueueable, but it may not be waitable yet either. Mark calls
149
+ // this case the "zombie death race".
150
+ ret = HANDLE_EINTR(waitpid(pid, &stat_loc, WNOHANG));
151
+ if (ret == 0) {
152
+ ret = kill(pid, SIGKILL);
153
+ if (ret != -1) {
154
+ HANDLE_EINTR(waitpid(pid, &stat_loc, 0));
155
+ }
156
+ }
157
+ }
158
+ } else {
159
+ struct kevent event = {0};
160
+ ret = HANDLE_EINTR(kevent(kq, NULL, 0, &event, 1, NULL));
161
+ if (ret == 1) {
162
+ if ((event.fflags & NOTE_EXIT) &&
163
+ (event.ident == static_cast<uintptr_t>(pid))) {
164
+ // The process is dead or dying. This won't block for long, if at
165
+ // all.
166
+ HANDLE_EINTR(waitpid(pid, &stat_loc, 0));
167
+ }
168
+ }
169
+ }
170
+ if (kq != -1) {
171
+ close(kq);
172
+ }
173
+ #else
174
+ while (true) {
175
+ errno = 0;
176
+ if ((ret = waitpid(pid, &stat_loc, 0)) != pid) {
177
+ if (ret == -1 && errno == EINTR) {
178
+ continue;
179
+ }
180
+ if (ret == -1 && errno == ECHILD) {
181
+ // XXX node v0.8.x seems to have this problem.
182
+ // waitpid is already handled elsewhere.
183
+ ;
184
+ } else {
185
+ assert(false);
186
+ }
187
+ }
188
+ break;
189
+ }
190
+ #endif
191
+ ExitEvent *exit_event = new ExitEvent;
192
+ if (WIFEXITED(stat_loc)) {
193
+ exit_event->exit_code = WEXITSTATUS(stat_loc); // errno?
194
+ }
195
+ if (WIFSIGNALED(stat_loc)) {
196
+ exit_event->signal_code = WTERMSIG(stat_loc);
197
+ }
198
+ auto status = tsfn.BlockingCall(exit_event, callback); // In main thread
199
+ switch (status) {
200
+ case napi_closing:
201
+ break;
202
+
203
+ case napi_queue_full:
204
+ Napi::Error::Fatal("SetupExitCallback", "Queue was full");
205
+
206
+ case napi_ok:
207
+ if (tsfn.Release() != napi_ok) {
208
+ Napi::Error::Fatal("SetupExitCallback", "ThreadSafeFunction.Release() failed");
209
+ }
210
+ break;
211
+
212
+ default:
213
+ Napi::Error::Fatal("SetupExitCallback", "ThreadSafeFunction.BlockingCall() failed");
214
+ }
215
+ });
216
+ }
217
+
218
+ /**
219
+ * Methods
220
+ */
221
+
222
+ Napi::Value PtyFork(const Napi::CallbackInfo& info);
223
+ Napi::Value PtyOpen(const Napi::CallbackInfo& info);
224
+ Napi::Value PtyResize(const Napi::CallbackInfo& info);
225
+ Napi::Value PtyGetProc(const Napi::CallbackInfo& info);
226
+
227
+ /**
228
+ * Functions
229
+ */
230
+
231
+ static int
232
+ pty_nonblock(int);
233
+
234
+ #if defined(__APPLE__)
235
+ static char *
236
+ pty_getproc(int);
237
+ #else
238
+ static char *
239
+ pty_getproc(int, char *);
240
+ #endif
241
+
242
+ #if defined(__APPLE__) || defined(__OpenBSD__)
243
+ static void
244
+ pty_posix_spawn(char** argv, char** env,
245
+ const struct termios *termp,
246
+ const struct winsize *winp,
247
+ int* master,
248
+ pid_t* pid,
249
+ int* err);
250
+ #endif
251
+
252
+ struct DelBuf {
253
+ int len;
254
+ DelBuf(int len) : len(len) {}
255
+ void operator()(char **p) {
256
+ if (p == nullptr)
257
+ return;
258
+ for (int i = 0; i < len; i++)
259
+ free(p[i]);
260
+ delete[] p;
261
+ }
262
+ };
263
+
264
+ Napi::Value PtyFork(const Napi::CallbackInfo& info) {
265
+ Napi::Env napiEnv(info.Env());
266
+ Napi::HandleScope scope(napiEnv);
267
+
268
+ if (info.Length() != 11 ||
269
+ !info[0].IsString() ||
270
+ !info[1].IsArray() ||
271
+ !info[2].IsArray() ||
272
+ !info[3].IsString() ||
273
+ !info[4].IsNumber() ||
274
+ !info[5].IsNumber() ||
275
+ !info[6].IsNumber() ||
276
+ !info[7].IsNumber() ||
277
+ !info[8].IsBoolean() ||
278
+ !info[9].IsString() ||
279
+ !info[10].IsFunction()) {
280
+ throw Napi::Error::New(napiEnv, "Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, helperPath, onexit)");
281
+ }
282
+
283
+ // file
284
+ std::string file = info[0].As<Napi::String>();
285
+
286
+ // args
287
+ Napi::Array argv_ = info[1].As<Napi::Array>();
288
+
289
+ // env
290
+ Napi::Array env_ = info[2].As<Napi::Array>();
291
+ int envc = env_.Length();
292
+ std::unique_ptr<char *, DelBuf> env_unique_ptr(new char *[envc + 1], DelBuf(envc + 1));
293
+ char **env = env_unique_ptr.get();
294
+ env[envc] = NULL;
295
+ for (int i = 0; i < envc; i++) {
296
+ std::string pair = env_.Get(i).As<Napi::String>();
297
+ env[i] = strdup(pair.c_str());
298
+ }
299
+
300
+ // cwd
301
+ std::string cwd_ = info[3].As<Napi::String>();
302
+
303
+ // size
304
+ struct winsize winp;
305
+ winp.ws_col = info[4].As<Napi::Number>().Int32Value();
306
+ winp.ws_row = info[5].As<Napi::Number>().Int32Value();
307
+ winp.ws_xpixel = 0;
308
+ winp.ws_ypixel = 0;
309
+
310
+ #if !defined(__APPLE__)
311
+ // uid / gid
312
+ int uid = info[6].As<Napi::Number>().Int32Value();
313
+ int gid = info[7].As<Napi::Number>().Int32Value();
314
+ #endif
315
+
316
+ // termios
317
+ struct termios t = termios();
318
+ struct termios *term = &t;
319
+ term->c_iflag = ICRNL | IXON | IXANY | IMAXBEL | BRKINT;
320
+ if (info[8].As<Napi::Boolean>().Value()) {
321
+ #if defined(IUTF8)
322
+ term->c_iflag |= IUTF8;
323
+ #endif
324
+ }
325
+ term->c_oflag = OPOST | ONLCR;
326
+ term->c_cflag = CREAD | CS8 | HUPCL;
327
+ term->c_lflag = ICANON | ISIG | IEXTEN | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL;
328
+
329
+ term->c_cc[VEOF] = 4;
330
+ term->c_cc[VEOL] = -1;
331
+ term->c_cc[VEOL2] = -1;
332
+ term->c_cc[VERASE] = 0x7f;
333
+ term->c_cc[VWERASE] = 23;
334
+ term->c_cc[VKILL] = 21;
335
+ term->c_cc[VREPRINT] = 18;
336
+ term->c_cc[VINTR] = 3;
337
+ term->c_cc[VQUIT] = 0x1c;
338
+ term->c_cc[VSUSP] = 26;
339
+ term->c_cc[VSTART] = 17;
340
+ term->c_cc[VSTOP] = 19;
341
+ term->c_cc[VLNEXT] = 22;
342
+ term->c_cc[VDISCARD] = 15;
343
+ term->c_cc[VMIN] = 1;
344
+ term->c_cc[VTIME] = 0;
345
+
346
+ #if (__APPLE__)
347
+ term->c_cc[VDSUSP] = 25;
348
+ term->c_cc[VSTATUS] = 20;
349
+ #endif
350
+
351
+ cfsetispeed(term, B38400);
352
+ cfsetospeed(term, B38400);
353
+
354
+ // helperPath
355
+ std::string helper_path = info[9].As<Napi::String>();
356
+
357
+ pid_t pid;
358
+ int master;
359
+ #if defined(__APPLE__)
360
+ int argc = argv_.Length();
361
+ int argl = argc + 4;
362
+ std::unique_ptr<char *, DelBuf> argv_unique_ptr(new char *[argl], DelBuf(argl));
363
+ char **argv = argv_unique_ptr.get();
364
+ argv[0] = strdup(helper_path.c_str());
365
+ argv[1] = strdup(cwd_.c_str());
366
+ argv[2] = strdup(file.c_str());
367
+ argv[argl - 1] = NULL;
368
+ for (int i = 0; i < argc; i++) {
369
+ std::string arg = argv_.Get(i).As<Napi::String>();
370
+ argv[i + 3] = strdup(arg.c_str());
371
+ }
372
+
373
+ int err = -1;
374
+ pty_posix_spawn(argv, env, term, &winp, &master, &pid, &err);
375
+ if (err != 0) {
376
+ throw Napi::Error::New(napiEnv, "posix_spawnp failed.");
377
+ }
378
+ if (pty_nonblock(master) == -1) {
379
+ throw Napi::Error::New(napiEnv, "Could not set master fd to nonblocking.");
380
+ }
381
+ #else
382
+ int argc = argv_.Length();
383
+ int argl = argc + 2;
384
+ std::unique_ptr<char *, DelBuf> argv_unique_ptr(new char *[argl], DelBuf(argl));
385
+ char** argv = argv_unique_ptr.get();
386
+ argv[0] = strdup(file.c_str());
387
+ argv[argl - 1] = NULL;
388
+ for (int i = 0; i < argc; i++) {
389
+ std::string arg = argv_.Get(i).As<Napi::String>();
390
+ argv[i + 1] = strdup(arg.c_str());
391
+ }
392
+
393
+ sigset_t newmask, oldmask;
394
+ struct sigaction sig_action;
395
+ // temporarily block all signals
396
+ // this is needed due to a race condition in openpty
397
+ // and to avoid running signal handlers in the child
398
+ // before exec* happened
399
+ sigfillset(&newmask);
400
+ pthread_sigmask(SIG_SETMASK, &newmask, &oldmask);
401
+
402
+ pid = forkpty(&master, nullptr, static_cast<termios*>(term), static_cast<winsize*>(&winp));
403
+
404
+ if (!pid) {
405
+ // remove all signal handler from child
406
+ sig_action.sa_handler = SIG_DFL;
407
+ sig_action.sa_flags = 0;
408
+ sigemptyset(&sig_action.sa_mask);
409
+ for (int i = 0 ; i < NSIG ; i++) { // NSIG is a macro for all signals + 1
410
+ sigaction(i, &sig_action, NULL);
411
+ }
412
+ }
413
+
414
+ // reenable signals
415
+ pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
416
+
417
+ switch (pid) {
418
+ case -1:
419
+ throw Napi::Error::New(napiEnv, "forkpty(3) failed.");
420
+ case 0:
421
+ if (strlen(cwd_.c_str())) {
422
+ if (chdir(cwd_.c_str()) == -1) {
423
+ perror("chdir(2) failed.");
424
+ _exit(1);
425
+ }
426
+ }
427
+
428
+ if (uid != -1 && gid != -1) {
429
+ if (setgid(gid) == -1) {
430
+ perror("setgid(2) failed.");
431
+ _exit(1);
432
+ }
433
+ if (setuid(uid) == -1) {
434
+ perror("setuid(2) failed.");
435
+ _exit(1);
436
+ }
437
+ }
438
+
439
+ {
440
+ char **old = environ;
441
+ environ = env;
442
+ execvp(argv[0], argv);
443
+ environ = old;
444
+ perror("execvp(3) failed.");
445
+ _exit(1);
446
+ }
447
+ default:
448
+ if (pty_nonblock(master) == -1) {
449
+ throw Napi::Error::New(napiEnv, "Could not set master fd to nonblocking.");
450
+ }
451
+ }
452
+ #endif
453
+
454
+ Napi::Object obj = Napi::Object::New(napiEnv);
455
+ obj.Set("fd", Napi::Number::New(napiEnv, master));
456
+ obj.Set("pid", Napi::Number::New(napiEnv, pid));
457
+ obj.Set("pty", Napi::String::New(napiEnv, ptsname(master)));
458
+
459
+ // Set up process exit callback.
460
+ Napi::Function cb = info[10].As<Napi::Function>();
461
+ SetupExitCallback(napiEnv, cb, pid);
462
+ return obj;
463
+ }
464
+
465
+ Napi::Value PtyOpen(const Napi::CallbackInfo& info) {
466
+ Napi::Env env(info.Env());
467
+ Napi::HandleScope scope(env);
468
+
469
+ if (info.Length() != 2 ||
470
+ !info[0].IsNumber() ||
471
+ !info[1].IsNumber()) {
472
+ throw Napi::Error::New(env, "Usage: pty.open(cols, rows)");
473
+ }
474
+
475
+ // size
476
+ struct winsize winp;
477
+ winp.ws_col = info[0].As<Napi::Number>().Int32Value();
478
+ winp.ws_row = info[1].As<Napi::Number>().Int32Value();
479
+ winp.ws_xpixel = 0;
480
+ winp.ws_ypixel = 0;
481
+
482
+ // pty
483
+ int master, slave;
484
+ int ret = openpty(&master, &slave, nullptr, NULL, static_cast<winsize*>(&winp));
485
+
486
+ if (ret == -1) {
487
+ throw Napi::Error::New(env, "openpty(3) failed.");
488
+ }
489
+
490
+ if (pty_nonblock(master) == -1) {
491
+ throw Napi::Error::New(env, "Could not set master fd to nonblocking.");
492
+ }
493
+
494
+ if (pty_nonblock(slave) == -1) {
495
+ throw Napi::Error::New(env, "Could not set slave fd to nonblocking.");
496
+ }
497
+
498
+ Napi::Object obj = Napi::Object::New(env);
499
+ obj.Set("master", Napi::Number::New(env, master));
500
+ obj.Set("slave", Napi::Number::New(env, slave));
501
+ obj.Set("pty", Napi::String::New(env, ptsname(master)));
502
+
503
+ return obj;
504
+ }
505
+
506
+ Napi::Value PtyResize(const Napi::CallbackInfo& info) {
507
+ Napi::Env env(info.Env());
508
+ Napi::HandleScope scope(env);
509
+
510
+ if (info.Length() != 3 ||
511
+ !info[0].IsNumber() ||
512
+ !info[1].IsNumber() ||
513
+ !info[2].IsNumber()) {
514
+ throw Napi::Error::New(env, "Usage: pty.resize(fd, cols, rows)");
515
+ }
516
+
517
+ int fd = info[0].As<Napi::Number>().Int32Value();
518
+
519
+ struct winsize winp;
520
+ winp.ws_col = info[1].As<Napi::Number>().Int32Value();
521
+ winp.ws_row = info[2].As<Napi::Number>().Int32Value();
522
+ winp.ws_xpixel = 0;
523
+ winp.ws_ypixel = 0;
524
+
525
+ if (ioctl(fd, TIOCSWINSZ, &winp) == -1) {
526
+ switch (errno) {
527
+ case EBADF:
528
+ throw Napi::Error::New(env, "ioctl(2) failed, EBADF");
529
+ case EFAULT:
530
+ throw Napi::Error::New(env, "ioctl(2) failed, EFAULT");
531
+ case EINVAL:
532
+ throw Napi::Error::New(env, "ioctl(2) failed, EINVAL");
533
+ case ENOTTY:
534
+ throw Napi::Error::New(env, "ioctl(2) failed, ENOTTY");
535
+ }
536
+ throw Napi::Error::New(env, "ioctl(2) failed");
537
+ }
538
+
539
+ return env.Undefined();
540
+ }
541
+
542
+ /**
543
+ * Foreground Process Name
544
+ */
545
+ Napi::Value PtyGetProc(const Napi::CallbackInfo& info) {
546
+ Napi::Env env(info.Env());
547
+ Napi::HandleScope scope(env);
548
+
549
+ #if defined(__APPLE__)
550
+ if (info.Length() != 1 ||
551
+ !info[0].IsNumber()) {
552
+ throw Napi::Error::New(env, "Usage: pty.process(pid)");
553
+ }
554
+
555
+ int fd = info[0].As<Napi::Number>().Int32Value();
556
+ char *name = pty_getproc(fd);
557
+ #else
558
+ if (info.Length() != 2 ||
559
+ !info[0].IsNumber() ||
560
+ !info[1].IsString()) {
561
+ throw Napi::Error::New(env, "Usage: pty.process(fd, tty)");
562
+ }
563
+
564
+ int fd = info[0].As<Napi::Number>().Int32Value();
565
+
566
+ std::string tty_ = info[1].As<Napi::String>();
567
+ char *tty = strdup(tty_.c_str());
568
+ char *name = pty_getproc(fd, tty);
569
+ free(tty);
570
+ #endif
571
+
572
+ if (name == NULL) {
573
+ return env.Undefined();
574
+ }
575
+
576
+ Napi::String name_ = Napi::String::New(env, name);
577
+ free(name);
578
+ return name_;
579
+ }
580
+
581
+ /**
582
+ * Nonblocking FD
583
+ */
584
+
585
+ static int
586
+ pty_nonblock(int fd) {
587
+ int flags = fcntl(fd, F_GETFL, 0);
588
+ if (flags == -1) return -1;
589
+ return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
590
+ }
591
+
592
+ /**
593
+ * pty_getproc
594
+ * Taken from tmux.
595
+ */
596
+
597
+ // Taken from: tmux (http://tmux.sourceforge.net/)
598
+ // Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net>
599
+ // Copyright (c) 2009 Joshua Elsasser <josh@elsasser.org>
600
+ // Copyright (c) 2009 Todd Carson <toc@daybefore.net>
601
+ //
602
+ // Permission to use, copy, modify, and distribute this software for any
603
+ // purpose with or without fee is hereby granted, provided that the above
604
+ // copyright notice and this permission notice appear in all copies.
605
+ //
606
+ // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
607
+ // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
608
+ // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
609
+ // ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
610
+ // WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
611
+ // IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
612
+ // OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
613
+
614
+ #if defined(__linux__)
615
+
616
+ static char *
617
+ pty_getproc(int fd, char *tty) {
618
+ FILE *f;
619
+ char *path, *buf;
620
+ size_t len;
621
+ int ch;
622
+ pid_t pgrp;
623
+ int r;
624
+
625
+ if ((pgrp = tcgetpgrp(fd)) == -1) {
626
+ return NULL;
627
+ }
628
+
629
+ r = asprintf(&path, "/proc/%lld/cmdline", (long long)pgrp);
630
+ if (r == -1 || path == NULL) return NULL;
631
+
632
+ if ((f = fopen(path, "r")) == NULL) {
633
+ free(path);
634
+ return NULL;
635
+ }
636
+
637
+ free(path);
638
+
639
+ len = 0;
640
+ buf = NULL;
641
+ while ((ch = fgetc(f)) != EOF) {
642
+ if (ch == '\0') break;
643
+ buf = (char *)realloc(buf, len + 2);
644
+ if (buf == NULL) return NULL;
645
+ buf[len++] = ch;
646
+ }
647
+
648
+ if (buf != NULL) {
649
+ buf[len] = '\0';
650
+ }
651
+
652
+ fclose(f);
653
+ return buf;
654
+ }
655
+
656
+ #elif defined(__APPLE__)
657
+
658
+ static char *
659
+ pty_getproc(int fd) {
660
+ int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, 0 };
661
+ size_t size;
662
+ struct kinfo_proc kp;
663
+
664
+ if ((mib[3] = tcgetpgrp(fd)) == -1) {
665
+ return NULL;
666
+ }
667
+
668
+ size = sizeof kp;
669
+ if (sysctl(mib, 4, &kp, &size, NULL, 0) == -1) {
670
+ return NULL;
671
+ }
672
+
673
+ if (size != (sizeof kp) || *kp.kp_proc.p_comm == '\0') {
674
+ return NULL;
675
+ }
676
+
677
+ return strdup(kp.kp_proc.p_comm);
678
+ }
679
+
680
+ #else
681
+
682
+ static char *
683
+ pty_getproc(int fd, char *tty) {
684
+ return NULL;
685
+ }
686
+
687
+ #endif
688
+
689
+ #if defined(__APPLE__)
690
+ static void
691
+ pty_posix_spawn(char** argv, char** env,
692
+ const struct termios *termp,
693
+ const struct winsize *winp,
694
+ int* master,
695
+ pid_t* pid,
696
+ int* err) {
697
+ int low_fds[3];
698
+ size_t low_fd_count = 0;
699
+
700
+ for (; low_fd_count < 3; low_fd_count++) {
701
+ low_fds[low_fd_count] = posix_openpt(O_RDWR);
702
+ if (low_fds[low_fd_count] >= STDERR_FILENO) {
703
+ low_fd_count++;
704
+ break;
705
+ }
706
+ }
707
+
708
+ int flags = POSIX_SPAWN_CLOEXEC_DEFAULT |
709
+ POSIX_SPAWN_SETSIGDEF |
710
+ POSIX_SPAWN_SETSIGMASK |
711
+ POSIX_SPAWN_SETSID;
712
+ *master = posix_openpt(O_RDWR);
713
+ if (*master == -1) {
714
+ return;
715
+ }
716
+
717
+ int res = grantpt(*master) || unlockpt(*master);
718
+ if (res == -1) {
719
+ return;
720
+ }
721
+
722
+ // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
723
+ int slave = -1;
724
+ char slave_pty_name[128];
725
+ res = ioctl(*master, TIOCPTYGNAME, slave_pty_name);
726
+ if (res == -1) {
727
+ return;
728
+ }
729
+
730
+ slave = open(slave_pty_name, O_RDWR | O_NOCTTY);
731
+ if (slave == -1) {
732
+ return;
733
+ }
734
+
735
+ if (termp) {
736
+ res = tcsetattr(slave, TCSANOW, termp);
737
+ if (res == -1) {
738
+ return;
739
+ };
740
+ }
741
+
742
+ if (winp) {
743
+ res = ioctl(slave, TIOCSWINSZ, winp);
744
+ if (res == -1) {
745
+ return;
746
+ }
747
+ }
748
+
749
+ posix_spawn_file_actions_t acts;
750
+ posix_spawn_file_actions_init(&acts);
751
+ posix_spawn_file_actions_adddup2(&acts, slave, STDIN_FILENO);
752
+ posix_spawn_file_actions_adddup2(&acts, slave, STDOUT_FILENO);
753
+ posix_spawn_file_actions_adddup2(&acts, slave, STDERR_FILENO);
754
+ posix_spawn_file_actions_addclose(&acts, slave);
755
+ posix_spawn_file_actions_addclose(&acts, *master);
756
+
757
+ posix_spawnattr_t attrs;
758
+ posix_spawnattr_init(&attrs);
759
+ *err = posix_spawnattr_setflags(&attrs, flags);
760
+ if (*err != 0) {
761
+ goto done;
762
+ }
763
+
764
+ sigset_t signal_set;
765
+ /* Reset all signal the child to their default behavior */
766
+ sigfillset(&signal_set);
767
+ *err = posix_spawnattr_setsigdefault(&attrs, &signal_set);
768
+ if (*err != 0) {
769
+ goto done;
770
+ }
771
+
772
+ /* Reset the signal mask for all signals */
773
+ sigemptyset(&signal_set);
774
+ *err = posix_spawnattr_setsigmask(&attrs, &signal_set);
775
+ if (*err != 0) {
776
+ goto done;
777
+ }
778
+
779
+ do
780
+ *err = posix_spawn(pid, argv[0], &acts, &attrs, argv, env);
781
+ while (*err == EINTR);
782
+ done:
783
+ posix_spawn_file_actions_destroy(&acts);
784
+ posix_spawnattr_destroy(&attrs);
785
+ if (slave != -1) {
786
+ close(slave);
787
+ }
788
+
789
+ while (low_fd_count > 0) {
790
+ low_fd_count--;
791
+ close(low_fds[low_fd_count]);
792
+ }
793
+ }
794
+ #endif
795
+
796
+ /**
797
+ * Init
798
+ */
799
+
800
+ Napi::Object init(Napi::Env env, Napi::Object exports) {
801
+ exports.Set("fork", Napi::Function::New(env, PtyFork));
802
+ exports.Set("open", Napi::Function::New(env, PtyOpen));
803
+ exports.Set("resize", Napi::Function::New(env, PtyResize));
804
+ exports.Set("process", Napi::Function::New(env, PtyGetProc));
805
+ return exports;
806
+ }
807
+
808
+ NODE_API_MODULE(NODE_GYP_MODULE_NAME, init)