BUG: Fix SharedForward with spaces on windows
The windows execvp function does not re-escape arguments correctly. Instead we generate the escape sequences before calling it.
This commit is contained in:
parent
014f684317
commit
d6643ebba4
@ -157,6 +157,7 @@
|
|||||||
# include <io.h>
|
# include <io.h>
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
# include <process.h>
|
# include <process.h>
|
||||||
|
# define KWSYS_SHARED_FORWARD_ESCAPE_ARGV /* re-escape argv for execvp */
|
||||||
#else
|
#else
|
||||||
# include <unistd.h>
|
# include <unistd.h>
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
@ -269,6 +270,146 @@ static const char kwsys_shared_forward_path_slash[2] = {KWSYS_SHARED_FORWARD_PAT
|
|||||||
# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
|
# define KWSYS_SHARED_FORWARD_LDPATH "LD_LIBRARY_PATH"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
typedef struct kwsys_sf_arg_info_s
|
||||||
|
{
|
||||||
|
const char* arg;
|
||||||
|
int size;
|
||||||
|
int quote;
|
||||||
|
} kwsys_sf_arg_info;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static kwsys_sf_arg_info kwsys_sf_get_arg_info(const char* in)
|
||||||
|
{
|
||||||
|
/* Initialize information. */
|
||||||
|
kwsys_sf_arg_info info;
|
||||||
|
|
||||||
|
/* String iterator. */
|
||||||
|
const char* c;
|
||||||
|
|
||||||
|
/* Keep track of how many backslashes have been encountered in a row. */
|
||||||
|
int windows_backslashes = 0;
|
||||||
|
|
||||||
|
/* Start with the length of the original argument, plus one for
|
||||||
|
either a terminating null or a separating space. */
|
||||||
|
info.arg = in;
|
||||||
|
info.size = (int)strlen(in) + 1;
|
||||||
|
info.quote = 0;
|
||||||
|
|
||||||
|
/* Scan the string for characters that require escaping or quoting. */
|
||||||
|
for(c=in; *c; ++c)
|
||||||
|
{
|
||||||
|
/* Check whether this character needs quotes. */
|
||||||
|
if(strchr(" \t?'#&<>|^", *c))
|
||||||
|
{
|
||||||
|
info.quote = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* On Windows only backslashes and double-quotes need escaping. */
|
||||||
|
if(*c == '\\')
|
||||||
|
{
|
||||||
|
/* Found a backslash. It may need to be escaped later. */
|
||||||
|
++windows_backslashes;
|
||||||
|
}
|
||||||
|
else if(*c == '"')
|
||||||
|
{
|
||||||
|
/* Found a double-quote. We need to escape it and all
|
||||||
|
immediately preceding backslashes. */
|
||||||
|
info.size += windows_backslashes + 1;
|
||||||
|
windows_backslashes = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Found another character. This eliminates the possibility
|
||||||
|
that any immediately preceding backslashes will be
|
||||||
|
escaped. */
|
||||||
|
windows_backslashes = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check whether the argument needs surrounding quotes. */
|
||||||
|
if(info.quote)
|
||||||
|
{
|
||||||
|
/* Surrounding quotes are needed. Allocate space for them. */
|
||||||
|
info.size += 2;
|
||||||
|
|
||||||
|
/* We must escape all ending backslashes when quoting on windows. */
|
||||||
|
info.size += windows_backslashes;
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static char* kwsys_sf_get_arg(kwsys_sf_arg_info info, char* out)
|
||||||
|
{
|
||||||
|
/* String iterator. */
|
||||||
|
const char* c;
|
||||||
|
|
||||||
|
/* Keep track of how many backslashes have been encountered in a row. */
|
||||||
|
int windows_backslashes = 0;
|
||||||
|
|
||||||
|
/* Whether the argument must be quoted. */
|
||||||
|
if(info.quote)
|
||||||
|
{
|
||||||
|
/* Add the opening quote for this argument. */
|
||||||
|
*out++ = '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scan the string for characters that require escaping or quoting. */
|
||||||
|
for(c=info.arg; *c; ++c)
|
||||||
|
{
|
||||||
|
/* On Windows only backslashes and double-quotes need escaping. */
|
||||||
|
if(*c == '\\')
|
||||||
|
{
|
||||||
|
/* Found a backslash. It may need to be escaped later. */
|
||||||
|
++windows_backslashes;
|
||||||
|
}
|
||||||
|
else if(*c == '"')
|
||||||
|
{
|
||||||
|
/* Found a double-quote. Escape all immediately preceding
|
||||||
|
backslashes. */
|
||||||
|
while(windows_backslashes > 0)
|
||||||
|
{
|
||||||
|
--windows_backslashes;
|
||||||
|
*out++ = '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the backslash to escape the double-quote. */
|
||||||
|
*out++ = '\\';
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We encountered a normal character. This eliminates any
|
||||||
|
escaping needed for preceding backslashes. */
|
||||||
|
windows_backslashes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store this character. */
|
||||||
|
*out++ = *c;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(info.quote)
|
||||||
|
{
|
||||||
|
/* Add enough backslashes to escape any trailing ones. */
|
||||||
|
while(windows_backslashes > 0)
|
||||||
|
{
|
||||||
|
--windows_backslashes;
|
||||||
|
*out++ = '\\';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add the closing quote for this argument. */
|
||||||
|
*out++ = '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Store a terminating null without incrementing. */
|
||||||
|
*out = 0;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Function to convert a logical or relative path to a physical full path. */
|
/* Function to convert a logical or relative path to a physical full path. */
|
||||||
static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
|
static int kwsys_shared_forward_realpath(const char* in_path, char* out_path)
|
||||||
@ -341,8 +482,34 @@ static void kwsys_shared_forward_strerror(char* message)
|
|||||||
|
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
/* Functions to execute a child process. */
|
/* Functions to execute a child process. */
|
||||||
static void kwsys_shared_forward_execvp(const char* cmd, char* const argv[])
|
static void kwsys_shared_forward_execvp(const char* cmd, char* const* argv)
|
||||||
{
|
{
|
||||||
|
#ifdef KWSYS_SHARED_FORWARD_ESCAPE_ARGV
|
||||||
|
/* Count the number of arguments. */
|
||||||
|
int argc = 0;
|
||||||
|
{
|
||||||
|
char* const* argvc;
|
||||||
|
for(argvc = argv; *argvc; ++argvc,++argc) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create the escaped arguments. */
|
||||||
|
{
|
||||||
|
char** nargv = (char**)malloc((argc+1) * sizeof(char*));
|
||||||
|
int i;
|
||||||
|
for(i=0; i < argc; ++i)
|
||||||
|
{
|
||||||
|
kwsys_sf_arg_info info = kwsys_sf_get_arg_info(argv[i]);
|
||||||
|
nargv[i] = (char*)malloc(info.size);
|
||||||
|
kwsys_sf_get_arg(info, nargv[i]);
|
||||||
|
}
|
||||||
|
nargv[argc] = 0;
|
||||||
|
|
||||||
|
/* Replace the command line to be used. */
|
||||||
|
argv = nargv;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Invoke the child process. */
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
_execvp(cmd, argv);
|
_execvp(cmd, argv);
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user