2021-01-12 22:02:29 +00:00
|
|
|
/*-
|
2021-01-12 22:16:18 +00:00
|
|
|
* Copyright (c) 2017-2021 Carsten Sonne Larsen <cs@innolan.net>
|
2021-01-12 22:02:29 +00:00
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "notify.h"
|
|
|
|
#include "global.h"
|
|
|
|
#include "message.h"
|
2021-01-31 19:10:59 +00:00
|
|
|
#include "setting.h"
|
|
|
|
#include "conv.h"
|
|
|
|
#include "text.h"
|
2021-01-12 22:02:29 +00:00
|
|
|
#include "ptz.h"
|
|
|
|
#include "timer.h"
|
|
|
|
#include "mem.h"
|
|
|
|
#include "tz.h"
|
|
|
|
|
|
|
|
#include <assert.h>
|
2021-01-31 19:10:59 +00:00
|
|
|
#include <utility/date.h>
|
2021-01-12 22:02:29 +00:00
|
|
|
|
|
|
|
#include "logmod.h"
|
|
|
|
#define MODULENAME "Timezone"
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
#define EnvTZTimezone 1
|
|
|
|
#define EnvTZOneTimezone 2
|
|
|
|
#define SetTZEnvTimezone 3
|
|
|
|
#define SetTZValTimezone 4
|
|
|
|
#define PrefsTimezone 5
|
|
|
|
|
|
|
|
#define TIMEZONE_STD 1
|
|
|
|
#define TIMEZONE_DST 2
|
|
|
|
|
|
|
|
#define ENV_TZ "TZ"
|
|
|
|
#define ENV_TZONE "TZONE"
|
|
|
|
#define ENV_TZ_FILE "ENV:TZ"
|
|
|
|
#define ENV_TZONE_FILE "ENV:TZONE"
|
|
|
|
#define ENV_PREFS_FILE "ENV:Sys/locale.prefs"
|
|
|
|
|
2021-01-12 22:02:29 +00:00
|
|
|
/*
|
|
|
|
* 2922 is the number of days between 1.1.1970 and 1.1.1978
|
|
|
|
* (2 leap years and 6 normal)
|
|
|
|
* 2922 * 24 * 60 * 60 = 252460800
|
|
|
|
*/
|
|
|
|
#define AMIGA_OFFSET 252460800
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static volatile bool TimezoneCheckerRunning = false;
|
|
|
|
static volatile bool TimezoneCheckerRestart = false;
|
|
|
|
static volatile bool TimezoneCheckerShutdown = false;
|
|
|
|
static volatile long TimezoneSource = 0;
|
|
|
|
static volatile long unixEpochOffset = 0;
|
|
|
|
|
|
|
|
static void StartTimezoneCheck(void);
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static void BuildTimezone(struct PosixLocalTimezone *timezone, int offset, bool std)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
long sign = (offset < 0 ? -1 : +1);
|
|
|
|
long offsetPositive = (offset < 0 ? -offset : offset);
|
|
|
|
long hoursOffset = (offsetPositive / 60L);
|
|
|
|
long minutsOffset = (offsetPositive % 60L);
|
|
|
|
|
|
|
|
if (Settings->TimeZoneName != NULL && *Settings->TimeZoneName != '\0' &&
|
|
|
|
((Settings->TimeZoneDst <= 0 && std) || (Settings->TimeZoneDst == 1 && !std)))
|
|
|
|
SNPrintf(timezone->abbreviation, MAX_ABBR - 1, "%s", Settings->TimeZoneName);
|
|
|
|
else if (minutsOffset == 0)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
SNPrintf(timezone->abbreviation, MAX_ABBR - 1, "GMT%s%ld",
|
|
|
|
(sign <= 0 ? "+" : "-"), hoursOffset);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SNPrintf(timezone->abbreviation, MAX_ABBR - 1, "GMT%s%ld:%02ld",
|
|
|
|
(sign <= 0 ? "+" : "-"), hoursOffset, minutsOffset);
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
timezone->offset.hours = hoursOffset;
|
|
|
|
timezone->offset.minutes = minutsOffset;
|
|
|
|
timezone->offset.seconds = 0;
|
|
|
|
timezone->offset.sign = -sign;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void FindCurrentTimezone(struct PosixTimezone *timezone, long opt)
|
|
|
|
{
|
|
|
|
if (opt == TIMEZONE_STD)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
StrCopy(timezone->current.abbreviation, timezone->std.abbreviation);
|
|
|
|
timezone->current.offset = timezone->std.offset;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
else if (opt == TIMEZONE_DST)
|
|
|
|
{
|
|
|
|
StrCopy(timezone->current.abbreviation, timezone->dst.abbreviation);
|
|
|
|
timezone->current.offset = timezone->dst.offset;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void SetCurrentTimezone(struct PosixTimezone *timezone)
|
|
|
|
{
|
|
|
|
if (Settings->TimeZoneDst == 0)
|
|
|
|
FindCurrentTimezone(timezone, TIMEZONE_STD);
|
|
|
|
else if (Settings->TimeZoneDst == 1)
|
|
|
|
FindCurrentTimezone(timezone, TIMEZONE_DST);
|
|
|
|
else if (timezone->source == PosixTypeTimezone &&
|
|
|
|
timezone->dst.abbreviation == NULL)
|
|
|
|
FindCurrentTimezone(timezone, TIMEZONE_DST);
|
2021-01-12 22:02:29 +00:00
|
|
|
else
|
2021-01-31 19:10:59 +00:00
|
|
|
FindCurrentTimezone(timezone, TIMEZONE_STD);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PosixTimezone *BuildAmigaTimezone(struct Locale *locale)
|
|
|
|
{
|
|
|
|
struct PosixTimezone *tz = AllocStructSafe(struct PosixTimezone);
|
|
|
|
tz->source = CustomTypeTimezone;
|
|
|
|
long offset = (locale != NULL ? locale->loc_GMTOffset : 0);
|
|
|
|
BuildTimezone(&tz->std, offset, true);
|
|
|
|
BuildTimezone(&tz->dst, offset - 60, false);
|
|
|
|
SetCurrentTimezone(tz);
|
|
|
|
return tz;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct PosixTimezone *BuildSettingsTimezone(void)
|
|
|
|
{
|
|
|
|
struct PosixTimezone *tz = AllocStructSafe(struct PosixTimezone);
|
|
|
|
tz->source = CustomTypeTimezone;
|
|
|
|
long value = Settings->TimeZoneValue;
|
|
|
|
long hours = (value != TZVALUE_DEF ? (value / -100) : 0);
|
|
|
|
long minutes = (value != TZVALUE_DEF ? (value % -100) : 0);
|
|
|
|
long offset = hours * 60 + minutes;
|
|
|
|
BuildTimezone(&tz->std, offset, true);
|
|
|
|
BuildTimezone(&tz->dst, offset - 60, false);
|
|
|
|
SetCurrentTimezone(tz);
|
|
|
|
return tz;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ShowTimezones(void)
|
|
|
|
{
|
|
|
|
char timezone[TIMEZONE_TEXT_LEN];
|
|
|
|
GetTimezoneText(timezone, TZD_STD);
|
|
|
|
LogInfo(timezoneStd, timezone);
|
|
|
|
GetTimezoneText(timezone, TZD_DST);
|
|
|
|
LogInfo(timezoneDst, timezone);
|
|
|
|
GetTimezoneText(timezone, TZD_OFFSET_IN_PARENS);
|
|
|
|
LogNotice(timezoneCur, timezone);
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *GetVariable(const char *variable)
|
|
|
|
{
|
|
|
|
unsigned long memsize = 256;
|
|
|
|
STRPTR var = (STRPTR)variable;
|
|
|
|
|
|
|
|
STRPTR buf = (STRPTR)AllocStringSafe(memsize);
|
|
|
|
if (!buf)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
return NULL;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
|
|
|
|
if (GetVar(var, buf, memsize - 1, GVF_GLOBAL_ONLY) > 0)
|
|
|
|
{
|
|
|
|
return (char *)buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
FreeMemSafe(buf);
|
|
|
|
return NULL;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static struct PosixTimezone *ParseSettingsTZ()
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
struct PosixTimezone *timezone = NULL;
|
|
|
|
if (Settings->TZ != NULL && *Settings->TZ != '\0')
|
|
|
|
{
|
|
|
|
timezone = InitPosixTimezone(Settings->TZ);
|
|
|
|
if (timezone != NULL)
|
|
|
|
LogInfo(tzSettingValid, tzFromSet, SettingKeys->TZ);
|
|
|
|
else
|
|
|
|
LogInfo(tzSettingInvalid, tzFromSet, SettingKeys->TZ);
|
|
|
|
LogDebug(settingValueString, SettingKeys->TZ, Settings->TZ);
|
|
|
|
}
|
|
|
|
return timezone;
|
|
|
|
}
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static struct PosixTimezone *ParseEnvTZ(const char *tz)
|
|
|
|
{
|
|
|
|
struct PosixTimezone *timezone = NULL;
|
|
|
|
char *var = GetVariable(tz);
|
|
|
|
|
|
|
|
if (var != NULL)
|
|
|
|
{
|
|
|
|
timezone = InitPosixTimezone(var);
|
|
|
|
if (timezone != NULL)
|
|
|
|
LogInfo(tzSettingValid, tzFromEnv, tz);
|
|
|
|
else
|
|
|
|
LogInfo(tzSettingInvalid, tzFromEnv, tz);
|
|
|
|
LogDebug(settingValueString, tz, var);
|
|
|
|
FreeMemSafe(var);
|
|
|
|
}
|
|
|
|
return timezone;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void ShowTimezoneSource(void)
|
|
|
|
{
|
|
|
|
switch (TimezoneSource)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
case SetTZValTimezone:
|
|
|
|
LogNotice(applyTimeZone, tzFromSet, SettingKeys->TimeZoneValue);
|
2021-01-12 22:02:29 +00:00
|
|
|
break;
|
2021-01-31 19:10:59 +00:00
|
|
|
case SetTZEnvTimezone:
|
|
|
|
LogNotice(applyTimeZone, tzFromSet, SettingKeys->TZ);
|
2021-01-12 22:02:29 +00:00
|
|
|
break;
|
2021-01-31 19:10:59 +00:00
|
|
|
case EnvTZTimezone:
|
|
|
|
LogNotice(applyTimeZone, tzFromEnv, ENV_TZ);
|
2021-01-12 22:02:29 +00:00
|
|
|
break;
|
2021-01-31 19:10:59 +00:00
|
|
|
case EnvTZOneTimezone:
|
|
|
|
LogNotice(applyTimeZone, tzFromEnv, ENV_TZONE);
|
2021-01-12 22:02:29 +00:00
|
|
|
break;
|
2021-01-31 19:10:59 +00:00
|
|
|
case PrefsTimezone:
|
|
|
|
LogNotice(applyTimeZone, tzWorkbench, tzPreferences);
|
2021-01-12 22:02:29 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
}
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static void ShowNextTransition(void)
|
|
|
|
{
|
|
|
|
if (NextTransition != NULL)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
char *nextTime = GetTimeText((ULONG)NextTransition->time);
|
|
|
|
const char *nextTrans = NextTransition->isdst ? tzDstAbbr : tzStdAbbr;
|
|
|
|
LogWarn(tzChange, nextTrans, nextTime);
|
|
|
|
FreeMemSafe(nextTime);
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
void InitTimezone(void)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
CleanupNotifications();
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
struct Locale *locale = OpenLocale(NULL);
|
|
|
|
struct PosixTimezone *set1Timezone = ParseSettingsTZ();
|
|
|
|
struct PosixTimezone *set2Timezone = BuildSettingsTimezone();
|
|
|
|
struct PosixTimezone *env1Timezone = ParseEnvTZ(ENV_TZ);
|
|
|
|
struct PosixTimezone *env2Timezone = ParseEnvTZ(ENV_TZONE);
|
|
|
|
struct PosixTimezone *prefTimezone = BuildAmigaTimezone(locale);
|
|
|
|
CloseLocale(locale);
|
2021-01-12 22:02:29 +00:00
|
|
|
|
|
|
|
struct timeval tv;
|
2021-01-31 19:10:59 +00:00
|
|
|
GetSysTime(&tv);
|
|
|
|
SetPosixTimezone(set1Timezone, &tv);
|
|
|
|
SetPosixTimezone(env1Timezone, &tv);
|
|
|
|
SetPosixTimezone(env2Timezone, &tv);
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
long source = 0;
|
|
|
|
struct PosixTimezone *timezone = NULL;
|
|
|
|
if (Settings->TimeZoneValue != TZVALUE_DEF)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
source = SetTZValTimezone;
|
|
|
|
timezone = set2Timezone;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
else if (set1Timezone != NULL)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
source = SetTZEnvTimezone;
|
|
|
|
timezone = set1Timezone;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
else if (env1Timezone != NULL)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
source = EnvTZTimezone;
|
|
|
|
timezone = env1Timezone;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-31 19:10:59 +00:00
|
|
|
else if (env2Timezone != NULL)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
source = EnvTZOneTimezone;
|
|
|
|
timezone = env2Timezone;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
source = PrefsTimezone;
|
|
|
|
timezone = prefTimezone;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
struct PosixTimezone *activeTimezone = AllocStructSafe(struct PosixTimezone);
|
|
|
|
CopyMem(timezone, activeTimezone, sizeof(struct PosixTimezone));
|
|
|
|
FreePosixTimezone(set1Timezone);
|
|
|
|
FreePosixTimezone(set2Timezone);
|
|
|
|
FreePosixTimezone(env1Timezone);
|
|
|
|
FreePosixTimezone(env2Timezone);
|
|
|
|
FreePosixTimezone(prefTimezone);
|
|
|
|
|
|
|
|
struct PosixTransitionTime *activeTransition = FindNextTransition(activeTimezone, &tv);
|
|
|
|
long offset = (activeTimezone->current.offset.sign < 0 ? +1 : -1) *
|
|
|
|
(activeTimezone->current.offset.hours * 60 * 60 +
|
|
|
|
activeTimezone->current.offset.minutes * 60 +
|
|
|
|
activeTimezone->current.offset.seconds);
|
|
|
|
offset += AMIGA_OFFSET;
|
|
|
|
|
|
|
|
// Switch global time zone variables
|
|
|
|
Forbid();
|
|
|
|
struct PosixTimezone *lastTimezone = Timezone;
|
|
|
|
Timezone = activeTimezone;
|
|
|
|
TimezoneSource = source;
|
|
|
|
NextTransition = activeTransition;
|
|
|
|
unixEpochOffset = offset;
|
|
|
|
Permit();
|
|
|
|
|
|
|
|
switch (source)
|
|
|
|
{
|
|
|
|
case EnvTZTimezone:
|
|
|
|
WatchFile(ENV_TZ_FILE, ATK_TZ_CHANGED);
|
|
|
|
break;
|
|
|
|
case EnvTZOneTimezone:
|
|
|
|
WatchFile(ENV_TZONE_FILE, ATK_TZONE_CHANGED);
|
|
|
|
break;
|
|
|
|
case PrefsTimezone:
|
|
|
|
WatchFile(ENV_PREFS_FILE, ATK_LOCALE_CHANGED);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
ShowTimezoneSource();
|
|
|
|
ShowTimezones();
|
|
|
|
ShowNextTransition();
|
|
|
|
StartTimezoneCheck();
|
|
|
|
FreePosixTimezone(lastTimezone);
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
void Unix2Amiga(struct timeval *utc, struct timeval *tv)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
assert(utc != NULL);
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
|
|
|
tv->tv_secs = utc->tv_secs - AMIGA_OFFSET;
|
|
|
|
tv->tv_micro = utc->tv_micro;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
void UnixUtc2AmigaLocal(struct timeval *utc, struct timeval *tv)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
|
|
|
assert(utc != NULL);
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
2021-01-12 22:16:18 +00:00
|
|
|
tv->tv_secs = utc->tv_secs - unixEpochOffset;
|
2021-01-12 22:02:29 +00:00
|
|
|
tv->tv_micro = utc->tv_micro;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetTimeOfDay(struct timeval *tv)
|
|
|
|
{
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
|
|
|
GetSysTime(tv);
|
|
|
|
tv->tv_secs = tv->tv_secs + unixEpochOffset;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GetLocalTimeOfDay(struct timeval *tv)
|
|
|
|
{
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
|
|
|
GetSysTime(tv);
|
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
long GetUtcOffsetValue(void)
|
|
|
|
{
|
|
|
|
return (unixEpochOffset - AMIGA_OFFSET);
|
|
|
|
}
|
|
|
|
|
2021-01-12 22:02:29 +00:00
|
|
|
void SetTimeOfDay(const struct TimerInfo *info, const struct timeval *tv)
|
|
|
|
{
|
|
|
|
struct timeval t;
|
|
|
|
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
|
|
|
t.tv_secs = tv->tv_secs - unixEpochOffset;
|
|
|
|
t.tv_micro = tv->tv_micro;
|
|
|
|
SetTime(&t);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SaveTimeOfDay(const struct timeval *tv)
|
|
|
|
{
|
|
|
|
assert(tv != NULL);
|
|
|
|
|
|
|
|
WriteBattClock((long)tv->tv_secs - unixEpochOffset);
|
|
|
|
}
|
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static long GetNextTransition(void)
|
2021-01-12 22:02:29 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
time_t next = (NextTransition != NULL ? NextTransition->time : 2147483647);
|
|
|
|
return (long)next;
|
|
|
|
}
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static long GetNextTransitionCheck(long now)
|
|
|
|
{
|
|
|
|
long diff = GetNextTransition() - now;
|
|
|
|
diff = (diff > 60 ? 60 : diff);
|
|
|
|
return diff;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void CheckTransition(void)
|
|
|
|
{
|
|
|
|
TimezoneCheckerShutdown = false;
|
|
|
|
TimezoneCheckerRestart = false;
|
|
|
|
|
|
|
|
if (NextTransition == NULL)
|
|
|
|
{
|
|
|
|
LogNotice(timezoneNoTrans);
|
|
|
|
LogInfo(Text2P, tzChecker, TextStopped);
|
|
|
|
TimezoneCheckerRunning = false;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
LogInfo(Text2P, tzChecker, TextStarted);
|
|
|
|
|
|
|
|
struct timeval tv;
|
|
|
|
GetSysTime(&tv);
|
|
|
|
ULONG next, now = (ULONG)(tv.tv_secs);
|
|
|
|
long diff = GetNextTransitionCheck(now);
|
|
|
|
|
|
|
|
while (!TimezoneCheckerShutdown)
|
|
|
|
{
|
|
|
|
if (diff < 0)
|
|
|
|
{
|
|
|
|
LogTrace(tzCheck);
|
|
|
|
GetSysTime(&tv);
|
|
|
|
now = (ULONG)(tv.tv_secs);
|
|
|
|
next = GetNextTransition();
|
|
|
|
|
|
|
|
if (now > next)
|
|
|
|
{
|
|
|
|
ShowTimezones();
|
|
|
|
LogNotice(tzTrans);
|
|
|
|
|
|
|
|
Forbid();
|
|
|
|
SetPosixTimezone(Timezone, &tv);
|
|
|
|
NextTransition = FindNextTransition(Timezone, &tv);
|
|
|
|
Permit();
|
|
|
|
|
|
|
|
ShowTimezones();
|
|
|
|
SendWindowMessage(ATK_TZ_CHANGED);
|
|
|
|
}
|
|
|
|
|
|
|
|
diff = GetNextTransitionCheck(now);
|
|
|
|
}
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
diff--;
|
|
|
|
Delay(50);
|
2021-01-12 22:02:29 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
if (TimezoneCheckerRestart)
|
|
|
|
{
|
|
|
|
LogInfo(Text2P, TextRestarting, tzChecker);
|
|
|
|
TimezoneCheckerRestart = false;
|
|
|
|
diff = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
LogInfo(Text2P, tzChecker, TextStopped);
|
|
|
|
TimezoneCheckerRunning = false;
|
|
|
|
TimezoneCheckerShutdown = false;
|
2021-01-12 22:02:29 +00:00
|
|
|
}
|
2021-01-12 22:16:18 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
void StopTimezoneCheck(void)
|
2021-01-12 22:16:18 +00:00
|
|
|
{
|
2021-01-31 19:10:59 +00:00
|
|
|
TimezoneCheckerShutdown = true;
|
|
|
|
while (TimezoneCheckerRunning)
|
|
|
|
Delay(10);
|
|
|
|
}
|
2021-01-12 22:16:18 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
static void StartTimezoneCheck(void)
|
|
|
|
{
|
|
|
|
if (TimezoneCheckerRunning)
|
|
|
|
{
|
|
|
|
LogTrace(Text2P, tzChecker, TextAlreadyRunning);
|
|
|
|
TimezoneCheckerRestart = true;
|
|
|
|
return;
|
|
|
|
}
|
2021-01-12 22:16:18 +00:00
|
|
|
|
2021-01-31 19:10:59 +00:00
|
|
|
TimezoneCheckerRunning = true;
|
|
|
|
LogNotice(Text2P, TextStarting, tzChecker);
|
|
|
|
|
|
|
|
struct Task *task = (struct Task *)CreateNewProcTags(
|
|
|
|
NP_Entry, (IPTR)CheckTransition,
|
|
|
|
NP_StackSize, 32 * 1024,
|
|
|
|
NP_Name, 0,
|
|
|
|
NP_Input, 0,
|
|
|
|
NP_Output, 0,
|
|
|
|
NP_Error, 0,
|
|
|
|
NP_CloseInput, FALSE,
|
|
|
|
NP_CloseOutput, FALSE,
|
|
|
|
NP_CloseError, FALSE,
|
|
|
|
NP_WindowPtr, 0,
|
|
|
|
NP_ConsoleTask, 0,
|
|
|
|
NP_Cli, FALSE,
|
|
|
|
TAG_DONE);
|
|
|
|
|
|
|
|
if (task == NULL)
|
|
|
|
{
|
|
|
|
LogError(Text2P, TextNoStart, tzChecker);
|
|
|
|
TimezoneCheckerRunning = false;
|
|
|
|
}
|
2021-01-12 22:16:18 +00:00
|
|
|
}
|