Time-Piece
view release on metacpan or search on metacpan
* separate working directory for each Perl interpreter, so that calling
* chdir() will not affect other interpreters.)
*
* (b) Only the first Perl interpreter instantiated within a process will
* "write through" environment changes to the process environment.
*
* (c) Even the primary Perl interpreter won't update the CRT copy of the
* the environment, only the Win32API copy (it calls win32_putenv()).
*
* As with CPerlHost::Getenv() and CPerlHost::Putenv() themselves, it makes
* sense to only update the process environment when inside the main
* interpreter, but we don't have access to CPerlHost's m_bTopLevel member
* from here so we'll just have to check PL_curinterp instead.
*
* Therefore, we can simply #undef getenv() and putenv() so that those names
* always refer to the CRT functions, and explicitly call win32_getenv() to
* access perl's %ENV.
*
* We also #undef malloc() and free() to be sure we are using the CRT
* functions otherwise under PERL_IMPLICIT_SYS they are redefined to calls
* into VMem::Malloc() and VMem::Free() and all allocations will be freed
* when the Perl interpreter is being destroyed so we'd end up with a pointer
* into deallocated memory in environ[] if a program embedding a Perl
* interpreter continues to operate even after the main Perl interpreter has
* been destroyed.
*
* Note that we don't free() the malloc()ed memory unless and until we call
* malloc() again ourselves because the CRT putenv() function simply puts its
* pointer argument into the environ[] array (it doesn't make a copy of it)
* so this memory must otherwise be leaked.
*/
#undef getenv
#undef putenv
# ifdef UNDER_CE
# define getenv xcegetenv
# define putenv xceputenv
# endif
#undef malloc
#undef free
static void
fix_win32_tzenv(void)
{
static char* oldenv = NULL;
char* newenv;
const char* perl_tz_env = win32_getenv("TZ");
const char* crt_tz_env = getenv("TZ");
if (perl_tz_env == NULL)
perl_tz_env = "";
if (crt_tz_env == NULL)
crt_tz_env = "";
if (strcmp(perl_tz_env, crt_tz_env) != 0) {
STRLEN perl_tz_env_len = strlen(perl_tz_env);
newenv = (char*)malloc(perl_tz_env_len + 4);
if (newenv != NULL) {
/* putenv with old MS CRTs will cause a double free internally if you delete
an env var with the CRT env that doesn't exist in Win32 env (perl %ENV only
modifies the Win32 env, not CRT env), so always create the env var in Win32
env before deleting it with CRT env api, so the error branch never executes
in __crtsetenv after SetEnvironmentVariableA executes inside __crtsetenv.
VC 9/2008 and up dont have this bug, older VC (msvcrt80.dll and older) and
mingw (msvcrt.dll) have it see [perl #125529]
*/
#if !(_MSC_VER >= 1500)
if(!perl_tz_env_len)
SetEnvironmentVariableA("TZ", "");
#endif
sprintf(newenv, "TZ=%s", perl_tz_env);
putenv(newenv);
if (oldenv != NULL)
free(oldenv);
oldenv = newenv;
}
}
}
#endif
/*
* my_tzset - wrapper to tzset() with a fix to make it work (better) on Win32.
* This code is duplicated in the POSIX module, so any changes made here
* should be made there too.
*/
static void
my_tzset(pTHX)
{
#ifdef WIN32
#if defined(USE_ITHREADS) && defined(PERL_IMPLICIT_SYS)
if (PL_curinterp == aTHX)
#endif
fix_win32_tzenv();
#endif
tzset();
}
/*
* my_mini_mktime - normalise struct tm values without the localtime()
* semantics (and overhead) of mktime(). Stolen shamelessly from Perl's
* Perl_mini_mktime() in util.c - for details on the algorithm, see that
* file.
*/
static void
my_mini_mktime(struct tm *ptm)
{
int yearday;
int secs;
int month, mday, year, jday;
int odd_cent, odd_year;
year = 1900 + ptm->tm_year;
month = ptm->tm_mon;
mday = ptm->tm_mday;
/* allow given yday with no month & mday to dominate the result */
if (ptm->tm_yday >= 0 && mday <= 0 && month <= 0) {
month = 0;
mday = 0;
jday = 1 + ptm->tm_yday;
}
else {
( run in 0.734 second using v1.01-cache-2.11-cpan-59e3e3084b8 )