LIBCx, which is a kLIBC extension library, provides spawn2() to support this feature. If LIBCx is available, then support a directory argument using spawn2() of LIBCx.
* lib/spawn-pipe.c (create_pipe) [kLIBC]: Use spawn2() of LIBCx to support a directory argument if available. * m4/spawn-pipe.m4 (gl_SPAWN_PIPE): Check the availability of libcx/spawn2.h. * modules/spawn-pipe (Depends-on): Add wait, waitid and waitpid if libcx/spawn2.h exists. --- lib/spawn-pipe.c | 45 ++++++++++++++++++++++++++++++++++++++++----- m4/spawn-pipe.m4 | 8 ++++++++ modules/spawn-pipe | 3 +++ 3 files changed, 51 insertions(+), 5 deletions(-) diff --git a/lib/spawn-pipe.c b/lib/spawn-pipe.c index 0f03926e9f..a4e4bc2581 100644 --- a/lib/spawn-pipe.c +++ b/lib/spawn-pipe.c @@ -72,6 +72,10 @@ /* OS/2 kLIBC API. */ # include <process.h> +# include <dlfcn.h> +# if HAVE_LIBCX_SPAWN2_H +# include <libcx/spawn2.h> +# endif # include "os2-spawn.h" #else @@ -356,11 +360,34 @@ create_pipe (const char *progname, } # else /* __KLIBC__ */ +# if HAVE_LIBCX_SPAWN2_H + static int (*libcx_spawn2) (int mode, + const char *name, const char * const argv[], + const char *cwd, const char * const envp[], + const int stdfds[]) = NULL; + static int libcx_spawn2_loaded = -1; +# endif + if (!(directory == NULL || strcmp (directory, ".") == 0)) { - /* A directory argument is not supported in this implementation. */ - saved_errno = EINVAL; - goto fail_with_saved_errno; +# if HAVE_LIBCX_SPAWN2_H + if (libcx_spawn2_loaded == -1) + { + void *libcx_handle; + + libcx_handle = dlopen ("libcx0", RTLD_LAZY); + if (libcx_handle != NULL) + libcx_spawn2 = dlsym (libcx_handle, "_spawn2"); + libcx_spawn2_loaded = libcx_handle != NULL && libcx_spawn2 != NULL; + } + + if (!libcx_spawn2_loaded) +# endif + { + /* A directory argument is not supported in this implementation. */ + saved_errno = EINVAL; + goto fail_with_saved_errno; + } } int orig_stdin; @@ -402,8 +429,16 @@ create_pipe (const char *progname, but it inherits all open()ed or dup2()ed file handles (which is what we want in the case of STD*_FILENO). */ { - child = _spawnvpe (P_NOWAIT, prog_path, argv + 1, - (const char **) environ); +# if HAVE_LIBCX_SPAWN2_H + if (directory == NULL || strcmp (directory, ".") == 0) +# endif + child = _spawnvpe (P_NOWAIT, prog_path, argv + 1, + (const char **) environ); +# if HAVE_LIBCX_SPAWN2_H + else + child = libcx_spawn2 (P_NOWAIT | P_2_THREADSAFE, prog_path, argv + 1, + directory, (const char **) environ, NULL); +# endif # if 0 /* Executing arbitrary files as shell scripts is unsecure. */ if (child == -1 && errno == ENOEXEC) { diff --git a/m4/spawn-pipe.m4 b/m4/spawn-pipe.m4 index 6539bdbb95..cb7e5dc8eb 100644 --- a/m4/spawn-pipe.m4 +++ b/m4/spawn-pipe.m4 @@ -9,4 +9,12 @@ AC_DEFUN([gl_SPAWN_PIPE], [ dnl Prerequisites of lib/spawn-pipe.c. AC_REQUIRE([AC_TYPE_MODE_T]) + + AC_CHECK_HEADERS_ONCE([libcx/spawn2.h]) + if test $ac_cv_header_libcx_spawn2_h = yes; then + HAVE_LIBCX_SPAWN2_H=1 + else + HAVE_LIBCX_SPAWN2_H=0 + fi + AC_SUBST(HAVE_LIBCX_SPAWN2_H) ]) diff --git a/modules/spawn-pipe b/modules/spawn-pipe index b2b343c093..d94dee1ad6 100644 --- a/modules/spawn-pipe +++ b/modules/spawn-pipe @@ -43,6 +43,9 @@ unistd-safer wait-process windows-spawn xalloc-die +wait [test $HAVE_LIBCX_SPAWN2_H = 1] +waitid [test $HAVE_LIBCX_SPAWN2_H = 1] +waitpid [test $HAVE_LIBCX_SPAWN2_H = 1] configure.ac: gl_SPAWN_PIPE -- 2.42.0