@@ -281,53 +281,39 @@ int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp,
281281 (size_t )newlen);
282282}
283283
284- static fd_t internal_spawn_impl (const char * argv[], const char * envp[],
285- pid_t *pid ) {
286- fd_t primary_fd = kInvalidFd ;
287- fd_t secondary_fd = kInvalidFd ;
284+ bool internal_spawn (const char * argv[], const char * envp[], pid_t * pid ,
285+ fd_t fd_stdin, fd_t fd_stdout ) {
286+ // NOTE: Caller ensures that fd_stdin and fd_stdout are not 0, 1, or 2, since
287+ // this can break communication.
288288
289+ int res;
289290 auto fd_closer = at_scope_exit ([&] {
290- internal_close (primary_fd );
291- internal_close (secondary_fd );
291+ internal_close (fd_stdin );
292+ internal_close (fd_stdout );
292293 });
293294
294- // We need a new pseudoterminal to avoid buffering problems. The 'atos' tool
295- // in particular detects when it's talking to a pipe and forgets to flush the
296- // output stream after sending a response.
297- primary_fd = posix_openpt (O_RDWR);
298- if (primary_fd == kInvalidFd )
299- return kInvalidFd ;
300-
301- int res = grantpt (primary_fd) || unlockpt (primary_fd);
302- if (res != 0 ) return kInvalidFd ;
303-
304- // Use TIOCPTYGNAME instead of ptsname() to avoid threading problems.
305- char secondary_pty_name[128 ];
306- res = ioctl (primary_fd, TIOCPTYGNAME, secondary_pty_name);
307- if (res == -1 ) return kInvalidFd ;
308-
309- secondary_fd = internal_open (secondary_pty_name, O_RDWR);
310- if (secondary_fd == kInvalidFd )
311- return kInvalidFd ;
312-
313295 // File descriptor actions
314296 posix_spawn_file_actions_t acts;
315297 res = posix_spawn_file_actions_init (&acts);
316- if (res != 0 ) return kInvalidFd ;
298+ if (res != 0 )
299+ return false ;
317300
318301 auto acts_cleanup = at_scope_exit ([&] {
319302 posix_spawn_file_actions_destroy (&acts);
320303 });
321304
322- res = posix_spawn_file_actions_adddup2 (&acts, secondary_fd, STDIN_FILENO) ||
323- posix_spawn_file_actions_adddup2 (&acts, secondary_fd, STDOUT_FILENO) ||
324- posix_spawn_file_actions_addclose (&acts, secondary_fd);
325- if (res != 0 ) return kInvalidFd ;
305+ res = posix_spawn_file_actions_adddup2 (&acts, fd_stdin, STDIN_FILENO) ||
306+ posix_spawn_file_actions_adddup2 (&acts, fd_stdout, STDOUT_FILENO) ||
307+ posix_spawn_file_actions_addclose (&acts, fd_stdin) ||
308+ posix_spawn_file_actions_addclose (&acts, fd_stdout);
309+ if (res != 0 )
310+ return false ;
326311
327312 // Spawn attributes
328313 posix_spawnattr_t attrs;
329314 res = posix_spawnattr_init (&attrs);
330- if (res != 0 ) return kInvalidFd ;
315+ if (res != 0 )
316+ return false ;
331317
332318 auto attrs_cleanup = at_scope_exit ([&] {
333319 posix_spawnattr_destroy (&attrs);
@@ -336,50 +322,17 @@ static fd_t internal_spawn_impl(const char *argv[], const char *envp[],
336322 // In the spawned process, close all file descriptors that are not explicitly
337323 // described by the file actions object. This is Darwin-specific extension.
338324 res = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_CLOEXEC_DEFAULT);
339- if (res != 0 ) return kInvalidFd ;
325+ if (res != 0 )
326+ return false ;
340327
341328 // posix_spawn
342329 char **argv_casted = const_cast <char **>(argv);
343330 char **envp_casted = const_cast <char **>(envp);
344331 res = posix_spawn (pid, argv[0 ], &acts, &attrs, argv_casted, envp_casted);
345- if (res != 0 ) return kInvalidFd ;
346-
347- // Disable echo in the new terminal, disable CR.
348- struct termios termflags;
349- tcgetattr (primary_fd, &termflags);
350- termflags.c_oflag &= ~ONLCR;
351- termflags.c_lflag &= ~ECHO;
352- tcsetattr (primary_fd, TCSANOW, &termflags);
353-
354- // On success, do not close primary_fd on scope exit.
355- fd_t fd = primary_fd;
356- primary_fd = kInvalidFd ;
357-
358- return fd;
359- }
360-
361- fd_t internal_spawn (const char *argv[], const char *envp[], pid_t *pid) {
362- // The client program may close its stdin and/or stdout and/or stderr thus
363- // allowing open/posix_openpt to reuse file descriptors 0, 1 or 2. In this
364- // case the communication is broken if either the parent or the child tries to
365- // close or duplicate these descriptors. We temporarily reserve these
366- // descriptors here to prevent this.
367- fd_t low_fds[3 ];
368- size_t count = 0 ;
369-
370- for (; count < 3 ; count++) {
371- low_fds[count] = posix_openpt (O_RDWR);
372- if (low_fds[count] >= STDERR_FILENO)
373- break ;
374- }
375-
376- fd_t fd = internal_spawn_impl (argv, envp, pid);
377-
378- for (; count > 0 ; count--) {
379- internal_close (low_fds[count]);
380- }
332+ if (res != 0 )
333+ return false ;
381334
382- return fd ;
335+ return true ;
383336}
384337
385338uptr internal_rename (const char *oldpath, const char *newpath) {
0 commit comments