1 /* Process handling for Windows. 2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 3 2006 Free Software Foundation, Inc. 4 This file is part of GNU Make. 5 6 GNU Make is free software; you can redistribute it and/or modify it under the 7 terms of the GNU General Public License as published by the Free Software 8 Foundation; either version 2, or (at your option) any later version. 9 10 GNU Make is distributed in the hope that it will be useful, but WITHOUT ANY 11 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR 12 A PARTICULAR PURPOSE. See the GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License along with 15 GNU Make; see the file COPYING. If not, write to the Free Software 16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. */ 17 18 #include <stdlib.h> 19 #include <stdio.h> 20 #include <process.h> /* for msvc _beginthreadex, _endthreadex */ 21 #include <signal.h> 22 #include <windows.h> 23 24 #include "sub_proc.h" 25 #include "proc.h" 26 #include "w32err.h" 27 #include "config.h" 28 #include "debug.h" 29 30 static char *make_command_line(char *shell_name, char *exec_path, char **argv); 31 32 typedef struct sub_process_t { 33 intptr_t sv_stdin[2]; 34 intptr_t sv_stdout[2]; 35 intptr_t sv_stderr[2]; 36 int using_pipes; 37 char *inp; 38 DWORD incnt; 39 char * volatile outp; 40 volatile DWORD outcnt; 41 char * volatile errp; 42 volatile DWORD errcnt; 43 intptr_t pid; 44 int exit_code; 45 int signal; 46 long last_err; 47 long lerrno; 48 } sub_process; 49 50 /* keep track of children so we can implement a waitpid-like routine */ 51 static sub_process *proc_array[MAXIMUM_WAIT_OBJECTS]; 52 static int proc_index = 0; 53 static int fake_exits_pending = 0; 54 55 /* 56 * When a process has been waited for, adjust the wait state 57 * array so that we don't wait for it again 58 */ 59 static void 60 process_adjust_wait_state(sub_process* pproc) 61 { 62 int i; 63 64 if (!proc_index) 65 return; 66 67 for (i = 0; i < proc_index; i++) 68 if (proc_array[i]->pid == pproc->pid) 69 break; 70 71 if (i < proc_index) { 72 proc_index--; 73 if (i != proc_index) 74 memmove(&proc_array[i], &proc_array[i+1], 75 (proc_index-i) * sizeof(sub_process*)); 76 proc_array[proc_index] = NULL; 77 } 78 } 79 80 /* 81 * Waits for any of the registered child processes to finish. 82 */ 83 static sub_process * 84 process_wait_for_any_private(void) 85 { 86 HANDLE handles[MAXIMUM_WAIT_OBJECTS]; 87 DWORD retval, which; 88 int i; 89 90 if (!proc_index) 91 return NULL; 92 93 /* build array of handles to wait for */ 94 for (i = 0; i < proc_index; i++) { 95 handles[i] = (HANDLE) proc_array[i]->pid; 96 97 if (fake_exits_pending && proc_array[i]->exit_code) 98 break; 99 } 100 101 /* wait for someone to exit */ 102 if (!fake_exits_pending) { 103 retval = WaitForMultipleObjects(proc_index, handles, FALSE, INFINITE); 104 which = retval - WAIT_OBJECT_0; 105 } else { 106 fake_exits_pending--; 107 retval = !WAIT_FAILED; 108 which = i; 109 } 110 111 /* return pointer to process */ 112 if (retval != WAIT_FAILED) { 113 sub_process* pproc = proc_array[which]; 114 process_adjust_wait_state(pproc); 115 return pproc; 116 } else 117 return NULL; 118 } 119 120 /* 121 * Terminate a process. 122 */ 123 BOOL 124 process_kill(HANDLE proc, int signal) 125 { 126 sub_process* pproc = (sub_process*) proc; 127 pproc->signal = signal; 128 return (TerminateProcess((HANDLE) pproc->pid, signal)); 129 } 130 131 /* 132 * Use this function to register processes you wish to wait for by 133 * calling process_file_io(NULL) or process_wait_any(). This must be done 134 * because it is possible for callers of this library to reuse the same 135 * handle for multiple processes launches :-( 136 */ 137 void 138 process_register(HANDLE proc) 139 { 140 if (proc_index < MAXIMUM_WAIT_OBJECTS) 141 proc_array[proc_index++] = (sub_process *) proc; 142 } 143 144 /* 145 * Return the number of processes that we are still waiting for. 146 */ 147 int 148 process_used_slots(void) 149 { 150 return proc_index; 151 } 152 153 /* 154 * Public function which works kind of like waitpid(). Wait for any 155 * of the children to die and return results. To call this function, 156 * you must do 1 of things: 157 * 158 * x = process_easy(...); 159 * 160 * or 161 * 162 * x = process_init_fd(); 163 * process_register(x); 164 * 165 * or 166 * 167 * x = process_init(); 168 * process_register(x); 169 * 170 * You must NOT then call process_pipe_io() because this function is 171 * not capable of handling automatic notification of any child 172 * death. 173 */ 174 175 HANDLE 176 process_wait_for_any(void) 177 { 178 sub_process* pproc = process_wait_for_any_private(); 179 180 if (!pproc) 181 return NULL; 182 else { 183 /* 184 * Ouch! can't tell caller if this fails directly. Caller 185 * will have to use process_last_err() 186 */ 187 (void) process_file_io(pproc); 188 return ((HANDLE) pproc); 189 } 190 } 191 192 long 193 process_signal(HANDLE proc) 194 { 195 if (proc == INVALID_HANDLE_VALUE) return 0; 196 return (((sub_process *)proc)->signal); 197 } 198 199 long 200 process_last_err(HANDLE proc) 201 { 202 if (proc == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; 203 return (((sub_process *)proc)->last_err); 204 } 205 206 long 207 process_exit_code(HANDLE proc) 208 { 209 if (proc == INVALID_HANDLE_VALUE) return EXIT_FAILURE; 210 return (((sub_process *)proc)->exit_code); 211 } 212 213 /* 214 2006-02: 215 All the following functions are currently unused. 216 All of them would crash gmake if called with argument INVALID_HANDLE_VALUE. 217 Hence whoever wants to use one of this functions must invent and implement 218 a reasonable error handling for this function. 219 220 char * 221 process_outbuf(HANDLE proc) 222 { 223 return (((sub_process *)proc)->outp); 224 } 225 226 char * 227 process_errbuf(HANDLE proc) 228 { 229 return (((sub_process *)proc)->errp); 230 } 231 232 int 233 process_outcnt(HANDLE proc) 234 { 235 return (((sub_process *)proc)->outcnt); 236 } 237 238 int 239 process_errcnt(HANDLE proc) 240 { 241 return (((sub_process *)proc)->errcnt); 242 } 243 244 void 245 process_pipes(HANDLE proc, int pipes[3]) 246 { 247 pipes[0] = ((sub_process *)proc)->sv_stdin[0]; 248 pipes[1] = ((sub_process *)proc)->sv_stdout[0]; 249 pipes[2] = ((sub_process *)proc)->sv_stderr[0]; 250 return; 251 } 252 */ 253 254 HANDLE 255 process_init() 256 { 257 sub_process *pproc; 258 /* 259 * open file descriptors for attaching stdin/stdout/sterr 260 */ 261 HANDLE stdin_pipes[2]; 262 HANDLE stdout_pipes[2]; 263 HANDLE stderr_pipes[2]; 264 SECURITY_ATTRIBUTES inherit; 265 BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH]; 266 267 pproc = malloc(sizeof(*pproc)); 268 memset(pproc, 0, sizeof(*pproc)); 269 270 /* We can't use NULL for lpSecurityDescriptor because that 271 uses the default security descriptor of the calling process. 272 Instead we use a security descriptor with no DACL. This 273 allows nonrestricted access to the associated objects. */ 274 275 if (!InitializeSecurityDescriptor((PSECURITY_DESCRIPTOR)(&sd), 276 SECURITY_DESCRIPTOR_REVISION)) { 277 pproc->last_err = GetLastError(); 278 pproc->lerrno = E_SCALL; 279 return((HANDLE)pproc); 280 } 281 282 inherit.nLength = sizeof(inherit); 283 inherit.lpSecurityDescriptor = (PSECURITY_DESCRIPTOR)(&sd); 284 inherit.bInheritHandle = TRUE; 285 286 // By convention, parent gets pipe[0], and child gets pipe[1] 287 // This means the READ side of stdin pipe goes into pipe[1] 288 // and the WRITE side of the stdout and stderr pipes go into pipe[1] 289 if (CreatePipe( &stdin_pipes[1], &stdin_pipes[0], &inherit, 0) == FALSE || 290 CreatePipe( &stdout_pipes[0], &stdout_pipes[1], &inherit, 0) == FALSE || 291 CreatePipe( &stderr_pipes[0], &stderr_pipes[1], &inherit, 0) == FALSE) { 292 293 pproc->last_err = GetLastError(); 294 pproc->lerrno = E_SCALL; 295 return((HANDLE)pproc); 296 } 297 298 // 299 // Mark the parent sides of the pipes as non-inheritable 300 // 301 if (SetHandleInformation(stdin_pipes[0], 302 HANDLE_FLAG_INHERIT, 0) == FALSE || 303 SetHandleInformation(stdout_pipes[0], 304 HANDLE_FLAG_INHERIT, 0) == FALSE || 305 SetHandleInformation(stderr_pipes[0], 306 HANDLE_FLAG_INHERIT, 0) == FALSE) { 307 308 pproc->last_err = GetLastError(); 309 pproc->lerrno = E_SCALL; 310 return((HANDLE)pproc); 311 } 312 pproc->sv_stdin[0] = (intptr_t) stdin_pipes[0]; 313 pproc->sv_stdin[1] = (intptr_t) stdin_pipes[1]; 314 pproc->sv_stdout[0] = (intptr_t) stdout_pipes[0]; 315 pproc->sv_stdout[1] = (intptr_t) stdout_pipes[1]; 316 pproc->sv_stderr[0] = (intptr_t) stderr_pipes[0]; 317 pproc->sv_stderr[1] = (intptr_t) stderr_pipes[1]; 318 319 pproc->using_pipes = 1; 320 321 pproc->lerrno = 0; 322 323 return((HANDLE)pproc); 324 } 325 326 327 HANDLE 328 process_init_fd(HANDLE stdinh, HANDLE stdouth, HANDLE stderrh) 329 { 330 sub_process *pproc; 331 332 pproc = malloc(sizeof(*pproc)); 333 memset(pproc, 0, sizeof(*pproc)); 334 335 /* 336 * Just pass the provided file handles to the 'child side' of the 337 * pipe, bypassing pipes altogether. 338 */ 339 pproc->sv_stdin[1] = (intptr_t) stdinh; 340 pproc->sv_stdout[1] = (intptr_t) stdouth; 341 pproc->sv_stderr[1] = (intptr_t) stderrh; 342 343 pproc->last_err = pproc->lerrno = 0; 344 345 return((HANDLE)pproc); 346 } 347 348 349 static HANDLE 350 find_file(char *exec_path, LPOFSTRUCT file_info) 351 { 352 HANDLE exec_handle; 353 char *fname; 354 char *ext; 355 356 fname = malloc(strlen(exec_path) + 5); 357 strcpy(fname, exec_path); 358 ext = fname + strlen(fname); 359 360 strcpy(ext, ".exe"); 361 if ((exec_handle = (HANDLE)(intptr_t)OpenFile(fname, file_info, 362 OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { 363 free(fname); 364 return(exec_handle); 365 } 366 367 strcpy(ext, ".cmd"); 368 if ((exec_handle = (HANDLE)(intptr_t)OpenFile(fname, file_info, 369 OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { 370 free(fname); 371 return(exec_handle); 372 } 373 374 strcpy(ext, ".bat"); 375 if ((exec_handle = (HANDLE)(intptr_t)OpenFile(fname, file_info, 376 OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { 377 free(fname); 378 return(exec_handle); 379 } 380 381 /* should .com come before this case? */ 382 if ((exec_handle = (HANDLE)(intptr_t)OpenFile(exec_path, file_info, 383 OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { 384 free(fname); 385 return(exec_handle); 386 } 387 388 strcpy(ext, ".com"); 389 if ((exec_handle = (HANDLE)(intptr_t)OpenFile(fname, file_info, 390 OF_READ | OF_SHARE_COMPAT)) != (HANDLE)HFILE_ERROR) { 391 free(fname); 392 return(exec_handle); 393 } 394 395 free(fname); 396 return(exec_handle); 397 } 398 399 400 /* 401 * Description: Create the child process to be helped 402 * 403 * Returns: success <=> 0 404 * 405 * Notes/Dependencies: 406 */ 407 long 408 process_begin( 409 HANDLE proc, 410 char **argv, 411 char **envp, 412 char *exec_path, 413 char *as_user) 414 { 415 sub_process *pproc = (sub_process *)proc; 416 char *shell_name = 0; 417 int file_not_found=0; 418 HANDLE exec_handle; 419 char buf[256]; 420 DWORD bytes_returned; 421 DWORD flags; 422 char *command_line; 423 STARTUPINFO startInfo; 424 PROCESS_INFORMATION procInfo; 425 char *envblk=NULL; 426 OFSTRUCT file_info; 427 428 429 /* 430 * Shell script detection... if the exec_path starts with #! then 431 * we want to exec shell-script-name exec-path, not just exec-path 432 * NT doesn't recognize #!/bin/sh or #!/etc/Tivoli/bin/perl. We do not 433 * hard-code the path to the shell or perl or whatever: Instead, we 434 * assume it's in the path somewhere (generally, the NT tools 435 * bin directory) 436 * We use OpenFile here because it is capable of searching the Path. 437 */ 438 439 exec_handle = find_file(exec_path, &file_info); 440 441 /* 442 * If we couldn't open the file, just assume that Windows32 will be able 443 * to find and execute it. 444 */ 445 if (exec_handle == (HANDLE)HFILE_ERROR) { 446 file_not_found++; 447 } 448 else { 449 /* Attempt to read the first line of the file */ 450 if (ReadFile( exec_handle, 451 buf, sizeof(buf) - 1, /* leave room for trailing NULL */ 452 &bytes_returned, 0) == FALSE || bytes_returned < 2) { 453 454 pproc->last_err = GetLastError(); 455 pproc->lerrno = E_IO; 456 CloseHandle(exec_handle); 457 return(-1); 458 } 459 if (buf[0] == '#' && buf[1] == '!') { 460 /* 461 * This is a shell script... Change the command line from 462 * exec_path args to shell_name exec_path args 463 */ 464 char *p; 465 466 /* Make sure buf is NULL terminated */ 467 buf[bytes_returned] = 0; 468 /* 469 * Depending on the file system type, etc. the first line 470 * of the shell script may end with newline or newline-carriage-return 471 * Whatever it ends with, cut it off. 472 */ 473 p= strchr(buf, '\n'); 474 if (p) 475 *p = 0; 476 p = strchr(buf, '\r'); 477 if (p) 478 *p = 0; 479 480 /* 481 * Find base name of shell 482 */ 483 shell_name = strrchr( buf, '/'); 484 if (shell_name) { 485 shell_name++; 486 } else { 487 shell_name = &buf[2];/* skipping "#!" */ 488 } 489 490 } 491 CloseHandle(exec_handle); 492 } 493 494 flags = 0; 495 496 if (file_not_found) 497 command_line = make_command_line( shell_name, exec_path, argv); 498 else 499 command_line = make_command_line( shell_name, file_info.szPathName, 500 argv); 501 502 if ( command_line == NULL ) { 503 pproc->last_err = 0; 504 pproc->lerrno = E_NO_MEM; 505 return(-1); 506 } 507 508 if (envp) { 509 if (arr2envblk(envp, &envblk) ==FALSE) { 510 pproc->last_err = 0; 511 pproc->lerrno = E_NO_MEM; 512 free( command_line ); 513 return(-1); 514 } 515 } 516 517 if ((shell_name) || (file_not_found)) { 518 exec_path = 0; /* Search for the program in %Path% */ 519 } else { 520 exec_path = file_info.szPathName; 521 } 522 523 /* 524 * Set up inherited stdin, stdout, stderr for child 525 */ 526 GetStartupInfo(&startInfo); 527 startInfo.dwFlags = STARTF_USESTDHANDLES; 528 startInfo.lpReserved = 0; 529 startInfo.cbReserved2 = 0; 530 startInfo.lpReserved2 = 0; 531 startInfo.lpTitle = shell_name ? shell_name : exec_path; 532 startInfo.hStdInput = (HANDLE)pproc->sv_stdin[1]; 533 startInfo.hStdOutput = (HANDLE)pproc->sv_stdout[1]; 534 startInfo.hStdError = (HANDLE)pproc->sv_stderr[1]; 535 536 if (as_user) { 537 if (envblk) free(envblk); 538 return -1; 539 } else { 540 DB (DB_JOBS, ("CreateProcess(%s,%s,...)\n", 541 exec_path ? exec_path : "NULL", 542 command_line ? command_line : "NULL")); 543 if (CreateProcess( 544 exec_path, 545 command_line, 546 NULL, 547 0, /* default security attributes for thread */ 548 TRUE, /* inherit handles (e.g. helper pipes, oserv socket) */ 549 flags, 550 envblk, 551 0, /* default starting directory */ 552 &startInfo, 553 &procInfo) == FALSE) { 554 555 pproc->last_err = GetLastError(); 556 pproc->lerrno = E_FORK; 557 fprintf(stderr, "process_begin: CreateProcess(%s, %s, ...) failed.\n", 558 exec_path ? exec_path : "NULL", command_line); 559 if (envblk) free(envblk); 560 free( command_line ); 561 return(-1); 562 } 563 } 564 565 pproc->pid = (intptr_t)procInfo.hProcess; 566 /* Close the thread handle -- we'll just watch the process */ 567 CloseHandle(procInfo.hThread); 568 569 /* Close the halves of the pipes we don't need */ 570 CloseHandle((HANDLE)pproc->sv_stdin[1]); 571 CloseHandle((HANDLE)pproc->sv_stdout[1]); 572 CloseHandle((HANDLE)pproc->sv_stderr[1]); 573 pproc->sv_stdin[1] = 0; 574 pproc->sv_stdout[1] = 0; 575 pproc->sv_stderr[1] = 0; 576 577 free( command_line ); 578 if (envblk) free(envblk); 579 pproc->lerrno=0; 580 return 0; 581 } 582 583 584 585 static DWORD 586 proc_stdin_thread(sub_process *pproc) 587 { 588 DWORD in_done; 589 for (;;) { 590 if (WriteFile( (HANDLE) pproc->sv_stdin[0], pproc->inp, pproc->incnt, 591 &in_done, NULL) == FALSE) 592 _endthreadex(0); 593 // This if should never be true for anonymous pipes, but gives 594 // us a chance to change I/O mechanisms later 595 if (in_done < pproc->incnt) { 596 pproc->incnt -= in_done; 597 pproc->inp += in_done; 598 } else { 599 _endthreadex(0); 600 } 601 } 602 return 0; // for compiler warnings only.. not reached 603 } 604 605 static DWORD 606 proc_stdout_thread(sub_process *pproc) 607 { 608 DWORD bufsize = 1024; 609 char c; 610 DWORD nread; 611 pproc->outp = malloc(bufsize); 612 if (pproc->outp == NULL) 613 _endthreadex(0); 614 pproc->outcnt = 0; 615 616 for (;;) { 617 if (ReadFile( (HANDLE)pproc->sv_stdout[0], &c, 1, &nread, NULL) 618 == FALSE) { 619 /* map_windows32_error_to_string(GetLastError());*/ 620 _endthreadex(0); 621 } 622 if (nread == 0) 623 _endthreadex(0); 624 if (pproc->outcnt + nread > bufsize) { 625 bufsize += nread + 512; 626 pproc->outp = realloc(pproc->outp, bufsize); 627 if (pproc->outp == NULL) { 628 pproc->outcnt = 0; 629 _endthreadex(0); 630 } 631 } 632 pproc->outp[pproc->outcnt++] = c; 633 } 634 return 0; 635 } 636 637 static DWORD 638 proc_stderr_thread(sub_process *pproc) 639 { 640 DWORD bufsize = 1024; 641 char c; 642 DWORD nread; 643 pproc->errp = malloc(bufsize); 644 if (pproc->errp == NULL) 645 _endthreadex(0); 646 pproc->errcnt = 0; 647 648 for (;;) { 649 if (ReadFile( (HANDLE)pproc->sv_stderr[0], &c, 1, &nread, NULL) == FALSE) { 650 map_windows32_error_to_string(GetLastError()); 651 _endthreadex(0); 652 } 653 if (nread == 0) 654 _endthreadex(0); 655 if (pproc->errcnt + nread > bufsize) { 656 bufsize += nread + 512; 657 pproc->errp = realloc(pproc->errp, bufsize); 658 if (pproc->errp == NULL) { 659 pproc->errcnt = 0; 660 _endthreadex(0); 661 } 662 } 663 pproc->errp[pproc->errcnt++] = c; 664 } 665 return 0; 666 } 667 668 669 /* 670 * Purpose: collects output from child process and returns results 671 * 672 * Description: 673 * 674 * Returns: 675 * 676 * Notes/Dependencies: 677 */ 678 long 679 process_pipe_io( 680 HANDLE proc, 681 char *stdin_data, 682 int stdin_data_len) 683 { 684 sub_process *pproc = (sub_process *)proc; 685 bool_t stdin_eof = FALSE, stdout_eof = FALSE, stderr_eof = FALSE; 686 HANDLE childhand = (HANDLE) pproc->pid; 687 HANDLE tStdin = NULL, tStdout = NULL, tStderr = NULL; 688 unsigned int dwStdin, dwStdout, dwStderr; 689 HANDLE wait_list[4]; 690 DWORD wait_count; 691 DWORD wait_return; 692 HANDLE ready_hand; 693 bool_t child_dead = FALSE; 694 BOOL GetExitCodeResult; 695 696 /* 697 * Create stdin thread, if needed 698 */ 699 pproc->inp = stdin_data; 700 pproc->incnt = stdin_data_len; 701 if (!pproc->inp) { 702 stdin_eof = TRUE; 703 CloseHandle((HANDLE)pproc->sv_stdin[0]); 704 pproc->sv_stdin[0] = 0; 705 } else { 706 tStdin = (HANDLE) _beginthreadex( 0, 1024, 707 (unsigned (__stdcall *) (void *))proc_stdin_thread, 708 pproc, 0, &dwStdin); 709 if (tStdin == 0) { 710 pproc->last_err = GetLastError(); 711 pproc->lerrno = E_SCALL; 712 goto done; 713 } 714 } 715 716 /* 717 * Assume child will produce stdout and stderr 718 */ 719 tStdout = (HANDLE) _beginthreadex( 0, 1024, 720 (unsigned (__stdcall *) (void *))proc_stdout_thread, pproc, 0, 721 &dwStdout); 722 tStderr = (HANDLE) _beginthreadex( 0, 1024, 723 (unsigned (__stdcall *) (void *))proc_stderr_thread, pproc, 0, 724 &dwStderr); 725 726 if (tStdout == 0 || tStderr == 0) { 727 728 pproc->last_err = GetLastError(); 729 pproc->lerrno = E_SCALL; 730 goto done; 731 } 732 733 734 /* 735 * Wait for all I/O to finish and for the child process to exit 736 */ 737 738 while (!stdin_eof || !stdout_eof || !stderr_eof || !child_dead) { 739 wait_count = 0; 740 if (!stdin_eof) { 741 wait_list[wait_count++] = tStdin; 742 } 743 if (!stdout_eof) { 744 wait_list[wait_count++] = tStdout; 745 } 746 if (!stderr_eof) { 747 wait_list[wait_count++] = tStderr; 748 } 749 if (!child_dead) { 750 wait_list[wait_count++] = childhand; 751 } 752 753 wait_return = WaitForMultipleObjects(wait_count, wait_list, 754 FALSE, /* don't wait for all: one ready will do */ 755 child_dead? 1000 :INFINITE); /* after the child dies, subthreads have 756 one second to collect all remaining output */ 757 758 if (wait_return == WAIT_FAILED) { 759 /* map_windows32_error_to_string(GetLastError());*/ 760 pproc->last_err = GetLastError(); 761 pproc->lerrno = E_SCALL; 762 goto done; 763 } 764 765 ready_hand = wait_list[wait_return - WAIT_OBJECT_0]; 766 767 if (ready_hand == tStdin) { 768 CloseHandle((HANDLE)pproc->sv_stdin[0]); 769 pproc->sv_stdin[0] = 0; 770 CloseHandle(tStdin); 771 tStdin = 0; 772 stdin_eof = TRUE; 773 774 } else if (ready_hand == tStdout) { 775 776 CloseHandle((HANDLE)pproc->sv_stdout[0]); 777 pproc->sv_stdout[0] = 0; 778 CloseHandle(tStdout); 779 tStdout = 0; 780 stdout_eof = TRUE; 781 782 } else if (ready_hand == tStderr) { 783 784 CloseHandle((HANDLE)pproc->sv_stderr[0]); 785 pproc->sv_stderr[0] = 0; 786 CloseHandle(tStderr); 787 tStderr = 0; 788 stderr_eof = TRUE; 789 790 } else if (ready_hand == childhand) { 791 792 DWORD ierr; 793 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); 794 if (ierr == CONTROL_C_EXIT) { 795 pproc->signal = SIGINT; 796 } else { 797 pproc->exit_code = ierr; 798 } 799 if (GetExitCodeResult == FALSE) { 800 pproc->last_err = GetLastError(); 801 pproc->lerrno = E_SCALL; 802 goto done; 803 } 804 child_dead = TRUE; 805 806 } else { 807 808 /* ?? Got back a handle we didn't query ?? */ 809 pproc->last_err = 0; 810 pproc->lerrno = E_FAIL; 811 goto done; 812 } 813 } 814 815 done: 816 if (tStdin != 0) 817 CloseHandle(tStdin); 818 if (tStdout != 0) 819 CloseHandle(tStdout); 820 if (tStderr != 0) 821 CloseHandle(tStderr); 822 823 if (pproc->lerrno) 824 return(-1); 825 else 826 return(0); 827 828 } 829 830 /* 831 * Purpose: collects output from child process and returns results 832 * 833 * Description: 834 * 835 * Returns: 836 * 837 * Notes/Dependencies: 838 */ 839 long 840 process_file_io( 841 HANDLE proc) 842 { 843 sub_process *pproc; 844 HANDLE childhand; 845 DWORD wait_return; 846 BOOL GetExitCodeResult; 847 DWORD ierr; 848 849 if (proc == NULL) 850 pproc = process_wait_for_any_private(); 851 else 852 pproc = (sub_process *)proc; 853 854 /* some sort of internal error */ 855 if (!pproc) 856 return -1; 857 858 childhand = (HANDLE) pproc->pid; 859 860 /* 861 * This function is poorly named, and could also be used just to wait 862 * for child death if you're doing your own pipe I/O. If that is 863 * the case, close the pipe handles here. 864 */ 865 if (pproc->sv_stdin[0]) { 866 CloseHandle((HANDLE)pproc->sv_stdin[0]); 867 pproc->sv_stdin[0] = 0; 868 } 869 if (pproc->sv_stdout[0]) { 870 CloseHandle((HANDLE)pproc->sv_stdout[0]); 871 pproc->sv_stdout[0] = 0; 872 } 873 if (pproc->sv_stderr[0]) { 874 CloseHandle((HANDLE)pproc->sv_stderr[0]); 875 pproc->sv_stderr[0] = 0; 876 } 877 878 /* 879 * Wait for the child process to exit 880 */ 881 882 wait_return = WaitForSingleObject(childhand, INFINITE); 883 884 if (wait_return != WAIT_OBJECT_0) { 885 /* map_windows32_error_to_string(GetLastError());*/ 886 pproc->last_err = GetLastError(); 887 pproc->lerrno = E_SCALL; 888 goto done2; 889 } 890 891 GetExitCodeResult = GetExitCodeProcess(childhand, &ierr); 892 if (ierr == CONTROL_C_EXIT) { 893 pproc->signal = SIGINT; 894 } else { 895 pproc->exit_code = ierr; 896 } 897 if (GetExitCodeResult == FALSE) { 898 pproc->last_err = GetLastError(); 899 pproc->lerrno = E_SCALL; 900 } 901 902 done2: 903 if (pproc->lerrno) 904 return(-1); 905 else 906 return(0); 907 908 } 909 910 /* 911 * Description: Clean up any leftover handles, etc. It is up to the 912 * caller to manage and free the input, ouput, and stderr buffers. 913 */ 914 void 915 process_cleanup( 916 HANDLE proc) 917 { 918 sub_process *pproc = (sub_process *)proc; 919 int i; 920 921 if (pproc->using_pipes) { 922 for (i= 0; i <= 1; i++) { 923 if ((HANDLE)pproc->sv_stdin[i]) 924 CloseHandle((HANDLE)pproc->sv_stdin[i]); 925 if ((HANDLE)pproc->sv_stdout[i]) 926 CloseHandle((HANDLE)pproc->sv_stdout[i]); 927 if ((HANDLE)pproc->sv_stderr[i]) 928 CloseHandle((HANDLE)pproc->sv_stderr[i]); 929 } 930 } 931 if ((HANDLE)pproc->pid) 932 CloseHandle((HANDLE)pproc->pid); 933 934 free(pproc); 935 } 936 937 938 /* 939 * Description: 940 * Create a command line buffer to pass to CreateProcess 941 * 942 * Returns: the buffer or NULL for failure 943 * Shell case: sh_name a:/full/path/to/script argv[1] argv[2] ... 944 * Otherwise: argv[0] argv[1] argv[2] ... 945 * 946 * Notes/Dependencies: 947 * CreateProcess does not take an argv, so this command creates a 948 * command line for the executable. 949 */ 950 951 static char * 952 make_command_line( char *shell_name, char *full_exec_path, char **argv) 953 { 954 int argc = 0; 955 char** argvi; 956 int* enclose_in_quotes = NULL; 957 int* enclose_in_quotes_i; 958 unsigned int bytes_required = 0; 959 char* command_line; 960 char* command_line_i; 961 int cygwin_mode = 0; /* HAVE_CYGWIN_SHELL */ 962 int have_sh = 0; /* HAVE_CYGWIN_SHELL */ 963 964 #ifdef HAVE_CYGWIN_SHELL 965 have_sh = (shell_name != NULL || strstr(full_exec_path, "sh.exe")); 966 cygwin_mode = 1; 967 #endif 968 969 if (shell_name && full_exec_path) { 970 bytes_required 971 = strlen(shell_name) + 1 + strlen(full_exec_path); 972 /* 973 * Skip argv[0] if any, when shell_name is given. 974 */ 975 if (*argv) argv++; 976 /* 977 * Add one for the intervening space. 978 */ 979 if (*argv) bytes_required++; 980 } 981 982 argvi = argv; 983 while (*(argvi++)) argc++; 984 985 if (argc) { 986 enclose_in_quotes = (int*) calloc(1, argc * sizeof(int)); 987 988 if (!enclose_in_quotes) { 989 return NULL; 990 } 991 } 992 993 /* We have to make one pass through each argv[i] to see if we need 994 * to enclose it in ", so we might as well figure out how much 995 * memory we'll need on the same pass. 996 */ 997 998 argvi = argv; 999 enclose_in_quotes_i = enclose_in_quotes; 1000 while(*argvi) { 1001 char* p = *argvi; 1002 unsigned int backslash_count = 0; 1003 1004 /* 1005 * We have to enclose empty arguments in ". 1006 */ 1007 if (!(*p)) *enclose_in_quotes_i = 1; 1008 1009 while(*p) { 1010 switch (*p) { 1011 case '\"': 1012 /* 1013 * We have to insert a backslash for each " 1014 * and each \ that precedes the ". 1015 */ 1016 bytes_required += (backslash_count + 1); 1017 backslash_count = 0; 1018 break; 1019 1020 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1021 case '\\': 1022 backslash_count++; 1023 break; 1024 #endif 1025 /* 1026 * At one time we set *enclose_in_quotes_i for '*' or '?' to suppress 1027 * wildcard expansion in programs linked with MSVC's SETARGV.OBJ so 1028 * that argv in always equals argv out. This was removed. Say you have 1029 * such a program named glob.exe. You enter 1030 * glob '*' 1031 * at the sh command prompt. Obviously the intent is to make glob do the 1032 * wildcarding instead of sh. If we set *enclose_in_quotes_i for '*' or '?', 1033 * then the command line that glob would see would be 1034 * glob "*" 1035 * and the _setargv in SETARGV.OBJ would _not_ expand the *. 1036 */ 1037 case ' ': 1038 case '\t': 1039 *enclose_in_quotes_i = 1; 1040 /* fall through */ 1041 1042 default: 1043 backslash_count = 0; 1044 break; 1045 } 1046 1047 /* 1048 * Add one for each character in argv[i]. 1049 */ 1050 bytes_required++; 1051 1052 p++; 1053 } 1054 1055 if (*enclose_in_quotes_i) { 1056 /* 1057 * Add one for each enclosing ", 1058 * and one for each \ that precedes the 1059 * closing ". 1060 */ 1061 bytes_required += (backslash_count + 2); 1062 } 1063 1064 /* 1065 * Add one for the intervening space. 1066 */ 1067 if (*(++argvi)) bytes_required++; 1068 enclose_in_quotes_i++; 1069 } 1070 1071 /* 1072 * Add one for the terminating NULL. 1073 */ 1074 bytes_required++; 1075 1076 command_line = (char*) malloc(bytes_required); 1077 1078 if (!command_line) { 1079 if (enclose_in_quotes) free(enclose_in_quotes); 1080 return NULL; 1081 } 1082 1083 command_line_i = command_line; 1084 1085 if (shell_name && full_exec_path) { 1086 while(*shell_name) { 1087 *(command_line_i++) = *(shell_name++); 1088 } 1089 1090 *(command_line_i++) = ' '; 1091 1092 while(*full_exec_path) { 1093 *(command_line_i++) = *(full_exec_path++); 1094 } 1095 1096 if (*argv) { 1097 *(command_line_i++) = ' '; 1098 } 1099 } 1100 1101 argvi = argv; 1102 enclose_in_quotes_i = enclose_in_quotes; 1103 1104 while(*argvi) { 1105 char* p = *argvi; 1106 unsigned int backslash_count = 0; 1107 1108 if (*enclose_in_quotes_i) { 1109 *(command_line_i++) = '\"'; 1110 } 1111 1112 while(*p) { 1113 if (*p == '\"') { 1114 if (cygwin_mode && have_sh) { /* HAVE_CYGWIN_SHELL */ 1115 /* instead of a \", cygwin likes "" */ 1116 *(command_line_i++) = '\"'; 1117 } else { 1118 1119 /* 1120 * We have to insert a backslash for the " 1121 * and each \ that precedes the ". 1122 */ 1123 backslash_count++; 1124 1125 while(backslash_count) { 1126 *(command_line_i++) = '\\'; 1127 backslash_count--; 1128 }; 1129 } 1130 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1131 } else if (*p == '\\') { 1132 backslash_count++; 1133 } else { 1134 backslash_count = 0; 1135 #endif 1136 } 1137 1138 /* 1139 * Copy the character. 1140 */ 1141 *(command_line_i++) = *(p++); 1142 } 1143 1144 if (*enclose_in_quotes_i) { 1145 #if !defined(HAVE_MKS_SHELL) && !defined(HAVE_CYGWIN_SHELL) 1146 /* 1147 * Add one \ for each \ that precedes the 1148 * closing ". 1149 */ 1150 while(backslash_count--) { 1151 *(command_line_i++) = '\\'; 1152 }; 1153 #endif 1154 *(command_line_i++) = '\"'; 1155 } 1156 1157 /* 1158 * Append an intervening space. 1159 */ 1160 if (*(++argvi)) { 1161 *(command_line_i++) = ' '; 1162 } 1163 1164 enclose_in_quotes_i++; 1165 } 1166 1167 /* 1168 * Append the terminating NULL. 1169 */ 1170 *command_line_i = '\0'; 1171 1172 if (enclose_in_quotes) free(enclose_in_quotes); 1173 return command_line; 1174 } 1175 1176 /* 1177 * Description: Given an argv and optional envp, launch the process 1178 * using the default stdin, stdout, and stderr handles. 1179 * Also, register process so that process_wait_for_any_private() 1180 * can be used via process_file_io(NULL) or 1181 * process_wait_for_any(). 1182 * 1183 * Returns: 1184 * 1185 * Notes/Dependencies: 1186 */ 1187 HANDLE 1188 process_easy( 1189 char **argv, 1190 char **envp) 1191 { 1192 HANDLE hIn; 1193 HANDLE hOut; 1194 HANDLE hErr; 1195 HANDLE hProcess; 1196 1197 if (proc_index >= MAXIMUM_WAIT_OBJECTS) { 1198 DB (DB_JOBS, ("process_easy: All process slots used up\n")); 1199 return INVALID_HANDLE_VALUE; 1200 } 1201 if (DuplicateHandle(GetCurrentProcess(), 1202 GetStdHandle(STD_INPUT_HANDLE), 1203 GetCurrentProcess(), 1204 &hIn, 1205 0, 1206 TRUE, 1207 DUPLICATE_SAME_ACCESS) == FALSE) { 1208 fprintf(stderr, 1209 "process_easy: DuplicateHandle(In) failed (e=%ld)\n", 1210 GetLastError()); 1211 return INVALID_HANDLE_VALUE; 1212 } 1213 if (DuplicateHandle(GetCurrentProcess(), 1214 GetStdHandle(STD_OUTPUT_HANDLE), 1215 GetCurrentProcess(), 1216 &hOut, 1217 0, 1218 TRUE, 1219 DUPLICATE_SAME_ACCESS) == FALSE) { 1220 fprintf(stderr, 1221 "process_easy: DuplicateHandle(Out) failed (e=%ld)\n", 1222 GetLastError()); 1223 return INVALID_HANDLE_VALUE; 1224 } 1225 if (DuplicateHandle(GetCurrentProcess(), 1226 GetStdHandle(STD_ERROR_HANDLE), 1227 GetCurrentProcess(), 1228 &hErr, 1229 0, 1230 TRUE, 1231 DUPLICATE_SAME_ACCESS) == FALSE) { 1232 fprintf(stderr, 1233 "process_easy: DuplicateHandle(Err) failed (e=%ld)\n", 1234 GetLastError()); 1235 return INVALID_HANDLE_VALUE; 1236 } 1237 1238 hProcess = process_init_fd(hIn, hOut, hErr); 1239 1240 if (process_begin(hProcess, argv, envp, argv[0], NULL)) { 1241 fake_exits_pending++; 1242 /* process_begin() failed: make a note of that. */ 1243 if (!((sub_process*) hProcess)->last_err) 1244 ((sub_process*) hProcess)->last_err = -1; 1245 ((sub_process*) hProcess)->exit_code = process_last_err(hProcess); 1246 1247 /* close up unused handles */ 1248 CloseHandle(hIn); 1249 CloseHandle(hOut); 1250 CloseHandle(hErr); 1251 } 1252 1253 process_register(hProcess); 1254 1255 return hProcess; 1256 } 1257