Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | /* |
michael@0 | 7 | * os2misc.c |
michael@0 | 8 | * |
michael@0 | 9 | */ |
michael@0 | 10 | |
michael@0 | 11 | #ifdef MOZ_OS2_HIGH_MEMORY |
michael@0 | 12 | /* os2safe.h has to be included before os2.h, needed for high mem */ |
michael@0 | 13 | #include <os2safe.h> |
michael@0 | 14 | #endif |
michael@0 | 15 | |
michael@0 | 16 | #include <string.h> |
michael@0 | 17 | #include "primpl.h" |
michael@0 | 18 | |
michael@0 | 19 | extern int _CRT_init(void); |
michael@0 | 20 | extern void _CRT_term(void); |
michael@0 | 21 | extern void __ctordtorInit(int flag); |
michael@0 | 22 | extern void __ctordtorTerm(int flag); |
michael@0 | 23 | |
michael@0 | 24 | char * |
michael@0 | 25 | _PR_MD_GET_ENV(const char *name) |
michael@0 | 26 | { |
michael@0 | 27 | return getenv(name); |
michael@0 | 28 | } |
michael@0 | 29 | |
michael@0 | 30 | PRIntn |
michael@0 | 31 | _PR_MD_PUT_ENV(const char *name) |
michael@0 | 32 | { |
michael@0 | 33 | return putenv(name); |
michael@0 | 34 | } |
michael@0 | 35 | |
michael@0 | 36 | |
michael@0 | 37 | /* |
michael@0 | 38 | ************************************************************************** |
michael@0 | 39 | ************************************************************************** |
michael@0 | 40 | ** |
michael@0 | 41 | ** Date and time routines |
michael@0 | 42 | ** |
michael@0 | 43 | ************************************************************************** |
michael@0 | 44 | ************************************************************************** |
michael@0 | 45 | */ |
michael@0 | 46 | |
michael@0 | 47 | #include <sys/timeb.h> |
michael@0 | 48 | /* |
michael@0 | 49 | *----------------------------------------------------------------------- |
michael@0 | 50 | * |
michael@0 | 51 | * PR_Now -- |
michael@0 | 52 | * |
michael@0 | 53 | * Returns the current time in microseconds since the epoch. |
michael@0 | 54 | * The epoch is midnight January 1, 1970 GMT. |
michael@0 | 55 | * The implementation is machine dependent. This is the |
michael@0 | 56 | * implementation for OS/2. |
michael@0 | 57 | * Cf. time_t time(time_t *tp) |
michael@0 | 58 | * |
michael@0 | 59 | *----------------------------------------------------------------------- |
michael@0 | 60 | */ |
michael@0 | 61 | |
michael@0 | 62 | PR_IMPLEMENT(PRTime) |
michael@0 | 63 | PR_Now(void) |
michael@0 | 64 | { |
michael@0 | 65 | PRInt64 s, ms, ms2us, s2us; |
michael@0 | 66 | struct timeb b; |
michael@0 | 67 | |
michael@0 | 68 | ftime(&b); |
michael@0 | 69 | LL_I2L(ms2us, PR_USEC_PER_MSEC); |
michael@0 | 70 | LL_I2L(s2us, PR_USEC_PER_SEC); |
michael@0 | 71 | LL_I2L(s, b.time); |
michael@0 | 72 | LL_I2L(ms, b.millitm); |
michael@0 | 73 | LL_MUL(ms, ms, ms2us); |
michael@0 | 74 | LL_MUL(s, s, s2us); |
michael@0 | 75 | LL_ADD(s, s, ms); |
michael@0 | 76 | return s; |
michael@0 | 77 | } |
michael@0 | 78 | |
michael@0 | 79 | |
michael@0 | 80 | /* |
michael@0 | 81 | *********************************************************************** |
michael@0 | 82 | *********************************************************************** |
michael@0 | 83 | * |
michael@0 | 84 | * Process creation routines |
michael@0 | 85 | * |
michael@0 | 86 | *********************************************************************** |
michael@0 | 87 | *********************************************************************** |
michael@0 | 88 | */ |
michael@0 | 89 | |
michael@0 | 90 | /* |
michael@0 | 91 | * Assemble the command line by concatenating the argv array. |
michael@0 | 92 | * Special characters intentionally do not get escaped, and it is |
michael@0 | 93 | * expected that the caller wraps arguments in quotes if needed |
michael@0 | 94 | * (e.g. for filename with spaces). |
michael@0 | 95 | * |
michael@0 | 96 | * On success, this function returns 0 and the resulting command |
michael@0 | 97 | * line is returned in *cmdLine. On failure, it returns -1. |
michael@0 | 98 | */ |
michael@0 | 99 | static int assembleCmdLine(char *const *argv, char **cmdLine) |
michael@0 | 100 | { |
michael@0 | 101 | char *const *arg; |
michael@0 | 102 | int cmdLineSize; |
michael@0 | 103 | |
michael@0 | 104 | /* |
michael@0 | 105 | * Find out how large the command line buffer should be. |
michael@0 | 106 | */ |
michael@0 | 107 | cmdLineSize = 1; /* final null */ |
michael@0 | 108 | for (arg = argv+1; *arg; arg++) { |
michael@0 | 109 | cmdLineSize += strlen(*arg) + 1; /* space in between */ |
michael@0 | 110 | } |
michael@0 | 111 | *cmdLine = PR_MALLOC(cmdLineSize); |
michael@0 | 112 | if (*cmdLine == NULL) { |
michael@0 | 113 | return -1; |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | (*cmdLine)[0] = '\0'; |
michael@0 | 117 | |
michael@0 | 118 | for (arg = argv+1; *arg; arg++) { |
michael@0 | 119 | if (arg > argv +1) { |
michael@0 | 120 | strcat(*cmdLine, " "); |
michael@0 | 121 | } |
michael@0 | 122 | strcat(*cmdLine, *arg); |
michael@0 | 123 | } |
michael@0 | 124 | return 0; |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | /* |
michael@0 | 128 | * Assemble the environment block by concatenating the envp array |
michael@0 | 129 | * (preserving the terminating null byte in each array element) |
michael@0 | 130 | * and adding a null byte at the end. |
michael@0 | 131 | * |
michael@0 | 132 | * Returns 0 on success. The resulting environment block is returned |
michael@0 | 133 | * in *envBlock. Note that if envp is NULL, a NULL pointer is returned |
michael@0 | 134 | * in *envBlock. Returns -1 on failure. |
michael@0 | 135 | */ |
michael@0 | 136 | static int assembleEnvBlock(char **envp, char **envBlock) |
michael@0 | 137 | { |
michael@0 | 138 | char *p; |
michael@0 | 139 | char *q; |
michael@0 | 140 | char **env; |
michael@0 | 141 | char *curEnv; |
michael@0 | 142 | char *cwdStart, *cwdEnd; |
michael@0 | 143 | int envBlockSize; |
michael@0 | 144 | |
michael@0 | 145 | PPIB ppib = NULL; |
michael@0 | 146 | PTIB ptib = NULL; |
michael@0 | 147 | |
michael@0 | 148 | if (envp == NULL) { |
michael@0 | 149 | *envBlock = NULL; |
michael@0 | 150 | return 0; |
michael@0 | 151 | } |
michael@0 | 152 | |
michael@0 | 153 | if(DosGetInfoBlocks(&ptib, &ppib) != NO_ERROR) |
michael@0 | 154 | return -1; |
michael@0 | 155 | |
michael@0 | 156 | curEnv = ppib->pib_pchenv; |
michael@0 | 157 | |
michael@0 | 158 | cwdStart = curEnv; |
michael@0 | 159 | while (*cwdStart) { |
michael@0 | 160 | if (cwdStart[0] == '=' && cwdStart[1] != '\0' |
michael@0 | 161 | && cwdStart[2] == ':' && cwdStart[3] == '=') { |
michael@0 | 162 | break; |
michael@0 | 163 | } |
michael@0 | 164 | cwdStart += strlen(cwdStart) + 1; |
michael@0 | 165 | } |
michael@0 | 166 | cwdEnd = cwdStart; |
michael@0 | 167 | if (*cwdEnd) { |
michael@0 | 168 | cwdEnd += strlen(cwdEnd) + 1; |
michael@0 | 169 | while (*cwdEnd) { |
michael@0 | 170 | if (cwdEnd[0] != '=' || cwdEnd[1] == '\0' |
michael@0 | 171 | || cwdEnd[2] != ':' || cwdEnd[3] != '=') { |
michael@0 | 172 | break; |
michael@0 | 173 | } |
michael@0 | 174 | cwdEnd += strlen(cwdEnd) + 1; |
michael@0 | 175 | } |
michael@0 | 176 | } |
michael@0 | 177 | envBlockSize = cwdEnd - cwdStart; |
michael@0 | 178 | |
michael@0 | 179 | for (env = envp; *env; env++) { |
michael@0 | 180 | envBlockSize += strlen(*env) + 1; |
michael@0 | 181 | } |
michael@0 | 182 | envBlockSize++; |
michael@0 | 183 | |
michael@0 | 184 | p = *envBlock = PR_MALLOC(envBlockSize); |
michael@0 | 185 | if (p == NULL) { |
michael@0 | 186 | return -1; |
michael@0 | 187 | } |
michael@0 | 188 | |
michael@0 | 189 | q = cwdStart; |
michael@0 | 190 | while (q < cwdEnd) { |
michael@0 | 191 | *p++ = *q++; |
michael@0 | 192 | } |
michael@0 | 193 | |
michael@0 | 194 | for (env = envp; *env; env++) { |
michael@0 | 195 | q = *env; |
michael@0 | 196 | while (*q) { |
michael@0 | 197 | *p++ = *q++; |
michael@0 | 198 | } |
michael@0 | 199 | *p++ = '\0'; |
michael@0 | 200 | } |
michael@0 | 201 | *p = '\0'; |
michael@0 | 202 | return 0; |
michael@0 | 203 | } |
michael@0 | 204 | |
michael@0 | 205 | /* |
michael@0 | 206 | * For qsort. We sort (case-insensitive) the environment strings |
michael@0 | 207 | * before generating the environment block. |
michael@0 | 208 | */ |
michael@0 | 209 | static int compare(const void *arg1, const void *arg2) |
michael@0 | 210 | { |
michael@0 | 211 | return stricmp(* (char**)arg1, * (char**)arg2); |
michael@0 | 212 | } |
michael@0 | 213 | |
michael@0 | 214 | PRProcess * _PR_CreateOS2Process( |
michael@0 | 215 | const char *path, |
michael@0 | 216 | char *const *argv, |
michael@0 | 217 | char *const *envp, |
michael@0 | 218 | const PRProcessAttr *attr) |
michael@0 | 219 | { |
michael@0 | 220 | PRProcess *proc = NULL; |
michael@0 | 221 | char *cmdLine = NULL; |
michael@0 | 222 | char **newEnvp = NULL; |
michael@0 | 223 | char *envBlock = NULL; |
michael@0 | 224 | |
michael@0 | 225 | STARTDATA startData = {0}; |
michael@0 | 226 | APIRET rc; |
michael@0 | 227 | ULONG ulAppType = 0; |
michael@0 | 228 | PID pid = 0; |
michael@0 | 229 | char *pszComSpec; |
michael@0 | 230 | char pszEXEName[CCHMAXPATH] = ""; |
michael@0 | 231 | char pszFormatString[CCHMAXPATH]; |
michael@0 | 232 | char pszObjectBuffer[CCHMAXPATH]; |
michael@0 | 233 | char *pszFormatResult = NULL; |
michael@0 | 234 | |
michael@0 | 235 | /* |
michael@0 | 236 | * Variables for DosExecPgm |
michael@0 | 237 | */ |
michael@0 | 238 | char szFailed[CCHMAXPATH]; |
michael@0 | 239 | char *pszCmdLine = NULL; |
michael@0 | 240 | RESULTCODES procInfo; |
michael@0 | 241 | HFILE hStdIn = 0, |
michael@0 | 242 | hStdOut = 0, |
michael@0 | 243 | hStdErr = 0; |
michael@0 | 244 | HFILE hStdInSave = -1, |
michael@0 | 245 | hStdOutSave = -1, |
michael@0 | 246 | hStdErrSave = -1; |
michael@0 | 247 | |
michael@0 | 248 | proc = PR_NEW(PRProcess); |
michael@0 | 249 | if (!proc) { |
michael@0 | 250 | PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
michael@0 | 251 | goto errorExit; |
michael@0 | 252 | } |
michael@0 | 253 | |
michael@0 | 254 | if (assembleCmdLine(argv, &cmdLine) == -1) { |
michael@0 | 255 | PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
michael@0 | 256 | goto errorExit; |
michael@0 | 257 | } |
michael@0 | 258 | |
michael@0 | 259 | #ifdef MOZ_OS2_HIGH_MEMORY |
michael@0 | 260 | /* |
michael@0 | 261 | * DosQueryAppType() fails if path (the char* in the first argument) is in |
michael@0 | 262 | * high memory. If that is the case, the following moves it to low memory. |
michael@0 | 263 | */ |
michael@0 | 264 | if ((ULONG)path >= 0x20000000) { |
michael@0 | 265 | size_t len = strlen(path) + 1; |
michael@0 | 266 | char *copy = (char *)alloca(len); |
michael@0 | 267 | memcpy(copy, path, len); |
michael@0 | 268 | path = copy; |
michael@0 | 269 | } |
michael@0 | 270 | #endif |
michael@0 | 271 | |
michael@0 | 272 | if (envp == NULL) { |
michael@0 | 273 | newEnvp = NULL; |
michael@0 | 274 | } else { |
michael@0 | 275 | int i; |
michael@0 | 276 | int numEnv = 0; |
michael@0 | 277 | while (envp[numEnv]) { |
michael@0 | 278 | numEnv++; |
michael@0 | 279 | } |
michael@0 | 280 | newEnvp = (char **) PR_MALLOC((numEnv+1) * sizeof(char *)); |
michael@0 | 281 | for (i = 0; i <= numEnv; i++) { |
michael@0 | 282 | newEnvp[i] = envp[i]; |
michael@0 | 283 | } |
michael@0 | 284 | qsort((void *) newEnvp, (size_t) numEnv, sizeof(char *), compare); |
michael@0 | 285 | } |
michael@0 | 286 | if (assembleEnvBlock(newEnvp, &envBlock) == -1) { |
michael@0 | 287 | PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); |
michael@0 | 288 | goto errorExit; |
michael@0 | 289 | } |
michael@0 | 290 | |
michael@0 | 291 | rc = DosQueryAppType(path, &ulAppType); |
michael@0 | 292 | if (rc != NO_ERROR) { |
michael@0 | 293 | char *pszDot = strrchr(path, '.'); |
michael@0 | 294 | if (pszDot) { |
michael@0 | 295 | /* If it is a CMD file, launch the users command processor */ |
michael@0 | 296 | if (!stricmp(pszDot, ".cmd")) { |
michael@0 | 297 | rc = DosScanEnv("COMSPEC", (PSZ *)&pszComSpec); |
michael@0 | 298 | if (!rc) { |
michael@0 | 299 | strcpy(pszFormatString, "/C %s %s"); |
michael@0 | 300 | strcpy(pszEXEName, pszComSpec); |
michael@0 | 301 | ulAppType = FAPPTYP_WINDOWCOMPAT; |
michael@0 | 302 | } |
michael@0 | 303 | } |
michael@0 | 304 | } |
michael@0 | 305 | } |
michael@0 | 306 | if (ulAppType == 0) { |
michael@0 | 307 | PR_SetError(PR_UNKNOWN_ERROR, 0); |
michael@0 | 308 | goto errorExit; |
michael@0 | 309 | } |
michael@0 | 310 | |
michael@0 | 311 | if ((ulAppType & FAPPTYP_WINDOWAPI) == FAPPTYP_WINDOWAPI) { |
michael@0 | 312 | startData.SessionType = SSF_TYPE_PM; |
michael@0 | 313 | } |
michael@0 | 314 | else if (ulAppType & FAPPTYP_WINDOWCOMPAT) { |
michael@0 | 315 | startData.SessionType = SSF_TYPE_WINDOWABLEVIO; |
michael@0 | 316 | } |
michael@0 | 317 | else { |
michael@0 | 318 | startData.SessionType = SSF_TYPE_DEFAULT; |
michael@0 | 319 | } |
michael@0 | 320 | |
michael@0 | 321 | if (ulAppType & (FAPPTYP_WINDOWSPROT31 | FAPPTYP_WINDOWSPROT | FAPPTYP_WINDOWSREAL)) |
michael@0 | 322 | { |
michael@0 | 323 | strcpy(pszEXEName, "WINOS2.COM"); |
michael@0 | 324 | startData.SessionType = PROG_31_STDSEAMLESSVDM; |
michael@0 | 325 | strcpy(pszFormatString, "/3 %s %s"); |
michael@0 | 326 | } |
michael@0 | 327 | |
michael@0 | 328 | startData.InheritOpt = SSF_INHERTOPT_SHELL; |
michael@0 | 329 | |
michael@0 | 330 | if (pszEXEName[0]) { |
michael@0 | 331 | pszFormatResult = PR_MALLOC(strlen(pszFormatString)+strlen(path)+strlen(cmdLine)); |
michael@0 | 332 | sprintf(pszFormatResult, pszFormatString, path, cmdLine); |
michael@0 | 333 | startData.PgmInputs = pszFormatResult; |
michael@0 | 334 | } else { |
michael@0 | 335 | strcpy(pszEXEName, path); |
michael@0 | 336 | startData.PgmInputs = cmdLine; |
michael@0 | 337 | } |
michael@0 | 338 | startData.PgmName = pszEXEName; |
michael@0 | 339 | |
michael@0 | 340 | startData.Length = sizeof(startData); |
michael@0 | 341 | startData.Related = SSF_RELATED_INDEPENDENT; |
michael@0 | 342 | startData.ObjectBuffer = pszObjectBuffer; |
michael@0 | 343 | startData.ObjectBuffLen = CCHMAXPATH; |
michael@0 | 344 | startData.Environment = envBlock; |
michael@0 | 345 | |
michael@0 | 346 | if (attr) { |
michael@0 | 347 | /* On OS/2, there is really no way to pass file handles for stdin, |
michael@0 | 348 | * stdout, and stderr to a new process. Instead, we can make it |
michael@0 | 349 | * a child process and make the given file handles a copy of our |
michael@0 | 350 | * stdin, stdout, and stderr. The child process then inherits |
michael@0 | 351 | * ours, and we set ours back. Twisted and gross I know. If you |
michael@0 | 352 | * know a better way, please use it. |
michael@0 | 353 | */ |
michael@0 | 354 | if (attr->stdinFd) { |
michael@0 | 355 | hStdIn = 0; |
michael@0 | 356 | DosDupHandle(hStdIn, &hStdInSave); |
michael@0 | 357 | DosDupHandle((HFILE) attr->stdinFd->secret->md.osfd, &hStdIn); |
michael@0 | 358 | } |
michael@0 | 359 | |
michael@0 | 360 | if (attr->stdoutFd) { |
michael@0 | 361 | hStdOut = 1; |
michael@0 | 362 | DosDupHandle(hStdOut, &hStdOutSave); |
michael@0 | 363 | DosDupHandle((HFILE) attr->stdoutFd->secret->md.osfd, &hStdOut); |
michael@0 | 364 | } |
michael@0 | 365 | |
michael@0 | 366 | if (attr->stderrFd) { |
michael@0 | 367 | hStdErr = 2; |
michael@0 | 368 | DosDupHandle(hStdErr, &hStdErrSave); |
michael@0 | 369 | DosDupHandle((HFILE) attr->stderrFd->secret->md.osfd, &hStdErr); |
michael@0 | 370 | } |
michael@0 | 371 | /* |
michael@0 | 372 | * Build up the Command Line for DosExecPgm |
michael@0 | 373 | */ |
michael@0 | 374 | pszCmdLine = PR_MALLOC(strlen(pszEXEName) + |
michael@0 | 375 | strlen(startData.PgmInputs) + 3); |
michael@0 | 376 | sprintf(pszCmdLine, "%s%c%s%c", pszEXEName, '\0', |
michael@0 | 377 | startData.PgmInputs, '\0'); |
michael@0 | 378 | rc = DosExecPgm(szFailed, |
michael@0 | 379 | CCHMAXPATH, |
michael@0 | 380 | EXEC_ASYNCRESULT, |
michael@0 | 381 | pszCmdLine, |
michael@0 | 382 | envBlock, |
michael@0 | 383 | &procInfo, |
michael@0 | 384 | pszEXEName); |
michael@0 | 385 | PR_DELETE(pszCmdLine); |
michael@0 | 386 | |
michael@0 | 387 | /* Restore our old values. Hope this works */ |
michael@0 | 388 | if (hStdInSave != -1) { |
michael@0 | 389 | DosDupHandle(hStdInSave, &hStdIn); |
michael@0 | 390 | DosClose(hStdInSave); |
michael@0 | 391 | } |
michael@0 | 392 | |
michael@0 | 393 | if (hStdOutSave != -1) { |
michael@0 | 394 | DosDupHandle(hStdOutSave, &hStdOut); |
michael@0 | 395 | DosClose(hStdOutSave); |
michael@0 | 396 | } |
michael@0 | 397 | |
michael@0 | 398 | if (hStdErrSave != -1) { |
michael@0 | 399 | DosDupHandle(hStdErrSave, &hStdErr); |
michael@0 | 400 | DosClose(hStdErrSave); |
michael@0 | 401 | } |
michael@0 | 402 | |
michael@0 | 403 | if (rc != NO_ERROR) { |
michael@0 | 404 | /* XXX what error code? */ |
michael@0 | 405 | PR_SetError(PR_UNKNOWN_ERROR, rc); |
michael@0 | 406 | goto errorExit; |
michael@0 | 407 | } |
michael@0 | 408 | |
michael@0 | 409 | proc->md.pid = procInfo.codeTerminate; |
michael@0 | 410 | } else { |
michael@0 | 411 | /* |
michael@0 | 412 | * If no STDIN/STDOUT redirection is not needed, use DosStartSession |
michael@0 | 413 | * to create a new, independent session |
michael@0 | 414 | */ |
michael@0 | 415 | rc = DosStartSession(&startData, &ulAppType, &pid); |
michael@0 | 416 | |
michael@0 | 417 | if ((rc != NO_ERROR) && (rc != ERROR_SMG_START_IN_BACKGROUND)) { |
michael@0 | 418 | PR_SetError(PR_UNKNOWN_ERROR, rc); |
michael@0 | 419 | goto errorExit; |
michael@0 | 420 | } |
michael@0 | 421 | |
michael@0 | 422 | proc->md.pid = pid; |
michael@0 | 423 | } |
michael@0 | 424 | |
michael@0 | 425 | if (pszFormatResult) { |
michael@0 | 426 | PR_DELETE(pszFormatResult); |
michael@0 | 427 | } |
michael@0 | 428 | |
michael@0 | 429 | PR_DELETE(cmdLine); |
michael@0 | 430 | if (newEnvp) { |
michael@0 | 431 | PR_DELETE(newEnvp); |
michael@0 | 432 | } |
michael@0 | 433 | if (envBlock) { |
michael@0 | 434 | PR_DELETE(envBlock); |
michael@0 | 435 | } |
michael@0 | 436 | return proc; |
michael@0 | 437 | |
michael@0 | 438 | errorExit: |
michael@0 | 439 | if (cmdLine) { |
michael@0 | 440 | PR_DELETE(cmdLine); |
michael@0 | 441 | } |
michael@0 | 442 | if (newEnvp) { |
michael@0 | 443 | PR_DELETE(newEnvp); |
michael@0 | 444 | } |
michael@0 | 445 | if (envBlock) { |
michael@0 | 446 | PR_DELETE(envBlock); |
michael@0 | 447 | } |
michael@0 | 448 | if (proc) { |
michael@0 | 449 | PR_DELETE(proc); |
michael@0 | 450 | } |
michael@0 | 451 | return NULL; |
michael@0 | 452 | } /* _PR_CreateOS2Process */ |
michael@0 | 453 | |
michael@0 | 454 | PRStatus _PR_DetachOS2Process(PRProcess *process) |
michael@0 | 455 | { |
michael@0 | 456 | /* On OS/2, a process is either created as a child or not. |
michael@0 | 457 | * You can't 'detach' it later on. |
michael@0 | 458 | */ |
michael@0 | 459 | PR_DELETE(process); |
michael@0 | 460 | return PR_SUCCESS; |
michael@0 | 461 | } |
michael@0 | 462 | |
michael@0 | 463 | /* |
michael@0 | 464 | * XXX: This will currently only work on a child process. |
michael@0 | 465 | */ |
michael@0 | 466 | PRStatus _PR_WaitOS2Process(PRProcess *process, |
michael@0 | 467 | PRInt32 *exitCode) |
michael@0 | 468 | { |
michael@0 | 469 | ULONG ulRetVal; |
michael@0 | 470 | RESULTCODES results; |
michael@0 | 471 | PID pidEnded = 0; |
michael@0 | 472 | |
michael@0 | 473 | ulRetVal = DosWaitChild(DCWA_PROCESS, DCWW_WAIT, |
michael@0 | 474 | &results, |
michael@0 | 475 | &pidEnded, process->md.pid); |
michael@0 | 476 | |
michael@0 | 477 | if (ulRetVal != NO_ERROR) { |
michael@0 | 478 | printf("\nDosWaitChild rc = %lu\n", ulRetVal); |
michael@0 | 479 | PR_SetError(PR_UNKNOWN_ERROR, ulRetVal); |
michael@0 | 480 | return PR_FAILURE; |
michael@0 | 481 | } |
michael@0 | 482 | PR_DELETE(process); |
michael@0 | 483 | return PR_SUCCESS; |
michael@0 | 484 | } |
michael@0 | 485 | |
michael@0 | 486 | PRStatus _PR_KillOS2Process(PRProcess *process) |
michael@0 | 487 | { |
michael@0 | 488 | ULONG ulRetVal; |
michael@0 | 489 | if ((ulRetVal = DosKillProcess(DKP_PROCESS, process->md.pid)) == NO_ERROR) { |
michael@0 | 490 | return PR_SUCCESS; |
michael@0 | 491 | } |
michael@0 | 492 | PR_SetError(PR_UNKNOWN_ERROR, ulRetVal); |
michael@0 | 493 | return PR_FAILURE; |
michael@0 | 494 | } |
michael@0 | 495 | |
michael@0 | 496 | PRStatus _MD_OS2GetHostName(char *name, PRUint32 namelen) |
michael@0 | 497 | { |
michael@0 | 498 | PRIntn rv; |
michael@0 | 499 | |
michael@0 | 500 | rv = gethostname(name, (PRInt32) namelen); |
michael@0 | 501 | if (0 == rv) { |
michael@0 | 502 | return PR_SUCCESS; |
michael@0 | 503 | } |
michael@0 | 504 | _PR_MD_MAP_GETHOSTNAME_ERROR(sock_errno()); |
michael@0 | 505 | return PR_FAILURE; |
michael@0 | 506 | } |
michael@0 | 507 | |
michael@0 | 508 | void |
michael@0 | 509 | _PR_MD_WAKEUP_CPUS( void ) |
michael@0 | 510 | { |
michael@0 | 511 | return; |
michael@0 | 512 | } |
michael@0 | 513 | |
michael@0 | 514 | /* |
michael@0 | 515 | ********************************************************************** |
michael@0 | 516 | * |
michael@0 | 517 | * Memory-mapped files |
michael@0 | 518 | * |
michael@0 | 519 | * A credible emulation of memory-mapped i/o on OS/2 would require |
michael@0 | 520 | * an exception-handler on each thread that might access the mapped |
michael@0 | 521 | * memory. In the Mozilla environment, that would be impractical. |
michael@0 | 522 | * Instead, the following simulates those modes which don't modify |
michael@0 | 523 | * the mapped file. It reads the entire mapped file segment at once |
michael@0 | 524 | * when MemMap is called, and frees it on MemUnmap. CreateFileMap |
michael@0 | 525 | * only does sanity-checks, while CloseFileMap does almost nothing. |
michael@0 | 526 | * |
michael@0 | 527 | ********************************************************************** |
michael@0 | 528 | */ |
michael@0 | 529 | |
michael@0 | 530 | PRStatus _MD_CreateFileMap(PRFileMap *fmap, PRInt64 size) |
michael@0 | 531 | { |
michael@0 | 532 | PRFileInfo64 info; |
michael@0 | 533 | |
michael@0 | 534 | /* assert on PR_PROT_READWRITE which modifies the underlying file */ |
michael@0 | 535 | PR_ASSERT(fmap->prot == PR_PROT_READONLY || |
michael@0 | 536 | fmap->prot == PR_PROT_WRITECOPY); |
michael@0 | 537 | if (fmap->prot != PR_PROT_READONLY && |
michael@0 | 538 | fmap->prot != PR_PROT_WRITECOPY) { |
michael@0 | 539 | PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0); |
michael@0 | 540 | return PR_FAILURE; |
michael@0 | 541 | } |
michael@0 | 542 | if (PR_GetOpenFileInfo64(fmap->fd, &info) == PR_FAILURE) { |
michael@0 | 543 | return PR_FAILURE; |
michael@0 | 544 | } |
michael@0 | 545 | /* reject zero-byte mappings & zero-byte files */ |
michael@0 | 546 | if (!size || !info.size) { |
michael@0 | 547 | PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
michael@0 | 548 | return PR_FAILURE; |
michael@0 | 549 | } |
michael@0 | 550 | /* file size rounded up to the next page boundary */ |
michael@0 | 551 | fmap->md.maxExtent = (info.size + 0xfff) & ~(0xfff); |
michael@0 | 552 | |
michael@0 | 553 | return PR_SUCCESS; |
michael@0 | 554 | } |
michael@0 | 555 | |
michael@0 | 556 | PRInt32 _MD_GetMemMapAlignment(void) |
michael@0 | 557 | { |
michael@0 | 558 | /* OS/2 pages are 4k */ |
michael@0 | 559 | return 0x1000; |
michael@0 | 560 | } |
michael@0 | 561 | |
michael@0 | 562 | void * _MD_MemMap(PRFileMap *fmap, PROffset64 offset, PRUint32 len) |
michael@0 | 563 | { |
michael@0 | 564 | PRUint32 rv; |
michael@0 | 565 | void *addr; |
michael@0 | 566 | |
michael@0 | 567 | /* prevent mappings beyond EOF + remainder of page */ |
michael@0 | 568 | if (offset + len > fmap->md.maxExtent) { |
michael@0 | 569 | PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0); |
michael@0 | 570 | return NULL; |
michael@0 | 571 | } |
michael@0 | 572 | if (PR_Seek64(fmap->fd, offset, PR_SEEK_SET) == -1) { |
michael@0 | 573 | return NULL; |
michael@0 | 574 | } |
michael@0 | 575 | /* try for high memory, fall back to low memory if hi-mem fails */ |
michael@0 | 576 | rv = DosAllocMem(&addr, len, OBJ_ANY | PAG_COMMIT | PAG_READ | PAG_WRITE); |
michael@0 | 577 | if (rv) { |
michael@0 | 578 | rv = DosAllocMem(&addr, len, PAG_COMMIT | PAG_READ | PAG_WRITE); |
michael@0 | 579 | if (rv) { |
michael@0 | 580 | PR_SetError(PR_OUT_OF_MEMORY_ERROR, rv); |
michael@0 | 581 | return NULL; |
michael@0 | 582 | } |
michael@0 | 583 | } |
michael@0 | 584 | if (PR_Read(fmap->fd, addr, len) == -1) { |
michael@0 | 585 | DosFreeMem(addr); |
michael@0 | 586 | return NULL; |
michael@0 | 587 | } |
michael@0 | 588 | /* don't permit writes if readonly */ |
michael@0 | 589 | if (fmap->prot == PR_PROT_READONLY) { |
michael@0 | 590 | rv = DosSetMem(addr, len, PAG_READ); |
michael@0 | 591 | if (rv) { |
michael@0 | 592 | DosFreeMem(addr); |
michael@0 | 593 | PR_SetError(PR_UNKNOWN_ERROR, rv); |
michael@0 | 594 | return NULL; |
michael@0 | 595 | } |
michael@0 | 596 | } |
michael@0 | 597 | return addr; |
michael@0 | 598 | } |
michael@0 | 599 | |
michael@0 | 600 | PRStatus _MD_MemUnmap(void *addr, PRUint32 len) |
michael@0 | 601 | { |
michael@0 | 602 | PRUint32 rv; |
michael@0 | 603 | |
michael@0 | 604 | /* we just have to trust that addr & len are those used by MemMap */ |
michael@0 | 605 | rv = DosFreeMem(addr); |
michael@0 | 606 | if (rv) { |
michael@0 | 607 | PR_SetError(PR_INVALID_ARGUMENT_ERROR, rv); |
michael@0 | 608 | return PR_FAILURE; |
michael@0 | 609 | } |
michael@0 | 610 | return PR_SUCCESS; |
michael@0 | 611 | } |
michael@0 | 612 | |
michael@0 | 613 | PRStatus _MD_CloseFileMap(PRFileMap *fmap) |
michael@0 | 614 | { |
michael@0 | 615 | /* nothing to do except free the PRFileMap struct */ |
michael@0 | 616 | PR_Free(fmap); |
michael@0 | 617 | return PR_SUCCESS; |
michael@0 | 618 | } |
michael@0 | 619 |