• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/ap/gpl/timemachine/gettext-0.17/gettext-tools/gnulib-lib/
1/* Auxiliary functions for the creation of subprocesses.  Native Woe32 API.
2   Copyright (C) 2003, 2006, 2007 Free Software Foundation, Inc.
3   Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5   This program is free software: you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by
7   the Free Software Foundation; either version 3 of the License, or
8   (at your option) any later version.
9
10   This program is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13   GNU General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18/* Get declarations of the Win32 API functions.  */
19#define WIN32_LEAN_AND_MEAN
20#include <windows.h>
21
22/* Get _get_osfhandle() and _open_osfhandle().  */
23#include <io.h>
24
25#include <stdbool.h>
26#include <string.h>
27#include <errno.h>
28
29#include "xalloc.h"
30
31/* Duplicates a file handle, making the copy uninheritable.  */
32static int
33dup_noinherit (int fd)
34{
35  HANDLE curr_process = GetCurrentProcess ();
36  HANDLE old_handle = (HANDLE) _get_osfhandle (fd);
37  HANDLE new_handle;
38  int nfd;
39
40  if (!DuplicateHandle (curr_process,		    /* SourceProcessHandle */
41			old_handle,		    /* SourceHandle */
42			curr_process,		    /* TargetProcessHandle */
43			(PHANDLE) &new_handle,	    /* TargetHandle */
44			(DWORD) 0,		    /* DesiredAccess */
45			FALSE,			    /* InheritHandle */
46			DUPLICATE_SAME_ACCESS))	    /* Options */
47    error (EXIT_FAILURE, 0, _("DuplicateHandle failed with error code 0x%08x"),
48	   GetLastError ());
49
50  nfd = _open_osfhandle ((long) new_handle, O_BINARY);
51  if (nfd < 0)
52    error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
53
54  return nfd;
55}
56
57/* Prepares an argument vector before calling spawn().
58   Note that spawn() does not by itself call the command interpreter
59     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
60      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
61         GetVersionEx(&v);
62         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
63      }) ? "cmd.exe" : "command.com").
64   Instead it simply concatenates the arguments, separated by ' ', and calls
65   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
66   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
67   special way:
68   - Space and tab are interpreted as delimiters. They are not treated as
69     delimiters if they are surrounded by double quotes: "...".
70   - Unescaped double quotes are removed from the input. Their only effect is
71     that within double quotes, space and tab are treated like normal
72     characters.
73   - Backslashes not followed by double quotes are not special.
74   - But 2*n+1 backslashes followed by a double quote become
75     n backslashes followed by a double quote (n >= 0):
76       \" -> "
77       \\\" -> \"
78       \\\\\" -> \\"
79 */
80#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"
81#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"
82static char **
83prepare_spawn (char **argv)
84{
85  size_t argc;
86  char **new_argv;
87  size_t i;
88
89  /* Count number of arguments.  */
90  for (argc = 0; argv[argc] != NULL; argc++)
91    ;
92
93  /* Allocate new argument vector.  */
94  new_argv = XNMALLOC (argc + 1, char *);
95
96  /* Put quoted arguments into the new argument vector.  */
97  for (i = 0; i < argc; i++)
98    {
99      const char *string = argv[i];
100
101      if (string[0] == '\0')
102	new_argv[i] = xstrdup ("\"\"");
103      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
104	{
105	  bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
106	  size_t length;
107	  unsigned int backslashes;
108	  const char *s;
109	  char *quoted_string;
110	  char *p;
111
112	  length = 0;
113	  backslashes = 0;
114	  if (quote_around)
115	    length++;
116	  for (s = string; *s != '\0'; s++)
117	    {
118	      char c = *s;
119	      if (c == '"')
120		length += backslashes + 1;
121	      length++;
122	      if (c == '\\')
123		backslashes++;
124	      else
125		backslashes = 0;
126	    }
127	  if (quote_around)
128	    length += backslashes + 1;
129
130	  quoted_string = (char *) xmalloc (length + 1);
131
132	  p = quoted_string;
133	  backslashes = 0;
134	  if (quote_around)
135	    *p++ = '"';
136	  for (s = string; *s != '\0'; s++)
137	    {
138	      char c = *s;
139	      if (c == '"')
140		{
141		  unsigned int j;
142		  for (j = backslashes + 1; j > 0; j--)
143		    *p++ = '\\';
144		}
145	      *p++ = c;
146	      if (c == '\\')
147		backslashes++;
148	      else
149		backslashes = 0;
150	    }
151	  if (quote_around)
152	    {
153	      unsigned int j;
154	      for (j = backslashes; j > 0; j--)
155		*p++ = '\\';
156	      *p++ = '"';
157	    }
158	  *p = '\0';
159
160	  new_argv[i] = quoted_string;
161	}
162      else
163	new_argv[i] = (char *) string;
164    }
165  new_argv[argc] = NULL;
166
167  return new_argv;
168}
169