105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* getdtablesize() function for platforms that don't have it.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2008-2012 Free Software Foundation, Inc.
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Written by Bruno Haible <bruno@clisp.org>, 2008.
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software: you can redistribute it and/or modify
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3 of the License, or
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   (at your option) any later version.
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h>
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification.  */
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <unistd.h>
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdio.h>
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include "msvc-inval.h"
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang_setmaxstdio_nothrow (int newmax)
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  int result;
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  TRY_MSVC_INVAL
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      result = _setmaxstdio (newmax);
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang  CATCH_MSVC_INVAL
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      result = -1;
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  DONE_MSVC_INVAL;
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return result;
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define _setmaxstdio _setmaxstdio_nothrow
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Cache for the previous getdtablesize () result.  */
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic int dtablesize;
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wanggetdtablesize (void)
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang  if (dtablesize == 0)
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang    {
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      /* We are looking for the number N such that the valid file descriptors
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang         are 0..N-1.  It can be obtained through a loop as follows:
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang           {
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang             int fd;
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang             for (fd = 3; fd < 65536; fd++)
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang               if (dup2 (0, fd) == -1)
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang                 break;
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang             return fd;
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang           }
6705436638acc7c010349a69c3395f1a57c642dc62Ying Wang         On Windows XP, the result is 2048.
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang         The drawback of this loop is that it allocates memory for a libc
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang         internal array that is never freed.
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang         The number N can also be obtained as the upper bound for
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang         _getmaxstdio ().  _getmaxstdio () returns the maximum number of open
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang         FILE objects.  The sanity check in _setmaxstdio reveals the maximum
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang         number of file descriptors.  This too allocates memory, but it is
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang         freed when we call _setmaxstdio with the original value.  */
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang      int orig_max_stdio = _getmaxstdio ();
7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      unsigned int bound;
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      for (bound = 0x10000; _setmaxstdio (bound) < 0; bound = bound / 2)
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang        ;
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang      _setmaxstdio (orig_max_stdio);
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang      dtablesize = bound;
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang    }
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return dtablesize;
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
87