Alexandre Julliard : ntdll: Add a __wine_unix_spawnvp syscall.
Alexandre Julliard
julliard at winehq.org
Mon Sep 27 15:21:44 CDT 2021
Module: wine
Branch: master
Commit: c1b3d6eb108a85e4bc8262b86de5dff9600eeca5
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c1b3d6eb108a85e4bc8262b86de5dff9600eeca5
Author: Alexandre Julliard <julliard at winehq.org>
Date: Mon Sep 27 12:30:25 2021 +0200
ntdll: Add a __wine_unix_spawnvp syscall.
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/ntdll/ntdll.spec | 1 +
dlls/ntdll/unix/loader.c | 1 +
dlls/ntdll/unix/process.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++
dlls/winex11.drv/window.c | 2 +-
dlls/wow64/syscall.c | 19 +++++++++++++++++
dlls/wow64/syscall.h | 1 +
include/winternl.h | 1 +
7 files changed, 77 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec
index 9837b09fd51..c822db14572 100644
--- a/dlls/ntdll/ntdll.spec
+++ b/dlls/ntdll/ntdll.spec
@@ -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)
diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c
index 5e39209eddc..dfc0d4c9a09 100644
--- a/dlls/ntdll/unix/loader.c
+++ b/dlls/ntdll/unix/loader.c
@@ -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,
diff --git a/dlls/ntdll/unix/process.c b/dlls/ntdll/unix/process.c
index f5b8b5315cd..1a53741de57 100644
--- a/dlls/ntdll/unix/process.c
+++ b/dlls/ntdll/unix/process.c
@@ -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
*
diff --git a/dlls/winex11.drv/window.c b/dlls/winex11.drv/window.c
index 4e856a41865..0057a341525 100644
--- a/dlls/winex11.drv/window.c
+++ b/dlls/winex11.drv/window.c
@@ -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 );
diff --git a/dlls/wow64/syscall.c b/dlls/wow64/syscall.c
index cc2ab1c48b3..952b862a37d 100644
--- a/dlls/wow64/syscall.c
+++ b/dlls/wow64/syscall.c
@@ -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
*/
diff --git a/dlls/wow64/syscall.h b/dlls/wow64/syscall.h
index be0ca780b9b..bc403dd6d31 100644
--- a/dlls/wow64/syscall.h
+++ b/dlls/wow64/syscall.h
@@ -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 ) \
diff --git a/include/winternl.h b/include/winternl.h
index 9e96591ad8e..f119ce6f4f6 100644
--- a/include/winternl.h
+++ b/include/winternl.h
@@ -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 */
More information about the wine-cvs
mailing list