Release 1.08
This commit is contained in:
parent
c5adeca556
commit
82fd462f87
|
@ -1,8 +1,15 @@
|
|||
AmiTimeKeeper Change Log
|
||||
|
||||
v1.08 18.05.2019
|
||||
- When using pool server cycle with prefix 0 to 3
|
||||
- Display of wrong signes in time zone fixed
|
||||
- Faulty log messages about settings fixed
|
||||
- Timer bug causing infitive loop fixed
|
||||
- Memory leak in settings window fixed
|
||||
|
||||
v1.07 15.02.2019
|
||||
- Support commodity hotkey and popup options
|
||||
- Hide advanced setting with new expert option
|
||||
- Hide advanced settings with new expert option
|
||||
|
||||
v1.06 08.02.2019
|
||||
- Adjust layout in settings window
|
||||
|
|
|
@ -42,17 +42,19 @@ string.o: compiler.h config.h string.h mem.h
|
|||
|
||||
time.o: compiler.h config.h time.h mem.h
|
||||
|
||||
val.o: compiler.h config.h state.h message.h log.h
|
||||
|
||||
win_main.o: compiler.h config.h message.h state.h time.h mem.h win.h
|
||||
|
||||
win_gad.o: compiler.h config.h message.h state.h time.h mem.h win.h
|
||||
|
||||
timekeeper: broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o
|
||||
timekeeper: broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o val.o win_main.o win_gad.o
|
||||
${CC} ${CFLAGS} ${LFLAGS} -s -o TimeKeeper \
|
||||
broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o win_main.o win_gad.o \
|
||||
broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o sntp.o state.o time.o string.o val.o win_main.o win_gad.o \
|
||||
${LDLIBS}
|
||||
|
||||
clean:
|
||||
rm -f TimeKeeper broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o settings.o sntp.o state.o time.o string.o win_main.o win_gad.o TimeKeeper.map
|
||||
rm -f TimeKeeper broker.o com.o library.o log.o main.o mem.o message.o net_getaddrinfo.o net_poll.o net.o settings.o sntp.o state.o time.o string.o val.o win_main.o win_gad.o TimeKeeper.map
|
||||
|
||||
depend:
|
||||
@echo Dependencies already done
|
||||
|
|
88
Manual
88
Manual
|
@ -1,5 +1,5 @@
|
|||
@database TimeKeeper.guide
|
||||
@$VER: TimeKeeper.guide 1.06 (2019-02-08)
|
||||
@$VER: TimeKeeper.guide 1.08 (2019-05-18)
|
||||
@(c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
|
||||
@author Carsten Sonne Larsen
|
||||
|
||||
|
@ -32,14 +32,17 @@
|
|||
@Next "Configuring the client"
|
||||
|
||||
AmiTimeKeeper is a small program which keeps the time right on your
|
||||
machine. No installation is required.
|
||||
machine. No installation is required. It is operated as a commodity
|
||||
and is controlled by AmigaOS. An AmiTCP compatible TCP/IP stack is
|
||||
required for AmiTimeKeeper to work.
|
||||
|
||||
AmiTimeKeeper is operated as a commodity and is controlled by AmigaOS.
|
||||
An AmiTCP compatible TCP/IP stack is required for AmiTimeKeeper to work.
|
||||
Several settings determine the behaviour. The settings are passed
|
||||
either directly from the command line or by using the tool types of
|
||||
an icon. Preferences can also be saved between reboots.
|
||||
|
||||
AmiTimeKeeper can be configured through several settings. This can be
|
||||
done either directly from the command line or by using the tooltypes
|
||||
of an icon. Preferences can also be saved between reboots.
|
||||
The local time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. in regular AmigaOS this is available through the
|
||||
Locale Preferences Editor.
|
||||
|
||||
@{"Configuring the client" Link "Configuring the client"}
|
||||
@{"Using tooltypes of an icon" Link "Using tooltypes of an icon"}
|
||||
|
@ -54,7 +57,7 @@ of an icon. Preferences can also be saved between reboots.
|
|||
@Toc "Main"
|
||||
@Prev "Main"
|
||||
@Next "Using tooltypes of an icon"
|
||||
@{b}Server Address@{ub}
|
||||
@{b}Server address@{ub}
|
||||
|
||||
NTP servers are managed by several organizations. The pool.ntp.org
|
||||
project and Network Time Foundation are probably the two most famous.
|
||||
|
@ -72,7 +75,10 @@ the address should be ch.pool.ntp.org.
|
|||
Network Time Foundation has a website on http://support.ntp.org/
|
||||
The pool.ntp.org project website is located at https://www.ntppool.org/
|
||||
|
||||
@{b}Server Port@{ub}
|
||||
Pool server addresses will automatically be prefixed with 0, 1, 2 or 3
|
||||
in order to lower the risk of choosing a none-responsive server.
|
||||
|
||||
@{b}Server port@{ub}
|
||||
|
||||
NTP servers use port 123 as default. Only under special circumstances
|
||||
are the NTP server port different from 123.
|
||||
|
@ -88,7 +94,7 @@ The requests are sent in certain intervals defined by the interval
|
|||
parameter. The interval should be specified using milliseconds. One
|
||||
thousand (1.000) milliseconds are equal to one second.
|
||||
|
||||
@{b}Threshold@{ub}
|
||||
@{b}Adjustment threshold@{ub}
|
||||
|
||||
Due to the accuracy of NTP servers and the nature of Amiga CPUs it does
|
||||
not make sense to adjust the Amiga clock on every response from the NTP
|
||||
|
@ -97,13 +103,20 @@ The amount of accepted inaccuracy is set using the threshold parameter.
|
|||
The threshold should be specified using microsecond. One million
|
||||
microseconds (1.000.000) are equal to one second.
|
||||
|
||||
@{b}Read Only@{ub}
|
||||
@{b}Read only@{ub}
|
||||
|
||||
It is possible to send request to the NTP server without setting the
|
||||
Amiga hardware clock. This option can be handy when debugging time zone
|
||||
setup and other time related parameters.
|
||||
|
||||
@{b}Connection Timeout@{ub}
|
||||
@{b}Expert mode@{ub}
|
||||
|
||||
Advanced settings are hidden from the settings windown when expert mode
|
||||
is not enabled. The advanced settings are server port, interval between
|
||||
requests, adjustment threshold, connection timeout, verbosity level and
|
||||
commodity priority.
|
||||
|
||||
@{b}Connection timeout@{ub}
|
||||
|
||||
In some cases, a connection to the NTP server cannot be established or
|
||||
the NTP server simply does respond. To avoid an infinitive wait for a
|
||||
|
@ -111,7 +124,7 @@ response the connection will instead make a time out. The timeout
|
|||
interval should be specified using milliseconds. One thousand (1.000)
|
||||
milliseconds are equal to one second.
|
||||
|
||||
@{b}Verbosity@{ub}
|
||||
@{b}Verbosity level@{ub}
|
||||
|
||||
The level of logging can be adjusted from none to all. Expressed as a
|
||||
numeric value verbose can be 0, 1, 2 or 3, where 0 is equal to none and
|
||||
|
@ -138,13 +151,16 @@ The available tooltypes are the same as the available command line
|
|||
parameters.
|
||||
|
||||
@{b}Parameter@{ub} | @{b}Short description@{ub}
|
||||
-----------------------------------------
|
||||
SERVER | Server Address
|
||||
PORT | Server Port
|
||||
-------------------------------------------------
|
||||
SERVER | NTP server Address
|
||||
PORT | NTP server Port
|
||||
THRESHOLD | Adjustment threshold
|
||||
INTERVAL | Interval between requests
|
||||
CX_POPUP | Show settings window on startup
|
||||
CX_POPKEY | Settings window keyboard shortcut
|
||||
CX_PRIORITY | Commodity priority
|
||||
READONLY | Read only option
|
||||
READONLY | Do not set clock
|
||||
EXPERT | Show advanced options
|
||||
TIMEOUT | Connection Timeout
|
||||
VERBOSE | Log verbosity
|
||||
LOGFILE | Log file location
|
||||
|
@ -153,11 +169,13 @@ LOGFILE | Log file location
|
|||
|
||||
Settings can be overridden and are set in the following order:
|
||||
1. Preference file
|
||||
2. Icon tooltypes
|
||||
3. CLI parameters
|
||||
2. Icon tooltypes / CLI parameters
|
||||
|
||||
CLI parameters has highest precedence and will always override settings
|
||||
from icon tooltypes and from the preference file.
|
||||
CLI parameters and icon tooltypes has highest precedence and will
|
||||
always override settings from the preference file.
|
||||
|
||||
Settings from icon tooltypes are used when starting from Workbench.
|
||||
Settings from CLI are used only when starting from shell.
|
||||
|
||||
@EndNode
|
||||
|
||||
|
@ -174,6 +192,8 @@ ENVARC:timekeeper.prefs
|
|||
|
||||
Depending on the setup the content of timekeeper.prefs could be:
|
||||
|
||||
CX_POPUP=NO
|
||||
CX_POPKEY=lshift control t
|
||||
CX_PRIORITY=25
|
||||
THRESHOLD=1000000
|
||||
SERVER=de.pool.ntp.org
|
||||
|
@ -181,7 +201,8 @@ PORT=123
|
|||
TIMEOUT=5000
|
||||
INTERVAL=17500
|
||||
VERBOSE=3
|
||||
READONLY=0
|
||||
READONLY=NO
|
||||
EXPERT=NO
|
||||
LOGFILE=RAM:log
|
||||
|
||||
The preference file should not be edited under normal circumstances.
|
||||
|
@ -189,7 +210,7 @@ The preference file should not be edited under normal circumstances.
|
|||
@{b}Caveats@{ub}
|
||||
|
||||
If LOGFILE is set in the preference file, no messages will be emitted
|
||||
to screen (unless overridden by CLI or Icon tooltype with LOGFILE=NO).
|
||||
to screen (unless overridden by CLI or icon tooltype with LOGFILE=NO).
|
||||
|
||||
@EndNode
|
||||
|
||||
|
@ -198,10 +219,29 @@ to screen (unless overridden by CLI or Icon tooltype with LOGFILE=NO).
|
|||
@Prev "Saving preferences"
|
||||
@Next "Software License"
|
||||
|
||||
Version 1.05, dated 06.08.2018, has proved itself to be a stable version
|
||||
and has been promoted to Long Term Support. It is distributed along with
|
||||
the latest version of AmiTimeKeeper.
|
||||
|
||||
A custom build version has been integrated into the Icaros Desktop system.
|
||||
The author encourages all developers with an interest to make their own
|
||||
build.
|
||||
|
||||
@{b}v1.08 18.05.2019@{ub}
|
||||
- When using pool server cycle with prefix 0 to 3
|
||||
- Display of wrong signes in time zone fixed
|
||||
- Faulty log messages about settings fixed
|
||||
- Timer bug causing infitive loop fixed
|
||||
- Memory leak in settings window fixed
|
||||
|
||||
@{b}v1.07 15.02.2019@{ub}
|
||||
- Support commodity hotkey and popup options
|
||||
- Hide advanced settings with new expert option
|
||||
|
||||
@{b}v1.06 08.02.2019@{ub}
|
||||
- Adjust layout in settings window
|
||||
|
||||
@{b}v1.05 06.08.2018@{ub}
|
||||
@{b}v1.05 06.08.2018 LTS@{ub}
|
||||
- Preferences can now be saved from settings window
|
||||
- Time zone is shown as UTC offset in settings window
|
||||
- Running multiple instances no longer create zombie processes
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
Short: Keep your time right
|
||||
Author: Carsten Larsen (carsten.larsen@mail.com)
|
||||
Uploader: Carsten Larsen (carsten.larsen@mail.com)
|
||||
Type: util/cdity
|
||||
Version: 1.08
|
||||
Architecture: m68k-amigaos
|
||||
|
||||
AmiTimeKeeper is a small program which keeps the time right on your
|
||||
machine. No installation is required. It is operated as a commodity
|
||||
and is controlled by AmigaOS. An AmiTCP compatible TCP/IP stack is
|
||||
required for AmiTimeKeeper to work.
|
||||
|
||||
Several settings determine the behaviour. The settings are passed
|
||||
either directly from the command line or by using the tool types of
|
||||
an icon. Preferences can also be saved between reboots.
|
||||
|
||||
The default server address is pool.ntp.org. To find another server
|
||||
try visiting support.ntp.org or one of the other sites listing time
|
||||
servers.
|
||||
|
||||
Version 1.05 has proved itself to be a stable version and has been
|
||||
promoted to Long Term Support. It is distributed along with the
|
||||
latest version.
|
||||
|
||||
A custom build version has been integrated into the Icaros Desktop
|
||||
system. The author encourages all developers with an interest to
|
||||
make their own build.
|
||||
|
||||
v1.08 18.05.2019
|
||||
- When using pool server cycle with prefix 0 to 3
|
||||
- Display of wrong signes in time zone fixed
|
||||
- Faulty log messages about settings fixed
|
||||
- Timer bug causing infitive loop fixed
|
||||
- Memory leak in settings window fixed
|
||||
|
||||
v1.07 15.02.2019
|
||||
- Support commodity hotkey and popup options
|
||||
- Hide advanced settings with new expert option
|
||||
|
||||
v1.06 08.02.2019
|
||||
- Adjust layout in settings window
|
||||
|
||||
v1.05 06.08.2018 LTS
|
||||
- Preferences can now be saved from settings window
|
||||
- Time zone is shown as UTC offset in settings window
|
||||
- Running multiple instances no longer creates zombie processes
|
||||
- Low water option renamed to threshold and high water option removed
|
||||
- New option for sending log messages to file instead of to screen
|
||||
- Some incorrect NTP log messages no longer appears
|
||||
- Read-only option is now applied consistently
|
||||
- Potential race condition in memory allocation fixed
|
||||
- Other minor enhancements
|
||||
|
||||
v1.04 15.12.2017
|
||||
- Default settings adjusted to comply better with AmigaOS
|
||||
- Bugs in threshold settings (high/low water) fixed
|
||||
- Bugs in opening and closing of libraries fixed
|
||||
- New and more accurate error and log messages
|
||||
|
||||
v1.03 09.12.2017
|
||||
- Settings window
|
||||
|
||||
v1.02 29.11.2017
|
||||
- AROS code compliance
|
||||
|
||||
v1.01 28.11.2017
|
||||
- Handle network disconnection
|
||||
- Fix infinity timeout problem
|
||||
- Support hardware clock
|
||||
- Improved error messages
|
||||
|
||||
v1.00 26.11.2017
|
||||
- First public release
|
3
broker.c
3
broker.c
|
@ -266,7 +266,6 @@ static void ProcessMsg(void)
|
|||
break;
|
||||
case CXCMD_KILL:
|
||||
LogInfo("Received shut down from commodity");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
break;
|
||||
|
@ -358,7 +357,6 @@ static void ProcessMsg(void)
|
|||
if (sigrcvd & (1 << Globals->Broker->ShutdownSigBit))
|
||||
{
|
||||
LogInfo("Received shut down from setting window");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
}
|
||||
|
@ -366,7 +364,6 @@ static void ProcessMsg(void)
|
|||
if (sigrcvd & SIGBREAKF_CTRL_C)
|
||||
{
|
||||
LogInfo("Received CTRL + C");
|
||||
LogWarning("Shutting down");
|
||||
StopSubProcesses();
|
||||
run = false;
|
||||
}
|
||||
|
|
161
com.c
161
com.c
|
@ -31,18 +31,26 @@
|
|||
#include "sntp.h"
|
||||
#include "mem.h"
|
||||
|
||||
#define POOLSUFFIX "pool.ntp.org"
|
||||
#define POOLPORT "123"
|
||||
|
||||
struct AppCom
|
||||
{
|
||||
bool Run;
|
||||
bool Restart;
|
||||
bool Exited;
|
||||
short TimerSigBit;
|
||||
short RestartSigBit;
|
||||
struct Process *Task;
|
||||
struct TimerInfo *TimerInfo;
|
||||
struct sntp *Client;
|
||||
short RestartSigBit;
|
||||
bool FirstRun;
|
||||
bool SocketOpen;
|
||||
int RunCount;
|
||||
int FailCount;
|
||||
int PoolServerNumber;
|
||||
char *ServerName;
|
||||
char *ServerPort;
|
||||
};
|
||||
|
||||
static void SyncProc(void);
|
||||
|
@ -91,8 +99,13 @@ void StartCom(void)
|
|||
Globals->Syncer->Restart = false;
|
||||
Globals->Syncer->Exited = false;
|
||||
Globals->Syncer->FirstRun = true;
|
||||
Globals->Syncer->SocketOpen = false;
|
||||
Globals->Syncer->RunCount = 0;
|
||||
Globals->Syncer->FailCount = 0;
|
||||
Globals->Syncer->PoolServerNumber = -1;
|
||||
Globals->Syncer->ServerName = NULL;
|
||||
Globals->Syncer->ServerPort = NULL;
|
||||
Globals->Syncer->TimerInfo = NULL;
|
||||
|
||||
Forbid();
|
||||
Globals->Syncer->Task = CreateNewProcTags(
|
||||
|
@ -112,6 +125,11 @@ void StartCom(void)
|
|||
}
|
||||
}
|
||||
|
||||
static ULONG GetTimerSigMask(void)
|
||||
{
|
||||
return (1 << Globals->Syncer->TimerSigBit);
|
||||
}
|
||||
|
||||
static ULONG GetSntpRestartSigMask(void)
|
||||
{
|
||||
return (1 << Globals->Syncer->RestartSigBit);
|
||||
|
@ -126,25 +144,12 @@ static void ComDestroy(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void Sync(void)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
ComOpen();
|
||||
SetTimer(Globals->Syncer->TimerInfo);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Sending next NTP request in %ld milliseconds",
|
||||
Globals->Settings->Interval);
|
||||
SendTraceMessage(message);
|
||||
ShowStats();
|
||||
Globals->Syncer->RunCount++;
|
||||
}
|
||||
|
||||
static void SyncProc(void)
|
||||
{
|
||||
Globals->Syncer->TimerInfo = CreateTimer(false);
|
||||
if (Globals->Syncer->TimerInfo == NULL)
|
||||
Globals->Syncer->TimerSigBit = AllocSignal(-1);
|
||||
if (Globals->Syncer->TimerSigBit == -1)
|
||||
{
|
||||
SendErrorMessage("Could not create timer for synchronizer");
|
||||
SendErrorMessage("Could not allocate signal for synchronizer");
|
||||
Globals->Syncer->Exited = true;
|
||||
return;
|
||||
}
|
||||
|
@ -153,23 +158,37 @@ static void SyncProc(void)
|
|||
if (Globals->Syncer->RestartSigBit == -1)
|
||||
{
|
||||
SendErrorMessage("Could not allocate signal for synchronizer");
|
||||
DeleteTimer(Globals->Syncer->TimerInfo);
|
||||
Globals->Syncer->Exited = true;
|
||||
FreeSignal(Globals->Syncer->TimerSigBit);
|
||||
return;
|
||||
}
|
||||
|
||||
Sync();
|
||||
Globals->Syncer->TimerInfo = CreateInterruptTimer(
|
||||
(struct Task *)Globals->Syncer->Task,
|
||||
Globals->Syncer->TimerSigBit);
|
||||
if (Globals->Syncer->TimerInfo == NULL)
|
||||
{
|
||||
SendErrorMessage("Could not create timer for synchronizer");
|
||||
Globals->Syncer->Exited = true;
|
||||
FreeSignal(Globals->Syncer->TimerSigBit);
|
||||
FreeSignal(Globals->Syncer->RestartSigBit);
|
||||
return;
|
||||
}
|
||||
|
||||
ComOpen();
|
||||
StartInterruptTimer(Globals->Syncer->TimerInfo);
|
||||
|
||||
do
|
||||
{
|
||||
ULONG sigtime = GetTimerSigMask(Globals->Syncer->TimerInfo);
|
||||
ULONG sigtime = GetTimerSigMask();
|
||||
ULONG sigrest = GetSntpRestartSigMask();
|
||||
ULONG sigmask = SIGBREAKF_CTRL_C | sigtime | sigrest;
|
||||
ULONG sigrcvd = Wait(sigmask);
|
||||
|
||||
if (sigrcvd & sigtime)
|
||||
{
|
||||
Sync();
|
||||
ComOpen();
|
||||
ShowStats();
|
||||
}
|
||||
|
||||
if (sigrcvd & sigrest)
|
||||
|
@ -177,6 +196,7 @@ static void SyncProc(void)
|
|||
ComDestroy();
|
||||
Globals->Syncer->Restart = true;
|
||||
ComOpen();
|
||||
ShowStats();
|
||||
}
|
||||
|
||||
if (sigrcvd & SIGBREAKF_CTRL_C)
|
||||
|
@ -186,6 +206,8 @@ static void SyncProc(void)
|
|||
} while (Globals->Syncer->Run);
|
||||
|
||||
ComDestroy();
|
||||
StopInterruptTimer(Globals->Syncer->TimerInfo);
|
||||
FreeSignal(Globals->Syncer->TimerSigBit);
|
||||
FreeSignal(Globals->Syncer->RestartSigBit);
|
||||
DeleteTimer(Globals->Syncer->TimerInfo);
|
||||
CloseSocketLibrary();
|
||||
|
@ -195,6 +217,18 @@ static void SyncProc(void)
|
|||
SendWarningMessage("Exited synchronizer process");
|
||||
}
|
||||
|
||||
if (Globals->Syncer->ServerName != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Syncer->ServerName);
|
||||
Globals->Syncer->ServerName = NULL;
|
||||
}
|
||||
|
||||
if (Globals->Syncer->ServerPort != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Syncer->ServerPort);
|
||||
Globals->Syncer->ServerPort = NULL;
|
||||
}
|
||||
|
||||
Globals->Syncer->TimerInfo = NULL;
|
||||
Globals->Syncer->Task = NULL;
|
||||
Globals->Syncer->Exited = true;
|
||||
|
@ -204,10 +238,12 @@ static void ComOpen(void)
|
|||
{
|
||||
if (OpenSocketLibrary() != LIB_OK)
|
||||
{
|
||||
// Make sure socket library is open
|
||||
Globals->Syncer->SocketOpen = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Syncer->SocketOpen = true;
|
||||
|
||||
if (Globals->Syncer->FirstRun)
|
||||
{
|
||||
SendInfoMessage("Starting SNTP client");
|
||||
|
@ -248,14 +284,33 @@ static void ComOpen(void)
|
|||
|
||||
static void ShowStats(void)
|
||||
{
|
||||
if (Globals->Syncer->SocketOpen)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Sending next NTP request in %ld milliseconds",
|
||||
Globals->Settings->Interval);
|
||||
SendTraceMessage(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Retry in %ld milliseconds",
|
||||
Globals->Settings->Interval);
|
||||
SendTraceMessage(message);
|
||||
}
|
||||
|
||||
Globals->Syncer->RunCount++;
|
||||
|
||||
if (Globals->Syncer->RunCount % 10 == 0)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
char timeString[10], dateString[10], dayString[10];
|
||||
SystemTimeString(timeString, dateString, dayString);
|
||||
char timeString[10], dateString[10], dayString[10], zoneString[10];
|
||||
SystemTimeString(timeString, dateString, dayString, zoneString);
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Local time is %s %s %s",
|
||||
dayString, dateString, timeString);
|
||||
"Local time is %s %s %s%s",
|
||||
dayString, dateString, timeString, zoneString);
|
||||
SendInfoMessage(message);
|
||||
}
|
||||
|
||||
|
@ -271,6 +326,51 @@ static void ShowStats(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void ChooseServer(void)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
int i;
|
||||
char *server = Globals->Settings->DestinationAddress;
|
||||
int len = StrLen(server);
|
||||
bool isPool = EndsWith(server, POOLSUFFIX) &&
|
||||
!StartsWith(server, "0.") &&
|
||||
!StartsWith(server, "1.") &&
|
||||
!StartsWith(server, "2.") &&
|
||||
!StartsWith(server, "3.");
|
||||
|
||||
if (Globals->Syncer->ServerName != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Syncer->ServerName);
|
||||
}
|
||||
|
||||
if (Globals->Syncer->ServerPort != NULL)
|
||||
{
|
||||
FreeMemSafe(Globals->Syncer->ServerPort);
|
||||
}
|
||||
|
||||
if (!isPool)
|
||||
{
|
||||
Globals->Syncer->ServerName = StrDupSafe(server);
|
||||
Globals->Syncer->ServerPort = StrDupSafe(Globals->Settings->DestinationPort);
|
||||
return;
|
||||
}
|
||||
|
||||
Globals->Syncer->ServerName = (char *)AllocMemSafe(len + 3);
|
||||
Globals->Syncer->ServerPort = StrDupSafe(POOLPORT);
|
||||
|
||||
do
|
||||
{
|
||||
i = RandomFast() % 4;
|
||||
} while (i < 0 || i == Globals->Syncer->PoolServerNumber);
|
||||
Globals->Syncer->PoolServerNumber = i;
|
||||
SNPrintf(Globals->Syncer->ServerName, len + 3,
|
||||
"%ld.%s", i, server);
|
||||
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Choosing pool server %s", Globals->Syncer->ServerName);
|
||||
SendWarningMessage(message);
|
||||
}
|
||||
|
||||
static void ComInit(void)
|
||||
{
|
||||
if (Globals->Syncer->Client != NULL)
|
||||
|
@ -279,9 +379,10 @@ static void ComInit(void)
|
|||
Globals->Syncer->Client = NULL;
|
||||
}
|
||||
|
||||
ChooseServer();
|
||||
Globals->Syncer->Client = sntp_create(
|
||||
Globals->Settings->DestinationAddress,
|
||||
Globals->Settings->DestinationPort,
|
||||
Globals->Syncer->ServerName,
|
||||
Globals->Syncer->ServerPort,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
|
@ -307,8 +408,8 @@ static int SyncClock(void)
|
|||
|
||||
SNPrintf(message, SETTINGMESSAGELEN,
|
||||
"Sending request to %s:%s",
|
||||
Globals->Settings->DestinationAddress,
|
||||
Globals->Settings->DestinationPort);
|
||||
Globals->Syncer->ServerName,
|
||||
Globals->Syncer->ServerPort);
|
||||
SendInfoMessage(message);
|
||||
|
||||
ret = sntp_send(Globals->Syncer->Client);
|
||||
|
|
7
config.h
7
config.h
|
@ -149,8 +149,8 @@ int poll(struct pollfd *, nfds_t, int);
|
|||
#define APP_LONG_NAME "Amiga Time Keeper"
|
||||
#endif
|
||||
|
||||
#define APP_VERSION "1.07"
|
||||
#define APP_DATE_VERSION "1.07 (15.02.2019)"
|
||||
#define APP_VERSION "1.08"
|
||||
#define APP_DATE_VERSION "1.08 (18.05.2019)"
|
||||
#define APP_ID APP_SHORT_NAME " " APP_DATE_VERSION
|
||||
#define APP_TITLE APP_LONG_NAME " " APP_DATE_VERSION
|
||||
#define APP_TITLE_VERSION APP_LONG_NAME " " APP_VERSION
|
||||
|
@ -218,6 +218,9 @@ void HideSettingWindow(void);
|
|||
int OpenLibraries(void);
|
||||
void CloseLibraries(void);
|
||||
|
||||
/* val.c */
|
||||
void SanitizeSettings(void);
|
||||
|
||||
/* net.c */
|
||||
int OpenSocketLibrary(void);
|
||||
void CloseSocketLibrary(void);
|
||||
|
|
|
@ -262,6 +262,8 @@ int OpenLibraries(void)
|
|||
|
||||
InitUtcOffset();
|
||||
|
||||
SeedRandom();
|
||||
|
||||
return LIB_OK;
|
||||
}
|
||||
|
||||
|
|
6
main.c
6
main.c
|
@ -148,7 +148,7 @@ static void LogStartMessage(void)
|
|||
|
||||
static void LogLocalTime(void)
|
||||
{
|
||||
char timeString[10], dateString[10], dayString[10];
|
||||
SystemTimeString(timeString, dateString, dayString);
|
||||
LogWarning("Local time is %s %s %s", dayString, dateString, timeString);
|
||||
char timeString[10], dateString[10], dayString[10], zoneString[10];
|
||||
SystemTimeString(timeString, dateString, dayString, zoneString);
|
||||
LogWarning("Local time is %s %s %s%s", dayString, dateString, timeString, zoneString);
|
||||
}
|
||||
|
|
142
state.c
142
state.c
|
@ -109,13 +109,10 @@ static const char *applyFileSettings = "Applying values from preference file";
|
|||
static const char *applyCliSettings = "Applying values from CLI";
|
||||
static const char *applyWbSettings = "Applying values from tooltypes";
|
||||
static const char *effectiveSettings = "Listing runtime values";
|
||||
static const char *settingTooLow = "%s < %ld (too low)";
|
||||
static const char *settingTooHigh = "%s > %ld (too high)";
|
||||
static const char *settingGreaterThan = "%s > %s";
|
||||
static const char *settingChangedLong = "%s changed: %ld -> %ld";
|
||||
static const char *settingChangedString = "%s changed: %s -> %s";
|
||||
static const char *settingSetLong = "%s already set to %ld";
|
||||
static const char *settingSetString = "%s already set to %s";
|
||||
static const char *settingSetLong = "%s is already set to %ld";
|
||||
static const char *settingSetString = "%s is already set to %s";
|
||||
static const char *settingValueLong = "%s=%ld";
|
||||
static const char *settingValueString = "%s=%s";
|
||||
static const char *saveValueLong = "%s=%ld\n";
|
||||
|
@ -236,7 +233,7 @@ static void ParseBooleanSetting(
|
|||
void *value,
|
||||
bool yesNo)
|
||||
{
|
||||
LogFoundSetting(settings->Type, SettingKeys->Popup);
|
||||
LogFoundSetting(settings->Type, keyword);
|
||||
|
||||
// CLI switch is always a long value
|
||||
if (settings->Type == CliSettingType && !yesNo)
|
||||
|
@ -600,7 +597,7 @@ static void ApplyBooleanSetting(
|
|||
}
|
||||
else if (!quiet)
|
||||
{
|
||||
LogTrace(settingValueString, keyword, BooleanAsText(*newValue));
|
||||
LogTrace(settingSetString, keyword, BooleanAsText(*newValue));
|
||||
}
|
||||
*curValue = *newValue;
|
||||
}
|
||||
|
@ -770,134 +767,3 @@ void ApplySettings()
|
|||
}
|
||||
}
|
||||
|
||||
static void ValidateInterval(void)
|
||||
{
|
||||
if (Globals->Settings->Interval < INTERVAL_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Interval,
|
||||
INTERVAL_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Interval,
|
||||
Globals->Settings->Interval,
|
||||
INTERVAL_MIN);
|
||||
Globals->Settings->Interval = INTERVAL_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeout(void)
|
||||
{
|
||||
if (Globals->Settings->Timeout < TIMEOUT_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
Globals->Settings->Timeout = TIMEOUT_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > Globals->Settings->Interval)
|
||||
{
|
||||
LogInfo(settingGreaterThan,
|
||||
SettingKeys->Timeout,
|
||||
SettingKeys->Interval);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
Globals->Settings->Interval);
|
||||
Globals->Settings->Timeout = Globals->Settings->Interval;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > TIMEOUT_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
Globals->Settings->Timeout = TIMEOUT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidatePriority(void)
|
||||
{
|
||||
if (Globals->Settings->Priority < PRIORITY_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MIN);
|
||||
Globals->Settings->Priority = PRIORITY_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Priority > PRIORITY_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MAX);
|
||||
Globals->Settings->Priority = PRIORITY_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateThreshold(void)
|
||||
{
|
||||
if (Globals->Settings->Threshold < THRESHOLD_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Threshold,
|
||||
Globals->Settings->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
Globals->Settings->Threshold = THRESHOLD_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateVerbose(void)
|
||||
{
|
||||
if (Globals->Settings->Verbose < VERBOSE_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MIN);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MIN);
|
||||
Globals->Settings->Verbose = VERBOSE_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Verbose > VERBOSE_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MAX);
|
||||
LogInfo(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MAX);
|
||||
Globals->Settings->Verbose = VERBOSE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void SanitizeSettings(void)
|
||||
{
|
||||
ValidateInterval();
|
||||
ValidateTimeout();
|
||||
ValidatePriority();
|
||||
ValidateThreshold();
|
||||
ValidateVerbose();
|
||||
}
|
||||
|
|
1
state.h
1
state.h
|
@ -140,7 +140,6 @@ extern const struct AppSettings DefaultSettings;
|
|||
|
||||
void InitState(void);
|
||||
void DestroyState(void);
|
||||
void SanitizeSettings(void);
|
||||
void ShowSettings(void);
|
||||
void LoadSettings(void);
|
||||
void SaveSettings(bool);
|
||||
|
|
58
string.c
58
string.c
|
@ -139,6 +139,64 @@ char *StrRChr(const char *start, const char c, int len)
|
|||
return l;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if a prefix occurs at the start of a string.
|
||||
*/
|
||||
bool StartsWith(const char *string, const char *prefix)
|
||||
{
|
||||
char *i = (char *)string;
|
||||
char *j = (char *)prefix;
|
||||
|
||||
if (i == NULL || j == NULL)
|
||||
return false;
|
||||
|
||||
while (*i == *j && *i != '\0' && *j != '\0')
|
||||
{
|
||||
i++;
|
||||
j++;
|
||||
}
|
||||
|
||||
return (*j == '\0' ? true : false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine if a suffix occurs at the end of a string.
|
||||
*/
|
||||
bool EndsWith(const char *string, const char *suffix)
|
||||
{
|
||||
int a = 0;
|
||||
int b = 0;
|
||||
char *i = (char *)string;
|
||||
char *j = (char *)suffix;
|
||||
|
||||
if (i == NULL || j == NULL)
|
||||
return false;
|
||||
|
||||
while (*i)
|
||||
{
|
||||
i++;
|
||||
a++;
|
||||
}
|
||||
|
||||
while (*j)
|
||||
{
|
||||
j++;
|
||||
b++;
|
||||
}
|
||||
|
||||
if (b > a)
|
||||
return false;
|
||||
|
||||
while (*i == *j && b != 0)
|
||||
{
|
||||
i--;
|
||||
j--;
|
||||
b--;
|
||||
}
|
||||
|
||||
return (b == 0) ? true : false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a long to a null terminated string.
|
||||
*/
|
||||
|
|
2
string.h
2
string.h
|
@ -42,6 +42,8 @@ int LongLongToStr(signed long long, char *);
|
|||
int StrToLongLong(char *, unsigned long long *);
|
||||
bool TryParseLong(char *, long *);
|
||||
bool TryParseLongLong(char *, long long *);
|
||||
bool StartsWith(const char *, const char *);
|
||||
bool EndsWith(const char *, const char *);
|
||||
int VSNPrintf(char *, size_t, const char *, va_list);
|
||||
int SNPrintf(char *, size_t, const char *, ...);
|
||||
void SplitFileName(const char *, char *, char *);
|
||||
|
|
192
time.c
192
time.c
|
@ -28,6 +28,7 @@
|
|||
#include "time.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include <exec/interrupts.h>
|
||||
#include <clib/alib_protos.h>
|
||||
|
||||
/*
|
||||
|
@ -41,15 +42,26 @@
|
|||
|
||||
struct TimerInfo
|
||||
{
|
||||
bool TimerTrigged;
|
||||
bool InterruptTimer;
|
||||
bool TimerStarted;
|
||||
bool TimerActive;
|
||||
bool TimerExited;
|
||||
long Interval;
|
||||
long Counter;
|
||||
struct MsgPort *TimerPort;
|
||||
struct Interrupt *TimerInterrupt;
|
||||
struct timerequest *TimerIO;
|
||||
struct Task *InterruptTask;
|
||||
ULONG InterruptSigBit;
|
||||
};
|
||||
|
||||
struct Device *TimerBase = NULL;
|
||||
static struct timerequest *TimerIO = NULL;
|
||||
static long utcOffset = 0;
|
||||
|
||||
// Only one interrupt timer is allowed
|
||||
struct TimerInfo *InterruptInfo;
|
||||
|
||||
/*
|
||||
* Set up pointer for timer functions.
|
||||
*/
|
||||
|
@ -88,10 +100,119 @@ void CloseTimerBase(void)
|
|||
}
|
||||
}
|
||||
|
||||
void TimerInterruptCode(void)
|
||||
{
|
||||
struct TimerInfo *info = InterruptInfo;
|
||||
struct timerequest *tr = (struct timerequest *)GetMsg(info->TimerPort);
|
||||
|
||||
if (!info->TimerActive)
|
||||
{
|
||||
info->TimerExited = true;
|
||||
return;
|
||||
}
|
||||
|
||||
info->Counter++;
|
||||
Signal(info->InterruptTask, info->InterruptSigBit);
|
||||
|
||||
tr->tr_node.io_Command = TR_ADDREQUEST;
|
||||
tr->tr_time.tv_secs = Globals->Settings->Interval / 1000;
|
||||
tr->tr_time.tv_micro = Globals->Settings->Interval % 1000;
|
||||
|
||||
BeginIO((struct IORequest *)tr);
|
||||
}
|
||||
|
||||
void StartInterruptTimer(struct TimerInfo *info)
|
||||
{
|
||||
info->TimerStarted = true;
|
||||
info->TimerActive = true;
|
||||
info->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
|
||||
info->TimerIO->tr_time.tv_secs = Globals->Settings->Interval / 1000;
|
||||
info->TimerIO->tr_time.tv_micro = Globals->Settings->Interval % 1000;
|
||||
BeginIO((struct IORequest *)info->TimerIO);
|
||||
}
|
||||
|
||||
void StopInterruptTimer(struct TimerInfo *info)
|
||||
{
|
||||
info->TimerActive = false;
|
||||
|
||||
AbortIO((struct IORequest *)info->TimerIO);
|
||||
if (info->TimerStarted)
|
||||
{
|
||||
WaitIO((struct IORequest *)info->TimerIO);
|
||||
}
|
||||
|
||||
while (!info->TimerExited)
|
||||
{
|
||||
Delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a timer device with UNIT_VBLANK.
|
||||
* Create a Timer device software interrupt as descibed on wiki.amigaos.net:
|
||||
* https://wiki.amigaos.net/wiki/Exec_Interrupts#Software_Interrupts
|
||||
* and Amiga Developer Docs 2.1, lib_examples/timersoftint.c
|
||||
*/
|
||||
struct TimerInfo *CreateTimer(bool setTimerBase)
|
||||
struct TimerInfo *CreateInterruptTimer(struct Task *task, short sigBit)
|
||||
{
|
||||
LONG error;
|
||||
struct TimerInfo *info = (struct TimerInfo *)AllocMemSafe(sizeof(struct TimerInfo));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
|
||||
info->InterruptTimer = true;
|
||||
info->InterruptTask = task;
|
||||
info->InterruptSigBit = 1 << sigBit;
|
||||
|
||||
info->TimerPort = (struct MsgPort *)AllocMemSafe(sizeof(struct MsgPort));
|
||||
if (info->TimerPort == NULL)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
info->TimerInterrupt = (struct Interrupt *)AllocMemSafe(sizeof(struct Interrupt));
|
||||
if (info->TimerInterrupt == NULL)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
NewList(&(info->TimerPort->mp_MsgList));
|
||||
info->TimerPort->mp_Node.ln_Type = NT_MSGPORT;
|
||||
info->TimerPort->mp_Flags = PA_SOFTINT;
|
||||
info->TimerPort->mp_SigTask = (struct Task *)info->TimerInterrupt;
|
||||
|
||||
info->TimerInterrupt->is_Code = TimerInterruptCode;
|
||||
info->TimerInterrupt->is_Data = info;
|
||||
info->TimerInterrupt->is_Node.ln_Pri = 0;
|
||||
|
||||
info->TimerIO = (struct timerequest *)CreateExtIO(info->TimerPort, sizeof(struct timerequest));
|
||||
if (info->TimerIO == NULL)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
error = OpenDevice(
|
||||
(STRPTR)TIMERNAME, UNIT_MICROHZ,
|
||||
(struct IORequest *)info->TimerIO, 0);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
DeleteTimer(info);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Only one interrupt timer is supported
|
||||
InterruptInfo = info;
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
/*
|
||||
* Open a timer device with UNIT_MICROHZ.
|
||||
*/
|
||||
struct TimerInfo *CreateTimer(void)
|
||||
{
|
||||
LONG error;
|
||||
static const char *name = APP_SHORT_NAME " Timer Message Port";
|
||||
|
@ -129,26 +250,15 @@ struct TimerInfo *CreateTimer(bool setTimerBase)
|
|||
return info;
|
||||
}
|
||||
|
||||
void SetTimer(struct TimerInfo *info)
|
||||
{
|
||||
info->TimerIO->tr_node.io_Command = TR_ADDREQUEST;
|
||||
info->TimerIO->tr_time.tv_secs = Globals->Settings->Interval / 1000;
|
||||
info->TimerIO->tr_time.tv_micro = Globals->Settings->Interval % 1000;
|
||||
SendIO((struct IORequest *)info->TimerIO);
|
||||
info->TimerTrigged = true;
|
||||
}
|
||||
|
||||
ULONG GetTimerSigMask(struct TimerInfo *info)
|
||||
{
|
||||
return (1 << info->TimerPort->mp_SigBit);
|
||||
}
|
||||
|
||||
void DeleteTimer(struct TimerInfo *info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
if (info->TimerIO != NULL)
|
||||
{
|
||||
AbortIO((struct IORequest *)info->TimerIO);
|
||||
if (info->TimerTrigged)
|
||||
if (info->TimerStarted)
|
||||
{
|
||||
WaitIO((struct IORequest *)info->TimerIO);
|
||||
}
|
||||
|
@ -159,7 +269,19 @@ void DeleteTimer(struct TimerInfo *info)
|
|||
|
||||
if (info->TimerPort != NULL)
|
||||
{
|
||||
DeleteMsgPort(info->TimerPort);
|
||||
if (info->InterruptTimer)
|
||||
{
|
||||
FreeMemSafe(info->TimerPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteMsgPort(info->TimerPort);
|
||||
}
|
||||
}
|
||||
|
||||
if (info->TimerInterrupt != NULL)
|
||||
{
|
||||
FreeMemSafe(info->TimerInterrupt);
|
||||
}
|
||||
|
||||
FreeMemSafe(info);
|
||||
|
@ -170,16 +292,17 @@ void InitUtcOffset(void)
|
|||
char timeZone[10];
|
||||
int gmtoffset = Globals->Locale->loc_GMTOffset * 60;
|
||||
utcOffset = gmtoffset + AMIGA_OFFSET;
|
||||
GetTimeZoneText(timeZone);
|
||||
GetTimeZoneText(timeZone, true);
|
||||
LogWarning("Local time zone is %s", timeZone);
|
||||
}
|
||||
|
||||
void GetTimeZoneText(char *text)
|
||||
void GetTimeZoneText(char *text, bool includeUtc)
|
||||
{
|
||||
SNPrintf(text, 10, "UTC%s%ld:%02ld",
|
||||
-Globals->Locale->loc_GMTOffset > 0 ? "+" : "",
|
||||
(long)-Globals->Locale->loc_GMTOffset / 60,
|
||||
(long)-Globals->Locale->loc_GMTOffset % 60);
|
||||
SNPrintf(text, 10, "%s%s%ld:%02ld",
|
||||
includeUtc ? "UTC" : "",
|
||||
(Globals->Locale->loc_GMTOffset < 0L) ? "+" : "",
|
||||
(long)(Globals->Locale->loc_GMTOffset / -60L),
|
||||
(long)(Globals->Locale->loc_GMTOffset % -60L));
|
||||
}
|
||||
|
||||
void Unix2Amiga(struct timeval *unix, struct timeval *tv)
|
||||
|
@ -219,7 +342,7 @@ void SaveTimeOfDay(const struct timeval *tv)
|
|||
WriteBattClock((long)tv->tv_secs - utcOffset);
|
||||
}
|
||||
|
||||
void SystemTimeString(char *time, char *date, char *day)
|
||||
void SystemTimeString(char *time, char *date, char *day, char *zone)
|
||||
{
|
||||
struct DateTime dt;
|
||||
|
||||
|
@ -232,4 +355,21 @@ void SystemTimeString(char *time, char *date, char *day)
|
|||
dt.dat_StrTime = (void *)time;
|
||||
|
||||
DateToStr(&dt);
|
||||
|
||||
GetTimeZoneText(zone, false);
|
||||
}
|
||||
|
||||
static int seed = 123456789;
|
||||
|
||||
void SeedRandom(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
GetLocalTimeOfDay(&tv);
|
||||
seed = tv.tv_micro;
|
||||
}
|
||||
|
||||
int RandomFast(void)
|
||||
{
|
||||
seed = (1103515245 * seed + 12345) % 0x7fffffff;
|
||||
return seed;
|
||||
}
|
||||
|
|
13
time.h
13
time.h
|
@ -33,19 +33,24 @@ struct TimerInfo;
|
|||
|
||||
struct Device *OpenTimerBase(void);
|
||||
void CloseTimerBase(void);
|
||||
struct TimerInfo *CreateTimer(bool);
|
||||
struct TimerInfo *CreateTimer(void);
|
||||
struct TimerInfo *CreateInterruptTimer(struct Task *, short);
|
||||
void SetTimer(struct TimerInfo *);
|
||||
void DeleteTimer(struct TimerInfo *);
|
||||
ULONG GetTimerSigMask(struct TimerInfo *info);
|
||||
void StartInterruptTimer(struct TimerInfo *);
|
||||
void StopInterruptTimer(struct TimerInfo *);
|
||||
|
||||
void InitUtcOffset(void);
|
||||
void GetTimeZoneText(char *text);
|
||||
void GetTimeZoneText(char *text, bool includeUtc);
|
||||
void GetTimeOfDay(struct timeval *tv);
|
||||
void SetTimeOfDay(const struct TimerInfo *, const struct timeval *tv);
|
||||
void SaveTimeOfDay(const struct timeval *tv);
|
||||
void GetLocalTimeOfDay(struct timeval *tv);
|
||||
void Unix2Amiga(struct timeval *unix, struct timeval *tv);
|
||||
void Utc2Local(struct timeval *utc, struct timeval *tv);
|
||||
void SystemTimeString(char *time, char *date, char *day);
|
||||
void SystemTimeString(char *time, char *date, char *day, char *zone);
|
||||
|
||||
void SeedRandom(void);
|
||||
int RandomFast(void);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,191 @@
|
|||
/*-
|
||||
* Copyright (c) 2017-2019 Carsten Sonne Larsen <cs@innolan.net>
|
||||
* 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 "state.h"
|
||||
#include "message.h"
|
||||
#include "log.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
static const char *settingChangedLong = "%s changed: %ld -> %ld";
|
||||
static const char *settingTooLow = "%s < %ld (too low)";
|
||||
static const char *settingTooHigh = "%s > %ld (too high)";
|
||||
static const char *settingGreaterThan = "%s * 2 > %s";
|
||||
|
||||
static void LogValidationLine(const char *format, va_list ap)
|
||||
{
|
||||
char message[SETTINGMESSAGELEN];
|
||||
VSNPrintf(message, SETTINGMESSAGELEN - 1, format, ap);
|
||||
|
||||
if (Globals->Broker->Task == NULL || FindTask(NULL) == Globals->Broker->Task)
|
||||
{
|
||||
LogInfo(message);
|
||||
}
|
||||
else
|
||||
{
|
||||
SendInfoMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
static void LogValidation(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
LogValidationLine(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static void ValidateInterval(void)
|
||||
{
|
||||
if (Globals->Settings->Interval < INTERVAL_MIN)
|
||||
{
|
||||
LogValidation(settingTooLow,
|
||||
SettingKeys->Interval,
|
||||
INTERVAL_MIN);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Interval,
|
||||
Globals->Settings->Interval,
|
||||
INTERVAL_MIN);
|
||||
Globals->Settings->Interval = INTERVAL_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeout(void)
|
||||
{
|
||||
if (Globals->Settings->Timeout < TIMEOUT_MIN)
|
||||
{
|
||||
LogValidation(settingTooLow,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MIN);
|
||||
Globals->Settings->Timeout = TIMEOUT_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > Globals->Settings->Interval / 2)
|
||||
{
|
||||
LogValidation(settingGreaterThan,
|
||||
SettingKeys->Timeout,
|
||||
SettingKeys->Interval);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
Globals->Settings->Interval / 2);
|
||||
Globals->Settings->Timeout = Globals->Settings->Interval / 2;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Timeout > TIMEOUT_MAX)
|
||||
{
|
||||
LogValidation(settingTooHigh,
|
||||
SettingKeys->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Timeout,
|
||||
Globals->Settings->Timeout,
|
||||
TIMEOUT_MAX);
|
||||
Globals->Settings->Timeout = TIMEOUT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidatePriority(void)
|
||||
{
|
||||
if (Globals->Settings->Priority < PRIORITY_MIN)
|
||||
{
|
||||
LogValidation(settingTooLow,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MIN);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MIN);
|
||||
Globals->Settings->Priority = PRIORITY_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Priority > PRIORITY_MAX)
|
||||
{
|
||||
LogValidation(settingTooHigh,
|
||||
SettingKeys->Priority,
|
||||
PRIORITY_MAX);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Priority,
|
||||
Globals->Settings->Priority,
|
||||
PRIORITY_MAX);
|
||||
Globals->Settings->Priority = PRIORITY_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateThreshold(void)
|
||||
{
|
||||
if (Globals->Settings->Threshold < THRESHOLD_MIN)
|
||||
{
|
||||
LogValidation(settingTooLow,
|
||||
SettingKeys->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Threshold,
|
||||
Globals->Settings->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
Globals->Settings->Threshold = THRESHOLD_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateVerbose(void)
|
||||
{
|
||||
if (Globals->Settings->Verbose < VERBOSE_MIN)
|
||||
{
|
||||
LogValidation(settingTooLow,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MIN);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MIN);
|
||||
Globals->Settings->Verbose = VERBOSE_MIN;
|
||||
}
|
||||
|
||||
if (Globals->Settings->Verbose > VERBOSE_MAX)
|
||||
{
|
||||
LogValidation(settingTooHigh,
|
||||
SettingKeys->Verbose,
|
||||
VERBOSE_MAX);
|
||||
LogValidation(settingChangedLong,
|
||||
SettingKeys->Verbose,
|
||||
Globals->Settings->Verbose,
|
||||
VERBOSE_MAX);
|
||||
Globals->Settings->Verbose = VERBOSE_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
void SanitizeSettings(void)
|
||||
{
|
||||
ValidateInterval();
|
||||
ValidateTimeout();
|
||||
ValidatePriority();
|
||||
ValidateThreshold();
|
||||
ValidateVerbose();
|
||||
}
|
27
win_gad.c
27
win_gad.c
|
@ -163,7 +163,6 @@ bool CreateGadgets(void)
|
|||
|
||||
Globals->Window->Gadgets->ServerGadget = gadget;
|
||||
|
||||
|
||||
if (Globals->Settings->Expert)
|
||||
{
|
||||
// Port
|
||||
|
@ -446,6 +445,7 @@ void SetServer(void)
|
|||
FreeMemSafe(Globals->Settings->DestinationAddress);
|
||||
Globals->Settings->DestinationAddress = StrDupSafe(server);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
}
|
||||
|
||||
|
@ -471,6 +471,7 @@ void SetPort(void)
|
|||
FreeMemSafe(Globals->Settings->DestinationPort);
|
||||
Globals->Settings->DestinationPort = StrDupSafe(port);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
}
|
||||
|
||||
|
@ -487,9 +488,6 @@ void SetInterval(void)
|
|||
GTIN_Number, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < INTERVAL_MIN)
|
||||
value = INTERVAL_MIN;
|
||||
|
||||
if (Globals->Settings->Interval != value)
|
||||
{
|
||||
char *text;
|
||||
|
@ -501,6 +499,9 @@ void SetInterval(void)
|
|||
Globals->Settings->Interval = value;
|
||||
text = BuildLogText(SettingKeys->Interval, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
SanitizeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -517,11 +518,6 @@ void SetTimeout(void)
|
|||
GTIN_Number, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < TIMEOUT_MIN)
|
||||
value = TIMEOUT_MIN;
|
||||
else if (value > TIMEOUT_MAX)
|
||||
value = TIMEOUT_MAX;
|
||||
|
||||
if (Globals->Settings->Timeout != value)
|
||||
{
|
||||
char *text;
|
||||
|
@ -533,6 +529,9 @@ void SetTimeout(void)
|
|||
Globals->Settings->Timeout = value;
|
||||
text = BuildLogText(SettingKeys->Timeout, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
SanitizeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -563,7 +562,9 @@ void SetThreshold(void)
|
|||
Globals->Settings->Threshold = value;
|
||||
text = BuildLogText(SettingKeys->Threshold, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
SendMessage(ATK_RESTART);
|
||||
SanitizeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -580,11 +581,6 @@ void SetVerbose(void)
|
|||
GTCY_Active, (IPTR)&value,
|
||||
TAG_END);
|
||||
|
||||
if (value < VERBOSE_MIN)
|
||||
value = VERBOSE_MIN;
|
||||
else if (value > VERBOSE_MAX)
|
||||
value = VERBOSE_MAX;
|
||||
|
||||
if (Globals->Settings->Verbose != value)
|
||||
{
|
||||
char *text;
|
||||
|
@ -595,7 +591,9 @@ void SetVerbose(void)
|
|||
LongToStr(value, newValue);
|
||||
text = BuildLogText(SettingKeys->Verbose, oldValue, newValue);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
Globals->Settings->Verbose = value;
|
||||
SanitizeSettings();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -634,6 +632,7 @@ void SetCxPriority(void)
|
|||
text = BuildLogText(SettingKeys->Priority, oldValue, newValue);
|
||||
SetBrokerPriority(value);
|
||||
SendInfoMessage(text);
|
||||
FreeMemSafe(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -114,7 +114,7 @@ static bool InitWindow(void)
|
|||
|
||||
LongToStr(Globals->Settings->Priority, Globals->Window->PriorityText);
|
||||
LongLongToStr(Globals->Settings->Threshold, Globals->Window->ThresholdText);
|
||||
GetTimeZoneText(Globals->Window->TimeZoneText);
|
||||
GetTimeZoneText(Globals->Window->TimeZoneText, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue