ntdll: Add a __wine_unix_spawnvp syscall.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-09-27 12:30:25 +02:00
parent a851703ed7
commit c1b3d6eb10
7 changed files with 77 additions and 1 deletions

View File

@ -1622,6 +1622,7 @@
# Unix interface
@ stdcall -syscall __wine_unix_call(int64 long ptr)
@ stdcall -syscall __wine_unix_spawnvp(long ptr)
@ cdecl __wine_set_unix_funcs(long ptr)
@ cdecl __wine_init_unix_lib(long long ptr ptr)
@ stdcall __wine_ctrl_routine(ptr)

View File

@ -344,6 +344,7 @@ static void * const syscalls[] =
NtYieldExecution,
__wine_dbg_write,
__wine_unix_call,
__wine_unix_spawnvp,
wine_nt_to_unix_file_name,
wine_server_call,
wine_server_fd_to_handle,

View File

@ -481,6 +481,59 @@ static NTSTATUS spawn_process( const RTL_USER_PROCESS_PARAMETERS *params, int so
}
/***********************************************************************
* __wine_unix_spawnvp
*/
NTSTATUS WINAPI __wine_unix_spawnvp( char * const argv[], int wait )
{
pid_t pid, wret;
int fd[2], status, err;
#ifdef HAVE_PIPE2
if (pipe2( fd, O_CLOEXEC ) == -1)
#endif
{
if (pipe(fd) == -1) return STATUS_TOO_MANY_OPENED_FILES;
fcntl( fd[0], F_SETFD, FD_CLOEXEC );
fcntl( fd[1], F_SETFD, FD_CLOEXEC );
}
if (!(pid = fork()))
{
/* in child */
close( fd[0] );
signal( SIGPIPE, SIG_DFL );
if (!wait)
{
if (!(pid = fork())) execvp( argv[0], argv ); /* in grandchild */
if (pid > 0) _exit(0); /* exit child if fork succeeded */
}
else execvp( argv[0], argv );
err = errno_to_status( errno );
write( fd[1], &err, sizeof(err) );
_exit(1);
}
close( fd[1] );
if (pid != -1)
{
while (pid != (wret = waitpid( pid, &status, 0 )))
if (wret == -1 && errno != EINTR) break;
if (read( fd[0], &err, sizeof(err) ) <= 0) /* if we read something, exec or second fork failed */
{
if (pid == wret && WIFEXITED(status)) err = WEXITSTATUS(status);
else err = 255; /* abnormal exit with an abort or an interrupt */
}
}
else err = errno_to_status( errno );
close( fd[0] );
return err;
}
/***********************************************************************
* fork_and_exec
*

View File

@ -2854,7 +2854,7 @@ static LRESULT start_screensaver(void)
if (!is_virtual_desktop())
{
const char *argv[3] = { "xdg-screensaver", "activate", NULL };
int pid = _spawnvp( _P_DETACH, argv[0], argv );
int pid = __wine_unix_spawnvp( (char **)argv, FALSE );
if (pid > 0)
{
TRACE( "started process %d\n", pid );

View File

@ -284,6 +284,25 @@ NTSTATUS WINAPI wow64___wine_unix_call( UINT *args )
}
/**********************************************************************
* wow64___wine_unix_spawnvp
*/
NTSTATUS WINAPI wow64___wine_unix_spawnvp( UINT *args )
{
ULONG *argv32 = get_ptr( &args );
int wait = get_ulong( &args );
unsigned int i, count = 0;
char **argv;
while (argv32[count]) count++;
argv = Wow64AllocateTemp( (count + 1) * sizeof(*argv) );
for (i = 0; i < count; i++) argv[i] = ULongToPtr( argv32[i] );
argv[count] = NULL;
return __wine_unix_spawnvp( argv, wait );
}
/**********************************************************************
* wow64_wine_server_call
*/

View File

@ -245,6 +245,7 @@
SYSCALL_ENTRY( NtYieldExecution ) \
SYSCALL_ENTRY( __wine_dbg_write ) \
SYSCALL_ENTRY( __wine_unix_call ) \
SYSCALL_ENTRY( __wine_unix_spawnvp ) \
SYSCALL_ENTRY( wine_nt_to_unix_file_name ) \
SYSCALL_ENTRY( wine_server_call ) \
SYSCALL_ENTRY( wine_server_fd_to_handle ) \

View File

@ -4603,6 +4603,7 @@ static inline PLIST_ENTRY RemoveTailList(PLIST_ENTRY le)
/* Wine internal functions */
extern NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out );
extern NTSTATUS WINAPI __wine_unix_spawnvp( char * const argv[], int wait );
/* The thread information for 16-bit threads */
/* NtCurrentTeb()->SubSystemTib points to this */