Jacek Caban : ntdll: Inherit tty std input and output in processes attached to Unix console.

Alexandre Julliard julliard at winehq.org
Wed May 5 16:09:01 CDT 2021


Module: wine
Branch: master
Commit: fdf568aaaef658de63f94d8f58feb872105f5c7c
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=fdf568aaaef658de63f94d8f58feb872105f5c7c

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Wed May  5 20:39:00 2021 +0200

ntdll: Inherit tty std input and output in processes attached to Unix console.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50117
Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/unix/process.c  | 53 +++++++++++++++++++++++++++++++++-------------
 include/wine/condrv.h      |  1 +
 programs/conhost/conhost.c |  6 ++++++
 3 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c
index ce2033bc0dc..79a4bbce7a8 100644
--- a/dlls/ntdll/unix/process.c
+++ b/dlls/ntdll/unix/process.c
@@ -58,7 +58,9 @@
 #define WIN32_NO_STATUS
 #include "windef.h"
 #include "winternl.h"
+#include "winioctl.h"
 #include "unix_private.h"
+#include "wine/condrv.h"
 #include "wine/exception.h"
 #include "wine/server.h"
 #include "wine/debug.h"
@@ -387,12 +389,23 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd )
         if (stdout_fd == -1) stdout_fd = fd;
     }
 
-    dup2( stdin_fd, 0 );
-    dup2( stdout_fd, 1 );
+    if (stdin_fd != 0) dup2( stdin_fd, 0 );
+    if (stdout_fd != 1) dup2( stdout_fd, 1 );
     if (fd != -1) close( fd );
 }
 
 
+/***********************************************************************
+ *           is_unix_console_handle
+ */
+static BOOL is_unix_console_handle( HANDLE handle )
+{
+    IO_STATUS_BLOCK io;
+    return !NtDeviceIoControlFile( handle, NULL, NULL, NULL, &io, IOCTL_CONDRV_IS_UNIX,
+                                   NULL, 0, NULL, 0 );
+}
+
+
 /***********************************************************************
  *           spawn_process
  */
@@ -404,8 +417,13 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
     pid_t pid;
     char **argv;
 
-    wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL );
-    wine_server_handle_to_fd( params->hStdOutput, FILE_WRITE_DATA, &stdout_fd, NULL );
+    if (wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL ) &&
+        isatty(0) && is_unix_console_handle( params->hStdInput ))
+        stdin_fd = 0;
+
+    if (wine_server_handle_to_fd( params->hStdOutput, FILE_WRITE_DATA, &stdout_fd, NULL ) &&
+        isatty(1) && is_unix_console_handle( params->hStdOutput ))
+        stdout_fd = 1;
 
     if (!(pid = fork()))  /* child */
     {
@@ -420,8 +438,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
             }
             else set_stdio_fd( stdin_fd, stdout_fd );
 
-            if (stdin_fd != -1) close( stdin_fd );
-            if (stdout_fd != -1) close( stdout_fd );
+            if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
+            if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
 
             if (winedebug) putenv( winedebug );
             if (unixdir != -1)
@@ -448,8 +466,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
     }
     else status = STATUS_NO_MEMORY;
 
-    if (stdin_fd != -1) close( stdin_fd );
-    if (stdout_fd != -1) close( stdout_fd );
+    if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
+    if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
     return status;
 }
 
@@ -484,8 +502,13 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
         fcntl( fd[1], F_SETFD, FD_CLOEXEC );
     }
 
-    wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL );
-    wine_server_handle_to_fd( params->hStdOutput, FILE_WRITE_DATA, &stdout_fd, NULL );
+    if (wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL ) &&
+        isatty(0) && is_unix_console_handle( params->hStdInput ))
+        stdin_fd = 0;
+
+    if (wine_server_handle_to_fd( params->hStdOutput, FILE_WRITE_DATA, &stdout_fd, NULL ) &&
+        isatty(1) && is_unix_console_handle( params->hStdOutput ))
+        stdout_fd = 1;
 
     if (!(pid = fork()))  /* child */
     {
@@ -494,7 +517,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
             close( fd[0] );
 
             if (params->ConsoleFlags ||
-                params->ConsoleHandle == (HANDLE)1 /* KERNEL32_CONSOLE_ALLOC */ ||
+                params->ConsoleHandle == CONSOLE_HANDLE_ALLOC ||
                 (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE))
             {
                 setsid();
@@ -502,8 +525,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
             }
             else set_stdio_fd( stdin_fd, stdout_fd );
 
-            if (stdin_fd != -1) close( stdin_fd );
-            if (stdout_fd != -1) close( stdout_fd );
+            if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
+            if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
 
             /* Reset signals that we previously set to SIG_IGN */
             signal( SIGPIPE, SIG_DFL );
@@ -550,8 +573,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
     else status = STATUS_NO_MEMORY;
 
     close( fd[0] );
-    if (stdin_fd != -1) close( stdin_fd );
-    if (stdout_fd != -1) close( stdout_fd );
+    if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
+    if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
 done:
     free( unix_name );
     return status;
diff --git a/include/wine/condrv.h b/include/wine/condrv.h
index 5c3c550070d..add08be20c8 100644
--- a/include/wine/condrv.h
+++ b/include/wine/condrv.h
@@ -27,6 +27,7 @@
 /* common console input and output ioctls */
 #define IOCTL_CONDRV_GET_MODE              CTL_CODE(FILE_DEVICE_CONSOLE,  0, METHOD_BUFFERED, FILE_READ_ACCESS)
 #define IOCTL_CONDRV_SET_MODE              CTL_CODE(FILE_DEVICE_CONSOLE,  1, METHOD_BUFFERED, FILE_WRITE_ACCESS)
+#define IOCTL_CONDRV_IS_UNIX               CTL_CODE(FILE_DEVICE_CONSOLE,  2, METHOD_BUFFERED, FILE_ANY_ACCESS)
 
 /* console input ioctls */
 #define IOCTL_CONDRV_READ_CONSOLE          CTL_CODE(FILE_DEVICE_CONSOLE, 10, METHOD_BUFFERED, FILE_READ_ACCESS)
diff --git a/programs/conhost/conhost.c b/programs/conhost/conhost.c
index f83528cb5f6..dd423ee5491 100644
--- a/programs/conhost/conhost.c
+++ b/programs/conhost/conhost.c
@@ -2375,6 +2375,9 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign
         TRACE( "set %x mode\n", screen_buffer->mode );
         return STATUS_SUCCESS;
 
+    case IOCTL_CONDRV_IS_UNIX:
+        return screen_buffer->console->is_unix ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
+
     case IOCTL_CONDRV_WRITE_CONSOLE:
         if (in_size % sizeof(WCHAR) || *out_size) return STATUS_INVALID_PARAMETER;
         return write_console( screen_buffer, in_data, in_size / sizeof(WCHAR) );
@@ -2452,6 +2455,9 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code,
         TRACE( "set %x mode\n", console->mode );
         return STATUS_SUCCESS;
 
+    case IOCTL_CONDRV_IS_UNIX:
+        return console->is_unix ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
+
     case IOCTL_CONDRV_READ_CONSOLE:
         if (in_size || *out_size % sizeof(WCHAR)) return STATUS_INVALID_PARAMETER;
         ensure_tty_input_thread( console );




More information about the wine-cvs mailing list