diff options
Diffstat (limited to 'pr/src/md/os2/os2misc.c')
-rw-r--r-- | pr/src/md/os2/os2misc.c | 398 |
1 files changed, 148 insertions, 250 deletions
diff --git a/pr/src/md/os2/os2misc.c b/pr/src/md/os2/os2misc.c index be597fcd..4e9bb932 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) { + cmdLineSize = 1; /* final null */ + for (arg = argv+1; *arg; arg++) { + cmdLineSize += strlen(*arg) + 1; /* space in between */ + } + *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; - } + (*cmdLine)[0] = '\0'; - if (argNeedQuotes) { - *p++ = '"'; + for (arg = argv+1; *arg; arg++) { + if (arg > argv +1) { + strcat(*cmdLine, " "); } - 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++ = '"'; - } - if(arg == argv) - *p++ = '\0'; + strcat(*cmdLine, *arg); } - - /* Add 2 nulls at the end */ - *p++ = '\0'; - *p = '\0'; return 0; } @@ -308,138 +229,160 @@ 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 = NULL; + 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_SHELL; + + 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) { - /* This is basically what they did on Windows (CloseHandle) - * but I don't think it will do much on OS/2. A process is - * either created as a child or not. You can't 'detach' it - * later on. + /* On OS/2, a process is either created as a child or not. + * You can't 'detach' it later on. */ - DosClose(process->md.pid); PR_DELETE(process); return PR_SUCCESS; } @@ -506,14 +449,12 @@ _PR_MD_WAKEUP_CPUS( void ) PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRInt32 _MD_GetMemMapAlignment(void) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return -1; } @@ -523,21 +464,18 @@ void * _MD_MemMap( PROffset64 offset, PRUint32 len) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return NULL; } PRStatus _MD_MemUnmap(void *addr, PRUint32 len) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } PRStatus _MD_CloseFileMap(PRFileMap *fmap) { - PR_ASSERT(!"Not implemented"); PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); return PR_FAILURE; } @@ -577,43 +515,3 @@ unsigned long _System _DLL_InitTerm( unsigned long mod_handle, unsigned long fla return rc; } -#ifndef XP_OS2_VACPP - -PRInt32 _PR_MD_ATOMIC_SET(PRInt32 *intp, PRInt32 val) -{ - PRInt32 result; - asm volatile ("lock ; xchg %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); - return result; -} - -PRInt32 _PR_MD_ATOMIC_ADD(PRInt32 *intp, PRInt32 val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(intp) - : "0"(val), "m"(intp)); - return result + val; -} - -PRInt32 _PR_MD_ATOMIC_INCREMENT(PRInt32 *val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); - return result + 1; -} - -PRInt32 _PR_MD_ATOMIC_DECREMENT(PRInt32 *val) -{ - PRInt32 result; - asm volatile ("lock ; xadd %0, %1" - : "=r"(result), "=m"(*val) - : "0"(1), "m"(*val)); - return result - 1; -} - -#endif - |