diff options
Diffstat (limited to 'pr/src/md/os2/os2misc.c')
-rw-r--r-- | pr/src/md/os2/os2misc.c | 344 |
1 files changed, 145 insertions, 199 deletions
diff --git a/pr/src/md/os2/os2misc.c b/pr/src/md/os2/os2misc.c index be597fcd..c27b0614 100644 --- a/pr/src/md/os2/os2misc.c +++ b/pr/src/md/os2/os2misc.c @@ -118,107 +118,28 @@ PR_Now(void) 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, a null between - * the EXE name and the arguments, and 2 nulls at the end - * of command line. - */ - cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */ - + 2 /* we quote every argument */ - + 4; /* space in between, or final nulls */ - } - p = *cmdLine = PR_MALLOC(cmdLineSize); - if (p == NULL) { + for (arg = argv+1; *arg; arg++) { + cmdLineSize += strlen(*arg) + 1; /* space in between, or final null */ + } + *cmdLine = PR_MALLOC(cmdLineSize); + if (*cmdLine == NULL) { return -1; } - for (arg = argv; *arg; arg++) { - /* Add a space to separates the arguments */ - if (arg > argv + 1) { - *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++; - } - } + (*cmdLine)[0] = '\0'; - /* 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++ = '\\'; - } + for (arg = argv+1; *arg; arg++) { + if (arg > argv +1) { + strcat(*cmdLine, " "); } - if (argNeedQuotes) { - *p++ = '"'; - } - if(arg == argv) - *p++ = '\0'; + strcat(*cmdLine, *arg); } - - /* Add 2 nulls at the end */ - *p++ = '\0'; - *p = '\0'; return 0; } @@ -308,129 +229,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) == 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_INDEPENDENT; + 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) { |