Eric Blake wrote:
> > Actually, this particular problem can be easily solved on Threos,
> > because the posix_spawn() API offers a function for this:
> > int posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t*
> > __restrict file_actions, const char* __restrict path);
> >
> > Note the "np" at the end, it means "non portable". I also found
> > references on Oracle's webpage [1].
>
> It's useful enough that we may want to add support for this in gnulib,
> whether or not other systems pick up on it. (gnulib is already able to
> overcome a lot of shortcomings in various platforms' posix_spawn)
I agree. It is useful
1) for findutils, as explained [1],
2) for Java implementations [2],
Implemented as follows. The prototype is as in [3], except that I dropped
the suffix '_np', because
- Functions with suffix '_np' are in the system's namespace, that is,
there is no requirement that different systems implement them with the
same semantics or same prototype.
- Gnulib has fewer backward compatibility requirements, in case we need
to change the prototype in order to conform to some future POSIX standard.
Note: In the source code, you can switch to use posix_spawn instead of fork(),
but that does not provide portability to native Windows, because gnulib does
not implement posix_spawn for native Windows so far. But the new API will not
cause problems, since the native Windows CreateProcess() function supports
providing a directory [4].
Note: There was already some proposed experimental support in glibc [5].
Bruno
[1] https://lists.gnu.org/archive/html/bug-findutils/2018-09/msg00002.html
[2] https://docs.oracle.com/cd/E53394_01/html/E54847/golbg.html
[3]
https://docs.oracle.com/cd/E86824_01/html/E54766/posix-spawn-file-actions-addchdir-np-3c.html
[4]
https://docs.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessw
[5] https://sourceware.org/ml/libc-alpha/2010-08/msg00109.html
>From 86b1dc8935e627c14f5d5f3141fbcc2ca7e900a3 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 7 Sep 2018 23:35:52 +0200
Subject: [PATCH 1/3] posix_spawn_file_actions_addchdir: New module.
Suggested by Eric Blake in
<https://lists.gnu.org/archive/html/bug-findutils/2018-09/msg00007.html>.
* lib/spawn.in.h (posix_spawn_file_actions_addchdir): New declaration.
* lib/spawn_int.h (struct __spawn_action): Add tag 'spawn_do_chdir' and
union member 'chdir_action'.
* lib/spawn_faction_addchdir.c: New file.
* lib/spawni.c (__spawni): Implement the spawn_do_chdir action.
* lib/spawn_faction_addclose.c: Test REPLACE_POSIX_SPAWN instead of
HAVE_WORKING_POSIX_SPAWN.
* lib/spawn_faction_adddup2.c: Likewise.
* lib/spawn_faction_addopen.c: Likewise.
* m4/posix_spawn_faction_addchdir.m4: New file.
* m4/posix_spawn.m4 (gl_POSIX_SPAWN_BODY): Test whether module
'posix_spawn_file_actions_addchdir' is present and whether
posix_spawn_file_actions_addchdir_np exists. Define REPLACE_POSIX_SPAWN
instead of HAVE_WORKING_POSIX_SPAWN.
* m4/spawn_h.m4 (gl_SPAWN_H): Test whether
posix_spawn_file_actions_addchdir is declared.
(gl_SPAWN_H_DEFAULTS): Initialize
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR.
* modules/spawn (Makefile.am): Substitute
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR.
* modules/posix_spawn_file_actions_addchdir: New file.
* modules/posix_spawn_file_actions_addclose (Depends-on,
configure.ac): Test also REPLACE_POSIX_SPAWN.
* modules/posix_spawn_file_actions_adddup2 (Depends-on,
configure.ac): Likewise.
* modules/posix_spawn_file_actions_addopen (Depends-on,
configure.ac): Likewise.
* tests/test-spawn-c++.cc (posix_spawn_file_actions_addchdir): Check
signature.
* doc/posix-functions/posix_spawn.texi: Mention the new module.
* doc/posix-functions/posix_spawnp.texi: Likewise.
---
ChangeLog | 41 ++++++++++++++++++
doc/posix-functions/posix_spawn.texi | 4 ++
doc/posix-functions/posix_spawnp.texi | 4 ++
lib/spawn.in.h | 35 +++++++++++++++
lib/spawn_faction_addchdir.c | 57 ++++++++++++++++++++++++
lib/spawn_faction_addclose.c | 4 +-
lib/spawn_faction_adddup2.c | 4 +-
lib/spawn_faction_addopen.c | 4 +-
lib/spawn_int.h | 7 ++-
lib/spawni.c | 6 +++
m4/posix_spawn.m4 | 72 ++++++++++++++++++-------------
m4/posix_spawn_faction_addchdir.m4 | 20 +++++++++
m4/spawn_h.m4 | 9 +++-
modules/posix_spawn_file_actions_addchdir | 30 +++++++++++++
modules/posix_spawn_file_actions_addclose | 6 +--
modules/posix_spawn_file_actions_adddup2 | 6 +--
modules/posix_spawn_file_actions_addopen | 6 +--
modules/spawn | 3 ++
tests/test-spawn-c++.cc | 5 +++
19 files changed, 275 insertions(+), 48 deletions(-)
create mode 100644 lib/spawn_faction_addchdir.c
create mode 100644 m4/posix_spawn_faction_addchdir.m4
create mode 100644 modules/posix_spawn_file_actions_addchdir
diff --git a/ChangeLog b/ChangeLog
index 12372c7..bb90832 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2018-09-07 Bruno Haible <[email protected]>
+
+ posix_spawn_file_actions_addchdir: New module.
+ Suggested by Eric Blake in
+ <https://lists.gnu.org/archive/html/bug-findutils/2018-09/msg00007.html>.
+ * lib/spawn.in.h (posix_spawn_file_actions_addchdir): New declaration.
+ * lib/spawn_int.h (struct __spawn_action): Add tag 'spawn_do_chdir' and
+ union member 'chdir_action'.
+ * lib/spawn_faction_addchdir.c: New file.
+ * lib/spawni.c (__spawni): Implement the spawn_do_chdir action.
+ * lib/spawn_faction_addclose.c: Test REPLACE_POSIX_SPAWN instead of
+ HAVE_WORKING_POSIX_SPAWN.
+ * lib/spawn_faction_adddup2.c: Likewise.
+ * lib/spawn_faction_addopen.c: Likewise.
+ * m4/posix_spawn_faction_addchdir.m4: New file.
+ * m4/posix_spawn.m4 (gl_POSIX_SPAWN_BODY): Test whether module
+ 'posix_spawn_file_actions_addchdir' is present and whether
+ posix_spawn_file_actions_addchdir_np exists. Define REPLACE_POSIX_SPAWN
+ instead of HAVE_WORKING_POSIX_SPAWN.
+ * m4/spawn_h.m4 (gl_SPAWN_H): Test whether
+ posix_spawn_file_actions_addchdir is declared.
+ (gl_SPAWN_H_DEFAULTS): Initialize
+ GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
+ HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
+ REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR.
+ * modules/spawn (Makefile.am): Substitute
+ GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
+ HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR,
+ REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR.
+ * modules/posix_spawn_file_actions_addchdir: New file.
+ * modules/posix_spawn_file_actions_addclose (Depends-on,
+ configure.ac): Test also REPLACE_POSIX_SPAWN.
+ * modules/posix_spawn_file_actions_adddup2 (Depends-on,
+ configure.ac): Likewise.
+ * modules/posix_spawn_file_actions_addopen (Depends-on,
+ configure.ac): Likewise.
+ * tests/test-spawn-c++.cc (posix_spawn_file_actions_addchdir): Check
+ signature.
+ * doc/posix-functions/posix_spawn.texi: Mention the new module.
+ * doc/posix-functions/posix_spawnp.texi: Likewise.
+
2018-09-06 Bruno Haible <[email protected]>
stddef: Override max_align_t on NetBSD 8.0/x86.
diff --git a/doc/posix-functions/posix_spawn.texi b/doc/posix-functions/posix_spawn.texi
index 30e491b..bed0e79 100644
--- a/doc/posix-functions/posix_spawn.texi
+++ b/doc/posix-functions/posix_spawn.texi
@@ -23,3 +23,7 @@ Portability problems not fixed by Gnulib:
This function does not work on some platforms:
AIX 6.1 (under particular circumstances), mingw.
@end itemize
+
+The Gnulib module @code{posix_spawn_file_actions_addchdir} provides an
+additional action, that consists in changing the current directory of
+the child process before starting the specified program.
diff --git a/doc/posix-functions/posix_spawnp.texi b/doc/posix-functions/posix_spawnp.texi
index 01446fc..6cfec28 100644
--- a/doc/posix-functions/posix_spawnp.texi
+++ b/doc/posix-functions/posix_spawnp.texi
@@ -23,3 +23,7 @@ Portability problems not fixed by Gnulib:
This function does not work on some platforms:
AIX 6.1 (under particular circumstances), mingw.
@end itemize
+
+The Gnulib module @code{posix_spawn_file_actions_addchdir} provides an
+additional action, that consists in changing the current directory of
+the child process before starting the specified program.
diff --git a/lib/spawn.in.h b/lib/spawn.in.h
index a606176..7460c65 100644
--- a/lib/spawn.in.h
+++ b/lib/spawn.in.h
@@ -878,6 +878,41 @@ _GL_WARN_ON_USE (posix_spawn_file_actions_adddup2,
# endif
#endif
+#if @GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@
+/* Add an action to FILE-ACTIONS which tells the implementation to call
+ 'chdir' to the given directory during the 'spawn' call. */
+# if @REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@
+# if !(defined __cplusplus && defined GNULIB_NAMESPACE)
+# define posix_spawn_file_actions_addchdir rpl_posix_spawn_file_actions_addchdir
+# endif
+_GL_FUNCDECL_RPL (posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *_Restrict_ __file_actions,
+ const char *_Restrict_ __path)
+ __THROW _GL_ARG_NONNULL ((1, 2)));
+_GL_CXXALIAS_RPL (posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *_Restrict_ __file_actions,
+ const char *_Restrict_ __path));
+# else
+# if !@HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR@
+_GL_FUNCDECL_SYS (posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *_Restrict_ __file_actions,
+ const char *_Restrict_ __path)
+ __THROW _GL_ARG_NONNULL ((1, 2)));
+# endif
+_GL_CXXALIAS_SYS (posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *_Restrict_ __file_actions,
+ const char *_Restrict_ __path));
+# endif
+_GL_CXXALIASWARN (posix_spawn_file_actions_addchdir);
+#elif defined GNULIB_POSIXCHECK
+# undef posix_spawn_file_actions_addchdir
+# if HAVE_RAW_DECL_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
+_GL_WARN_ON_USE (posix_spawn_file_actions_addchdir,
+ "posix_spawn_file_actions_addchdir is unportable - "
+ "use gnulib module posix_spawn_file_actions_addchdir for portability");
+# endif
+#endif
+
#endif /* _@GUARD_PREFIX@_SPAWN_H */
#endif /* _@GUARD_PREFIX@_SPAWN_H */
diff --git a/lib/spawn_faction_addchdir.c b/lib/spawn_faction_addchdir.c
new file mode 100644
index 0000000..027cd8d
--- /dev/null
+++ b/lib/spawn_faction_addchdir.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+/* Specification. */
+#include <spawn.h>
+
+#include <errno.h>
+
+#if REPLACE_POSIX_SPAWN
+# include "spawn_int.h"
+#endif
+
+/* Add an action to FILE-ACTIONS which tells the implementation to call
+ 'chdir' to the given directory during the 'spawn' call. */
+int
+posix_spawn_file_actions_addchdir (posix_spawn_file_actions_t *file_actions,
+ const char *path)
+#undef posix_spawn_file_actions_addchdir
+{
+#if !REPLACE_POSIX_SPAWN
+ return posix_spawn_file_actions_addchdir_np (file_actions, path);
+#else
+ /* Allocate more memory if needed. */
+ if (file_actions->_used == file_actions->_allocated
+ && __posix_spawn_file_actions_realloc (file_actions) != 0)
+ /* This can only mean we ran out of memory. */
+ return ENOMEM;
+
+ {
+ struct __spawn_action *rec;
+
+ /* Add the new value. */
+ rec = &file_actions->_actions[file_actions->_used];
+ rec->tag = spawn_do_chdir;
+ rec->action.chdir_action.path = path;
+
+ /* Account for the new entry. */
+ ++file_actions->_used;
+
+ return 0;
+ }
+#endif
+}
diff --git a/lib/spawn_faction_addclose.c b/lib/spawn_faction_addclose.c
index 93827dc..bac6cff 100644
--- a/lib/spawn_faction_addclose.c
+++ b/lib/spawn_faction_addclose.c
@@ -26,7 +26,7 @@
# define __sysconf(open_max) getdtablesize ()
#endif
-#if !HAVE_WORKING_POSIX_SPAWN
+#if REPLACE_POSIX_SPAWN
# include "spawn_int.h"
#endif
@@ -43,7 +43,7 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
if (fd < 0 || fd >= maxfd)
return EBADF;
-#if HAVE_WORKING_POSIX_SPAWN
+#if !REPLACE_POSIX_SPAWN
return posix_spawn_file_actions_addclose (file_actions, fd);
#else
/* Allocate more memory if needed. */
diff --git a/lib/spawn_faction_adddup2.c b/lib/spawn_faction_adddup2.c
index 86ae0af..fc25fb8 100644
--- a/lib/spawn_faction_adddup2.c
+++ b/lib/spawn_faction_adddup2.c
@@ -26,7 +26,7 @@
# define __sysconf(open_max) getdtablesize ()
#endif
-#if !HAVE_WORKING_POSIX_SPAWN
+#if REPLACE_POSIX_SPAWN
# include "spawn_int.h"
#endif
@@ -43,7 +43,7 @@ posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
if (fd < 0 || newfd < 0 || fd >= maxfd || newfd >= maxfd)
return EBADF;
-#if HAVE_WORKING_POSIX_SPAWN
+#if !REPLACE_POSIX_SPAWN
return posix_spawn_file_actions_adddup2 (file_actions, fd, newfd);
#else
/* Allocate more memory if needed. */
diff --git a/lib/spawn_faction_addopen.c b/lib/spawn_faction_addopen.c
index 5b62142..8fa1141 100644
--- a/lib/spawn_faction_addopen.c
+++ b/lib/spawn_faction_addopen.c
@@ -26,7 +26,7 @@
# define __sysconf(open_max) getdtablesize ()
#endif
-#if !HAVE_WORKING_POSIX_SPAWN
+#if REPLACE_POSIX_SPAWN
# include "spawn_int.h"
#endif
@@ -44,7 +44,7 @@ posix_spawn_file_actions_addopen (posix_spawn_file_actions_t *file_actions,
if (fd < 0 || fd >= maxfd)
return EBADF;
-#if HAVE_WORKING_POSIX_SPAWN
+#if !REPLACE_POSIX_SPAWN
return posix_spawn_file_actions_addopen (file_actions, fd, path, oflag, mode);
#else
/* Allocate more memory if needed. */
diff --git a/lib/spawn_int.h b/lib/spawn_int.h
index 909122e..f4b4be6 100644
--- a/lib/spawn_int.h
+++ b/lib/spawn_int.h
@@ -23,7 +23,8 @@ struct __spawn_action
{
spawn_do_close,
spawn_do_dup2,
- spawn_do_open
+ spawn_do_open,
+ spawn_do_chdir
} tag;
union
@@ -44,6 +45,10 @@ struct __spawn_action
int oflag;
mode_t mode;
} open_action;
+ struct
+ {
+ const char *path;
+ } chdir_action;
} action;
};
diff --git a/lib/spawni.c b/lib/spawni.c
index 40f89d2..bd49cc8 100644
--- a/lib/spawni.c
+++ b/lib/spawni.c
@@ -284,6 +284,12 @@ __spawni (pid_t *pid, const char *file,
/* The 'dup2' call failed. */
_exit (SPAWN_ERROR);
break;
+
+ case spawn_do_chdir:
+ if (chdir (action->action.chdir_action.path) < 0)
+ /* The 'chdir' call failed. */
+ _exit (SPAWN_ERROR);
+ break;
}
}
}
diff --git a/m4/posix_spawn.m4 b/m4/posix_spawn.m4
index 685f0f4..f656cfc 100644
--- a/m4/posix_spawn.m4
+++ b/m4/posix_spawn.m4
@@ -1,4 +1,4 @@
-# posix_spawn.m4 serial 14
+# posix_spawn.m4 serial 15
dnl Copyright (C) 2008-2018 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -33,45 +33,57 @@ AC_DEFUN([gl_POSIX_SPAWN_BODY],
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setsigmask])
dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_destroy])
if test $ac_cv_func_posix_spawn = yes; then
- gl_POSIX_SPAWN_WORKS
- case "$gl_cv_func_posix_spawn_works" in
- *yes)
- AC_DEFINE([HAVE_WORKING_POSIX_SPAWN], [1],
- [Define if you have the posix_spawn and posix_spawnp functions and
- they work.])
- dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER
- dnl evaluates to nonzero.
- dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy])
- dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy])
- AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported],
- [gl_cv_func_spawnattr_setschedpolicy],
- [AC_EGREP_CPP([POSIX scheduling supported], [
+ m4_ifdef([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR],
+ [dnl Module 'posix_spawn_file_actions_addchdir' is present.
+ AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_addchdir_np])
+ if test $ac_cv_func_posix_spawn_file_actions_addchdir_np = no; then
+ dnl In order to implement the posix_spawn_file_actions_addchdir
+ dnl function, we need to replace the entire posix_spawn facility.
+ REPLACE_POSIX_SPAWN=1
+ fi
+ ])
+ if test $REPLACE_POSIX_SPAWN = 0; then
+ gl_POSIX_SPAWN_WORKS
+ case "$gl_cv_func_posix_spawn_works" in
+ *yes)
+ dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDULER
+ dnl evaluates to nonzero.
+ dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedpolicy])
+ dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedpolicy])
+ AC_CACHE_CHECK([whether posix_spawnattr_setschedpolicy is supported],
+ [gl_cv_func_spawnattr_setschedpolicy],
+ [AC_EGREP_CPP([POSIX scheduling supported], [
#include <spawn.h>
#if POSIX_SPAWN_SETSCHEDULER
POSIX scheduling supported
#endif
],
- [gl_cv_func_spawnattr_setschedpolicy=yes],
- [gl_cv_func_spawnattr_setschedpolicy=no])
- ])
- dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM
- dnl evaluates to nonzero.
- dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam])
- dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam])
- AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported],
- [gl_cv_func_spawnattr_setschedparam],
- [AC_EGREP_CPP([POSIX scheduling supported], [
+ [gl_cv_func_spawnattr_setschedpolicy=yes],
+ [gl_cv_func_spawnattr_setschedpolicy=no])
+ ])
+ dnl Assume that these functions are available if POSIX_SPAWN_SETSCHEDPARAM
+ dnl evaluates to nonzero.
+ dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_getschedparam])
+ dnl AC_CHECK_FUNCS_ONCE([posix_spawnattr_setschedparam])
+ AC_CACHE_CHECK([whether posix_spawnattr_setschedparam is supported],
+ [gl_cv_func_spawnattr_setschedparam],
+ [AC_EGREP_CPP([POSIX scheduling supported], [
#include <spawn.h>
#if POSIX_SPAWN_SETSCHEDPARAM
POSIX scheduling supported
#endif
],
- [gl_cv_func_spawnattr_setschedparam=yes],
- [gl_cv_func_spawnattr_setschedparam=no])
- ])
- ;;
- *) REPLACE_POSIX_SPAWN=1 ;;
- esac
+ [gl_cv_func_spawnattr_setschedparam=yes],
+ [gl_cv_func_spawnattr_setschedparam=no])
+ ])
+ ;;
+ *) REPLACE_POSIX_SPAWN=1 ;;
+ esac
+ fi
+ fi
+ if test $ac_cv_func_posix_spawn != yes || test $REPLACE_POSIX_SPAWN = 1; then
+ AC_DEFINE([REPLACE_POSIX_SPAWN], [1],
+ [Define if gnulib uses its own posix_spawn and posix_spawnp functions.])
fi
])
diff --git a/m4/posix_spawn_faction_addchdir.m4 b/m4/posix_spawn_faction_addchdir.m4
new file mode 100644
index 0000000..ae3e03f
--- /dev/null
+++ b/m4/posix_spawn_faction_addchdir.m4
@@ -0,0 +1,20 @@
+# posix_spawn_faction_addchdir.m4 serial 1
+dnl Copyright (C) 2018 Free Software Foundation, Inc.
+dnl This file is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+AC_DEFUN([gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR],
+[
+ AC_REQUIRE([gl_SPAWN_H_DEFAULTS])
+ AC_REQUIRE([AC_PROG_CC])
+ gl_POSIX_SPAWN
+ AC_CHECK_FUNCS_ONCE([posix_spawn_file_actions_addchdir posix_spawn_file_actions_addchdir_np])
+ if test $ac_cv_func_posix_spawn_file_actions_addchdir = yes; then
+ dnl This function is not yet standardized. Therefore override the
+ dnl system's implementation always.
+ REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=1
+ else
+ HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=0
+ fi
+])
diff --git a/m4/spawn_h.m4 b/m4/spawn_h.m4
index 6cbdc4c9..4862eef 100644
--- a/m4/spawn_h.m4
+++ b/m4/spawn_h.m4
@@ -1,4 +1,4 @@
-# spawn_h.m4 serial 16
+# spawn_h.m4 serial 17
dnl Copyright (C) 2008-2018 Free Software Foundation, Inc.
dnl This file is free software; the Free Software Foundation
dnl gives unlimited permission to copy and/or distribute it,
@@ -53,7 +53,7 @@ AC_DEFUN([gl_SPAWN_H],
posix_spawnattr_getschedparam posix_spawnattr_setschedparam
posix_spawn_file_actions_init posix_spawn_file_actions_destroy
posix_spawn_file_actions_addopen posix_spawn_file_actions_addclose
- posix_spawn_file_actions_adddup2])
+ posix_spawn_file_actions_adddup2 posix_spawn_file_actions_addchdir])
])
dnl Checks whether the system has the functions posix_spawn.
@@ -92,6 +92,7 @@ AC_DEFUN([gl_SPAWN_H_DEFAULTS],
GNULIB_POSIX_SPAWN=0; AC_SUBST([GNULIB_POSIX_SPAWN])
GNULIB_POSIX_SPAWNP=0; AC_SUBST([GNULIB_POSIX_SPAWNP])
GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT=0; AC_SUBST([GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT])
+ GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=0; AC_SUBST([GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR])
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE=0; AC_SUBST([GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE])
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2=0; AC_SUBST([GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2])
GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN=0; AC_SUBST([GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN])
@@ -115,7 +116,11 @@ AC_DEFUN([gl_SPAWN_H_DEFAULTS],
HAVE_POSIX_SPAWNATTR_T=1; AC_SUBST([HAVE_POSIX_SPAWNATTR_T])
HAVE_POSIX_SPAWN_FILE_ACTIONS_T=1;
AC_SUBST([HAVE_POSIX_SPAWN_FILE_ACTIONS_T])
+ HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=1;
+ AC_SUBST([HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR])
REPLACE_POSIX_SPAWN=0; AC_SUBST([REPLACE_POSIX_SPAWN])
+ REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR=0;
+ AC_SUBST([REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR])
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE=0;
AC_SUBST([REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE])
REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2=0;
diff --git a/modules/posix_spawn_file_actions_addchdir b/modules/posix_spawn_file_actions_addchdir
new file mode 100644
index 0000000..ad09334
--- /dev/null
+++ b/modules/posix_spawn_file_actions_addchdir
@@ -0,0 +1,30 @@
+Description:
+posix_spawn_file_actions_addchdir() function: augment a child process actions
+specification.
+
+Files:
+lib/spawn_faction_addchdir.c
+lib/spawn_int.h
+m4/posix_spawn_faction_addchdir.m4
+
+Depends-on:
+spawn
+posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = 1]
+
+configure.ac:
+gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
+if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR = 1; then
+ AC_LIBOBJ([spawn_faction_addchdir])
+fi
+gl_SPAWN_MODULE_INDICATOR([posix_spawn_file_actions_addchdir])
+
+Makefile.am:
+
+Include:
+<spawn.h>
+
+License:
+LGPLv2+
+
+Maintainer:
+all
diff --git a/modules/posix_spawn_file_actions_addclose b/modules/posix_spawn_file_actions_addclose
index 7a7a342..27d6d8e 100644
--- a/modules/posix_spawn_file_actions_addclose
+++ b/modules/posix_spawn_file_actions_addclose
@@ -9,12 +9,12 @@ m4/posix_spawn.m4
Depends-on:
spawn
-getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1]
-posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1]
+getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1]
+posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1]
configure.ac:
gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE
-if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1; then
+if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE = 1; then
AC_LIBOBJ([spawn_faction_addclose])
fi
gl_SPAWN_MODULE_INDICATOR([posix_spawn_file_actions_addclose])
diff --git a/modules/posix_spawn_file_actions_adddup2 b/modules/posix_spawn_file_actions_adddup2
index df60b47..361ccb8 100644
--- a/modules/posix_spawn_file_actions_adddup2
+++ b/modules/posix_spawn_file_actions_adddup2
@@ -9,12 +9,12 @@ m4/posix_spawn.m4
Depends-on:
spawn
-getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1]
-posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1]
+getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1]
+posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1]
configure.ac:
gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2
-if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1; then
+if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2 = 1; then
AC_LIBOBJ([spawn_faction_adddup2])
fi
gl_SPAWN_MODULE_INDICATOR([posix_spawn_file_actions_adddup2])
diff --git a/modules/posix_spawn_file_actions_addopen b/modules/posix_spawn_file_actions_addopen
index 50fd21a..b4ee0da 100644
--- a/modules/posix_spawn_file_actions_addopen
+++ b/modules/posix_spawn_file_actions_addopen
@@ -9,12 +9,12 @@ m4/posix_spawn.m4
Depends-on:
spawn
-getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1]
-posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1]
+getdtablesize [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1]
+posix_spawn_file_actions_init [test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1]
configure.ac:
gl_FUNC_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN
-if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1; then
+if test $HAVE_POSIX_SPAWN = 0 || test $REPLACE_POSIX_SPAWN = 1 || test $REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN = 1; then
AC_LIBOBJ([spawn_faction_addopen])
fi
gl_SPAWN_MODULE_INDICATOR([posix_spawn_file_actions_addopen])
diff --git a/modules/spawn b/modules/spawn
index 7a2af28..dc861d3 100644
--- a/modules/spawn
+++ b/modules/spawn
@@ -32,6 +32,7 @@ spawn.h: spawn.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's/@''GNULIB_POSIX_SPAWN''@/$(GNULIB_POSIX_SPAWN)/g' \
-e 's/@''GNULIB_POSIX_SPAWNP''@/$(GNULIB_POSIX_SPAWNP)/g' \
-e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_INIT)/g' \
+ -e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR)/g' \
-e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)/g' \
-e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)/g' \
-e 's/@''GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@/$(GNULIB_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)/g' \
@@ -53,7 +54,9 @@ spawn.h: spawn.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_NONNULL_H)
-e 's|@''HAVE_POSIX_SPAWN''@|$(HAVE_POSIX_SPAWN)|g' \
-e 's|@''HAVE_POSIX_SPAWNATTR_T''@|$(HAVE_POSIX_SPAWNATTR_T)|g' \
-e 's|@''HAVE_POSIX_SPAWN_FILE_ACTIONS_T''@|$(HAVE_POSIX_SPAWN_FILE_ACTIONS_T)|g' \
+ -e 's|@''HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR''@|$(HAVE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR)|g' \
-e 's|@''REPLACE_POSIX_SPAWN''@|$(REPLACE_POSIX_SPAWN)|g' \
+ -e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR)|g' \
-e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDCLOSE)|g' \
-e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDDUP2)|g' \
-e 's|@''REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN''@|$(REPLACE_POSIX_SPAWN_FILE_ACTIONS_ADDOPEN)|g' \
diff --git a/tests/test-spawn-c++.cc b/tests/test-spawn-c++.cc
index a822a18..04b7aa3 100644
--- a/tests/test-spawn-c++.cc
+++ b/tests/test-spawn-c++.cc
@@ -132,6 +132,11 @@ SIGNATURE_CHECK (GNULIB_NAMESPACE::posix_spawn_file_actions_adddup2, int,
(posix_spawn_file_actions_t *, int, int));
#endif
+#if GNULIB_TEST_POSIX_SPAWN_FILE_ACTIONS_ADDCHDIR
+SIGNATURE_CHECK (GNULIB_NAMESPACE::posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *, const char *));
+#endif
+
int
main ()
--
2.7.4
>From 340de5fed84643e5473777114896864e63231663 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Fri, 7 Sep 2018 23:38:53 +0200
Subject: [PATCH 2/3] posix_spawn_file_actions_addchdir: Add tests.
* tests/test-posix_spawn_file_actions_addchdir.c: New file.
* tests/test-posix_spawn4.c: New file.
* modules/posix_spawn_file_actions_addchdir-tests: New file.
---
ChangeLog | 7 ++
modules/posix_spawn_file_actions_addchdir-tests | 20 ++++
tests/test-posix_spawn4.c | 143 ++++++++++++++++++++++++
tests/test-posix_spawn_file_actions_addchdir.c | 42 +++++++
4 files changed, 212 insertions(+)
create mode 100644 modules/posix_spawn_file_actions_addchdir-tests
create mode 100644 tests/test-posix_spawn4.c
create mode 100644 tests/test-posix_spawn_file_actions_addchdir.c
diff --git a/ChangeLog b/ChangeLog
index bb90832..1ea5560 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
2018-09-07 Bruno Haible <[email protected]>
+ posix_spawn_file_actions_addchdir: Add tests.
+ * tests/test-posix_spawn_file_actions_addchdir.c: New file.
+ * tests/test-posix_spawn4.c: New file.
+ * modules/posix_spawn_file_actions_addchdir-tests: New file.
+
+2018-09-07 Bruno Haible <[email protected]>
+
posix_spawn_file_actions_addchdir: New module.
Suggested by Eric Blake in
<https://lists.gnu.org/archive/html/bug-findutils/2018-09/msg00007.html>.
diff --git a/modules/posix_spawn_file_actions_addchdir-tests b/modules/posix_spawn_file_actions_addchdir-tests
new file mode 100644
index 0000000..9c31f21
--- /dev/null
+++ b/modules/posix_spawn_file_actions_addchdir-tests
@@ -0,0 +1,20 @@
+Files:
+tests/test-posix_spawn_file_actions_addchdir.c
+tests/test-posix_spawn4.c
+tests/signature.h
+tests/macros.h
+
+Depends-on:
+posix_spawn_file_actions_init
+posix_spawnp-tests
+
+configure.ac:
+
+Makefile.am:
+TESTS += test-posix_spawn_file_actions_addchdir
+check_PROGRAMS += test-posix_spawn_file_actions_addchdir
+
+if POSIX_SPAWN_PORTED
+TESTS += test-posix_spawn4
+check_PROGRAMS += test-posix_spawn4
+endif
diff --git a/tests/test-posix_spawn4.c b/tests/test-posix_spawn4.c
new file mode 100644
index 0000000..79308b9
--- /dev/null
+++ b/tests/test-posix_spawn4.c
@@ -0,0 +1,143 @@
+/* Test of posix_spawn() function with 'chdir' action.
+ Copyright (C) 2008-2018 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+/* Written by Bruno Haible <[email protected]>, 2018. */
+
+#include <config.h>
+
+#include <spawn.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+extern char **environ;
+
+static int
+fd_safer (int fd)
+{
+ if (0 <= fd && fd <= 2)
+ {
+ int f = fd_safer (dup (fd));
+ int e = errno;
+ close (fd);
+ errno = e;
+ fd = f;
+ }
+
+ return fd;
+}
+
+int
+main ()
+{
+ char *argv[2] = { (char *) "pwd", NULL };
+ int ifd[2];
+ sigset_t blocked_signals;
+ sigset_t fatal_signal_set;
+ posix_spawn_file_actions_t actions;
+ bool actions_allocated;
+ posix_spawnattr_t attrs;
+ bool attrs_allocated;
+ int err;
+ pid_t child;
+ int fd;
+ FILE *fp;
+ char line[80];
+ int status;
+ int exitstatus;
+
+ if (pipe (ifd) < 0 || (ifd[0] = fd_safer (ifd[0])) < 0)
+ {
+ perror ("cannot create pipe");
+ exit (1);
+ }
+ sigprocmask (SIG_SETMASK, NULL, &blocked_signals);
+ sigemptyset (&fatal_signal_set);
+ sigaddset (&fatal_signal_set, SIGINT);
+ sigaddset (&fatal_signal_set, SIGTERM);
+ sigaddset (&fatal_signal_set, SIGHUP);
+ sigaddset (&fatal_signal_set, SIGPIPE);
+ sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
+ actions_allocated = false;
+ attrs_allocated = false;
+ if ((err = posix_spawn_file_actions_init (&actions)) != 0
+ || (actions_allocated = true,
+ (err = posix_spawn_file_actions_adddup2 (&actions, ifd[1], STDOUT_FILENO)) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[1])) != 0
+ || (err = posix_spawn_file_actions_addclose (&actions, ifd[0])) != 0
+ || (err = posix_spawn_file_actions_addopen (&actions, STDIN_FILENO, "/dev/null", O_RDONLY, 0)) != 0
+ || (err = posix_spawn_file_actions_addchdir (&actions, "/")) != 0
+ || (err = posix_spawnattr_init (&attrs)) != 0
+ || (attrs_allocated = true,
+ (err = posix_spawnattr_setsigmask (&attrs, &blocked_signals)) != 0
+ || (err = posix_spawnattr_setflags (&attrs, POSIX_SPAWN_SETSIGMASK)) != 0)
+ || (err = posix_spawnp (&child, "pwd", &actions, &attrs, argv, environ)) != 0))
+ {
+ if (actions_allocated)
+ posix_spawn_file_actions_destroy (&actions);
+ if (attrs_allocated)
+ posix_spawnattr_destroy (&attrs);
+ sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
+ errno = err;
+ perror ("subprocess failed");
+ exit (1);
+ }
+ posix_spawn_file_actions_destroy (&actions);
+ posix_spawnattr_destroy (&attrs);
+ sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
+ close (ifd[1]);
+ fd = ifd[0];
+ fp = fdopen (fd, "r");
+ if (fp == NULL)
+ {
+ fprintf (stderr, "fdopen() failed\n");
+ exit (1);
+ }
+ if (fread (line, 1, 80, fp) < 2)
+ {
+ fprintf (stderr, "could not read expected output\n");
+ exit (1);
+ }
+ if (memcmp (line, "/\n", 2) != 0)
+ {
+ fprintf (stderr, "read output is not the expected output");
+ exit (1);
+ }
+ fclose (fp);
+ status = 0;
+ while (waitpid (child, &status, 0) != child)
+ ;
+ if (!WIFEXITED (status))
+ {
+ fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status);
+ exit (1);
+ }
+ exitstatus = WEXITSTATUS (status);
+ if (exitstatus != 0)
+ {
+ fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus);
+ exit (1);
+ }
+ return 0;
+}
diff --git a/tests/test-posix_spawn_file_actions_addchdir.c b/tests/test-posix_spawn_file_actions_addchdir.c
new file mode 100644
index 0000000..2cd0f97
--- /dev/null
+++ b/tests/test-posix_spawn_file_actions_addchdir.c
@@ -0,0 +1,42 @@
+/* Test posix_spawn_file_actions_addchdir() function.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>. */
+
+#include <config.h>
+
+#include <spawn.h>
+
+#include "signature.h"
+SIGNATURE_CHECK (posix_spawn_file_actions_addchdir, int,
+ (posix_spawn_file_actions_t *, const char *));
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <unistd.h>
+
+#include "macros.h"
+
+int
+main (void)
+{
+ posix_spawn_file_actions_t actions;
+
+ ASSERT (posix_spawn_file_actions_init (&actions) == 0);
+
+ ASSERT (posix_spawn_file_actions_addchdir (&actions, "/") == 0);
+
+ return 0;
+}
--
2.7.4