From: Twaik Yont <9674930+twaik@users.noreply.github.com> Some platforms do not provide posix_spawn() and posix_spawnp(). Use vfork() with execv()/execvp() as a local fallback for the helper process startup paths that only need to distinguish a successful exec from a failed launch. Keep using posix_spawn() where available. Signed-off-by: Twaik Yont <9674930+twaik@users.noreply.github.com> --- configure | 6 +++++ configure.ac | 1 + dlls/msv1_0/unixlib.c | 51 ++++++++++++++++++++++++++++++++++++---- dlls/ntdll/unix/loader.c | 23 ++++++++++++++++-- include/config.h.in | 3 +++ 5 files changed, 77 insertions(+), 7 deletions(-) diff --git a/configure b/configure index fda5e60e415..118009ca227 100755 --- a/configure +++ b/configure @@ -21980,6 +21980,12 @@ if test "x$ac_cv_func_posix_fallocate" = xyes then : printf "%s\n" "#define HAVE_POSIX_FALLOCATE 1" >>confdefs.h +fi +ac_fn_c_check_func "$LINENO" "posix_spawn" "ac_cv_func_posix_spawn" +if test "x$ac_cv_func_posix_spawn" = xyes +then : + printf "%s\n" "#define HAVE_POSIX_SPAWN 1" >>confdefs.h + fi ac_fn_c_check_func "$LINENO" "prctl" "ac_cv_func_prctl" if test "x$ac_cv_func_prctl" = xyes diff --git a/configure.ac b/configure.ac index 485a1370b06..3cfb61a1adb 100644 --- a/configure.ac +++ b/configure.ac @@ -2119,6 +2119,7 @@ AC_CHECK_FUNCS(\ port_create \ posix_fadvise \ posix_fallocate \ + posix_spawn \ prctl \ process_vm_readv \ process_vm_writev \ diff --git a/dlls/msv1_0/unixlib.c b/dlls/msv1_0/unixlib.c index e9c2088da9e..880a4aeb8bd 100644 --- a/dlls/msv1_0/unixlib.c +++ b/dlls/msv1_0/unixlib.c @@ -28,7 +28,6 @@ #include <unistd.h> #include <fcntl.h> #include <errno.h> -#include <spawn.h> #include <sys/wait.h> #include "ntstatus.h" #include "windef.h" @@ -36,6 +35,10 @@ #include "winbase.h" #include "sspi.h" +#ifdef HAVE_POSIX_SPAWN +#include <spawn.h> +#endif + #include "wine/debug.h" #include "unixlib.h" @@ -161,9 +164,12 @@ static NTSTATUS ntlm_fork( void *args ) { const struct fork_params *params = args; struct ntlm_ctx *ctx = params->ctx; - posix_spawn_file_actions_t file_actions; - int pipe_in[2], pipe_out[2], err; + int pipe_in[2], pipe_out[2]; NTSTATUS status = STATUS_SUCCESS; +#ifdef HAVE_POSIX_SPAWN + int err; + posix_spawn_file_actions_t file_actions; +#endif #ifdef HAVE_PIPE2 if (pipe2( pipe_in, O_CLOEXEC ) < 0) @@ -187,6 +193,7 @@ static NTSTATUS ntlm_fork( void *args ) fcntl( pipe_out[1], F_SETFD, FD_CLOEXEC ); } +#ifdef HAVE_POSIX_SPAWN posix_spawn_file_actions_init( &file_actions ); posix_spawn_file_actions_adddup2( &file_actions, pipe_out[0], 0 ); @@ -207,13 +214,47 @@ static NTSTATUS ntlm_fork( void *args ) status = STATUS_UNSUCCESSFUL; } + posix_spawn_file_actions_destroy( &file_actions ); +#else + { + volatile int failed = 0; + pid_t child = vfork(); + + if (!child) + { + if (dup2( pipe_out[0], 0 ) == -1 || dup2( pipe_in[1], 1 ) == -1) + { + failed = 1; + _exit(127); + } + + close( pipe_out[0] ); + close( pipe_out[1] ); + close( pipe_in[0] ); + close( pipe_in[1] ); + + execvp( params->argv[0], params->argv ); + failed = 1; + _exit(127); + } + + if (child == -1 || failed) + { + ctx->pid = -1; + write( pipe_in[1], "BH\n", 3 ); + ERR_(winediag)( "Can't start ntlm_auth. " + "Usually you can find it in the winbind package of your distribution.\n" ); + status = STATUS_UNSUCCESSFUL; + } + else ctx->pid = child; + } +#endif + ctx->pipe_in = pipe_in[0]; close( pipe_in[1] ); ctx->pipe_out = pipe_out[1]; close( pipe_out[0] ); - posix_spawn_file_actions_destroy( &file_actions ); - return status; } diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index c1e6b588dcb..491cdfce586 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -30,7 +30,6 @@ #include <stdarg.h> #include <stdio.h> #include <signal.h> -#include <spawn.h> #include <string.h> #include <stdlib.h> #include <sys/types.h> @@ -39,6 +38,9 @@ #include <sys/wait.h> #include <unistd.h> #include <dlfcn.h> +#ifdef HAVE_POSIX_SPAWN +#include <spawn.h> +#endif #ifdef HAVE_PWD_H # include <pwd.h> #endif @@ -249,10 +251,27 @@ static char *build_relative_path( const char *base, const char *from, const char /* build a path to a binary and exec it */ static int build_path_and_exec( pid_t *pid, const char *dir, const char *name, char **argv ) { - int ret; + int ret = 0; argv[0] = build_path( dir, name ); +#ifdef HAVE_POSIX_SPAWN ret = posix_spawn( pid, argv[0], NULL, NULL, argv, environ ); +#else + { + volatile int failed = 0; + pid_t child = vfork(); + + if (!child) + { + execv( argv[0], argv ); + failed = 1; + _exit(127); + } + + ret = child == -1 || failed ? 127 : 0; + if (!ret) *pid = child; + } +#endif free( argv[0] ); return ret; } diff --git a/include/config.h.in b/include/config.h.in index 551771eaa6a..82d08d53b5f 100644 --- a/include/config.h.in +++ b/include/config.h.in @@ -336,6 +336,9 @@ /* Define to 1 if you have the 'posix_fallocate' function. */ #undef HAVE_POSIX_FALLOCATE +/* Define to 1 if you have the 'posix_spawn' function. */ +#undef HAVE_POSIX_SPAWN + /* Define to 1 if you have the 'prctl' function. */ #undef HAVE_PRCTL -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10926