diff options
author | Brad King <brad.king@kitware.com> | 2006-06-15 14:40:42 -0400 |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2006-06-15 14:40:42 -0400 |
commit | 6438bec4c9355960f47e4b853f27b548a55ec5e0 (patch) | |
tree | 9580881b94fa12d7201875fbf5cc30194d3d7d1f /Source/kwsys/ProcessWin32.c | |
parent | 6071052835552a7dbdf7bd4f38263c6f206b26dd (diff) | |
download | cmake-6438bec4c9355960f47e4b853f27b548a55ec5e0.tar.gz |
ENH: Added Option_Verbatim to run whole command lines directly.
Diffstat (limited to 'Source/kwsys/ProcessWin32.c')
-rw-r--r-- | Source/kwsys/ProcessWin32.c | 361 |
1 files changed, 205 insertions, 156 deletions
diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index 26b77f9035..406a187176 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -107,6 +107,11 @@ static void kwsysProcessCleanupHandle(PHANDLE h); static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle); 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, @@ -206,6 +211,9 @@ struct kwsysProcess_s /* Whether to hide the child process's window. */ int HideWindow; + /* Whether to treat command lines as verbatim. */ + int Verbatim; + /* On Win9x platforms, the path to the forwarding executable. */ char* Win9x; @@ -646,7 +654,7 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) char** newCommands; /* Make sure we have a command to add. */ - if(!cp || !command) + if(!cp || !command || !*command) { return 0; } @@ -669,77 +677,19 @@ 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. */ + 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. */ { - char* cmd; - char const* const* arg; - int length = 0; /* First determine the length of the final string. */ - for(arg = command; *arg; ++arg) - { - /* Keep track of how many backslashes have been encountered in a - row in this argument. */ - int backslashes = 0; - int spaces = 0; - const char* c; - - /* Scan the string for spaces. If there are no spaces, we can - pass the argument verbatim. */ - for(c=*arg; *c; ++c) - { - if(*c == ' ' || *c == '\t') - { - spaces = 1; - break; - } - } - - /* Add the length of the argument, plus 1 for the space - separating the arguments. */ - length += (int)strlen(*arg) + 1; - - if(spaces) - { - /* Add 2 for double quotes since spaces are present. */ - length += 2; - - /* Scan the string to find characters that need escaping. */ - for(c=*arg; *c; ++c) - { - if(*c == '\\') - { - /* Found a backslash. It may need to be escaped later. */ - ++backslashes; - } - else if(*c == '"') - { - /* Found a double-quote. We need to escape it and all - immediately preceding backslashes. */ - length += backslashes + 1; - backslashes = 0; - } - else - { - /* Found another character. This eliminates the possibility - that any immediately preceding backslashes will be - escaped. */ - backslashes = 0; - } - } - - /* We need to escape all ending backslashes. */ - length += backslashes; - } - } + 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. */ + byte for the terminating null because we allocated a space for + the first argument that we will not use. */ newCommands[cp->NumberOfCommands] = (char*)malloc(length); if(!newCommands[cp->NumberOfCommands]) { @@ -749,94 +699,8 @@ int kwsysProcess_AddCommand(kwsysProcess* cp, char const* const* command) } /* Construct the command line in the allocated buffer. */ - cmd = newCommands[cp->NumberOfCommands]; - for(arg = command; *arg; ++arg) - { - /* Keep track of how many backslashes have been encountered in a - row in an argument. */ - int backslashes = 0; - int spaces = 0; - const char* c; - - /* Scan the string for spaces. If there are no spaces, we can - pass the argument verbatim. */ - for(c=*arg; *c; ++c) - { - if(*c == ' ' || *c == '\t') - { - spaces = 1; - break; - } - } - - /* Add the separating space if this is not the first argument. */ - if(arg != command) - { - *cmd++ = ' '; - } - - if(spaces) - { - /* Add the opening double-quote for this argument. */ - *cmd++ = '"'; - - /* Add the characters of the argument, possibly escaping them. */ - for(c=*arg; *c; ++c) - { - if(*c == '\\') - { - /* Found a backslash. It may need to be escaped later. */ - ++backslashes; - *cmd++ = '\\'; - } - else if(*c == '"') - { - /* Add enough backslashes to escape any that preceded the - double-quote. */ - while(backslashes > 0) - { - --backslashes; - *cmd++ = '\\'; - } - - /* Add the backslash to escape the double-quote. */ - *cmd++ = '\\'; - - /* Add the double-quote itself. */ - *cmd++ = '"'; - } - else - { - /* We encountered a normal character. This eliminates any - escaping needed for preceding backslashes. Add the - character. */ - backslashes = 0; - *cmd++ = *c; - } - } - - /* Add enough backslashes to escape any trailing ones. */ - while(backslashes > 0) - { - --backslashes; - *cmd++ = '\\'; - } - - /* Add the closing double-quote for this argument. */ - *cmd++ = '"'; - } - else - { - /* No spaces. Add the argument verbatim. */ - for(c=*arg; *c; ++c) - { - *cmd++ = *c; - } - } - } - - /* Add the terminating null character to the command line. */ - *cmd = 0; + kwsysProcessComputeCommandLine(cp, command, + newCommands[cp->NumberOfCommands]); } /* Save the new array of commands. */ @@ -968,6 +832,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) { case kwsysProcess_Option_Detach: return cp->OptionDetach; case kwsysProcess_Option_HideWindow: return cp->HideWindow; + case kwsysProcess_Option_Verbatim: return cp->Verbatim; default: return 0; } } @@ -984,6 +849,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) { case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; + case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; default: break; } } @@ -2199,6 +2065,189 @@ 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 = 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) + { + /* Keep track of how many backslashes have been encountered in a + row in this argument. */ + int backslashes = 0; + int spaces = 0; + const char* c; + + /* Scan the string for spaces. If there are no spaces, we can + pass the argument verbatim. */ + for(c=*arg; *c; ++c) + { + if(*c == ' ' || *c == '\t') + { + spaces = 1; + break; + } + } + + /* Add the length of the argument, plus 1 for the space + separating the arguments. */ + length += (int)strlen(*arg) + 1; + + if(spaces) + { + /* Add 2 for double quotes since spaces are present. */ + length += 2; + + /* Scan the string to find characters that need escaping. */ + for(c=*arg; *c; ++c) + { + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++backslashes; + } + else if(*c == '"') + { + /* Found a double-quote. We need to escape it and all + immediately preceding backslashes. */ + length += backslashes + 1; + backslashes = 0; + } + else + { + /* Found another character. This eliminates the possibility + that any immediately preceding backslashes will be + escaped. */ + backslashes = 0; + } + } + + /* We need to escape all ending backslashes. */ + length += backslashes; + } + } + } + + 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) + { + /* Keep track of how many backslashes have been encountered in a + row in an argument. */ + int backslashes = 0; + int spaces = 0; + const char* c; + + /* Scan the string for spaces. If there are no spaces, we can + pass the argument verbatim. */ + for(c=*arg; *c; ++c) + { + if(*c == ' ' || *c == '\t') + { + spaces = 1; + break; + } + } + + /* Add the separating space if this is not the first argument. */ + if(arg != command) + { + *cmd++ = ' '; + } + + if(spaces) + { + /* Add the opening double-quote for this argument. */ + *cmd++ = '"'; + + /* Add the characters of the argument, possibly escaping them. */ + for(c=*arg; *c; ++c) + { + if(*c == '\\') + { + /* Found a backslash. It may need to be escaped later. */ + ++backslashes; + *cmd++ = '\\'; + } + else if(*c == '"') + { + /* Add enough backslashes to escape any that preceded the + double-quote. */ + while(backslashes > 0) + { + --backslashes; + *cmd++ = '\\'; + } + + /* Add the backslash to escape the double-quote. */ + *cmd++ = '\\'; + + /* Add the double-quote itself. */ + *cmd++ = '"'; + } + else + { + /* We encountered a normal character. This eliminates any + escaping needed for preceding backslashes. Add the + character. */ + backslashes = 0; + *cmd++ = *c; + } + } + + /* Add enough backslashes to escape any trailing ones. */ + while(backslashes > 0) + { + --backslashes; + *cmd++ = '\\'; + } + + /* Add the closing double-quote for this argument. */ + *cmd++ = '"'; + } + else + { + /* No spaces. Add the argument verbatim. */ + for(c=*arg; *c; ++c) + { + *cmd++ = *c; + } + } + } + + /* 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. */ int kwsysProcessGetTimeoutTime(kwsysProcess* cp, double* userTimeout, |