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

« back to all changes in this revision

Viewing changes to lib/select.c

  • 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
/* -*- buffer-read-only: t -*- vi: set ro: */
 
2
/* DO NOT EDIT! GENERATED AUTOMATICALLY! */
 
3
/* Emulation for select(2)
 
4
   Contributed by Paolo Bonzini.
 
5
 
 
6
   Copyright 2008-2011 Free Software Foundation, Inc.
 
7
 
 
8
   This file is part of gnulib.
 
9
 
 
10
   This program is free software; you can redistribute it and/or modify
 
11
   it under the terms of the GNU General Public License as published by
 
12
   the Free Software Foundation; either version 3, or (at your option)
 
13
   any later version.
 
14
 
 
15
   This program is distributed in the hope that it will be useful,
 
16
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
   GNU General Public License for more details.
 
19
 
 
20
   You should have received a copy of the GNU General Public License along
 
21
   with this program; if not, write to the Free Software Foundation,
 
22
   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
 
23
 
 
24
#include <config.h>
 
25
#include <alloca.h>
 
26
#include <assert.h>
 
27
 
 
28
#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
 
29
/* Native Win32.  */
 
30
 
 
31
#include <sys/types.h>
 
32
#include <stdbool.h>
 
33
#include <errno.h>
 
34
#include <limits.h>
 
35
 
 
36
#include <winsock2.h>
 
37
#include <windows.h>
 
38
#include <io.h>
 
39
#include <stdio.h>
 
40
#include <conio.h>
 
41
#include <time.h>
 
42
 
 
43
struct bitset {
 
44
  unsigned char in[FD_SETSIZE / CHAR_BIT];
 
45
  unsigned char out[FD_SETSIZE / CHAR_BIT];
 
46
};
 
47
 
 
48
/* Declare data structures for ntdll functions.  */
 
49
typedef struct _FILE_PIPE_LOCAL_INFORMATION {
 
50
  ULONG NamedPipeType;
 
51
  ULONG NamedPipeConfiguration;
 
52
  ULONG MaximumInstances;
 
53
  ULONG CurrentInstances;
 
54
  ULONG InboundQuota;
 
55
  ULONG ReadDataAvailable;
 
56
  ULONG OutboundQuota;
 
57
  ULONG WriteQuotaAvailable;
 
58
  ULONG NamedPipeState;
 
59
  ULONG NamedPipeEnd;
 
60
} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;
 
61
 
 
62
typedef struct _IO_STATUS_BLOCK
 
63
{
 
64
  union {
 
65
    DWORD Status;
 
66
    PVOID Pointer;
 
67
  } u;
 
68
  ULONG_PTR Information;
 
69
} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
 
70
 
 
71
typedef enum _FILE_INFORMATION_CLASS {
 
72
  FilePipeLocalInformation = 24
 
73
} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;
 
74
 
 
75
typedef DWORD (WINAPI *PNtQueryInformationFile)
 
76
         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);
 
77
 
 
78
#ifndef PIPE_BUF
 
79
#define PIPE_BUF        512
 
80
#endif
 
81
 
 
82
#define IsConsoleHandle(h) (((long) (h) & 3) == 3)
 
83
 
 
84
static BOOL
 
85
IsSocketHandle (HANDLE h)
 
86
{
 
87
  WSANETWORKEVENTS ev;
 
88
 
 
89
  if (IsConsoleHandle (h))
 
90
    return FALSE;
 
91
 
 
92
  /* Under Wine, it seems that getsockopt returns 0 for pipes too.
 
93
     WSAEnumNetworkEvents instead distinguishes the two correctly.  */
 
94
  ev.lNetworkEvents = 0xDEADBEEF;
 
95
  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);
 
96
  return ev.lNetworkEvents != 0xDEADBEEF;
 
97
}
 
98
 
 
99
/* Compute output fd_sets for libc descriptor FD (whose Win32 handle is H).  */
 
100
 
 
101
static int
 
102
win32_poll_handle (HANDLE h, int fd, struct bitset *rbits, struct bitset *wbits,
 
103
                   struct bitset *xbits)
 
104
{
 
105
  BOOL read, write, except;
 
106
  int i, ret;
 
107
  INPUT_RECORD *irbuffer;
 
108
  DWORD avail, nbuffer;
 
109
  BOOL bRet;
 
110
  IO_STATUS_BLOCK iosb;
 
111
  FILE_PIPE_LOCAL_INFORMATION fpli;
 
112
  static PNtQueryInformationFile NtQueryInformationFile;
 
113
  static BOOL once_only;
 
114
 
 
115
  read = write = except = FALSE;
 
116
  switch (GetFileType (h))
 
117
    {
 
118
    case FILE_TYPE_DISK:
 
119
      read = TRUE;
 
120
      write = TRUE;
 
121
      break;
 
122
 
 
123
    case FILE_TYPE_PIPE:
 
124
      if (!once_only)
 
125
        {
 
126
          NtQueryInformationFile = (PNtQueryInformationFile)
 
127
            GetProcAddress (GetModuleHandle ("ntdll.dll"),
 
128
                            "NtQueryInformationFile");
 
129
          once_only = TRUE;
 
130
        }
 
131
 
 
132
      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)
 
133
        {
 
134
          if (avail)
 
135
            read = TRUE;
 
136
        }
 
137
      else if (GetLastError () == ERROR_BROKEN_PIPE)
 
138
        ;
 
139
 
 
140
      else
 
141
        {
 
142
          /* It was the write-end of the pipe.  Check if it is writable.
 
143
             If NtQueryInformationFile fails, optimistically assume the pipe is
 
144
             writable.  This could happen on Win9x, where NtQueryInformationFile
 
145
             is not available, or if we inherit a pipe that doesn't permit
 
146
             FILE_READ_ATTRIBUTES access on the write end (I think this should
 
147
             not happen since WinXP SP2; WINE seems fine too).  Otherwise,
 
148
             ensure that enough space is available for atomic writes.  */
 
149
          memset (&iosb, 0, sizeof (iosb));
 
150
          memset (&fpli, 0, sizeof (fpli));
 
151
 
 
152
          if (!NtQueryInformationFile
 
153
              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),
 
154
                                         FilePipeLocalInformation)
 
155
              || fpli.WriteQuotaAvailable >= PIPE_BUF
 
156
              || (fpli.OutboundQuota < PIPE_BUF &&
 
157
                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))
 
158
            write = TRUE;
 
159
        }
 
160
      break;
 
161
 
 
162
    case FILE_TYPE_CHAR:
 
163
      write = TRUE;
 
164
      if (!(rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
 
165
        break;
 
166
 
 
167
      ret = WaitForSingleObject (h, 0);
 
168
      if (ret == WAIT_OBJECT_0)
 
169
        {
 
170
          if (!IsConsoleHandle (h))
 
171
            {
 
172
              read = TRUE;
 
173
              break;
 
174
            }
 
175
 
 
176
          nbuffer = avail = 0;
 
177
          bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);
 
178
 
 
179
          /* Screen buffers handles are filtered earlier.  */
 
180
          assert (bRet);
 
181
          if (nbuffer == 0)
 
182
            {
 
183
              except = TRUE;
 
184
              break;
 
185
            }
 
186
 
 
187
          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));
 
188
          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);
 
189
          if (!bRet || avail == 0)
 
190
            {
 
191
              except = TRUE;
 
192
              break;
 
193
            }
 
194
 
 
195
          for (i = 0; i < avail; i++)
 
196
            if (irbuffer[i].EventType == KEY_EVENT)
 
197
              read = TRUE;
 
198
        }
 
199
      break;
 
200
 
 
201
    default:
 
202
      ret = WaitForSingleObject (h, 0);
 
203
      write = TRUE;
 
204
      if (ret == WAIT_OBJECT_0)
 
205
        read = TRUE;
 
206
 
 
207
      break;
 
208
    }
 
209
 
 
210
  ret = 0;
 
211
  if (read && (rbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
 
212
    {
 
213
      rbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
 
214
      ret++;
 
215
    }
 
216
 
 
217
  if (write && (wbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
 
218
    {
 
219
      wbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
 
220
      ret++;
 
221
    }
 
222
 
 
223
  if (except && (xbits->in[fd / CHAR_BIT] & (1 << (fd & (CHAR_BIT - 1)))))
 
224
    {
 
225
      xbits->out[fd / CHAR_BIT] |= (1 << (fd & (CHAR_BIT - 1)));
 
226
      ret++;
 
227
    }
 
228
 
 
229
  return ret;
 
230
}
 
231
 
 
232
int
 
233
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
 
234
            struct timeval *timeout)
 
235
{
 
236
  static struct timeval tv0;
 
237
  static HANDLE hEvent;
 
238
  HANDLE h, handle_array[FD_SETSIZE + 2];
 
239
  fd_set handle_rfds, handle_wfds, handle_xfds;
 
240
  struct bitset rbits, wbits, xbits;
 
241
  unsigned char anyfds_in[FD_SETSIZE / CHAR_BIT];
 
242
  DWORD ret, wait_timeout, nhandles, nsock, nbuffer;
 
243
  MSG msg;
 
244
  int i, fd, rc;
 
245
 
 
246
  if (nfds > FD_SETSIZE)
 
247
    nfds = FD_SETSIZE;
 
248
 
 
249
  if (!timeout)
 
250
    wait_timeout = INFINITE;
 
251
  else
 
252
    {
 
253
      wait_timeout = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;
 
254
 
 
255
      /* select is also used as a portable usleep.  */
 
256
      if (!rfds && !wfds && !xfds)
 
257
        {
 
258
          Sleep (wait_timeout);
 
259
          return 0;
 
260
        }
 
261
    }
 
262
 
 
263
  if (!hEvent)
 
264
    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);
 
265
 
 
266
  handle_array[0] = hEvent;
 
267
  nhandles = 1;
 
268
  nsock = 0;
 
269
 
 
270
  /* Copy descriptors to bitsets.  At the same time, eliminate
 
271
     bits in the "wrong" direction for console input buffers
 
272
     and screen buffers, because screen buffers are waitable
 
273
     and they will block until a character is available.  */
 
274
  memset (&rbits, 0, sizeof (rbits));
 
275
  memset (&wbits, 0, sizeof (wbits));
 
276
  memset (&xbits, 0, sizeof (xbits));
 
277
  memset (anyfds_in, 0, sizeof (anyfds_in));
 
278
  if (rfds)
 
279
    for (i = 0; i < rfds->fd_count; i++)
 
280
      {
 
281
        fd = rfds->fd_array[i];
 
282
        h = (HANDLE) _get_osfhandle (fd);
 
283
        if (IsConsoleHandle (h)
 
284
            && !GetNumberOfConsoleInputEvents (h, &nbuffer))
 
285
          continue;
 
286
 
 
287
        rbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
288
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
289
      }
 
290
  else
 
291
    rfds = (fd_set *) alloca (sizeof (fd_set));
 
292
 
 
293
  if (wfds)
 
294
    for (i = 0; i < wfds->fd_count; i++)
 
295
      {
 
296
        fd = wfds->fd_array[i];
 
297
        h = (HANDLE) _get_osfhandle (fd);
 
298
        if (IsConsoleHandle (h)
 
299
            && GetNumberOfConsoleInputEvents (h, &nbuffer))
 
300
          continue;
 
301
 
 
302
        wbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
303
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
304
      }
 
305
  else
 
306
    wfds = (fd_set *) alloca (sizeof (fd_set));
 
307
 
 
308
  if (xfds)
 
309
    for (i = 0; i < xfds->fd_count; i++)
 
310
      {
 
311
        fd = xfds->fd_array[i];
 
312
        xbits.in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
313
        anyfds_in[fd / CHAR_BIT] |= 1 << (fd & (CHAR_BIT - 1));
 
314
      }
 
315
  else
 
316
    xfds = (fd_set *) alloca (sizeof (fd_set));
 
317
 
 
318
  /* Zero all the fd_sets, including the application's.  */
 
319
  FD_ZERO (rfds);
 
320
  FD_ZERO (wfds);
 
321
  FD_ZERO (xfds);
 
322
  FD_ZERO (&handle_rfds);
 
323
  FD_ZERO (&handle_wfds);
 
324
  FD_ZERO (&handle_xfds);
 
325
 
 
326
  /* Classify handles.  Create fd sets for sockets, poll the others. */
 
327
  for (i = 0; i < nfds; i++)
 
328
    {
 
329
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
 
330
        continue;
 
331
 
 
332
      h = (HANDLE) _get_osfhandle (i);
 
333
      if (!h)
 
334
        {
 
335
          errno = EBADF;
 
336
          return -1;
 
337
        }
 
338
 
 
339
      if (IsSocketHandle (h))
 
340
        {
 
341
          int requested = FD_CLOSE;
 
342
 
 
343
          /* See above; socket handles are mapped onto select, but we
 
344
             need to map descriptors to handles.  */
 
345
          if (rbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
346
            {
 
347
              requested |= FD_READ | FD_ACCEPT;
 
348
              FD_SET ((SOCKET) h, rfds);
 
349
              FD_SET ((SOCKET) h, &handle_rfds);
 
350
            }
 
351
          if (wbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
352
            {
 
353
              requested |= FD_WRITE | FD_CONNECT;
 
354
              FD_SET ((SOCKET) h, wfds);
 
355
              FD_SET ((SOCKET) h, &handle_wfds);
 
356
            }
 
357
          if (xbits.in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
358
            {
 
359
              requested |= FD_OOB;
 
360
              FD_SET ((SOCKET) h, xfds);
 
361
              FD_SET ((SOCKET) h, &handle_xfds);
 
362
            }
 
363
 
 
364
          WSAEventSelect ((SOCKET) h, hEvent, requested);
 
365
          nsock++;
 
366
        }
 
367
      else
 
368
        {
 
369
          handle_array[nhandles++] = h;
 
370
 
 
371
          /* Poll now.  If we get an event, do not wait below.  */
 
372
          if (wait_timeout != 0
 
373
              && win32_poll_handle (h, i, &rbits, &wbits, &xbits))
 
374
            wait_timeout = 0;
 
375
        }
 
376
    }
 
377
 
 
378
  if (wait_timeout == 0 || nsock == 0)
 
379
    rc = 0;
 
380
  else
 
381
    {
 
382
      /* See if we need to wait in the loop below.  If any select is ready,
 
383
         do MsgWaitForMultipleObjects anyway to dispatch messages, but
 
384
         no need to call select again.  */
 
385
      rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
 
386
      if (rc == 0)
 
387
        {
 
388
          /* Restore the fd_sets for the other select we do below.  */
 
389
          memcpy (&handle_rfds, rfds, sizeof (fd_set));
 
390
          memcpy (&handle_wfds, wfds, sizeof (fd_set));
 
391
          memcpy (&handle_xfds, xfds, sizeof (fd_set));
 
392
        }
 
393
      else
 
394
        wait_timeout = 0;
 
395
    }
 
396
 
 
397
  for (;;)
 
398
    {
 
399
      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,
 
400
                                       wait_timeout, QS_ALLINPUT);
 
401
 
 
402
      if (ret == WAIT_OBJECT_0 + nhandles)
 
403
        {
 
404
          /* new input of some other kind */
 
405
          BOOL bRet;
 
406
          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)
 
407
            {
 
408
              TranslateMessage (&msg);
 
409
              DispatchMessage (&msg);
 
410
            }
 
411
        }
 
412
      else
 
413
        break;
 
414
    }
 
415
 
 
416
  /* If we haven't done it yet, check the status of the sockets.  */
 
417
  if (rc == 0 && nsock > 0)
 
418
    rc = select (0, &handle_rfds, &handle_wfds, &handle_xfds, &tv0);
 
419
 
 
420
  /* Now fill in the results.  */
 
421
  FD_ZERO (rfds);
 
422
  FD_ZERO (wfds);
 
423
  FD_ZERO (xfds);
 
424
 
 
425
  /* Place a sentinel at the end of the array.  */
 
426
  handle_array[nhandles] = NULL;
 
427
  nhandles = 1;
 
428
  for (i = 0; i < nfds; i++)
 
429
    {
 
430
      if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
 
431
        continue;
 
432
 
 
433
      h = (HANDLE) _get_osfhandle (i);
 
434
      if (h != handle_array[nhandles])
 
435
        {
 
436
          /* Perform handle->descriptor mapping.  Don't update rc, as these
 
437
             results are counted in the return value of Winsock's select.  */
 
438
          WSAEventSelect ((SOCKET) h, NULL, 0);
 
439
          if (FD_ISSET (h, &handle_rfds))
 
440
            FD_SET (i, rfds);
 
441
          if (FD_ISSET (h, &handle_wfds))
 
442
            FD_SET (i, wfds);
 
443
          if (FD_ISSET (h, &handle_xfds))
 
444
            FD_SET (i, xfds);
 
445
        }
 
446
      else
 
447
        {
 
448
          /* Not a socket.  */
 
449
          nhandles++;
 
450
          win32_poll_handle (h, i, &rbits, &wbits, &xbits);
 
451
          if (rbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
452
            {
 
453
              rc++;
 
454
              FD_SET (i, rfds);
 
455
            }
 
456
          if (wbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
457
            {
 
458
              rc++;
 
459
              FD_SET (i, wfds);
 
460
            }
 
461
          if (xbits.out[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1))))
 
462
            {
 
463
              rc++;
 
464
              FD_SET (i, xfds);
 
465
            }
 
466
        }
 
467
    }
 
468
 
 
469
  return rc;
 
470
}
 
471
 
 
472
#else /* ! Native Win32.  */
 
473
 
 
474
#include <sys/select.h>
 
475
 
 
476
#undef select
 
477
 
 
478
int
 
479
rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set *xfds,
 
480
            struct timeval *timeout)
 
481
{
 
482
  /* Interix 3.5 has a bug: it does not support nfds == 0.  */
 
483
  if (nfds == 0)
 
484
    {
 
485
      nfds = 1;
 
486
      rfds = NULL;
 
487
      wfds = NULL;
 
488
      xfds = NULL;
 
489
    }
 
490
  return select (nfds, rfds, wfds, xfds, timeout);
 
491
}
 
492
 
 
493
#endif