Various updates, mainly to the Windows port, from Eli Zaretskii and
authorPaul Smith <psmith@gnu.org>
Wed, 1 Feb 2006 07:54:22 +0000 (07:54 +0000)
committerPaul Smith <psmith@gnu.org>
Wed, 1 Feb 2006 07:54:22 +0000 (07:54 +0000)
Markus Maurhart.

16 files changed:
ChangeLog
Makefile.am
NEWS
README.W32.template
README.cvs
config.h.W32.template
doc/make.texi
job.c
main.c
make_msvc_net2003.vcproj
po/ChangeLog
po/LINGUAS
remake.c
tests/scripts/options/symlinks
w32/include/sub_proc.h
w32/subproc/sub_proc.c

index 817ba1d9844209369a144a69b65e36a0d5e565d6..5eaa94dfe98ac983e4b1d81732e3315cf65d4df6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,50 @@
+2006-01-31  Paul D. Smith  <psmith@gnu.org>
+
+       * README.W32.template: Applied patch #4785 from
+       Markus Mauhart <qwe123@chello.at>.
+       * README.cvs: Applied patch #4786 from
+       Markus Mauhart <qwe123@chello.at>.
+       * make_msvc_net2003.vcproj [WINDOWS32]: New version from
+       Markus Mauhart <qwe123@chello.at>.
+
+       * main.c: Update the copyright year in the version output.
+       * prepare_w32.bat: Remove this file from the distribution.
+
+2006-01-21  Eli Zaretskii  <eliz@gnu.org>
+
+       * remake.c (update_goal_chain): Set g->changed instead of
+       incrementing it, as it is only 8-bit wide, and could overflow if
+       many commands got started in update_file.
+
+       * w32/include/sub_proc.h: Add a prototype for process_used_slots.
+
+       * w32/subproc/sub_proc.c: Change dimension of proc_array[] to
+       MAXIMUM_WAIT_OBJECTS.
+       (process_wait_for_any_private): Change dimension of handles[]
+       array to MAXIMUM_WAIT_OBJECTS.
+       (process_used_slots): New function.
+       (process_register): Don't register more processes than the
+       available number of slots.
+       (process_easy): Don't start new processes if all slots are used up.
+
+       * job.c (load_too_high, start_waiting_jobs) [WINDOWS32]: If there
+       are already more children than sub_proc.c can handle, behave as if
+       the load were too high.
+       (start_job_command): Fix a typo in error message when process_easy
+       fails.
+
+2006-01-14  Eli Zaretskii  <eliz@gnu.org>
+
+       * main.c (main) [WINDOWS32]: Don't refuse to run with -jN, even if
+       the shell is not sh.exe.
+
+       * job.c (create_batch_file): Renamed from create_batch_filename;
+       all callers changed.  Don't close the temporary file; return its
+       file descriptor instead.  New arg FD allows to return the file
+       descriptor.
+       (construct_command_argv_internal): Use _fdopen instead of fopen to
+       open the batch file.
+
 2006-01-04  Paul D. Smith  <psmith@gnu.org>
 
        * readme.vms: Updates for case-insensitive VMS file systems from
        disable warnings for MSC.
        Patch by Rob Tulloh <rtulloh@yahoo.com>.
 
-2005-12-18  Paul D. Smith  <psmith@gnu.org>
-
-       * Makefile.am (EXTRA_DIST): Distribute prepare_w32.bat.
-
 2005-12-17  Eli Zaretskii  <eliz@gnu.org>
 
        * doc/make.texi (Execution): Add a footnote about changes in
index 2c54794686c102564a3a29d4ca9511d96793e980..ebd83a72f4f206faeb8aa43b983fe4124bb34df0 100644 (file)
@@ -59,7 +59,7 @@ EXTRA_DIST =  README build.sh.in $(man_MANS) \
                README.Amiga Makefile.ami config.ami make.lnk amiga.c amiga.h \
                README.DOS Makefile.DOS configure.bat dosbuild.bat configh.dos\
                README.W32 NMakefile config.h.W32 build_w32.bat subproc.bat \
-               make_msvc_net2003.sln make_msvc_net2003.vcproj prepare_w32.bat\
+               make_msvc_net2003.sln make_msvc_net2003.vcproj \
                readme.vms makefile.vms makefile.com config.h-vms \
                vmsdir.h vmsfunctions.c vmsify.c
 
diff --git a/NEWS b/NEWS
index 6b3f2e3b1d2f5785e4eebd62bbf8343766c3e2ad..1bf8301752c831b8db28525f24318cb846885c5c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -111,6 +111,10 @@ Version 3.81beta4
 * On VMS there is now support for case-sensitive filesystems such as ODS5.
   See the readme.vms file for information.
 
+* Parallel builds (-jN) no longer require a working Bourne shell on
+  Windows platforms.  They work even with the stock Windows shells, such
+  as cmd.exe and command.com.
+
 * Updated to autoconf 2.59, automake 1.9.5, and gettext 0.14.1.  Users
   should not be impacted.
 
index f40884e8bcdee97f60a1d773d8e89fbb6d93c83e..437ebcb5735e3875ddbf380e0e550556a58d6855 100644 (file)
@@ -9,52 +9,63 @@ It builds with the MinGW port of GCC 3.x (tested with GCC 3.4.2).
 The Windows 32-bit port of GNU make is maintained jointly by various
 people.  It was originally made by Rob Tulloh.
 
-To build with MinGW:
 
-       1. Edit config.h.W32 to your liking (especially the few
-           shell-related defines near the end).
+Do this first, regardless of the build method you choose:
+---------------------------------------------------------
 
-       2. Invoke build_w32.bat with the "gcc" argument:
+ 0. If your sources come from CVS, read the Windows-specific section of
+    README.cvs.
 
-               build_w32 gcc
+ 1. At the Windows command prompt run:
 
-          This produces gnumake.exe in the current directory.
+       if not exist config.h copy config.h.W32 config.h
 
-To build with nmake:
+    Then edit config.h to your liking (especially the few shell-related
+    defines near the end, or HAVE_CASE_INSENSITIVE_FS which corresponds
+    to './configure --enable-case-insensitive-file-system').
 
-       1. Make sure cl.exe is in your %Path%. Example:
 
-               set Path=%Path%;c:/msdev/bin
+Using make_msvc_net2003.vcproj
+------------------------------
 
-       2. Make sure %include% is set to msvc include directory. Example:
+ 2. Open make_msvc_net2003.vcproj in MSVS71 or MSVC71 or any compatible IDE,
+    then build this project as usual.
 
-               set include=c:/msdev/include
 
-       3. Make sure %lib% is set to msvc lib directory. Example:
+Building with (MinGW-)GCC using build_w32.bat
+---------------------------------------------
 
-               set lib=c:/msdev/lib
+ 2. Open a W32 command prompt for your installed (MinGW-)GCC, setup a
+    correct PATH and other environment variables for it, then execute ...
 
-       4. nmake /f NMakefile
+       build_w32.bat gcc
 
+    This produces gnumake.exe in the current directory.
 
-    A short cut to steps 1, 2, and 3 is to run VCVARS32.bat before
-    invoking nmake. For example:
 
-        c:
-        cd \msdev\bin
-        VCVARS32.bat
-       cd \path\to\make-%VERSION%
-       nmake /f NMakefile
+Building with (MSVC++-)cl using build_w32.bat or NMakefile
+----------------------------------------------------------
+
+ 2. Open a W32 command prompt for your installed (MSVC++-)cl, setup a
+    correct PATH and other environment variables for it (usually via
+    executing vcvars32.bat or vsvars32.bat from the cl-installation,
+    e.g. "%VS71COMNTOOLS%vsvars32.bat"; or using a corresponding start
+    menue entry from the cl-installation), then execute EITHER ...
+
+       build_w32.bat
 
-There is a bat file (build_w32.bat) for folks who have fear of nmake.
+    (this produces WinDebug/gnumake.exe and WinRel/gnumake.exe)
 
-Outputs:
+    ... OR ...
+
+       nmake /f NMakefile
 
-       WinDebug/make.exe
-       WinRel/make.exe
+    (this produces WinDebug/make.exe and WinRel/make.exe).
 
 
+-------------------
 -- Notes/Caveats --
+-------------------
 
 GNU make on Windows 32-bit platforms:
 
index fd109348d88c24f61fa8c5f26604d4896c530e86..fe6c1ac3307dadeeb0a2307fceb52feb9ba24f4a 100644 (file)
@@ -8,7 +8,7 @@ already performed this step; however, for completeness, you can obtain
 the GNU make source code via anonymous CVS from the FSF's Savannah
 project <http://savannah.gnu.org/projects/make/>:
 
-  $ cvs -d:pserver:anoncvs@subversions.gnu.org:/cvsroot/make co make
+  $ cvs -d:pserver:anoncvs@cvs.savannah.gnu.org:/sources/make co make
 
 You might want to use the "-z3" option to get compression, and you most
 certainly will want the -P option to avoid unneeded directories
@@ -93,6 +93,28 @@ T. and the AutoToolers!
 That's it, you're done!
 
 
+Windows builds from CVS
+-----------------------
+
+IF you have managed to successfully perform the 1st two or three steps of
+the general build procedure as explained above:
+
+  $ autoreconf [-i] -s
+  $ ./configure
+ [$ make update]
+
+THEN proceed with file README.W32.
+
+ELSE ignore the general build procedure, instead execute the following
+command lines at a Windows command prompt:
+
+  if not exist README.W32 copy README.W32.template README.W32
+  if not exist config.h.W32 copy config.h.W32.template config.h.W32
+  if not exist NMakefile copy NMakefile.template NMakefile
+
+Now proceed with file README.W32.
+
+
 Appendix A - For The Brave
 --------------------------
 
index 160f120474e84752e138544e308e44e79402f60a..e0b4f6ff6736ebd4a0427c354de45c574a01d8b0 100644 (file)
@@ -4,7 +4,9 @@
    Maybe after the code cleanup for ISO C we can remove some/all of these.  */
 #if _MSC_VER > 1000
 # pragma warning(disable:4100) /* unreferenced formal parameter */
+# pragma warning(disable:4102) /* unreferenced label */
 # pragma warning(disable:4127) /* conditional expression is constant */
+# pragma warning(disable:4131) /* uses old-style declarator */
 # pragma warning(disable:4702) /* unreachable code */
 #endif
 
index b0de8454e9eeb7ffc36e5bb465cb938f013eb146..eba92c787a77ab181bb3fed8374eb986cd68142f 100644 (file)
@@ -10,8 +10,8 @@
 @set RCSID $Id$
 @set EDITION 0.70
 @set VERSION 3.81
-@set UPDATED 28 Dec 2005
-@set UPDATE-MONTH Dec 2005
+@set UPDATED 29 Jan 2006
+@set UPDATE-MONTH Jan 2006
 @c ISBN provided by Lisa M. Opus Goldstein <opus@gnu.org>, 5 May 2004
 @set ISBN 1-882114-83-5
 
@@ -2589,7 +2589,7 @@ each pattern in the list with @var{name} and perform the above directory
 searches using that library filename.  If no library is found, the next
 word in the list will be used.
 
-The default value for @code{.LIBPATTERNS} is ``@samp{lib%.so lib%.a}'',
+The default value for @code{.LIBPATTERNS} is @samp{lib%.so lib%.a},
 which provides the default behavior described above.
 
 You can turn off link library expansion completely by setting this
@@ -4825,7 +4825,6 @@ Sub-@code{make}}, for information about @code{MAKELEVEL}.)
 @example
 @group
 ifeq (0,$@{MAKELEVEL@})
-cur-dir   := $(shell pwd)
 whoami    := $(shell whoami)
 host-type := $(shell arch)
 MAKE := $@{MAKE@} host-type=$@{host-type@} whoami=$@{whoami@}
@@ -4840,7 +4839,7 @@ An advantage of this use of @samp{:=} is that a typical
 @example
 @group
 $@{subdirs@}:
-      $@{MAKE@} cur-dir=$@{cur-dir@}/$@@ -C $@@ all
+        $@{MAKE@} -C $@@ all
 @end group
 @end example
 
@@ -8818,10 +8817,11 @@ with @samp{s.}, ends in @samp{.c} and is at least five characters long.
 that the @samp{%} matches is called the @dfn{stem}.@refill
 
 @samp{%} in a prerequisite of a pattern rule stands for the same stem
-that was matched by the @samp{%} in the target.  In order for
-the pattern rule to apply, its target pattern must match the file name
-under consideration, and its prerequisite patterns must name files that
-exist or can be made.  These files become prerequisites of the target.
+that was matched by the @samp{%} in the target.  In order for the
+pattern rule to apply, its target pattern must match the file name
+under consideration and all of its prerequisites (after pattern
+substitution) must name files that exist or can be made.  These files
+become prerequisites of the target.
 @cindex prerequisite pattern, implicit
 
 Thus, a rule of the form
diff --git a/job.c b/job.c
index ba012970b842324be7694f63e0c4c3720d78eda1..9fbe84e6400f7d307abe6ba24e42de22364b5275 100644 (file)
--- a/job.c
+++ b/job.c
@@ -242,11 +242,12 @@ w32_kill(int pid, int sig)
   return ((process_kill((HANDLE)pid, sig) == TRUE) ? 0 : -1);
 }
 
-/* This function creates a temporary file name with the given extension
- * the unixy param controls both the extension and the path separator
- * return an xmalloc'ed string of a newly created temp file or die.  */
+/* This function creates a temporary file name with an extension specified
+ * by the unixy arg.
+ * Return an xmalloc'ed string of a newly created temp file and its
+ * file descriptor, or die.  */
 static char *
-create_batch_filename(char const *base, int unixy)
+create_batch_file (char const *base, int unixy, int *fd)
 {
   const char *const ext = unixy ? "sh" : "bat";
   const char *error = NULL;
@@ -304,7 +305,7 @@ create_batch_filename(char const *base, int unixy)
           const unsigned final_size = path_size + size + 1;
           char *const path = (char *) xmalloc (final_size);
           memcpy (path, temp_path, final_size);
-          CloseHandle (h);
+          *fd = _open_osfhandle ((long)h, 0);
           if (unixy)
             {
               char *p;
@@ -317,6 +318,7 @@ create_batch_filename(char const *base, int unixy)
         }
     }
 
+  *fd = -1;
   if (error == NULL)
     error = _("Cannot create a temporary file\n");
   fatal (NILF, error);
@@ -1380,7 +1382,7 @@ start_job_command (struct child *child)
         int i;
         unblock_sigs();
         fprintf(stderr,
-          _("process_easy() failed failed to launch process (e=%ld)\n"),
+          _("process_easy() failed to launch process (e=%ld)\n"),
           process_last_err(hPID));
                for (i = 0; argv[i]; i++)
                  fprintf(stderr, "%s ", argv[i]);
@@ -1429,7 +1431,12 @@ start_waiting_job (struct child *c)
 
   /* If we are running at least one job already and the load average
      is too high, make this one wait.  */
-  if (!c->remote && job_slots_used > 0 && load_too_high ())
+  if (!c->remote
+      && ((job_slots_used > 0 && load_too_high ())
+#ifdef WINDOWS32
+         || (process_used_slots () >= MAXIMUM_WAIT_OBJECTS)
+#endif
+         ))
     {
       /* Put this child on the chain of children waiting for the load average
          to go down.  */
@@ -1799,6 +1806,12 @@ load_too_high (void)
   double load, guess;
   time_t now;
 
+#ifdef WINDOWS32
+  /* sub_proc.c cannot wait for more than MAXIMUM_WAIT_OBJECTS children */
+  if (process_used_slots () >= MAXIMUM_WAIT_OBJECTS)
+    return 1;
+#endif
+
   if (max_load_average < 0)
     return 0;
 
@@ -2755,19 +2768,21 @@ construct_command_argv_internal (char *line, char **restp, char *shell,
        command line (e.g. Cygnus GNUWIN32 sh.exe on WIN32 systems).  In these
        cases, run commands via a script file.  */
     if ((no_default_sh_exe || batch_mode_shell) && batch_filename_ptr) {
+      int temp_fd;
       FILE* batch = NULL;
       int id = GetCurrentProcessId();
       PATH_VAR(fbuf);
 
       /* create a file name */
       sprintf(fbuf, "make%d", id);
-      *batch_filename_ptr = create_batch_filename (fbuf, unixy_shell);
+      *batch_filename_ptr = create_batch_file (fbuf, unixy_shell, &temp_fd);
 
       DB (DB_JOBS, (_("Creating temporary batch file %s\n"),
                     *batch_filename_ptr));
 
-      /* create batch file to execute command */
-      batch = fopen (*batch_filename_ptr, "w");
+      /* Create a FILE object for the batch file, and write to it the
+        commands to be executed.  */
+      batch = _fdopen (temp_fd, "w");
       if (!unixy_shell)
         fputs ("@echo off\n", batch);
       fputs (command_ptr, batch);
diff --git a/main.c b/main.c
index 52babce5727b71e40ad40187c8415843941cf1af..8e9187d1a23a310934b06bb04f8933cb883fa8df 100644 (file)
--- a/main.c
+++ b/main.c
@@ -1595,12 +1595,6 @@ main (int argc, char **argv, char **envp)
   /* look one last time after reading all Makefiles */
   if (no_default_sh_exe)
     no_default_sh_exe = !find_and_set_default_shell(NULL);
-
-  if (no_default_sh_exe && job_slots != 1) {
-    error (NILF, _("Do not specify -j or --jobs if sh.exe is not available."));
-    error (NILF, _("Resetting make for single job mode."));
-    job_slots = 1;
-  }
 #endif /* WINDOWS32 */
 
 #if defined (__MSDOS__) || defined (__EMX__)
@@ -2944,7 +2938,7 @@ print_version (void)
      word "Copyright", so it hardly seems worth it.  */
 
   printf ("%sGNU Make %s\n\
-%sCopyright (C) 2003  Free Software Foundation, Inc.\n",
+%sCopyright (C) 2006  Free Software Foundation, Inc.\n",
           precede, version_string, precede);
 
   printf (_("%sThis is free software; see the source for copying conditions.\n\
index fcf6ba8bd2f866b83db982bcfec6c2869a85d15d..af64cb2da9a7fe995c18fa4030e6d2f3d67b3901 100644 (file)
@@ -27,7 +27,8 @@
                                ForceConformanceInForLoopScope="TRUE"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               SuppressStartupBanner="TRUE"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
                                DebugInformationFormat="4"/>\r
                        <Tool\r
                                Name="VCCustomBuildTool"/>\r
@@ -44,7 +45,9 @@
                        <Tool\r
                                Name="VCPostBuildEventTool"/>\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Copying config.h.W32 to config.h"\r
+                               CommandLine="if not exist config.h copy config.h.W32 config.h"/>\r
                        <Tool\r
                                Name="VCPreLinkEventTool"/>\r
                        <Tool\r
@@ -74,7 +77,7 @@
                                ForceConformanceInForLoopScope="TRUE"\r
                                UsePrecompiledHeader="0"\r
                                WarningLevel="4"\r
-                               Detect64BitPortabilityProblems="TRUE"\r
+                               Detect64BitPortabilityProblems="FALSE"\r
                                DebugInformationFormat="3"/>\r
                        <Tool\r
                                Name="VCCustomBuildTool"/>\r
@@ -92,7 +95,9 @@
                        <Tool\r
                                Name="VCPostBuildEventTool"/>\r
                        <Tool\r
-                               Name="VCPreBuildEventTool"/>\r
+                               Name="VCPreBuildEventTool"\r
+                               Description="Copying config.h.W32 to config.h"\r
+                               CommandLine="if not exist config.h copy config.h.W32 config.h"/>\r
                        <Tool\r
                                Name="VCPreLinkEventTool"/>\r
                        <Tool\r
index 1be5d52d8f3bd2f987510d0ae1b77f7e97361b75..369d33ad8dc6aef9d41864b3fced3fec1c5aa09a 100644 (file)
@@ -1,3 +1,7 @@
+2006-01-28  Paul D. Smith  <psmith@gnu.org>
+
+       * LINGUAS: Added new translation for Vietnamese (vi).
+
 2005-07-14  Paul D. Smith  <psmith@gnu.org>
 
        * LINGUAS: Added new translation for Indonesian (id).
index ec0dffc1e26b79e798ddba1bb0fb727b4bee3ab5..3f0c531c0f96b4db87622d1c5ff0af295ae732b2 100644 (file)
@@ -1,5 +1,5 @@
-# Set of available languages: 22 languages
+# Set of available languages: 23 languages
 
-be da de es fi fr ga gl he hr id ja ko nl pl pt_BR ru rw sv tr uk zh_CN
+be da de es fi fr ga gl he hr id ja ko nl pl pt_BR ru rw sv tr uk vi zh_CN
 
 # Can't seem to get en@quot and en@boldquot to build properly?
index 35005350f850e3dc249cfb34ae7fc5cb8cc7e82b..184e9101fbb916245bd9603ff5decc554cc47fec 100644 (file)
--- a/remake.c
+++ b/remake.c
@@ -159,7 +159,8 @@ update_goal_chain (struct dep *goals)
              /* Set the goal's `changed' flag if any commands were started
                 by calling update_file above.  We check this flag below to
                 decide when to give an "up to date" diagnostic.  */
-             g->changed += commands_started - ocommands_started;
+              if (commands_started > ocommands_started)
+                g->changed = 1;
 
               /* If we updated a file and STATUS was not already 1, set it to
                  1 if updating failed, or to 0 if updating succeeded.  Leave
index d63e2221f6aafdb73aa01c08c5dba1d4722cf29f..70cba3cbdbaad1b30332d9130ecb63a68e684d42 100644 (file)
@@ -5,7 +5,12 @@ $description = "Test the -L option.";
 $details = "Verify that symlink handling with and without -L works properly.";
 
 # Only run these tests if the system sypports symlinks
-if (eval { symlink("",""); 1 }) {
+
+# Apparently the Windows port of Perl reports that it does support symlinks
+# (in that the symlink() function doesn't fail) but it really doesn't, so
+# check for it explicitly.
+
+if ($port_type ne 'W32' && eval { symlink("",""); 1 }) {
 
   # Set up a symlink sym -> dep
   # We'll make both dep and targ older than sym
index 2654b34b32c4d0ea405ebd0e13f9bf35bb86616e..612400fa0db8f7d97d653e571d4b265f64b6fade 100644 (file)
@@ -29,6 +29,7 @@ EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));
 EXTERN_DECL(void process_register, (HANDLE proc));\r
 EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));\r
 EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));\r
+EXTERN_DECL(int process_used_slots, (VOID_DECL));\r
 \r
 /* support routines */\r
 EXTERN_DECL(long process_errno, (HANDLE proc));\r
index ae1a35419d1ece145b1705910baa3e19e9f1e844..6af33bc7a5e2afbd699167e08070c07cc76e814f 100644 (file)
@@ -31,7 +31,7 @@ typedef struct sub_process_t {
 } sub_process;
 
 /* keep track of children so we can implement a waitpid-like routine */
-static sub_process *proc_array[256];
+static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS];
 static int proc_index = 0;
 static int fake_exits_pending = 0;
 
@@ -66,7 +66,7 @@ process_adjust_wait_state(sub_process* pproc)
 static sub_process *
 process_wait_for_any_private(void)
 {
-       HANDLE handles[256];
+       HANDLE handles[MAXIMUM_WAIT_OBJECTS];
        DWORD retval, which;
        int i;
 
@@ -120,7 +120,17 @@ process_kill(HANDLE proc, int signal)
 void
 process_register(HANDLE proc)
 {
-       proc_array[proc_index++] = (sub_process *) proc;
+       if (proc_index < MAXIMUM_WAIT_OBJECTS)
+               proc_array[proc_index++] = (sub_process *) proc;
+}
+
+/*
+ * Return the number of processes that we are still waiting for.
+ */
+int
+process_used_slots(void)
+{
+       return proc_index;
 }
 
 /*
@@ -1169,6 +1179,10 @@ process_easy(
   HANDLE hErr;
   HANDLE hProcess;
 
+  if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
+       DB (DB_JOBS, ("process_easy: All process slots used up\n"));
+       return INVALID_HANDLE_VALUE;
+  }
   if (DuplicateHandle(GetCurrentProcess(),
                       GetStdHandle(STD_INPUT_HANDLE),
                       GetCurrentProcess(),