[newlib-cygwin] Cygwin: testsuite: test posix_spawn of a non-Cygwin executable.

Jeremy Drake via Cygwin-cvs <[email protected]>
Newsgroups gmane.os.cygwin.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=9deb0bc3b53956154d788988808bb0150385d0ba

commit 9deb0bc3b53956154d788988808bb0150385d0ba
Author: Jeremy Drake <[email protected]>
Date:   Wed Jun 25 22:51:05 2025 -0700

    Cygwin: testsuite: test posix_spawn of a non-Cygwin executable.
    
    Test CWD and redirection of standard handles.
    
    Signed-off-by: Jeremy Drake <[email protected]>

Diff:
---
 winsup/testsuite/Makefile.am                    |   1 +
 winsup/testsuite/winsup.api/posix_spawn/win32.c | 170 ++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/winsup/testsuite/Makefile.am b/winsup/testsuite/Makefile.am
index 03f65d818..20e06b9c5 100644
--- a/winsup/testsuite/Makefile.am
+++ b/winsup/testsuite/Makefile.am
@@ -316,6 +316,7 @@ check_PROGRAMS = \
 	winsup.api/posix_spawn/fds \
 	winsup.api/posix_spawn/signals \
 	winsup.api/posix_spawn/spawnp \
+	winsup.api/posix_spawn/win32 \
 	winsup.api/samples/sample-fail \
 	winsup.api/samples/sample-pass
 # winsup.api/ltp/ulimit01 is omitted as we don't have <ulimit.h>
diff --git a/winsup/testsuite/winsup.api/posix_spawn/win32.c b/winsup/testsuite/winsup.api/posix_spawn/win32.c
new file mode 100644
index 000000000..cd2bedcd9
--- /dev/null
+++ b/winsup/testsuite/winsup.api/posix_spawn/win32.c
@@ -0,0 +1,170 @@
+#include "test.h"
+#include <dlfcn.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <spawn.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/cygwin.h>
+#include <unistd.h>
+
+char * find_winchild (void)
+{
+  static const char winchild[] = "/winchild";
+  char *mingwtestdir = getenv ("mingwtestdir");
+  if (!mingwtestdir)
+    {
+      Dl_info dli;
+      if (dladdr (&find_winchild, &dli))
+        {
+	  ssize_t i = strlen (dli.dli_fname) - 1;
+	  for (int slashes = 0; i >= 0 && slashes < 3; --i)
+	    if (dli.dli_fname[i] == '/')
+	      slashes++;
+	  stpcpy (stpcpy (dli.dli_fname + i + 1, "/mingw"), winchild);
+	  return realpath (dli.dli_fname, NULL);
+	}
+      else
+        {
+	  return realpath ("../../mingw/winchild", NULL);
+	}
+    }
+  else
+    {
+      char *ret, *tmp = malloc (strlen (mingwtestdir) + sizeof (winchild));
+      stpcpy (stpcpy (tmp, mingwtestdir), winchild);
+      ret = realpath (tmp, NULL);
+      free (tmp);
+      return ret;
+    }
+}
+
+static char tmppath[] = "pspawn.XXXXXX";
+static char tmpcwd[] = "tmpcwd.XXXXXX";
+static char tmppath2[sizeof (tmpcwd) + 9] = {0};
+
+static void cleanup_tmpfiles (void)
+{
+  if (tmppath2[0])
+    unlink (tmppath2);
+  rmdir (tmpcwd);
+  unlink (tmppath);
+}
+
+int main (void)
+{
+  posix_spawn_file_actions_t fa;
+  pid_t pid;
+  int status;
+  int fd, fdcloexec, cwdfd;
+  char *childargv[] = {"winchild", NULL, NULL, NULL};
+  char *winchild = find_winchild ();
+
+  /* unbuffer stdout */
+  setvbuf(stdout, NULL, _IONBF, 0);
+
+  /* temp regular file */
+  negError (fd = mkstemp (tmppath));
+  atexit (cleanup_tmpfiles);
+  negError (close (fd));
+
+  /* temp directory */
+  nullError (mkdtemp (tmpcwd));
+
+  /* temp file within temp directory */
+  stpcpy (stpcpy (stpcpy (tmppath2, tmpcwd), "/"), "tmpfile2");
+  negError (fd = open (tmppath2, O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR));
+  negError (close (fd));
+
+  /* open file descriptors to test inheritance */
+  negError (fd = open ("/dev/null", O_RDONLY, 0644));
+  negError (fdcloexec = open ("/dev/full", O_RDONLY|O_CLOEXEC, 0644));
+
+  /* test posix_spawn_file_actions_addopen */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 0, "/dev/zero", O_RDONLY,
+					     0644));
+  childargv[1] = "0";
+  childargv[2] = "\\Device\\Null";
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, fd, 0));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 with CLOEXEC fd */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, fdcloexec, 0));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_adddup2 with out to err */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, "/dev/zero", O_WRONLY,
+					     0644));
+  errCode (posix_spawn_file_actions_adddup2 (&fa, 1, 2));
+  childargv[1] = "2";
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_addopen with real file */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, tmppath, O_WRONLY, 0644));
+  childargv[1] = "1";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmppath);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  /* test posix_spawn_file_actions_addchdir */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addchdir (&fa, tmpcwd));
+  childargv[1] = "CWD";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmpcwd);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+
+  /* test posix_spawn_file_actions_addfchdir */
+  negError (cwdfd = open (tmpcwd, O_SEARCH|O_DIRECTORY|O_CLOEXEC, 0755));
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd));
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  /* test posix_spawn_file_actions_addfchdir followed by addopen */
+  errCode (posix_spawn_file_actions_init (&fa));
+  errCode (posix_spawn_file_actions_addfchdir (&fa, cwdfd));
+  errCode (posix_spawn_file_actions_addopen (&fa, 1, "tmpfile2", O_WRONLY, 0644));
+  childargv[1] = "1";
+  childargv[2] = cygwin_create_path (CCP_POSIX_TO_WIN_A|CCP_ABSOLUTE, tmppath2);
+  errCode (posix_spawn (&pid, winchild, &fa, NULL, childargv, environ));
+  negError (waitpid (pid, &status, 0));
+  exitStatus (status, 0);
+  errCode (posix_spawn_file_actions_destroy (&fa));
+  free (childargv[2]);
+
+  negError (close (cwdfd));
+  negError (close (fd));
+  negError (close (fdcloexec));
+
+  return 0;
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.