Commit 8504e845 authored by Brad King's avatar Brad King
Browse files

Process: Simplify Windows command line construction

Use an algorithm that simply reverses CommandLineToArgvW to construct
a string encoding command line arguments.

Change-Id: I52a5d27679da3962eda36b8bb6a1fb714a735a1d
parent 1f19c187
......@@ -11,14 +11,12 @@
============================================================================*/
#include "kwsysPrivate.h"
#include KWSYS_HEADER(Process.h)
#include KWSYS_HEADER(System.h)
#include KWSYS_HEADER(Encoding.h)
/* Work-around CMake dependency scanning limitation. This must
duplicate the above list of headers. */
#if 0
# include "Process.h.in"
# include "System.h.in"
# include "Encoding_c.h.in"
#endif
......@@ -120,11 +118,6 @@ static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle);
static void kwsysProcessCleanupHandle(PHANDLE h);
static void kwsysProcessCleanup(kwsysProcess* cp, int error);
static void kwsysProcessCleanErrorMessage(kwsysProcess* cp);
static int kwsysProcessComputeCommandLength(kwsysProcess* cp,
char const* const* command);
static void kwsysProcessComputeCommandLine(kwsysProcess* cp,
char const* const* command,
char* cmd);
static int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout,
kwsysProcessTime* timeoutTime);
static int kwsysProcessGetTimeoutLeft(kwsysProcessTime* timeoutTime,
......@@ -602,37 +595,69 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command)
}
}
/* We need to construct a single string representing the command
and its arguments. We will surround each argument containing
spaces with double-quotes. Inside a double-quoted argument, we
need to escape double-quotes and all backslashes before them.
We also need to escape backslashes at the end of an argument
because they come before the closing double-quote for the
argument. */
{
/* First determine the length of the final string. */
int length = kwsysProcessComputeCommandLength(cp, command);
/* Allocate enough space for the command. We do not need an extra
byte for the terminating null because we allocated a space for
the first argument that we will not use. */
char* new_cmd = malloc(length);
if(!new_cmd)
if (cp->Verbatim)
{
/* Out of memory. */
/* Copy the verbatim command line into the buffer. */
newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(*command);
}
else
{
/* Encode the arguments so CommandLineToArgvW can decode
them from the command line string in the child. */
char buffer[32768]; /* CreateProcess max command-line length. */
char* end = buffer + sizeof(buffer);
char* out = buffer;
char const* const* a;
for (a = command; *a; ++a)
{
int quote = !**a; /* Quote the empty string. */
int slashes = 0;
char const* c;
if (a != command && out != end) { *out++ = ' '; }
for (c = *a; !quote && *c; ++c)
{ quote = (*c == ' ' || *c == '\t'); }
if (quote && out != end) { *out++ = '"'; }
for (c = *a; *c; ++c)
{
if (*c == '\\')
{
++slashes;
}
else
{
if (*c == '"')
{
// Add n+1 backslashes to total 2n+1 before internal '"'.
while(slashes-- >= 0 && out != end) { *out++ = '\\'; }
}
slashes = 0;
}
if (out != end) { *out++ = *c; }
}
if (quote)
{
// Add n backslashes to total 2n before ending '"'.
while (slashes-- > 0 && out != end) { *out++ = '\\'; }
if (out != end) { *out++ = '"'; }
}
}
if(out != end)
{
*out = '\0';
newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(buffer);
}
else
{
newCommands[cp->NumberOfCommands] = 0;
}
}
if (!newCommands[cp->NumberOfCommands])
{
/* Out of memory or command line too long. */
free(newCommands);
return 0;
}
/* Construct the command line in the allocated buffer. */
kwsysProcessComputeCommandLine(cp, command,
new_cmd);
newCommands[cp->NumberOfCommands] = kwsysEncoding_DupToWide(new_cmd);
free(new_cmd);
}
/* Save the new array of commands. */
free(cp->Commands);
cp->Commands = newCommands;
......@@ -1961,66 +1986,6 @@ void kwsysProcessCleanErrorMessage(kwsysProcess* cp)
}
}
/*--------------------------------------------------------------------------*/
int kwsysProcessComputeCommandLength(kwsysProcess* cp,
char const* const* command)
{
int length = 0;
if(cp->Verbatim)
{
/* Treat the first argument as a verbatim command line. Use its
length directly and add space for the null-terminator. */
length = (int)strlen(*command)+1;
}
else
{
/* Compute the length of the command line when it is converted to
a single string. Space for the null-terminator is allocated by
the whitespace character allocated for the first argument that
will not be used. */
char const* const* arg;
for(arg = command; *arg; ++arg)
{
/* Add the length of this argument. It already includes room
for a separating space or terminating null. */
length += kwsysSystem_Shell_GetArgumentSizeForWindows(*arg, 0);
}
}
return length;
}
/*--------------------------------------------------------------------------*/
void kwsysProcessComputeCommandLine(kwsysProcess* cp,
char const* const* command,
char* cmd)
{
if(cp->Verbatim)
{
/* Copy the verbatim command line into the buffer. */
strcpy(cmd, *command);
}
else
{
/* Construct the command line in the allocated buffer. */
char const* const* arg;
for(arg = command; *arg; ++arg)
{
/* Add the separating space if this is not the first argument. */
if(arg != command)
{
*cmd++ = ' ';
}
/* Add the current argument. */
cmd = kwsysSystem_Shell_GetArgumentForWindows(*arg, cmd, 0);
}
/* Add the terminating null character to the command line. */
*cmd = 0;
}
}
/*--------------------------------------------------------------------------*/
/* Get the time at which either the process or user timeout will
expire. Returns 1 if the user timeout is first, and 0 otherwise. */
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment