~ubuntu-branches/ubuntu/precise/wget/precise-proposed

« back to all changes in this revision

Viewing changes to lib/w32spawn.h

  • Committer: Bazaar Package Importer
  • Author(s): Steve Langasek
  • Date: 2011-10-19 00:00:09 UTC
  • mfrom: (2.1.13 sid)
  • Revision ID: james.westby@ubuntu.com-20111019000009-8p33w3wz4b1rdri0
Tags: 1.13-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - Add wget-udeb to ship wget.gnu as alternative to busybox wget
    implementation.
  - Depend on libssl-dev 0.9.8k-7ubuntu4 (LP: #503339)
* Dropped changes, superseded in Debian:
  - Keep build dependencies in main:
    + debian/control: remove info2man build-dep
    + debian/patches/series: disable wget-infopod_generated_manpage
  - Mark wget Multi-Arch: foreign, so packages that aren't of the same arch
    can depend on it.
* Pass --with-ssl=openssl; we don't want to use gnutls, there's no udeb for
  it.
* Add a second build pass for the udeb, so we can build without libidn.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Auxiliary functions for the creation of subprocesses.  Native Woe32 API.
 
2
   Copyright (C) 2001, 2003-2011 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 <unistd.h>
 
28
#include <errno.h>
 
29
 
 
30
#include "cloexec.h"
 
31
#include "xalloc.h"
 
32
 
 
33
/* Duplicates a file handle, making the copy uninheritable.
 
34
   Returns -1 for a file handle that is equivalent to closed.  */
 
35
static int
 
36
dup_noinherit (int fd)
 
37
{
 
38
  fd = dup_cloexec (fd);
 
39
  if (fd < 0 && errno == EMFILE)
 
40
    error (EXIT_FAILURE, errno, _("_open_osfhandle failed"));
 
41
 
 
42
  return fd;
 
43
}
 
44
 
 
45
/* Returns a file descriptor equivalent to FD, except that the resulting file
 
46
   descriptor is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
 
47
   FD must be open and non-inheritable.  The result will be non-inheritable as
 
48
   well.
 
49
   If FD < 0, FD itself is returned.  */
 
50
static int
 
51
fd_safer_noinherit (int fd)
 
52
{
 
53
  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
 
54
    {
 
55
      /* The recursion depth is at most 3.  */
 
56
      int nfd = fd_safer_noinherit (dup_noinherit (fd));
 
57
      int saved_errno = errno;
 
58
      close (fd);
 
59
      errno = saved_errno;
 
60
      return nfd;
 
61
    }
 
62
  return fd;
 
63
}
 
64
 
 
65
/* Duplicates a file handle, making the copy uninheritable and ensuring the
 
66
   result is none of STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO.
 
67
   Returns -1 for a file handle that is equivalent to closed.  */
 
68
static int
 
69
dup_safer_noinherit (int fd)
 
70
{
 
71
  return fd_safer_noinherit (dup_noinherit (fd));
 
72
}
 
73
 
 
74
/* Undoes the effect of TEMPFD = dup_safer_noinherit (ORIGFD);  */
 
75
static void
 
76
undup_safer_noinherit (int tempfd, int origfd)
 
77
{
 
78
  if (tempfd >= 0)
 
79
    {
 
80
      if (dup2 (tempfd, origfd) < 0)
 
81
        error (EXIT_FAILURE, errno, _("cannot restore fd %d: dup2 failed"),
 
82
               origfd);
 
83
      close (tempfd);
 
84
    }
 
85
  else
 
86
    {
 
87
      /* origfd was closed or open to no handle at all.  Set it to a closed
 
88
         state.  This is (nearly) equivalent to the original state.  */
 
89
      close (origfd);
 
90
    }
 
91
}
 
92
 
 
93
/* Prepares an argument vector before calling spawn().
 
94
   Note that spawn() does not by itself call the command interpreter
 
95
     (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") :
 
96
      ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
 
97
         GetVersionEx(&v);
 
98
         v.dwPlatformId == VER_PLATFORM_WIN32_NT;
 
99
      }) ? "cmd.exe" : "command.com").
 
100
   Instead it simply concatenates the arguments, separated by ' ', and calls
 
101
   CreateProcess().  We must quote the arguments since Win32 CreateProcess()
 
102
   interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a
 
103
   special way:
 
104
   - Space and tab are interpreted as delimiters. They are not treated as
 
105
     delimiters if they are surrounded by double quotes: "...".
 
106
   - Unescaped double quotes are removed from the input. Their only effect is
 
107
     that within double quotes, space and tab are treated like normal
 
108
     characters.
 
109
   - Backslashes not followed by double quotes are not special.
 
110
   - But 2*n+1 backslashes followed by a double quote become
 
111
     n backslashes followed by a double quote (n >= 0):
 
112
       \" -> "
 
113
       \\\" -> \"
 
114
       \\\\\" -> \\"
 
115
 */
 
116
#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"
 
117
#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"
 
118
static char **
 
119
prepare_spawn (char **argv)
 
120
{
 
121
  size_t argc;
 
122
  char **new_argv;
 
123
  size_t i;
 
124
 
 
125
  /* Count number of arguments.  */
 
126
  for (argc = 0; argv[argc] != NULL; argc++)
 
127
    ;
 
128
 
 
129
  /* Allocate new argument vector.  */
 
130
  new_argv = XNMALLOC (1 + argc + 1, char *);
 
131
 
 
132
  /* Add an element upfront that can be used when argv[0] turns out to be a
 
133
     script, not a program.
 
134
     On Unix, this would be "/bin/sh". On native Windows, "sh" is actually
 
135
     "sh.exe".  We have to omit the directory part and rely on the search in
 
136
     PATH, because the mingw "mount points" are not visible inside Win32
 
137
     CreateProcess().  */
 
138
  *new_argv++ = "sh.exe";
 
139
 
 
140
  /* Put quoted arguments into the new argument vector.  */
 
141
  for (i = 0; i < argc; i++)
 
142
    {
 
143
      const char *string = argv[i];
 
144
 
 
145
      if (string[0] == '\0')
 
146
        new_argv[i] = xstrdup ("\"\"");
 
147
      else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL)
 
148
        {
 
149
          bool quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL);
 
150
          size_t length;
 
151
          unsigned int backslashes;
 
152
          const char *s;
 
153
          char *quoted_string;
 
154
          char *p;
 
155
 
 
156
          length = 0;
 
157
          backslashes = 0;
 
158
          if (quote_around)
 
159
            length++;
 
160
          for (s = string; *s != '\0'; s++)
 
161
            {
 
162
              char c = *s;
 
163
              if (c == '"')
 
164
                length += backslashes + 1;
 
165
              length++;
 
166
              if (c == '\\')
 
167
                backslashes++;
 
168
              else
 
169
                backslashes = 0;
 
170
            }
 
171
          if (quote_around)
 
172
            length += backslashes + 1;
 
173
 
 
174
          quoted_string = (char *) xmalloc (length + 1);
 
175
 
 
176
          p = quoted_string;
 
177
          backslashes = 0;
 
178
          if (quote_around)
 
179
            *p++ = '"';
 
180
          for (s = string; *s != '\0'; s++)
 
181
            {
 
182
              char c = *s;
 
183
              if (c == '"')
 
184
                {
 
185
                  unsigned int j;
 
186
                  for (j = backslashes + 1; j > 0; j--)
 
187
                    *p++ = '\\';
 
188
                }
 
189
              *p++ = c;
 
190
              if (c == '\\')
 
191
                backslashes++;
 
192
              else
 
193
                backslashes = 0;
 
194
            }
 
195
          if (quote_around)
 
196
            {
 
197
              unsigned int j;
 
198
              for (j = backslashes; j > 0; j--)
 
199
                *p++ = '\\';
 
200
              *p++ = '"';
 
201
            }
 
202
          *p = '\0';
 
203
 
 
204
          new_argv[i] = quoted_string;
 
205
        }
 
206
      else
 
207
        new_argv[i] = (char *) string;
 
208
    }
 
209
  new_argv[argc] = NULL;
 
210
 
 
211
  return new_argv;
 
212
}