Commit fdf568aa authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

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

parent 7856fec1
...@@ -58,7 +58,9 @@ ...@@ -58,7 +58,9 @@
#define WIN32_NO_STATUS #define WIN32_NO_STATUS
#include "windef.h" #include "windef.h"
#include "winternl.h" #include "winternl.h"
#include "winioctl.h"
#include "unix_private.h" #include "unix_private.h"
#include "wine/condrv.h"
#include "wine/exception.h" #include "wine/exception.h"
#include "wine/server.h" #include "wine/server.h"
#include "wine/debug.h" #include "wine/debug.h"
...@@ -387,13 +389,24 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd ) ...@@ -387,13 +389,24 @@ static void set_stdio_fd( int stdin_fd, int stdout_fd )
if (stdout_fd == -1) stdout_fd = fd; if (stdout_fd == -1) stdout_fd = fd;
} }
dup2( stdin_fd, 0 ); if (stdin_fd != 0) dup2( stdin_fd, 0 );
dup2( stdout_fd, 1 ); if (stdout_fd != 1) dup2( stdout_fd, 1 );
if (fd != -1) close( fd ); 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 * spawn_process
*/ */
static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd, static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int socketfd,
...@@ -404,8 +417,13 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so ...@@ -404,8 +417,13 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
pid_t pid; pid_t pid;
char **argv; char **argv;
wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL ); if (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 ); 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 */ if (!(pid = fork())) /* child */
{ {
...@@ -420,8 +438,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so ...@@ -420,8 +438,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
} }
else set_stdio_fd( stdin_fd, stdout_fd ); else set_stdio_fd( stdin_fd, stdout_fd );
if (stdin_fd != -1) close( stdin_fd ); if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
if (stdout_fd != -1) close( stdout_fd ); if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
if (winedebug) putenv( winedebug ); if (winedebug) putenv( winedebug );
if (unixdir != -1) if (unixdir != -1)
...@@ -448,8 +466,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so ...@@ -448,8 +466,8 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
} }
else status = STATUS_NO_MEMORY; else status = STATUS_NO_MEMORY;
if (stdin_fd != -1) close( stdin_fd ); if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
if (stdout_fd != -1) close( stdout_fd ); if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
return status; return status;
} }
...@@ -484,8 +502,13 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir, ...@@ -484,8 +502,13 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
fcntl( fd[1], F_SETFD, FD_CLOEXEC ); fcntl( fd[1], F_SETFD, FD_CLOEXEC );
} }
wine_server_handle_to_fd( params->hStdInput, FILE_READ_DATA, &stdin_fd, NULL ); if (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 ); 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 */ if (!(pid = fork())) /* child */
{ {
...@@ -494,7 +517,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir, ...@@ -494,7 +517,7 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
close( fd[0] ); close( fd[0] );
if (params->ConsoleFlags || 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)) (params->hStdInput == INVALID_HANDLE_VALUE && params->hStdOutput == INVALID_HANDLE_VALUE))
{ {
setsid(); setsid();
...@@ -502,8 +525,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir, ...@@ -502,8 +525,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
} }
else set_stdio_fd( stdin_fd, stdout_fd ); else set_stdio_fd( stdin_fd, stdout_fd );
if (stdin_fd != -1) close( stdin_fd ); if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
if (stdout_fd != -1) close( stdout_fd ); if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
/* Reset signals that we previously set to SIG_IGN */ /* Reset signals that we previously set to SIG_IGN */
signal( SIGPIPE, SIG_DFL ); signal( SIGPIPE, SIG_DFL );
...@@ -550,8 +573,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir, ...@@ -550,8 +573,8 @@ static NTSTATUS fork_and_exec( OBJECT_ATTRIBUTES *attr, int unixdir,
else status = STATUS_NO_MEMORY; else status = STATUS_NO_MEMORY;
close( fd[0] ); close( fd[0] );
if (stdin_fd != -1) close( stdin_fd ); if (stdin_fd != -1 && stdin_fd != 0) close( stdin_fd );
if (stdout_fd != -1) close( stdout_fd ); if (stdout_fd != -1 && stdout_fd != 1) close( stdout_fd );
done: done:
free( unix_name ); free( unix_name );
return status; return status;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
/* common console input and output ioctls */ /* 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_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_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 */ /* console input ioctls */
#define IOCTL_CONDRV_READ_CONSOLE CTL_CODE(FILE_DEVICE_CONSOLE, 10, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_CONDRV_READ_CONSOLE CTL_CODE(FILE_DEVICE_CONSOLE, 10, METHOD_BUFFERED, FILE_READ_ACCESS)
......
...@@ -2375,6 +2375,9 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign ...@@ -2375,6 +2375,9 @@ static NTSTATUS screen_buffer_ioctl( struct screen_buffer *screen_buffer, unsign
TRACE( "set %x mode\n", screen_buffer->mode ); TRACE( "set %x mode\n", screen_buffer->mode );
return STATUS_SUCCESS; return STATUS_SUCCESS;
case IOCTL_CONDRV_IS_UNIX:
return screen_buffer->console->is_unix ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
case IOCTL_CONDRV_WRITE_CONSOLE: case IOCTL_CONDRV_WRITE_CONSOLE:
if (in_size % sizeof(WCHAR) || *out_size) return STATUS_INVALID_PARAMETER; if (in_size % sizeof(WCHAR) || *out_size) return STATUS_INVALID_PARAMETER;
return write_console( screen_buffer, in_data, in_size / sizeof(WCHAR) ); 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, ...@@ -2452,6 +2455,9 @@ static NTSTATUS console_input_ioctl( struct console *console, unsigned int code,
TRACE( "set %x mode\n", console->mode ); TRACE( "set %x mode\n", console->mode );
return STATUS_SUCCESS; return STATUS_SUCCESS;
case IOCTL_CONDRV_IS_UNIX:
return console->is_unix ? STATUS_SUCCESS : STATUS_NOT_SUPPORTED;
case IOCTL_CONDRV_READ_CONSOLE: case IOCTL_CONDRV_READ_CONSOLE:
if (in_size || *out_size % sizeof(WCHAR)) return STATUS_INVALID_PARAMETER; if (in_size || *out_size % sizeof(WCHAR)) return STATUS_INVALID_PARAMETER;
ensure_tty_input_thread( console ); ensure_tty_input_thread( console );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment