📄 ntmisc.c
字号:
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- *//* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is the Netscape Portable Runtime (NSPR). * * The Initial Developer of the Original Code is Netscape * Communications Corporation. Portions created by Netscape are * Copyright (C) 1998-2000 Netscape Communications Corporation. All * Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable * instead of those above. If you wish to allow use of your * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL. If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * ntmisc.c * */#include "primpl.h"char *_PR_MD_GET_ENV(const char *name){ return getenv(name);}/*** _PR_MD_PUT_ENV() -- add or change environment variable*****/PRIntn _PR_MD_PUT_ENV(const char *name){ return(putenv(name));}/* ************************************************************************** ************************************************************************** ** ** Date and time routines ** ************************************************************************** ************************************************************************** */#include <sys/timeb.h>/* *----------------------------------------------------------------------- * * PR_Now -- * * Returns the current time in microseconds since the epoch. * The epoch is midnight January 1, 1970 GMT. * The implementation is machine dependent. This is the * implementation for Windows. * Cf. time_t time(time_t *tp) * *----------------------------------------------------------------------- */PR_IMPLEMENT(PRTime)PR_Now(void){ PRInt64 s, ms, ms2us, s2us; struct timeb b; ftime(&b); LL_I2L(ms2us, PR_USEC_PER_MSEC); LL_I2L(s2us, PR_USEC_PER_SEC); LL_I2L(s, b.time); LL_I2L(ms, b.millitm); LL_MUL(ms, ms, ms2us); LL_MUL(s, s, s2us); LL_ADD(s, s, ms); return s; }/* * The following code works around a bug in NT (Netscape Bugsplat * Defect ID 47942). * * In Windows NT 3.51 and 4.0, if the local time zone does not practice * daylight savings time, e.g., Arizona, Taiwan, and Japan, the global * variables that _ftime() and localtime() depend on have the wrong * default values: * _tzname[0] "PST" * _tzname[1] "PDT" * _daylight 1 * _timezone 28800 * * So at startup time, we need to invoke _PR_Win32InitTimeZone(), which * on NT sets these global variables to the correct values (obtained by * calling GetTimeZoneInformation(). */#include <time.h> /* for _tzname, _daylight, _timezone */void_PR_Win32InitTimeZone(void){ OSVERSIONINFO version; TIME_ZONE_INFORMATION tzinfo; version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); if (GetVersionEx(&version) != FALSE) { /* Only Windows NT needs this hack */ if (version.dwPlatformId != VER_PLATFORM_WIN32_NT) { return; } } if (GetTimeZoneInformation(&tzinfo) == 0xffffffff) { return; /* not much we can do if this failed */ } /* * I feel nervous about modifying these globals. I hope that no * other thread is reading or modifying these globals simultaneously * during nspr initialization. * * I am assuming that _tzname[0] and _tzname[1] point to static buffers * and that the buffers are at least 32 byte long. My experiments show * this is true, but of course this is undocumented. --wtc * * Convert time zone names from WCHAR to CHAR and copy them to * the static buffers pointed to by _tzname[0] and _tzname[1]. * Ignore conversion errors, because it is _timezone and _daylight * that _ftime() and localtime() really depend on. */ WideCharToMultiByte(CP_ACP, 0, tzinfo.StandardName, -1, _tzname[0], 32, NULL, NULL); WideCharToMultiByte(CP_ACP, 0, tzinfo.DaylightName, -1, _tzname[1], 32, NULL, NULL); /* _timezone is in seconds. tzinfo.Bias is in minutes. */ _timezone = tzinfo.Bias * 60; _daylight = tzinfo.DaylightBias ? 1 : 0; return;}/* *********************************************************************** *********************************************************************** * * Process creation routines * *********************************************************************** *********************************************************************** *//* * Assemble the command line by concatenating the argv array. * On success, this function returns 0 and the resulting command * line is returned in *cmdLine. On failure, it returns -1. */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, and * a null byte at the end of command line. */ cmdLineSize += 2 * strlen(*arg) /* \ and " need to be escaped */ + 2 /* we quote every argument */ + 1; /* space in between, or final null */ } p = *cmdLine = PR_MALLOC(cmdLineSize); if (p == NULL) { return -1; } for (arg = argv; *arg; arg++) { /* Add a space to separates the arguments */ if (arg != argv) { *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++; } } /* 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++ = '"'; } } *p = '\0'; return 0;}/* * Assemble the environment block by concatenating the envp array * (preserving the terminating null byte in each array element) * and adding a null byte at the end. * * Returns 0 on success. The resulting environment block is returned * in *envBlock. Note that if envp is NULL, a NULL pointer is returned * in *envBlock. Returns -1 on failure. */static int assembleEnvBlock(char **envp, char **envBlock){ char *p; char *q; char **env; char *curEnv; char *cwdStart, *cwdEnd; int envBlockSize; if (envp == NULL) { *envBlock = NULL; return 0; } curEnv = GetEnvironmentStrings(); cwdStart = curEnv; while (*cwdStart) { if (cwdStart[0] == '=' && cwdStart[1] != '\0' && cwdStart[2] == ':' && cwdStart[3] == '=') { break; } cwdStart += strlen(cwdStart) + 1; } cwdEnd = cwdStart; if (*cwdEnd) { cwdEnd += strlen(cwdEnd) + 1; while (*cwdEnd) { if (cwdEnd[0] != '=' || cwdEnd[1] == '\0' || cwdEnd[2] != ':' || cwdEnd[3] != '=') { break; } cwdEnd += strlen(cwdEnd) + 1; } } envBlockSize = cwdEnd - cwdStart; for (env = envp; *env; env++) { envBlockSize += strlen(*env) + 1; } envBlockSize++; p = *envBlock = PR_MALLOC(envBlockSize); if (p == NULL) { FreeEnvironmentStrings(curEnv); return -1; } q = cwdStart; while (q < cwdEnd) { *p++ = *q++; } FreeEnvironmentStrings(curEnv); for (env = envp; *env; env++) { q = *env; while (*q) { *p++ = *q++; } *p++ = '\0'; } *p = '\0'; return 0;}/* * For qsort. We sort (case-insensitive) the environment strings * before generating the environment block. */static int compare(const void *arg1, const void *arg2){ return _stricmp(* (char**)arg1, * (char**)arg2);}PRProcess * _PR_CreateWindowsProcess( const char *path, char *const *argv, char *const *envp, const PRProcessAttr *attr){ STARTUPINFO startupInfo; PROCESS_INFORMATION procInfo; BOOL retVal; char *cmdLine = NULL; char *envBlock = NULL; char **newEnvp = NULL; const char *cwd = NULL; /* current working directory */ PRProcess *proc = 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 attr->fdInheritBuffer is not NULL, we need to insert * it into the envp array, so envp cannot be NULL. */ if ((envp == NULL) && attr && attr->fdInheritBuffer) { envp = environ; } if (envp != NULL) { int idx; int numEnv; int newEnvpSize; numEnv = 0; while (envp[numEnv]) { numEnv++; } newEnvpSize = numEnv + 1; /* terminating null pointer */ if (attr && attr->fdInheritBuffer) { newEnvpSize++; } newEnvp = (char **) PR_MALLOC(newEnvpSize * sizeof(char *)); for (idx = 0; idx < numEnv; idx++) { newEnvp[idx] = envp[idx]; } if (attr && attr->fdInheritBuffer) { newEnvp[idx++] = attr->fdInheritBuffer; } newEnvp[idx] = NULL; qsort((void *) newEnvp, (size_t) (newEnvpSize - 1), sizeof(char *), compare); } if (assembleEnvBlock(newEnvp, &envBlock) == -1) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto errorExit; } ZeroMemory(&startupInfo, sizeof(startupInfo)); startupInfo.cb = sizeof(startupInfo); if (attr) { PRBool redirected = PR_FALSE; /* * XXX the default value for stdin, stdout, and stderr * should probably be the console input and output, not * those of the parent process. */ startupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); startupInfo.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); startupInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); if (attr->stdinFd) { startupInfo.hStdInput = (HANDLE) attr->stdinFd->secret->md.osfd; redirected = PR_TRUE; } if (attr->stdoutFd) { startupInfo.hStdOutput = (HANDLE) attr->stdoutFd->secret->md.osfd; redirected = PR_TRUE; } if (attr->stderrFd) { startupInfo.hStdError = (HANDLE) attr->stderrFd->secret->md.osfd; redirected = PR_TRUE; } if (redirected) { startupInfo.dwFlags |= STARTF_USESTDHANDLES; } cwd = attr->currentDirectory; } retVal = CreateProcess(NULL, cmdLine, NULL, /* security attributes for the new * process */ NULL, /* security attributes for the primary * thread in the new process */ TRUE, /* inherit handles */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -