Changeset 3140 for trunk/src/kmk/w32


Ignore:
Timestamp:
Mar 14, 2018, 10:28:10 PM (7 years ago)
Author:
bird
Message:

kmk: Merged in changes from GNU make 4.2.1 (2e55f5e4abdc0e38c1d64be703b446695e70b3b6 / https://git.savannah.gnu.org/git/make.git).

Location:
trunk/src/kmk
Files:
1 deleted
14 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk

  • trunk/src/kmk/w32/Makefile.am

    r2591 r3140  
    11# Makefile.am to create libw32.a for mingw32 host.
    2 # Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    3 # 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2# Copyright (C) 1997-2016 Free Software Foundation, Inc.
    43# This file is part of GNU Make.
    54#
     
    1716# this program.  If not, see <http://www.gnu.org/licenses/>.
    1817
     18AUTOMAKE_OPTIONS = subdir-objects
     19
    1920noinst_LIBRARIES = libw32.a
    2021
    2122libw32_a_SOURCES =  subproc/misc.c subproc/sub_proc.c subproc/w32err.c \
    22                     pathstuff.c
     23                    compat/posixfcn.c pathstuff.c w32os.c
    2324
    24 libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir)
     25libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) \
     26                    -I$(top_srcdir)/glob
  • trunk/src/kmk/w32/compat/dirent.c

    r2591 r3140  
    11/* Directory entry code for Window platforms.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    3231opendir(const char* pDirName)
    3332{
    34         struct stat sb;
    35         DIR*    pDir;
    36         char*   pEndDirName;
    37         int     nBufferLen;
    38 
    39         /* sanity checks */
    40         if (!pDirName) {
    41                 errno = EINVAL;
    42                 return NULL;
    43         }
    44         if (stat(pDirName, &sb) != 0) {
    45                 errno = ENOENT;
    46                 return NULL;
    47         }
    48         if ((sb.st_mode & S_IFMT) != S_IFDIR) {
    49                 errno = ENOTDIR;
    50                 return NULL;
    51         }
    52 
    53         /* allocate a DIR structure to return */
    54         pDir = (DIR *) malloc(sizeof (DIR));
    55 
    56         if (!pDir)
    57                 return NULL;
    58 
    59         /* input directory name length */
    60         nBufferLen = strlen(pDirName);
    61 
    62         /* copy input directory name to DIR buffer */
    63         strcpy(pDir->dir_pDirectoryName, pDirName);
    64 
    65         /* point to end of the copied directory name */
    66         pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
    67 
    68         /* if directory name did not end in '/' or '\', add '/' */
    69         if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
    70                 pEndDirName++;
    71                 *pEndDirName = '/';
    72         }
    73 
    74         /* now append the wildcard character to the buffer */
    75         pEndDirName++;
    76         *pEndDirName = '*';
    77         pEndDirName++;
    78         *pEndDirName = '\0';
    79 
    80         /* other values defaulted */
    81         pDir->dir_nNumFiles = 0;
    82         pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
    83         pDir->dir_ulCookie = __DIRENT_COOKIE;
     33        struct stat sb;
     34        DIR*    pDir;
     35        char*   pEndDirName;
     36        int     nBufferLen;
     37
     38        /* sanity checks */
     39        if (!pDirName) {
     40                errno = EINVAL;
     41                return NULL;
     42        }
     43        if (stat(pDirName, &sb) != 0) {
     44                errno = ENOENT;
     45                return NULL;
     46        }
     47        if ((sb.st_mode & S_IFMT) != S_IFDIR) {
     48                errno = ENOTDIR;
     49                return NULL;
     50        }
     51
     52        /* allocate a DIR structure to return */
     53        pDir = (DIR *) malloc(sizeof (DIR));
     54
     55        if (!pDir)
     56                return NULL;
     57
     58        /* input directory name length */
     59        nBufferLen = strlen(pDirName);
     60
     61        /* copy input directory name to DIR buffer */
     62        strcpy(pDir->dir_pDirectoryName, pDirName);
     63
     64        /* point to end of the copied directory name */
     65        pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1];
     66
     67        /* if directory name did not end in '/' or '\', add '/' */
     68        if ((*pEndDirName != '/') && (*pEndDirName != '\\')) {
     69                pEndDirName++;
     70                *pEndDirName = '/';
     71        }
     72
     73        /* now append the wildcard character to the buffer */
     74        pEndDirName++;
     75        *pEndDirName = '*';
     76        pEndDirName++;
     77        *pEndDirName = '\0';
     78
     79        /* other values defaulted */
     80        pDir->dir_nNumFiles = 0;
     81        pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
     82        pDir->dir_ulCookie = __DIRENT_COOKIE;
    8483
    8584#ifdef KMK_PRF
    86         fprintf(stderr, "opendir(%s) -> %p\n", pDirName, pDir);
     85        fprintf(stderr, "opendir(%s) -> %p\n", pDirName, pDir);
    8786#endif
    88         return pDir;
     87        return pDir;
    8988}
    9089
     
    9291closedir(DIR *pDir)
    9392{
    94         /* got a valid pointer? */
    95         if (!pDir) {
    96                 errno = EINVAL;
    97                 return;
    98         }
    99 
    100         /* sanity check that this is a DIR pointer */
    101         if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    102                 errno = EINVAL;
    103                 return;
    104         }
    105 
    106         /* close the WINDOWS32 directory handle */
    107         if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
    108                 FindClose(pDir->dir_hDirHandle);
    109 
    110         free(pDir);
    111 
    112         return;
     93        /* got a valid pointer? */
     94        if (!pDir) {
     95                errno = EINVAL;
     96                return;
     97        }
     98
     99        /* sanity check that this is a DIR pointer */
     100        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     101                errno = EINVAL;
     102                return;
     103        }
     104
     105        /* close the WINDOWS32 directory handle */
     106        if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
     107                FindClose(pDir->dir_hDirHandle);
     108
     109        free(pDir);
     110
     111        return;
    113112}
    114113
     
    116115readdir(DIR* pDir)
    117116{
    118         WIN32_FIND_DATA wfdFindData;
    119 
    120         if (!pDir) {
    121                 errno = EINVAL;
    122                 return NULL;
    123         }
    124 
    125         /* sanity check that this is a DIR pointer */
    126         if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    127                 errno = EINVAL;
    128                 return NULL;
    129         }
    130 
    131         if (pDir->dir_nNumFiles == 0) {
    132                 pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
    133                 if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
    134                         return NULL;
    135         } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
    136                         return NULL;
    137 
    138         /* bump count for next call to readdir() or telldir() */
    139         pDir->dir_nNumFiles++;
    140 
    141         /* fill in struct dirent values */
    142         pDir->dir_sdReturn.d_ino = (ino_t)-1;
    143         strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
    144 
    145         return &pDir->dir_sdReturn;
     117        WIN32_FIND_DATA wfdFindData;
     118
     119        if (!pDir) {
     120                errno = EINVAL;
     121                return NULL;
     122        }
     123
     124        /* sanity check that this is a DIR pointer */
     125        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     126                errno = EINVAL;
     127                return NULL;
     128        }
     129
     130        if (pDir->dir_nNumFiles == 0) {
     131                pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData);
     132                if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE)
     133                        return NULL;
     134        } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData))
     135                        return NULL;
     136
     137        /* bump count for next call to readdir() or telldir() */
     138        pDir->dir_nNumFiles++;
     139
     140        /* fill in struct dirent values */
     141        pDir->dir_sdReturn.d_ino = (ino_t)-1;
     142        strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName);
     143
     144        return &pDir->dir_sdReturn;
    146145}
    147146
     
    149148rewinddir(DIR* pDir)
    150149{
    151         if (!pDir) {
    152                 errno = EINVAL;
    153                 return;
    154         }
    155 
    156         /* sanity check that this is a DIR pointer */
    157         if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    158                 errno = EINVAL;
    159                 return;
    160         }
    161 
    162         /* close the WINDOWS32 directory handle */
    163         if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
    164                 if (!FindClose(pDir->dir_hDirHandle))
    165                         errno = EBADF;
    166 
    167         /* reset members which control readdir() */
    168         pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
    169         pDir->dir_nNumFiles = 0;
    170 
    171         return;
     150        if (!pDir) {
     151                errno = EINVAL;
     152                return;
     153        }
     154
     155        /* sanity check that this is a DIR pointer */
     156        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     157                errno = EINVAL;
     158                return;
     159        }
     160
     161        /* close the WINDOWS32 directory handle */
     162        if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE)
     163                if (!FindClose(pDir->dir_hDirHandle))
     164                        errno = EBADF;
     165
     166        /* reset members which control readdir() */
     167        pDir->dir_hDirHandle = INVALID_HANDLE_VALUE;
     168        pDir->dir_nNumFiles = 0;
     169
     170        return;
    172171}
    173172
     
    175174telldir(DIR* pDir)
    176175{
    177         if (!pDir) {
    178                 errno = EINVAL;
    179                 return -1;
    180         }
    181 
    182         /* sanity check that this is a DIR pointer */
    183         if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
    184                 errno = EINVAL;
    185                 return -1;
    186         }
    187 
    188         /* return number of times readdir() called */
    189         return pDir->dir_nNumFiles;
     176        if (!pDir) {
     177                errno = EINVAL;
     178                return -1;
     179        }
     180
     181        /* sanity check that this is a DIR pointer */
     182        if (pDir->dir_ulCookie != __DIRENT_COOKIE) {
     183                errno = EINVAL;
     184                return -1;
     185        }
     186
     187        /* return number of times readdir() called */
     188        return pDir->dir_nNumFiles;
    190189}
    191190
     
    193192seekdir(DIR* pDir, long nPosition)
    194193{
    195         if (!pDir)
    196                 return;
    197 
    198         /* sanity check that this is a DIR pointer */
    199         if (pDir->dir_ulCookie != __DIRENT_COOKIE)
    200                 return;
    201 
    202         /* go back to beginning of directory */
    203         rewinddir(pDir);
    204 
    205         /* loop until we have found position we care about */
    206         for (--nPosition; nPosition && readdir(pDir); nPosition--);
    207 
    208         /* flag invalid nPosition value */
    209         if (nPosition)
    210                 errno = EINVAL;
    211 
    212         return;
    213 }
     194        if (!pDir)
     195                return;
     196
     197        /* sanity check that this is a DIR pointer */
     198        if (pDir->dir_ulCookie != __DIRENT_COOKIE)
     199                return;
     200
     201        /* go back to beginning of directory */
     202        rewinddir(pDir);
     203
     204        /* loop until we have found position we care about */
     205        for (--nPosition; nPosition && readdir(pDir); nPosition--);
     206
     207        /* flag invalid nPosition value */
     208        if (nPosition)
     209                errno = EINVAL;
     210
     211        return;
     212}
  • trunk/src/kmk/w32/imagecache.c

    r2640 r3140  
    2929*   Header Files                                                               *
    3030*******************************************************************************/
    31 #include "make.h"
     31#include "makeint.h"
    3232
    3333#include <Windows.h>
  • trunk/src/kmk/w32/include/dirent.h

    r2702 r3140  
    11/* Windows version of dirent.h
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    3 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    4443struct dirent
    4544{
    46   ino_t d_ino;                  /* unused - no equivalent on WINDOWS32 */
     45  ino_t d_ino;                  /* unused - no equivalent on WINDOWS32 */
    4746  char d_name[NAME_MAX+1];
    4847};
    4948
    5049typedef struct dir_struct {
    51         ULONG   dir_ulCookie;
    52         HANDLE  dir_hDirHandle;
    53         DWORD   dir_nNumFiles;
    54         char    dir_pDirectoryName[NAME_MAX+1];
    55         struct dirent dir_sdReturn;
     50        ULONG   dir_ulCookie;
     51        HANDLE  dir_hDirHandle;
     52        DWORD   dir_nNumFiles;
     53        char    dir_pDirectoryName[NAME_MAX+1];
     54        struct dirent dir_sdReturn;
    5655} DIR;
    5756
  • trunk/src/kmk/w32/include/pathstuff.h

    r2591 r3140  
    11/* Definitions for Windows path manipulation.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    3 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
  • trunk/src/kmk/w32/include/sub_proc.h

    r2912 r3140  
    11/* Definitions for Windows process invocation.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    2221 * Component Name:
    2322 *
    24  * $Date: 2010/07/13 01:20:43 $
     23 * $Date$
    2524 *
    26  * $Source: /sources/make/make/w32/include/sub_proc.h,v $
     25 * $Source$
    2726 *
    28  * $Id: sub_proc.h,v 1.12 2010/07/13 01:20:43 psmith Exp $
     27 * $Id$
    2928 */
    3029
     
    3433EXTERN_DECL(HANDLE process_init, (VOID_DECL));
    3534EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth,
    36         HANDLE stderrh));
     35                                     HANDLE stderrh));
    3736EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp,
    38         char *exec_path, char *as_user));
     37                                 char *exec_path, char *as_user));
    3938EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data,
    40         int stdin_data_len));
     39                                   int stdin_data_len));
    4140#ifndef KMK /* unused */
    4241EXTERN_DECL(long process_file_io, (HANDLE proc));
    4342#endif
    4443EXTERN_DECL(void process_cleanup, (HANDLE proc));
    45 EXTERN_DECL(HANDLE process_wait_for_any, (VOID_DECL));
     44EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus));
    4645EXTERN_DECL(void process_register, (HANDLE proc));
    47 EXTERN_DECL(HANDLE process_easy, (char** argv, char** env));
     46EXTERN_DECL(HANDLE process_easy, (char** argv, char** env,
     47                                  int outfd, int errfd));
    4848EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal));
    4949EXTERN_DECL(int process_used_slots, (VOID_DECL));
     50EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles));
     51
    5052#ifdef KMK
    5153EXTERN_DECL(int process_kmk_register_submit, (HANDLE hEvent, intptr_t clue, pid_t *pPid));
     
    6365EXTERN_DECL(int process_errcnt, (HANDLE proc));
    6466EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3]));
     67EXTERN_DECL(void process_noinherit, (int fildes));
    6568
    6669#endif
  • trunk/src/kmk/w32/include/w32err.h

    r2591 r3140  
    11/* Definitions for Windows error handling.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    2322#endif
    2423
    25 EXTERN_DECL(char * map_windows32_error_to_string, (DWORD error));
     24EXTERN_DECL(const char * map_windows32_error_to_string, (DWORD error));
    2625
    2726#endif /* !_W32ERR_H */
  • trunk/src/kmk/w32/pathstuff.c

    r3060 r3140  
    11/* Path conversion for Windows pathnames.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
    3 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    1615this program.  If not, see <http://www.gnu.org/licenses/>.  */
    1716
    18 #include "make.h"
     17#include "makeint.h"
    1918#include <string.h>
    2019#include <stdlib.h>
     
    3231    char *etok;            /* token separator for old Path */
    3332
    34         /*
    35         * Convert all spaces to delimiters. Note that pathnames which
    36         * contain blanks get trounced here. Use 8.3 format as a workaround.
    37         */
    38         for (etok = Path; etok && *etok; etok++)
    39                 if (isblank ((unsigned char) *etok))
    40                         *etok = to_delim;
    41 
    42         return (convert_Path_to_windows32(Path, to_delim));
     33        /*
     34        * Convert all spaces to delimiters. Note that pathnames which
     35        * contain blanks get trounced here. Use 8.3 format as a workaround.
     36        */
     37        for (etok = Path; etok && *etok; etok++)
     38                if (ISBLANK ((unsigned char) *etok))
     39                        *etok = to_delim;
     40
     41        return (convert_Path_to_windows32(Path, to_delim));
    4342}
    4443
     
    8483                *etok = to_delim;
    8584                p = ++etok;
    86             } else
     85            } else
    8786                p += strlen(p);
    8887        } else {
     
    128127getcwd_fs(char* buf, int len)
    129128{
    130         char *p = getcwd(buf, len);
    131 
    132         if (p) {
    133                 char *q = w32ify(buf, 0);
    134 #if 1  /* bird */
     129        char *p = getcwd(buf, len);
     130
     131        if (p) {
     132                char *q = w32ify(buf, 0);
     133#if 1  /* bird - UPSTREAM? */
    135134                buf[0] = '\0';
    136135                strncat(buf, q, len);
    137136#else  /* !bird */
    138                 strncpy(buf, q, len);
    139 #endif /* !bird */
    140         }
    141 
    142         return p;
     137                strncpy(buf, q, len);
     138#endif
     139        }
     140
     141        return p;
    143142}
    144143
  • trunk/src/kmk/w32/subproc/NMakefile

    r2591 r3140  
    1 # NOTE: If you have no `make' program at all to process this makefile, run
    2 # `build.bat' instead.
     1# NOTE: If you have no 'make' program at all to process this makefile, run
     2# 'build.bat' instead.
    33#
    4 # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    5 # 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     4# Copyright (C) 1996-2016 Free Software Foundation, Inc.
    65# This file is part of GNU Make.
    76#
  • trunk/src/kmk/w32/subproc/misc.c

    r2591 r3140  
    11/* Process handling for Windows
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    2625/*
    2726 * Description:  Convert a NULL string terminated UNIX environment block to
    28  *              an environment block suitable for a windows32 system call
     27 *              an environment block suitable for a windows32 system call
    2928 *
    3029 * Returns:  TRUE= success, FALSE=fail
    3130 *
    3231 * Notes/Dependencies:  the environment block is sorted in case-insensitive
    33  *      order, is double-null terminated, and is a char *, not a char **
     32 *      order, is double-null terminated, and is a char *, not a char **
    3433 */
    3534int _cdecl compare(const void *a1, const void *a2)
    3635{
    37         return _stricoll(*((char**)a1),*((char**)a2));
     36        return _stricoll(*((char**)a1),*((char**)a2));
    3837}
    3938bool_t
    40 arr2envblk(char **arr, char **envblk_out)
     39arr2envblk(char **arr, char **envblk_out, int *envsize_needed)
    4140{
    42         char **tmp;
    43         int size_needed;
    44         int arrcnt;
    45         char *ptr;
     41        char **tmp;
     42        int size_needed;
     43        int arrcnt;
     44        char *ptr;
    4645
    47         arrcnt = 0;
    48         while (arr[arrcnt]) {
    49                 arrcnt++;
    50         }
     46        arrcnt = 0;
     47        while (arr[arrcnt]) {
     48                arrcnt++;
     49        }
    5150
    52         tmp = (char**) calloc(arrcnt + 1, sizeof(char *));
    53         if (!tmp) {
    54                 return FALSE;
    55         }
     51        tmp = (char**) calloc(arrcnt + 1, sizeof(char *));
     52        if (!tmp) {
     53                return FALSE;
     54        }
    5655
    57         arrcnt = 0;
    58         size_needed = 0;
    59         while (arr[arrcnt]) {
    60                 tmp[arrcnt] = arr[arrcnt];
    61                 size_needed += strlen(arr[arrcnt]) + 1;
    62                 arrcnt++;
    63         }
    64         size_needed++;
     56        arrcnt = 0;
     57        size_needed = *envsize_needed = 0;
     58        while (arr[arrcnt]) {
     59                tmp[arrcnt] = arr[arrcnt];
     60                size_needed += strlen(arr[arrcnt]) + 1;
     61                arrcnt++;
     62        }
     63        size_needed++;
     64        *envsize_needed = size_needed;
    6565
    66         qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);
     66        qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare);
    6767
    68         ptr = *envblk_out = calloc(size_needed, 1);
    69         if (!ptr) {
    70                 free(tmp);
    71                 return FALSE;
    72         }
     68        ptr = *envblk_out = calloc(size_needed, 1);
     69        if (!ptr) {
     70                free(tmp);
     71                return FALSE;
     72        }
    7373
    74         arrcnt = 0;
    75         while (tmp[arrcnt]) {
    76                 strcpy(ptr, tmp[arrcnt]);
    77                 ptr += strlen(tmp[arrcnt]) + 1;
    78                 arrcnt++;
    79         }
     74        arrcnt = 0;
     75        while (tmp[arrcnt]) {
     76                strcpy(ptr, tmp[arrcnt]);
     77                ptr += strlen(tmp[arrcnt]) + 1;
     78                arrcnt++;
     79        }
    8080
    81         free(tmp);
    82         return TRUE;
     81        free(tmp);
     82        return TRUE;
    8383}
  • trunk/src/kmk/w32/subproc/proc.h

    r2591 r3140  
    11/* Definitions for Windows
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    2120typedef int bool_t;
    2221
    23 #define E_SCALL         101
    24 #define E_IO            102
    25 #define E_NO_MEM        103
    26 #define E_FORK          104
     22#define E_SCALL         101
     23#define E_IO            102
     24#define E_NO_MEM        103
     25#define E_FORK          104
    2726
    28 extern bool_t arr2envblk(char **arr, char **envblk_out);
     27extern bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed);
    2928
    3029#endif
  • trunk/src/kmk/w32/subproc/sub_proc.c

    r3051 r3140  
    11/* Process handling for Windows.
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    1918#include <stdlib.h>
    2019#include <stdio.h>
     20#include <io.h>         /* for _get_osfhandle */
    2121#ifdef _MSC_VER
    2222# include <stddef.h>    /* for intptr_t */
     
    2424# include <stdint.h>
    2525#endif
     26#include <string.h>
    2627#include <process.h>  /* for msvc _beginthreadex, _endthreadex */
    2728#include <signal.h>
    2829#include <windows.h>
    29 #ifdef KMK
    30 # include <assert.h>
    31 # include "make.h"
    32 # include "kmkbuiltin.h"
    33 #endif
    34 
    35 
     30
     31#include "makeint.h"
     32#include "filedef.h"
     33#include "variable.h"
    3634#include "sub_proc.h"
    3735#include "proc.h"
     
    3937#include "debug.h"
    4038
     39#ifdef KMK
     40# include <assert.h>
     41# include "kmkbuiltin.h"
     42extern void kmk_cache_exec_image(const char *); /* imagecache.c */
     43#endif
     44
    4145static char *make_command_line(char *shell_name, char *exec_path, char **argv);
    42 #ifndef KMK
    43 extern char *xmalloc (unsigned int);
    44 #else
    45 extern void kmk_cache_exec_image(const char *); /* imagecache.c */
    46 #endif
    4746
    4847typedef struct sub_process_t {
    4948#ifdef KMK
    50         enum { kRegular = 0, kSubmit, kSubProcFreed } enmType;
    51         intptr_t clue;
    52 #endif
    53         intptr_t sv_stdin[2];
    54         intptr_t sv_stdout[2];
    55         intptr_t sv_stderr[2];
    56         int using_pipes;
    57         char *inp;
    58         DWORD incnt;
    59         char * volatile outp;
    60         volatile DWORD outcnt;
    61         char * volatile errp;
    62         volatile DWORD errcnt;
    63         pid_t pid;
    64         int exit_code;
    65         int signal;
    66         long last_err;
    67         long lerrno;
     49        enum { kRegular = 0, kSubmit, kSubProcFreed } enmType;
     50        intptr_t clue;
     51#endif
     52        intptr_t sv_stdin[2];
     53        intptr_t sv_stdout[2];
     54        intptr_t sv_stderr[2];
     55        int using_pipes;
     56        char *inp;
     57        DWORD incnt;
     58        char * volatile outp;
     59        volatile DWORD outcnt;
     60        char * volatile errp;
     61        volatile DWORD errcnt;
     62        pid_t pid;
     63        int exit_code;
     64        int signal;
     65        long last_err;
     66        long lerrno;
    6867} sub_process;
    6968
     
    7473static int proc_index = 0;
    7574static int fake_exits_pending = 0;
     75
     76
     77/*
     78 * Fill a HANDLE list with handles to wait for.
     79 */
     80DWORD
     81process_set_handles(HANDLE *handles)
     82{
     83    DWORD count = 0;
     84    int i;
     85
     86    /* Build array of handles to wait for */
     87    for (i = 0; i < proc_index; i++) {
     88        /* Don't wait on child processes that have already finished */
     89        if (fake_exits_pending && proc_array[i]->exit_code)
     90            continue;
     91
     92        handles[count++] = (HANDLE) proc_array[i]->pid;
     93    }
     94
     95    return count;
     96}
    7697
    7798#ifndef KMK /* Inefficient! */
     
    83104process_adjust_wait_state(sub_process* pproc)
    84105{
    85         int i;
    86 
    87         if (!proc_index)
    88                 return;
    89 
    90         for (i = 0; i < proc_index; i++)
    91                 if (proc_array[i]->pid == pproc->pid)
    92                         break;
    93 
    94         if (i < proc_index) {
    95                 proc_index--;
    96                 if (i != proc_index)
    97                         memmove(&proc_array[i], &proc_array[i+1],
    98                                 (proc_index-i) * sizeof(sub_process*));
    99                 proc_array[proc_index] = NULL;
    100         }
    101 }
     106        int i;
     107
     108        if (!proc_index)
     109                return;
     110
     111        for (i = 0; i < proc_index; i++)
     112                if (proc_array[i]->pid == pproc->pid)
     113                        break;
     114
     115        if (i < proc_index) {
     116                proc_index--;
     117                if (i != proc_index)
     118                        memmove(&proc_array[i], &proc_array[i+1],
     119                                (proc_index-i) * sizeof(sub_process*));
     120                proc_array[proc_index] = NULL;
     121        }
     122}
     123
    102124#endif /* !KMK */
    103125
     
    106128 */
    107129static sub_process *
    108 process_wait_for_any_private(void)
    109 {
    110         HANDLE handles[MAXIMUM_WAIT_OBJECTS];
    111         DWORD retval, which;
    112         int i;
    113 
    114         if (!proc_index)
    115                 return NULL;
    116 
    117         /* build array of handles to wait for */
    118         for (i = 0; i < proc_index; i++) {
    119                 handles[i] = (HANDLE) proc_array[i]->pid;
    120 
    121                 if (fake_exits_pending && proc_array[i]->exit_code)
    122                         break;
    123         }
    124 
    125         /* wait for someone to exit */
    126         if (!fake_exits_pending) {
     130process_wait_for_any_private(int block, DWORD* pdwWaitStatus)
     131{
     132        HANDLE handles[MAXIMUM_WAIT_OBJECTS];
     133        DWORD retval, which;
     134        int i;
     135
     136        if (!proc_index)
     137                return NULL;
     138
     139        /* build array of handles to wait for */
     140        for (i = 0; i < proc_index; i++) {
     141                handles[i] = (HANDLE) proc_array[i]->pid;
     142
     143                if (fake_exits_pending && proc_array[i]->exit_code)
     144                        break;
     145        }
     146
     147        /* wait for someone to exit */
     148        if (!fake_exits_pending) {
    127149#ifdef KMK
    128150l_wait_again:
    129151#endif
    130                 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE);
    131                 which = retval - WAIT_OBJECT_0;
    132         } else {
    133                 fake_exits_pending--;
    134                 retval = !WAIT_FAILED;
    135                 which = i;
    136         }
    137 
    138         /* return pointer to process */
    139         if (retval != WAIT_FAILED) {
    140                 sub_process* pproc = proc_array[which];
    141 #ifdef KMK
    142                 if (pproc->enmType == kSubmit) {
    143                     /* Try get the result from kSubmit.c.  This may not succeed if the whole
    144                        result hasn't arrived yet, in which we just restart the wait. */
    145                     if (kSubmitSubProcGetResult(pproc->clue, &pproc->exit_code, &pproc->signal) != 0) {
    146                         goto l_wait_again;
    147                     }
    148                 }
     152                retval = WaitForMultipleObjects(proc_index, handles, FALSE, (block ? INFINITE : 0));
     153                which = retval - WAIT_OBJECT_0;
     154        } else {
     155                fake_exits_pending--;
     156                retval = !WAIT_FAILED;
     157                which = i;
     158        }
     159
     160        /* If the pointer is not NULL, set the wait status result variable. */
     161        if (pdwWaitStatus)
     162            *pdwWaitStatus = retval;
     163
     164        /* return pointer to process */
     165        if ((retval == WAIT_TIMEOUT) || (retval == WAIT_FAILED)) {
     166                return NULL;
     167        }
     168        else {
     169                sub_process* pproc = proc_array[which];
     170#ifdef KMK
     171                if (pproc->enmType == kSubmit) {
     172                        /* Try get the result from kSubmit.c.  This may not succeed if the whole
     173                           result hasn't arrived yet, in which we just restart the wait. */
     174                        if (kSubmitSubProcGetResult(pproc->clue, &pproc->exit_code, &pproc->signal) != 0) {
     175                                goto l_wait_again;
     176                        }
     177                }
    149178#endif
    150179#ifndef KMK /* Inefficient! */
    151                 process_adjust_wait_state(pproc);
     180                process_adjust_wait_state(pproc);
    152181#else
    153                 proc_index--;
    154                 if ((int)which < proc_index)
    155                         proc_array[which] = proc_array[proc_index];
    156                 proc_array[proc_index] = NULL;
    157 #endif
    158                 return pproc;
    159         } else
    160                 return NULL;
     182                proc_index--;
     183                if ((int)which < proc_index)
     184                        proc_array[which] = proc_array[proc_index];
     185                proc_array[proc_index] = NULL;
     186#endif
     187                return pproc;
     188        }
    161189}
    162190
     
    167195 process_kill(HANDLE proc, int signal)
    168196{
    169         sub_process* pproc = (sub_process*) proc;
    170         pproc->signal = signal;
    171 #ifdef KMK
    172         if (pproc->enmType == kRegular) {
    173 #endif
    174         return (TerminateProcess((HANDLE) pproc->pid, signal));
    175 #ifdef KMK
    176         } else if (pproc->enmType == kSubmit) {
    177                 return kSubmitSubProcKill(pproc->clue, signal) == 0;
    178         }
    179         assert(0);
    180         return FALSE;
     197        sub_process* pproc = (sub_process*) proc;
     198#ifdef KMK
     199    if (pproc->enmType == kRegular) {
     200#endif
     201        pproc->signal = signal;
     202        return (TerminateProcess((HANDLE) pproc->pid, signal));
     203#ifdef KMK
     204    } else if (pproc->enmType == kSubmit)
     205        return kSubmitSubProcKill(pproc->clue, signal) == 0;
     206    assert(0);
     207    return FALSE;
    181208#endif
    182209}
     
    192219{
    193220#ifdef KMK
    194         assert(((sub_process *)proc)->enmType == kRegular);
    195 #endif
    196         if (proc_index < MAXIMUM_WAIT_OBJECTS)
    197                 proc_array[proc_index++] = (sub_process *) proc;
     221        assert(((sub_process *)proc)->enmType == kRegular);
     222#endif
     223        if (proc_index < MAXIMUM_WAIT_OBJECTS)
     224                proc_array[proc_index++] = (sub_process *) proc;
    198225}
    199226
     
    255282process_used_slots(void)
    256283{
    257         return proc_index;
     284        return proc_index;
    258285}
    259286
     
    263290 * you must do 1 of things:
    264291 *
    265  *      x = process_easy(...);
     292 *      x = process_easy(...);
    266293 *
    267294 * or
    268295 *
    269  *      x = process_init_fd();
    270  *      process_register(x);
     296 *      x = process_init_fd();
     297 *      process_register(x);
    271298 *
    272299 * or
    273300 *
    274  *      x = process_init();
    275  *      process_register(x);
     301 *      x = process_init();
     302 *      process_register(x);
    276303 *
    277304 * You must NOT then call process_pipe_io() because this function is
     
    281308
    282309HANDLE
    283 process_wait_for_any(void)
    284 {
    285         sub_process* pproc = process_wait_for_any_private();
    286 
    287         if (!pproc)
    288                 return NULL;
    289         else {
    290                 /*
    291                 * Ouch! can't tell caller if this fails directly. Caller
    292                 * will have to use process_last_err()
    293                 */
    294 #ifdef KMK
    295                 /* Invalidate negative directory cache entries now that a
    296                    job has completed and possibly created new files that
    297                    was missing earlier. */
    298                 dir_cache_invalid_after_job ();
    299 
    300                 if (pproc->enmType == kRegular) {
    301                     (void)process_file_io_private(pproc, FALSE);
    302                 }
     310process_wait_for_any(int block, DWORD* pdwWaitStatus)
     311{
     312        sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus);
     313
     314        if (!pproc)
     315                return NULL;
     316        else {
     317                /*
     318                * Ouch! can't tell caller if this fails directly. Caller
     319                * will have to use process_last_err()
     320                */
     321#ifdef KMK
     322                /* Invalidate negative directory cache entries now that a
     323                   job has completed and possibly created new files that
     324                   was missing earlier. */
     325                dir_cache_invalid_after_job ();
     326
     327                if (pproc->enmType == kRegular) {
     328                        (void)process_file_io_private(pproc, FALSE);
     329                }
    303330#else
    304                 (void) process_file_io(pproc);
    305 #endif
    306                 return ((HANDLE) pproc);
    307         }
     331                (void) process_file_io(pproc);
     332#endif
     333                return ((HANDLE) pproc);
     334        }
    308335}
    309336
     
    319346{
    320347        if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE;
    321         return (((sub_process *)proc)->last_err);
     348        return (((sub_process *)proc)->last_err);
    322349}
    323350
     
    326353{
    327354        if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE;
    328         return (((sub_process *)proc)->exit_code);
     355        return (((sub_process *)proc)->exit_code);
     356}
     357
     358void
     359process_noinherit(int fd)
     360{
     361  HANDLE fh = (HANDLE)_get_osfhandle(fd);
     362
     363  if (fh && fh != INVALID_HANDLE_VALUE)
     364        SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0);
    329365}
    330366
     
    339375process_outbuf(HANDLE proc)
    340376{
    341         return (((sub_process *)proc)->outp);
     377        return (((sub_process *)proc)->outp);
    342378}
    343379
     
    345381process_errbuf(HANDLE proc)
    346382{
    347         return (((sub_process *)proc)->errp);
     383        return (((sub_process *)proc)->errp);
    348384}
    349385
     
    351387process_outcnt(HANDLE proc)
    352388{
    353         return (((sub_process *)proc)->outcnt);
     389        return (((sub_process *)proc)->outcnt);
    354390}
    355391
     
    357393process_errcnt(HANDLE proc)
    358394{
    359         return (((sub_process *)proc)->errcnt);
     395        return (((sub_process *)proc)->errcnt);
    360396}
    361397
     
    363399process_pipes(HANDLE proc, int pipes[3])
    364400{
    365         pipes[0] = ((sub_process *)proc)->sv_stdin[0];
    366         pipes[1] = ((sub_process *)proc)->sv_stdout[0];
    367         pipes[2] = ((sub_process *)proc)->sv_stderr[0];
    368         return;
     401        pipes[0] = ((sub_process *)proc)->sv_stdin[0];
     402        pipes[1] = ((sub_process *)proc)->sv_stdout[0];
     403        pipes[2] = ((sub_process *)proc)->sv_stderr[0];
     404        return;
    369405}
    370406*/
    371407
    372         HANDLE
     408        HANDLE
    373409process_init()
    374410{
    375         sub_process *pproc;
    376         /*
    377         * open file descriptors for attaching stdin/stdout/sterr
    378         */
    379         HANDLE stdin_pipes[2];
    380         HANDLE stdout_pipes[2];
    381         HANDLE stderr_pipes[2];
    382         SECURITY_ATTRIBUTES inherit;
    383         BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
    384 
    385         pproc = malloc(sizeof(*pproc));
    386         memset(pproc, 0, sizeof(*pproc));
    387 
    388         /* We can't use NULL for lpSecurityDescriptor because that
    389            uses the default security descriptor of the calling process.
    390            Instead we use a security descriptor with no DACL.  This
    391            allows nonrestricted access to the associated objects. */
    392 
    393         if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
    394                                           SECURITY_DESCRIPTOR_REVISION)) {
    395                 pproc->last_err = GetLastError();
    396                 pproc->lerrno = E_SCALL;
    397                 return((HANDLE)pproc);
    398         }
    399 
    400         inherit.nLength = sizeof(inherit);
    401         inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
    402         inherit.bInheritHandle = TRUE;
    403 
    404         // By convention, parent gets pipe[0], and child gets pipe[1]
    405         // This means the READ side of stdin pipe goes into pipe[1]
    406         // and the WRITE side of the stdout and stderr pipes go into pipe[1]
    407         if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
    408         CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
    409         CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
    410 
    411                 pproc->last_err = GetLastError();
    412                 pproc->lerrno = E_SCALL;
    413                 return((HANDLE)pproc);
    414         }
    415 
    416         //
    417         // Mark the parent sides of the pipes as non-inheritable
    418         //
    419         if (SetHandleInformation(stdin_pipes[0],
    420                                 HANDLE_FLAG_INHERIT, 0) == FALSE ||
    421                 SetHandleInformation(stdout_pipes[0],
    422                                 HANDLE_FLAG_INHERIT, 0) == FALSE ||
    423                 SetHandleInformation(stderr_pipes[0],
    424                                 HANDLE_FLAG_INHERIT, 0) == FALSE) {
    425 
    426                 pproc->last_err = GetLastError();
    427                 pproc->lerrno = E_SCALL;
    428                 return((HANDLE)pproc);
    429         }
    430         pproc->sv_stdin[0]  = (intptr_t) stdin_pipes[0];
    431         pproc->sv_stdin[1]  = (intptr_t) stdin_pipes[1];
    432         pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
    433         pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
    434         pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
    435         pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
    436 
    437         pproc->using_pipes = 1;
    438 
    439         pproc->lerrno = 0;
    440 
    441         return((HANDLE)pproc);
    442 }
    443 
    444 
    445         HANDLE
     411        sub_process *pproc;
     412        /*
     413        * open file descriptors for attaching stdin/stdout/sterr
     414        */
     415        HANDLE stdin_pipes[2];
     416        HANDLE stdout_pipes[2];
     417        HANDLE stderr_pipes[2];
     418        SECURITY_ATTRIBUTES inherit;
     419        BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
     420
     421        pproc = malloc(sizeof(*pproc));
     422        memset(pproc, 0, sizeof(*pproc));
     423
     424        /* We can't use NULL for lpSecurityDescriptor because that
     425           uses the default security descriptor of the calling process.
     426           Instead we use a security descriptor with no DACL.  This
     427           allows nonrestricted access to the associated objects. */
     428
     429        if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd),
     430                                          SECURITY_DESCRIPTOR_REVISION)) {
     431                pproc->last_err = GetLastError();
     432                pproc->lerrno = E_SCALL;
     433                return((HANDLE)pproc);
     434        }
     435
     436        inherit.nLength = sizeof(inherit);
     437        inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd);
     438        inherit.bInheritHandle = TRUE;
     439
     440        // By convention, parent gets pipe[0], and child gets pipe[1]
     441        // This means the READ side of stdin pipe goes into pipe[1]
     442        // and the WRITE side of the stdout and stderr pipes go into pipe[1]
     443        if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE ||
     444        CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE ||
     445        CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) {
     446
     447                pproc->last_err = GetLastError();
     448                pproc->lerrno = E_SCALL;
     449                return((HANDLE)pproc);
     450        }
     451
     452        //
     453        // Mark the parent sides of the pipes as non-inheritable
     454        //
     455        if (SetHandleInformation(stdin_pipes[0],
     456                                HANDLE_FLAG_INHERIT, 0) == FALSE ||
     457                SetHandleInformation(stdout_pipes[0],
     458                                HANDLE_FLAG_INHERIT, 0) == FALSE ||
     459                SetHandleInformation(stderr_pipes[0],
     460                                HANDLE_FLAG_INHERIT, 0) == FALSE) {
     461
     462                pproc->last_err = GetLastError();
     463                pproc->lerrno = E_SCALL;
     464                return((HANDLE)pproc);
     465        }
     466        pproc->sv_stdin[0]  = (intptr_t) stdin_pipes[0];
     467        pproc->sv_stdin[1]  = (intptr_t) stdin_pipes[1];
     468        pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0];
     469        pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1];
     470        pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0];
     471        pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1];
     472
     473        pproc->using_pipes = 1;
     474
     475        pproc->lerrno = 0;
     476
     477        return((HANDLE)pproc);
     478}
     479
     480
     481        HANDLE
    446482process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh)
    447483{
    448         sub_process *pproc;
    449 
    450         pproc = malloc(sizeof(*pproc));
    451         memset(pproc, 0, sizeof(*pproc));
    452 
    453         /*
    454          * Just pass the provided file handles to the 'child side' of the
    455          * pipe, bypassing pipes altogether.
    456          */
    457         pproc->sv_stdin[1]  = (intptr_t) stdinh;
    458         pproc->sv_stdout[1] = (intptr_t) stdouth;
    459         pproc->sv_stderr[1] = (intptr_t) stderrh;
    460 
    461         pproc->last_err = pproc->lerrno = 0;
    462 
    463         return((HANDLE)pproc);
     484        sub_process *pproc;
     485
     486        pproc = malloc(sizeof(*pproc));
     487        if (pproc) {
     488                memset(pproc, 0, sizeof(*pproc));
     489
     490                /*
     491                 * Just pass the provided file handles to the 'child
     492                 * side' of the pipe, bypassing pipes altogether.
     493                 */
     494                pproc->sv_stdin[1]  = (intptr_t) stdinh;
     495                pproc->sv_stdout[1] = (intptr_t) stdouth;
     496                pproc->sv_stderr[1] = (intptr_t) stderrh;
     497
     498                pproc->last_err = pproc->lerrno = 0;
     499        }
     500
     501        return((HANDLE)pproc);
    464502}
    465503
     
    467505static HANDLE
    468506find_file(const char *exec_path, const char *path_var,
    469           char *full_fname, DWORD full_len)
    470 {
    471         HANDLE exec_handle;
    472         char *fname;
    473         char *ext;
    474         DWORD req_len;
    475         int i;
    476         static const char *extensions[] =
    477           /* Should .com come before no-extension case?  */
    478           { ".exe", ".cmd", ".bat", "", ".com", NULL };
    479 
    480         fname = xmalloc(strlen(exec_path) + 5);
    481         strcpy(fname, exec_path);
    482         ext = fname + strlen(fname);
    483 
    484         for (i = 0; extensions[i]; i++) {
    485                 strcpy(ext, extensions[i]);
    486                 if (((req_len = SearchPath (path_var, fname, NULL, full_len,
    487                                             full_fname, NULL)) > 0
    488                      /* For compatibility with previous code, which
    489                         used OpenFile, and with Windows operation in
    490                         general, also look in various default
    491                         locations, such as Windows directory and
    492                         Windows System directory.  Warning: this also
    493                         searches PATH in the Make's environment, which
    494                         might not be what the Makefile wants, but it
    495                         seems to be OK as a fallback, after the
    496                         previous SearchPath failed to find on child's
    497                         PATH.  */
    498                      || (req_len = SearchPath (NULL, fname, NULL, full_len,
    499                                                full_fname, NULL)) > 0)
    500                     && req_len <= full_len
    501                     && (exec_handle =
    502                                 CreateFile(full_fname,
    503                                            GENERIC_READ,
    504                                            FILE_SHARE_READ | FILE_SHARE_WRITE,
    505                                            NULL,
    506                                            OPEN_EXISTING,
    507                                            FILE_ATTRIBUTE_NORMAL,
    508                                            NULL)) != INVALID_HANDLE_VALUE) {
    509                         free(fname);
    510                         return(exec_handle);
    511                 }
    512         }
    513 
    514         free(fname);
    515         return INVALID_HANDLE_VALUE;
     507          char *full_fname, DWORD full_len)
     508{
     509        HANDLE exec_handle;
     510        char *fname;
     511        char *ext;
     512        DWORD req_len;
     513        int i;
     514        static const char *extensions[] =
     515          /* Should .com come before no-extension case?  */
     516          { ".exe", ".cmd", ".bat", "", ".com", NULL };
     517
     518        fname = xmalloc(strlen(exec_path) + 5);
     519        strcpy(fname, exec_path);
     520        ext = fname + strlen(fname);
     521
     522        for (i = 0; extensions[i]; i++) {
     523                strcpy(ext, extensions[i]);
     524                if (((req_len = SearchPath (path_var, fname, NULL, full_len,
     525                                            full_fname, NULL)) > 0
     526                     /* For compatibility with previous code, which
     527                        used OpenFile, and with Windows operation in
     528                        general, also look in various default
     529                        locations, such as Windows directory and
     530                        Windows System directory.  Warning: this also
     531                        searches PATH in the Make's environment, which
     532                        might not be what the Makefile wants, but it
     533                        seems to be OK as a fallback, after the
     534                        previous SearchPath failed to find on child's
     535                        PATH.  */
     536                     || (req_len = SearchPath (NULL, fname, NULL, full_len,
     537                                               full_fname, NULL)) > 0)
     538                    && req_len <= full_len
     539                    && (exec_handle =
     540                                CreateFile(full_fname,
     541                                           GENERIC_READ,
     542                                           FILE_SHARE_READ | FILE_SHARE_WRITE,
     543                                           NULL,
     544                                           OPEN_EXISTING,
     545                                           FILE_ATTRIBUTE_NORMAL,
     546                                           NULL)) != INVALID_HANDLE_VALUE) {
     547                        free(fname);
     548                        return(exec_handle);
     549                }
     550        }
     551
     552        free(fname);
     553        return INVALID_HANDLE_VALUE;
     554}
     555
     556/*
     557 * Return non-zero of FNAME specifies a batch file and its name
     558 * includes embedded whitespace.
     559 */
     560
     561static int
     562batch_file_with_spaces(const char *fname)
     563{
     564        size_t fnlen = strlen(fname);
     565
     566        return (fnlen > 4
     567                && (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0
     568                    || _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0)
     569                /* The set of characters in the 2nd arg to strpbrk
     570                   should be the same one used by make_command_line
     571                   below to decide whether an argv[] element needs
     572                   quoting.  */
     573                && strpbrk(fname, " \t") != NULL);
    516574}
    517575
     
    526584long
    527585process_begin(
    528         HANDLE proc,
    529         char **argv,
    530         char **envp,
    531         char *exec_path,
    532         char *as_user)
    533 {
    534         sub_process *pproc = (sub_process *)proc;
    535         char *shell_name = 0;
    536         int file_not_found=0;
    537         HANDLE exec_handle;
    538         char exec_fname[MAX_PATH];
    539         const char *path_var = NULL;
    540         char **ep;
    541         char buf[256];
    542         DWORD bytes_returned;
    543         DWORD flags;
    544         char *command_line;
    545         STARTUPINFO startInfo;
    546         PROCESS_INFORMATION procInfo;
    547         char *envblk=NULL;
     586        HANDLE proc,
     587        char **argv,
     588        char **envp,
     589        char *exec_path,
     590        char *as_user)
     591{
     592        sub_process *pproc = (sub_process *)proc;
     593        char *shell_name = 0;
     594        int file_not_found=0;
     595        HANDLE exec_handle;
     596        char exec_fname[MAX_PATH];
     597        const char *path_var = NULL;
     598        char **ep;
     599        char buf[MAX_PATH];
     600        DWORD bytes_returned;
     601        DWORD flags;
     602        char *command_line;
     603        STARTUPINFO startInfo;
     604        PROCESS_INFORMATION procInfo;
     605        char *envblk=NULL;
     606        int envsize_needed = 0;
     607        int pass_null_exec_path = 0;
    548608#ifdef KMK
    549609        size_t exec_path_len;
     
    552612        assert (pproc->enmType == kRegular);
    553613#endif
    554 
    555614
    556615        /*
     
    574633        else {
    575634#endif /* KMK */
    576                 /* Use the Makefile's value of PATH to look for the program to
    577                    execute, because it could be different from Make's PATH
    578                    (e.g., if the target sets its own value.  */
    579                 if (envp)
    580                         for (ep = envp; *ep; ep++) {
    581                                 if (strncmp (*ep, "PATH=", 5) == 0
    582                                     || strncmp (*ep, "Path=", 5) == 0) {
    583                                         path_var = *ep + 5;
    584                                         break;
    585                                 }
    586                         }
    587                 exec_handle = find_file(exec_path, path_var,
    588                                         exec_fname, sizeof(exec_fname));
    589 #ifdef KMK
    590         }
    591 #endif
    592 
    593         /*
    594          * If we couldn't open the file, just assume that Windows will be
    595          * somehow able to find and execute it.
    596          */
    597         if (exec_handle == INVALID_HANDLE_VALUE) {
    598                 file_not_found++;
    599         }
    600         else {
    601                 /* Attempt to read the first line of the file */
    602                 if (ReadFile( exec_handle,
    603                                 buf, sizeof(buf) - 1, /* leave room for trailing NULL */
    604                                 &bytes_returned, 0) == FALSE || bytes_returned < 2) {
    605 
    606                         pproc->last_err = GetLastError();
    607                         pproc->lerrno = E_IO;
    608                         CloseHandle(exec_handle);
    609                         return(-1);
    610                 }
    611                 if (buf[0] == '#' && buf[1] == '!') {
    612                         /*
    613                          *  This is a shell script...  Change the command line from
    614                          *      exec_path args to shell_name exec_path args
    615                          */
    616                         char *p;
    617 
    618                         /*  Make sure buf is NULL terminated */
    619                         buf[bytes_returned] = 0;
    620                         /*
    621                          * Depending on the file system type, etc. the first line
    622                          * of the shell script may end with newline or newline-carriage-return
    623                          * Whatever it ends with, cut it off.
    624                          */
    625                         p= strchr(buf, '\n');
    626                         if (p)
    627                                 *p = 0;
    628                         p = strchr(buf, '\r');
    629                         if (p)
    630                                 *p = 0;
    631 
    632                         /*
    633                          *  Find base name of shell
    634                          */
    635                         shell_name = strrchr( buf, '/');
    636                         if (shell_name) {
    637                                 shell_name++;
    638                         } else {
    639                                 shell_name = &buf[2];/* skipping "#!" */
    640                         }
    641 
    642                 }
    643                 CloseHandle(exec_handle);
    644         }
    645 
    646         flags = 0;
    647 
    648         if (file_not_found)
    649                 command_line = make_command_line( shell_name, exec_path, argv);
    650         else
    651                 command_line = make_command_line( shell_name, exec_fname, argv);
    652 
    653         if ( command_line == NULL ) {
    654                 pproc->last_err = 0;
    655                 pproc->lerrno = E_NO_MEM;
    656                 return(-1);
    657         }
    658 
    659         if (envp) {
    660                 if (arr2envblk(envp, &envblk) ==FALSE) {
    661                         pproc->last_err = 0;
    662                         pproc->lerrno = E_NO_MEM;
    663                         free( command_line );
    664                         return(-1);
    665                 }
    666         }
    667 
    668         if ((shell_name) || (file_not_found)) {
    669                 exec_path = 0;  /* Search for the program in %Path% */
    670         } else {
    671                 exec_path = exec_fname;
    672         }
    673 
    674         /*
    675          *  Set up inherited stdin, stdout, stderr for child
    676          */
    677         GetStartupInfo(&startInfo);
     635
     636        /* Use the Makefile's value of PATH to look for the program to
     637           execute, because it could be different from Make's PATH
     638           (e.g., if the target sets its own value.  */
     639        if (envp)
     640                for (ep = envp; *ep; ep++) {
     641                        if (strncmp (*ep, "PATH=", 5) == 0
     642                            || strncmp (*ep, "Path=", 5) == 0) {
     643                                path_var = *ep + 5;
     644                                break;
     645                        }
     646                }
     647        exec_handle = find_file(exec_path, path_var,
     648                                exec_fname, sizeof(exec_fname));
     649#ifdef KMK
     650        }
     651#endif
     652
     653        /*
     654         * If we couldn't open the file, just assume that Windows will be
     655         * somehow able to find and execute it.  If the first character
     656         * of the command is '/', assume they set SHELL to a Unixy shell
     657         * that have some magic mounts known only to it, and run the whole
     658         * command via $SHELL -c "COMMAND" instead.
     659         */
     660        if (exec_handle == INVALID_HANDLE_VALUE) {
     661                if (exec_path[0] == '/') {
     662                        char *new_argv0;
     663                        char **argvi = argv;
     664                        int arglen = 0;
     665
     666                        strcpy(buf, variable_expand ("$(SHELL)"));
     667                        shell_name = &buf[0];
     668                        strcpy(exec_fname, "-c");
     669                        /* Construct a single command string in argv[0].  */
     670                        while (*argvi) {
     671                                arglen += strlen(*argvi) + 1;
     672                                argvi++;
     673                        }
     674                        new_argv0 = xmalloc(arglen + 1);
     675                        new_argv0[0] = '\0';
     676                        for (argvi = argv; *argvi; argvi++) {
     677                                strcat(new_argv0, *argvi);
     678                                strcat(new_argv0, " ");
     679                        }
     680                        /* Remove the extra blank at the end.  */
     681                        new_argv0[arglen-1] = '\0';
     682                        free(argv[0]);
     683                        argv[0] = new_argv0;
     684                        argv[1] = NULL;
     685                }
     686                else
     687                        file_not_found++;
     688        }
     689        else {
     690                /* Attempt to read the first line of the file */
     691                if (ReadFile( exec_handle,
     692                                buf, sizeof(buf) - 1, /* leave room for trailing NULL */
     693                                &bytes_returned, 0) == FALSE || bytes_returned < 2) {
     694
     695                        pproc->last_err = GetLastError();
     696                        pproc->lerrno = E_IO;
     697                        CloseHandle(exec_handle);
     698                        return(-1);
     699                }
     700                if (buf[0] == '#' && buf[1] == '!') {
     701                        /*
     702                         *  This is a shell script...  Change the command line from
     703                         *      exec_path args to shell_name exec_path args
     704                         */
     705                        char *p;
     706
     707                        /*  Make sure buf is NULL terminated */
     708                        buf[bytes_returned] = 0;
     709                        /*
     710                         * Depending on the file system type, etc. the first line
     711                         * of the shell script may end with newline or newline-carriage-return
     712                         * Whatever it ends with, cut it off.
     713                         */
     714                        p= strchr(buf, '\n');
     715                        if (p)
     716                                *p = 0;
     717                        p = strchr(buf, '\r');
     718                        if (p)
     719                                *p = 0;
     720
     721                        /*
     722                         *  Find base name of shell
     723                         */
     724                        shell_name = strrchr( buf, '/');
     725                        if (shell_name) {
     726                                shell_name++;
     727                        } else {
     728                                shell_name = &buf[2];/* skipping "#!" */
     729                        }
     730
     731                }
     732                CloseHandle(exec_handle);
     733        }
     734
     735        flags = 0;
     736
     737        if (file_not_found)
     738                command_line = make_command_line( shell_name, exec_path, argv);
     739        else {
     740                /* If exec_fname includes whitespace, CreateProcess
     741                   behaves erratically and unreliably, and often fails
     742                   if argv[0] also includes whitespace (and thus will
     743                   be quoted by make_command_line below).  So in that
     744                   case, we don't pass exec_fname as the 1st arg to
     745                   CreateProcess, but instead replace argv[0] with
     746                   exec_fname (to keep its leading directories and
     747                   extension as found by find_file), and pass NULL to
     748                   CreateProcess as its 1st arg.  This works around
     749                   the bugs in CreateProcess, which are probably
     750                   caused by its passing the command to cmd.exe with
     751                   some incorrect quoting.  */
     752                if (!shell_name
     753                    && batch_file_with_spaces(exec_fname)
     754                    && _stricmp(exec_path, argv[0]) == 0) {
     755                        char *new_argv, *p;
     756                        char **argvi;
     757                        int arglen, i;
     758                        pass_null_exec_path = 1;
     759                        /* Rewrite argv[] replacing argv[0] with exec_fname.  */
     760                        for (argvi = argv + 1, arglen = strlen(exec_fname) + 1;
     761                             *argvi;
     762                             argvi++) {
     763                                arglen += strlen(*argvi) + 1;
     764                        }
     765                        new_argv = xmalloc(arglen);
     766                        p = strcpy(new_argv, exec_fname) + strlen(exec_fname) + 1;
     767                        for (argvi = argv + 1, i = 1; *argvi; argvi++, i++) {
     768                                strcpy(p, *argvi);
     769                                argv[i] = p;
     770                                p += strlen(*argvi) + 1;
     771                        }
     772                        argv[i] = NULL;
     773                        free (argv[0]);
     774                        argv[0] = new_argv;
     775                }
     776                command_line = make_command_line( shell_name, exec_fname, argv);
     777        }
     778
     779        if ( command_line == NULL ) {
     780                pproc->last_err = 0;
     781                pproc->lerrno = E_NO_MEM;
     782                return(-1);
     783        }
     784
     785        if (envp) {
     786                if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) {
     787                        pproc->lerrno = E_NO_MEM;
     788                        free( command_line );
     789                        if ((pproc->last_err == ERROR_INVALID_PARAMETER
     790                             || pproc->last_err == ERROR_MORE_DATA)
     791                            && envsize_needed > 32*1024) {
     792                                fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n",
     793                                         envsize_needed);
     794                        }
     795                        pproc->last_err = 0;
     796                        return(-1);
     797                }
     798        }
     799
     800        if (shell_name || file_not_found || pass_null_exec_path) {
     801                exec_path = 0;  /* Search for the program in %Path% */
     802        } else {
     803                exec_path = exec_fname;
     804        }
     805
     806        /*
     807         *  Set up inherited stdin, stdout, stderr for child
     808         */
     809        memset(&startInfo, '\0', sizeof(startInfo));
     810        GetStartupInfo(&startInfo);
    678811#ifndef KMK
    679         startInfo.dwFlags = STARTF_USESTDHANDLES;
    680 #endif
    681         startInfo.lpReserved = 0;
    682         startInfo.cbReserved2 = 0;
    683         startInfo.lpReserved2 = 0;
    684         startInfo.lpTitle = shell_name ? shell_name : exec_path;
     812        startInfo.dwFlags = STARTF_USESTDHANDLES;
     813#endif
     814        startInfo.lpReserved = 0;
     815        startInfo.cbReserved2 = 0;
     816        startInfo.lpReserved2 = 0;
    685817#ifndef KMK
    686         startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
    687         startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
    688         startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
     818        startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
     819        startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
     820        startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
    689821#else
    690         if (    pproc->sv_stdin[1]
    691                 ||  pproc->sv_stdout[1]
    692                 ||  pproc->sv_stderr[1]) {
    693                 startInfo.dwFlags = STARTF_USESTDHANDLES;
    694                 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
    695                 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
    696                 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
    697         } else {
    698                 startInfo.dwFlags = 0;
    699                 startInfo.hStdInput = 0;
    700                 startInfo.hStdOutput = 0;
    701                 startInfo.hStdError = 0;
    702         }
    703 #endif
    704 
    705         if (as_user) {
    706                 if (envblk) free(envblk);
    707                 return -1;
    708         } else {
    709                 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
    710                         exec_path ? exec_path : "NULL",
    711                         command_line ? command_line : "NULL"));
     822        if (   ((HANDLE)pproc->sv_stdin[1]  != INVALID_HANDLE_VALUE && pproc->sv_stdin[1])
     823            || ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE && pproc->sv_stdout[1])
     824            || ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE && pproc->sv_stderr[1]) ) {
     825                startInfo.dwFlags = STARTF_USESTDHANDLES;
     826                startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1];
     827                startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1];
     828                startInfo.hStdError = (HANDLE)pproc->sv_stderr[1];
     829        } else {
     830                startInfo.dwFlags = 0;
     831                startInfo.hStdInput = 0;
     832                startInfo.hStdOutput = 0;
     833                startInfo.hStdError = 0;
     834        }
     835#endif
     836
     837        if (as_user) {
     838                free(envblk);
     839                return -1;
     840        } else {
     841                DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n",
     842                        exec_path ? exec_path : "NULL",
     843                        command_line ? command_line : "NULL"));
    712844#ifdef KMK
    713845                if (exec_fname[0])
     
    726858                }
    727859#endif
    728                 if (CreateProcess(
    729                         exec_path,
    730                         command_line,
    731                         NULL,
    732                         0, /* default security attributes for thread */
    733                         TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
    734                         flags,
    735                         envblk,
    736                         0, /* default starting directory */
    737                         &startInfo,
    738                         &procInfo) == FALSE) {
    739 
    740                         pproc->last_err = GetLastError();
    741                         pproc->lerrno = E_FORK;
    742 #ifdef KMK
    743                         if (pproc->last_err == ERROR_FILE_NOT_FOUND)
    744                                 pproc->exit_code = 127; /* see execve failure in job.c. */
    745 #endif
    746                         fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
     860                if (CreateProcess(
     861                        exec_path,
     862                        command_line,
     863                        NULL,
     864                        0, /* default security attributes for thread */
     865                        TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */
     866                        flags,
     867                        envblk,
     868                        0, /* default starting directory */
     869                        &startInfo,
     870                        &procInfo) == FALSE) {
     871
     872                        pproc->last_err = GetLastError();
     873                        pproc->lerrno = E_FORK;
     874                        fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n",
    747875                                exec_path ? exec_path : "NULL", command_line);
    748                         if (envblk) free(envblk);
    749                         free( command_line );
    750                         return(-1);
    751                 }
    752 #ifdef KMK
    753                 switch (process_priority) {
    754                 case 1: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_IDLE); break;
    755                 case 2: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break;
    756                 case 3: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_NORMAL); break;
    757                 case 4: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_HIGHEST); break;
    758                 case 5: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break;
    759                 }
    760                 ResumeThread(procInfo.hThread);
    761 #endif
    762         }
    763 
    764         pproc->pid = (pid_t)procInfo.hProcess;
    765         /* Close the thread handle -- we'll just watch the process */
    766         CloseHandle(procInfo.hThread);
    767 
    768         /* Close the halves of the pipes we don't need */
    769 #ifndef KMK
    770         CloseHandle((HANDLE)pproc->sv_stdin[1]);
    771         CloseHandle((HANDLE)pproc->sv_stdout[1]);
    772         CloseHandle((HANDLE)pproc->sv_stderr[1]);
    773         pproc->sv_stdin[1] = 0;
    774         pproc->sv_stdout[1] = 0;
    775         pproc->sv_stderr[1] = 0;
    776 #else
    777         if ((HANDLE)pproc->sv_stdin[1]) {
    778                 CloseHandle((HANDLE)pproc->sv_stdin[1]);
    779                 pproc->sv_stdin[1] = 0;
    780         }
    781         if ((HANDLE)pproc->sv_stdout[1]) {
    782                 CloseHandle((HANDLE)pproc->sv_stdout[1]);
    783                 pproc->sv_stdout[1] = 0;
    784         }
    785         if ((HANDLE)pproc->sv_stderr[1]) {
    786                 CloseHandle((HANDLE)pproc->sv_stderr[1]);
    787                 pproc->sv_stderr[1] = 0;
    788         }
    789 #endif
    790 
    791         free( command_line );
    792         if (envblk) free(envblk);
    793         pproc->lerrno=0;
    794         return 0;
    795 }
    796 
    797 
    798 
     876                        free(envblk);
     877                        free( command_line );
     878                        return(-1);
     879                }
     880#ifdef KMK
     881                switch (process_priority) {
     882                case 1: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_IDLE); break;
     883                case 2: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_BELOW_NORMAL); break;
     884                case 3: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_NORMAL); break;
     885                case 4: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_HIGHEST); break;
     886                case 5: SetThreadPriority(procInfo.hThread, THREAD_PRIORITY_TIME_CRITICAL); break;
     887                }
     888                ResumeThread(procInfo.hThread);
     889#endif
     890        }
     891
     892        pproc->pid = (pid_t)procInfo.hProcess;
     893        /* Close the thread handle -- we'll just watch the process */
     894        CloseHandle(procInfo.hThread);
     895
     896        /* Close the halves of the pipes we don't need */
     897        if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE && pproc->sv_stdin[1])
     898          CloseHandle((HANDLE)pproc->sv_stdin[1]);
     899        if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE && pproc->sv_stdout[1])
     900          CloseHandle((HANDLE)pproc->sv_stdout[1]);
     901        if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE && pproc->sv_stderr[1])
     902          CloseHandle((HANDLE)pproc->sv_stderr[1]);
     903        pproc->sv_stdin[1] = 0;
     904        pproc->sv_stdout[1] = 0;
     905        pproc->sv_stderr[1] = 0;
     906
     907        free( command_line );
     908        free(envblk);
     909        pproc->lerrno=0;
     910        return 0;
     911}
     912
     913
     914
     915#if 0   /* unused */
    799916static DWORD
    800917proc_stdin_thread(sub_process *pproc)
    801918{
    802         DWORD in_done;
    803         for (;;) {
    804                 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
    805                                         &in_done, NULL) == FALSE)
    806                         _endthreadex(0);
    807                 // This if should never be true for anonymous pipes, but gives
    808                 // us a chance to change I/O mechanisms later
    809                 if (in_done < pproc->incnt) {
    810                         pproc->incnt -= in_done;
    811                         pproc->inp += in_done;
    812                 } else {
    813                         _endthreadex(0);
    814                 }
    815         }
    816         return 0; // for compiler warnings only.. not reached
     919        DWORD in_done;
     920        for (;;) {
     921                if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt,
     922                                        &in_done, NULL) == FALSE)
     923                        _endthreadex(0);
     924                // This if should never be true for anonymous pipes, but gives
     925                // us a chance to change I/O mechanisms later
     926                if (in_done < pproc->incnt) {
     927                        pproc->incnt -= in_done;
     928                        pproc->inp += in_done;
     929                } else {
     930                        _endthreadex(0);
     931                }
     932        }
     933        return 0; // for compiler warnings only.. not reached
    817934}
    818935
     
    820937proc_stdout_thread(sub_process *pproc)
    821938{
    822         DWORD bufsize = 1024;
    823         char c;
    824         DWORD nread;
    825         pproc->outp = malloc(bufsize);
    826         if (pproc->outp == NULL)
    827                 _endthreadex(0);
    828         pproc->outcnt = 0;
    829 
    830         for (;;) {
    831                 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
    832                                         == FALSE) {
    833 /*                      map_windows32_error_to_string(GetLastError());*/
    834                         _endthreadex(0);
    835                 }
    836                 if (nread == 0)
    837                         _endthreadex(0);
    838                 if (pproc->outcnt + nread > bufsize) {
    839                         bufsize += nread + 512;
    840                         pproc->outp = realloc(pproc->outp, bufsize);
    841                         if (pproc->outp == NULL) {
    842                                 pproc->outcnt = 0;
    843                                 _endthreadex(0);
    844                         }
    845                 }
    846                 pproc->outp[pproc->outcnt++] = c;
    847         }
    848         return 0;
     939        DWORD bufsize = 1024;
     940        char c;
     941        DWORD nread;
     942        pproc->outp = malloc(bufsize);
     943        if (pproc->outp == NULL)
     944                _endthreadex(0);
     945        pproc->outcnt = 0;
     946
     947        for (;;) {
     948                if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL)
     949                                        == FALSE) {
     950/*                      map_windows32_error_to_string(GetLastError());*/
     951                        _endthreadex(0);
     952                }
     953                if (nread == 0)
     954                        _endthreadex(0);
     955                if (pproc->outcnt + nread > bufsize) {
     956                        bufsize += nread + 512;
     957                        pproc->outp = realloc(pproc->outp, bufsize);
     958                        if (pproc->outp == NULL) {
     959                                pproc->outcnt = 0;
     960                                _endthreadex(0);
     961                        }
     962                }
     963                pproc->outp[pproc->outcnt++] = c;
     964        }
     965        return 0;
    849966}
    850967
     
    852969proc_stderr_thread(sub_process *pproc)
    853970{
    854         DWORD bufsize = 1024;
    855         char c;
    856         DWORD nread;
    857         pproc->errp = malloc(bufsize);
    858         if (pproc->errp == NULL)
    859                 _endthreadex(0);
    860         pproc->errcnt = 0;
    861 
    862         for (;;) {
    863                 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
    864                         map_windows32_error_to_string(GetLastError());
    865                         _endthreadex(0);
    866                 }
    867                 if (nread == 0)
    868                         _endthreadex(0);
    869                 if (pproc->errcnt + nread > bufsize) {
    870                         bufsize += nread + 512;
    871                         pproc->errp = realloc(pproc->errp, bufsize);
    872                         if (pproc->errp == NULL) {
    873                                 pproc->errcnt = 0;
    874                                 _endthreadex(0);
    875                         }
    876                 }
    877                 pproc->errp[pproc->errcnt++] = c;
    878         }
    879         return 0;
     971        DWORD bufsize = 1024;
     972        char c;
     973        DWORD nread;
     974        pproc->errp = malloc(bufsize);
     975        if (pproc->errp == NULL)
     976                _endthreadex(0);
     977        pproc->errcnt = 0;
     978
     979        for (;;) {
     980                if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) {
     981                        map_windows32_error_to_string(GetLastError());
     982                        _endthreadex(0);
     983                }
     984                if (nread == 0)
     985                        _endthreadex(0);
     986                if (pproc->errcnt + nread > bufsize) {
     987                        bufsize += nread + 512;
     988                        pproc->errp = realloc(pproc->errp, bufsize);
     989                        if (pproc->errp == NULL) {
     990                                pproc->errcnt = 0;
     991                                _endthreadex(0);
     992                        }
     993                }
     994                pproc->errp[pproc->errcnt++] = c;
     995        }
     996        return 0;
    880997}
    881998
     
    8901007 * Notes/Dependencies:
    8911008 */
    892         long
     1009        long
    8931010process_pipe_io(
    894         HANDLE proc,
    895         char *stdin_data,
    896         int stdin_data_len)
    897 {
    898         sub_process *pproc = (sub_process *)proc;
    899         bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
    900         HANDLE childhand = (HANDLE) pproc->pid;
    901         HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
    902         unsigned int dwStdin, dwStdout, dwStderr;
    903         HANDLE wait_list[4];
    904         DWORD wait_count;
    905         DWORD wait_return;
    906         HANDLE ready_hand;
    907         bool_t child_dead = FALSE;
    908         BOOL GetExitCodeResult;
     1011        HANDLE proc,
     1012        char *stdin_data,
     1013        int stdin_data_len)
     1014{
     1015        sub_process *pproc = (sub_process *)proc;
     1016        bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE;
     1017        HANDLE childhand = (HANDLE) pproc->pid;
     1018        HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL;
     1019        unsigned int dwStdin, dwStdout, dwStderr;
     1020        HANDLE wait_list[4];
     1021        DWORD wait_count;
     1022        DWORD wait_return;
     1023        HANDLE ready_hand;
     1024        bool_t child_dead = FALSE;
     1025        BOOL GetExitCodeResult;
    9091026#ifdef KMK
    9101027        assert (pproc->enmType == kRegular);
    9111028#endif
    9121029
    913         /*
    914         *  Create stdin thread, if needed
    915         */
    916         pproc->inp = stdin_data;
    917         pproc->incnt = stdin_data_len;
    918         if (!pproc->inp) {
    919                 stdin_eof = TRUE;
    920                 CloseHandle((HANDLE)pproc->sv_stdin[0]);
    921                 pproc->sv_stdin[0] = 0;
    922         } else {
    923                 tStdin = (HANDLE) _beginthreadex( 0, 1024,
    924                         (unsigned (__stdcall *) (void *))proc_stdin_thread,
    925                                                   pproc, 0, &dwStdin);
    926                 if (tStdin == 0) {
    927                         pproc->last_err = GetLastError();
    928                         pproc->lerrno = E_SCALL;
    929                         goto done;
    930                 }
    931         }
    932 
    933         /*
    934         *   Assume child will produce stdout and stderr
    935         */
    936         tStdout = (HANDLE) _beginthreadex( 0, 1024,
    937                 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
    938                 &dwStdout);
    939         tStderr = (HANDLE) _beginthreadex( 0, 1024,
    940                 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
    941                 &dwStderr);
    942 
    943         if (tStdout == 0 || tStderr == 0) {
    944 
    945                 pproc->last_err = GetLastError();
    946                 pproc->lerrno = E_SCALL;
    947                 goto done;
    948         }
    949 
    950 
    951         /*
    952         *  Wait for all I/O to finish and for the child process to exit
    953         */
    954 
    955         while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
    956                 wait_count = 0;
    957                 if (!stdin_eof) {
    958                         wait_list[wait_count++] = tStdin;
    959                 }
    960                 if (!stdout_eof) {
    961                         wait_list[wait_count++] = tStdout;
    962                 }
    963                 if (!stderr_eof) {
    964                         wait_list[wait_count++] = tStderr;
    965                 }
    966                 if (!child_dead) {
    967                         wait_list[wait_count++] = childhand;
    968                 }
    969 
    970                 wait_return = WaitForMultipleObjects(wait_count, wait_list,
    971                         FALSE, /* don't wait for all: one ready will do */
    972                         child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
    973                                 one second to collect all remaining output */
     1030        /*
     1031        *  Create stdin thread, if needed
     1032        */
     1033        pproc->inp = stdin_data;
     1034        pproc->incnt = stdin_data_len;
     1035        if (!pproc->inp) {
     1036                stdin_eof = TRUE;
     1037                CloseHandle((HANDLE)pproc->sv_stdin[0]);
     1038                pproc->sv_stdin[0] = 0;
     1039        } else {
     1040                tStdin = (HANDLE) _beginthreadex( 0, 1024,
     1041                        (unsigned (__stdcall *) (void *))proc_stdin_thread,
     1042                                                  pproc, 0, &dwStdin);
     1043                if (tStdin == 0) {
     1044                        pproc->last_err = GetLastError();
     1045                        pproc->lerrno = E_SCALL;
     1046                        goto done;
     1047                }
     1048        }
     1049
     1050        /*
     1051        *   Assume child will produce stdout and stderr
     1052        */
     1053        tStdout = (HANDLE) _beginthreadex( 0, 1024,
     1054                (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0,
     1055                &dwStdout);
     1056        tStderr = (HANDLE) _beginthreadex( 0, 1024,
     1057                (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0,
     1058                &dwStderr);
     1059
     1060        if (tStdout == 0 || tStderr == 0) {
     1061
     1062                pproc->last_err = GetLastError();
     1063                pproc->lerrno = E_SCALL;
     1064                goto done;
     1065        }
     1066
     1067
     1068        /*
     1069        *  Wait for all I/O to finish and for the child process to exit
     1070        */
     1071
     1072        while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) {
     1073                wait_count = 0;
     1074                if (!stdin_eof) {
     1075                        wait_list[wait_count++] = tStdin;
     1076                }
     1077                if (!stdout_eof) {
     1078                        wait_list[wait_count++] = tStdout;
     1079                }
     1080                if (!stderr_eof) {
     1081                        wait_list[wait_count++] = tStderr;
     1082                }
     1083                if (!child_dead) {
     1084                        wait_list[wait_count++] = childhand;
     1085                }
     1086
     1087                wait_return = WaitForMultipleObjects(wait_count, wait_list,
     1088                        FALSE, /* don't wait for all: one ready will do */
     1089                        child_dead? 1000 :INFINITE); /* after the child dies, subthreads have
     1090                                one second to collect all remaining output */
    9741091
    9751092                if (wait_return == WAIT_FAILED) {
    976 /*                      map_windows32_error_to_string(GetLastError());*/
    977                         pproc->last_err = GetLastError();
    978                         pproc->lerrno = E_SCALL;
    979                         goto done;
    980                 }
    981 
    982                 ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
    983 
    984                 if (ready_hand == tStdin) {
    985                         CloseHandle((HANDLE)pproc->sv_stdin[0]);
    986                         pproc->sv_stdin[0] = 0;
    987                         CloseHandle(tStdin);
    988                         tStdin = 0;
    989                         stdin_eof = TRUE;
    990 
    991                 } else if (ready_hand == tStdout) {
    992 
    993                         CloseHandle((HANDLE)pproc->sv_stdout[0]);
    994                         pproc->sv_stdout[0] = 0;
    995                         CloseHandle(tStdout);
    996                         tStdout = 0;
    997                         stdout_eof = TRUE;
    998 
    999                 } else if (ready_hand == tStderr) {
    1000 
    1001                         CloseHandle((HANDLE)pproc->sv_stderr[0]);
    1002                         pproc->sv_stderr[0] = 0;
    1003                         CloseHandle(tStderr);
    1004                         tStderr = 0;
    1005                         stderr_eof = TRUE;
    1006 
    1007                 } else if (ready_hand == childhand) {
    1008 
    1009                         DWORD ierr;
    1010                         GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
    1011                         if (ierr == CONTROL_C_EXIT) {
    1012                                 pproc->signal = SIGINT;
    1013                         } else {
    1014                                 pproc->exit_code = ierr;
    1015                         }
    1016                         if (GetExitCodeResult == FALSE) {
    1017                                 pproc->last_err = GetLastError();
    1018                                 pproc->lerrno = E_SCALL;
    1019                                 goto done;
    1020                         }
    1021                         child_dead = TRUE;
    1022 
    1023                 } else {
    1024 
    1025                         /* ?? Got back a handle we didn't query ?? */
    1026                         pproc->last_err = 0;
    1027                         pproc->lerrno = E_FAIL;
    1028                         goto done;
    1029                 }
    1030         }
     1093/*                      map_windows32_error_to_string(GetLastError());*/
     1094                        pproc->last_err = GetLastError();
     1095                        pproc->lerrno = E_SCALL;
     1096                        goto done;
     1097                }
     1098
     1099                ready_hand = wait_list[wait_return - WAIT_OBJECT_0];
     1100
     1101                if (ready_hand == tStdin) {
     1102                        CloseHandle((HANDLE)pproc->sv_stdin[0]);
     1103                        pproc->sv_stdin[0] = 0;
     1104                        CloseHandle(tStdin);
     1105                        tStdin = 0;
     1106                        stdin_eof = TRUE;
     1107
     1108                } else if (ready_hand == tStdout) {
     1109
     1110                        CloseHandle((HANDLE)pproc->sv_stdout[0]);
     1111                        pproc->sv_stdout[0] = 0;
     1112                        CloseHandle(tStdout);
     1113                        tStdout = 0;
     1114                        stdout_eof = TRUE;
     1115
     1116                } else if (ready_hand == tStderr) {
     1117
     1118                        CloseHandle((HANDLE)pproc->sv_stderr[0]);
     1119                        pproc->sv_stderr[0] = 0;
     1120                        CloseHandle(tStderr);
     1121                        tStderr = 0;
     1122                        stderr_eof = TRUE;
     1123
     1124                } else if (ready_hand == childhand) {
     1125
     1126                        DWORD ierr;
     1127                        GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
     1128                        if (ierr == CONTROL_C_EXIT) {
     1129                                pproc->signal = SIGINT;
     1130                        } else {
     1131                                pproc->exit_code = ierr;
     1132                        }
     1133                        if (GetExitCodeResult == FALSE) {
     1134                                pproc->last_err = GetLastError();
     1135                                pproc->lerrno = E_SCALL;
     1136                                goto done;
     1137                        }
     1138                        child_dead = TRUE;
     1139
     1140                } else {
     1141
     1142                        /* ?? Got back a handle we didn't query ?? */
     1143                        pproc->last_err = 0;
     1144                        pproc->lerrno = E_FAIL;
     1145                        goto done;
     1146                }
     1147        }
    10311148
    10321149 done:
    1033         if (tStdin != 0)
    1034                 CloseHandle(tStdin);
    1035         if (tStdout != 0)
    1036                 CloseHandle(tStdout);
    1037         if (tStderr != 0)
    1038                 CloseHandle(tStderr);
    1039 
    1040         if (pproc->lerrno)
    1041                 return(-1);
    1042         else
    1043                 return(0);
    1044 
    1045 }
     1150        if (tStdin != 0)
     1151                CloseHandle(tStdin);
     1152        if (tStdout != 0)
     1153                CloseHandle(tStdout);
     1154        if (tStderr != 0)
     1155                CloseHandle(tStderr);
     1156
     1157        if (pproc->lerrno)
     1158                return(-1);
     1159        else
     1160                return(0);
     1161
     1162}
     1163#endif  /* unused */
    10461164
    10471165#ifndef KMK /* unused */
     
    10551173 * Notes/Dependencies:
    10561174 */
    1057         long
     1175        long
    10581176process_file_io(
    1059         HANDLE proc)
    1060 {
    1061         sub_process *pproc;
    1062         if (proc == NULL)
    1063                 pproc = process_wait_for_any_private();
    1064         else
    1065                 pproc = (sub_process *)proc;
    1066 
    1067         /* some sort of internal error */
    1068         if (!pproc)
    1069                 return -1;
     1177        HANDLE proc)
     1178{
     1179        sub_process *pproc;
     1180
     1181        if (proc == NULL)
     1182                pproc = process_wait_for_any_private(1, 0);
     1183        else
     1184                pproc = (sub_process *)proc;
     1185
     1186        /* some sort of internal error */
     1187        if (!pproc)
     1188                return -1;
    10701189
    10711190        return process_file_io_private(proc, TRUE);
     
    10841203        DWORD ierr;
    10851204
    1086         childhand = (HANDLE) pproc->pid;
    1087 
    1088         /*
    1089         * This function is poorly named, and could also be used just to wait
    1090         * for child death if you're doing your own pipe I/O.  If that is
    1091         * the case, close the pipe handles here.
    1092         */
    1093         if (pproc->sv_stdin[0]) {
    1094                 CloseHandle((HANDLE)pproc->sv_stdin[0]);
    1095                 pproc->sv_stdin[0] = 0;
    1096         }
    1097         if (pproc->sv_stdout[0]) {
    1098                 CloseHandle((HANDLE)pproc->sv_stdout[0]);
    1099                 pproc->sv_stdout[0] = 0;
    1100         }
    1101         if (pproc->sv_stderr[0]) {
    1102                 CloseHandle((HANDLE)pproc->sv_stderr[0]);
    1103                 pproc->sv_stderr[0] = 0;
    1104         }
     1205        childhand = (HANDLE) pproc->pid;
     1206
     1207        /*
     1208        * This function is poorly named, and could also be used just to wait
     1209        * for child death if you're doing your own pipe I/O.  If that is
     1210        * the case, close the pipe handles here.
     1211        */
     1212        if (pproc->sv_stdin[0]) {
     1213                CloseHandle((HANDLE)pproc->sv_stdin[0]);
     1214                pproc->sv_stdin[0] = 0;
     1215        }
     1216        if (pproc->sv_stdout[0]) {
     1217                CloseHandle((HANDLE)pproc->sv_stdout[0]);
     1218                pproc->sv_stdout[0] = 0;
     1219        }
     1220        if (pproc->sv_stderr[0]) {
     1221                CloseHandle((HANDLE)pproc->sv_stderr[0]);
     1222                pproc->sv_stderr[0] = 0;
     1223        }
    11051224
    11061225#ifdef KMK
     
    11101229#endif
    11111230
    1112         /*
    1113          *  Wait for the child process to exit it we didn't do that already.
    1114          */
    1115         if (fNeedToWait) {
    1116                 wait_return = WaitForSingleObject(childhand, INFINITE);
    1117                 if (wait_return != WAIT_OBJECT_0) {
    1118 /*                      map_windows32_error_to_string(GetLastError());*/
    1119                         pproc->last_err = GetLastError();
    1120                         pproc->lerrno = E_SCALL;
    1121                         goto done2;
    1122                 }
    1123         }
    1124 
    1125         GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
    1126         if (ierr == CONTROL_C_EXIT) {
    1127                 pproc->signal = SIGINT;
    1128         } else {
    1129                 pproc->exit_code = ierr;
    1130         }
    1131         if (GetExitCodeResult == FALSE) {
    1132                 pproc->last_err = GetLastError();
    1133                 pproc->lerrno = E_SCALL;
    1134         }
     1231        /*
     1232         *  Wait for the child process to exit
     1233         */
     1234
     1235    if (fNeedToWait) { /* bird */
     1236        wait_return = WaitForSingleObject(childhand, INFINITE);
     1237
     1238        if (wait_return != WAIT_OBJECT_0) {
     1239/*              map_windows32_error_to_string(GetLastError());*/
     1240                pproc->last_err = GetLastError();
     1241                pproc->lerrno = E_SCALL;
     1242                goto done2;
     1243        }
     1244    } /* bird */
     1245
     1246        GetExitCodeResult = GetExitCodeProcess(childhand, &ierr);
     1247        if (ierr == CONTROL_C_EXIT) {
     1248                pproc->signal = SIGINT;
     1249        } else {
     1250                pproc->exit_code = ierr;
     1251        }
     1252        if (GetExitCodeResult == FALSE) {
     1253                pproc->last_err = GetLastError();
     1254                pproc->lerrno = E_SCALL;
     1255        }
    11351256
    11361257done2:
    1137         if (pproc->lerrno)
    1138                 return(-1);
    1139         else
    1140                 return(0);
     1258        if (pproc->lerrno)
     1259                return(-1);
     1260        else
     1261                return(0);
    11411262
    11421263}
     
    11441265/*
    11451266 * Description:  Clean up any leftover handles, etc.  It is up to the
    1146  * caller to manage and free the input, ouput, and stderr buffers.
     1267 * caller to manage and free the input, output, and stderr buffers.
    11471268 */
    1148         void
     1269        void
    11491270process_cleanup(
    1150         HANDLE proc)
    1151 {
    1152         sub_process *pproc = (sub_process *)proc;
    1153         int i;
    1154 
    1155 #ifdef KMK
    1156         if (pproc->enmType == kRegular) {
    1157 #endif
    1158 
    1159         if (pproc->using_pipes) {
    1160                 for (i= 0; i <= 1; i++) {
    1161                         if ((HANDLE)pproc->sv_stdin[i])
    1162                                 CloseHandle((HANDLE)pproc->sv_stdin[i]);
    1163                         if ((HANDLE)pproc->sv_stdout[i])
    1164                                 CloseHandle((HANDLE)pproc->sv_stdout[i]);
    1165                         if ((HANDLE)pproc->sv_stderr[i])
    1166                                 CloseHandle((HANDLE)pproc->sv_stderr[i]);
    1167                 }
    1168         }
    1169         if ((HANDLE)pproc->pid)
    1170                 CloseHandle((HANDLE)pproc->pid);
    1171 #ifdef KMK
    1172         } else if (pproc->enmType == kSubmit) {
    1173             kSubmitSubProcCleanup(pproc->clue);
    1174         } else {
    1175             assert(0);
    1176             return;
    1177         }
    1178         pproc->enmType = kSubProcFreed;
    1179 #endif
    1180 
    1181         free(pproc);
     1271        HANDLE proc)
     1272{
     1273        sub_process *pproc = (sub_process *)proc;
     1274        int i;
     1275
     1276#ifdef KMK
     1277    if (pproc->enmType == kRegular) {
     1278#endif
     1279        if (pproc->using_pipes) {
     1280                for (i= 0; i <= 1; i++) {
     1281                        if ((HANDLE)pproc->sv_stdin[i]
     1282                            && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE)
     1283                                CloseHandle((HANDLE)pproc->sv_stdin[i]);
     1284                        if ((HANDLE)pproc->sv_stdout[i]
     1285                            && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE)
     1286                                CloseHandle((HANDLE)pproc->sv_stdout[i]);
     1287                        if ((HANDLE)pproc->sv_stderr[i]
     1288                            && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE)
     1289                                CloseHandle((HANDLE)pproc->sv_stderr[i]);
     1290                }
     1291        }
     1292        if ((HANDLE)pproc->pid)
     1293                CloseHandle((HANDLE)pproc->pid);
     1294#ifdef KMK
     1295    } else if (pproc->enmType == kSubmit) {
     1296        kSubmitSubProcCleanup(pproc->clue);
     1297    } else {
     1298       assert(0);
     1299       return;
     1300    }
     1301        pproc->enmType = kSubProcFreed;
     1302#endif
     1303
     1304        free(pproc);
    11821305}
    11831306
     
    11851308/*
    11861309 * Description:
    1187  *      Create a command line buffer to pass to CreateProcess
     1310 *      Create a command line buffer to pass to CreateProcess
    11881311 *
    11891312 * Returns:  the buffer or NULL for failure
    1190  *      Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...
     1313 *      Shell case:  sh_name a:/full/path/to/script argv[1] argv[2] ...
    11911314 *  Otherwise:   argv[0] argv[1] argv[2] ...
    11921315 *
     
    11991322make_command_line( char *shell_name, char *full_exec_path, char **argv)
    12001323{
    1201         int             argc = 0;
    1202         char**          argvi;
    1203         int*            enclose_in_quotes = NULL;
    1204         int*            enclose_in_quotes_i;
    1205         unsigned int    bytes_required = 0;
    1206         char*           command_line;
    1207         char*           command_line_i;
    1208         int  cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
    1209         int have_sh = 0; /* HAVE_CYGWIN_SHELL */
    1210 #undef HAVE_CYGWIN_SHELL
     1324        int             argc = 0;
     1325        char**          argvi;
     1326        int*            enclose_in_quotes = NULL;
     1327        int*            enclose_in_quotes_i;
     1328        unsigned int    bytes_required = 0;
     1329        char*           command_line;
     1330        char*           command_line_i;
     1331        int  cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */
     1332        int have_sh = 0; /* HAVE_CYGWIN_SHELL */
     1333#undef HAVE_CYGWIN_SHELL /* bird: paranoia */
    12111334#ifdef HAVE_CYGWIN_SHELL
    1212         have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
    1213         cygwin_mode = 1;
    1214 #endif
    1215 
    1216         if (shell_name && full_exec_path) {
    1217                 bytes_required
    1218                   = strlen(shell_name) + 1 + strlen(full_exec_path);
    1219                 /*
    1220                  * Skip argv[0] if any, when shell_name is given.
    1221                  */
    1222                 if (*argv) argv++;
    1223                 /*
    1224                  * Add one for the intervening space.
    1225                  */
    1226                 if (*argv) bytes_required++;
    1227         }
    1228 
    1229         argvi = argv;
    1230         while (*(argvi++)) argc++;
    1231 
    1232         if (argc) {
    1233                 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
    1234 
    1235                 if (!enclose_in_quotes) {
    1236                         return NULL;
    1237                 }
    1238         }
    1239 
    1240         /* We have to make one pass through each argv[i] to see if we need
    1241          * to enclose it in ", so we might as well figure out how much
    1242          * memory we'll need on the same pass.
    1243          */
    1244 
    1245         argvi = argv;
    1246         enclose_in_quotes_i = enclose_in_quotes;
    1247         while(*argvi) {
    1248                 char* p = *argvi;
    1249                 unsigned int backslash_count = 0;
    1250 
    1251                 /*
    1252                  * We have to enclose empty arguments in ".
    1253                  */
    1254                 if (!(*p)) *enclose_in_quotes_i = 1;
    1255 
    1256                 while(*p) {
    1257                         switch (*p) {
    1258                         case '\"':
    1259                                 /*
    1260                                  * We have to insert a backslash for each "
    1261                                  * and each \ that precedes the ".
    1262                                  */
    1263                                 bytes_required += (backslash_count + 1);
    1264                                 backslash_count = 0;
    1265                                 break;
     1335        have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe"));
     1336        cygwin_mode = 1;
     1337#endif
     1338
     1339        if (shell_name && full_exec_path) {
     1340                bytes_required
     1341                  = strlen(shell_name) + 1 + strlen(full_exec_path);
     1342                /*
     1343                 * Skip argv[0] if any, when shell_name is given.
     1344                 * The special case of "-c" in full_exec_path means
     1345                 * argv[0] is not the shell name, but the command string
     1346                 * to pass to the shell.
     1347                 */
     1348                if (*argv && strcmp(full_exec_path, "-c")) argv++;
     1349                /*
     1350                 * Add one for the intervening space.
     1351                 */
     1352                if (*argv) bytes_required++;
     1353        }
     1354
     1355        argvi = argv;
     1356        while (*(argvi++)) argc++;
     1357
     1358        if (argc) {
     1359                enclose_in_quotes = (int*) calloc(1, argc * sizeof(int));
     1360
     1361                if (!enclose_in_quotes) {
     1362                        return NULL;
     1363                }
     1364        }
     1365
     1366        /* We have to make one pass through each argv[i] to see if we need
     1367         * to enclose it in ", so we might as well figure out how much
     1368         * memory we'll need on the same pass.
     1369         */
     1370
     1371        argvi = argv;
     1372        enclose_in_quotes_i = enclose_in_quotes;
     1373        while(*argvi) {
     1374                char* p = *argvi;
     1375                unsigned int backslash_count = 0;
     1376
     1377                /*
     1378                 * We have to enclose empty arguments in ".
     1379                 */
     1380                if (!(*p)) *enclose_in_quotes_i = 1;
     1381
     1382                while(*p) {
     1383                        switch (*p) {
     1384                        case '\"':
     1385                                /*
     1386                                 * We have to insert a backslash for each "
     1387                                 * and each \ that precedes the ".
     1388                                 */
     1389                                bytes_required += (backslash_count + 1);
     1390                                backslash_count = 0;
     1391                                break;
    12661392
    12671393#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
    1268                         case '\\':
    1269                                 backslash_count++;
    1270                                 break;
    1271 #endif
    1272         /*
    1273         * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
    1274         * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
    1275         * that argv in always equals argv out. This was removed.  Say you have
    1276         * such a program named glob.exe.  You enter
    1277         * glob '*'
    1278         * at the sh command prompt.  Obviously the intent is to make glob do the
    1279         * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',
    1280         * then the command line that glob would see would be
    1281         * glob "*"
    1282         * and the _setargv in SETARGV.OBJ would _not_ expand the *.
    1283         */
    1284                         case ' ':
    1285                         case '\t':
    1286                                 *enclose_in_quotes_i = 1;
    1287                                 /* fall through */
    1288 
    1289                         default:
    1290                                 backslash_count = 0;
    1291                                 break;
    1292                         }
    1293 
    1294                         /*
    1295                         * Add one for each character in argv[i].
    1296                         */
    1297                         bytes_required++;
    1298 
    1299                         p++;
    1300                 }
    1301 
    1302                 if (*enclose_in_quotes_i) {
    1303                         /*
    1304                         * Add one for each enclosing ",
    1305                         * and one for each \ that precedes the
    1306                         * closing ".
    1307                         */
    1308                         bytes_required += (backslash_count + 2);
    1309                 }
    1310 
    1311                 /*
    1312                 * Add one for the intervening space.
    1313                 */
    1314                 if (*(++argvi)) bytes_required++;
    1315                 enclose_in_quotes_i++;
    1316         }
    1317 
    1318         /*
    1319         * Add one for the terminating NULL.
    1320         */
    1321         bytes_required++;
     1394                        case '\\':
     1395                                backslash_count++;
     1396                                break;
     1397#endif
     1398        /*
     1399        * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress
     1400        * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so
     1401        * that argv in always equals argv out. This was removed.  Say you have
     1402        * such a program named glob.exe.  You enter
     1403        * glob '*'
     1404        * at the sh command prompt.  Obviously the intent is to make glob do the
     1405        * wildcarding instead of sh.  If we set *enclose_in_quotes_i for '*' or '?',
     1406        * then the command line that glob would see would be
     1407        * glob "*"
     1408        * and the _setargv in SETARGV.OBJ would _not_ expand the *.
     1409        */
     1410                        case ' ':
     1411                        case '\t':
     1412                                *enclose_in_quotes_i = 1;
     1413                                /* fall through */
     1414
     1415                        default:
     1416                                backslash_count = 0;
     1417                                break;
     1418                        }
     1419
     1420                        /*
     1421                        * Add one for each character in argv[i].
     1422                        */
     1423                        bytes_required++;
     1424
     1425                        p++;
     1426                }
     1427
     1428                if (*enclose_in_quotes_i) {
     1429                        /*
     1430                        * Add one for each enclosing ",
     1431                        * and one for each \ that precedes the
     1432                        * closing ".
     1433                        */
     1434                        bytes_required += (backslash_count + 2);
     1435                }
     1436
     1437                /*
     1438                * Add one for the intervening space.
     1439                */
     1440                if (*(++argvi)) bytes_required++;
     1441                enclose_in_quotes_i++;
     1442        }
     1443
     1444        /*
     1445        * Add one for the terminating NULL.
     1446        */
     1447        bytes_required++;
    13221448#ifdef KMK /* for the space before the final " in case we need it. */
    13231449        bytes_required++;
    13241450#endif
    13251451
    1326         command_line = (char*) malloc(bytes_required);
    1327 
    1328         if (!command_line) {
    1329                 if (enclose_in_quotes) free(enclose_in_quotes);
    1330                 return NULL;
    1331         }
    1332 
    1333         command_line_i = command_line;
    1334 
    1335         if (shell_name && full_exec_path) {
    1336                 while(*shell_name) {
    1337                         *(command_line_i++) = *(shell_name++);
    1338                 }
    1339 
    1340                 *(command_line_i++) = ' ';
    1341 
    1342                 while(*full_exec_path) {
    1343                         *(command_line_i++) = *(full_exec_path++);
    1344                 }
    1345 
    1346                 if (*argv) {
    1347                         *(command_line_i++) = ' ';
    1348                 }
    1349         }
    1350 
    1351         argvi = argv;
    1352         enclose_in_quotes_i = enclose_in_quotes;
    1353 
    1354         while(*argvi) {
    1355                 char* p = *argvi;
    1356                 unsigned int backslash_count = 0;
    1357 
    1358                 if (*enclose_in_quotes_i) {
    1359                         *(command_line_i++) = '\"';
    1360                 }
    1361 
    1362                 while(*p) {
    1363                         if (*p == '\"') {
    1364                                 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
    1365                                         /* instead of a \", cygwin likes "" */
    1366                                         *(command_line_i++) = '\"';
    1367                                 } else {
    1368 
    1369                                         /*
    1370                                         * We have to insert a backslash for the "
    1371                                         * and each \ that precedes the ".
    1372                                         */
    1373                                         backslash_count++;
    1374 
    1375                                         while(backslash_count) {
    1376                                                 *(command_line_i++) = '\\';
    1377                                                 backslash_count--;
    1378                                         };
    1379                                 }
     1452        command_line = (char*) malloc(bytes_required);
     1453
     1454        if (!command_line) {
     1455                free(enclose_in_quotes);
     1456                return NULL;
     1457        }
     1458
     1459        command_line_i = command_line;
     1460
     1461        if (shell_name && full_exec_path) {
     1462                while(*shell_name) {
     1463                        *(command_line_i++) = *(shell_name++);
     1464                }
     1465
     1466                *(command_line_i++) = ' ';
     1467
     1468                while(*full_exec_path) {
     1469                        *(command_line_i++) = *(full_exec_path++);
     1470                }
     1471
     1472                if (*argv) {
     1473                        *(command_line_i++) = ' ';
     1474                }
     1475        }
     1476
     1477        argvi = argv;
     1478        enclose_in_quotes_i = enclose_in_quotes;
     1479
     1480        while(*argvi) {
     1481                char* p = *argvi;
     1482                unsigned int backslash_count = 0;
     1483
     1484                if (*enclose_in_quotes_i) {
     1485                        *(command_line_i++) = '\"';
     1486                }
     1487
     1488                while(*p) {
     1489                        if (*p == '\"') {
     1490                                if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */
     1491                                        /* instead of a \", cygwin likes "" */
     1492                                        *(command_line_i++) = '\"';
     1493                                } else {
     1494
     1495                                /*
     1496                                * We have to insert a backslash for the "
     1497                                * and each \ that precedes the ".
     1498                                */
     1499                                backslash_count++;
     1500
     1501                                while(backslash_count) {
     1502                                        *(command_line_i++) = '\\';
     1503                                        backslash_count--;
     1504                                };
     1505                                }
    13801506#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
    1381                         } else if (*p == '\\') {
    1382                                 backslash_count++;
    1383                         } else {
    1384                                 backslash_count = 0;
    1385 #endif
    1386                         }
    1387 
    1388                         /*
    1389                         * Copy the character.
    1390                         */
    1391                         *(command_line_i++) = *(p++);
    1392                 }
    1393 
    1394                 if (*enclose_in_quotes_i) {
     1507                        } else if (*p == '\\') {
     1508                                backslash_count++;
     1509                        } else {
     1510                                backslash_count = 0;
     1511#endif
     1512                        }
     1513
     1514                        /*
     1515                        * Copy the character.
     1516                        */
     1517                        *(command_line_i++) = *(p++);
     1518                }
     1519
     1520                if (*enclose_in_quotes_i) {
    13951521#if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL)
    1396                         /*
    1397                         * Add one \ for each \ that precedes the
    1398                         * closing ".
    1399                         */
    1400                         while(backslash_count--) {
    1401                                 *(command_line_i++) = '\\';
    1402                         };
     1522                        /*
     1523                        * Add one \ for each \ that precedes the
     1524                        * closing ".
     1525                        */
     1526                        while(backslash_count--) {
     1527                                *(command_line_i++) = '\\';
     1528                        };
    14031529#endif
    14041530#ifdef KMK
     
    14131539                        }
    14141540#endif
    1415                         *(command_line_i++) = '\"';
    1416                 }
    1417 
    1418                 /*
    1419                  * Append an intervening space.
    1420                  */
    1421                 if (*(++argvi)) {
    1422                         *(command_line_i++) = ' ';
    1423                 }
    1424 
    1425                 enclose_in_quotes_i++;
    1426         }
    1427 
    1428         /*
    1429          * Append the terminating NULL.
    1430          */
    1431         *command_line_i = '\0';
    1432 
    1433         if (enclose_in_quotes) free(enclose_in_quotes);
    1434         return command_line;
     1541
     1542                        *(command_line_i++) = '\"';
     1543                }
     1544
     1545                /*
     1546                 * Append an intervening space.
     1547                 */
     1548                if (*(++argvi)) {
     1549                        *(command_line_i++) = ' ';
     1550                }
     1551
     1552                enclose_in_quotes_i++;
     1553        }
     1554
     1555        /*
     1556         * Append the terminating NULL.
     1557         */
     1558        *command_line_i = '\0';
     1559
     1560        free(enclose_in_quotes);
     1561        return command_line;
    14351562}
    14361563
     
    14391566 *              using the default stdin, stdout, and stderr handles.
    14401567 *              Also, register process so that process_wait_for_any_private()
    1441  *              can be used via process_file_io(NULL) or
    1442  *              process_wait_for_any().
     1568 *              can be used via process_file_io(NULL) or
     1569 *              process_wait_for_any().
    14431570 *
    14441571 * Returns:
     
    14481575HANDLE
    14491576process_easy(
    1450         char **argv,
    1451         char **envp)
    1452 {
    1453 #ifndef KMK
    1454   HANDLE hIn;
    1455   HANDLE hOut;
    1456   HANDLE hErr;
    1457 #endif
    1458   HANDLE hProcess;
     1577        char **argv,
     1578        char **envp,
     1579        int outfd,
     1580        int errfd)
     1581{
     1582  HANDLE hIn = INVALID_HANDLE_VALUE;
     1583  HANDLE hOut = INVALID_HANDLE_VALUE;
     1584  HANDLE hErr = INVALID_HANDLE_VALUE;
     1585  HANDLE hProcess, tmpIn, tmpOut, tmpErr;
     1586  DWORD e;
    14591587
    14601588  if (proc_index >= MAXIMUM_WAIT_OBJECTS) {
    1461         DB (DB_JOBS, ("process_easy: All process slots used up\n"));
    1462         return INVALID_HANDLE_VALUE;
     1589        DB (DB_JOBS, ("process_easy: All process slots used up\n"));
     1590        return INVALID_HANDLE_VALUE;
    14631591  }
    1464 #ifndef KMK
     1592#ifdef KMK /* We can effort here by lettering CreateProcess/kernel do the standard handle duplication. */
     1593 if (outfd != -1 || errfd != -1) {
     1594#endif
     1595  /* Standard handles returned by GetStdHandle can be NULL or
     1596     INVALID_HANDLE_VALUE if the parent process closed them.  If that
     1597     happens, we open the null device and pass its handle to
     1598     CreateProcess as the corresponding handle to inherit.  */
     1599  tmpIn = GetStdHandle(STD_INPUT_HANDLE);
    14651600  if (DuplicateHandle(GetCurrentProcess(),
    1466                       GetStdHandle(STD_INPUT_HANDLE),
     1601                      tmpIn,
    14671602                      GetCurrentProcess(),
    14681603                      &hIn,
     
    14701605                      TRUE,
    14711606                      DUPLICATE_SAME_ACCESS) == FALSE) {
    1472     fprintf(stderr,
    1473             "process_easy: DuplicateHandle(In) failed (e=%ld)\n",
    1474             GetLastError());
    1475     return INVALID_HANDLE_VALUE;
     1607    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
     1608      tmpIn = CreateFile("NUL", GENERIC_READ,
     1609                         FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
     1610                         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     1611      if (tmpIn != INVALID_HANDLE_VALUE
     1612          && DuplicateHandle(GetCurrentProcess(),
     1613                             tmpIn,
     1614                             GetCurrentProcess(),
     1615                             &hIn,
     1616                             0,
     1617                             TRUE,
     1618                             DUPLICATE_SAME_ACCESS) == FALSE)
     1619        CloseHandle(tmpIn);
     1620    }
     1621    if (hIn == INVALID_HANDLE_VALUE) {
     1622      fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e);
     1623      return INVALID_HANDLE_VALUE;
     1624    }
    14761625  }
     1626  if (outfd >= 0)
     1627    tmpOut = (HANDLE)_get_osfhandle (outfd);
     1628  else
     1629    tmpOut = GetStdHandle (STD_OUTPUT_HANDLE);
    14771630  if (DuplicateHandle(GetCurrentProcess(),
    1478                       GetStdHandle(STD_OUTPUT_HANDLE),
     1631                      tmpOut,
    14791632                      GetCurrentProcess(),
    14801633                      &hOut,
     
    14821635                      TRUE,
    14831636                      DUPLICATE_SAME_ACCESS) == FALSE) {
    1484     fprintf(stderr,
    1485            "process_easy: DuplicateHandle(Out) failed (e=%ld)\n",
    1486            GetLastError());
    1487     return INVALID_HANDLE_VALUE;
     1637    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
     1638      tmpOut = CreateFile("NUL", GENERIC_WRITE,
     1639                          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
     1640                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     1641      if (tmpOut != INVALID_HANDLE_VALUE
     1642          && DuplicateHandle(GetCurrentProcess(),
     1643                             tmpOut,
     1644                             GetCurrentProcess(),
     1645                             &hOut,
     1646                             0,
     1647                             TRUE,
     1648                             DUPLICATE_SAME_ACCESS) == FALSE)
     1649        CloseHandle(tmpOut);
     1650    }
     1651    if (hOut == INVALID_HANDLE_VALUE) {
     1652      fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e);
     1653      return INVALID_HANDLE_VALUE;
     1654    }
    14881655  }
     1656  if (errfd >= 0)
     1657    tmpErr = (HANDLE)_get_osfhandle (errfd);
     1658  else
     1659    tmpErr = GetStdHandle(STD_ERROR_HANDLE);
    14891660  if (DuplicateHandle(GetCurrentProcess(),
    1490                       GetStdHandle(STD_ERROR_HANDLE),
     1661                      tmpErr,
    14911662                      GetCurrentProcess(),
    14921663                      &hErr,
     
    14941665                      TRUE,
    14951666                      DUPLICATE_SAME_ACCESS) == FALSE) {
    1496     fprintf(stderr,
    1497             "process_easy: DuplicateHandle(Err) failed (e=%ld)\n",
    1498             GetLastError());
    1499     return INVALID_HANDLE_VALUE;
     1667    if ((e = GetLastError()) == ERROR_INVALID_HANDLE) {
     1668      tmpErr = CreateFile("NUL", GENERIC_WRITE,
     1669                          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
     1670                          OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
     1671      if (tmpErr != INVALID_HANDLE_VALUE
     1672          && DuplicateHandle(GetCurrentProcess(),
     1673                             tmpErr,
     1674                             GetCurrentProcess(),
     1675                             &hErr,
     1676                             0,
     1677                             TRUE,
     1678                             DUPLICATE_SAME_ACCESS) == FALSE)
     1679        CloseHandle(tmpErr);
     1680    }
     1681    if (hErr == INVALID_HANDLE_VALUE) {
     1682      fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e);
     1683      return INVALID_HANDLE_VALUE;
     1684    }
    15001685  }
     1686#ifdef KMK /* saving effort */
     1687 }
     1688#endif
    15011689
    15021690  hProcess = process_init_fd(hIn, hOut, hErr);
    1503 #else
    1504   hProcess = process_init_fd(0, 0, 0);
    1505 #endif /* !KMK */
    15061691
    15071692  if (process_begin(hProcess, argv, envp, argv[0], NULL)) {
     
    15151700      ((sub_process*) hProcess)->exit_code = process_last_err(hProcess);
    15161701
    1517 #ifndef KMK
    15181702    /* close up unused handles */
    1519     CloseHandle(hIn);
    1520     CloseHandle(hOut);
    1521     CloseHandle(hErr);
    1522 #endif
     1703    if (hIn != INVALID_HANDLE_VALUE)
     1704      CloseHandle(hIn);
     1705    if (hOut != INVALID_HANDLE_VALUE)
     1706      CloseHandle(hOut);
     1707    if (hErr != INVALID_HANDLE_VALUE)
     1708      CloseHandle(hErr);
    15231709  }
    15241710
  • trunk/src/kmk/w32/subproc/w32err.c

    r2591 r3140  
    11/* Error handling for Windows
    2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    3 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
     2Copyright (C) 1996-2016 Free Software Foundation, Inc.
    43This file is part of GNU Make.
    54
     
    1615this program.  If not, see <http://www.gnu.org/licenses/>.  */
    1716
     17#include <stdlib.h>
    1818#include <windows.h>
     19#include "makeint.h"
    1920#include "w32err.h"
    2021
     
    2728 *      comp.os.ms-windows.programmer.win32
    2829 */
    29 char *
     30const char *
    3031map_windows32_error_to_string (DWORD ercode) {
    31 /* __declspec (thread) necessary if you will use multiple threads on MSVC */
    32 #ifdef _MSC_VER
    33 __declspec (thread) static char szMessageBuffer[128];
    34 #else
    35 static char szMessageBuffer[128];
    36 #endif
    37         /* Fill message buffer with a default message in
    38          * case FormatMessage fails
    39          */
     32/*
     33 * We used to have an MSVC-specific '__declspec (thread)' qualifier
     34 * here, with the following comment:
     35 *
     36 * __declspec (thread) necessary if you will use multiple threads on MSVC
     37 *
     38 * However, Make was never multithreaded on Windows (except when
     39 * Ctrl-C is hit, in which case the main thread is stopped
     40 * immediately, so it doesn't matter in this context).  The functions
     41 * on sub_proc.c that started and stopped additional threads were
     42 * never used, and are now #ifdef'ed away.  Until we need more than
     43 * one thread, we have no problems with the following buffer being
     44 * static.  (If and when we do need it to be in thread-local storage,
     45 * the corresponding GCC qualifier is '__thread'.)
     46 */
     47    static char szMessageBuffer[128];
     48        /* Fill message buffer with a default message in
     49         * case FormatMessage fails
     50         */
    4051    wsprintf (szMessageBuffer, "Error %ld\n", ercode);
    4152
    42         /*
    43          *  Special code for winsock error handling.
    44          */
    45         if (ercode > WSABASEERR) {
    46                 HMODULE hModule = GetModuleHandle("wsock32");
    47                 if (hModule != NULL) {
    48                         FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
    49                                 hModule,
    50                                 ercode,
    51                                 LANG_NEUTRAL,
    52                                 szMessageBuffer,
    53                                 sizeof(szMessageBuffer),
    54                                 NULL);
    55                         FreeLibrary(hModule);
    56                 }
    57         } else {
    58                 /*
    59                  *  Default system message handling
    60                  */
    61         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
    62                   NULL,
    63                   ercode,
    64                   LANG_NEUTRAL,
    65                   szMessageBuffer,
    66                   sizeof(szMessageBuffer),
    67                   NULL);
    68         }
     53        /*
     54         *  Special code for winsock error handling.
     55         */
     56        if (ercode > WSABASEERR) {
     57#if 0
     58                HMODULE hModule = GetModuleHandle("wsock32");
     59                if (hModule != NULL) {
     60                        FormatMessage(FORMAT_MESSAGE_FROM_HMODULE,
     61                                hModule,
     62                                ercode,
     63                                LANG_NEUTRAL,
     64                                szMessageBuffer,
     65                                sizeof(szMessageBuffer),
     66                                NULL);
     67                        FreeLibrary(hModule);
     68                }
     69#else
     70                O (fatal, NILF, szMessageBuffer);
     71#endif
     72        } else {
     73                /*
     74                 *  Default system message handling
     75                 */
     76                FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
     77                        NULL,
     78                        ercode,
     79                        LANG_NEUTRAL,
     80                        szMessageBuffer,
     81                        sizeof(szMessageBuffer),
     82                        NULL);
     83        }
    6984    return szMessageBuffer;
    7085}
  • trunk/src/kmk/w32/w32os.c

    r3139 r3140  
    169169jobserver_acquire (int timeout)
    170170{
    171     HANDLE handles[MAXIMUM_WAIT_OBJECTS];
     171    HANDLE handles[MAXIMUM_WAIT_OBJECTS + 1]; /* bird: + 1 to prevent trashing the stack. */
    172172    DWORD dwHandleCount;
    173173    DWORD dwEvent;
Note: See TracChangeset for help on using the changeset viewer.