]> Savannah Git Hosting - gnulib.git/commitdiff
windows-spawn: New module.
authorBruno Haible <bruno@clisp.org>
Sat, 28 Nov 2020 09:46:23 +0000 (10:46 +0100)
committerBruno Haible <bruno@clisp.org>
Sat, 28 Nov 2020 09:46:23 +0000 (10:46 +0100)
* lib/windows-spawn.h: Renamed from lib/w32spawn.h. Remove
implementations.
* lib/windows-spawn.c: Renamed from lib/w32spawn.h.
* modules/windows-spawn: New file.
* lib/execute.c: Include "windows-spawn.h" instead of "w32spawn.h".
* lib/spawn-pipe.c: Likewise.
* modules/execute (Files): Remove lib/w32spawn.h.
(Depends-on): Add windows-spawn. Remove cloexec, msvc-nothrow, strpbrk,
xalloc.
(Makefile.am): Remove w32spawn.h from lib_SOURCES.
* modules/spawn-pipe (Files): Remove lib/w32spawn.h.
(Depends-on): Add windows-spawn. Remove cloexec, msvc-nothrow, strpbrk,
xalloc.
(Makefile.am): Remove w32spawn.h from lib_SOURCES.

ChangeLog
lib/execute.c
lib/spawn-pipe.c
lib/w32spawn.h [deleted file]
lib/windows-spawn.c [new file with mode: 0644]
lib/windows-spawn.h [new file with mode: 0644]
modules/execute
modules/spawn-pipe
modules/windows-spawn [new file with mode: 0644]

index bf29984838fe612ebcfee308782509398f0d61d0..22a26e7e94f1d8512fe1745714002e4c001f9f1d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2020-11-28  Bruno Haible  <bruno@clisp.org>
+
+       windows-spawn: New module.
+       * lib/windows-spawn.h: Renamed from lib/w32spawn.h. Remove
+       implementations.
+       * lib/windows-spawn.c: Renamed from lib/w32spawn.h.
+       * modules/windows-spawn: New file.
+       * lib/execute.c: Include "windows-spawn.h" instead of "w32spawn.h".
+       * lib/spawn-pipe.c: Likewise.
+       * modules/execute (Files): Remove lib/w32spawn.h.
+       (Depends-on): Add windows-spawn. Remove cloexec, msvc-nothrow, strpbrk,
+       xalloc.
+       (Makefile.am): Remove w32spawn.h from lib_SOURCES.
+       * modules/spawn-pipe (Files): Remove lib/w32spawn.h.
+       (Depends-on): Add windows-spawn. Remove cloexec, msvc-nothrow, strpbrk,
+       xalloc.
+       (Makefile.am): Remove w32spawn.h from lib_SOURCES.
+
 2020-11-27  Bruno Haible  <bruno@clisp.org>
 
        ssfmalloc tests: Port to macOS 11.
index 15d9ba98d2ee57a50ba7d2b50998e8122ec6fcb4..41e1e9222cdc7fd37aa1708d5433269b66159524 100644 (file)
@@ -39,7 +39,7 @@
 
 /* Native Windows API.  */
 # include <process.h>
-# include "w32spawn.h"
+# include "windows-spawn.h"
 
 #else
 
index 947825ac8ebf0a6b71bb8e955c0e5eebf87a7170..1a7a1e1662b6ed319fe92d07b3419edac8306f90 100644 (file)
@@ -44,7 +44,7 @@
 
 /* Native Windows API.  */
 # include <process.h>
-# include "w32spawn.h"
+# include "windows-spawn.h"
 
 #else
 
diff --git a/lib/w32spawn.h b/lib/w32spawn.h
deleted file mode 100644 (file)
index a4b3b1e..0000000
+++ /dev/null
@@ -1,233 +0,0 @@
-/* Auxiliary functions for the creation of subprocesses.  Native Windows API.
-   Copyright (C) 2001, 2003-2020 Free Software Foundation, Inc.
-   Written by Bruno Haible <bruno@clisp.org>, 2003.
-
-   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/>.  */
-
-#ifndef __KLIBC__
-/* Get declarations of the native Windows API functions.  */
-# define WIN32_LEAN_AND_MEAN
-# include <windows.h>
-#endif
-
-/* Get _open_osfhandle().  */
-#include <io.h>
-
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-#include <errno.h>
-
-/* Get _get_osfhandle().  */
-# if GNULIB_MSVC_NOTHROW
-#  include "msvc-nothrow.h"
-# else
-#  include <io.h>
-# endif
-
-#include "cloexec.h"
-#include "xalloc.h"
-
-/* Duplicates a file handle, making the copy uninheritable.
-   Returns -1 for a file handle that is equivalent to closed.  */
-static int
-dup_noinherit (int fd)
-{
-  fd = dup_cloexec (fd);
-  if (fd < 0 && errno == EMFILE)
-    error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
-
-  return fd;
-}
-
-/* Returns a file descriptor equivalent to FD, except that the resulting file
-   descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
-   FD must be open and non-inheritable.  The result will be non-inheritable as
-   well.
-   If FD < 0, FD itself is returned.  */
-static int
-fd_safer_noinherit (int fd)
-{
-  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
-    {
-      /* The recursion depth is at most 3.  */
-      int nfd = fd_safer_noinherit (dup_noinherit (fd));
-      int saved_errno = errno;
-      close (fd);
-      errno = saved_errno;
-      return nfd;
-    }
-  return fd;
-}
-
-/* Duplicates a file handle, making the copy uninheritable and ensuring the
-   result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
-   Returns -1 for a file handle that is equivalent to closed.  */
-static int
-dup_safer_noinherit (int fd)
-{
-  return fd_safer_noinherit (dup_noinherit (fd));
-}
-
-/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD);  */
-static void
-undup_safer_noinherit (int tempfd, int origfd)
-{
-  if (tempfd >= 0)
-    {
-      if (dup2 (tempfd, origfd) < 0)
-        error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"),
-               origfd);
-      close (tempfd);
-    }
-  else
-    {
-      /* origfd was closed or open to no handle at all.  Set it to a closed
-         state.  This is (nearly) equivalent to the original state.  */
-      close (origfd);
-    }
-}
-
-/* Prepares an argument vector before calling spawn().
-   Note that spawn() does not by itself call the command interpreter
-     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
-      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
-         GetVersionEx(&v);
-         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
-      }) ? "cmd.exe" : "command.com").
-   Instead it simply concatenates the arguments, separated by ' ', and calls
-   CreateProcess().  We must quote the arguments since Windows CreateProcess()
-   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
-   special way:
-   - Space and tab are interpreted as delimiters. They are not treated as
-     delimiters if they are surrounded by double quotes: "...".
-   - Unescaped double quotes are removed from the input. Their only effect is
-     that within double quotes, space and tab are treated like normal
-     characters.
-   - Backslashes not followed by double quotes are not special.
-   - But 2*n+1 backslashes followed by a double quote become
-     n backslashes followed by a double quote (n >= 0):
-       \" -> "
-       \\\" -> \"
-       \\\\\" -> \\"
-   - '*', '?' characters may get expanded through wildcard expansion in the
-     callee: By default, in the callee, the initialization code before main()
-     takes the result of GetCommandLine(), wildcard-expands it, and passes it
-     to main(). The exceptions to this rule are:
-       - programs that inspect GetCommandLine() and ignore argv,
-       - mingw programs that have a global variable 'int _CRT_glob = 0;',
-       - Cygwin programs, when invoked from a Cygwin program.
- */
-#ifndef __KLIBC__
-# define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*?"
-# define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
-#else
-# define SHELL_SPECIAL_CHARS ""
-# define SHELL_SPACE_CHARS ""
-#endif
-static char **
-prepare_spawn (char **argv)
-{
-  size_t argc;
-  char **new_argv;
-  size_t i;
-
-  /* Count number of arguments.  */
-  for (argc = 0; argv[argc] != NULL; argc++)
-    ;
-
-  /* Allocate new argument vector.  */
-  new_argv = XNMALLOC (1 + argc + 1, char *);
-
-  /* Add an element upfront that can be used when argv[0] turns out to be a
-     script, not a program.
-     On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
-     "sh.exe".  We have to omit the directory part and rely on the search in
-     PATH, because the mingw "mount points" are not visible inside Windows
-     CreateProcess().  */
-  *new_argv++ = "sh.exe";
-
-  /* Put quoted arguments into the new argument vector.  */
-  for (i = 0; i < argc; i++)
-    {
-      const char *string = argv[i];
-
-      if (string[0] == '\0')
-        new_argv[i] = xstrdup ("\"\"");
-      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
-        {
-          bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
-          size_t length;
-          unsigned int backslashes;
-          const char *s;
-          char *quoted_string;
-          char *p;
-
-          length = 0;
-          backslashes = 0;
-          if (quote_around)
-            length++;
-          for (s = string; *s != '\0'; s++)
-            {
-              char c = *s;
-              if (c == '"')
-                length += backslashes + 1;
-              length++;
-              if (c == '\\')
-                backslashes++;
-              else
-                backslashes = 0;
-            }
-          if (quote_around)
-            length += backslashes + 1;
-
-          quoted_string = (char *) xmalloc (length + 1);
-
-          p = quoted_string;
-          backslashes = 0;
-          if (quote_around)
-            *p++ = '"';
-          for (s = string; *s != '\0'; s++)
-            {
-              char c = *s;
-              if (c == '"')
-                {
-                  unsigned int j;
-                  for (j = backslashes + 1; j > 0; j--)
-                    *p++ = '\\';
-                }
-              *p++ = c;
-              if (c == '\\')
-                backslashes++;
-              else
-                backslashes = 0;
-            }
-          if (quote_around)
-            {
-              unsigned int j;
-              for (j = backslashes; j > 0; j--)
-                *p++ = '\\';
-              *p++ = '"';
-            }
-          *p = '\0';
-
-          new_argv[i] = quoted_string;
-        }
-      else
-        new_argv[i] = (char *) string;
-    }
-  new_argv[argc] = NULL;
-
-  return new_argv;
-}
diff --git a/lib/windows-spawn.c b/lib/windows-spawn.c
new file mode 100644 (file)
index 0000000..eedb7e4
--- /dev/null
@@ -0,0 +1,210 @@
+/* Auxiliary functions for the creation of subprocesses.  Native Windows API.
+   Copyright (C) 2001, 2003-2020 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+   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 "windows-spawn.h"
+
+#ifndef __KLIBC__
+/* Get declarations of the native Windows API functions.  */
+# define WIN32_LEAN_AND_MEAN
+# include <windows.h>
+#endif
+
+/* Get _open_osfhandle().  */
+#include <io.h>
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Get _get_osfhandle().  */
+#if GNULIB_MSVC_NOTHROW
+# include "msvc-nothrow.h"
+#else
+# include <io.h>
+#endif
+
+#include "cloexec.h"
+#include "error.h"
+#include "xalloc.h"
+#include "gettext.h"
+
+#define _(str) gettext (str)
+
+
+/* Duplicates a file handle, making the copy uninheritable.
+   Returns -1 for a file handle that is equivalent to closed.  */
+static int
+dup_noinherit (int fd)
+{
+  fd = dup_cloexec (fd);
+  if (fd < 0 && errno == EMFILE)
+    error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
+
+  return fd;
+}
+
+/* Returns a file descriptor equivalent to FD, except that the resulting file
+   descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
+   FD must be open and non-inheritable.  The result will be non-inheritable as
+   well.
+   If FD < 0, FD itself is returned.  */
+static int
+fd_safer_noinherit (int fd)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+    {
+      /* The recursion depth is at most 3.  */
+      int nfd = fd_safer_noinherit (dup_noinherit (fd));
+      int saved_errno = errno;
+      close (fd);
+      errno = saved_errno;
+      return nfd;
+    }
+  return fd;
+}
+
+int
+dup_safer_noinherit (int fd)
+{
+  return fd_safer_noinherit (dup_noinherit (fd));
+}
+
+void
+undup_safer_noinherit (int tempfd, int origfd)
+{
+  if (tempfd >= 0)
+    {
+      if (dup2 (tempfd, origfd) < 0)
+        error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"),
+               origfd);
+      close (tempfd);
+    }
+  else
+    {
+      /* origfd was closed or open to no handle at all.  Set it to a closed
+         state.  This is (nearly) equivalent to the original state.  */
+      close (origfd);
+    }
+}
+
+#ifndef __KLIBC__
+# define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037*?"
+# define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037"
+#else
+# define SHELL_SPECIAL_CHARS ""
+# define SHELL_SPACE_CHARS ""
+#endif
+char **
+prepare_spawn (char **argv)
+{
+  size_t argc;
+  char **new_argv;
+  size_t i;
+
+  /* Count number of arguments.  */
+  for (argc = 0; argv[argc] != NULL; argc++)
+    ;
+
+  /* Allocate new argument vector.  */
+  new_argv = XNMALLOC (1 + argc + 1, char *);
+
+  /* Add an element upfront that can be used when argv[0] turns out to be a
+     script, not a program.
+     On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
+     "sh.exe".  We have to omit the directory part and rely on the search in
+     PATH, because the mingw "mount points" are not visible inside Windows
+     CreateProcess().  */
+  *new_argv++ = "sh.exe";
+
+  /* Put quoted arguments into the new argument vector.  */
+  for (i = 0; i < argc; i++)
+    {
+      const char *string = argv[i];
+
+      if (string[0] == '\0')
+        new_argv[i] = xstrdup ("\"\"");
+      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
+        {
+          bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
+          size_t length;
+          unsigned int backslashes;
+          const char *s;
+          char *quoted_string;
+          char *p;
+
+          length = 0;
+          backslashes = 0;
+          if (quote_around)
+            length++;
+          for (s = string; *s != '\0'; s++)
+            {
+              char c = *s;
+              if (c == '"')
+                length += backslashes + 1;
+              length++;
+              if (c == '\\')
+                backslashes++;
+              else
+                backslashes = 0;
+            }
+          if (quote_around)
+            length += backslashes + 1;
+
+          quoted_string = (char *) xmalloc (length + 1);
+
+          p = quoted_string;
+          backslashes = 0;
+          if (quote_around)
+            *p++ = '"';
+          for (s = string; *s != '\0'; s++)
+            {
+              char c = *s;
+              if (c == '"')
+                {
+                  unsigned int j;
+                  for (j = backslashes + 1; j > 0; j--)
+                    *p++ = '\\';
+                }
+              *p++ = c;
+              if (c == '\\')
+                backslashes++;
+              else
+                backslashes = 0;
+            }
+          if (quote_around)
+            {
+              unsigned int j;
+              for (j = backslashes; j > 0; j--)
+                *p++ = '\\';
+              *p++ = '"';
+            }
+          *p = '\0';
+
+          new_argv[i] = quoted_string;
+        }
+      else
+        new_argv[i] = (char *) string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}
diff --git a/lib/windows-spawn.h b/lib/windows-spawn.h
new file mode 100644 (file)
index 0000000..200f321
--- /dev/null
@@ -0,0 +1,61 @@
+/* Auxiliary functions for the creation of subprocesses.  Native Windows API.
+   Copyright (C) 2001, 2003-2020 Free Software Foundation, Inc.
+   Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+   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/>.  */
+
+#ifndef _WINDOWS_SPAWN_H
+#define _WINDOWS_SPAWN_H
+
+/* Duplicates a file handle, making the copy uninheritable and ensuring the
+   result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
+   Returns -1 for a file handle that is equivalent to closed.  */
+extern int dup_safer_noinherit (int fd);
+
+/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD);  */
+extern void undup_safer_noinherit (int tempfd, int origfd);
+
+/* Prepares an argument vector before calling spawn().
+   Note that spawn() does not by itself call the command interpreter
+     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
+      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+         GetVersionEx(&v);
+         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
+      }) ? "cmd.exe" : "command.com").
+   Instead it simply concatenates the arguments, separated by ' ', and calls
+   CreateProcess().  We must quote the arguments since Windows CreateProcess()
+   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
+   special way:
+   - Space and tab are interpreted as delimiters. They are not treated as
+     delimiters if they are surrounded by double quotes: "...".
+   - Unescaped double quotes are removed from the input. Their only effect is
+     that within double quotes, space and tab are treated like normal
+     characters.
+   - Backslashes not followed by double quotes are not special.
+   - But 2*n+1 backslashes followed by a double quote become
+     n backslashes followed by a double quote (n >= 0):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+   - '*', '?' characters may get expanded through wildcard expansion in the
+     callee: By default, in the callee, the initialization code before main()
+     takes the result of GetCommandLine(), wildcard-expands it, and passes it
+     to main(). The exceptions to this rule are:
+       - programs that inspect GetCommandLine() and ignore argv,
+       - mingw programs that have a global variable 'int _CRT_glob = 0;',
+       - Cygwin programs, when invoked from a Cygwin program.
+ */
+extern char ** prepare_spawn (char **argv);
+
+#endif /* _WINDOWS_SPAWN_H */
index a438fbfd7bc12513f65525787aee023827e4ed51..4a7f8459617a63b4dfeaa447f1c5d1b0b766411c 100644 (file)
@@ -4,17 +4,14 @@ Creation of autonomous subprocesses.
 Files:
 lib/execute.h
 lib/execute.c
-lib/w32spawn.h
 m4/execute.m4
 
 Depends-on:
-cloexec
 dup2
 error
 fatal-signal
 wait-process
 gettext-h
-msvc-nothrow
 spawn
 posix_spawnp
 posix_spawn_file_actions_init
@@ -26,16 +23,15 @@ posix_spawnattr_setflags
 posix_spawnattr_destroy
 stdbool
 stdlib
-strpbrk
 unistd
 environ
-xalloc
+windows-spawn
 
 configure.ac:
 gl_EXECUTE
 
 Makefile.am:
-lib_SOURCES += execute.h execute.c w32spawn.h
+lib_SOURCES += execute.h execute.c
 
 Include:
 "execute.h"
index dd07fef303ee562e128bf81312f6598b47b43254..2c62586e272ae3f43ece27306beecccaba72df6c 100644 (file)
@@ -4,17 +4,14 @@ Creation of subprocesses, communicating via pipes.
 Files:
 lib/spawn-pipe.h
 lib/spawn-pipe.c
-lib/w32spawn.h
 m4/spawn-pipe.m4
 
 Depends-on:
-cloexec
 dup2
 environ
 error
 fatal-signal
 gettext-h
-msvc-nothrow
 open
 pipe2
 pipe2-safer
@@ -31,17 +28,16 @@ posix_spawnattr_setflags
 posix_spawnattr_destroy
 stdbool
 stdlib
-strpbrk
 unistd
 unistd-safer
 wait-process
-xalloc
+windows-spawn
 
 configure.ac:
 gl_SPAWN_PIPE
 
 Makefile.am:
-lib_SOURCES += spawn-pipe.h spawn-pipe.c w32spawn.h
+lib_SOURCES += spawn-pipe.h spawn-pipe.c
 
 Include:
 "spawn-pipe.h"
diff --git a/modules/windows-spawn b/modules/windows-spawn
new file mode 100644 (file)
index 0000000..747f8bb
--- /dev/null
@@ -0,0 +1,37 @@
+Description:
+Auxiliary functions for the creation of subprocesses on native Windows.
+
+Files:
+lib/windows-spawn.h
+lib/windows-spawn.c
+
+Depends-on:
+cloexec
+dup2
+error
+gettext-h
+msvc-nothrow
+stdbool
+stdlib
+strpbrk
+unistd
+xalloc
+
+configure.ac:
+AC_REQUIRE([AC_CANONICAL_HOST])
+case "$host_os" in
+  mingw*)
+    AC_LIBOBJ([windows-spawn])
+    ;;
+esac
+
+Makefile.am:
+
+Include:
+"windows-spawn.h"
+
+License:
+GPL
+
+Maintainer:
+all