@@ -97,7 +97,24 @@ static bool check_host_origin(struct lws *wsi) {
9797 return len > 0 && strcasecmp (buf , host_buf ) == 0 ;
9898}
9999
100- pid_t pty_fork (int * pty , const char * file , char * const argv [], const char * term ) {
100+ static bool fd_set_cloexec (const int fd ) {
101+ int flags = fcntl (fd , F_GETFD );
102+ if (flags < 0 ) return false;
103+ return (flags & FD_CLOEXEC ) == 0 || fcntl (fd , F_SETFD , flags | FD_CLOEXEC ) != -1 ;
104+ }
105+
106+ static int fd_duplicate (int fd , uv_pipe_t * pipe ) {
107+ int fd_dup = dup (fd );
108+ if (fd_dup < 0 ) return - errno ;
109+
110+ fd_set_cloexec (fd_dup );
111+
112+ int status = uv_pipe_open (pipe , fd_dup );
113+ if (status ) close (fd_dup );
114+ return status ;
115+ }
116+
117+ static pid_t pty_fork (int * pty , const char * file , char * const argv [], const char * term ) {
101118 pid_t pid = forkpty (pty , NULL , NULL , NULL );
102119
103120 if (pid < 0 ) {
@@ -122,7 +139,7 @@ pid_t pty_fork(int *pty, const char *file, char *const argv[], const char *term)
122139 return pid ;
123140}
124141
125- int pty_resize (int pty , int cols , int rows ) {
142+ static int pty_resize (int pty , int cols , int rows ) {
126143 struct winsize size ;
127144
128145 size .ws_col = (unsigned short )cols ;
@@ -134,21 +151,22 @@ int pty_resize(int pty, int cols, int rows) {
134151}
135152
136153static void close_cb (uv_handle_t * handle ) {
137- struct pty_proc * proc = container_of ((uv_pipe_t * )handle , struct pty_proc , pipe );
154+ struct pty_proc * proc = container_of ((uv_pipe_t * )handle , struct pty_proc , out_pipe );
138155 free (proc );
139156}
140157
141158static void pty_proc_free (struct pty_proc * proc ) {
142- uv_read_stop ((uv_stream_t * )& proc -> pipe );
143- close (proc -> pty );
159+ uv_read_stop ((uv_stream_t * )& proc -> out_pipe );
160+ if ( proc -> pty_fd > 0 ) close (proc -> pty_fd );
144161 if (proc -> pty_buffer != NULL ) {
145162 free (proc -> pty_buffer );
146163 proc -> pty_buffer = NULL ;
147164 }
148165 for (int i = 0 ; i < proc -> argc ; i ++ ) {
149166 free (proc -> args [i ]);
150167 }
151- uv_close ((uv_handle_t * )& proc -> pipe , close_cb );
168+ uv_close ((uv_handle_t * )& proc -> in_pipe , NULL );
169+ uv_close ((uv_handle_t * )& proc -> out_pipe , close_cb );
152170}
153171
154172static void alloc_cb (uv_handle_t * handle , size_t suggested_size , uv_buf_t * buf ) {
@@ -232,16 +250,21 @@ static int spawn_process(struct pss_tty *pss) {
232250 fd_set_cloexec (lws_get_socket_fd (pss -> wsi ));
233251
234252 // create process with pseudo-tty
235- proc -> pid = pty_fork (& proc -> pty , argv [0 ], argv , server -> terminal_type );
236- if (proc -> pid < 0 ) {
253+ uv_disable_stdio_inheritance ();
254+ int master , pid ;
255+ pid = pty_fork (& master , argv [0 ], argv , server -> terminal_type );
256+ if (pid < 0 ) {
237257 lwsl_err ("pty_fork: %d (%s)\n" , errno , strerror (errno ));
238258 return 1 ;
239259 }
240260
241- lwsl_notice ("started process, pid: %d\n" , proc -> pid );
261+ lwsl_notice ("started process, pid: %d\n" , pid );
242262
243- proc -> pipe .data = pss ;
244- uv_pipe_open (& proc -> pipe , proc -> pty );
263+ proc -> pty_fd = master ;
264+ proc -> pid = pid ;
265+ proc -> out_pipe .data = pss ;
266+ if (fd_duplicate (master , & proc -> in_pipe ) || fd_duplicate (master , & proc -> out_pipe ))
267+ return 1 ;
245268
246269 lws_callback_on_writable (pss -> wsi );
247270
@@ -314,7 +337,8 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
314337 memset (proc , 0 , sizeof (struct pty_proc ));
315338 proc -> status = -1 ;
316339 proc -> state = STATE_INIT ;
317- uv_pipe_init (server -> loop , & proc -> pipe , 0 );
340+ uv_pipe_init (server -> loop , & proc -> in_pipe , 0 );
341+ uv_pipe_init (server -> loop , & proc -> out_pipe , 0 );
318342
319343 if (server -> url_arg ) {
320344 while (lws_hdr_copy_fragment (wsi , buf , sizeof (buf ), WSI_TOKEN_HTTP_URI_ARGS , n ++ ) > 0 ) {
@@ -344,7 +368,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
344368 if (!pss -> initialized ) {
345369 if (pss -> initial_cmd_index == sizeof (initial_cmds )) {
346370 pss -> initialized = true;
347- uv_read_start ((uv_stream_t * )& proc -> pipe , alloc_cb , read_cb );
371+ uv_read_start ((uv_stream_t * )& proc -> out_pipe , alloc_cb , read_cb );
348372 break ;
349373 }
350374 if (send_initial_message (wsi , pss -> initial_cmd_index ) < 0 ) {
@@ -376,7 +400,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
376400 proc -> pty_buffer = NULL ;
377401 }
378402
379- uv_read_start ((uv_stream_t * )& proc -> pipe , alloc_cb , read_cb );
403+ uv_read_start ((uv_stream_t * )& proc -> out_pipe , alloc_cb , read_cb );
380404 break ;
381405
382406 case LWS_CALLBACK_RECEIVE :
@@ -406,7 +430,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
406430 proc = pss -> proc ;
407431 switch (command ) {
408432 case INPUT :
409- if (proc -> pty == 0 ) break ;
433+ if (proc -> pty_fd == 0 ) break ;
410434 if (server -> readonly ) break ;
411435
412436 char * data = xmalloc (pss -> len - 1 );
@@ -416,7 +440,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
416440 uv_write_t * req = xmalloc (sizeof (uv_write_t ));
417441 req -> data = data ;
418442
419- int err = uv_write (req , (uv_stream_t * )& proc -> pipe , & b , 1 , write_cb );
443+ int err = uv_write (req , (uv_stream_t * )& proc -> in_pipe , & b , 1 , write_cb );
420444 if (err ) {
421445 lwsl_err ("uv_write: %s (%s)\n" , uv_err_name (err ), uv_strerror (err ));
422446 return -1 ;
@@ -425,20 +449,20 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
425449 case RESIZE_TERMINAL : {
426450 int cols , rows ;
427451 if (parse_window_size (pss , & cols , & rows )) {
428- if (pty_resize (proc -> pty , cols , rows ) < 0 ) {
452+ if (pty_resize (proc -> pty_fd , cols , rows ) < 0 ) {
429453 lwsl_err ("pty_resize: %d (%s)\n" , errno , strerror (errno ));
430454 }
431455 }
432456 } break ;
433457 case PAUSE :
434458 if (proc -> state == STATE_INIT ) {
435- uv_read_stop ((uv_stream_t * )& proc -> pipe );
459+ uv_read_stop ((uv_stream_t * )& proc -> out_pipe );
436460 proc -> state = STATE_PAUSE ;
437461 }
438462 break ;
439463 case RESUME :
440464 if (proc -> state == STATE_PAUSE ) {
441- uv_read_start ((uv_stream_t * )& proc -> pipe , alloc_cb , read_cb );
465+ uv_read_start ((uv_stream_t * )& proc -> out_pipe , alloc_cb , read_cb );
442466 proc -> state = STATE_INIT ;
443467 }
444468 break ;
@@ -486,7 +510,7 @@ int callback_tty(struct lws *wsi, enum lws_callback_reasons reason, void *user,
486510 pty_proc_free (proc );
487511 } else {
488512 proc -> state = STATE_KILL ;
489- uv_read_stop ((uv_stream_t * )& proc -> pipe );
513+ uv_read_stop ((uv_stream_t * )& proc -> out_pipe );
490514 kill_process (proc );
491515 }
492516
0 commit comments