]> git.ipfire.org Git - thirdparty/gettext.git/commitdiff
Spawn support for Woe32.
authorBruno Haible <bruno@clisp.org>
Thu, 3 Apr 2003 15:32:07 +0000 (15:32 +0000)
committerBruno Haible <bruno@clisp.org>
Tue, 23 Jun 2009 10:10:20 +0000 (12:10 +0200)
gettext-tools/lib/w32spawn.h [new file with mode: 0644]

diff --git a/gettext-tools/lib/w32spawn.h b/gettext-tools/lib/w32spawn.h
new file mode 100644 (file)
index 0000000..e5c5c8e
--- /dev/null
@@ -0,0 +1,169 @@
+/* Auxiliary functions for the creation of subprocesses.  Native Woe32 API.
+   Copyright (C) 2003 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 2, 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, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* Get declarations of the Win32 API functions.  */
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+
+/* Get _get_osfhandle() and _open_osfhandle().  */
+#include <io.h>
+
+#include <stdbool.h>
+#include <errno.h>
+
+#include "strpbrk.h"
+#include "xmalloc.h"
+
+/* Duplicates a file handle, making the copy uninheritable.  */
+static int
+dup_noinherit (int fd)
+{
+  HANDLE curr_process = GetCurrentProcess ();
+  HANDLE old_handle = _get_osfhandle (fd);
+  HANDLE new_handle;
+  int nfd;
+
+  if (!DuplicateHandle (curr_process,              /* SourceProcessHandle */
+                       old_handle,                 /* SourceHandle */
+                       curr_process,               /* TargetProcessHandle */
+                       (PHANDLE) &new_handle,      /* TargetHandle */
+                       (DWORD) 0,                  /* DesiredAccess */
+                       FALSE,                      /* InheritHandle */
+                       DUPLICATE_SAME_ACCESS))     /* Options */
+    error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"),
+          GetLastError ());
+
+  nfd = _open_osfhandle (new_handle, O_BINARY);
+  if (nfd < 0)
+    error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
+
+  return nfd;
+}
+
+/* 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 Win32 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):
+       \" -> "
+       \\\" -> \"
+       \\\\\" -> \\"
+ */
+#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"
+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 = (char **) xmalloc ((argc + 1) * sizeof (char *));
+
+  /* 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] = string;
+    }
+  new_argv[argc] = NULL;
+
+  return new_argv;
+}