trunk fix for 84115. Pass arguments to the process (I omitted these in an earlier

checkin). Bad because xpi files that invoke processes with args are not functioning
correctly. r=ssu, sr=mscott, a=drivers (asa)
This commit is contained in:
syd%netscape.com 2001-06-06 04:33:19 +00:00
Родитель 16951bbe32
Коммит 421006c67d
1 изменённых файлов: 114 добавлений и 2 удалений

Просмотреть файл

@ -39,6 +39,7 @@
#include <stdlib.h>
#if defined( XP_WIN )
#include "prmem.h"
#include "nsString.h"
#include "nsLiteralString.h"
#include "nsReadableUtils.h"
@ -85,6 +86,110 @@ nsProcess::Init(nsIFile* executable)
}
#if defined( XP_WIN )
static int assembleCmdLine(char *const *argv, char **cmdLine)
{
char *const *arg;
char *p, *q;
int cmdLineSize;
int numBackslashes;
int i;
int argNeedQuotes;
/*
* Find out how large the command line buffer should be.
*/
cmdLineSize = 0;
for (arg = argv; *arg; arg++) {
/*
* \ and " need to be escaped by a \. In the worst case,
* every character is a \ or ", so the string of length
* may double. If we quote an argument, that needs two ".
* Finally, we need a space between arguments, and
* a null byte at the end of command line.
*/
cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */
+ 2 /* we quote every argument */
+ 1; /* space in between, or final null */
}
p = *cmdLine = (char *) PR_MALLOC(cmdLineSize);
if (p == NULL) {
return -1;
}
for (arg = argv; *arg; arg++) {
/* Add a space to separates the arguments */
if (arg != argv) {
*p++ = ' ';
}
q = *arg;
numBackslashes = 0;
argNeedQuotes = 0;
/* If the argument contains white space, it needs to be quoted. */
if (strpbrk(*arg, " \f\n\r\t\v")) {
argNeedQuotes = 1;
}
if (argNeedQuotes) {
*p++ = '"';
}
while (*q) {
if (*q == '\\') {
numBackslashes++;
q++;
} else if (*q == '"') {
if (numBackslashes) {
/*
* Double the backslashes since they are followed
* by a quote
*/
for (i = 0; i < 2 * numBackslashes; i++) {
*p++ = '\\';
}
numBackslashes = 0;
}
/* To escape the quote */
*p++ = '\\';
*p++ = *q++;
} else {
if (numBackslashes) {
/*
* Backslashes are not followed by a quote, so
* don't need to double the backslashes.
*/
for (i = 0; i < numBackslashes; i++) {
*p++ = '\\';
}
numBackslashes = 0;
}
*p++ = *q++;
}
}
/* Now we are at the end of this argument */
if (numBackslashes) {
/*
* Double the backslashes if we have a quote string
* delimiter at the end.
*/
if (argNeedQuotes) {
numBackslashes *= 2;
}
for (i = 0; i < numBackslashes; i++) {
*p++ = '\\';
}
}
if (argNeedQuotes) {
*p++ = '"';
}
}
*p = '\0';
return 0;
}
#endif
NS_IMETHODIMP
nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid)
{
@ -113,12 +218,19 @@ nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid
STARTUPINFO startupInfo;
PROCESS_INFORMATION procInfo;
BOOL retVal;
char *cmdLine;
if (assembleCmdLine(my_argv, &cmdLine) == -1) {
nsMemory::Free(my_argv);
return NS_ERROR_FILE_EXECUTION_FAILED;
}
ZeroMemory(&startupInfo, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
retVal = CreateProcess(NULL,
NS_CONST_CAST(char*, mTargetPath.get()),
// NS_CONST_CAST(char*, mTargetPath.get()),
cmdLine,
NULL, /* security attributes for the new
* process */
NULL, /* security attributes for the primary
@ -130,7 +242,7 @@ nsProcess::Run(PRBool blocking, const char **args, PRUint32 count, PRUint32 *pid
&startupInfo,
&procInfo
);
PR_FREEIF( cmdLine );
if (blocking) {
// if success, wait for process termination. the early returns and such