diff options
author | wtc%netscape.com <devnull@localhost> | 2002-01-12 01:06:32 +0000 |
---|---|---|
committer | wtc%netscape.com <devnull@localhost> | 2002-01-12 01:06:32 +0000 |
commit | b5907e7dcb74c70fe2aa413cc6bec773b93a917c (patch) | |
tree | b9830c7f2fba5b42dceb0f64a9a1348160a5a770 | |
parent | 6f2eb08b88173f282ab23c0ac6644cb24b28a50c (diff) | |
download | nspr-hg-b5907e7dcb74c70fe2aa413cc6bec773b93a917c.tar.gz |
Checked in the fix for bug 118631 on the NSPRPUB_PRE_4_2_CLIENT_BRANCH.
-rw-r--r-- | pr/src/md/os2/os2misc.c | 254 |
1 files changed, 139 insertions, 115 deletions
diff --git a/pr/src/md/os2/os2misc.c b/pr/src/md/os2/os2misc.c index be597fcd..2c8a9b56 100644 --- a/pr/src/md/os2/os2misc.c +++ b/pr/src/md/os2/os2misc.c @@ -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; - - 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) { - /* 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); + 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; + } + + 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++; } - if (attr->stderrFd) { - hStdErr = 2; - DosDupHandle(hStdErr, &hStdErrSave); - DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr); + newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *)); + for (i = 0; i <= numEnv; i++) { + newEnvp[i] = envp[i]; } - } - - 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); - } + 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 (retVal != NO_ERROR) { - /* XXX what error code? */ - PR_SetError(PR_UNKNOWN_ERROR, retVal); + 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; + } + } + } + } + if (ulAppType == 0) { + PR_SetError(PR_UNKNOWN_ERROR, 0); goto errorExit; - } - - proc->md.pid = procInfo.codeTerminate; + } + + 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 ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) { + PR_SetError(PR_UNKNOWN_ERROR, 0); + } + + proc->md.pid = pid; - 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) { |