mirror of
https://github.com/mirror/make.git
synced 2025-02-04 16:51:12 +08:00
Fix invocation of Windows batch files with whitespace in their names.
w32/subproc/sub_proc.c: Include makeint.h. Remove a private incompatible prototype of xmalloc. (batch_file_with_spaces): New function, detects Windows batch files whose names include whitespace characters. (process_begin): If exec_name is a batch file with whitespace characters in its name, pass NULL as the first argument to CreateProcess. This avoids weird failures due to buggy quoting by CreateProcess. For the details, see the discussion starting at http://lists.gnu.org/archive/html/make-w32/2013-04/msg00008.html.
This commit is contained in:
parent
a66469e003
commit
82793f85f5
10
ChangeLog
10
ChangeLog
@ -1,5 +1,15 @@
|
|||||||
2013-05-03 Eli Zaretskii <eliz@gnu.org>
|
2013-05-03 Eli Zaretskii <eliz@gnu.org>
|
||||||
|
|
||||||
|
* w32/subproc/sub_proc.c: Include makeint.h. Remove a private
|
||||||
|
incompatible prototype of xmalloc.
|
||||||
|
(batch_file_with_spaces): New function, detects Windows batch
|
||||||
|
files whose names include whitespace characters.
|
||||||
|
(process_begin): If exec_name is a batch file with whitespace
|
||||||
|
characters in its name, pass NULL as the first argument to
|
||||||
|
CreateProcess. This avoids weird failures due to buggy quoting by
|
||||||
|
CreateProcess. For the details, see the discussion starting at
|
||||||
|
http://lists.gnu.org/archive/html/make-w32/2013-04/msg00008.html.
|
||||||
|
|
||||||
* load.c (load_object, load_file): Accept an additional argument
|
* load.c (load_object, load_file): Accept an additional argument
|
||||||
DLP and return in it a pointer that can be used to unload the
|
DLP and return in it a pointer that can be used to unload the
|
||||||
dynamic object.
|
dynamic object.
|
||||||
|
@ -23,17 +23,18 @@ this program. If not, see <http://www.gnu.org/licenses/>. */
|
|||||||
#else
|
#else
|
||||||
# include <stdint.h>
|
# include <stdint.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <string.h>
|
||||||
#include <process.h> /* for msvc _beginthreadex, _endthreadex */
|
#include <process.h> /* for msvc _beginthreadex, _endthreadex */
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
|
#include "makeint.h"
|
||||||
#include "sub_proc.h"
|
#include "sub_proc.h"
|
||||||
#include "proc.h"
|
#include "proc.h"
|
||||||
#include "w32err.h"
|
#include "w32err.h"
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
|
|
||||||
static char *make_command_line(char *shell_name, char *exec_path, char **argv);
|
static char *make_command_line(char *shell_name, char *exec_path, char **argv);
|
||||||
extern char *xmalloc (unsigned int);
|
|
||||||
|
|
||||||
typedef struct sub_process_t {
|
typedef struct sub_process_t {
|
||||||
intptr_t sv_stdin[2];
|
intptr_t sv_stdin[2];
|
||||||
@ -540,6 +541,26 @@ find_file(const char *exec_path, const char *path_var,
|
|||||||
return INVALID_HANDLE_VALUE;
|
return INVALID_HANDLE_VALUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return non-zero of FNAME specifies a batch file and its name
|
||||||
|
* includes embedded whitespace.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
batch_file_with_spaces(const char *fname)
|
||||||
|
{
|
||||||
|
size_t fnlen = strlen(fname);
|
||||||
|
|
||||||
|
return (fnlen > 4
|
||||||
|
&& (_strnicmp(fname + fnlen - 4, ".bat", 4) == 0
|
||||||
|
|| _strnicmp(fname + fnlen - 4, ".cmd", 4) == 0)
|
||||||
|
/* The set of characters in the 2nd arg to strpbrk
|
||||||
|
should be the same one used by make_command_line
|
||||||
|
below to decide whether an argv[] element needs
|
||||||
|
quoting. */
|
||||||
|
&& strpbrk(fname, " \t") != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Description: Create the child process to be helped
|
* Description: Create the child process to be helped
|
||||||
@ -570,6 +591,7 @@ process_begin(
|
|||||||
STARTUPINFO startInfo;
|
STARTUPINFO startInfo;
|
||||||
PROCESS_INFORMATION procInfo;
|
PROCESS_INFORMATION procInfo;
|
||||||
char *envblk=NULL;
|
char *envblk=NULL;
|
||||||
|
int pass_null_exec_path = 0;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Shell script detection... if the exec_path starts with #! then
|
* Shell script detection... if the exec_path starts with #! then
|
||||||
@ -651,8 +673,28 @@ process_begin(
|
|||||||
|
|
||||||
if (file_not_found)
|
if (file_not_found)
|
||||||
command_line = make_command_line( shell_name, exec_path, argv);
|
command_line = make_command_line( shell_name, exec_path, argv);
|
||||||
else
|
else {
|
||||||
|
/* If exec_fname includes whitespace, CreateProcess
|
||||||
|
behaves erratically and unreliably, and often fails
|
||||||
|
if argv[0] also includes whitespace (and thus will
|
||||||
|
be quoted by make_command_line below). So in that
|
||||||
|
case, we don't pass exec_fname as the 1st arg to
|
||||||
|
CreateProcess, but instead replace argv[0] with
|
||||||
|
exec_fname (to keep its leading directories and
|
||||||
|
extension as found by find_file), and pass NULL to
|
||||||
|
CreateProcess as its 1st arg. This works around
|
||||||
|
the bugs in CreateProcess, which are probably
|
||||||
|
caused by its passing the command to cmd.exe with
|
||||||
|
some incorrect quoting. */
|
||||||
|
if (!shell_name
|
||||||
|
&& batch_file_with_spaces(exec_fname)
|
||||||
|
&& _stricmp(exec_path, argv[0]) == 0) {
|
||||||
|
pass_null_exec_path = 1;
|
||||||
|
free (argv[0]);
|
||||||
|
argv[0] = xstrdup(exec_fname);
|
||||||
|
}
|
||||||
command_line = make_command_line( shell_name, exec_fname, argv);
|
command_line = make_command_line( shell_name, exec_fname, argv);
|
||||||
|
}
|
||||||
|
|
||||||
if ( command_line == NULL ) {
|
if ( command_line == NULL ) {
|
||||||
pproc->last_err = 0;
|
pproc->last_err = 0;
|
||||||
@ -669,7 +711,7 @@ process_begin(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((shell_name) || (file_not_found)) {
|
if (shell_name || file_not_found || pass_null_exec_path) {
|
||||||
exec_path = 0; /* Search for the program in %Path% */
|
exec_path = 0; /* Search for the program in %Path% */
|
||||||
} else {
|
} else {
|
||||||
exec_path = exec_fname;
|
exec_path = exec_fname;
|
||||||
|
Loading…
Reference in New Issue
Block a user