mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bugzilla bug 118631: a correct implementation of _PR_CreateOS2Process.
The patch is contributed by Michael Kaply <mkaply@us.ibm.com>. r=Javier Pedemonte.
This commit is contained in:
parent
64f0128f80
commit
f11b7d2893
@ -128,7 +128,7 @@ static int assembleCmdLine(char *const *argv, char **cmdLine)
|
||||
* Find out how large the command line buffer should be.
|
||||
*/
|
||||
cmdLineSize = 0;
|
||||
for (arg = argv; *arg; arg++) {
|
||||
for (arg = argv+1; *arg; arg++) {
|
||||
/*
|
||||
* \ and " need to be escaped by a \. In the worst case,
|
||||
* every character is a \ or ", so the string of length
|
||||
@ -146,7 +146,7 @@ static int assembleCmdLine(char *const *argv, char **cmdLine)
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (arg = argv; *arg; arg++) {
|
||||
for (arg = argv+1; *arg; arg++) {
|
||||
/* Add a space to separates the arguments */
|
||||
if (arg > argv + 1) {
|
||||
*p++ = ' ';
|
||||
@ -213,11 +213,10 @@ static int assembleCmdLine(char *const *argv, char **cmdLine)
|
||||
*p++ = '"';
|
||||
}
|
||||
if(arg == argv)
|
||||
*p++ = '\0';
|
||||
*p++ = ' ';
|
||||
}
|
||||
|
||||
/* Add 2 nulls at the end */
|
||||
*p++ = '\0';
|
||||
/* Add a null at the end */
|
||||
*p = '\0';
|
||||
return 0;
|
||||
}
|
||||
@ -308,129 +307,154 @@ static int compare(const void *arg1, const void *arg2)
|
||||
{
|
||||
return stricmp(* (char**)arg1, * (char**)arg2);
|
||||
}
|
||||
|
||||
PRProcess * _PR_CreateOS2Process(
|
||||
const char *path,
|
||||
char *const *argv,
|
||||
char *const *envp,
|
||||
const PRProcessAttr *attr)
|
||||
{
|
||||
char szFailed[CCHMAXPATH];
|
||||
RESULTCODES procInfo;
|
||||
APIRET retVal;
|
||||
char *cmdLine = NULL;
|
||||
char *envBlock = NULL;
|
||||
char **newEnvp;
|
||||
PRProcess *proc = NULL;
|
||||
HFILE hStdIn = 0,
|
||||
hStdOut = 0,
|
||||
hStdErr = 0;
|
||||
HFILE hStdInSave = -1,
|
||||
hStdOutSave = -1,
|
||||
hStdErrSave = -1;
|
||||
PRProcess *proc = NULL;
|
||||
char *cmdLine = NULL;
|
||||
char **newEnvp;
|
||||
char *envBlock = NULL;
|
||||
|
||||
STARTDATA startData = {0};
|
||||
APIRET rc;
|
||||
ULONG ulAppType = 0;
|
||||
PID pid = 0;
|
||||
char *pEnvWPS = NULL;
|
||||
char *pszComSpec;
|
||||
char pszEXEName[CCHMAXPATH] = "";
|
||||
char pszFormatString[CCHMAXPATH];
|
||||
char pszObjectBuffer[CCHMAXPATH];
|
||||
char *pszFormatResult = NULL;
|
||||
|
||||
proc = PR_NEW(PRProcess);
|
||||
if (!proc) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
proc = PR_NEW(PRProcess);
|
||||
if (!proc) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (assembleCmdLine(argv, &cmdLine) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (envp == NULL) {
|
||||
newEnvp = NULL;
|
||||
} else {
|
||||
int i;
|
||||
int numEnv = 0;
|
||||
while (envp[numEnv]) {
|
||||
numEnv++;
|
||||
}
|
||||
newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *));
|
||||
for (i = 0; i <= numEnv; i++) {
|
||||
newEnvp[i] = envp[i];
|
||||
}
|
||||
qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
|
||||
}
|
||||
if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
PR_ASSERT(!"Not implemented");
|
||||
}
|
||||
|
||||
if (assembleCmdLine(argv, &cmdLine) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
if (envp == NULL) {
|
||||
newEnvp = NULL;
|
||||
} else {
|
||||
int i;
|
||||
int numEnv = 0;
|
||||
while (envp[numEnv]) {
|
||||
numEnv++;
|
||||
rc = DosQueryAppType(path, &ulAppType);
|
||||
if (rc != NO_ERROR) {
|
||||
char *pszDot = strrchr(path, '.');
|
||||
if (pszDot) {
|
||||
/* If it is a CMD file, launch the users command processor */
|
||||
if (!stricmp(pszDot, ".cmd")) {
|
||||
rc = DosScanEnv("COMSPEC", &pszComSpec);
|
||||
if (!rc) {
|
||||
strcpy(pszFormatString, "/C %s %s");
|
||||
strcpy(pszEXEName, pszComSpec);
|
||||
ulAppType = FAPPTYP_WINDOWCOMPAT;
|
||||
}
|
||||
}
|
||||
}
|
||||
newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *));
|
||||
for (i = 0; i <= numEnv; i++) {
|
||||
newEnvp[i] = envp[i];
|
||||
}
|
||||
qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare);
|
||||
}
|
||||
if (assembleEnvBlock(newEnvp, &envBlock) == -1) {
|
||||
PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0);
|
||||
}
|
||||
if (ulAppType == 0) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
goto errorExit;
|
||||
}
|
||||
}
|
||||
|
||||
if (ulAppType & FAPPTYP_WINDOWAPI) {
|
||||
startData.SessionType = SSF_TYPE_PM;
|
||||
}
|
||||
else if (ulAppType & FAPPTYP_WINDOWCOMPAT) {
|
||||
startData.SessionType = SSF_TYPE_WINDOWABLEVIO;
|
||||
}
|
||||
else {
|
||||
startData.SessionType = SSF_TYPE_DEFAULT;
|
||||
}
|
||||
|
||||
if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL))
|
||||
{
|
||||
strcpy(pszEXEName, "WINOS2.COM");
|
||||
startData.SessionType = PROG_31_STDSEAMLESSVDM;
|
||||
strcpy(pszFormatString, "/3 %s %s");
|
||||
}
|
||||
|
||||
startData.InheritOpt = SSF_INHERTOPT_PARENT;
|
||||
|
||||
if (pszEXEName[0]) {
|
||||
pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine));
|
||||
sprintf(pszFormatResult, pszFormatString, path, cmdLine);
|
||||
startData.PgmInputs = pszFormatResult;
|
||||
} else {
|
||||
strcpy(pszEXEName, path);
|
||||
startData.PgmInputs = cmdLine;
|
||||
}
|
||||
startData.PgmName = pszEXEName;
|
||||
|
||||
startData.Length = sizeof(startData);
|
||||
startData.Related = SSF_RELATED_CHILD;
|
||||
startData.ObjectBuffer = pszObjectBuffer;
|
||||
startData.ObjectBuffLen = CCHMAXPATH;
|
||||
startData.Environment = envBlock;
|
||||
|
||||
rc = DosStartSession(&startData, &ulAppType, &pid);
|
||||
|
||||
if (attr) {
|
||||
/* On OS/2, there is really no way to pass file handles for stdin, stdout,
|
||||
* and stderr to a new process. Instead, we can make it a child process
|
||||
* and make the given file handles a copy of our stdin, stdout, and stderr.
|
||||
* The child process then inherits ours, and we set ours back. Twisted
|
||||
* and gross I know. If you know a better way, please use it.
|
||||
*/
|
||||
if (attr->stdinFd) {
|
||||
hStdIn = 0;
|
||||
DosDupHandle(hStdIn, &hStdInSave);
|
||||
DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn);
|
||||
}
|
||||
if (attr->stdoutFd) {
|
||||
hStdOut = 1;
|
||||
DosDupHandle(hStdOut, &hStdOutSave);
|
||||
DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut);
|
||||
}
|
||||
if (attr->stderrFd) {
|
||||
hStdErr = 2;
|
||||
DosDupHandle(hStdErr, &hStdErrSave);
|
||||
DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr);
|
||||
}
|
||||
}
|
||||
if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) {
|
||||
PR_SetError(PR_UNKNOWN_ERROR, 0);
|
||||
}
|
||||
|
||||
proc->md.pid = pid;
|
||||
|
||||
retVal = DosExecPgm(szFailed,
|
||||
CCHMAXPATH,
|
||||
EXEC_ASYNCRESULT,
|
||||
cmdLine,
|
||||
envBlock,
|
||||
&procInfo,
|
||||
argv[0]);
|
||||
|
||||
/* Restore our old values. Hope this works */
|
||||
if(hStdInSave != -1){
|
||||
DosDupHandle(hStdInSave, &hStdIn);
|
||||
DosClose(hStdInSave);
|
||||
}
|
||||
if(hStdOutSave != -1){
|
||||
DosDupHandle(hStdOutSave, &hStdOut);
|
||||
DosClose(hStdOutSave);
|
||||
}
|
||||
if(hStdErrSave != -1){
|
||||
DosDupHandle(hStdErrSave, &hStdErr);
|
||||
DosClose(hStdErrSave);
|
||||
}
|
||||
|
||||
if (retVal != NO_ERROR) {
|
||||
/* XXX what error code? */
|
||||
PR_SetError(PR_UNKNOWN_ERROR, retVal);
|
||||
goto errorExit;
|
||||
}
|
||||
|
||||
proc->md.pid = procInfo.codeTerminate;
|
||||
|
||||
PR_DELETE(cmdLine);
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
return proc;
|
||||
if (pszFormatResult) {
|
||||
PR_DELETE(pszFormatResult);
|
||||
}
|
||||
|
||||
PR_DELETE(cmdLine);
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
return proc;
|
||||
|
||||
errorExit:
|
||||
if (cmdLine) {
|
||||
PR_DELETE(cmdLine);
|
||||
}
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
if (proc) {
|
||||
PR_DELETE(proc);
|
||||
}
|
||||
return NULL;
|
||||
|
||||
} /* _PR_CreateWindowsProcess */
|
||||
if (cmdLine) {
|
||||
PR_DELETE(cmdLine);
|
||||
}
|
||||
if (newEnvp) {
|
||||
PR_DELETE(newEnvp);
|
||||
}
|
||||
if (envBlock) {
|
||||
PR_DELETE(envBlock);
|
||||
}
|
||||
if (proc) {
|
||||
PR_DELETE(proc);
|
||||
}
|
||||
return NULL;
|
||||
} /* _PR_CreateOS2Process */
|
||||
|
||||
PRStatus _PR_DetachOS2Process(PRProcess *process)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user