Mercurial > hg > CbC > CbC_gcc
comparison libiberty/pex-win32.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | 77e2b8dfacca |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
68:561a7518be6b | 111:04ced10e8804 |
---|---|
1 /* Utilities to execute a program in a subprocess (possibly linked by pipes | 1 /* Utilities to execute a program in a subprocess (possibly linked by pipes |
2 with other subprocesses), and wait for it. Generic Win32 specialization. | 2 with other subprocesses), and wait for it. Generic Win32 specialization. |
3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006 | 3 Copyright (C) 1996-2017 Free Software Foundation, Inc. |
4 Free Software Foundation, Inc. | |
5 | 4 |
6 This file is part of the libiberty library. | 5 This file is part of the libiberty library. |
7 Libiberty is free software; you can redistribute it and/or | 6 Libiberty is free software; you can redistribute it and/or |
8 modify it under the terms of the GNU Library General Public | 7 modify it under the terms of the GNU Library General Public |
9 License as published by the Free Software Foundation; either | 8 License as published by the Free Software Foundation; either |
76 *s = '\\'; | 75 *s = '\\'; |
77 return; | 76 return; |
78 } | 77 } |
79 | 78 |
80 static int pex_win32_open_read (struct pex_obj *, const char *, int); | 79 static int pex_win32_open_read (struct pex_obj *, const char *, int); |
81 static int pex_win32_open_write (struct pex_obj *, const char *, int); | 80 static int pex_win32_open_write (struct pex_obj *, const char *, int, int); |
82 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, | 81 static pid_t pex_win32_exec_child (struct pex_obj *, int, const char *, |
83 char * const *, char * const *, | 82 char * const *, char * const *, |
84 int, int, int, int, | 83 int, int, int, int, |
85 const char **, int *); | 84 const char **, int *); |
86 static int pex_win32_close (struct pex_obj *, int); | 85 static int pex_win32_close (struct pex_obj *, int); |
124 | 123 |
125 /* Open a file for writing. */ | 124 /* Open a file for writing. */ |
126 | 125 |
127 static int | 126 static int |
128 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, | 127 pex_win32_open_write (struct pex_obj *obj ATTRIBUTE_UNUSED, const char *name, |
129 int binary) | 128 int binary, int append) |
130 { | 129 { |
131 /* Note that we can't use O_EXCL here because gcc may have already | 130 /* Note that we can't use O_EXCL here because gcc may have already |
132 created the temporary file via make_temp_file. */ | 131 created the temporary file via make_temp_file. */ |
132 if (append) | |
133 return -1; | |
133 return _open (name, | 134 return _open (name, |
134 (_O_WRONLY | _O_CREAT | _O_TRUNC | 135 (_O_WRONLY | _O_CREAT | _O_TRUNC |
135 | (binary ? _O_BINARY : _O_TEXT)), | 136 | (binary ? _O_BINARY : _O_TEXT)), |
136 _S_IREAD | _S_IWRITE); | 137 _S_IREAD | _S_IWRITE); |
137 } | 138 } |
208 foundbuf = XNEWVEC (char, maxlen); | 209 foundbuf = XNEWVEC (char, maxlen); |
209 foundbuf[0] = '\0'; | 210 foundbuf[0] = '\0'; |
210 if (!namebuf || !foundbuf) | 211 if (!namebuf || !foundbuf) |
211 { | 212 { |
212 RegCloseKey (hKey); | 213 RegCloseKey (hKey); |
213 if (namebuf) | 214 free (namebuf); |
214 free (namebuf); | 215 free (foundbuf); |
215 if (foundbuf) | |
216 free (foundbuf); | |
217 return executable; | 216 return executable; |
218 } | 217 } |
219 | 218 |
220 /* Look through all of the keys for one that begins with Minimal GNU... | 219 /* Look through all of the keys for one that begins with Minimal GNU... |
221 Try to get the latest version by doing a string compare although that | 220 Try to get the latest version by doing a string compare although that |
313 | 312 |
314 if (res) | 313 if (res) |
315 return tack_on_executable (buf, executable); | 314 return tack_on_executable (buf, executable); |
316 | 315 |
317 /* failed */ | 316 /* failed */ |
318 if (buf) | 317 free (buf); |
319 free (buf); | |
320 return executable; | 318 return executable; |
321 } | 319 } |
322 #endif | 320 #endif |
323 | 321 |
324 /* Return the number of arguments in an argv array, not including the null | 322 /* Return the number of arguments in an argv array, not including the null |
341 { | 339 { |
342 char *cmdline; | 340 char *cmdline; |
343 char *p; | 341 char *p; |
344 size_t cmdline_len; | 342 size_t cmdline_len; |
345 int i, j, k; | 343 int i, j, k; |
344 int needs_quotes; | |
346 | 345 |
347 cmdline_len = 0; | 346 cmdline_len = 0; |
348 for (i = 0; argv[i]; i++) | 347 for (i = 0; argv[i]; i++) |
349 { | 348 { |
350 /* We quote every last argument. This simplifies the problem; | 349 /* We only quote arguments that contain spaces, \t or " characters to |
351 we need only escape embedded double-quotes and immediately | 350 prevent wasting 2 chars per argument of the CreateProcess 32k char |
351 limit. We need only escape embedded double-quotes and immediately | |
352 preceeding backslash characters. A sequence of backslach characters | 352 preceeding backslash characters. A sequence of backslach characters |
353 that is not follwed by a double quote character will not be | 353 that is not follwed by a double quote character will not be |
354 escaped. */ | 354 escaped. */ |
355 needs_quotes = 0; | |
355 for (j = 0; argv[i][j]; j++) | 356 for (j = 0; argv[i][j]; j++) |
356 { | 357 { |
358 if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"') | |
359 { | |
360 needs_quotes = 1; | |
361 } | |
362 | |
357 if (argv[i][j] == '"') | 363 if (argv[i][j] == '"') |
358 { | 364 { |
359 /* Escape preceeding backslashes. */ | 365 /* Escape preceeding backslashes. */ |
360 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) | 366 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) |
361 cmdline_len++; | 367 cmdline_len++; |
362 /* Escape the qote character. */ | 368 /* Escape the qote character. */ |
363 cmdline_len++; | 369 cmdline_len++; |
364 } | 370 } |
365 } | 371 } |
372 if (j == 0) | |
373 needs_quotes = 1; | |
366 /* Trailing backslashes also need to be escaped because they will be | 374 /* Trailing backslashes also need to be escaped because they will be |
367 followed by the terminating quote. */ | 375 followed by the terminating quote. */ |
368 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) | 376 if (needs_quotes) |
369 cmdline_len++; | 377 { |
378 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) | |
379 cmdline_len++; | |
380 } | |
370 cmdline_len += j; | 381 cmdline_len += j; |
371 cmdline_len += 3; /* for leading and trailing quotes and space */ | 382 /* for leading and trailing quotes and space */ |
383 cmdline_len += needs_quotes * 2 + 1; | |
372 } | 384 } |
373 cmdline = XNEWVEC (char, cmdline_len); | 385 cmdline = XNEWVEC (char, cmdline_len); |
374 p = cmdline; | 386 p = cmdline; |
375 for (i = 0; argv[i]; i++) | 387 for (i = 0; argv[i]; i++) |
376 { | 388 { |
377 *p++ = '"'; | 389 needs_quotes = 0; |
390 for (j = 0; argv[i][j]; j++) | |
391 { | |
392 if (argv[i][j] == ' ' || argv[i][j] == '\t' || argv[i][j] == '"') | |
393 { | |
394 needs_quotes = 1; | |
395 break; | |
396 } | |
397 } | |
398 if (j == 0) | |
399 needs_quotes = 1; | |
400 | |
401 if (needs_quotes) | |
402 { | |
403 *p++ = '"'; | |
404 } | |
378 for (j = 0; argv[i][j]; j++) | 405 for (j = 0; argv[i][j]; j++) |
379 { | 406 { |
380 if (argv[i][j] == '"') | 407 if (argv[i][j] == '"') |
381 { | 408 { |
382 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) | 409 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) |
383 *p++ = '\\'; | 410 *p++ = '\\'; |
384 *p++ = '\\'; | 411 *p++ = '\\'; |
385 } | 412 } |
386 *p++ = argv[i][j]; | 413 *p++ = argv[i][j]; |
387 } | 414 } |
388 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) | 415 if (needs_quotes) |
389 *p++ = '\\'; | 416 { |
390 *p++ = '"'; | 417 for (k = j - 1; k >= 0 && argv[i][k] == '\\'; k--) |
418 *p++ = '\\'; | |
419 *p++ = '"'; | |
420 } | |
391 *p++ = ' '; | 421 *p++ = ' '; |
392 } | 422 } |
393 p[-1] = '\0'; | 423 p[-1] = '\0'; |
394 return cmdline; | 424 return cmdline; |
395 } | 425 } |
605 (LPVOID) env_block, | 635 (LPVOID) env_block, |
606 /*lpCurrentDirectory=*/NULL, | 636 /*lpCurrentDirectory=*/NULL, |
607 si, | 637 si, |
608 pi)) | 638 pi)) |
609 { | 639 { |
610 if (env_block) | 640 free (env_block); |
611 free (env_block); | |
612 | 641 |
613 free (full_executable); | 642 free (full_executable); |
614 | 643 |
615 return (pid_t) -1; | 644 return (pid_t) -1; |
616 } | 645 } |
617 | 646 |
618 /* Clean up. */ | 647 /* Clean up. */ |
619 CloseHandle (pi->hThread); | 648 CloseHandle (pi->hThread); |
620 free (full_executable); | 649 free (full_executable); |
621 if (env_block) | 650 free (env_block); |
622 free (env_block); | |
623 | 651 |
624 return (pid_t) pi->hProcess; | 652 return (pid_t) pi->hProcess; |
625 | 653 |
626 error: | 654 error: |
627 if (env_block) | 655 free (env_block); |
628 free (env_block); | 656 free (cmdline); |
629 if (cmdline) | 657 free (full_executable); |
630 free (cmdline); | |
631 if (full_executable) | |
632 free (full_executable); | |
633 | 658 |
634 return (pid_t) -1; | 659 return (pid_t) -1; |
635 } | 660 } |
636 | 661 |
637 /* Spawn a script. This simulates the Unix script execution mechanism. | 662 /* Spawn a script. This simulates the Unix script execution mechanism. |
747 STARTUPINFO si; | 772 STARTUPINFO si; |
748 PROCESS_INFORMATION pi; | 773 PROCESS_INFORMATION pi; |
749 int orig_out, orig_in, orig_err; | 774 int orig_out, orig_in, orig_err; |
750 BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT); | 775 BOOL separate_stderr = !(flags & PEX_STDERR_TO_STDOUT); |
751 | 776 |
752 /* Ensure we have inheritable descriptors to pass to the child, and close the | 777 /* Ensure we have inheritable descriptors to pass to the child. */ |
753 original descriptors. */ | |
754 orig_in = in; | 778 orig_in = in; |
755 in = _dup (orig_in); | 779 in = _dup (orig_in); |
756 if (orig_in != STDIN_FILENO) | |
757 _close (orig_in); | |
758 | 780 |
759 orig_out = out; | 781 orig_out = out; |
760 out = _dup (orig_out); | 782 out = _dup (orig_out); |
761 if (orig_out != STDOUT_FILENO) | |
762 _close (orig_out); | |
763 | 783 |
764 if (separate_stderr) | 784 if (separate_stderr) |
765 { | 785 { |
766 orig_err = errdes; | 786 orig_err = errdes; |
767 errdes = _dup (orig_err); | 787 errdes = _dup (orig_err); |
768 if (orig_err != STDERR_FILENO) | |
769 _close (orig_err); | |
770 } | 788 } |
771 | 789 |
772 stdin_handle = INVALID_HANDLE_VALUE; | 790 stdin_handle = INVALID_HANDLE_VALUE; |
773 stdout_handle = INVALID_HANDLE_VALUE; | 791 stdout_handle = INVALID_HANDLE_VALUE; |
774 stderr_handle = INVALID_HANDLE_VALUE; | 792 stderr_handle = INVALID_HANDLE_VALUE; |
842 { | 860 { |
843 *err = ENOENT; | 861 *err = ENOENT; |
844 *errmsg = "CreateProcess"; | 862 *errmsg = "CreateProcess"; |
845 } | 863 } |
846 | 864 |
865 /* If the child was created successfully, close the original file | |
866 descriptors. If the process creation fails, these are closed by | |
867 pex_run_in_environment instead. We must not close them twice as | |
868 that seems to cause a Windows exception. */ | |
869 | |
870 if (pid != (pid_t) -1) | |
871 { | |
872 if (orig_in != STDIN_FILENO) | |
873 _close (orig_in); | |
874 if (orig_out != STDOUT_FILENO) | |
875 _close (orig_out); | |
876 if (separate_stderr | |
877 && orig_err != STDERR_FILENO) | |
878 _close (orig_err); | |
879 } | |
880 | |
847 /* Close the standard input, standard output and standard error handles | 881 /* Close the standard input, standard output and standard error handles |
848 in the parent. */ | 882 in the parent. */ |
849 | 883 |
850 _close (in); | 884 _close (in); |
851 _close (out); | 885 _close (out); |