Changeset 3138 for vendor/gnumake/current/w32
- Timestamp:
- Mar 12, 2018, 8:32:29 PM (7 years ago)
- Location:
- vendor/gnumake/current/w32
- Files:
-
- 3 added
- 2 deleted
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/gnumake/current/w32/Makefile.am
r2596 r3138 1 1 # 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. 4 3 # This file is part of GNU Make. 5 4 # … … 17 16 # this program. If not, see <http://www.gnu.org/licenses/>. 18 17 18 AUTOMAKE_OPTIONS = subdir-objects 19 19 20 noinst_LIBRARIES = libw32.a 20 21 21 22 libw32_a_SOURCES = subproc/misc.c subproc/sub_proc.c subproc/w32err.c \ 22 pathstuff.c23 compat/posixfcn.c pathstuff.c w32os.c 23 24 24 libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) 25 libw32_a_CPPFLAGS = -I$(srcdir)/include -I$(srcdir)/subproc -I$(top_srcdir) \ 26 -I$(top_srcdir)/glob -
vendor/gnumake/current/w32/compat/dirent.c
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 29 28 opendir(const char* pDirName) 30 29 { 31 32 DIR*pDir;33 char*pEndDirName;34 intnBufferLen;35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 30 struct stat sb; 31 DIR* pDir; 32 char* pEndDirName; 33 int nBufferLen; 34 35 /* sanity checks */ 36 if (!pDirName) { 37 errno = EINVAL; 38 return NULL; 39 } 40 if (stat(pDirName, &sb) != 0) { 41 errno = ENOENT; 42 return NULL; 43 } 44 if ((sb.st_mode & S_IFMT) != S_IFDIR) { 45 errno = ENOTDIR; 46 return NULL; 47 } 48 49 /* allocate a DIR structure to return */ 50 pDir = (DIR *) malloc(sizeof (DIR)); 51 52 if (!pDir) 53 return NULL; 54 55 /* input directory name length */ 56 nBufferLen = strlen(pDirName); 57 58 /* copy input directory name to DIR buffer */ 59 strcpy(pDir->dir_pDirectoryName, pDirName); 60 61 /* point to end of the copied directory name */ 62 pEndDirName = &pDir->dir_pDirectoryName[nBufferLen - 1]; 63 64 /* if directory name did not end in '/' or '\', add '/' */ 65 if ((*pEndDirName != '/') && (*pEndDirName != '\\')) { 66 pEndDirName++; 67 *pEndDirName = '/'; 68 } 69 70 /* now append the wildcard character to the buffer */ 71 pEndDirName++; 72 *pEndDirName = '*'; 73 pEndDirName++; 74 *pEndDirName = '\0'; 75 76 /* other values defaulted */ 77 pDir->dir_nNumFiles = 0; 78 pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; 79 pDir->dir_ulCookie = __DIRENT_COOKIE; 80 81 return pDir; 83 82 } 84 83 … … 86 85 closedir(DIR *pDir) 87 86 { 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 87 /* got a valid pointer? */ 88 if (!pDir) { 89 errno = EINVAL; 90 return; 91 } 92 93 /* sanity check that this is a DIR pointer */ 94 if (pDir->dir_ulCookie != __DIRENT_COOKIE) { 95 errno = EINVAL; 96 return; 97 } 98 99 /* close the WINDOWS32 directory handle */ 100 if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) 101 FindClose(pDir->dir_hDirHandle); 102 103 free(pDir); 104 105 return; 107 106 } 108 107 … … 110 109 readdir(DIR* pDir) 111 110 { 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 111 WIN32_FIND_DATA wfdFindData; 112 113 if (!pDir) { 114 errno = EINVAL; 115 return NULL; 116 } 117 118 /* sanity check that this is a DIR pointer */ 119 if (pDir->dir_ulCookie != __DIRENT_COOKIE) { 120 errno = EINVAL; 121 return NULL; 122 } 123 124 if (pDir->dir_nNumFiles == 0) { 125 pDir->dir_hDirHandle = FindFirstFile(pDir->dir_pDirectoryName, &wfdFindData); 126 if (pDir->dir_hDirHandle == INVALID_HANDLE_VALUE) 127 return NULL; 128 } else if (!FindNextFile(pDir->dir_hDirHandle, &wfdFindData)) 129 return NULL; 130 131 /* bump count for next call to readdir() or telldir() */ 132 pDir->dir_nNumFiles++; 133 134 /* fill in struct dirent values */ 135 pDir->dir_sdReturn.d_ino = (ino_t)-1; 136 strcpy(pDir->dir_sdReturn.d_name, wfdFindData.cFileName); 137 138 return &pDir->dir_sdReturn; 140 139 } 141 140 … … 143 142 rewinddir(DIR* pDir) 144 143 { 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 144 if (!pDir) { 145 errno = EINVAL; 146 return; 147 } 148 149 /* sanity check that this is a DIR pointer */ 150 if (pDir->dir_ulCookie != __DIRENT_COOKIE) { 151 errno = EINVAL; 152 return; 153 } 154 155 /* close the WINDOWS32 directory handle */ 156 if (pDir->dir_hDirHandle != INVALID_HANDLE_VALUE) 157 if (!FindClose(pDir->dir_hDirHandle)) 158 errno = EBADF; 159 160 /* reset members which control readdir() */ 161 pDir->dir_hDirHandle = INVALID_HANDLE_VALUE; 162 pDir->dir_nNumFiles = 0; 163 164 return; 166 165 } 167 166 … … 169 168 telldir(DIR* pDir) 170 169 { 171 172 173 174 175 176 177 178 179 180 181 182 183 170 if (!pDir) { 171 errno = EINVAL; 172 return -1; 173 } 174 175 /* sanity check that this is a DIR pointer */ 176 if (pDir->dir_ulCookie != __DIRENT_COOKIE) { 177 errno = EINVAL; 178 return -1; 179 } 180 181 /* return number of times readdir() called */ 182 return pDir->dir_nNumFiles; 184 183 } 185 184 … … 187 186 seekdir(DIR* pDir, long nPosition) 188 187 { 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 } 188 if (!pDir) 189 return; 190 191 /* sanity check that this is a DIR pointer */ 192 if (pDir->dir_ulCookie != __DIRENT_COOKIE) 193 return; 194 195 /* go back to beginning of directory */ 196 rewinddir(pDir); 197 198 /* loop until we have found position we care about */ 199 for (--nPosition; nPosition && readdir(pDir); nPosition--); 200 201 /* flag invalid nPosition value */ 202 if (nPosition) 203 errno = EINVAL; 204 205 return; 206 } -
vendor/gnumake/current/w32/include/dirent.h
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 38 37 struct dirent 39 38 { 40 ino_t d_ino; 39 ino_t d_ino; /* unused - no equivalent on WINDOWS32 */ 41 40 char d_name[NAME_MAX+1]; 42 41 }; 43 42 44 43 typedef struct dir_struct { 45 ULONGdir_ulCookie;46 HANDLEdir_hDirHandle;47 DWORDdir_nNumFiles;48 chardir_pDirectoryName[NAME_MAX+1];49 44 ULONG dir_ulCookie; 45 HANDLE dir_hDirHandle; 46 DWORD dir_nNumFiles; 47 char dir_pDirectoryName[NAME_MAX+1]; 48 struct dirent dir_sdReturn; 50 49 } DIR; 51 50 -
vendor/gnumake/current/w32/include/pathstuff.h
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 -
vendor/gnumake/current/w32/include/sub_proc.h
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 22 21 * Component Name: 23 22 * 24 * $Date : 2010/07/13 01:20:43$23 * $Date$ 25 24 * 26 * $Source : /sources/make/make/w32/include/sub_proc.h,v$25 * $Source$ 27 26 * 28 * $Id : sub_proc.h,v 1.12 2010/07/13 01:20:43 psmith Exp$27 * $Id$ 29 28 */ 30 29 … … 34 33 EXTERN_DECL(HANDLE process_init, (VOID_DECL)); 35 34 EXTERN_DECL(HANDLE process_init_fd, (HANDLE stdinh, HANDLE stdouth, 36 35 HANDLE stderrh)); 37 36 EXTERN_DECL(long process_begin, (HANDLE proc, char **argv, char **envp, 38 37 char *exec_path, char *as_user)); 39 38 EXTERN_DECL(long process_pipe_io, (HANDLE proc, char *stdin_data, 40 39 int stdin_data_len)); 41 40 EXTERN_DECL(long process_file_io, (HANDLE proc)); 42 41 EXTERN_DECL(void process_cleanup, (HANDLE proc)); 43 EXTERN_DECL(HANDLE process_wait_for_any, ( VOID_DECL));42 EXTERN_DECL(HANDLE process_wait_for_any, (int block, DWORD* pdwWaitStatus)); 44 43 EXTERN_DECL(void process_register, (HANDLE proc)); 45 EXTERN_DECL(HANDLE process_easy, (char** argv, char** env)); 44 EXTERN_DECL(HANDLE process_easy, (char** argv, char** env, 45 int outfd, int errfd)); 46 46 EXTERN_DECL(BOOL process_kill, (HANDLE proc, int signal)); 47 47 EXTERN_DECL(int process_used_slots, (VOID_DECL)); 48 EXTERN_DECL(DWORD process_set_handles, (HANDLE *handles)); 48 49 49 50 /* support routines */ … … 57 58 EXTERN_DECL(int process_errcnt, (HANDLE proc)); 58 59 EXTERN_DECL(void process_pipes, (HANDLE proc, int pipes[3])); 60 EXTERN_DECL(void process_noinherit, (int fildes)); 59 61 60 62 #endif -
vendor/gnumake/current/w32/include/w32err.h
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 23 22 #endif 24 23 25 EXTERN_DECL(c har * map_windows32_error_to_string, (DWORD error));24 EXTERN_DECL(const char * map_windows32_error_to_string, (DWORD error)); 26 25 27 26 #endif /* !_W32ERR_H */ -
vendor/gnumake/current/w32/pathstuff.c
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 16 15 this program. If not, see <http://www.gnu.org/licenses/>. */ 17 16 18 #include "make .h"17 #include "makeint.h" 19 18 #include <string.h> 20 19 #include <stdlib.h> … … 29 28 char *etok; /* token separator for old Path */ 30 29 31 32 33 34 35 36 if (isblank((unsigned char) *etok))37 38 39 30 /* 31 * Convert all spaces to delimiters. Note that pathnames which 32 * contain blanks get trounced here. Use 8.3 format as a workaround. 33 */ 34 for (etok = Path; etok && *etok; etok++) 35 if (ISBLANK ((unsigned char) *etok)) 36 *etok = to_delim; 37 38 return (convert_Path_to_windows32(Path, to_delim)); 40 39 } 41 40 … … 81 80 *etok = to_delim; 82 81 p = ++etok; 83 82 } else 84 83 p += strlen(p); 85 84 } else { … … 116 115 getcwd_fs(char* buf, int len) 117 116 { 118 119 120 121 122 123 124 125 117 char *p = getcwd(buf, len); 118 119 if (p) { 120 char *q = w32ify(buf, 0); 121 strncpy(buf, q, len); 122 } 123 124 return p; 126 125 } 127 126 -
vendor/gnumake/current/w32/subproc/NMakefile
r2596 r3138 1 # NOTE: If you have no `make' program at all to process this makefile, run2 # `build.bat' instead.1 # NOTE: If you have no 'make' program at all to process this makefile, run 2 # 'build.bat' instead. 3 3 # 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. 6 5 # This file is part of GNU Make. 7 6 # -
vendor/gnumake/current/w32/subproc/misc.c
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 26 25 /* 27 26 * Description: Convert a NULL string terminated UNIX environment block to 28 * 27 * an environment block suitable for a windows32 system call 29 28 * 30 29 * Returns: TRUE= success, FALSE=fail 31 30 * 32 31 * Notes/Dependencies: the environment block is sorted in case-insensitive 33 * 32 * order, is double-null terminated, and is a char *, not a char ** 34 33 */ 35 34 int _cdecl compare(const void *a1, const void *a2) 36 35 { 37 36 return _stricoll(*((char**)a1),*((char**)a2)); 38 37 } 39 38 bool_t 40 arr2envblk(char **arr, char **envblk_out )39 arr2envblk(char **arr, char **envblk_out, int *envsize_needed) 41 40 { 42 43 44 45 41 char **tmp; 42 int size_needed; 43 int arrcnt; 44 char *ptr; 46 45 47 48 49 50 46 arrcnt = 0; 47 while (arr[arrcnt]) { 48 arrcnt++; 49 } 51 50 52 53 54 55 51 tmp = (char**) calloc(arrcnt + 1, sizeof(char *)); 52 if (!tmp) { 53 return FALSE; 54 } 56 55 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; 65 65 66 66 qsort((void *) tmp, (size_t) arrcnt, sizeof (char*), compare); 67 67 68 69 70 71 72 68 ptr = *envblk_out = calloc(size_needed, 1); 69 if (!ptr) { 70 free(tmp); 71 return FALSE; 72 } 73 73 74 75 76 77 78 79 74 arrcnt = 0; 75 while (tmp[arrcnt]) { 76 strcpy(ptr, tmp[arrcnt]); 77 ptr += strlen(tmp[arrcnt]) + 1; 78 arrcnt++; 79 } 80 80 81 82 81 free(tmp); 82 return TRUE; 83 83 } -
vendor/gnumake/current/w32/subproc/proc.h
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 21 20 typedef int bool_t; 22 21 23 #define E_SCALL 24 #define E_IO 25 #define E_NO_MEM 26 #define E_FORK 22 #define E_SCALL 101 23 #define E_IO 102 24 #define E_NO_MEM 103 25 #define E_FORK 104 27 26 28 extern bool_t arr2envblk(char **arr, char **envblk_out );27 extern bool_t arr2envblk(char **arr, char **envblk_out, int *envsize_needed); 29 28 30 29 #endif -
vendor/gnumake/current/w32/subproc/sub_proc.c
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 19 18 #include <stdlib.h> 20 19 #include <stdio.h> 20 #include <io.h> /* for _get_osfhandle */ 21 21 #ifdef _MSC_VER 22 22 # include <stddef.h> /* for intptr_t */ … … 24 24 # include <stdint.h> 25 25 #endif 26 #include <string.h> 26 27 #include <process.h> /* for msvc _beginthreadex, _endthreadex */ 27 28 #include <signal.h> 28 29 #include <windows.h> 29 30 31 #include "makeint.h" 32 #include "filedef.h" 33 #include "variable.h" 30 34 #include "sub_proc.h" 31 35 #include "proc.h" … … 34 38 35 39 static char *make_command_line(char *shell_name, char *exec_path, char **argv); 36 extern char *xmalloc (unsigned int);37 40 38 41 typedef struct sub_process_t { 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 42 intptr_t sv_stdin[2]; 43 intptr_t sv_stdout[2]; 44 intptr_t sv_stderr[2]; 45 int using_pipes; 46 char *inp; 47 DWORD incnt; 48 char * volatile outp; 49 volatile DWORD outcnt; 50 char * volatile errp; 51 volatile DWORD errcnt; 52 pid_t pid; 53 int exit_code; 54 int signal; 55 long last_err; 56 long lerrno; 54 57 } sub_process; 55 58 … … 58 61 static int proc_index = 0; 59 62 static int fake_exits_pending = 0; 63 64 65 /* 66 * Fill a HANDLE list with handles to wait for. 67 */ 68 DWORD 69 process_set_handles(HANDLE *handles) 70 { 71 DWORD count = 0; 72 int i; 73 74 /* Build array of handles to wait for */ 75 for (i = 0; i < proc_index; i++) { 76 /* Don't wait on child processes that have already finished */ 77 if (fake_exits_pending && proc_array[i]->exit_code) 78 continue; 79 80 handles[count++] = (HANDLE) proc_array[i]->pid; 81 } 82 83 return count; 84 } 60 85 61 86 /* … … 66 91 process_adjust_wait_state(sub_process* pproc) 67 92 { 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 93 int i; 94 95 if (!proc_index) 96 return; 97 98 for (i = 0; i < proc_index; i++) 99 if (proc_array[i]->pid == pproc->pid) 100 break; 101 102 if (i < proc_index) { 103 proc_index--; 104 if (i != proc_index) 105 memmove(&proc_array[i], &proc_array[i+1], 106 (proc_index-i) * sizeof(sub_process*)); 107 proc_array[proc_index] = NULL; 108 } 84 109 } 85 110 … … 88 113 */ 89 114 static sub_process * 90 process_wait_for_any_private(void) 91 { 92 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 93 DWORD retval, which; 94 int i; 95 96 if (!proc_index) 97 return NULL; 98 99 /* build array of handles to wait for */ 100 for (i = 0; i < proc_index; i++) { 101 handles[i] = (HANDLE) proc_array[i]->pid; 102 103 if (fake_exits_pending && proc_array[i]->exit_code) 104 break; 105 } 106 107 /* wait for someone to exit */ 108 if (!fake_exits_pending) { 109 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE); 110 which = retval - WAIT_OBJECT_0; 111 } else { 112 fake_exits_pending--; 113 retval = !WAIT_FAILED; 114 which = i; 115 } 116 117 /* return pointer to process */ 118 if (retval != WAIT_FAILED) { 119 sub_process* pproc = proc_array[which]; 120 process_adjust_wait_state(pproc); 121 return pproc; 122 } else 123 return NULL; 115 process_wait_for_any_private(int block, DWORD* pdwWaitStatus) 116 { 117 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 118 DWORD retval, which; 119 int i; 120 121 if (!proc_index) 122 return NULL; 123 124 /* build array of handles to wait for */ 125 for (i = 0; i < proc_index; i++) { 126 handles[i] = (HANDLE) proc_array[i]->pid; 127 128 if (fake_exits_pending && proc_array[i]->exit_code) 129 break; 130 } 131 132 /* wait for someone to exit */ 133 if (!fake_exits_pending) { 134 retval = WaitForMultipleObjects(proc_index, handles, FALSE, (block ? INFINITE : 0)); 135 which = retval - WAIT_OBJECT_0; 136 } else { 137 fake_exits_pending--; 138 retval = !WAIT_FAILED; 139 which = i; 140 } 141 142 /* If the pointer is not NULL, set the wait status result variable. */ 143 if (pdwWaitStatus) 144 *pdwWaitStatus = retval; 145 146 /* return pointer to process */ 147 if ((retval == WAIT_TIMEOUT) || (retval == WAIT_FAILED)) { 148 return NULL; 149 } 150 else { 151 sub_process* pproc = proc_array[which]; 152 process_adjust_wait_state(pproc); 153 return pproc; 154 } 124 155 } 125 156 … … 130 161 process_kill(HANDLE proc, int signal) 131 162 { 132 133 134 163 sub_process* pproc = (sub_process*) proc; 164 pproc->signal = signal; 165 return (TerminateProcess((HANDLE) pproc->pid, signal)); 135 166 } 136 167 … … 144 175 process_register(HANDLE proc) 145 176 { 146 147 177 if (proc_index < MAXIMUM_WAIT_OBJECTS) 178 proc_array[proc_index++] = (sub_process *) proc; 148 179 } 149 180 … … 154 185 process_used_slots(void) 155 186 { 156 187 return proc_index; 157 188 } 158 189 … … 162 193 * you must do 1 of things: 163 194 * 164 * 195 * x = process_easy(...); 165 196 * 166 197 * or 167 198 * 168 * 169 * 199 * x = process_init_fd(); 200 * process_register(x); 170 201 * 171 202 * or 172 203 * 173 * 174 * 204 * x = process_init(); 205 * process_register(x); 175 206 * 176 207 * You must NOT then call process_pipe_io() because this function is … … 180 211 181 212 HANDLE 182 process_wait_for_any( void)183 { 184 sub_process* pproc = process_wait_for_any_private();185 186 187 188 189 190 191 213 process_wait_for_any(int block, DWORD* pdwWaitStatus) 214 { 215 sub_process* pproc = process_wait_for_any_private(block, pdwWaitStatus); 216 217 if (!pproc) 218 return NULL; 219 else { 220 /* 221 * Ouch! can't tell caller if this fails directly. Caller 222 * will have to use process_last_err() 192 223 */ 193 194 195 224 (void) process_file_io(pproc); 225 return ((HANDLE) pproc); 226 } 196 227 } 197 228 … … 207 238 { 208 239 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; 209 240 return (((sub_process *)proc)->last_err); 210 241 } 211 242 … … 214 245 { 215 246 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE; 216 return (((sub_process *)proc)->exit_code); 247 return (((sub_process *)proc)->exit_code); 248 } 249 250 void 251 process_noinherit(int fd) 252 { 253 HANDLE fh = (HANDLE)_get_osfhandle(fd); 254 255 if (fh && fh != INVALID_HANDLE_VALUE) 256 SetHandleInformation(fh, HANDLE_FLAG_INHERIT, 0); 217 257 } 218 258 … … 227 267 process_outbuf(HANDLE proc) 228 268 { 229 269 return (((sub_process *)proc)->outp); 230 270 } 231 271 … … 233 273 process_errbuf(HANDLE proc) 234 274 { 235 275 return (((sub_process *)proc)->errp); 236 276 } 237 277 … … 239 279 process_outcnt(HANDLE proc) 240 280 { 241 281 return (((sub_process *)proc)->outcnt); 242 282 } 243 283 … … 245 285 process_errcnt(HANDLE proc) 246 286 { 247 287 return (((sub_process *)proc)->errcnt); 248 288 } 249 289 … … 251 291 process_pipes(HANDLE proc, int pipes[3]) 252 292 { 253 254 255 256 293 pipes[0] = ((sub_process *)proc)->sv_stdin[0]; 294 pipes[1] = ((sub_process *)proc)->sv_stdout[0]; 295 pipes[2] = ((sub_process *)proc)->sv_stderr[0]; 296 return; 257 297 } 258 298 */ 259 299 260 300 HANDLE 261 301 process_init() 262 302 { 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 } 331 332 333 303 sub_process *pproc; 304 /* 305 * open file descriptors for attaching stdin/stdout/sterr 306 */ 307 HANDLE stdin_pipes[2]; 308 HANDLE stdout_pipes[2]; 309 HANDLE stderr_pipes[2]; 310 SECURITY_ATTRIBUTES inherit; 311 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; 312 313 pproc = malloc(sizeof(*pproc)); 314 memset(pproc, 0, sizeof(*pproc)); 315 316 /* We can't use NULL for lpSecurityDescriptor because that 317 uses the default security descriptor of the calling process. 318 Instead we use a security descriptor with no DACL. This 319 allows nonrestricted access to the associated objects. */ 320 321 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd), 322 SECURITY_DESCRIPTOR_REVISION)) { 323 pproc->last_err = GetLastError(); 324 pproc->lerrno = E_SCALL; 325 return((HANDLE)pproc); 326 } 327 328 inherit.nLength = sizeof(inherit); 329 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd); 330 inherit.bInheritHandle = TRUE; 331 332 // By convention, parent gets pipe[0], and child gets pipe[1] 333 // This means the READ side of stdin pipe goes into pipe[1] 334 // and the WRITE side of the stdout and stderr pipes go into pipe[1] 335 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE || 336 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE || 337 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) { 338 339 pproc->last_err = GetLastError(); 340 pproc->lerrno = E_SCALL; 341 return((HANDLE)pproc); 342 } 343 344 // 345 // Mark the parent sides of the pipes as non-inheritable 346 // 347 if (SetHandleInformation(stdin_pipes[0], 348 HANDLE_FLAG_INHERIT, 0) == FALSE || 349 SetHandleInformation(stdout_pipes[0], 350 HANDLE_FLAG_INHERIT, 0) == FALSE || 351 SetHandleInformation(stderr_pipes[0], 352 HANDLE_FLAG_INHERIT, 0) == FALSE) { 353 354 pproc->last_err = GetLastError(); 355 pproc->lerrno = E_SCALL; 356 return((HANDLE)pproc); 357 } 358 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; 359 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; 360 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; 361 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; 362 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; 363 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; 364 365 pproc->using_pipes = 1; 366 367 pproc->lerrno = 0; 368 369 return((HANDLE)pproc); 370 } 371 372 373 HANDLE 334 374 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) 335 375 { 336 sub_process *pproc; 337 338 pproc = malloc(sizeof(*pproc)); 339 memset(pproc, 0, sizeof(*pproc)); 340 341 /* 342 * Just pass the provided file handles to the 'child side' of the 343 * pipe, bypassing pipes altogether. 344 */ 345 pproc->sv_stdin[1] = (intptr_t) stdinh; 346 pproc->sv_stdout[1] = (intptr_t) stdouth; 347 pproc->sv_stderr[1] = (intptr_t) stderrh; 348 349 pproc->last_err = pproc->lerrno = 0; 350 351 return((HANDLE)pproc); 376 sub_process *pproc; 377 378 pproc = malloc(sizeof(*pproc)); 379 if (pproc) { 380 memset(pproc, 0, sizeof(*pproc)); 381 382 /* 383 * Just pass the provided file handles to the 'child 384 * side' of the pipe, bypassing pipes altogether. 385 */ 386 pproc->sv_stdin[1] = (intptr_t) stdinh; 387 pproc->sv_stdout[1] = (intptr_t) stdouth; 388 pproc->sv_stderr[1] = (intptr_t) stderrh; 389 390 pproc->last_err = pproc->lerrno = 0; 391 } 392 393 return((HANDLE)pproc); 352 394 } 353 395 … … 355 397 static HANDLE 356 398 find_file(const char *exec_path, const char *path_var, 357 char *full_fname, DWORD full_len) 358 { 359 HANDLE exec_handle; 360 char *fname; 361 char *ext; 362 DWORD req_len; 363 int i; 364 static const char *extensions[] = 365 /* Should .com come before no-extension case? */ 366 { ".exe", ".cmd", ".bat", "", ".com", NULL }; 367 368 fname = xmalloc(strlen(exec_path) + 5); 369 strcpy(fname, exec_path); 370 ext = fname + strlen(fname); 371 372 for (i = 0; extensions[i]; i++) { 373 strcpy(ext, extensions[i]); 374 if (((req_len = SearchPath (path_var, fname, NULL, full_len, 375 full_fname, NULL)) > 0 376 /* For compatibility with previous code, which 377 used OpenFile, and with Windows operation in 378 general, also look in various default 379 locations, such as Windows directory and 380 Windows System directory. Warning: this also 381 searches PATH in the Make's environment, which 382 might not be what the Makefile wants, but it 383 seems to be OK as a fallback, after the 384 previous SearchPath failed to find on child's 385 PATH. */ 386 || (req_len = SearchPath (NULL, fname, NULL, full_len, 387 full_fname, NULL)) > 0) 388 && req_len <= full_len 389 && (exec_handle = 390 CreateFile(full_fname, 391 GENERIC_READ, 392 FILE_SHARE_READ | FILE_SHARE_WRITE, 393 NULL, 394 OPEN_EXISTING, 395 FILE_ATTRIBUTE_NORMAL, 396 NULL)) != INVALID_HANDLE_VALUE) { 397 free(fname); 398 return(exec_handle); 399 } 400 } 401 402 free(fname); 403 return INVALID_HANDLE_VALUE; 399 char *full_fname, DWORD full_len) 400 { 401 HANDLE exec_handle; 402 char *fname; 403 char *ext; 404 DWORD req_len; 405 int i; 406 static const char *extensions[] = 407 /* Should .com come before no-extension case? */ 408 { ".exe", ".cmd", ".bat", "", ".com", NULL }; 409 410 fname = xmalloc(strlen(exec_path) + 5); 411 strcpy(fname, exec_path); 412 ext = fname + strlen(fname); 413 414 for (i = 0; extensions[i]; i++) { 415 strcpy(ext, extensions[i]); 416 if (((req_len = SearchPath (path_var, fname, NULL, full_len, 417 full_fname, NULL)) > 0 418 /* For compatibility with previous code, which 419 used OpenFile, and with Windows operation in 420 general, also look in various default 421 locations, such as Windows directory and 422 Windows System directory. Warning: this also 423 searches PATH in the Make's environment, which 424 might not be what the Makefile wants, but it 425 seems to be OK as a fallback, after the 426 previous SearchPath failed to find on child's 427 PATH. */ 428 || (req_len = SearchPath (NULL, fname, NULL, full_len, 429 full_fname, NULL)) > 0) 430 && req_len <= full_len 431 && (exec_handle = 432 CreateFile(full_fname, 433 GENERIC_READ, 434 FILE_SHARE_READ | FILE_SHARE_WRITE, 435 NULL, 436 OPEN_EXISTING, 437 FILE_ATTRIBUTE_NORMAL, 438 NULL)) != INVALID_HANDLE_VALUE) { 439 free(fname); 440 return(exec_handle); 441 } 442 } 443 444 free(fname); 445 return INVALID_HANDLE_VALUE; 446 } 447 448 /* 449 * Return non-zero of FNAME specifies a batch file and its name 450 * includes embedded whitespace. 451 */ 452 453 static int 454 batch_file_with_spaces(const char *fname) 455 { 456 size_t fnlen = strlen(fname); 457 458 return (fnlen > 4 459 && (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0 460 || _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0) 461 /* The set of characters in the 2nd arg to strpbrk 462 should be the same one used by make_command_line 463 below to decide whether an argv[] element needs 464 quoting. */ 465 && strpbrk(fname, " \t") != NULL); 404 466 } 405 467 … … 414 476 long 415 477 process_begin( 416 HANDLE proc, 417 char **argv, 418 char **envp, 419 char *exec_path, 420 char *as_user) 421 { 422 sub_process *pproc = (sub_process *)proc; 423 char *shell_name = 0; 424 int file_not_found=0; 425 HANDLE exec_handle; 426 char exec_fname[MAX_PATH]; 427 const char *path_var = NULL; 428 char **ep; 429 char buf[256]; 430 DWORD bytes_returned; 431 DWORD flags; 432 char *command_line; 433 STARTUPINFO startInfo; 434 PROCESS_INFORMATION procInfo; 435 char *envblk=NULL; 436 437 /* 438 * Shell script detection... if the exec_path starts with #! then 439 * we want to exec shell-script-name exec-path, not just exec-path 440 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not 441 * hard-code the path to the shell or perl or whatever: Instead, we 442 * assume it's in the path somewhere (generally, the NT tools 443 * bin directory) 444 */ 445 446 /* Use the Makefile's value of PATH to look for the program to 447 execute, because it could be different from Make's PATH 448 (e.g., if the target sets its own value. */ 449 if (envp) 450 for (ep = envp; *ep; ep++) { 451 if (strncmp (*ep, "PATH=", 5) == 0 452 || strncmp (*ep, "Path=", 5) == 0) { 453 path_var = *ep + 5; 454 break; 455 } 456 } 457 exec_handle = find_file(exec_path, path_var, 458 exec_fname, sizeof(exec_fname)); 459 460 /* 461 * If we couldn't open the file, just assume that Windows will be 462 * somehow able to find and execute it. 463 */ 464 if (exec_handle == INVALID_HANDLE_VALUE) { 465 file_not_found++; 466 } 467 else { 468 /* Attempt to read the first line of the file */ 469 if (ReadFile( exec_handle, 470 buf, sizeof(buf) - 1, /* leave room for trailing NULL */ 471 &bytes_returned, 0) == FALSE || bytes_returned < 2) { 472 473 pproc->last_err = GetLastError(); 474 pproc->lerrno = E_IO; 475 CloseHandle(exec_handle); 476 return(-1); 477 } 478 if (buf[0] == '#' && buf[1] == '!') { 479 /* 480 * This is a shell script... Change the command line from 481 * exec_path args to shell_name exec_path args 482 */ 483 char *p; 484 485 /* Make sure buf is NULL terminated */ 486 buf[bytes_returned] = 0; 487 /* 488 * Depending on the file system type, etc. the first line 489 * of the shell script may end with newline or newline-carriage-return 490 * Whatever it ends with, cut it off. 491 */ 492 p= strchr(buf, '\n'); 493 if (p) 494 *p = 0; 495 p = strchr(buf, '\r'); 496 if (p) 497 *p = 0; 498 499 /* 500 * Find base name of shell 501 */ 502 shell_name = strrchr( buf, '/'); 503 if (shell_name) { 504 shell_name++; 505 } else { 506 shell_name = &buf[2];/* skipping "#!" */ 507 } 508 509 } 510 CloseHandle(exec_handle); 511 } 512 513 flags = 0; 514 515 if (file_not_found) 516 command_line = make_command_line( shell_name, exec_path, argv); 517 else 518 command_line = make_command_line( shell_name, exec_fname, argv); 519 520 if ( command_line == NULL ) { 521 pproc->last_err = 0; 522 pproc->lerrno = E_NO_MEM; 523 return(-1); 524 } 525 526 if (envp) { 527 if (arr2envblk(envp, &envblk) ==FALSE) { 528 pproc->last_err = 0; 529 pproc->lerrno = E_NO_MEM; 530 free( command_line ); 531 return(-1); 532 } 533 } 534 535 if ((shell_name) || (file_not_found)) { 536 exec_path = 0; /* Search for the program in %Path% */ 537 } else { 538 exec_path = exec_fname; 539 } 540 541 /* 542 * Set up inherited stdin, stdout, stderr for child 543 */ 544 GetStartupInfo(&startInfo); 545 startInfo.dwFlags = STARTF_USESTDHANDLES; 546 startInfo.lpReserved = 0; 547 startInfo.cbReserved2 = 0; 548 startInfo.lpReserved2 = 0; 549 startInfo.lpTitle = shell_name ? shell_name : exec_path; 550 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; 551 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; 552 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; 553 554 if (as_user) { 555 if (envblk) free(envblk); 556 return -1; 557 } else { 558 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", 559 exec_path ? exec_path : "NULL", 560 command_line ? command_line : "NULL")); 561 if (CreateProcess( 562 exec_path, 563 command_line, 564 NULL, 565 0, /* default security attributes for thread */ 566 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ 567 flags, 568 envblk, 569 0, /* default starting directory */ 570 &startInfo, 571 &procInfo) == FALSE) { 572 573 pproc->last_err = GetLastError(); 574 pproc->lerrno = E_FORK; 575 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", 478 HANDLE proc, 479 char **argv, 480 char **envp, 481 char *exec_path, 482 char *as_user) 483 { 484 sub_process *pproc = (sub_process *)proc; 485 char *shell_name = 0; 486 int file_not_found=0; 487 HANDLE exec_handle; 488 char exec_fname[MAX_PATH]; 489 const char *path_var = NULL; 490 char **ep; 491 char buf[MAX_PATH]; 492 DWORD bytes_returned; 493 DWORD flags; 494 char *command_line; 495 STARTUPINFO startInfo; 496 PROCESS_INFORMATION procInfo; 497 char *envblk=NULL; 498 int envsize_needed = 0; 499 int pass_null_exec_path = 0; 500 501 /* 502 * Shell script detection... if the exec_path starts with #! then 503 * we want to exec shell-script-name exec-path, not just exec-path 504 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not 505 * hard-code the path to the shell or perl or whatever: Instead, we 506 * assume it's in the path somewhere (generally, the NT tools 507 * bin directory) 508 */ 509 510 /* Use the Makefile's value of PATH to look for the program to 511 execute, because it could be different from Make's PATH 512 (e.g., if the target sets its own value. */ 513 if (envp) 514 for (ep = envp; *ep; ep++) { 515 if (strncmp (*ep, "PATH=", 5) == 0 516 || strncmp (*ep, "Path=", 5) == 0) { 517 path_var = *ep + 5; 518 break; 519 } 520 } 521 exec_handle = find_file(exec_path, path_var, 522 exec_fname, sizeof(exec_fname)); 523 524 /* 525 * If we couldn't open the file, just assume that Windows will be 526 * somehow able to find and execute it. If the first character 527 * of the command is '/', assume they set SHELL to a Unixy shell 528 * that have some magic mounts known only to it, and run the whole 529 * command via $SHELL -c "COMMAND" instead. 530 */ 531 if (exec_handle == INVALID_HANDLE_VALUE) { 532 if (exec_path[0] == '/') { 533 char *new_argv0; 534 char **argvi = argv; 535 int arglen = 0; 536 537 strcpy(buf, variable_expand ("$(SHELL)")); 538 shell_name = &buf[0]; 539 strcpy(exec_fname, "-c"); 540 /* Construct a single command string in argv[0]. */ 541 while (*argvi) { 542 arglen += strlen(*argvi) + 1; 543 argvi++; 544 } 545 new_argv0 = xmalloc(arglen + 1); 546 new_argv0[0] = '\0'; 547 for (argvi = argv; *argvi; argvi++) { 548 strcat(new_argv0, *argvi); 549 strcat(new_argv0, " "); 550 } 551 /* Remove the extra blank at the end. */ 552 new_argv0[arglen-1] = '\0'; 553 free(argv[0]); 554 argv[0] = new_argv0; 555 argv[1] = NULL; 556 } 557 else 558 file_not_found++; 559 } 560 else { 561 /* Attempt to read the first line of the file */ 562 if (ReadFile( exec_handle, 563 buf, sizeof(buf) - 1, /* leave room for trailing NULL */ 564 &bytes_returned, 0) == FALSE || bytes_returned < 2) { 565 566 pproc->last_err = GetLastError(); 567 pproc->lerrno = E_IO; 568 CloseHandle(exec_handle); 569 return(-1); 570 } 571 if (buf[0] == '#' && buf[1] == '!') { 572 /* 573 * This is a shell script... Change the command line from 574 * exec_path args to shell_name exec_path args 575 */ 576 char *p; 577 578 /* Make sure buf is NULL terminated */ 579 buf[bytes_returned] = 0; 580 /* 581 * Depending on the file system type, etc. the first line 582 * of the shell script may end with newline or newline-carriage-return 583 * Whatever it ends with, cut it off. 584 */ 585 p= strchr(buf, '\n'); 586 if (p) 587 *p = 0; 588 p = strchr(buf, '\r'); 589 if (p) 590 *p = 0; 591 592 /* 593 * Find base name of shell 594 */ 595 shell_name = strrchr( buf, '/'); 596 if (shell_name) { 597 shell_name++; 598 } else { 599 shell_name = &buf[2];/* skipping "#!" */ 600 } 601 602 } 603 CloseHandle(exec_handle); 604 } 605 606 flags = 0; 607 608 if (file_not_found) 609 command_line = make_command_line( shell_name, exec_path, argv); 610 else { 611 /* If exec_fname includes whitespace, CreateProcess 612 behaves erratically and unreliably, and often fails 613 if argv[0] also includes whitespace (and thus will 614 be quoted by make_command_line below). So in that 615 case, we don't pass exec_fname as the 1st arg to 616 CreateProcess, but instead replace argv[0] with 617 exec_fname (to keep its leading directories and 618 extension as found by find_file), and pass NULL to 619 CreateProcess as its 1st arg. This works around 620 the bugs in CreateProcess, which are probably 621 caused by its passing the command to cmd.exe with 622 some incorrect quoting. */ 623 if (!shell_name 624 && batch_file_with_spaces(exec_fname) 625 && _stricmp(exec_path, argv[0]) == 0) { 626 char *new_argv, *p; 627 char **argvi; 628 int arglen, i; 629 pass_null_exec_path = 1; 630 /* Rewrite argv[] replacing argv[0] with exec_fname. */ 631 for (argvi = argv + 1, arglen = strlen(exec_fname) + 1; 632 *argvi; 633 argvi++) { 634 arglen += strlen(*argvi) + 1; 635 } 636 new_argv = xmalloc(arglen); 637 p = strcpy(new_argv, exec_fname) + strlen(exec_fname) + 1; 638 for (argvi = argv + 1, i = 1; *argvi; argvi++, i++) { 639 strcpy(p, *argvi); 640 argv[i] = p; 641 p += strlen(*argvi) + 1; 642 } 643 argv[i] = NULL; 644 free (argv[0]); 645 argv[0] = new_argv; 646 } 647 command_line = make_command_line( shell_name, exec_fname, argv); 648 } 649 650 if ( command_line == NULL ) { 651 pproc->last_err = 0; 652 pproc->lerrno = E_NO_MEM; 653 return(-1); 654 } 655 656 if (envp) { 657 if (arr2envblk(envp, &envblk, &envsize_needed) == FALSE) { 658 pproc->lerrno = E_NO_MEM; 659 free( command_line ); 660 if ((pproc->last_err == ERROR_INVALID_PARAMETER 661 || pproc->last_err == ERROR_MORE_DATA) 662 && envsize_needed > 32*1024) { 663 fprintf (stderr, "CreateProcess failed, probably because environment is too large (%d bytes).\n", 664 envsize_needed); 665 } 666 pproc->last_err = 0; 667 return(-1); 668 } 669 } 670 671 if (shell_name || file_not_found || pass_null_exec_path) { 672 exec_path = 0; /* Search for the program in %Path% */ 673 } else { 674 exec_path = exec_fname; 675 } 676 677 /* 678 * Set up inherited stdin, stdout, stderr for child 679 */ 680 memset(&startInfo, '\0', sizeof(startInfo)); 681 GetStartupInfo(&startInfo); 682 startInfo.dwFlags = STARTF_USESTDHANDLES; 683 startInfo.lpReserved = 0; 684 startInfo.cbReserved2 = 0; 685 startInfo.lpReserved2 = 0; 686 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; 687 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; 688 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; 689 690 if (as_user) { 691 free(envblk); 692 return -1; 693 } else { 694 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", 695 exec_path ? exec_path : "NULL", 696 command_line ? command_line : "NULL")); 697 if (CreateProcess( 698 exec_path, 699 command_line, 700 NULL, 701 0, /* default security attributes for thread */ 702 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ 703 flags, 704 envblk, 705 0, /* default starting directory */ 706 &startInfo, 707 &procInfo) == FALSE) { 708 709 pproc->last_err = GetLastError(); 710 pproc->lerrno = E_FORK; 711 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", 576 712 exec_path ? exec_path : "NULL", command_line); 577 if (envblk) free(envblk); 578 free( command_line ); 579 return(-1); 580 } 581 } 582 583 pproc->pid = (pid_t)procInfo.hProcess; 584 /* Close the thread handle -- we'll just watch the process */ 585 CloseHandle(procInfo.hThread); 586 587 /* Close the halves of the pipes we don't need */ 588 CloseHandle((HANDLE)pproc->sv_stdin[1]); 589 CloseHandle((HANDLE)pproc->sv_stdout[1]); 590 CloseHandle((HANDLE)pproc->sv_stderr[1]); 713 free(envblk); 714 free( command_line ); 715 return(-1); 716 } 717 } 718 719 pproc->pid = (pid_t)procInfo.hProcess; 720 /* Close the thread handle -- we'll just watch the process */ 721 CloseHandle(procInfo.hThread); 722 723 /* Close the halves of the pipes we don't need */ 724 if ((HANDLE)pproc->sv_stdin[1] != INVALID_HANDLE_VALUE) 725 CloseHandle((HANDLE)pproc->sv_stdin[1]); 726 if ((HANDLE)pproc->sv_stdout[1] != INVALID_HANDLE_VALUE) 727 CloseHandle((HANDLE)pproc->sv_stdout[1]); 728 if ((HANDLE)pproc->sv_stderr[1] != INVALID_HANDLE_VALUE) 729 CloseHandle((HANDLE)pproc->sv_stderr[1]); 591 730 pproc->sv_stdin[1] = 0; 592 731 pproc->sv_stdout[1] = 0; 593 732 pproc->sv_stderr[1] = 0; 594 733 595 free( command_line ); 596 if (envblk) free(envblk); 597 pproc->lerrno=0; 598 return 0; 599 } 600 601 602 734 free( command_line ); 735 free(envblk); 736 pproc->lerrno=0; 737 return 0; 738 } 739 740 741 742 #if 0 /* unused */ 603 743 static DWORD 604 744 proc_stdin_thread(sub_process *pproc) 605 745 { 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 746 DWORD in_done; 747 for (;;) { 748 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt, 749 &in_done, NULL) == FALSE) 750 _endthreadex(0); 751 // This if should never be true for anonymous pipes, but gives 752 // us a chance to change I/O mechanisms later 753 if (in_done < pproc->incnt) { 754 pproc->incnt -= in_done; 755 pproc->inp += in_done; 756 } else { 757 _endthreadex(0); 758 } 759 } 760 return 0; // for compiler warnings only.. not reached 621 761 } 622 762 … … 624 764 proc_stdout_thread(sub_process *pproc) 625 765 { 626 627 628 629 630 631 632 633 634 635 636 637 /* 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 766 DWORD bufsize = 1024; 767 char c; 768 DWORD nread; 769 pproc->outp = malloc(bufsize); 770 if (pproc->outp == NULL) 771 _endthreadex(0); 772 pproc->outcnt = 0; 773 774 for (;;) { 775 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) 776 == FALSE) { 777 /* map_windows32_error_to_string(GetLastError());*/ 778 _endthreadex(0); 779 } 780 if (nread == 0) 781 _endthreadex(0); 782 if (pproc->outcnt + nread > bufsize) { 783 bufsize += nread + 512; 784 pproc->outp = realloc(pproc->outp, bufsize); 785 if (pproc->outp == NULL) { 786 pproc->outcnt = 0; 787 _endthreadex(0); 788 } 789 } 790 pproc->outp[pproc->outcnt++] = c; 791 } 792 return 0; 653 793 } 654 794 … … 656 796 proc_stderr_thread(sub_process *pproc) 657 797 { 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 798 DWORD bufsize = 1024; 799 char c; 800 DWORD nread; 801 pproc->errp = malloc(bufsize); 802 if (pproc->errp == NULL) 803 _endthreadex(0); 804 pproc->errcnt = 0; 805 806 for (;;) { 807 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) { 808 map_windows32_error_to_string(GetLastError()); 809 _endthreadex(0); 810 } 811 if (nread == 0) 812 _endthreadex(0); 813 if (pproc->errcnt + nread > bufsize) { 814 bufsize += nread + 512; 815 pproc->errp = realloc(pproc->errp, bufsize); 816 if (pproc->errp == NULL) { 817 pproc->errcnt = 0; 818 _endthreadex(0); 819 } 820 } 821 pproc->errp[pproc->errcnt++] = c; 822 } 823 return 0; 684 824 } 685 825 … … 694 834 * Notes/Dependencies: 695 835 */ 696 836 long 697 837 process_pipe_io( 698 699 700 701 { 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 /* 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 838 HANDLE proc, 839 char *stdin_data, 840 int stdin_data_len) 841 { 842 sub_process *pproc = (sub_process *)proc; 843 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE; 844 HANDLE childhand = (HANDLE) pproc->pid; 845 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL; 846 unsigned int dwStdin, dwStdout, dwStderr; 847 HANDLE wait_list[4]; 848 DWORD wait_count; 849 DWORD wait_return; 850 HANDLE ready_hand; 851 bool_t child_dead = FALSE; 852 BOOL GetExitCodeResult; 853 854 /* 855 * Create stdin thread, if needed 856 */ 857 pproc->inp = stdin_data; 858 pproc->incnt = stdin_data_len; 859 if (!pproc->inp) { 860 stdin_eof = TRUE; 861 CloseHandle((HANDLE)pproc->sv_stdin[0]); 862 pproc->sv_stdin[0] = 0; 863 } else { 864 tStdin = (HANDLE) _beginthreadex( 0, 1024, 865 (unsigned (__stdcall *) (void *))proc_stdin_thread, 866 pproc, 0, &dwStdin); 867 if (tStdin == 0) { 868 pproc->last_err = GetLastError(); 869 pproc->lerrno = E_SCALL; 870 goto done; 871 } 872 } 873 874 /* 875 * Assume child will produce stdout and stderr 876 */ 877 tStdout = (HANDLE) _beginthreadex( 0, 1024, 878 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0, 879 &dwStdout); 880 tStderr = (HANDLE) _beginthreadex( 0, 1024, 881 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0, 882 &dwStderr); 883 884 if (tStdout == 0 || tStderr == 0) { 885 886 pproc->last_err = GetLastError(); 887 pproc->lerrno = E_SCALL; 888 goto done; 889 } 890 891 892 /* 893 * Wait for all I/O to finish and for the child process to exit 894 */ 895 896 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) { 897 wait_count = 0; 898 if (!stdin_eof) { 899 wait_list[wait_count++] = tStdin; 900 } 901 if (!stdout_eof) { 902 wait_list[wait_count++] = tStdout; 903 } 904 if (!stderr_eof) { 905 wait_list[wait_count++] = tStderr; 906 } 907 if (!child_dead) { 908 wait_list[wait_count++] = childhand; 909 } 910 911 wait_return = WaitForMultipleObjects(wait_count, wait_list, 912 FALSE, /* don't wait for all: one ready will do */ 913 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have 914 one second to collect all remaining output */ 915 916 if (wait_return == WAIT_FAILED) { 917 /* map_windows32_error_to_string(GetLastError());*/ 918 pproc->last_err = GetLastError(); 919 pproc->lerrno = E_SCALL; 920 goto done; 921 } 922 923 ready_hand = wait_list[wait_return - WAIT_OBJECT_0]; 924 925 if (ready_hand == tStdin) { 926 CloseHandle((HANDLE)pproc->sv_stdin[0]); 927 pproc->sv_stdin[0] = 0; 928 CloseHandle(tStdin); 929 tStdin = 0; 930 stdin_eof = TRUE; 931 932 } else if (ready_hand == tStdout) { 933 934 CloseHandle((HANDLE)pproc->sv_stdout[0]); 935 pproc->sv_stdout[0] = 0; 936 CloseHandle(tStdout); 937 tStdout = 0; 938 stdout_eof = TRUE; 939 940 } else if (ready_hand == tStderr) { 941 942 CloseHandle((HANDLE)pproc->sv_stderr[0]); 943 pproc->sv_stderr[0] = 0; 944 CloseHandle(tStderr); 945 tStderr = 0; 946 stderr_eof = TRUE; 947 948 } else if (ready_hand == childhand) { 949 950 DWORD ierr; 951 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); 952 if (ierr == CONTROL_C_EXIT) { 953 pproc->signal = SIGINT; 954 } else { 955 pproc->exit_code = ierr; 956 } 957 if (GetExitCodeResult == FALSE) { 958 pproc->last_err = GetLastError(); 959 pproc->lerrno = E_SCALL; 960 goto done; 961 } 962 child_dead = TRUE; 963 964 } else { 965 966 /* ?? Got back a handle we didn't query ?? */ 967 pproc->last_err = 0; 968 pproc->lerrno = E_FAIL; 969 goto done; 970 } 971 } 832 972 833 973 done: 834 if (tStdin != 0) 835 CloseHandle(tStdin); 836 if (tStdout != 0) 837 CloseHandle(tStdout); 838 if (tStderr != 0) 839 CloseHandle(tStderr); 840 841 if (pproc->lerrno) 842 return(-1); 843 else 844 return(0); 845 846 } 974 if (tStdin != 0) 975 CloseHandle(tStdin); 976 if (tStdout != 0) 977 CloseHandle(tStdout); 978 if (tStderr != 0) 979 CloseHandle(tStderr); 980 981 if (pproc->lerrno) 982 return(-1); 983 else 984 return(0); 985 986 } 987 #endif /* unused */ 847 988 848 989 /* … … 855 996 * Notes/Dependencies: 856 997 */ 857 998 long 858 999 process_file_io( 859 860 { 861 862 863 864 1000 HANDLE proc) 1001 { 1002 sub_process *pproc; 1003 HANDLE childhand; 1004 DWORD wait_return; 1005 BOOL GetExitCodeResult; 865 1006 DWORD ierr; 866 1007 867 868 pproc = process_wait_for_any_private();869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 /* 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 1008 if (proc == NULL) 1009 pproc = process_wait_for_any_private(1, 0); 1010 else 1011 pproc = (sub_process *)proc; 1012 1013 /* some sort of internal error */ 1014 if (!pproc) 1015 return -1; 1016 1017 childhand = (HANDLE) pproc->pid; 1018 1019 /* 1020 * This function is poorly named, and could also be used just to wait 1021 * for child death if you're doing your own pipe I/O. If that is 1022 * the case, close the pipe handles here. 1023 */ 1024 if (pproc->sv_stdin[0]) { 1025 CloseHandle((HANDLE)pproc->sv_stdin[0]); 1026 pproc->sv_stdin[0] = 0; 1027 } 1028 if (pproc->sv_stdout[0]) { 1029 CloseHandle((HANDLE)pproc->sv_stdout[0]); 1030 pproc->sv_stdout[0] = 0; 1031 } 1032 if (pproc->sv_stderr[0]) { 1033 CloseHandle((HANDLE)pproc->sv_stderr[0]); 1034 pproc->sv_stderr[0] = 0; 1035 } 1036 1037 /* 1038 * Wait for the child process to exit 1039 */ 1040 1041 wait_return = WaitForSingleObject(childhand, INFINITE); 1042 1043 if (wait_return != WAIT_OBJECT_0) { 1044 /* map_windows32_error_to_string(GetLastError());*/ 1045 pproc->last_err = GetLastError(); 1046 pproc->lerrno = E_SCALL; 1047 goto done2; 1048 } 1049 1050 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); 1051 if (ierr == CONTROL_C_EXIT) { 1052 pproc->signal = SIGINT; 1053 } else { 1054 pproc->exit_code = ierr; 1055 } 1056 if (GetExitCodeResult == FALSE) { 1057 pproc->last_err = GetLastError(); 1058 pproc->lerrno = E_SCALL; 1059 } 919 1060 920 1061 done2: 921 922 923 924 1062 if (pproc->lerrno) 1063 return(-1); 1064 else 1065 return(0); 925 1066 926 1067 } … … 928 1069 /* 929 1070 * Description: Clean up any leftover handles, etc. It is up to the 930 * caller to manage and free the input, ou put, and stderr buffers.1071 * caller to manage and free the input, output, and stderr buffers. 931 1072 */ 932 1073 void 933 1074 process_cleanup( 934 HANDLE proc) 935 { 936 sub_process *pproc = (sub_process *)proc; 937 int i; 938 939 if (pproc->using_pipes) { 940 for (i= 0; i <= 1; i++) { 941 if ((HANDLE)pproc->sv_stdin[i]) 942 CloseHandle((HANDLE)pproc->sv_stdin[i]); 943 if ((HANDLE)pproc->sv_stdout[i]) 944 CloseHandle((HANDLE)pproc->sv_stdout[i]); 945 if ((HANDLE)pproc->sv_stderr[i]) 946 CloseHandle((HANDLE)pproc->sv_stderr[i]); 947 } 948 } 949 if ((HANDLE)pproc->pid) 950 CloseHandle((HANDLE)pproc->pid); 951 952 free(pproc); 1075 HANDLE proc) 1076 { 1077 sub_process *pproc = (sub_process *)proc; 1078 int i; 1079 1080 if (pproc->using_pipes) { 1081 for (i= 0; i <= 1; i++) { 1082 if ((HANDLE)pproc->sv_stdin[i] 1083 && (HANDLE)pproc->sv_stdin[i] != INVALID_HANDLE_VALUE) 1084 CloseHandle((HANDLE)pproc->sv_stdin[i]); 1085 if ((HANDLE)pproc->sv_stdout[i] 1086 && (HANDLE)pproc->sv_stdout[i] != INVALID_HANDLE_VALUE) 1087 CloseHandle((HANDLE)pproc->sv_stdout[i]); 1088 if ((HANDLE)pproc->sv_stderr[i] 1089 && (HANDLE)pproc->sv_stderr[i] != INVALID_HANDLE_VALUE) 1090 CloseHandle((HANDLE)pproc->sv_stderr[i]); 1091 } 1092 } 1093 if ((HANDLE)pproc->pid) 1094 CloseHandle((HANDLE)pproc->pid); 1095 1096 free(pproc); 953 1097 } 954 1098 … … 956 1100 /* 957 1101 * Description: 958 * 1102 * Create a command line buffer to pass to CreateProcess 959 1103 * 960 1104 * Returns: the buffer or NULL for failure 961 * 1105 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... 962 1106 * Otherwise: argv[0] argv[1] argv[2] ... 963 1107 * … … 970 1114 make_command_line( char *shell_name, char *full_exec_path, char **argv) 971 1115 { 972 intargc = 0;973 char**argvi;974 int*enclose_in_quotes = NULL;975 int*enclose_in_quotes_i;976 unsigned intbytes_required = 0;977 char*command_line;978 char*command_line_i;979 980 1116 int argc = 0; 1117 char** argvi; 1118 int* enclose_in_quotes = NULL; 1119 int* enclose_in_quotes_i; 1120 unsigned int bytes_required = 0; 1121 char* command_line; 1122 char* command_line_i; 1123 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */ 1124 int have_sh = 0; /* HAVE_CYGWIN_SHELL */ 981 1125 982 1126 #ifdef HAVE_CYGWIN_SHELL 983 984 1127 have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe")); 1128 cygwin_mode = 1; 985 1129 #endif 986 1130 987 if (shell_name && full_exec_path) { 988 bytes_required 989 = strlen(shell_name) + 1 + strlen(full_exec_path); 990 /* 991 * Skip argv[0] if any, when shell_name is given. 992 */ 993 if (*argv) argv++; 994 /* 995 * Add one for the intervening space. 996 */ 997 if (*argv) bytes_required++; 998 } 999 1000 argvi = argv; 1001 while (*(argvi++)) argc++; 1002 1003 if (argc) { 1004 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); 1005 1006 if (!enclose_in_quotes) { 1007 return NULL; 1008 } 1009 } 1010 1011 /* We have to make one pass through each argv[i] to see if we need 1012 * to enclose it in ", so we might as well figure out how much 1013 * memory we'll need on the same pass. 1014 */ 1015 1016 argvi = argv; 1017 enclose_in_quotes_i = enclose_in_quotes; 1018 while(*argvi) { 1019 char* p = *argvi; 1020 unsigned int backslash_count = 0; 1021 1022 /* 1023 * We have to enclose empty arguments in ". 1024 */ 1025 if (!(*p)) *enclose_in_quotes_i = 1; 1026 1027 while(*p) { 1028 switch (*p) { 1029 case '\"': 1030 /* 1031 * We have to insert a backslash for each " 1032 * and each \ that precedes the ". 1033 */ 1034 bytes_required += (backslash_count + 1); 1035 backslash_count = 0; 1036 break; 1131 if (shell_name && full_exec_path) { 1132 bytes_required 1133 = strlen(shell_name) + 1 + strlen(full_exec_path); 1134 /* 1135 * Skip argv[0] if any, when shell_name is given. 1136 * The special case of "-c" in full_exec_path means 1137 * argv[0] is not the shell name, but the command string 1138 * to pass to the shell. 1139 */ 1140 if (*argv && strcmp(full_exec_path, "-c")) argv++; 1141 /* 1142 * Add one for the intervening space. 1143 */ 1144 if (*argv) bytes_required++; 1145 } 1146 1147 argvi = argv; 1148 while (*(argvi++)) argc++; 1149 1150 if (argc) { 1151 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); 1152 1153 if (!enclose_in_quotes) { 1154 return NULL; 1155 } 1156 } 1157 1158 /* We have to make one pass through each argv[i] to see if we need 1159 * to enclose it in ", so we might as well figure out how much 1160 * memory we'll need on the same pass. 1161 */ 1162 1163 argvi = argv; 1164 enclose_in_quotes_i = enclose_in_quotes; 1165 while(*argvi) { 1166 char* p = *argvi; 1167 unsigned int backslash_count = 0; 1168 1169 /* 1170 * We have to enclose empty arguments in ". 1171 */ 1172 if (!(*p)) *enclose_in_quotes_i = 1; 1173 1174 while(*p) { 1175 switch (*p) { 1176 case '\"': 1177 /* 1178 * We have to insert a backslash for each " 1179 * and each \ that precedes the ". 1180 */ 1181 bytes_required += (backslash_count + 1); 1182 backslash_count = 0; 1183 break; 1037 1184 1038 1185 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1039 1040 1041 1186 case '\\': 1187 backslash_count++; 1188 break; 1042 1189 #endif 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 if (enclose_in_quotes)free(enclose_in_quotes);1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1190 /* 1191 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress 1192 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so 1193 * that argv in always equals argv out. This was removed. Say you have 1194 * such a program named glob.exe. You enter 1195 * glob '*' 1196 * at the sh command prompt. Obviously the intent is to make glob do the 1197 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', 1198 * then the command line that glob would see would be 1199 * glob "*" 1200 * and the _setargv in SETARGV.OBJ would _not_ expand the *. 1201 */ 1202 case ' ': 1203 case '\t': 1204 *enclose_in_quotes_i = 1; 1205 /* fall through */ 1206 1207 default: 1208 backslash_count = 0; 1209 break; 1210 } 1211 1212 /* 1213 * Add one for each character in argv[i]. 1214 */ 1215 bytes_required++; 1216 1217 p++; 1218 } 1219 1220 if (*enclose_in_quotes_i) { 1221 /* 1222 * Add one for each enclosing ", 1223 * and one for each \ that precedes the 1224 * closing ". 1225 */ 1226 bytes_required += (backslash_count + 2); 1227 } 1228 1229 /* 1230 * Add one for the intervening space. 1231 */ 1232 if (*(++argvi)) bytes_required++; 1233 enclose_in_quotes_i++; 1234 } 1235 1236 /* 1237 * Add one for the terminating NULL. 1238 */ 1239 bytes_required++; 1240 1241 command_line = (char*) malloc(bytes_required); 1242 1243 if (!command_line) { 1244 free(enclose_in_quotes); 1245 return NULL; 1246 } 1247 1248 command_line_i = command_line; 1249 1250 if (shell_name && full_exec_path) { 1251 while(*shell_name) { 1252 *(command_line_i++) = *(shell_name++); 1253 } 1254 1255 *(command_line_i++) = ' '; 1256 1257 while(*full_exec_path) { 1258 *(command_line_i++) = *(full_exec_path++); 1259 } 1260 1261 if (*argv) { 1262 *(command_line_i++) = ' '; 1263 } 1264 } 1265 1266 argvi = argv; 1267 enclose_in_quotes_i = enclose_in_quotes; 1268 1269 while(*argvi) { 1270 char* p = *argvi; 1271 unsigned int backslash_count = 0; 1272 1273 if (*enclose_in_quotes_i) { 1274 *(command_line_i++) = '\"'; 1275 } 1276 1277 while(*p) { 1278 if (*p == '\"') { 1279 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */ 1280 /* instead of a \", cygwin likes "" */ 1281 *(command_line_i++) = '\"'; 1282 } else { 1283 1284 /* 1285 * We have to insert a backslash for the " 1286 * and each \ that precedes the ". 1287 */ 1288 backslash_count++; 1289 1290 while(backslash_count) { 1291 *(command_line_i++) = '\\'; 1292 backslash_count--; 1293 }; 1294 } 1148 1295 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1149 1150 1151 1152 1296 } else if (*p == '\\') { 1297 backslash_count++; 1298 } else { 1299 backslash_count = 0; 1153 1300 #endif 1154 1155 1156 1157 1158 1159 1160 1161 1162 1301 } 1302 1303 /* 1304 * Copy the character. 1305 */ 1306 *(command_line_i++) = *(p++); 1307 } 1308 1309 if (*enclose_in_quotes_i) { 1163 1310 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1164 1165 1166 1167 1168 1169 1170 1311 /* 1312 * Add one \ for each \ that precedes the 1313 * closing ". 1314 */ 1315 while(backslash_count--) { 1316 *(command_line_i++) = '\\'; 1317 }; 1171 1318 #endif 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 if (enclose_in_quotes)free(enclose_in_quotes);1191 1319 *(command_line_i++) = '\"'; 1320 } 1321 1322 /* 1323 * Append an intervening space. 1324 */ 1325 if (*(++argvi)) { 1326 *(command_line_i++) = ' '; 1327 } 1328 1329 enclose_in_quotes_i++; 1330 } 1331 1332 /* 1333 * Append the terminating NULL. 1334 */ 1335 *command_line_i = '\0'; 1336 1337 free(enclose_in_quotes); 1338 return command_line; 1192 1339 } 1193 1340 … … 1196 1343 * using the default stdin, stdout, and stderr handles. 1197 1344 * Also, register process so that process_wait_for_any_private() 1198 * 1199 * 1345 * can be used via process_file_io(NULL) or 1346 * process_wait_for_any(). 1200 1347 * 1201 1348 * Returns: … … 1205 1352 HANDLE 1206 1353 process_easy( 1207 char **argv, 1208 char **envp) 1209 { 1210 HANDLE hIn; 1211 HANDLE hOut; 1212 HANDLE hErr; 1213 HANDLE hProcess; 1354 char **argv, 1355 char **envp, 1356 int outfd, 1357 int errfd) 1358 { 1359 HANDLE hIn = INVALID_HANDLE_VALUE; 1360 HANDLE hOut = INVALID_HANDLE_VALUE; 1361 HANDLE hErr = INVALID_HANDLE_VALUE; 1362 HANDLE hProcess, tmpIn, tmpOut, tmpErr; 1363 DWORD e; 1214 1364 1215 1365 if (proc_index >= MAXIMUM_WAIT_OBJECTS) { 1216 1217 1366 DB (DB_JOBS, ("process_easy: All process slots used up\n")); 1367 return INVALID_HANDLE_VALUE; 1218 1368 } 1369 /* Standard handles returned by GetStdHandle can be NULL or 1370 INVALID_HANDLE_VALUE if the parent process closed them. If that 1371 happens, we open the null device and pass its handle to 1372 CreateProcess as the corresponding handle to inherit. */ 1373 tmpIn = GetStdHandle(STD_INPUT_HANDLE); 1219 1374 if (DuplicateHandle(GetCurrentProcess(), 1220 GetStdHandle(STD_INPUT_HANDLE),1375 tmpIn, 1221 1376 GetCurrentProcess(), 1222 1377 &hIn, … … 1224 1379 TRUE, 1225 1380 DUPLICATE_SAME_ACCESS) == FALSE) { 1226 fprintf(stderr, 1227 "process_easy: DuplicateHandle(In) failed (e=%ld)\n", 1228 GetLastError()); 1229 return INVALID_HANDLE_VALUE; 1381 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { 1382 tmpIn = CreateFile("NUL", GENERIC_READ, 1383 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1384 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1385 if (tmpIn != INVALID_HANDLE_VALUE 1386 && DuplicateHandle(GetCurrentProcess(), 1387 tmpIn, 1388 GetCurrentProcess(), 1389 &hIn, 1390 0, 1391 TRUE, 1392 DUPLICATE_SAME_ACCESS) == FALSE) 1393 CloseHandle(tmpIn); 1394 } 1395 if (hIn == INVALID_HANDLE_VALUE) { 1396 fprintf(stderr, "process_easy: DuplicateHandle(In) failed (e=%ld)\n", e); 1397 return INVALID_HANDLE_VALUE; 1398 } 1230 1399 } 1400 if (outfd >= 0) 1401 tmpOut = (HANDLE)_get_osfhandle (outfd); 1402 else 1403 tmpOut = GetStdHandle (STD_OUTPUT_HANDLE); 1231 1404 if (DuplicateHandle(GetCurrentProcess(), 1232 GetStdHandle(STD_OUTPUT_HANDLE),1405 tmpOut, 1233 1406 GetCurrentProcess(), 1234 1407 &hOut, … … 1236 1409 TRUE, 1237 1410 DUPLICATE_SAME_ACCESS) == FALSE) { 1238 fprintf(stderr, 1239 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", 1240 GetLastError()); 1241 return INVALID_HANDLE_VALUE; 1411 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { 1412 tmpOut = CreateFile("NUL", GENERIC_WRITE, 1413 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1414 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1415 if (tmpOut != INVALID_HANDLE_VALUE 1416 && DuplicateHandle(GetCurrentProcess(), 1417 tmpOut, 1418 GetCurrentProcess(), 1419 &hOut, 1420 0, 1421 TRUE, 1422 DUPLICATE_SAME_ACCESS) == FALSE) 1423 CloseHandle(tmpOut); 1424 } 1425 if (hOut == INVALID_HANDLE_VALUE) { 1426 fprintf(stderr, "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", e); 1427 return INVALID_HANDLE_VALUE; 1428 } 1242 1429 } 1430 if (errfd >= 0) 1431 tmpErr = (HANDLE)_get_osfhandle (errfd); 1432 else 1433 tmpErr = GetStdHandle(STD_ERROR_HANDLE); 1243 1434 if (DuplicateHandle(GetCurrentProcess(), 1244 GetStdHandle(STD_ERROR_HANDLE),1435 tmpErr, 1245 1436 GetCurrentProcess(), 1246 1437 &hErr, … … 1248 1439 TRUE, 1249 1440 DUPLICATE_SAME_ACCESS) == FALSE) { 1250 fprintf(stderr, 1251 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", 1252 GetLastError()); 1253 return INVALID_HANDLE_VALUE; 1441 if ((e = GetLastError()) == ERROR_INVALID_HANDLE) { 1442 tmpErr = CreateFile("NUL", GENERIC_WRITE, 1443 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, 1444 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1445 if (tmpErr != INVALID_HANDLE_VALUE 1446 && DuplicateHandle(GetCurrentProcess(), 1447 tmpErr, 1448 GetCurrentProcess(), 1449 &hErr, 1450 0, 1451 TRUE, 1452 DUPLICATE_SAME_ACCESS) == FALSE) 1453 CloseHandle(tmpErr); 1454 } 1455 if (hErr == INVALID_HANDLE_VALUE) { 1456 fprintf(stderr, "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", e); 1457 return INVALID_HANDLE_VALUE; 1458 } 1254 1459 } 1255 1460 … … 1264 1469 1265 1470 /* close up unused handles */ 1266 CloseHandle(hIn); 1267 CloseHandle(hOut); 1268 CloseHandle(hErr); 1471 if (hIn != INVALID_HANDLE_VALUE) 1472 CloseHandle(hIn); 1473 if (hOut != INVALID_HANDLE_VALUE) 1474 CloseHandle(hOut); 1475 if (hErr != INVALID_HANDLE_VALUE) 1476 CloseHandle(hErr); 1269 1477 } 1270 1478 -
vendor/gnumake/current/w32/subproc/w32err.c
r2596 r3138 1 1 /* 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. 2 Copyright (C) 1996-2016 Free Software Foundation, Inc. 4 3 This file is part of GNU Make. 5 4 … … 16 15 this program. If not, see <http://www.gnu.org/licenses/>. */ 17 16 17 #include <stdlib.h> 18 18 #include <windows.h> 19 #include "makeint.h" 19 20 #include "w32err.h" 20 21 … … 27 28 * comp.os.ms-windows.programmer.win32 28 29 */ 29 c har *30 const char * 30 31 map_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 */ 40 51 wsprintf (szMessageBuffer, "Error %ld\n", ercode); 41 52 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 } 69 84 return szMessageBuffer; 70 85 }
Note:
See TracChangeset
for help on using the changeset viewer.