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