node-pty 0.11.0-beta9 → 1.1.0-beta1
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.
- package/README.md +5 -4
- package/binding.gyp +70 -29
- package/lib/conpty_console_list_agent.js.map +1 -1
- package/lib/terminal.js +10 -4
- package/lib/terminal.js.map +1 -1
- package/lib/terminal.test.js +3 -0
- package/lib/terminal.test.js.map +1 -1
- package/lib/unixTerminal.js +30 -4
- package/lib/unixTerminal.js.map +1 -1
- package/lib/unixTerminal.test.js +147 -18
- package/lib/unixTerminal.test.js.map +1 -1
- package/lib/windowsPtyAgent.js +13 -6
- package/lib/windowsPtyAgent.js.map +1 -1
- package/lib/windowsTerminal.js +21 -3
- package/lib/windowsTerminal.js.map +1 -1
- package/lib/windowsTerminal.test.js +98 -97
- package/lib/windowsTerminal.test.js.map +1 -1
- package/lib/worker/conoutSocketWorker.js +3 -0
- package/lib/worker/conoutSocketWorker.js.map +1 -1
- package/package.json +3 -4
- package/scripts/post-install.js +1 -0
- package/src/conpty_console_list_agent.ts +1 -1
- package/src/interfaces.ts +8 -2
- package/src/native.d.ts +6 -5
- package/src/terminal.test.ts +3 -0
- package/src/terminal.ts +21 -20
- package/src/tsconfig.json +1 -3
- package/src/unix/pty.cc +297 -205
- package/src/unix/spawn-helper.cc +23 -0
- package/src/unixTerminal.test.ts +117 -25
- package/src/unixTerminal.ts +31 -11
- package/src/win/conpty.cc +85 -38
- package/src/win/conpty_console_list.cc +3 -3
- package/src/win/path_util.cc +22 -3
- package/src/win/path_util.h +1 -0
- package/src/win/winpty.cc +118 -54
- package/src/windowsConoutConnection.ts +1 -1
- package/src/windowsPtyAgent.ts +16 -11
- package/src/windowsTerminal.test.ts +100 -99
- package/src/windowsTerminal.ts +23 -4
- package/src/worker/conoutSocketWorker.ts +4 -0
- package/typings/node-pty.d.ts +11 -20
- package/deps/winpty/.gitignore +0 -15
- package/deps/winpty/misc/.gitignore +0 -2
- package/scripts/install.js +0 -18
package/src/unix/pty.cc
CHANGED
|
@@ -32,20 +32,14 @@
|
|
|
32
32
|
|
|
33
33
|
/* forkpty */
|
|
34
34
|
/* http://www.gnu.org/software/gnulib/manual/html_node/forkpty.html */
|
|
35
|
-
#if defined(
|
|
35
|
+
#if defined(__linux__)
|
|
36
36
|
#include <pty.h>
|
|
37
|
-
#elif defined(__APPLE__)
|
|
37
|
+
#elif defined(__APPLE__)
|
|
38
38
|
#include <util.h>
|
|
39
39
|
#elif defined(__FreeBSD__)
|
|
40
40
|
#include <libutil.h>
|
|
41
|
-
#elif defined(__sun)
|
|
42
|
-
#include <stropts.h> /* for I_PUSH */
|
|
43
|
-
#else
|
|
44
|
-
#include <pty.h>
|
|
45
41
|
#endif
|
|
46
42
|
|
|
47
|
-
#include <termios.h> /* tcgetattr, tty_ioctl */
|
|
48
|
-
|
|
49
43
|
/* Some platforms name VWERASE and VDISCARD differently */
|
|
50
44
|
#if !defined(VWERASE) && defined(VWERSE)
|
|
51
45
|
#define VWERASE VWERSE
|
|
@@ -54,22 +48,17 @@
|
|
|
54
48
|
#define VDISCARD VDISCRD
|
|
55
49
|
#endif
|
|
56
50
|
|
|
57
|
-
/* environ for execvpe */
|
|
58
|
-
/* node/src/node_child_process.cc */
|
|
59
|
-
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
|
60
|
-
#include <crt_externs.h>
|
|
61
|
-
#define environ (*_NSGetEnviron())
|
|
62
|
-
#else
|
|
63
|
-
extern char **environ;
|
|
64
|
-
#endif
|
|
65
|
-
|
|
66
51
|
/* for pty_getproc */
|
|
67
52
|
#if defined(__linux__)
|
|
68
53
|
#include <stdio.h>
|
|
69
54
|
#include <stdint.h>
|
|
70
55
|
#elif defined(__APPLE__)
|
|
71
|
-
#include <sys/sysctl.h>
|
|
72
56
|
#include <libproc.h>
|
|
57
|
+
#include <os/availability.h>
|
|
58
|
+
#include <paths.h>
|
|
59
|
+
#include <spawn.h>
|
|
60
|
+
#include <sys/event.h>
|
|
61
|
+
#include <termios.h>
|
|
73
62
|
#endif
|
|
74
63
|
|
|
75
64
|
/* NSIG - macro for highest signal + 1, should be defined */
|
|
@@ -77,6 +66,38 @@ extern char **environ;
|
|
|
77
66
|
#define NSIG 32
|
|
78
67
|
#endif
|
|
79
68
|
|
|
69
|
+
/* macOS 10.14 back does not define this constant */
|
|
70
|
+
#ifndef POSIX_SPAWN_SETSID
|
|
71
|
+
#define POSIX_SPAWN_SETSID 1024
|
|
72
|
+
#endif
|
|
73
|
+
|
|
74
|
+
/* environ for execvpe */
|
|
75
|
+
/* node/src/node_child_process.cc */
|
|
76
|
+
#if !defined(__APPLE__)
|
|
77
|
+
extern char **environ;
|
|
78
|
+
#endif
|
|
79
|
+
|
|
80
|
+
#if defined(__APPLE__)
|
|
81
|
+
extern "C" {
|
|
82
|
+
// Changes the current thread's directory to a path or directory file
|
|
83
|
+
// descriptor. libpthread only exposes a syscall wrapper starting in
|
|
84
|
+
// macOS 10.12, but the system call dates back to macOS 10.5. On older OSes,
|
|
85
|
+
// the syscall is issued directly.
|
|
86
|
+
int pthread_chdir_np(const char* dir) API_AVAILABLE(macosx(10.12));
|
|
87
|
+
int pthread_fchdir_np(int fd) API_AVAILABLE(macosx(10.12));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
#define HANDLE_EINTR(x) ({ \
|
|
91
|
+
int eintr_wrapper_counter = 0; \
|
|
92
|
+
decltype(x) eintr_wrapper_result; \
|
|
93
|
+
do { \
|
|
94
|
+
eintr_wrapper_result = (x); \
|
|
95
|
+
} while (eintr_wrapper_result == -1 && errno == EINTR && \
|
|
96
|
+
eintr_wrapper_counter++ < 100); \
|
|
97
|
+
eintr_wrapper_result; \
|
|
98
|
+
})
|
|
99
|
+
#endif
|
|
100
|
+
|
|
80
101
|
/**
|
|
81
102
|
* Structs
|
|
82
103
|
*/
|
|
@@ -103,24 +124,16 @@ NAN_METHOD(PtyGetProc);
|
|
|
103
124
|
* Functions
|
|
104
125
|
*/
|
|
105
126
|
|
|
106
|
-
static int
|
|
107
|
-
pty_execvpe(const char *, char **, char **);
|
|
108
|
-
|
|
109
127
|
static int
|
|
110
128
|
pty_nonblock(int);
|
|
111
129
|
|
|
130
|
+
#if defined(__APPLE__)
|
|
131
|
+
static char *
|
|
132
|
+
pty_getproc(int);
|
|
133
|
+
#else
|
|
112
134
|
static char *
|
|
113
135
|
pty_getproc(int, char *);
|
|
114
|
-
|
|
115
|
-
static int
|
|
116
|
-
pty_openpty(int *, int *, char *,
|
|
117
|
-
const struct termios *,
|
|
118
|
-
const struct winsize *);
|
|
119
|
-
|
|
120
|
-
static pid_t
|
|
121
|
-
pty_forkpty(int *, char *,
|
|
122
|
-
const struct termios *,
|
|
123
|
-
const struct winsize *);
|
|
136
|
+
#endif
|
|
124
137
|
|
|
125
138
|
static void
|
|
126
139
|
pty_waitpid(void *);
|
|
@@ -131,10 +144,20 @@ pty_after_waitpid(uv_async_t *);
|
|
|
131
144
|
static void
|
|
132
145
|
pty_after_close(uv_handle_t *);
|
|
133
146
|
|
|
147
|
+
#if defined(__APPLE__) || defined(__OpenBSD__)
|
|
148
|
+
static void
|
|
149
|
+
pty_posix_spawn(char** argv, char** env,
|
|
150
|
+
const struct termios *termp,
|
|
151
|
+
const struct winsize *winp,
|
|
152
|
+
int* master,
|
|
153
|
+
pid_t* pid,
|
|
154
|
+
int* err);
|
|
155
|
+
#endif
|
|
156
|
+
|
|
134
157
|
NAN_METHOD(PtyFork) {
|
|
135
158
|
Nan::HandleScope scope;
|
|
136
159
|
|
|
137
|
-
if (info.Length() !=
|
|
160
|
+
if (info.Length() != 11 ||
|
|
138
161
|
!info[0]->IsString() ||
|
|
139
162
|
!info[1]->IsArray() ||
|
|
140
163
|
!info[2]->IsArray() ||
|
|
@@ -144,41 +167,30 @@ NAN_METHOD(PtyFork) {
|
|
|
144
167
|
!info[6]->IsNumber() ||
|
|
145
168
|
!info[7]->IsNumber() ||
|
|
146
169
|
!info[8]->IsBoolean() ||
|
|
147
|
-
!info[9]->
|
|
170
|
+
!info[9]->IsString() ||
|
|
171
|
+
!info[10]->IsFunction()) {
|
|
148
172
|
return Nan::ThrowError(
|
|
149
|
-
"Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, onexit)");
|
|
173
|
+
"Usage: pty.fork(file, args, env, cwd, cols, rows, uid, gid, utf8, helperPath, onexit)");
|
|
150
174
|
}
|
|
151
175
|
|
|
152
176
|
// file
|
|
153
177
|
Nan::Utf8String file(info[0]);
|
|
154
178
|
|
|
155
179
|
// args
|
|
156
|
-
int i = 0;
|
|
157
180
|
v8::Local<v8::Array> argv_ = v8::Local<v8::Array>::Cast(info[1]);
|
|
158
|
-
int argc = argv_->Length();
|
|
159
|
-
int argl = argc + 1 + 1;
|
|
160
|
-
char **argv = new char*[argl];
|
|
161
|
-
argv[0] = strdup(*file);
|
|
162
|
-
argv[argl-1] = NULL;
|
|
163
|
-
for (; i < argc; i++) {
|
|
164
|
-
Nan::Utf8String arg(Nan::Get(argv_, i).ToLocalChecked());
|
|
165
|
-
argv[i+1] = strdup(*arg);
|
|
166
|
-
}
|
|
167
181
|
|
|
168
182
|
// env
|
|
169
|
-
i = 0;
|
|
170
183
|
v8::Local<v8::Array> env_ = v8::Local<v8::Array>::Cast(info[2]);
|
|
171
184
|
int envc = env_->Length();
|
|
172
185
|
char **env = new char*[envc+1];
|
|
173
186
|
env[envc] = NULL;
|
|
174
|
-
for (; i < envc; i++) {
|
|
187
|
+
for (int i = 0; i < envc; i++) {
|
|
175
188
|
Nan::Utf8String pair(Nan::Get(env_, i).ToLocalChecked());
|
|
176
189
|
env[i] = strdup(*pair);
|
|
177
190
|
}
|
|
178
191
|
|
|
179
192
|
// cwd
|
|
180
193
|
Nan::Utf8String cwd_(info[3]);
|
|
181
|
-
char *cwd = strdup(*cwd_);
|
|
182
194
|
|
|
183
195
|
// size
|
|
184
196
|
struct winsize winp;
|
|
@@ -187,6 +199,12 @@ NAN_METHOD(PtyFork) {
|
|
|
187
199
|
winp.ws_xpixel = 0;
|
|
188
200
|
winp.ws_ypixel = 0;
|
|
189
201
|
|
|
202
|
+
#if !defined(__APPLE__)
|
|
203
|
+
// uid / gid
|
|
204
|
+
int uid = info[6]->IntegerValue(Nan::GetCurrentContext()).FromJust();
|
|
205
|
+
int gid = info[7]->IntegerValue(Nan::GetCurrentContext()).FromJust();
|
|
206
|
+
#endif
|
|
207
|
+
|
|
190
208
|
// termios
|
|
191
209
|
struct termios t = termios();
|
|
192
210
|
struct termios *term = &t;
|
|
@@ -225,16 +243,48 @@ NAN_METHOD(PtyFork) {
|
|
|
225
243
|
cfsetispeed(term, B38400);
|
|
226
244
|
cfsetospeed(term, B38400);
|
|
227
245
|
|
|
228
|
-
//
|
|
229
|
-
|
|
230
|
-
int gid = info[7]->IntegerValue(Nan::GetCurrentContext()).FromJust();
|
|
246
|
+
// helperPath
|
|
247
|
+
Nan::Utf8String helper_path(info[9]);
|
|
231
248
|
|
|
232
|
-
|
|
233
|
-
int master
|
|
249
|
+
pid_t pid;
|
|
250
|
+
int master;
|
|
251
|
+
#if defined(__APPLE__)
|
|
252
|
+
int argc = argv_->Length();
|
|
253
|
+
int argl = argc + 4;
|
|
254
|
+
char **argv = new char*[argl];
|
|
255
|
+
argv[0] = strdup(*helper_path);
|
|
256
|
+
argv[1] = strdup(*cwd_);
|
|
257
|
+
argv[2] = strdup(*file);
|
|
258
|
+
argv[argl - 1] = NULL;
|
|
259
|
+
for (int i = 0; i < argc; i++) {
|
|
260
|
+
Nan::Utf8String arg(Nan::Get(argv_, i).ToLocalChecked());
|
|
261
|
+
argv[i + 3] = strdup(*arg);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
int err = -1;
|
|
265
|
+
pty_posix_spawn(argv, env, term, &winp, &master, &pid, &err);
|
|
266
|
+
if (err != 0) {
|
|
267
|
+
Nan::ThrowError("posix_spawnp failed.");
|
|
268
|
+
goto done;
|
|
269
|
+
}
|
|
270
|
+
if (pty_nonblock(master) == -1) {
|
|
271
|
+
Nan::ThrowError("Could not set master fd to nonblocking.");
|
|
272
|
+
goto done;
|
|
273
|
+
}
|
|
274
|
+
#else
|
|
275
|
+
int argc = argv_->Length();
|
|
276
|
+
int argl = argc + 2;
|
|
277
|
+
char **argv = new char*[argl];
|
|
278
|
+
argv[0] = strdup(*file);
|
|
279
|
+
argv[argl - 1] = NULL;
|
|
280
|
+
for (int i = 0; i < argc; i++) {
|
|
281
|
+
Nan::Utf8String arg(Nan::Get(argv_, i).ToLocalChecked());
|
|
282
|
+
argv[i + 1] = strdup(*arg);
|
|
283
|
+
}
|
|
234
284
|
|
|
285
|
+
char* cwd = strdup(*cwd_);
|
|
235
286
|
sigset_t newmask, oldmask;
|
|
236
287
|
struct sigaction sig_action;
|
|
237
|
-
|
|
238
288
|
// temporarily block all signals
|
|
239
289
|
// this is needed due to a race condition in openpty
|
|
240
290
|
// and to avoid running signal handlers in the child
|
|
@@ -242,7 +292,7 @@ NAN_METHOD(PtyFork) {
|
|
|
242
292
|
sigfillset(&newmask);
|
|
243
293
|
pthread_sigmask(SIG_SETMASK, &newmask, &oldmask);
|
|
244
294
|
|
|
245
|
-
|
|
295
|
+
pid = forkpty(&master, nullptr, static_cast<termios*>(term), static_cast<winsize*>(&winp));
|
|
246
296
|
|
|
247
297
|
if (!pid) {
|
|
248
298
|
// remove all signal handler from child
|
|
@@ -252,21 +302,23 @@ NAN_METHOD(PtyFork) {
|
|
|
252
302
|
for (int i = 0 ; i < NSIG ; i++) { // NSIG is a macro for all signals + 1
|
|
253
303
|
sigaction(i, &sig_action, NULL);
|
|
254
304
|
}
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
|
|
258
|
-
|
|
259
|
-
if (pid) {
|
|
260
|
-
for (i = 0; i < argl; i++) free(argv[i]);
|
|
305
|
+
} else {
|
|
306
|
+
for (int i = 0; i < argl; i++) free(argv[i]);
|
|
261
307
|
delete[] argv;
|
|
262
|
-
|
|
308
|
+
|
|
309
|
+
for (int i = 0; i < envc; i++) free(env[i]);
|
|
263
310
|
delete[] env;
|
|
311
|
+
|
|
264
312
|
free(cwd);
|
|
265
313
|
}
|
|
266
314
|
|
|
315
|
+
// reenable signals
|
|
316
|
+
pthread_sigmask(SIG_SETMASK, &oldmask, NULL);
|
|
317
|
+
|
|
267
318
|
switch (pid) {
|
|
268
319
|
case -1:
|
|
269
|
-
|
|
320
|
+
Nan::ThrowError("forkpty(3) failed.");
|
|
321
|
+
goto done;
|
|
270
322
|
case 0:
|
|
271
323
|
if (strlen(cwd)) {
|
|
272
324
|
if (chdir(cwd) == -1) {
|
|
@@ -286,40 +338,56 @@ NAN_METHOD(PtyFork) {
|
|
|
286
338
|
}
|
|
287
339
|
}
|
|
288
340
|
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
341
|
+
{
|
|
342
|
+
char **old = environ;
|
|
343
|
+
environ = env;
|
|
344
|
+
execvp(argv[0], argv);
|
|
345
|
+
environ = old;
|
|
346
|
+
perror("execvp(3) failed.");
|
|
347
|
+
_exit(1);
|
|
348
|
+
}
|
|
293
349
|
default:
|
|
294
350
|
if (pty_nonblock(master) == -1) {
|
|
295
|
-
|
|
351
|
+
Nan::ThrowError("Could not set master fd to nonblocking.");
|
|
352
|
+
goto done;
|
|
296
353
|
}
|
|
354
|
+
}
|
|
355
|
+
#endif
|
|
297
356
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
Nan::
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
Nan::
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
357
|
+
{
|
|
358
|
+
v8::Local<v8::Object> obj = Nan::New<v8::Object>();
|
|
359
|
+
Nan::Set(obj,
|
|
360
|
+
Nan::New<v8::String>("fd").ToLocalChecked(),
|
|
361
|
+
Nan::New<v8::Number>(master));
|
|
362
|
+
Nan::Set(obj,
|
|
363
|
+
Nan::New<v8::String>("pid").ToLocalChecked(),
|
|
364
|
+
Nan::New<v8::Number>(pid));
|
|
365
|
+
Nan::Set(obj,
|
|
366
|
+
Nan::New<v8::String>("pty").ToLocalChecked(),
|
|
367
|
+
Nan::New<v8::String>(ptsname(master)).ToLocalChecked());
|
|
368
|
+
|
|
369
|
+
pty_baton *baton = new pty_baton();
|
|
370
|
+
baton->exit_code = 0;
|
|
371
|
+
baton->signal_code = 0;
|
|
372
|
+
baton->cb.Reset(v8::Local<v8::Function>::Cast(info[10]));
|
|
373
|
+
baton->pid = pid;
|
|
374
|
+
baton->async.data = baton;
|
|
375
|
+
|
|
376
|
+
uv_async_init(uv_default_loop(), &baton->async, pty_after_waitpid);
|
|
377
|
+
|
|
378
|
+
uv_thread_create(&baton->tid, pty_waitpid, static_cast<void*>(baton));
|
|
379
|
+
|
|
380
|
+
return info.GetReturnValue().Set(obj);
|
|
321
381
|
}
|
|
322
382
|
|
|
383
|
+
done:
|
|
384
|
+
#if defined(__APPLE__)
|
|
385
|
+
for (int i = 0; i < argl; i++) free(argv[i]);
|
|
386
|
+
delete[] argv;
|
|
387
|
+
|
|
388
|
+
for (int i = 0; i < envc; i++) free(env[i]);
|
|
389
|
+
delete[] env;
|
|
390
|
+
#endif
|
|
323
391
|
return info.GetReturnValue().SetUndefined();
|
|
324
392
|
}
|
|
325
393
|
|
|
@@ -341,7 +409,7 @@ NAN_METHOD(PtyOpen) {
|
|
|
341
409
|
|
|
342
410
|
// pty
|
|
343
411
|
int master, slave;
|
|
344
|
-
int ret =
|
|
412
|
+
int ret = openpty(&master, &slave, nullptr, NULL, static_cast<winsize*>(&winp));
|
|
345
413
|
|
|
346
414
|
if (ret == -1) {
|
|
347
415
|
return Nan::ThrowError("openpty(3) failed.");
|
|
@@ -406,6 +474,15 @@ NAN_METHOD(PtyResize) {
|
|
|
406
474
|
NAN_METHOD(PtyGetProc) {
|
|
407
475
|
Nan::HandleScope scope;
|
|
408
476
|
|
|
477
|
+
#if defined(__APPLE__)
|
|
478
|
+
if (info.Length() != 1 ||
|
|
479
|
+
!info[0]->IsNumber()) {
|
|
480
|
+
return Nan::ThrowError("Usage: pty.process(pid)");
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
int pid = info[0]->IntegerValue(Nan::GetCurrentContext()).FromJust();
|
|
484
|
+
char *name = pty_getproc(pid);
|
|
485
|
+
#else
|
|
409
486
|
if (info.Length() != 2 ||
|
|
410
487
|
!info[0]->IsNumber() ||
|
|
411
488
|
!info[1]->IsString()) {
|
|
@@ -418,6 +495,7 @@ NAN_METHOD(PtyGetProc) {
|
|
|
418
495
|
char *tty = strdup(*tty_);
|
|
419
496
|
char *name = pty_getproc(fd, tty);
|
|
420
497
|
free(tty);
|
|
498
|
+
#endif
|
|
421
499
|
|
|
422
500
|
if (name == NULL) {
|
|
423
501
|
return info.GetReturnValue().SetUndefined();
|
|
@@ -428,21 +506,6 @@ NAN_METHOD(PtyGetProc) {
|
|
|
428
506
|
return info.GetReturnValue().Set(name_);
|
|
429
507
|
}
|
|
430
508
|
|
|
431
|
-
/**
|
|
432
|
-
* execvpe
|
|
433
|
-
*/
|
|
434
|
-
|
|
435
|
-
// execvpe(3) is not portable.
|
|
436
|
-
// http://www.gnu.org/software/gnulib/manual/html_node/execvpe.html
|
|
437
|
-
static int
|
|
438
|
-
pty_execvpe(const char *file, char **argv, char **envp) {
|
|
439
|
-
char **old = environ;
|
|
440
|
-
environ = envp;
|
|
441
|
-
int ret = execvp(file, argv);
|
|
442
|
-
environ = old;
|
|
443
|
-
return ret;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
509
|
/**
|
|
447
510
|
* Nonblocking FD
|
|
448
511
|
*/
|
|
@@ -463,11 +526,44 @@ static void
|
|
|
463
526
|
pty_waitpid(void *data) {
|
|
464
527
|
int ret;
|
|
465
528
|
int stat_loc;
|
|
466
|
-
|
|
467
529
|
pty_baton *baton = static_cast<pty_baton*>(data);
|
|
468
|
-
|
|
469
530
|
errno = 0;
|
|
470
|
-
|
|
531
|
+
#if defined(__APPLE__)
|
|
532
|
+
// Based on
|
|
533
|
+
// https://source.chromium.org/chromium/chromium/src/+/main:base/process/kill_mac.cc;l=35-69?
|
|
534
|
+
int kq = HANDLE_EINTR(kqueue());
|
|
535
|
+
struct kevent change = {0};
|
|
536
|
+
EV_SET(&change, baton->pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL);
|
|
537
|
+
ret = HANDLE_EINTR(kevent(kq, &change, 1, NULL, 0, NULL));
|
|
538
|
+
if (ret == -1) {
|
|
539
|
+
if (errno == ESRCH) {
|
|
540
|
+
// At this point, one of the following has occurred:
|
|
541
|
+
// 1. The process has died but has not yet been reaped.
|
|
542
|
+
// 2. The process has died and has already been reaped.
|
|
543
|
+
// 3. The process is in the process of dying. It's no longer
|
|
544
|
+
// kqueueable, but it may not be waitable yet either. Mark calls
|
|
545
|
+
// this case the "zombie death race".
|
|
546
|
+
ret = HANDLE_EINTR(waitpid(baton->pid, &stat_loc, WNOHANG));
|
|
547
|
+
if (ret == 0) {
|
|
548
|
+
ret = kill(baton->pid, SIGKILL);
|
|
549
|
+
if (ret != -1) {
|
|
550
|
+
HANDLE_EINTR(waitpid(baton->pid, &stat_loc, 0));
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
} else {
|
|
555
|
+
struct kevent event = {0};
|
|
556
|
+
ret = HANDLE_EINTR(kevent(kq, NULL, 0, &event, 1, NULL));
|
|
557
|
+
if (ret == 1) {
|
|
558
|
+
if ((event.fflags & NOTE_EXIT) &&
|
|
559
|
+
(event.ident == static_cast<uintptr_t>(baton->pid))) {
|
|
560
|
+
// The process is dead or dying. This won't block for long, if at
|
|
561
|
+
// all.
|
|
562
|
+
HANDLE_EINTR(waitpid(baton->pid, &stat_loc, 0));
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
#else
|
|
471
567
|
if ((ret = waitpid(baton->pid, &stat_loc, 0)) != baton->pid) {
|
|
472
568
|
if (ret == -1 && errno == EINTR) {
|
|
473
569
|
return pty_waitpid(baton);
|
|
@@ -480,6 +576,7 @@ pty_waitpid(void *data) {
|
|
|
480
576
|
assert(false);
|
|
481
577
|
}
|
|
482
578
|
}
|
|
579
|
+
#endif
|
|
483
580
|
|
|
484
581
|
if (WIFEXITED(stat_loc)) {
|
|
485
582
|
baton->exit_code = WEXITSTATUS(stat_loc); // errno?
|
|
@@ -595,25 +692,13 @@ pty_getproc(int fd, char *tty) {
|
|
|
595
692
|
#elif defined(__APPLE__)
|
|
596
693
|
|
|
597
694
|
static char *
|
|
598
|
-
pty_getproc(int
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
struct kinfo_proc kp;
|
|
602
|
-
|
|
603
|
-
if ((mib[3] = tcgetpgrp(fd)) == -1) {
|
|
695
|
+
pty_getproc(int pid) {
|
|
696
|
+
char pname[MAXCOMLEN + 1];
|
|
697
|
+
if (!proc_name(pid, pname, sizeof(pname))) {
|
|
604
698
|
return NULL;
|
|
605
699
|
}
|
|
606
700
|
|
|
607
|
-
|
|
608
|
-
if (sysctl(mib, 4, &kp, &size, NULL, 0) == -1) {
|
|
609
|
-
return NULL;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
if (size != (sizeof kp) || *kp.kp_proc.p_comm == '\0') {
|
|
613
|
-
return NULL;
|
|
614
|
-
}
|
|
615
|
-
|
|
616
|
-
return strdup(kp.kp_proc.p_comm);
|
|
701
|
+
return strdup(pname);
|
|
617
702
|
}
|
|
618
703
|
|
|
619
704
|
#else
|
|
@@ -625,99 +710,106 @@ pty_getproc(int fd, char *tty) {
|
|
|
625
710
|
|
|
626
711
|
#endif
|
|
627
712
|
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if (grantpt(master) == -1) goto err;
|
|
646
|
-
if (unlockpt(master) == -1) goto err;
|
|
647
|
-
|
|
648
|
-
slave_name = ptsname(master);
|
|
649
|
-
if (slave_name == NULL) goto err;
|
|
650
|
-
if (name) strcpy(name, slave_name);
|
|
651
|
-
|
|
652
|
-
slave = open(slave_name, O_RDWR | O_NOCTTY);
|
|
653
|
-
if (slave == -1) goto err;
|
|
654
|
-
if (aslave) *aslave = slave;
|
|
713
|
+
#if defined(__APPLE__)
|
|
714
|
+
static void
|
|
715
|
+
pty_posix_spawn(char** argv, char** env,
|
|
716
|
+
const struct termios *termp,
|
|
717
|
+
const struct winsize *winp,
|
|
718
|
+
int* master,
|
|
719
|
+
pid_t* pid,
|
|
720
|
+
int* err) {
|
|
721
|
+
int low_fds[3];
|
|
722
|
+
size_t count = 0;
|
|
723
|
+
|
|
724
|
+
for (; count < 3; count++) {
|
|
725
|
+
low_fds[count] = posix_openpt(O_RDWR);
|
|
726
|
+
if (low_fds[count] >= STDERR_FILENO)
|
|
727
|
+
break;
|
|
728
|
+
}
|
|
655
729
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
730
|
+
int flags = POSIX_SPAWN_CLOEXEC_DEFAULT |
|
|
731
|
+
POSIX_SPAWN_SETSIGDEF |
|
|
732
|
+
POSIX_SPAWN_SETSIGMASK |
|
|
733
|
+
POSIX_SPAWN_SETSID;
|
|
734
|
+
*master = posix_openpt(O_RDWR);
|
|
735
|
+
if (*master == -1) {
|
|
736
|
+
return;
|
|
737
|
+
}
|
|
659
738
|
|
|
660
|
-
|
|
661
|
-
if (
|
|
739
|
+
int res = grantpt(*master) || unlockpt(*master);
|
|
740
|
+
if (res == -1) {
|
|
741
|
+
return;
|
|
742
|
+
}
|
|
662
743
|
|
|
663
|
-
|
|
744
|
+
// Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
|
|
745
|
+
int slave;
|
|
746
|
+
char slave_pty_name[128];
|
|
747
|
+
res = ioctl(*master, TIOCPTYGNAME, slave_pty_name);
|
|
748
|
+
if (res == -1) {
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
664
751
|
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
return openpty(amaster, aslave, name, (termios *)termp, (winsize *)winp);
|
|
670
|
-
#endif
|
|
671
|
-
}
|
|
752
|
+
slave = open(slave_pty_name, O_RDWR | O_NOCTTY);
|
|
753
|
+
if (slave == -1) {
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
672
756
|
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
int master, slave;
|
|
757
|
+
if (termp) {
|
|
758
|
+
res = tcsetattr(slave, TCSANOW, termp);
|
|
759
|
+
if (res == -1) {
|
|
760
|
+
return;
|
|
761
|
+
};
|
|
762
|
+
}
|
|
680
763
|
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
764
|
+
if (winp) {
|
|
765
|
+
res = ioctl(slave, TIOCSWINSZ, winp);
|
|
766
|
+
if (res == -1) {
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
}
|
|
684
770
|
|
|
685
|
-
|
|
771
|
+
posix_spawn_file_actions_t acts;
|
|
772
|
+
posix_spawn_file_actions_init(&acts);
|
|
773
|
+
posix_spawn_file_actions_adddup2(&acts, slave, STDIN_FILENO);
|
|
774
|
+
posix_spawn_file_actions_adddup2(&acts, slave, STDOUT_FILENO);
|
|
775
|
+
posix_spawn_file_actions_adddup2(&acts, slave, STDERR_FILENO);
|
|
776
|
+
posix_spawn_file_actions_addclose(&acts, slave);
|
|
777
|
+
posix_spawn_file_actions_addclose(&acts, *master);
|
|
778
|
+
|
|
779
|
+
posix_spawnattr_t attrs;
|
|
780
|
+
posix_spawnattr_init(&attrs);
|
|
781
|
+
*err = posix_spawnattr_setflags(&attrs, flags);
|
|
782
|
+
if (*err != 0) {
|
|
783
|
+
goto done;
|
|
784
|
+
}
|
|
686
785
|
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
setsid();
|
|
695
|
-
|
|
696
|
-
#if defined(TIOCSCTTY)
|
|
697
|
-
// glibc does this
|
|
698
|
-
if (ioctl(slave, TIOCSCTTY, NULL) == -1) {
|
|
699
|
-
_exit(1);
|
|
700
|
-
}
|
|
701
|
-
#endif
|
|
786
|
+
sigset_t signal_set;
|
|
787
|
+
/* Reset all signal the child to their default behavior */
|
|
788
|
+
sigfillset(&signal_set);
|
|
789
|
+
*err = posix_spawnattr_setsigdefault(&attrs, &signal_set);
|
|
790
|
+
if (*err != 0) {
|
|
791
|
+
goto done;
|
|
792
|
+
}
|
|
702
793
|
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
794
|
+
/* Reset the signal mask for all signals */
|
|
795
|
+
sigemptyset(&signal_set);
|
|
796
|
+
*err = posix_spawnattr_setsigmask(&attrs, &signal_set);
|
|
797
|
+
if (*err != 0) {
|
|
798
|
+
goto done;
|
|
799
|
+
}
|
|
706
800
|
|
|
707
|
-
|
|
801
|
+
do
|
|
802
|
+
*err = posix_spawn(pid, argv[0], &acts, &attrs, argv, env);
|
|
803
|
+
while (*err == EINTR);
|
|
804
|
+
done:
|
|
805
|
+
posix_spawn_file_actions_destroy(&acts);
|
|
806
|
+
posix_spawnattr_destroy(&attrs);
|
|
708
807
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
close(slave);
|
|
712
|
-
return pid;
|
|
808
|
+
for (; count > 0; count--) {
|
|
809
|
+
close(low_fds[count]);
|
|
713
810
|
}
|
|
714
|
-
|
|
715
|
-
return -1;
|
|
716
|
-
#else
|
|
717
|
-
return forkpty(amaster, name, (termios *)termp, (winsize *)winp);
|
|
718
|
-
#endif
|
|
719
811
|
}
|
|
720
|
-
|
|
812
|
+
#endif
|
|
721
813
|
|
|
722
814
|
/**
|
|
723
815
|
* Init
|