mirror of
https://ranger.innolan.net/rainlance/AmiTimeKeeper.git
synced 2025-10-07 12:43:00 +00:00
Release 1.12
This commit is contained in:
@@ -1,5 +1,16 @@
|
||||
AmiTimeKeeper Change Log
|
||||
|
||||
v1.12 31.01.2021
|
||||
- New options to specify the local time zone
|
||||
- New ARexx commands, parameters and error variables
|
||||
- New option to start without active time synchronization
|
||||
- New deactivate logging option for performance saving
|
||||
- More bugs in calculation of time zone transition fixed
|
||||
- Sanity check on value for interval between requests
|
||||
- Updated ARexx documentation and script
|
||||
- Honour ARexx result flag (RXFF_RESULT)
|
||||
- Various minor bug fixes and improvements
|
||||
|
||||
v1.11 11.01.2021
|
||||
- New dedicated external control utility
|
||||
- New ARexx port with a diverse set of commands
|
||||
|
||||
+382
-124
@@ -1,5 +1,5 @@
|
||||
@database TimeKeeper.guide
|
||||
@$VER: TimeKeeper.guide 1.11 (11.01.2021)
|
||||
@$VER: TimeKeeper.guide 1.12 (31.01.2021)
|
||||
@(c) 2017-2021 Carsten Sonne Larsen <cs@innolan.net>
|
||||
@author Carsten Sonne Larsen
|
||||
|
||||
@@ -26,46 +26,50 @@
|
||||
@rem (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
@rem THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@Width 74
|
||||
@Width 67
|
||||
|
||||
@Node Main "TimeKeeper.guide"
|
||||
@Next "Configuring the client"
|
||||
@Index "Index"
|
||||
@Smartwrap
|
||||
|
||||
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.
|
||||
@{par}
|
||||
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.
|
||||
|
||||
@{par}
|
||||
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. A utility
|
||||
for small tasks like starting and stopping is also included.
|
||||
Comprehensive control is possible using ARexx.
|
||||
either directly from the command line or by using the tool types
|
||||
of an icon. Preferences can also be saved between reboots.
|
||||
A utility for small tasks like starting and stopping is also
|
||||
included. Comprehensive control is possible using ARexx.
|
||||
|
||||
@{par}
|
||||
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. Use a fixed pool server by prefixing the domain, for example,
|
||||
1.pool.ntp.org.
|
||||
try visiting support.ntp.org or one of the other sites listing
|
||||
time servers. Use a fixed pool server by prefixing the domain,
|
||||
for example, 1.pool.ntp.org.
|
||||
|
||||
The local time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. In AmigaOS 3.1 and 3.9 this is available through
|
||||
the Locale Preferences Editor. Daylight saving time is only supported
|
||||
through the POSIX TZ environment variable.
|
||||
@{par}
|
||||
The time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. In Amiga OS this is available through the
|
||||
Locale Preferences Editor. The local time zone and daylight saving
|
||||
time are optionally specified manually or using a POSIX TZ
|
||||
variable style.
|
||||
|
||||
This version (1.11) has two known issues:
|
||||
- Settings window in AROS is broken (and disabled in this version)
|
||||
- Setting Popkey is not supported in ARexx
|
||||
|
||||
@{"Configuring the client" Link "Configuring the client"}
|
||||
@{"Using tooltypes of an icon" Link "Using tooltypes of an icon"}
|
||||
@{"Saving preferences" Link "Saving preferences"}
|
||||
@{"ARexx interface" Link "ARexx interface"}
|
||||
@{"The POSIX TZ environment variable" Link "The POSIX TZ environment variable"}
|
||||
@{"Change Log / Change History" Link "Change Log"}
|
||||
@{"Software License" Link "Software License"}
|
||||
@{"Credits and donations" Link "Credits and donations"}
|
||||
@{"Contacting the author" Link "Contacting the author"}
|
||||
@{par}
|
||||
@{"Configuring the client" Link "Configuring the client"}@{line}
|
||||
@{"Using tooltypes of an icon" Link "Using tooltypes of an icon"}@{line}
|
||||
@{"Local time zone" Link "Local time zone"}@{line}
|
||||
@{"Saving preferences" Link "Saving preferences"}@{line}
|
||||
@{"ARexx interface" Link "ARexx interface"}@{line}
|
||||
@{"POSIX TZ environment variable" Link "POSIX TZ environment variable"}@{line}
|
||||
@{"Change Log / Change History" Link "Change Log"}@{line}
|
||||
@{"Software License" Link "Software License"}@{line}
|
||||
@{"Credits and donations" Link "Credits and donations"}@{line}
|
||||
@{"Contacting the author" Link "Contacting the author"}@{line}
|
||||
|
||||
@EndNode
|
||||
|
||||
@@ -103,53 +107,101 @@ is the NTP server port different from 123.
|
||||
@{b}Interval between requests@{ub}
|
||||
|
||||
The Amiga hardware clock will slowly drift away from true time. The
|
||||
drift is determined by several factors and is small, but the drift is not
|
||||
insignificant. Request are repeatedly sent to the NTP server in order to
|
||||
keep the Amiga hardware clock as close to true time as possible.
|
||||
drift is determined by several factors and is small, but the drift
|
||||
is not insignificant. Request are repeatedly sent to the NTP server
|
||||
in order to keep the Amiga hardware clock as close to true time as
|
||||
possible.
|
||||
|
||||
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.
|
||||
thousand (1.000) milliseconds are equal to one second. The max value
|
||||
is 172.800.000 equal to 48 hours.
|
||||
|
||||
@{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
|
||||
server. Processing the response could take longer time than anticipated.
|
||||
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.
|
||||
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 server. Processing the response could take longer time
|
||||
than anticipated. The amount of accepted inaccuracy is set using the
|
||||
threshold parameter. The threshold should be specified using micro-
|
||||
seconds. One million microseconds (1.000.000) are equal to one
|
||||
second.
|
||||
|
||||
@{b}Start with synchronization active@{ub}
|
||||
|
||||
Maybe some related settings or the network connection are not ready
|
||||
from the beginning. The commodity can then be started in a preparation
|
||||
mode. Activation is possible from within AmigaOS, through the control
|
||||
utility @{i}TimeCtrl@{ui}, or through the ARexx interface.
|
||||
|
||||
@{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.
|
||||
Amiga hardware clock. This option can be handy when debugging time
|
||||
zone setup and other time related parameters.
|
||||
|
||||
@{b}Expert mode@{ub}
|
||||
|
||||
Advanced settings are hidden from the settings window when expert mode
|
||||
is not enabled. The advanced settings are server port, interval between
|
||||
requests, adjustment threshold, connection timeout, verbosity level and
|
||||
commodity priority.
|
||||
Advanced settings are hidden from the settings window 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}
|
||||
@{b}Connection time out@{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
|
||||
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.
|
||||
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 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. The max value is half
|
||||
of the value of interval between requests.
|
||||
|
||||
@{b}Logging@{ub}
|
||||
|
||||
It is possible view log messages using the supplied tool TimeLogger.
|
||||
It is possible view log messages using the supplied tool @{i}TimeLogger@{ui}.
|
||||
The logger facility can be turned off with the NOLOG switch.
|
||||
|
||||
@{b}Automatically synchronization@{ub}
|
||||
|
||||
Sometimes it is feasible to start without synchronization. The clock
|
||||
is synchronized in the background, only when synchronization is
|
||||
active. By default synchronization is not active.
|
||||
|
||||
@{b}Time zone display@{ub}
|
||||
|
||||
Different options for displaying the current time zone exists. The
|
||||
most common is a combination of time zone name and time zone offset
|
||||
from GMT. The ARexx documentation describes the time zone display
|
||||
methods in details.
|
||||
|
||||
@{b}Time zone@{ub}
|
||||
|
||||
If the local time zone is expressed as a POSIX TZ compatible string,
|
||||
an optional setting is available.
|
||||
|
||||
@{b}Time zone value@{ub}
|
||||
|
||||
The most simple way to expressed the local time zone is in hours
|
||||
and minutes from Greenwich Mean Time (GMT) or UTC. One hour ahead
|
||||
is equal to 100. One hour behind is equal to -100. Two and a half
|
||||
hour ahead is equal to 230.
|
||||
|
||||
@{b}Time zone abbreviation@{ub}
|
||||
|
||||
If no name is given for the local time zone, the time zone is shown
|
||||
as hours and minutes from Greenwich Mean Time (GMT). It is possible
|
||||
to specify a time zone abbreviation for better readability.
|
||||
|
||||
@{b}Daylight saving time@{ub}
|
||||
|
||||
Sometimes is feasible to force a standard one hour ahead daylight
|
||||
saving time (DST). Use this option if needed.
|
||||
|
||||
@{b}Caveats@{ub}
|
||||
|
||||
TimeKeeper does not start as a background process. When started in the
|
||||
startup-sequence it will by default block execution. Use the run command
|
||||
to avoid this behaviour:
|
||||
TimeKeeper does not start as a background process. When started in
|
||||
the startup-sequence it will by default block execution. Use the run
|
||||
command to avoid this behaviour:
|
||||
> RUN >NIL: TimeKeeper
|
||||
|
||||
@EndNode
|
||||
@@ -158,18 +210,18 @@ to avoid this behaviour:
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
@Prev "Configuring the client"
|
||||
@Next "Saving preferences"
|
||||
@Next "Local time zone"
|
||||
|
||||
Settings can be changes by setting tooltypes in the TimeKeeper icon.
|
||||
Add the following line to the icon tooltypes in order to set the server
|
||||
to an European pool server:
|
||||
Settings can be changes by setting tooltypes in the TimeKeeper
|
||||
icon. Add the following line to the icon tooltypes in order to
|
||||
set the server to an European pool server:
|
||||
SERVER=europe.pool.ntp.org
|
||||
|
||||
The available tooltypes are the same as the available command line
|
||||
parameters.
|
||||
The available tooltypes are the same as the available command
|
||||
line parameters.
|
||||
|
||||
@{b}Parameter@{ub} | @{b}Short description@{ub}
|
||||
-------------------------------------------------
|
||||
-----------------------------------------------------------
|
||||
SERVER | NTP server Address
|
||||
PORT | NTP server Port
|
||||
THRESHOLD | Adjustment threshold
|
||||
@@ -180,6 +232,13 @@ CX_PRIORITY | Commodity priority
|
||||
READONLY | Do not set clock
|
||||
EXPERT | Show advanced options
|
||||
TIMEOUT | Connection Timeout
|
||||
ACTIVE | Automatically start time synchronization
|
||||
NOLOG | deactivate logger facility
|
||||
TZD | Time zone display mode i settings window
|
||||
TZ | Optional TZ POSIX string
|
||||
TZVALUE | Optional time zone value
|
||||
TZNAME | Optional time zone abbreviation
|
||||
TZDST | Optionally force day light saving time
|
||||
|
||||
@{b}Caveats@{ub}
|
||||
|
||||
@@ -187,50 +246,90 @@ Settings can be overridden and are set in the following order:
|
||||
1. Preference file
|
||||
2. Icon tooltypes / CLI parameters
|
||||
|
||||
CLI parameters and icon tooltypes has highest precedence and will
|
||||
always override settings 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.
|
||||
|
||||
When using WBStartup folder or a similar system, remember to add the
|
||||
mandatory tooltype DONOTWAIT. Otherwise the startup execution will be
|
||||
blocked.
|
||||
When using WBStartup folder or a similar system, remember to add
|
||||
the mandatory tool type DONOTWAIT. Otherwise the startup execution
|
||||
will be blocked.
|
||||
|
||||
@EndNode
|
||||
|
||||
@Node "Local time zone" "TimeKeeper.guide/Local time zone"
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
@Prev "Using tooltypes of an icon"
|
||||
@Next "Saving preferences"
|
||||
|
||||
@{b}Selecting time zone@{ub}
|
||||
|
||||
The local time zone is selected from 5 different options, in
|
||||
the following order:
|
||||
1. TZVALUE setting
|
||||
2. TZ setting
|
||||
3. Global TZ environment variable
|
||||
4. Global TZONE environment variable
|
||||
5. Workbench Locale Preferences
|
||||
|
||||
@{b}TZVALUE setting@{ub}
|
||||
The local time zone value setting is available from CLI, icon
|
||||
tool types and ARexx. The value is specified in hours and minutes
|
||||
from GMT or UTC. One hour ahead is equal to 100. One hour
|
||||
behind is equal to -100.
|
||||
|
||||
@{b}TZ setting@{ub}
|
||||
The TZ setting is available from CLI, icon tool types and ARexx.
|
||||
|
||||
@{b}Global TZ environment variable@{ub}
|
||||
The Amiga DOS global environment variable TZ containing a POSIX
|
||||
TZ compliant string.
|
||||
|
||||
@{b}Global TZONE environment variable@{ub}
|
||||
The Amiga DOS environment global variable TZONE containing a
|
||||
POSIX TZ compliant string.
|
||||
|
||||
@{b}Workbench Locale Preferences@{ub}
|
||||
Amiga OS / Workbench Locale Preferences Editor
|
||||
|
||||
@EndNode
|
||||
|
||||
@Node "Saving preferences" "TimeKeeper.guide/Saving preferences"
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
@Prev "Using tooltypes of an icon"
|
||||
@Prev "Local time zone"
|
||||
@Next "ARexx interface"
|
||||
|
||||
Preferences from the setting window are saved in the file
|
||||
ENV:timekeeper.prefs
|
||||
Preferences are saved in the file
|
||||
ENV:AmiTimeKeeper/timekeeper.prefs
|
||||
|
||||
Preferences are also persisted between reboots in the file
|
||||
ENVARC:timekeeper.prefs
|
||||
ENVARC:AmiTimeKeeper/timekeeper.prefs
|
||||
|
||||
Depending on the setup the content of timekeeper.prefs could be:
|
||||
|
||||
CX_POPUP=NO
|
||||
CX_POPKEY=lshift control t
|
||||
CX_PRIORITY=25
|
||||
CX_PRIORITY=5
|
||||
THRESHOLD=1000000
|
||||
SERVER=de.pool.ntp.org
|
||||
PORT=123
|
||||
TIMEOUT=5000
|
||||
TIMEOUT=1000
|
||||
INTERVAL=17500
|
||||
READONLY=NO
|
||||
EXPERT=NO
|
||||
ACTIVE=YES
|
||||
NOLOG=YES
|
||||
|
||||
The preference file should not be edited under normal circumstances.
|
||||
|
||||
@{b}Caveats@{ub}
|
||||
|
||||
Not only visible settings in the settings window are saved to the
|
||||
preference file. All setting are saved includes default settings and
|
||||
settings from CLI and icon tooltypes.
|
||||
preference file. All setting are saved includes default settings
|
||||
and settings from CLI and icon tooltypes.
|
||||
|
||||
@EndNode
|
||||
|
||||
@@ -238,7 +337,7 @@ settings from CLI and icon tooltypes.
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
@Prev "Saving preferences"
|
||||
@Next "The POSIX TZ environment variable"
|
||||
@Next "POSIX TZ environment variable"
|
||||
|
||||
TimeKeeper provides an ARexx port with a diverse set of commands.
|
||||
The ARexx address is 'TIMEKEEPER.1'.
|
||||
@@ -251,17 +350,77 @@ HELP | Get a list of ARexx commands and a short description
|
||||
STATUS | Get current synchronization status
|
||||
TIMEZONE | Get current time zone
|
||||
LASTSYNC | Get time of last synchronization operation
|
||||
LASTAD | Get time of last clock adjustment
|
||||
LASTADJ | Get time of last clock adjustment
|
||||
GET | Get a runtime configuration value
|
||||
SET | Set a runtime configuration value
|
||||
NOW | Get current time and date
|
||||
SHOW | Show settings window
|
||||
HIDE | Hide settings window
|
||||
START | Start the time synchronization process
|
||||
STOP | Stop the time synchronization process
|
||||
SHUTDOWN | Shutdown TimeKeeper
|
||||
LOGTRANS | Emit time zone transition map to log
|
||||
-----------------------------------------------------------------
|
||||
|
||||
@{b}Examples@{ub}
|
||||
@{b}Parameters@{ub}
|
||||
STATUS accepts NUMBER as parameter. Result is instead formatted
|
||||
as binary value.
|
||||
|
||||
TIMEZONE accepts a code as parameter. The code determines how
|
||||
the result is formatted:
|
||||
1 Seconds ahead of UTC (+[s])
|
||||
2 Minutes ahead of UTC (+[m])
|
||||
3 TZ style long format (UTC-[hh]:[mm])
|
||||
4 TZ style short format (-[hh]:[mm])
|
||||
5 ISO 8601 style (+[hh][mm])
|
||||
6 ISO 8601 style (+[hh]:[mm])
|
||||
7 ISO 8601 short style (+[h])
|
||||
8 Common identifier (GMT+[hh]:[mm])
|
||||
9 Common identifier, offset with name in parens
|
||||
10 Common identifier, name with offset in parens
|
||||
11 Standard time zone
|
||||
12 DST time zone
|
||||
|
||||
NOW, LASTSYNC and LASTADJ accepts DOS, ASCII, DATE, TIME, RFC850,
|
||||
RFC1123, RFC2822, RFC3339 or ISO8601 as first parameter. DOS is
|
||||
assumed if parameter is not specified.
|
||||
DOS AmigaDOS style
|
||||
ASCII C ASCII style
|
||||
DATE ARexx formatted as sorted date
|
||||
TIME Time in seconds since midnight
|
||||
|
||||
LOCAL and UTC are accepted as second parameter. LOCAL is assumed
|
||||
if second parameter is not specified. RFC850 and RFC1123 are always
|
||||
GMT.
|
||||
|
||||
GET accepts SERVER, PORT, THRESHOLD, INTERVAL, CX_PRIORITY,
|
||||
CX_POPKEY, CX_POPUP, READONLY, EXPERT, TIMEOUT, ACTIVE, NOLOG,
|
||||
TZD, TZ, TZNAME, TZVALUE and TZDST as parameter. CX_POPUP,
|
||||
READONLY, EXPERT, ACTIVE and NOLOG accepts NUMBER as parameter.
|
||||
|
||||
SET accepts the same parameters as GET, except CX_POPKEY, and an
|
||||
addition value parameter.
|
||||
|
||||
ID, VERSION, HELP, SHOW, HIDE, START, STOP, SHUTDOWN and LOGTRANS
|
||||
does not accept parameters.
|
||||
|
||||
@{b}Error handling@{ub}
|
||||
|
||||
The local variables TIMEKEEPER.ERRORCODE and TIMEKEEPER.ERRORTEXT
|
||||
are set on each call too ARexx.
|
||||
|
||||
There is a number of possible error codes.
|
||||
0 No errors
|
||||
10 Unknown ARexx command
|
||||
11 Unknown parameter
|
||||
12 Parameter is missing
|
||||
13 Invalid parameter value
|
||||
18 Clock has not been adjusted
|
||||
19 No responses from NTP server
|
||||
20 Synchronization is already active
|
||||
21 Synchronization is already deactivated
|
||||
|
||||
@{b}ARexx examples@{ub}
|
||||
Stop the the time synchronization process with:
|
||||
@{"Address TIMEKEEPER.1 stop" rxs "Address TIMEKEEPER.1 stop"}
|
||||
|
||||
@@ -276,13 +435,15 @@ The arexx folder contains a set of sample scripts.
|
||||
@{b}TimeCtrl@{ub}
|
||||
|
||||
Controlling TimeKeeper without using ARexx is done through the
|
||||
control utility TimeCtrl. The following commands are available.
|
||||
control utility @{i}TimeCtrl@{ui}. The following commands are available.
|
||||
|
||||
@{b}Command@{ub} | @{b}Description@{ub}
|
||||
-----------------------------------------------------------------
|
||||
ID | Get application identifier
|
||||
VERSION | Get application version number
|
||||
STATUS | Get current synchronization status
|
||||
TIME | Get current time and date
|
||||
ZONE | Get current time zone
|
||||
START | Start the time synchronization process
|
||||
STOP | Stop the time synchronization process
|
||||
SHOW | Show settings window
|
||||
@@ -292,23 +453,24 @@ SHUTDOWN | Shutdown TimeKeeper
|
||||
|
||||
@EndNode
|
||||
|
||||
@Node "The POSIX TZ environment variable" "TimeKeeper.guide/The POSIX TZ environment variable"
|
||||
@Node "POSIX TZ environment variable" "TimeKeeper.guide/POSIX TZ environment variable"
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
@Prev "ARexx interface"
|
||||
@Next "Change Log"
|
||||
|
||||
This is a list of time zone information for locations around the globe.
|
||||
Information is represented in the POSIX TZ environment variable format.
|
||||
The list originates from the IANA time zone database version 2019b.
|
||||
This is a list of time zone information for locations around the
|
||||
globe. Information is represented in the POSIX TZ environment
|
||||
variable format. The list originates from the IANA time zone
|
||||
database version 2019b.
|
||||
|
||||
A formal definition of the POSIX TZ environment variable is available
|
||||
to the public from The GNU C Library Reference Manual and The Open Group
|
||||
Library.
|
||||
A formal definition of the POSIX TZ environment variable is
|
||||
available to the public from The GNU C Library Reference Manual
|
||||
and The Open Group Library.
|
||||
|
||||
The POSIX TZ environment variable is described in dept by for example
|
||||
The Open Group Base Specifications Issue 7, 2018 edition and The GNU C
|
||||
Library Reference Manual.
|
||||
The POSIX TZ environment variable is described in dept by for
|
||||
example The Open Group Base Specifications Issue 7, 2018 edition
|
||||
and The GNU C Library Reference Manual.
|
||||
|
||||
Set the TZ environment variable to Central Europe Time:
|
||||
> SETENV TZ CET-1
|
||||
@@ -753,6 +915,17 @@ Pacific/Wallis TZ <GMT+12>-12
|
||||
@Prev "Saving preferences"
|
||||
@Next "Software License"
|
||||
|
||||
@{b}v1.12 31.01.2021@{ub}
|
||||
- New options to specify the local time zone
|
||||
- New ARexx commands, parameters and error variables
|
||||
- New option to start without active time synchronization
|
||||
- New deactivate logging option for performance saving
|
||||
- More bugs in calculation of time zone transition fixed
|
||||
- Sanity check on value for interval between requests
|
||||
- Updated ARexx documentation and script
|
||||
- Honour ARexx result flag (RXFF_RESULT)
|
||||
- Various minor bug fixes and improvements
|
||||
|
||||
@{b}v1.11 11.01.2021@{ub}
|
||||
- New dedicated external control utility
|
||||
- New ARexx port with a diverse set of commands
|
||||
@@ -833,6 +1006,11 @@ Pacific/Wallis TZ <GMT+12>-12
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
|
||||
@{b}Bug reports@{ub}
|
||||
|
||||
Please report bugs and other issues by sending a mail or using:
|
||||
https://ranger.innolan.net/rainlance/AmiTimeKeeper
|
||||
|
||||
@{b}Simplified BSD License / 2-clause BSD license@{ub}
|
||||
|
||||
Copyright (c) 2001, 02 Motoyuki Kasahara
|
||||
@@ -869,17 +1047,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@Toc "Main"
|
||||
@Index "Index"
|
||||
|
||||
A custom version has been integrated into the Icaros Desktop system.
|
||||
The author encourages all developers with an interest to make their own
|
||||
build.
|
||||
|
||||
The following people have contributed with bug reports, comments,
|
||||
suggestions and donations:
|
||||
|
||||
* aPEX from a1k.org
|
||||
* Greg Donner
|
||||
* Paolo Besser
|
||||
* Knut Hansen
|
||||
* Greg Donner
|
||||
* Thomas Blatt
|
||||
* Bartosz Makara
|
||||
* Benny Damsgaard
|
||||
@@ -911,52 +1085,136 @@ January 2021
|
||||
|
||||
@{b}A@{ub}
|
||||
|
||||
@{"ARexx interface" Link "ARexx interface"}
|
||||
@{"Adjustment threshold" Link "Configuring the client" 40 }
|
||||
@{"ARexx interface" Link "ARexx interface" 1 }
|
||||
@{"Automatically synchronization" Link "Configuring the client" 84 }
|
||||
|
||||
@{b}C@{ub}
|
||||
|
||||
@{"Configution" Link "Configuring the client"}
|
||||
@{"CLI" Link "Using tooltypes of an icon"}
|
||||
@{"Configution" Link "Configuring the client" 1 }
|
||||
@{"Connection time out" Link "Configuring the client" 70 }
|
||||
@{"CLI" Link "Using tooltypes of an icon" 7 }
|
||||
|
||||
@{b}D@{ub}
|
||||
|
||||
@{"Daylight saving time" Link "Configuring the client" 113 }
|
||||
|
||||
@{b}E@{ub}
|
||||
|
||||
@{"Environment variable" Link "Local time zone" 20 }
|
||||
@{"Expert mode" Link "Configuring the client" 63 }
|
||||
|
||||
@{b}I@{ub}
|
||||
|
||||
@{"Interval between requests" Link "Configuring the client" 27 }
|
||||
@{"ISO8601" Link "ARexx interface" 44 }
|
||||
|
||||
@{b}K@{ub}
|
||||
|
||||
@{"Keywords" Link "ARexx" 1 }
|
||||
@{"ACTIVE - Automatically synchronization" Link "Configuring the client" 84 }
|
||||
@{"ASCII" Link "ARexx interface" 44 }
|
||||
@{"CX_POPKEY" Link "Using tooltypes of an icon" 17 }
|
||||
@{"CX_POPUP" Link "Using tooltypes of an icon" 16 }
|
||||
@{"CX_PRIORITY" Link "Using tooltypes of an icon" 18 }
|
||||
@{"DATE" Link "ARexx interface" 44 }
|
||||
@{"DONOTWAIT" Link "Using tooltypes of an icon" 42 }
|
||||
@{"DOS" Link "ARexx interface" 44 }
|
||||
@{"DST - Daylight saving time" Link "Configuring the client" 113 }
|
||||
@{"EXPERT - Expert mode" Link "Configuring the client" 63 }
|
||||
@{"INTERVAL - Interval between requests" Link "Configuring the client" 27 }
|
||||
@{"ISO8601" Link "ARexx interface" 44 }
|
||||
@{"LOCAL" Link "ARexx interface" 52 }
|
||||
@{"NOLOG - Logging" Link "Configuring the client" 79 }
|
||||
@{"NUMBER" Link "ARexx interface" 56 }
|
||||
@{"POPUP" Link "Configuring the client"}
|
||||
@{"PORT - Server port" Link "Configuring the client" 22 }
|
||||
@{"READONLY" Link "Configuring the client" 57 }
|
||||
@{"RFC850" Link "ARexx interface" 44 }
|
||||
@{"RFC1123" Link "ARexx interface" 44 }
|
||||
@{"RFC2822" Link "ARexx interface" 44 }
|
||||
@{"RFC3339" Link "ARexx interface" 44 }
|
||||
@{"SERVER - Server address" Link "Configuring the client" 1 }
|
||||
@{"THRESHOLD - Adjustment threshold" Link "Configuring the client" 40 }
|
||||
@{"TIME" Link "ARexx interface" 44 }
|
||||
@{"TIMEOUT - Connection time out" Link "Configuring the client" 70 }
|
||||
@{"TIMEZONE - Time zone" Link "Configuring the client" 97 }
|
||||
@{"TIMEZONEABBREVIATION - Time zone abbreviation" Link "Configuring the client" 104 }
|
||||
@{"TIMEZONEDISPLAY - Time zone display" Link "Configuring the client" 90 }
|
||||
@{"TIMEZONEVALUE - Time zone value" Link "Configuring the client" 109 }
|
||||
@{"TZ - Time zone" Link "Configuring the client" 97 }
|
||||
@{"TZD - Time zone display" Link "Configuring the client" 90 }
|
||||
@{"TZDST - Daylight saving time" Link "Configuring the client" 113 }
|
||||
@{"TZNAME - Time zone abbreviation" Link "Configuring the client" 104 }
|
||||
@{"TZVALUE - Time zone value" Link "Configuring the client" 109 }
|
||||
@{"UTC" Link "ARexx interface" 52 }
|
||||
|
||||
@{b}L@{ub}
|
||||
|
||||
@{"Logging" Link "Configuring the client"}
|
||||
@{"Logging" Link "Configuring the client" 79 }
|
||||
|
||||
@{b}N@{ub}
|
||||
|
||||
@{"Network Time Foundation" Link "Configuring the client"}
|
||||
@{"Network Time Foundation" Link "Configuring the client" 4 }
|
||||
|
||||
@{b}P@{ub}
|
||||
|
||||
@{"Pool servers" Link "Configuring the client"}
|
||||
@{"Posix" Link "The POSIX TZ environment variable"}
|
||||
@{"Preferences" Link "Saving preferences"}
|
||||
@{"Pool servers" Link "Configuring the client" 9 }
|
||||
@{"Popkey" Link "Using tooltypes of an icon" 17 }
|
||||
@{"Popup" Link "Using tooltypes of an icon" 16 }
|
||||
@{"Posix" Link "POSIX TZ environment variable" 1 }
|
||||
@{"Preferences" Link "Saving preferences" 1 }
|
||||
@{"Priority" Link "Using tooltypes of an icon" 18 }
|
||||
|
||||
@{b}R@{ub}
|
||||
|
||||
@{"Read only" Link "Configuring the client" 57 }
|
||||
@{"RFC850" Link "ARexx interface" 44 }
|
||||
@{"RFC1123" Link "ARexx interface" 44 }
|
||||
@{"RFC2822" Link "ARexx interface" 44 }
|
||||
@{"RFC3339" Link "ARexx interface" 44 }
|
||||
|
||||
@{b}S@{ub}
|
||||
|
||||
@{"Settings" Link "Configuring the client"}
|
||||
@{"Connection timeout" Link "Configuring the client"}
|
||||
@{"Expert mode " Link "Configuring the client"}
|
||||
@{"Interval" Link "Configuring the client"}
|
||||
@{"Logging" Link "Configuring the client"}
|
||||
@{"Popkey" Link "Configuring the client"}
|
||||
@{"Popup" Link "Configuring the client"}
|
||||
@{"Priority" Link "Configuring the client"}
|
||||
@{"Read only" Link "Configuring the client"}
|
||||
@{"Server address" Link "Configuring the client"}
|
||||
@{"Server port" Link "Configuring the client"}
|
||||
@{"Threshold" Link "Configuring the client"}
|
||||
@{"Standard time" Link "The POSIX TZ environment variable"}
|
||||
@{"Summer time" Link "The POSIX TZ environment variable"}
|
||||
@{"Server address" Link "Configuring the client" 1 }
|
||||
@{"Server port" Link "Configuring the client" 22 }
|
||||
@{"Settings" Link "Configuring the client" 1 }
|
||||
@{"Automatically synchronization" Link "Configuring the client" 84 }
|
||||
@{"Connection time out" Link "Configuring the client" 70}
|
||||
@{"Daylight saving time" Link "Configuring the client" 113 }
|
||||
@{"Expert mode " Link "Configuring the client" 63 }
|
||||
@{"Interval between requests" Link "Configuring the client" 27 }
|
||||
@{"Logging" Link "Configuring the client" 79 }
|
||||
@{"Popkey" Link "Using tooltypes of an icon" 17 }
|
||||
@{"Popup" Link "Using tooltypes of an icon" 16 }
|
||||
@{"Priority" Link "Using tooltypes of an icon" 18 }
|
||||
@{"Read only" Link "Configuring the client" 57 }
|
||||
@{"Server address" Link "Configuring the client" 1 }
|
||||
@{"Server port" Link "Configuring the client" 22 }
|
||||
@{"Threshold" Link "Configuring the client" 40 }
|
||||
@{"Time zone" Link "Configuring the client" 97 }
|
||||
@{"Time zone abbreviation" Link "Configuring the client" 104 }
|
||||
@{"Time zone display" Link "Configuring the client" 90 }
|
||||
@{"Time zone value" Link "Configuring the client" 109 }
|
||||
@{"Standard time" Link "Configuring the client" 113 }
|
||||
@{"Startup Sequence" Link "Configuring the client" 120 }
|
||||
@{"Summer time" Link "Configuring the client" 113 }
|
||||
|
||||
@{b}T@{ub}
|
||||
|
||||
@{"TimeCtrl" Link "ARexx interface"}
|
||||
@{"TimeLogger" Link "Configuring the client"}
|
||||
@{"Time zone" Link "Main"}
|
||||
@{"Getting" Link "ARexx interface"}
|
||||
@{"Setting" Link "Main"}
|
||||
@{"Tool types" Link "Using tooltypes of an icon"}
|
||||
@{"TZ" Link "The POSIX TZ environment variable"}
|
||||
@{"Threshold" Link "Configuring the client" 40 }
|
||||
@{"TimeCtrl" Link "ARexx interface" 95 }
|
||||
@{"TimeLogger" Link "Configuring the client" 81 }
|
||||
@{"Time zone" Link "Local time zone" 1 }
|
||||
@{"Getting" Link "ARexx interface" 29 }
|
||||
@{"Setting" Link "Local time zone" 1 }
|
||||
@{"Time zone abbreviation" Link "Configuring the client" 104 }
|
||||
@{"Time zone display" Link "Configuring the client" 90 }
|
||||
@{"Time zone value" Link "Local time zone" 109 }
|
||||
@{"Tool types" Link "Using tooltypes of an icon" 1 }
|
||||
@{"TZ" Link "Local time zone" 18 }
|
||||
@{"Content" Link "POSIX TZ environment variable" 7 }
|
||||
@{"Setting" Link "Local time zone" 1 }
|
||||
@{"TZONE" Link "Local time zone" 25 }
|
||||
|
||||
@EndNode
|
||||
|
||||
+353
-96
@@ -9,36 +9,39 @@
|
||||
<p><a>Contents</a> <a href="#index">Index</a> <a>Help</a> <a>Prev</a> <a href="#configuring+the+client">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
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.
|
||||
|
||||
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. A utility
|
||||
for small tasks like starting and stopping is also included.
|
||||
Comprehensive control is possible using ARexx.
|
||||
either directly from the command line or by using the tool types
|
||||
of an icon. Preferences can also be saved between reboots.
|
||||
A utility for small tasks like starting and stopping is also
|
||||
included. Comprehensive control is possible using ARexx.
|
||||
|
||||
|
||||
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. Use a fixed pool server by prefixing the domain, for example,
|
||||
1.pool.ntp.org.
|
||||
try visiting support.ntp.org or one of the other sites listing
|
||||
time servers. Use a fixed pool server by prefixing the domain,
|
||||
for example, 1.pool.ntp.org.
|
||||
|
||||
The local time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. In AmigaOS 3.1 and 3.9 this is available through
|
||||
the Locale Preferences Editor. Daylight saving time is only supported
|
||||
through the POSIX TZ environment variable.
|
||||
|
||||
This version (1.11) has two known issues:
|
||||
- Settings window in AROS is broken (and disabled in this version)
|
||||
- Setting Popkey is not supported in ARexx
|
||||
The time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. In Amiga OS this is available through the
|
||||
Locale Preferences Editor. The local time zone and daylight saving
|
||||
time are optionally specified manually or using a POSIX TZ
|
||||
variable style.
|
||||
|
||||
|
||||
<a href="#configuring+the+client">Configuring the client</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Using tooltypes of an icon</a>
|
||||
<a href="#local+time+zone">Local time zone</a>
|
||||
<a href="#saving+preferences">Saving preferences</a>
|
||||
<a href="#arexx+interface">ARexx interface</a>
|
||||
<a href="#the+posix+tz+environment+variable">The POSIX TZ environment variable</a>
|
||||
<a href="#posix+tz+environment+variable">POSIX TZ environment variable</a>
|
||||
<a href="#change+log">Change Log / Change History</a>
|
||||
<a href="#software+license">Software License</a>
|
||||
<a href="#credits+and+donations">Credits and donations</a>
|
||||
@@ -80,53 +83,101 @@ is the NTP server port different from 123.
|
||||
<b>Interval between requests</b>
|
||||
|
||||
The Amiga hardware clock will slowly drift away from true time. The
|
||||
drift is determined by several factors and is small, but the drift is not
|
||||
insignificant. Request are repeatedly sent to the NTP server in order to
|
||||
keep the Amiga hardware clock as close to true time as possible.
|
||||
drift is determined by several factors and is small, but the drift
|
||||
is not insignificant. Request are repeatedly sent to the NTP server
|
||||
in order to keep the Amiga hardware clock as close to true time as
|
||||
possible.
|
||||
|
||||
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.
|
||||
thousand (1.000) milliseconds are equal to one second. The max value
|
||||
is 172.800.000 equal to 48 hours.
|
||||
|
||||
<b>Adjustment threshold</b>
|
||||
|
||||
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
|
||||
server. Processing the response could take longer time than anticipated.
|
||||
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.
|
||||
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 server. Processing the response could take longer time
|
||||
than anticipated. The amount of accepted inaccuracy is set using the
|
||||
threshold parameter. The threshold should be specified using micro-
|
||||
seconds. One million microseconds (1.000.000) are equal to one
|
||||
second.
|
||||
|
||||
<b>Start with synchronization active</b>
|
||||
|
||||
Maybe some related settings or the network connection are not ready
|
||||
from the beginning. The commodity can then be started in a preparation
|
||||
mode. Activation is possible from within AmigaOS, through the control
|
||||
utility <i>TimeCtrl</i>, or through the ARexx interface.
|
||||
|
||||
<b>Read only</b>
|
||||
|
||||
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.
|
||||
Amiga hardware clock. This option can be handy when debugging time
|
||||
zone setup and other time related parameters.
|
||||
|
||||
<b>Expert mode</b>
|
||||
|
||||
Advanced settings are hidden from the settings window when expert mode
|
||||
is not enabled. The advanced settings are server port, interval between
|
||||
requests, adjustment threshold, connection timeout, verbosity level and
|
||||
commodity priority.
|
||||
Advanced settings are hidden from the settings window 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</b>
|
||||
<b>Connection time out</b>
|
||||
|
||||
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
|
||||
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.
|
||||
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 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. The max value is half
|
||||
of the value of interval between requests.
|
||||
|
||||
<b>Logging</b>
|
||||
|
||||
It is possible view log messages using the supplied tool TimeLogger.
|
||||
It is possible view log messages using the supplied tool <i>TimeLogger</i>.
|
||||
The logger facility can be turned off with the NOLOG switch.
|
||||
|
||||
<b>Automatically synchronization</b>
|
||||
|
||||
Sometimes it is feasible to start without synchronization. The clock
|
||||
is synchronized in the background, only when synchronization is
|
||||
active. By default synchronization is not active.
|
||||
|
||||
<b>Time zone display</b>
|
||||
|
||||
Different options for displaying the current time zone exists. The
|
||||
most common is a combination of time zone name and time zone offset
|
||||
from GMT. The ARexx documentation describes the time zone display
|
||||
methods in details.
|
||||
|
||||
<b>Time zone</b>
|
||||
|
||||
If the local time zone is expressed as a POSIX TZ compatible string,
|
||||
an optional setting is available.
|
||||
|
||||
<b>Time zone value</b>
|
||||
|
||||
The most simple way to expressed the local time zone is in hours
|
||||
and minutes from Greenwich Mean Time (GMT) or UTC. One hour ahead
|
||||
is equal to 100. One hour behind is equal to -100. Two and a half
|
||||
hour ahead is equal to 230.
|
||||
|
||||
<b>Time zone abbreviation</b>
|
||||
|
||||
If no name is given for the local time zone, the time zone is shown
|
||||
as hours and minutes from Greenwich Mean Time (GMT). It is possible
|
||||
to specify a time zone abbreviation for better readability.
|
||||
|
||||
<b>Daylight saving time</b>
|
||||
|
||||
Sometimes is feasible to force a standard one hour ahead daylight
|
||||
saving time (DST). Use this option if needed.
|
||||
|
||||
<b>Caveats</b>
|
||||
|
||||
TimeKeeper does not start as a background process. When started in the
|
||||
startup-sequence it will by default block execution. Use the run command
|
||||
to avoid this behaviour:
|
||||
TimeKeeper does not start as a background process. When started in
|
||||
the startup-sequence it will by default block execution. Use the run
|
||||
command to avoid this behaviour:
|
||||
> RUN >NIL: TimeKeeper
|
||||
|
||||
</pre>
|
||||
@@ -134,19 +185,19 @@ to avoid this behaviour:
|
||||
<div id="using+tooltypes+of+an+icon">
|
||||
<hr/>
|
||||
<p><b>TimeKeeper.guide/Using tooltypes of an icon</b></p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#configuring+the+client">Prev</a> <a href="#saving+preferences">Next</a> </p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#configuring+the+client">Prev</a> <a href="#local+time+zone">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
Settings can be changes by setting tooltypes in the TimeKeeper icon.
|
||||
Add the following line to the icon tooltypes in order to set the server
|
||||
to an European pool server:
|
||||
Settings can be changes by setting tooltypes in the TimeKeeper
|
||||
icon. Add the following line to the icon tooltypes in order to
|
||||
set the server to an European pool server:
|
||||
SERVER=europe.pool.ntp.org
|
||||
|
||||
The available tooltypes are the same as the available command line
|
||||
parameters.
|
||||
The available tooltypes are the same as the available command
|
||||
line parameters.
|
||||
|
||||
<b>Parameter</b> | <b>Short description</b>
|
||||
-------------------------------------------------
|
||||
-----------------------------------------------------------
|
||||
SERVER | NTP server Address
|
||||
PORT | NTP server Port
|
||||
THRESHOLD | Adjustment threshold
|
||||
@@ -157,6 +208,13 @@ CX_PRIORITY | Commodity priority
|
||||
READONLY | Do not set clock
|
||||
EXPERT | Show advanced options
|
||||
TIMEOUT | Connection Timeout
|
||||
ACTIVE | Automatically start time synchronization
|
||||
NOLOG | deactivate logger facility
|
||||
TZD | Time zone display mode i settings window
|
||||
TZ | Optional TZ POSIX string
|
||||
TZVALUE | Optional time zone value
|
||||
TZNAME | Optional time zone abbreviation
|
||||
TZDST | Optionally force day light saving time
|
||||
|
||||
<b>Caveats</b>
|
||||
|
||||
@@ -164,57 +222,97 @@ Settings can be overridden and are set in the following order:
|
||||
1. Preference file
|
||||
2. Icon tooltypes / CLI parameters
|
||||
|
||||
CLI parameters and icon tooltypes has highest precedence and will
|
||||
always override settings 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.
|
||||
|
||||
When using WBStartup folder or a similar system, remember to add the
|
||||
mandatory tooltype DONOTWAIT. Otherwise the startup execution will be
|
||||
blocked.
|
||||
When using WBStartup folder or a similar system, remember to add
|
||||
the mandatory tool type DONOTWAIT. Otherwise the startup execution
|
||||
will be blocked.
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
<div id="local+time+zone">
|
||||
<hr/>
|
||||
<p><b>TimeKeeper.guide/Local time zone</b></p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#using+tooltypes+of+an+icon">Prev</a> <a href="#saving+preferences">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
<b>Selecting time zone</b>
|
||||
|
||||
The local time zone is selected from 5 different options, in
|
||||
the following order:
|
||||
1. TZVALUE setting
|
||||
2. TZ setting
|
||||
3. Global TZ environment variable
|
||||
4. Global TZONE environment variable
|
||||
5. Workbench Locale Preferences
|
||||
|
||||
<b>TZVALUE setting</b>
|
||||
The local time zone value setting is available from CLI, icon
|
||||
tool types and ARexx. The value is specified in hours and minutes
|
||||
from GMT or UTC. One hour ahead is equal to 100. One hour
|
||||
behind is equal to -100.
|
||||
|
||||
<b>TZ setting</b>
|
||||
The TZ setting is available from CLI, icon tool types and ARexx.
|
||||
|
||||
<b>Global TZ environment variable</b>
|
||||
The Amiga DOS global environment variable TZ containing a POSIX
|
||||
TZ compliant string.
|
||||
|
||||
<b>Global TZONE environment variable</b>
|
||||
The Amiga DOS environment global variable TZONE containing a
|
||||
POSIX TZ compliant string.
|
||||
|
||||
<b>Workbench Locale Preferences</b>
|
||||
Amiga OS / Workbench Locale Preferences Editor
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
<div id="saving+preferences">
|
||||
<hr/>
|
||||
<p><b>TimeKeeper.guide/Saving preferences</b></p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#using+tooltypes+of+an+icon">Prev</a> <a href="#arexx+interface">Next</a> </p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#local+time+zone">Prev</a> <a href="#arexx+interface">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
Preferences from the setting window are saved in the file
|
||||
ENV:timekeeper.prefs
|
||||
Preferences are saved in the file
|
||||
ENV:AmiTimeKeeper/timekeeper.prefs
|
||||
|
||||
Preferences are also persisted between reboots in the file
|
||||
ENVARC:timekeeper.prefs
|
||||
ENVARC:AmiTimeKeeper/timekeeper.prefs
|
||||
|
||||
Depending on the setup the content of timekeeper.prefs could be:
|
||||
|
||||
CX_POPUP=NO
|
||||
CX_POPKEY=lshift control t
|
||||
CX_PRIORITY=25
|
||||
CX_PRIORITY=5
|
||||
THRESHOLD=1000000
|
||||
SERVER=de.pool.ntp.org
|
||||
PORT=123
|
||||
TIMEOUT=5000
|
||||
TIMEOUT=1000
|
||||
INTERVAL=17500
|
||||
READONLY=NO
|
||||
EXPERT=NO
|
||||
ACTIVE=YES
|
||||
NOLOG=YES
|
||||
|
||||
The preference file should not be edited under normal circumstances.
|
||||
|
||||
<b>Caveats</b>
|
||||
|
||||
Not only visible settings in the settings window are saved to the
|
||||
preference file. All setting are saved includes default settings and
|
||||
settings from CLI and icon tooltypes.
|
||||
preference file. All setting are saved includes default settings
|
||||
and settings from CLI and icon tooltypes.
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
<div id="arexx+interface">
|
||||
<hr/>
|
||||
<p><b>TimeKeeper.guide/ARexx interface</b></p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#saving+preferences">Prev</a> <a href="#the+posix+tz+environment+variable">Next</a> </p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#saving+preferences">Prev</a> <a href="#posix+tz+environment+variable">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
TimeKeeper provides an ARexx port with a diverse set of commands.
|
||||
@@ -228,17 +326,77 @@ HELP | Get a list of ARexx commands and a short description
|
||||
STATUS | Get current synchronization status
|
||||
TIMEZONE | Get current time zone
|
||||
LASTSYNC | Get time of last synchronization operation
|
||||
LASTAD | Get time of last clock adjustment
|
||||
LASTADJ | Get time of last clock adjustment
|
||||
GET | Get a runtime configuration value
|
||||
SET | Set a runtime configuration value
|
||||
NOW | Get current time and date
|
||||
SHOW | Show settings window
|
||||
HIDE | Hide settings window
|
||||
START | Start the time synchronization process
|
||||
STOP | Stop the time synchronization process
|
||||
SHUTDOWN | Shutdown TimeKeeper
|
||||
LOGTRANS | Emit time zone transition map to log
|
||||
-----------------------------------------------------------------
|
||||
|
||||
<b>Examples</b>
|
||||
<b>Parameters</b>
|
||||
STATUS accepts NUMBER as parameter. Result is instead formatted
|
||||
as binary value.
|
||||
|
||||
TIMEZONE accepts a code as parameter. The code determines how
|
||||
the result is formatted:
|
||||
1 Seconds ahead of UTC (+[s])
|
||||
2 Minutes ahead of UTC (+[m])
|
||||
3 TZ style long format (UTC-[hh]:[mm])
|
||||
4 TZ style short format (-[hh]:[mm])
|
||||
5 ISO 8601 style (+[hh][mm])
|
||||
6 ISO 8601 style (+[hh]:[mm])
|
||||
7 ISO 8601 short style (+[h])
|
||||
8 Common identifier (GMT+[hh]:[mm])
|
||||
9 Common identifier, offset with name in parens
|
||||
10 Common identifier, name with offset in parens
|
||||
11 Standard time zone
|
||||
12 DST time zone
|
||||
|
||||
NOW, LASTSYNC and LASTADJ accepts DOS, ASCII, DATE, TIME, RFC850,
|
||||
RFC1123, RFC2822, RFC3339 or ISO8601 as first parameter. DOS is
|
||||
assumed if parameter is not specified.
|
||||
DOS AmigaDOS style
|
||||
ASCII C ASCII style
|
||||
DATE ARexx formatted as sorted date
|
||||
TIME Time in seconds since midnight
|
||||
|
||||
LOCAL and UTC are accepted as second parameter. LOCAL is assumed
|
||||
if second parameter is not specified. RFC850 and RFC1123 are always
|
||||
GMT.
|
||||
|
||||
GET accepts SERVER, PORT, THRESHOLD, INTERVAL, CX_PRIORITY,
|
||||
CX_POPKEY, CX_POPUP, READONLY, EXPERT, TIMEOUT, ACTIVE, NOLOG,
|
||||
TZD, TZ, TZNAME, TZVALUE and TZDST as parameter. CX_POPUP,
|
||||
READONLY, EXPERT, ACTIVE and NOLOG accepts NUMBER as parameter.
|
||||
|
||||
SET accepts the same parameters as GET, except CX_POPKEY, and an
|
||||
addition value parameter.
|
||||
|
||||
ID, VERSION, HELP, SHOW, HIDE, START, STOP, SHUTDOWN and LOGTRANS
|
||||
does not accept parameters.
|
||||
|
||||
<b>Error handling</b>
|
||||
|
||||
The local variables TIMEKEEPER.ERRORCODE and TIMEKEEPER.ERRORTEXT
|
||||
are set on each call too ARexx.
|
||||
|
||||
There is a number of possible error codes.
|
||||
0 No errors
|
||||
10 Unknown ARexx command
|
||||
11 Unknown parameter
|
||||
12 Parameter is missing
|
||||
13 Invalid parameter value
|
||||
18 Clock has not been adjusted
|
||||
19 No responses from NTP server
|
||||
20 Synchronization is already active
|
||||
21 Synchronization is already deactivated
|
||||
|
||||
<b>ARexx examples</b>
|
||||
Stop the the time synchronization process with:
|
||||
Address TIMEKEEPER.1 stop
|
||||
|
||||
@@ -253,13 +411,15 @@ The arexx folder contains a set of sample scripts.
|
||||
<b>TimeCtrl</b>
|
||||
|
||||
Controlling TimeKeeper without using ARexx is done through the
|
||||
control utility TimeCtrl. The following commands are available.
|
||||
control utility <i>TimeCtrl</i>. The following commands are available.
|
||||
|
||||
<b>Command</b> | <b>Description</b>
|
||||
-----------------------------------------------------------------
|
||||
ID | Get application identifier
|
||||
VERSION | Get application version number
|
||||
STATUS | Get current synchronization status
|
||||
TIME | Get current time and date
|
||||
ZONE | Get current time zone
|
||||
START | Start the time synchronization process
|
||||
STOP | Stop the time synchronization process
|
||||
SHOW | Show settings window
|
||||
@@ -269,23 +429,24 @@ SHUTDOWN | Shutdown TimeKeeper
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
<div id="the+posix+tz+environment+variable">
|
||||
<div id="posix+tz+environment+variable">
|
||||
<hr/>
|
||||
<p><b>TimeKeeper.guide/The POSIX TZ environment variable</b></p>
|
||||
<p><b>TimeKeeper.guide/POSIX TZ environment variable</b></p>
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#arexx+interface">Prev</a> <a href="#change+log">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
This is a list of time zone information for locations around the globe.
|
||||
Information is represented in the POSIX TZ environment variable format.
|
||||
The list originates from the IANA time zone database version 2019b.
|
||||
This is a list of time zone information for locations around the
|
||||
globe. Information is represented in the POSIX TZ environment
|
||||
variable format. The list originates from the IANA time zone
|
||||
database version 2019b.
|
||||
|
||||
A formal definition of the POSIX TZ environment variable is available
|
||||
to the public from The GNU C Library Reference Manual and The Open Group
|
||||
Library.
|
||||
A formal definition of the POSIX TZ environment variable is
|
||||
available to the public from The GNU C Library Reference Manual
|
||||
and The Open Group Library.
|
||||
|
||||
The POSIX TZ environment variable is described in dept by for example
|
||||
The Open Group Base Specifications Issue 7, 2018 edition and The GNU C
|
||||
Library Reference Manual.
|
||||
The POSIX TZ environment variable is described in dept by for
|
||||
example The Open Group Base Specifications Issue 7, 2018 edition
|
||||
and The GNU C Library Reference Manual.
|
||||
|
||||
Set the TZ environment variable to Central Europe Time:
|
||||
> SETENV TZ CET-1
|
||||
@@ -730,6 +891,17 @@ Pacific/Wallis TZ <GMT+12>-12
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#saving+preferences">Prev</a> <a href="#software+license">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
<b>v1.12 31.01.2021</b>
|
||||
- New options to specify the local time zone
|
||||
- New ARexx commands, parameters and error variables
|
||||
- New option to start without active time synchronization
|
||||
- New deactivate logging option for performance saving
|
||||
- More bugs in calculation of time zone transition fixed
|
||||
- Sanity check on value for interval between requests
|
||||
- Updated ARexx documentation and script
|
||||
- Honour ARexx result flag (RXFF_RESULT)
|
||||
- Various minor bug fixes and improvements
|
||||
|
||||
<b>v1.11 11.01.2021</b>
|
||||
- New dedicated external control utility
|
||||
- New ARexx port with a diverse set of commands
|
||||
@@ -810,6 +982,11 @@ Pacific/Wallis TZ <GMT+12>-12
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#change+log">Prev</a> <a href="#credits+and+donations">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
<b>Bug reports</b>
|
||||
|
||||
Please report bugs and other issues by sending a mail or using:
|
||||
https://ranger.innolan.net/rainlance/AmiTimeKeeper
|
||||
|
||||
<b>Simplified BSD License / 2-clause BSD license</b>
|
||||
|
||||
Copyright (c) 2001, 02 Motoyuki Kasahara
|
||||
@@ -846,17 +1023,13 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
<p><a href="#main">Contents</a> <a href="#index">Index</a> <a>Help</a> <a href="#software+license">Prev</a> <a href="#contacting+the+author">Next</a> </p>
|
||||
<pre>
|
||||
|
||||
A custom version has been integrated into the Icaros Desktop system.
|
||||
The author encourages all developers with an interest to make their own
|
||||
build.
|
||||
|
||||
The following people have contributed with bug reports, comments,
|
||||
suggestions and donations:
|
||||
|
||||
* aPEX from a1k.org
|
||||
* Greg Donner
|
||||
* Paolo Besser
|
||||
* Knut Hansen
|
||||
* Greg Donner
|
||||
* Thomas Blatt
|
||||
* Bartosz Makara
|
||||
* Benny Damsgaard
|
||||
@@ -892,13 +1065,70 @@ January 2021
|
||||
|
||||
<b>A</b>
|
||||
|
||||
<a href="#configuring+the+client">Adjustment threshold</a>
|
||||
<a href="#arexx+interface">ARexx interface</a>
|
||||
<a href="#configuring+the+client">Automatically synchronization</a>
|
||||
|
||||
<b>C</b>
|
||||
|
||||
<a href="#configuring+the+client">Configution</a>
|
||||
<a href="#configuring+the+client">Connection time out</a>
|
||||
<a href="#using+tooltypes+of+an+icon">CLI</a>
|
||||
|
||||
<b>D</b>
|
||||
|
||||
<a href="#configuring+the+client">Daylight saving time</a>
|
||||
|
||||
<b>E</b>
|
||||
|
||||
<a href="#local+time+zone">Environment variable</a>
|
||||
<a href="#configuring+the+client">Expert mode</a>
|
||||
|
||||
<b>I</b>
|
||||
|
||||
<a href="#configuring+the+client">Interval between requests</a>
|
||||
<a href="#arexx+interface">ISO8601</a>
|
||||
|
||||
<b>K</b>
|
||||
|
||||
<a href="#arexx">Keywords</a>
|
||||
<a href="#configuring+the+client">ACTIVE - Automatically synchronization</a>
|
||||
<a href="#arexx+interface">ASCII</a>
|
||||
<a href="#using+tooltypes+of+an+icon">CX_POPKEY</a>
|
||||
<a href="#using+tooltypes+of+an+icon">CX_POPUP</a>
|
||||
<a href="#using+tooltypes+of+an+icon">CX_PRIORITY</a>
|
||||
<a href="#arexx+interface">DATE</a>
|
||||
<a href="#using+tooltypes+of+an+icon">DONOTWAIT</a>
|
||||
<a href="#arexx+interface">DOS</a>
|
||||
<a href="#configuring+the+client">DST - Daylight saving time</a>
|
||||
<a href="#configuring+the+client">EXPERT - Expert mode</a>
|
||||
<a href="#configuring+the+client">INTERVAL - Interval between requests</a>
|
||||
<a href="#arexx+interface">ISO8601</a>
|
||||
<a href="#arexx+interface">LOCAL</a>
|
||||
<a href="#configuring+the+client">NOLOG - Logging</a>
|
||||
<a href="#arexx+interface">NUMBER</a>
|
||||
<a href="#configuring+the+client">POPUP</a>
|
||||
<a href="#configuring+the+client">PORT - Server port</a>
|
||||
<a href="#configuring+the+client">READONLY</a>
|
||||
<a href="#arexx+interface">RFC850</a>
|
||||
<a href="#arexx+interface">RFC1123</a>
|
||||
<a href="#arexx+interface">RFC2822</a>
|
||||
<a href="#arexx+interface">RFC3339</a>
|
||||
<a href="#configuring+the+client">SERVER - Server address</a>
|
||||
<a href="#configuring+the+client">THRESHOLD - Adjustment threshold</a>
|
||||
<a href="#arexx+interface">TIME</a>
|
||||
<a href="#configuring+the+client">TIMEOUT - Connection time out</a>
|
||||
<a href="#configuring+the+client">TIMEZONE - Time zone</a>
|
||||
<a href="#configuring+the+client">TIMEZONEABBREVIATION - Time zone abbreviation</a>
|
||||
<a href="#configuring+the+client">TIMEZONEDISPLAY - Time zone display</a>
|
||||
<a href="#configuring+the+client">TIMEZONEVALUE - Time zone value</a>
|
||||
<a href="#configuring+the+client">TZ - Time zone</a>
|
||||
<a href="#configuring+the+client">TZD - Time zone display</a>
|
||||
<a href="#configuring+the+client">TZDST - Daylight saving time</a>
|
||||
<a href="#configuring+the+client">TZNAME - Time zone abbreviation</a>
|
||||
<a href="#configuring+the+client">TZVALUE - Time zone value</a>
|
||||
<a href="#arexx+interface">UTC</a>
|
||||
|
||||
<b>L</b>
|
||||
|
||||
<a href="#configuring+the+client">Logging</a>
|
||||
@@ -910,35 +1140,62 @@ January 2021
|
||||
<b>P</b>
|
||||
|
||||
<a href="#configuring+the+client">Pool servers</a>
|
||||
<a href="#the+posix+tz+environment+variable">Posix</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Popkey</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Popup</a>
|
||||
<a href="#posix+tz+environment+variable">Posix</a>
|
||||
<a href="#saving+preferences">Preferences</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Priority</a>
|
||||
|
||||
<b>R</b>
|
||||
|
||||
<a href="#configuring+the+client">Read only</a>
|
||||
<a href="#arexx+interface">RFC850</a>
|
||||
<a href="#arexx+interface">RFC1123</a>
|
||||
<a href="#arexx+interface">RFC2822</a>
|
||||
<a href="#arexx+interface">RFC3339</a>
|
||||
|
||||
<b>S</b>
|
||||
|
||||
<a href="#configuring+the+client">Server address</a>
|
||||
<a href="#configuring+the+client">Server port</a>
|
||||
<a href="#configuring+the+client">Settings</a>
|
||||
<a href="#configuring+the+client">Connection timeout</a>
|
||||
<a href="#configuring+the+client">Automatically synchronization</a>
|
||||
<a href="#configuring+the+client">Connection time out</a>
|
||||
<a href="#configuring+the+client">Daylight saving time</a>
|
||||
<a href="#configuring+the+client">Expert mode </a>
|
||||
<a href="#configuring+the+client">Interval</a>
|
||||
<a href="#configuring+the+client">Interval between requests</a>
|
||||
<a href="#configuring+the+client">Logging</a>
|
||||
<a href="#configuring+the+client">Popkey</a>
|
||||
<a href="#configuring+the+client">Popup</a>
|
||||
<a href="#configuring+the+client">Priority</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Popkey</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Popup</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Priority</a>
|
||||
<a href="#configuring+the+client">Read only</a>
|
||||
<a href="#configuring+the+client">Server address</a>
|
||||
<a href="#configuring+the+client">Server port</a>
|
||||
<a href="#configuring+the+client">Threshold</a>
|
||||
<a href="#the+posix+tz+environment+variable">Standard time</a>
|
||||
<a href="#the+posix+tz+environment+variable">Summer time</a>
|
||||
<a href="#configuring+the+client">Time zone</a>
|
||||
<a href="#configuring+the+client">Time zone abbreviation</a>
|
||||
<a href="#configuring+the+client">Time zone display</a>
|
||||
<a href="#configuring+the+client">Time zone value</a>
|
||||
<a href="#configuring+the+client">Standard time</a>
|
||||
<a href="#configuring+the+client">Startup Sequence</a>
|
||||
<a href="#configuring+the+client">Summer time</a>
|
||||
|
||||
<b>T</b>
|
||||
|
||||
<a href="#configuring+the+client">Threshold</a>
|
||||
<a href="#arexx+interface">TimeCtrl</a>
|
||||
<a href="#configuring+the+client">TimeLogger</a>
|
||||
<a href="#main">Time zone</a>
|
||||
<a href="#local+time+zone">Time zone</a>
|
||||
<a href="#arexx+interface">Getting</a>
|
||||
<a href="#main">Setting</a>
|
||||
<a href="#local+time+zone">Setting</a>
|
||||
<a href="#configuring+the+client">Time zone abbreviation</a>
|
||||
<a href="#configuring+the+client">Time zone display</a>
|
||||
<a href="#local+time+zone">Time zone value</a>
|
||||
<a href="#using+tooltypes+of+an+icon">Tool types</a>
|
||||
<a href="#the+posix+tz+environment+variable">TZ</a>
|
||||
<a href="#local+time+zone">TZ</a>
|
||||
<a href="#posix+tz+environment+variable">Content</a>
|
||||
<a href="#local+time+zone">Setting</a>
|
||||
<a href="#local+time+zone">TZONE</a>
|
||||
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
+16
-20
@@ -2,7 +2,7 @@ Short: Keep your time right
|
||||
Author: Carsten Larsen (carsten.larsen@mail.com)
|
||||
Uploader: Carsten Larsen (carsten.larsen@mail.com)
|
||||
Type: util/cdity
|
||||
Version: 1.11
|
||||
Version: 1.12
|
||||
Architecture: m68k-amigaos
|
||||
|
||||
AmiTimeKeeper is a small program which keeps the time right on your
|
||||
@@ -21,29 +21,25 @@ try visiting support.ntp.org or one of the other sites listing time
|
||||
servers. Use a fixed pool server by prefixing the domain, for example,
|
||||
1.pool.ntp.org.
|
||||
|
||||
The local time zone needs to be configured using Workbench preferences
|
||||
or a similar tool. In AmigaOS 3.1 and 3.9 this is available through
|
||||
the Locale Preferences Editor. Daylight saving time is only supported
|
||||
through the POSIX TZ environment variable.
|
||||
The time zone needs to be configured using Workbench preferences or
|
||||
a similar tool. In Amiga OS this is available through the Locale
|
||||
Preferences Editor. The local time zone and daylight saving time are
|
||||
optionally specified manually or using a POSIX TZ variable style.
|
||||
|
||||
The Icaros Desktop system is distributed with a custom build version of
|
||||
AmiTimeKeeper. The author encourages everyone with an interest to build
|
||||
their own version.
|
||||
|
||||
Version 1.11 has two known issues:
|
||||
- Settings window in AROS is broken (and disabled in this version)
|
||||
- Setting Popkey is not supported in ARexx
|
||||
Please report bugs and other issues by sending a mail or using:
|
||||
https://ranger.innolan.net/rainlance/AmiTimeKeeper
|
||||
|
||||
Changes in v1.11, 11.01.2021
|
||||
- New dedicated external control utility
|
||||
- New ARexx port with a diverse set of commands
|
||||
- Rewritten logger facility with more verbose output
|
||||
- Bug preventing commodity to shutdown fixed
|
||||
- Bug in CLI SWITCH parameters reporting wrong values fixed
|
||||
- Support AmigaOS 1.3 (v34) but without settings window
|
||||
- Time zone information displayed using GMT instead of UTC
|
||||
- Only watch current env variable for time zone changes
|
||||
- Improved validation of application settings
|
||||
- Several dead and duplicated code blocks removed
|
||||
v1.12 31.01.2021
|
||||
- New options to specify the local time zone
|
||||
- New ARexx commands, parameters and error variables
|
||||
- New option to start without active time synchronization
|
||||
- New deactivate logging option for performance saving
|
||||
- More bugs in calculation of time zone transition fixed
|
||||
- Sanity check on value for interval between requests
|
||||
- Updated ARexx documentation and script
|
||||
- Honour ARexx result flag (RXFF_RESULT)
|
||||
- Various minor bug fixes and improvements
|
||||
- Documentation in HTML format
|
||||
|
||||
@@ -1,743 +0,0 @@
|
||||
/*
|
||||
** This file is in the public domain.
|
||||
*/
|
||||
|
||||
#include "amiga.h"
|
||||
#include "private.h"
|
||||
#include <dos/var.h>
|
||||
#include <devices/timer.h>
|
||||
#include <libraries/locale.h>
|
||||
#include <utility/date.h>
|
||||
|
||||
/* Amiga convert functions */
|
||||
void Amiga2Tm(ULONG seconds, struct tm *tm);
|
||||
ULONG Tm2Amiga(struct tm *tm);
|
||||
ULONG Unix2Amiga(time_t t);
|
||||
time_t Amiga2Unix(ULONG t);
|
||||
void Tm2DateStamp(struct tm *tm, struct DateStamp *date);
|
||||
void DateStamp2Tm(struct DateStamp *date, struct tm *tm);
|
||||
void Unix2DateStamp(time_t *time, struct DateStamp *date);
|
||||
void DateStamp2Unix(struct DateStamp *date, time_t *time);
|
||||
void Tm2Date(struct tm *tm, struct ClockData *date);
|
||||
void Date2Tm(struct ClockData *date, struct tm *tm);
|
||||
void Date2Unix(struct ClockData *date, time_t *time);
|
||||
void Unix2Date(time_t *time, struct ClockData *date);
|
||||
|
||||
static struct timerequest *TimeRequest;
|
||||
static struct MsgPort *TimerPort;
|
||||
|
||||
const struct lc_time_T C_time_locale = {
|
||||
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"},
|
||||
{"January", "February", "March", "April", "May", "June",
|
||||
"July", "August", "September", "October", "November", "December"},
|
||||
{"Sun", "Mon", "Tue", "Wed",
|
||||
"Thu", "Fri", "Sat"},
|
||||
{"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"},
|
||||
|
||||
/* X_fmt */
|
||||
"%H:%M:%S",
|
||||
|
||||
/*
|
||||
** x_fmt
|
||||
** C99 requires this format.
|
||||
** Using just numbers (as here) makes Quakers happier;
|
||||
** it's also compatible with SVR4.
|
||||
*/
|
||||
"%m/%d/%y",
|
||||
|
||||
/*
|
||||
** c_fmt
|
||||
** C99 requires this format.
|
||||
** Previously this code used "%D %X", but we now conform to C99.
|
||||
** Note that
|
||||
** "%a %b %d %H:%M:%S %Y"
|
||||
** is used by Solaris 2.3.
|
||||
*/
|
||||
"%a %b %e %T %Y",
|
||||
|
||||
/* t_fmt_ampm */
|
||||
"TODO",
|
||||
|
||||
/* am */
|
||||
"AM",
|
||||
|
||||
/* pm */
|
||||
"PM",
|
||||
|
||||
/* am_pm */
|
||||
{ "TODOAM", "TODOPM"},
|
||||
|
||||
/* date_fmt */
|
||||
"%a %b %e %H:%M:%S %Z %Y"};
|
||||
|
||||
static int
|
||||
CreateTimer()
|
||||
{
|
||||
int error;
|
||||
|
||||
TimerPort = CreateMsgPort();
|
||||
if (TimerPort == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
TimeRequest = (struct timerequest *)CreateIORequest(
|
||||
TimerPort,
|
||||
sizeof(struct timerequest));
|
||||
|
||||
if (TimeRequest == NULL)
|
||||
{
|
||||
DeleteMsgPort(TimerPort);
|
||||
return 2;
|
||||
}
|
||||
|
||||
error = OpenDevice(
|
||||
(STRPTR)TIMERNAME,
|
||||
UNIT_MICROHZ,
|
||||
(struct IORequest *)TimeRequest,
|
||||
0);
|
||||
|
||||
if (error != 0)
|
||||
{
|
||||
DeleteIORequest((struct IORequest *)TimeRequest);
|
||||
DeleteMsgPort(TimerPort);
|
||||
return 3;
|
||||
}
|
||||
|
||||
TimerBase = (struct Device *)TimeRequest->tr_node.io_Device;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteTimer()
|
||||
{
|
||||
TimerBase = NULL;
|
||||
|
||||
if (TimeRequest != NULL)
|
||||
{
|
||||
if (!CheckIO((struct IORequest *)TimeRequest))
|
||||
{
|
||||
WaitIO((struct IORequest *)TimeRequest);
|
||||
}
|
||||
|
||||
CloseDevice((struct IORequest *)TimeRequest);
|
||||
DeleteIORequest((struct IORequest *)TimeRequest);
|
||||
|
||||
TimeRequest = NULL;
|
||||
}
|
||||
|
||||
if (TimerPort != NULL)
|
||||
{
|
||||
DeleteMsgPort(TimerPort);
|
||||
TimerPort = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int gmtoffset(time_t locale_time)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t time = locale_time;
|
||||
localtime_r(&time, &tm);
|
||||
return tm.tm_gmtoff;
|
||||
}
|
||||
|
||||
int gettimeofday(struct timeval *tv, void *tz)
|
||||
{
|
||||
long zone;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ObtainSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
if (CreateTimer() != 0)
|
||||
{
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
zone = gmtoffset(tv->tv_secs);
|
||||
|
||||
TimeRequest->tr_node.io_Command = TR_GETSYSTIME;
|
||||
DoIO((struct IORequest *)TimeRequest);
|
||||
tv->tv_secs = (long)TimeRequest->tr_time.tv_secs + EPOCH_OFFSET + zone;
|
||||
tv->tv_micro = TimeRequest->tr_time.tv_micro;
|
||||
|
||||
DeleteTimer();
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int settimeofday(const struct timeval *tv, void *tz)
|
||||
{
|
||||
long zone;
|
||||
|
||||
if (tv == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ObtainSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
if (CreateTimer() != 0)
|
||||
{
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
zone = gmtoffset(tv->tv_secs);
|
||||
|
||||
TimeRequest->tr_node.io_Command = TR_SETSYSTIME;
|
||||
TimeRequest->tr_time.tv_secs = (long)tv->tv_secs - EPOCH_OFFSET - zone;
|
||||
TimeRequest->tr_time.tv_micro = tv->tv_micro;
|
||||
DoIO((struct IORequest *)TimeRequest);
|
||||
|
||||
DeleteTimer();
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int getsystime(struct timeval *tv)
|
||||
{
|
||||
if (tv == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ObtainSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
if (CreateTimer() != 0)
|
||||
{
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
tv->tv_secs = 0;
|
||||
tv->tv_micro = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef AROS
|
||||
TimeRequest->tr_node.io_Command = TR_GETSYSTIME;
|
||||
DoIO((struct IORequest *)TimeRequest);
|
||||
tv->tv_secs = TimeRequest->tr_time.tv_secs;
|
||||
tv->tv_micro = 0;
|
||||
#else
|
||||
{
|
||||
struct timeval tv1;
|
||||
GetSysTime(&tv1);
|
||||
*tv = tv1;
|
||||
}
|
||||
#endif
|
||||
|
||||
DeleteTimer();
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int setsystime(struct timeval *tv)
|
||||
{
|
||||
if (tv == NULL)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ObtainSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
if (CreateTimer() != 0)
|
||||
{
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
TimeRequest->tr_node.io_Command = TR_SETSYSTIME;
|
||||
TimeRequest->tr_time.tv_secs = (long)tv->tv_secs;
|
||||
TimeRequest->tr_time.tv_micro = tv->tv_micro;
|
||||
DoIO((struct IORequest *)TimeRequest);
|
||||
|
||||
DeleteTimer();
|
||||
|
||||
if (TimerSemaphore != NULL)
|
||||
{
|
||||
ReleaseSemaphore(TimerSemaphore);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__AROS__)
|
||||
int *__stdc_geterrnoptr(void)
|
||||
{
|
||||
return &errno;
|
||||
}
|
||||
#endif
|
||||
|
||||
int daylight_c(void)
|
||||
{
|
||||
return daylight;
|
||||
}
|
||||
|
||||
long Timezone_c(void)
|
||||
{
|
||||
return Timezone;
|
||||
}
|
||||
|
||||
long altzone_c(void)
|
||||
{
|
||||
return altzone;
|
||||
}
|
||||
|
||||
char **tzname_c(void)
|
||||
{
|
||||
return (char **)tzname;
|
||||
}
|
||||
|
||||
/*
|
||||
struct lc_time_T *_current_locale()
|
||||
{
|
||||
return (struct lc_time_T *)&C_time_locale;
|
||||
}
|
||||
|
||||
size_t
|
||||
_strftime(const Timezone_t sp, char *const s, const size_t maxsize,
|
||||
const char *const format, const struct tm *const t, struct lc_time_T *loc);
|
||||
|
||||
size_t
|
||||
strftime_lz(const Timezone_t sp, char *const s, const size_t maxsize,
|
||||
const char *const format, const struct tm *const t, locale_t locale)
|
||||
{
|
||||
size_t res;
|
||||
struct lc_time_T *l = openlc(locale);
|
||||
|
||||
res = _strftime(sp, s, maxsize, format, t, l);
|
||||
|
||||
closelc(l);
|
||||
return res;
|
||||
}
|
||||
*/
|
||||
|
||||
struct lc_time_T *openlc(locale_t locale)
|
||||
{
|
||||
int i, j;
|
||||
struct lc_time_T *l = (struct lc_time_T *)AllocMem(
|
||||
sizeof(struct lc_time_T),
|
||||
MEMF_ANY | MEMF_CLEAR);
|
||||
|
||||
struct Locale *loc = locale;
|
||||
|
||||
if (!loc)
|
||||
{
|
||||
loc = OpenLocale(NULL);
|
||||
}
|
||||
|
||||
l->X_fmt = (const char *)loc->loc_TimeFormat;
|
||||
l->x_fmt = (const char *)loc->loc_ShortDateFormat;
|
||||
l->c_fmt = (const char *)loc->loc_DateTimeFormat;
|
||||
l->am = (const char *)GetLocaleStr(loc, AM_STR);
|
||||
l->pm = (const char *)GetLocaleStr(loc, PM_STR);
|
||||
l->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
|
||||
|
||||
j = 0;
|
||||
for (i = 1; i < 8; i++)
|
||||
{
|
||||
l->weekday[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 8; i < 15; i++)
|
||||
{
|
||||
l->wday[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 15; i < 27; i++)
|
||||
{
|
||||
l->month[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 27; i < 39; i++)
|
||||
{
|
||||
l->mon[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
l->locale = loc;
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
void closelc(struct lc_time_T *lc)
|
||||
{
|
||||
if (lc->locale)
|
||||
{
|
||||
CloseLocale(lc->locale);
|
||||
}
|
||||
|
||||
FreeMem(lc, sizeof(struct lc_time_T));
|
||||
}
|
||||
|
||||
/* Similar to intuition.library CurrentTime */
|
||||
void CurrentTimeGmt(ULONG *seconds, ULONG *micros)
|
||||
{
|
||||
ULONG sec, mic;
|
||||
CurrentTime(&sec, &mic);
|
||||
*seconds = sec + (daylight ? altzone : Timezone);
|
||||
*micros = mic;
|
||||
}
|
||||
|
||||
struct tm *AmigaLocalTime(ULONG *seconds, struct tm *tm)
|
||||
{
|
||||
time_t time;
|
||||
if (tm == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (seconds == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
Date2Tm(NULL, tm);
|
||||
return tm;
|
||||
}
|
||||
|
||||
time = Amiga2Unix(*seconds);
|
||||
localtime_r(&time, tm);
|
||||
return tm;
|
||||
}
|
||||
|
||||
struct tm *AmigaLocalTimeZ(ULONG *seconds, struct tm *tm, const Timezone_t tz)
|
||||
{
|
||||
time_t time;
|
||||
if (tm == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (seconds == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
Date2Tm(NULL, tm);
|
||||
return tm;
|
||||
}
|
||||
|
||||
time = Amiga2Unix(*seconds);
|
||||
localtime_rz(tz, &time, tm);
|
||||
return tm;
|
||||
}
|
||||
|
||||
/* Similar to locale.library FormatDate */
|
||||
void FormatDateTm(char *const s, const char *format, struct tm *tm,
|
||||
char *buffer, long maxsize)
|
||||
{
|
||||
strftime(s, maxsize, format, tm);
|
||||
}
|
||||
|
||||
/* Similar to locale.library ParseDate */
|
||||
int ParseDateTm(struct Locale *locale, const char *format, struct tm *tm,
|
||||
const char *string)
|
||||
{
|
||||
// TODO
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Similar to utility.library Amiga2Date.
|
||||
Fills in a tm structure with the date and time calculated
|
||||
from a ULONG containing the number of seconds from 01-Jan-1978
|
||||
to the date. */
|
||||
void Amiga2Tm(ULONG seconds, struct tm *tm)
|
||||
{
|
||||
struct tm tmp;
|
||||
time_t t;
|
||||
if (tm == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
t = seconds + EPOCH_OFFSET;
|
||||
localtime_r(&t, &tmp);
|
||||
t = seconds + EPOCH_OFFSET - tmp.tm_gmtoff;
|
||||
localtime_r(&t, tm);
|
||||
}
|
||||
|
||||
/* Similar to utility.library Date2Amiga.
|
||||
Calculates the number of seconds from 01-Jan-1978 to the date
|
||||
specified in the tm structure. */
|
||||
ULONG Tm2Amiga(struct tm *tm)
|
||||
{
|
||||
time_t time;
|
||||
if (tm == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
return 0;
|
||||
}
|
||||
|
||||
time = timelocal(tm);
|
||||
return time - EPOCH_OFFSET;
|
||||
}
|
||||
|
||||
/* Convert between Unix Time Epoch and Amiga Time Epoch */
|
||||
ULONG Unix2Amiga(time_t t)
|
||||
{
|
||||
return t - EPOCH_OFFSET;
|
||||
}
|
||||
|
||||
time_t Amiga2Unix(ULONG t)
|
||||
{
|
||||
return t + EPOCH_OFFSET;
|
||||
}
|
||||
|
||||
/* Convert to and from DateStamp */
|
||||
void Tm2DateStamp(struct tm *tm, struct DateStamp *date)
|
||||
{
|
||||
time_t time;
|
||||
struct tm tmp = *tm;
|
||||
|
||||
if (date == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (tm == NULL)
|
||||
{
|
||||
/* UNIX Epoch time */
|
||||
time = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
time = mktime(&tmp);
|
||||
}
|
||||
|
||||
Unix2DateStamp(&time, date);
|
||||
}
|
||||
|
||||
void DateStamp2Tm(struct DateStamp *date, struct tm *tm)
|
||||
{
|
||||
time_t time;
|
||||
if (tm == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (date == NULL)
|
||||
{
|
||||
Date2Tm(NULL, tm);
|
||||
return;
|
||||
}
|
||||
|
||||
DateStamp2Unix(date, &time);
|
||||
gmtime_r(&time, tm);
|
||||
}
|
||||
|
||||
void Unix2DateStamp(time_t *time, struct DateStamp *date)
|
||||
{
|
||||
long t, d, m, q;
|
||||
if (date == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (time == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
date->ds_Days = 0;
|
||||
date->ds_Minute = 0;
|
||||
date->ds_Tick = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
t = *time - EPOCH_OFFSET;
|
||||
d = t / SECONDSPERDAY;
|
||||
m = (t - SECONDSPERDAY * d) / 60;
|
||||
q = (t - SECONDSPERDAY * d - m * 60) * 60; // TODO: Ticks = 50
|
||||
|
||||
date->ds_Days = d;
|
||||
date->ds_Minute = m;
|
||||
date->ds_Tick = q;
|
||||
}
|
||||
|
||||
void DateStamp2Unix(struct DateStamp *date, time_t *time)
|
||||
{
|
||||
if (time == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (date == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
*time = EPOCH_OFFSET;
|
||||
return;
|
||||
}
|
||||
|
||||
*time = date->ds_Days * SECONDSPERDAY +
|
||||
date->ds_Minute * 60 +
|
||||
date->ds_Tick / 60 +
|
||||
EPOCH_OFFSET;
|
||||
}
|
||||
|
||||
/* Convert from tm to ClockData */
|
||||
void Tm2Date(struct tm *tm, struct ClockData *date)
|
||||
{
|
||||
if (date == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (tm == NULL)
|
||||
{
|
||||
/* UNIX Epoch time */
|
||||
date->sec = 0;
|
||||
date->min = 0;
|
||||
date->hour = 0;
|
||||
date->mday = 1;
|
||||
date->month = 1;
|
||||
date->year = EPOCH_YEAR;
|
||||
date->wday = EPOCH_WDAY;
|
||||
return;
|
||||
}
|
||||
|
||||
date->sec = (UWORD)tm->tm_sec;
|
||||
date->min = (UWORD)tm->tm_min;
|
||||
date->hour = (UWORD)tm->tm_hour;
|
||||
date->mday = (UWORD)tm->tm_mday;
|
||||
date->month = (UWORD)tm->tm_mon + 1;
|
||||
date->year = (UWORD)tm->tm_year + TM_YEAR_BASE + EPOCH_OFFSET_YEAR;
|
||||
date->wday = (UWORD)tm->tm_wday;
|
||||
|
||||
/* tm allow seconds in interval [0-61] */
|
||||
if (date->sec > 59)
|
||||
{
|
||||
date->sec = 59;
|
||||
}
|
||||
}
|
||||
|
||||
/* Convert from ClockData to tm */
|
||||
void Date2Tm(struct ClockData *date, struct tm *tm)
|
||||
{
|
||||
if (tm == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (date == NULL)
|
||||
{
|
||||
/* Amiga Epoch time */
|
||||
tm->tm_sec = 0;
|
||||
tm->tm_min = 0;
|
||||
tm->tm_hour = 0;
|
||||
tm->tm_mday = 1;
|
||||
tm->tm_mon = 0;
|
||||
tm->tm_year = EPOCH_YEAR + EPOCH_OFFSET_YEAR - TM_YEAR_BASE;
|
||||
mktime(tm);
|
||||
return;
|
||||
}
|
||||
|
||||
tm->tm_sec = (int)date->sec;
|
||||
tm->tm_min = (int)date->min;
|
||||
tm->tm_hour = (int)date->hour;
|
||||
tm->tm_mday = (int)date->mday;
|
||||
tm->tm_mon = (int)date->month - 1;
|
||||
tm->tm_year = (int)date->year - TM_YEAR_BASE - EPOCH_OFFSET_YEAR;
|
||||
tm->tm_wday = (int)date->wday;
|
||||
mktime(tm);
|
||||
}
|
||||
|
||||
void Date2Unix(struct ClockData *date, time_t *time)
|
||||
{
|
||||
struct tm tm;
|
||||
if (time == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (date == NULL)
|
||||
{
|
||||
/* UNIX Epoch time */
|
||||
*time = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Date2Tm(date, &tm);
|
||||
mktime(&tm);
|
||||
}
|
||||
|
||||
void Unix2Date(time_t *time, struct ClockData *date)
|
||||
{
|
||||
struct tm tm;
|
||||
time_t t;
|
||||
if (date == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (time == NULL)
|
||||
{
|
||||
/* UNIX Epoch time */
|
||||
Tm2Date(NULL, date);
|
||||
return;
|
||||
}
|
||||
|
||||
t = *time;
|
||||
gmtime_r(&t, &tm);
|
||||
Tm2Date(&tm, date);
|
||||
}
|
||||
|
||||
#undef time
|
||||
#undef time_t
|
||||
|
||||
time_t
|
||||
time(time_t *x)
|
||||
{
|
||||
time_t tloc;
|
||||
ULONG sec, mic;
|
||||
CurrentTime(&sec, &mic);
|
||||
tloc = (time_t)(sec);
|
||||
|
||||
if (x)
|
||||
{
|
||||
*x = tloc;
|
||||
}
|
||||
|
||||
return tloc;
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
** This file is in the public domain.
|
||||
*/
|
||||
|
||||
#ifndef AMIGA_H
|
||||
#define AMIGA_H
|
||||
|
||||
/* Used by localtime.c but not by amiga */
|
||||
#define O_CLOEXEC 0
|
||||
#define _DIAGASSERT(x)
|
||||
#define __aconst
|
||||
|
||||
/* Used by amiga.c */
|
||||
#define SECONDSPERDAY 86400
|
||||
|
||||
/*
|
||||
* The following macro is used to remove const cast-away warnings
|
||||
* from gcc -Wcast-qual; it should be used with caution because it
|
||||
* can hide valid errors; in particular most valid uses are in
|
||||
* situations where the API requires it, not to cast away string
|
||||
* constants. We don't use *intptr_t on purpose here and we are
|
||||
* explicit about unsigned long so that we don't have additional
|
||||
* dependencies.
|
||||
*/
|
||||
#define __UNCONST(a) ((void *)(unsigned long)(const void *)(a))
|
||||
|
||||
#define NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU 1
|
||||
#define HAVE_STRFTIME_L 0
|
||||
|
||||
/* Thread safety */
|
||||
#define rwlock_wrlock(x)
|
||||
#define rwlock_unlock(x)
|
||||
|
||||
#define TIME_MAX ULONG_MAX
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include "mem.h"
|
||||
|
||||
#define TZLIB_NAME "tz.library"
|
||||
#define VERSION_NO 7
|
||||
#define VERSION_TEXT "7"
|
||||
#define REVISION_NO 00
|
||||
#define REVISION_TEXT "00"
|
||||
#define DATE_TEXT "10.01.2018"
|
||||
#define VERS TZLIB_NAME " " VERSION_TEXT "." REVISION_TEXT
|
||||
#define VSTRING TZLIB_NAME " " VERSION_TEXT "." REVISION_TEXT \
|
||||
"(" DATE_TEXT ")\r\n"
|
||||
#define VERSTAG "\0$VER: " TZLIB_NAME " " VERSION_TEXT "." REVISION_TEXT \
|
||||
"(" DATE_TEXT ")"
|
||||
|
||||
#define TZVARIABLE1 "TZ"
|
||||
#define TZVARIABLE2 "Timezone.prefs"
|
||||
#define TZVARIABLE TZVARIABLE1
|
||||
#define ENVSIZE 128
|
||||
|
||||
#include <exec/io.h>
|
||||
#include <proto/exec.h>
|
||||
#include <inline/exec.h>
|
||||
#include <proto/dos.h>
|
||||
#include <inline/dos.h>
|
||||
#include <proto/locale.h>
|
||||
#include <inline/locale.h>
|
||||
#include <proto/timer.h>
|
||||
#include <inline/timer.h>
|
||||
#include <proto/intuition.h>
|
||||
#include <inline/intuition.h>
|
||||
|
||||
#ifndef REG
|
||||
#define REG(reg, arg) arg __asm(#reg)
|
||||
#endif
|
||||
|
||||
#ifndef UNUSED
|
||||
#define UNUSED __attribute__((unused))
|
||||
#endif
|
||||
|
||||
typedef struct Locale *locale_t;
|
||||
|
||||
struct lc_time_T
|
||||
{
|
||||
const char *mon[12];
|
||||
const char *month[12];
|
||||
const char *wday[7];
|
||||
const char *weekday[7];
|
||||
const char *X_fmt;
|
||||
const char *x_fmt;
|
||||
const char *c_fmt;
|
||||
const char *t_fmt_ampm; // TODO
|
||||
const char *am;
|
||||
const char *pm;
|
||||
const char *am_pm[2]; // TODO
|
||||
const char *date_fmt;
|
||||
locale_t locale;
|
||||
};
|
||||
|
||||
#undef ctime_rz
|
||||
#define ctime_rz tz_ctime_rz
|
||||
#undef tzgetgmtoff
|
||||
#define tzgetgmtoff tz_tzgetgmtoff
|
||||
#undef timelocal_z
|
||||
#define timelocal_z tz_timelocal_z
|
||||
#undef tzgetname
|
||||
#define tzgetname tz_tzgetname
|
||||
#undef offtime_r
|
||||
#define offtime_r tz_offtime_r
|
||||
#undef tzgetlocation
|
||||
#define tzgetlocation tz_tzgetlocation
|
||||
#undef snprintf
|
||||
#define snprintf SNPrintf
|
||||
|
||||
/* amiga.c tz functions */
|
||||
int daylight_c(void);
|
||||
long Timezone_c(void);
|
||||
long altzone_c(void);
|
||||
char **tzname_c(void);
|
||||
int getsystime(struct timeval *tv);
|
||||
int setsystime(struct timeval *tv);
|
||||
int gettimeofday(struct timeval *tv, void *tz);
|
||||
int settimeofday(const struct timeval *tv, void *tz);
|
||||
|
||||
/* amiga.c internals */
|
||||
struct lc_time_T *openlc(locale_t locale);
|
||||
void closelc(struct lc_time_T *lc);
|
||||
extern const struct lc_time_T C_time_locale;
|
||||
extern long Timezone;
|
||||
extern long altzone;
|
||||
extern int daylight;
|
||||
extern struct SignalSemaphore *TimerSemaphore;
|
||||
|
||||
/* string.c */
|
||||
void bcopy(const void *src, void *dest, size_t len); // <string.h>
|
||||
void *memmove(void *dest, const void *src, size_t len); // <string.h>
|
||||
size_t strlen(const char *string); // <string.h>
|
||||
char *strcpy(char *dest, const char *src); // <string.h>
|
||||
char *strcat(char *dest, const char *src); // <string.h>
|
||||
int strcmp(const char *s1, const char *s2); // <string.h>
|
||||
char *strchr(const char *s, int c); // <string.h>
|
||||
int strncmp(const char *s1, const char *s2, size_t n); // <string.h>
|
||||
char *getenv(const char *name); // <stdlib.h>
|
||||
int isdigit(char c);
|
||||
int isspace(char c);
|
||||
int isalpha(char c);
|
||||
int toupper(char c);
|
||||
int strncasecmp(const char *_s1, const char *_s2, size_t n);
|
||||
int SNPrintf(char *str, size_t size, const char *format, ...);
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ < 3)
|
||||
void *memcpy(void *dst, const void *src, unsigned long len);
|
||||
#else
|
||||
void *memcpy(void *dst, const void *src, size_t len);
|
||||
#endif
|
||||
void *memset(void *str, int c, size_t n);
|
||||
|
||||
extern struct ExecBase *SysBase;
|
||||
extern int errno;
|
||||
|
||||
#endif
|
||||
@@ -38,6 +38,8 @@
|
||||
#include "tz.h"
|
||||
|
||||
#include <proto/rexxsyslib.h>
|
||||
#include <proto/alib.h>
|
||||
#include <rexx/errors.h>
|
||||
#include <rexx/storage.h>
|
||||
#include <rexx/rxslib.h>
|
||||
|
||||
@@ -46,64 +48,66 @@
|
||||
|
||||
static char *arexxHelpText = NULL;
|
||||
|
||||
typedef void (*ArexxCommand)(struct RexxMsg *, char **);
|
||||
typedef void (*ARexxCommand)(struct RexxMsg *, char **);
|
||||
|
||||
struct ArexxCommandDef
|
||||
struct ARexxCommandDef
|
||||
{
|
||||
/* Unique numeric command identifier */
|
||||
const int Identifier;
|
||||
/* Command name as exposed in ARexx interface */
|
||||
const char *Name;
|
||||
/* Short description of command purpose */
|
||||
const char *Description;
|
||||
ArexxCommand Command;
|
||||
/* Function pointer to action code */
|
||||
ARexxCommand Command;
|
||||
/* True if command only return a result. False is command is an action */
|
||||
bool ResultCommand;
|
||||
/* Number of parameters / arguments */
|
||||
int Parameters;
|
||||
};
|
||||
|
||||
struct ArexxParameterDef
|
||||
struct ARexxParameterDef
|
||||
{
|
||||
const int Identifier;
|
||||
const char *Keyword;
|
||||
};
|
||||
|
||||
static void ArexxIdentifierCommand(struct RexxMsg *, char **);
|
||||
static void ArexxVersionCommand(struct RexxMsg *, char **);
|
||||
static void ArexxHelpCommand(struct RexxMsg *, char **);
|
||||
static void ArexxStatusCommand(struct RexxMsg *, char **);
|
||||
static void ArexxTimezoneCommand(struct RexxMsg *msg, char **);
|
||||
static void ArexxLastSyncCommand(struct RexxMsg *msg, char **);
|
||||
static void ArexxLastAdjustCommand(struct RexxMsg *msg, char **);
|
||||
static void ArexxGetValueCommand(struct RexxMsg *, char **);
|
||||
static void ArexxSetValueCommand(struct RexxMsg *, char **);
|
||||
static void ArexxShowCommand(struct RexxMsg *, char **);
|
||||
static void ArexxHideCommand(struct RexxMsg *, char **);
|
||||
static void ArexxStartCommand(struct RexxMsg *, char **);
|
||||
static void ArexxStopCommand(struct RexxMsg *, char **);
|
||||
static void ArexxShutdownCommand(struct RexxMsg *, char **);
|
||||
static void ARexxIdentifierCommand(struct RexxMsg *, char **);
|
||||
static void ARexxVersionCommand(struct RexxMsg *, char **);
|
||||
static void ARexxHelpCommand(struct RexxMsg *, char **);
|
||||
static void ARexxStatusCommand(struct RexxMsg *, char **);
|
||||
static void ARexxTimezoneCommand(struct RexxMsg *msg, char **);
|
||||
static void ARexxLastSyncCommand(struct RexxMsg *msg, char **);
|
||||
static void ARexxLastAdjustCommand(struct RexxMsg *msg, char **);
|
||||
static void ARexxGetValueCommand(struct RexxMsg *, char **);
|
||||
static void ARexxSetValueCommand(struct RexxMsg *, char **);
|
||||
static void ARexxNowCommand(struct RexxMsg *, char **);
|
||||
static void ARexxShowCommand(struct RexxMsg *, char **);
|
||||
static void ARexxHideCommand(struct RexxMsg *, char **);
|
||||
static void ARexxStartCommand(struct RexxMsg *, char **);
|
||||
static void ARexxStopCommand(struct RexxMsg *, char **);
|
||||
static void ARexxShutdownCommand(struct RexxMsg *, char **);
|
||||
static void ARexxLogTransitionsCommand(struct RexxMsg *, char **);
|
||||
|
||||
#define AREXX_COMMAND_OK 0
|
||||
#define AREXX_COMMAND_ERROR 1
|
||||
#define AREXX_COMMAND_UNKNOWN 10
|
||||
#define AREXX_COMMAND_PARM_UNKNOWN 11
|
||||
#define AREXX_COMMAND_PARM_INVALID 12
|
||||
#define AREXX_COMMAND_SHUTDOWN 99
|
||||
#define AREXX_COMMAND_COUNT 16
|
||||
static struct ARexxCommandDef arexxCommands[] = {
|
||||
{1, "ID", "Get application identifier", ARexxIdentifierCommand, true, 0},
|
||||
{2, "VERSION", "Get application version number", ARexxVersionCommand, true, 0},
|
||||
{3, "HELP", "Get a list of ARexx commands and a short description", ARexxHelpCommand, true, 0},
|
||||
{4, "STATUS", "Get current synchronization status", ARexxStatusCommand, true, 1},
|
||||
{5, "TIMEZONE", "Get current time zone", ARexxTimezoneCommand, true, 1},
|
||||
{6, "LASTSYNC", "Get time of last synchronization operation", ARexxLastSyncCommand, true, 2},
|
||||
{7, "LASTADJ", "Get time of last clock adjustment", ARexxLastAdjustCommand, true, 2},
|
||||
{8, "GET", "Get a runtime configuration value", ARexxGetValueCommand, true, 1},
|
||||
{9, "SET", "Set a runtime configuration value", ARexxSetValueCommand, false, 2},
|
||||
{10, "NOW", "Get current time and date", ARexxNowCommand, false, 2},
|
||||
{11, "SHOW", "Show settings window", ARexxShowCommand, false, 0},
|
||||
{12, "HIDE", "Hide settings window", ARexxHideCommand, false, 0},
|
||||
{13, "START", "Start the time synchronization process", ARexxStartCommand, false, 0},
|
||||
{14, "STOP", "Stop the time synchronization process", ARexxStopCommand, false, 0},
|
||||
{15, "SHUTDOWN", "Shutdown " APP_SHORT_NAME, ARexxShutdownCommand, false, 0},
|
||||
{16, "LOGTRANS", "Emit time zone transition map to log", ARexxLogTransitionsCommand, false, 0}};
|
||||
|
||||
static struct ArexxCommandDef arexxCommands[] = {
|
||||
{1, "ID", "Get application identifier", ArexxIdentifierCommand, 0},
|
||||
{2, "VERSION", "Get application version number", ArexxVersionCommand},
|
||||
{3, "HELP", "Get a list of ARexx commands and a short description", ArexxHelpCommand, 0},
|
||||
{4, "STATUS", "Get current synchronization status", ArexxStatusCommand, 0},
|
||||
{5, "TIMEZONE", "Get current time zone", ArexxTimezoneCommand, 0},
|
||||
{6, "LASTSYNC", "Get time of last synchronization operation", ArexxLastSyncCommand, 0},
|
||||
{7, "LASTADJ", "Get time of last clock adjustment", ArexxLastAdjustCommand, 0},
|
||||
{8, "GET", "Get a runtime configuration value", ArexxGetValueCommand, 1},
|
||||
{9, "SET", "Set a runtime configuration value", ArexxSetValueCommand, 2},
|
||||
{10, "SHOW", "Show settings window", ArexxShowCommand, 0},
|
||||
{11, "HIDE", "Hide settings window", ArexxHideCommand, 0},
|
||||
{12, "START", "Start the time synchronization process", ArexxStartCommand, 0},
|
||||
{13, "STOP", "Stop the time synchronization process", ArexxStopCommand, 0},
|
||||
{14, "SHUTDOWN", "Shutdown " APP_SHORT_NAME, ArexxShutdownCommand, 0}};
|
||||
|
||||
#define AREXX_COMMAND_COUNT 14
|
||||
|
||||
#define AREXX_PARAMETER_UNKNOWN 0
|
||||
#define AREXX_PARAMETER_SERVER 1
|
||||
#define AREXX_PARAMETER_PORT 2
|
||||
#define AREXX_PARAMETER_THRESHOLD 3
|
||||
@@ -114,8 +118,21 @@ static struct ArexxCommandDef arexxCommands[] = {
|
||||
#define AREXX_PARAMETER_READONLY 8
|
||||
#define AREXX_PARAMETER_EXPERT 9
|
||||
#define AREXX_PARAMETER_TIMEOUT 10
|
||||
#define AREXX_PARAMETER_ACTIVE 11
|
||||
#define AREXX_PARAMETER_NOLOG 12
|
||||
#define AREXX_PARAMETER_TZ 13
|
||||
#define AREXX_PARAMETER_TZD 14
|
||||
#define AREXX_PARAMETER_TZNAME 15
|
||||
#define AREXX_PARAMETER_TZVALUE 16
|
||||
#define AREXX_PARAMETER_TZDST 17
|
||||
#define AREXX_PARAMETER_LAST 17
|
||||
|
||||
static struct ArexxParameterDef arexxParameters[] = {
|
||||
#define AREXX_PARAMETER_UNKNOWN 90
|
||||
#define AREXX_PARAMETER_MISSING 91
|
||||
#define AREXX_PARAMETER_SHUTDOWN 92
|
||||
|
||||
#define AREXX_PARAMETER_COUNT AREXX_PARAMETER_LAST
|
||||
static struct ARexxParameterDef arexxParameters[] = {
|
||||
{AREXX_PARAMETER_SERVER, KEYWORD_SERVER},
|
||||
{AREXX_PARAMETER_PORT, KEYWORD_PORT},
|
||||
{AREXX_PARAMETER_THRESHOLD, KEYWORD_THRESHOLD},
|
||||
@@ -125,12 +142,43 @@ static struct ArexxParameterDef arexxParameters[] = {
|
||||
{AREXX_PARAMETER_POPUP, KEYWORD_POPUP},
|
||||
{AREXX_PARAMETER_READONLY, KEYWORD_READONLY},
|
||||
{AREXX_PARAMETER_EXPERT, KEYWORD_EXPERT},
|
||||
{AREXX_PARAMETER_TIMEOUT, KEYWORD_TIMEOUT}};
|
||||
|
||||
#define AREXX_PARAMETER_COUNT 10
|
||||
{AREXX_PARAMETER_TIMEOUT, KEYWORD_TIMEOUT},
|
||||
{AREXX_PARAMETER_ACTIVE, KEYWORD_ACTIVE},
|
||||
{AREXX_PARAMETER_NOLOG, KEYWORD_NOLOG},
|
||||
{AREXX_PARAMETER_TZ, KEYWORD_TZ},
|
||||
{AREXX_PARAMETER_TZD, KEYWORD_TZD},
|
||||
{AREXX_PARAMETER_TZNAME, KEYWORD_TZNAME},
|
||||
{AREXX_PARAMETER_TZVALUE, KEYWORD_TZVALUE},
|
||||
{AREXX_PARAMETER_TZDST, KEYWORD_TZDST}};
|
||||
|
||||
#define AREXX_MAX_ARGS_COUNT 8
|
||||
|
||||
struct ARexxErrorDef
|
||||
{
|
||||
const long Code;
|
||||
const char **Text;
|
||||
};
|
||||
|
||||
#define AREXX_ERROR_UNKNOWN_CMD 10 /* Unknown ARexx command */
|
||||
#define AREXX_ERROR_UNKNOWN_PARM 11 /* Unknown parameter */
|
||||
#define AREXX_ERROR_PARM_MISS 12 /* Parameter is missing */
|
||||
#define AREXX_ERROR_PARM_INV 13 /* Invalid parameter value */
|
||||
#define AREXX_ERROR_CLOCK_INV 18 /* Clock has not been adjusted */
|
||||
#define AREXX_ERROR_SYNC_INV 19 /* No responses from NTP server */
|
||||
#define AREXX_ERROR_SYNC_ON 20 /* Synchronization is already active */
|
||||
#define AREXX_ERROR_SYNC_OFF 21 /*Synchronization is already deactivated */
|
||||
|
||||
#define AREXX_ERROR_COUNT 8
|
||||
static struct ARexxErrorDef arexxErrors[] = {
|
||||
{AREXX_ERROR_UNKNOWN_CMD, &TextARexxCmdUnknown},
|
||||
{AREXX_ERROR_UNKNOWN_PARM, &TextARexxParmUnknown},
|
||||
{AREXX_ERROR_PARM_MISS, &TextARexxParmMiss},
|
||||
{AREXX_ERROR_PARM_INV, &TextARexxParmInvalid},
|
||||
{AREXX_ERROR_CLOCK_INV, &TextNoClockAdjust},
|
||||
{AREXX_ERROR_SYNC_INV, &TextNoResponses},
|
||||
{AREXX_ERROR_SYNC_ON, &TextSyncAlreadyOn},
|
||||
{AREXX_ERROR_SYNC_OFF, &TextSyncAlreadyOff}};
|
||||
|
||||
static void SplitAndTerminate(char *string, char **res)
|
||||
{
|
||||
char *p = string;
|
||||
@@ -164,7 +212,7 @@ static void SplitAndTerminate(char *string, char **res)
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildArexxHelpText(void)
|
||||
static void BuildARexxHelpText(void)
|
||||
{
|
||||
char *p;
|
||||
int i, line, len = 0;
|
||||
@@ -172,8 +220,9 @@ static void BuildArexxHelpText(void)
|
||||
if (arexxHelpText != NULL)
|
||||
return;
|
||||
|
||||
len += 26; // Header
|
||||
len += 71 * 2; // Spacer
|
||||
len += 26; // Header
|
||||
len += 71 * 2; // Spacer
|
||||
len += StrLen(AREXX_ERROR_VAR_CODE) + StrLen(AREXX_ERROR_VAR_TEXT) + 32; // Footer
|
||||
|
||||
for (i = 0; i < AREXX_COMMAND_COUNT; i++)
|
||||
{
|
||||
@@ -201,9 +250,15 @@ static void BuildArexxHelpText(void)
|
||||
}
|
||||
|
||||
p = AppendChar(p, '-', 70);
|
||||
p = AppendChar(p, '\n', 1);
|
||||
|
||||
p = AppendText(p, "Error status is set in ");
|
||||
p = AppendText(p, AREXX_ERROR_VAR_CODE);
|
||||
p = AppendText(p, " and ");
|
||||
p = AppendText(p, AREXX_ERROR_VAR_TEXT);
|
||||
}
|
||||
|
||||
void CleanupArexx(void)
|
||||
void CleanupARexx(void)
|
||||
{
|
||||
if (arexxHelpText != NULL)
|
||||
{
|
||||
@@ -212,75 +267,209 @@ void CleanupArexx(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxIdentifierCommand(struct RexxMsg *msg, char **parms)
|
||||
static void SetARexxVar(struct RexxMsg *msg, const char *var, const char *text)
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)APP_TITLE, (LONG)StrLen(APP_TITLE));
|
||||
}
|
||||
|
||||
static void ArexxVersionCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)APP_VERSION, (LONG)StrLen(APP_VERSION));
|
||||
}
|
||||
|
||||
static void ArexxHelpCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
BuildArexxHelpText();
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)arexxHelpText, (LONG)StrLen(arexxHelpText));
|
||||
}
|
||||
|
||||
static void ArexxStatusCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
if (SynchronizerRunning)
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)TextSyncOn, (LONG)StrLen(TextSyncOn));
|
||||
LONG error = SetRexxVar(msg, (CONST_STRPTR)var, (CONST_STRPTR)text, (LONG)StrLen(text));
|
||||
if (error != 0)
|
||||
{
|
||||
LogWarn(TextARexxVarError, (long)error);
|
||||
LogWarn(TextARexxVarValue, var, text);
|
||||
}
|
||||
else
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)TextSyncOff, (LONG)StrLen(TextSyncOff));
|
||||
{
|
||||
LogTrace(TextARexxVarValue, var, text);
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxTimezoneCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxErrorClear(struct RexxMsg *msg)
|
||||
{
|
||||
char Timezone[TIMEZONE_TEXT_LEN];
|
||||
GetTimezoneText(AppLocale, Timezone, UTC_NO_PARENS);
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)Timezone, (LONG)StrLen(Timezone));
|
||||
SetARexxVar(msg, AREXX_ERROR_VAR_CODE, "0");
|
||||
SetARexxVar(msg, AREXX_ERROR_VAR_TEXT, "");
|
||||
}
|
||||
|
||||
static void ArexxLastSyncCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxError(struct RexxMsg *msg, long code)
|
||||
{
|
||||
char errorCode[MAXLONGCHARSIZE];
|
||||
LongToStr(code, errorCode);
|
||||
SetARexxVar(msg, AREXX_ERROR_VAR_CODE, errorCode);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < AREXX_ERROR_COUNT; i++)
|
||||
{
|
||||
if (arexxErrors[i].Code == code)
|
||||
{
|
||||
const char *text = *(arexxErrors[i].Text);
|
||||
SetARexxVar(msg, AREXX_ERROR_VAR_TEXT, text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ARexxResult(struct RexxMsg *msg, const char *text)
|
||||
{
|
||||
if (msg->rm_Action & RXFF_RESULT)
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)text, (LONG)StrLen(text));
|
||||
}
|
||||
|
||||
LogTrace(TextARexxResult, text);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
|
||||
static void ARexxResultLong(struct RexxMsg *msg, long value)
|
||||
{
|
||||
char text[MAXLONGCHARSIZE];
|
||||
SNPrintf(text, MAXLONGCHARSIZE, "%ld", value);
|
||||
ARexxResult(msg, text);
|
||||
}
|
||||
|
||||
static void ARexxResultBool(struct RexxMsg *msg, char *parm, long value)
|
||||
{
|
||||
char text[MAXBOOLCHARSIZE];
|
||||
if (Stricmp((STRPTR)parm, (STRPTR)KEYWORD_NUMBER) == 0)
|
||||
BoolToStrNum(value, text);
|
||||
else
|
||||
BoolToStr(value, text);
|
||||
ARexxResult(msg, text);
|
||||
}
|
||||
|
||||
static void ARexxTimeResult(struct RexxMsg *msg, char **parms, struct timeval *utv, long error)
|
||||
{
|
||||
if (utv->tv_secs == 0 && utv->tv_micro == 0)
|
||||
{
|
||||
ARexxError(msg, error);
|
||||
return;
|
||||
}
|
||||
|
||||
bool utc;
|
||||
STRPTR format = (STRPTR)*parms++;
|
||||
if (Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_UTC) == 0)
|
||||
{
|
||||
utc = true;
|
||||
}
|
||||
else if (*parms == NULL || Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_LOCAL) == 0)
|
||||
{
|
||||
utc = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
return;
|
||||
}
|
||||
|
||||
char result[DATETIME_TEXT_LEN + 1];
|
||||
if (format == NULL || Stricmp(format, (STRPTR)KEYWORD_DOS) == 0)
|
||||
Utc2DOS(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_ASCII) == 0)
|
||||
Utc2ASCII(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_DATE) == 0)
|
||||
Utc2ARexxDate(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_TIME) == 0)
|
||||
Utc2ARexxTime(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_RFC850) == 0)
|
||||
Utc2RFC850(utv, result);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_RFC1123) == 0)
|
||||
Utc2RFC1123(utv, result);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_RFC2822) == 0)
|
||||
Utc2RFC2822(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_RFC3339) == 0)
|
||||
Utc2RFC3339(utv, result, utc);
|
||||
else if (Stricmp(format, (STRPTR)KEYWORD_ISO8601) == 0)
|
||||
Utc2ISO8601(utv, result, utc);
|
||||
else
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
return;
|
||||
}
|
||||
|
||||
ARexxResult(msg, result);
|
||||
}
|
||||
|
||||
static void ARexxIdentifierCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
ARexxResult(msg, APP_TITLE);
|
||||
}
|
||||
|
||||
static void ARexxVersionCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
ARexxResult(msg, APP_VERSION);
|
||||
}
|
||||
|
||||
static void ARexxHelpCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
BuildARexxHelpText();
|
||||
ARexxResult(msg, arexxHelpText);
|
||||
}
|
||||
|
||||
static void ARexxStatusCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
if (Stricmp((STRPTR)*parms, (STRPTR)KEYWORD_NUMBER) == 0)
|
||||
{
|
||||
char buf[4];
|
||||
BoolToStrNum(SynchronizerRunning, buf);
|
||||
ARexxResult(msg, buf);
|
||||
}
|
||||
else if (*parms == NULL)
|
||||
{
|
||||
const char *result = SynchronizerRunning ? TextSyncOn : TextSyncOff;
|
||||
ARexxResult(msg, result);
|
||||
}
|
||||
else
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
}
|
||||
}
|
||||
|
||||
static void ARexxTimezoneCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
long val;
|
||||
if (parms == NULL)
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_MISS);
|
||||
}
|
||||
else if (!TryParseLong(*parms, &val))
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
}
|
||||
else if (val < 1 || val > 12)
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
}
|
||||
else
|
||||
{
|
||||
char buf[TIMEZONE_TEXT_LEN];
|
||||
GetTimezoneText(buf, val);
|
||||
ARexxResult(msg, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void ARexxNowCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
struct timeval tv;
|
||||
GetTimeOfDay(&tv);
|
||||
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_SYNC_INV);
|
||||
}
|
||||
|
||||
static void ARexxLastSyncCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
struct timeval tv = LastSync;
|
||||
if (tv.tv_sec == 0 && tv.tv_micro == 0)
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)TextNoResponses, (LONG)StrLen(TextNoResponses));
|
||||
}
|
||||
else
|
||||
{
|
||||
char result[64];
|
||||
Utc2Str(&tv, result);
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)result, (LONG)StrLen(result));
|
||||
}
|
||||
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_SYNC_INV);
|
||||
}
|
||||
|
||||
static void ArexxLastAdjustCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxLastAdjustCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
struct timeval tv = LastAdjust;
|
||||
if (tv.tv_sec == 0 && tv.tv_micro == 0)
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)TextNoClockAdjust, (LONG)StrLen(TextNoClockAdjust));
|
||||
}
|
||||
else
|
||||
{
|
||||
char result[64];
|
||||
Utc2Str(&tv, result);
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)result, (LONG)StrLen(result));
|
||||
}
|
||||
ARexxTimeResult(msg, parms, &tv, AREXX_ERROR_CLOCK_INV);
|
||||
}
|
||||
|
||||
static int ArexxFindParameter(char **parms)
|
||||
static int ARexxFindParameter(char **parms)
|
||||
{
|
||||
int i;
|
||||
char *parm = parms[0];
|
||||
|
||||
if (parm == NULL || *parm == '\0')
|
||||
{
|
||||
return AREXX_PARAMETER_UNKNOWN;
|
||||
return AREXX_PARAMETER_MISSING;
|
||||
}
|
||||
|
||||
for (i = 0; i < AREXX_PARAMETER_COUNT; i++)
|
||||
@@ -294,68 +483,84 @@ static int ArexxFindParameter(char **parms)
|
||||
return AREXX_PARAMETER_UNKNOWN;
|
||||
}
|
||||
|
||||
static void ArexxGetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxGetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
char buf[MAXLONGLONGCHARSIZE];
|
||||
char *res;
|
||||
int param = ArexxFindParameter(parms);
|
||||
|
||||
int param = ARexxFindParameter(parms++);
|
||||
switch (param)
|
||||
{
|
||||
case AREXX_PARAMETER_UNKNOWN:
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_UNKNOWN;
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
|
||||
break;
|
||||
case AREXX_PARAMETER_MISSING:
|
||||
ARexxError(msg, AREXX_ERROR_PARM_MISS);
|
||||
break;
|
||||
case AREXX_PARAMETER_SERVER:
|
||||
res = Settings->DestinationAddress;
|
||||
ARexxResult(msg, Settings->DestinationAddress);
|
||||
break;
|
||||
case AREXX_PARAMETER_PORT:
|
||||
res = Settings->DestinationPort;
|
||||
break;
|
||||
case AREXX_PARAMETER_THRESHOLD:
|
||||
LongLongToStr(Settings->Threshold, buf);
|
||||
res = buf;
|
||||
ARexxResult(msg, Settings->DestinationPort);
|
||||
break;
|
||||
case AREXX_PARAMETER_INTERVAL:
|
||||
LongToStr(Settings->Interval, buf);
|
||||
res = buf;
|
||||
ARexxResultLong(msg, Settings->Interval);
|
||||
break;
|
||||
case AREXX_PARAMETER_PRIORITY:
|
||||
LongToStr(Settings->Priority, buf);
|
||||
res = buf;
|
||||
ARexxResultLong(msg, Settings->Priority);
|
||||
break;
|
||||
case AREXX_PARAMETER_POPKEY:
|
||||
res = Settings->PopKey;
|
||||
ARexxResult(msg, Settings->PopKey);
|
||||
break;
|
||||
case AREXX_PARAMETER_POPUP:
|
||||
BoolToStr(Settings->Popup, buf);
|
||||
res = buf;
|
||||
ARexxResultBool(msg, *parms, Settings->Popup);
|
||||
break;
|
||||
case AREXX_PARAMETER_READONLY:
|
||||
BoolToStr(Settings->Readonly, buf);
|
||||
res = buf;
|
||||
ARexxResultBool(msg, *parms, Settings->Readonly);
|
||||
break;
|
||||
case AREXX_PARAMETER_EXPERT:
|
||||
BoolToStr(Settings->Expert, buf);
|
||||
res = buf;
|
||||
ARexxResultBool(msg, *parms, Settings->Expert);
|
||||
break;
|
||||
case AREXX_PARAMETER_TIMEOUT:
|
||||
LongToStr(Settings->Timeout, buf);
|
||||
res = buf;
|
||||
ARexxResultLong(msg, Settings->Timeout);
|
||||
break;
|
||||
default:
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_UNKNOWN;
|
||||
case AREXX_PARAMETER_ACTIVE:
|
||||
ARexxResultBool(msg, *parms, SynchronizerRunning);
|
||||
break;
|
||||
}
|
||||
|
||||
if (msg->rm_Result1 != AREXX_COMMAND_PARM_UNKNOWN)
|
||||
case AREXX_PARAMETER_NOLOG:
|
||||
ARexxResultBool(msg, *parms, Settings->NoLog);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZ:
|
||||
ARexxResult(msg, Settings->TZ);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZD:
|
||||
ARexxResultLong(msg, Settings->TimeZoneDisplay);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZNAME:
|
||||
ARexxResult(msg, Settings->TimeZoneName);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZVALUE:
|
||||
if (Settings->TimeZoneValue != TZVALUE_DEF)
|
||||
ARexxResultLong(msg, Settings->TimeZoneValue);
|
||||
else
|
||||
ARexxResult(msg, "");
|
||||
break;
|
||||
case AREXX_PARAMETER_TZDST:
|
||||
ARexxResultLong(msg, Settings->TimeZoneDst);
|
||||
break;
|
||||
case AREXX_PARAMETER_THRESHOLD:
|
||||
{
|
||||
msg->rm_Result2 = (LONG)CreateArgstring((STRPTR)res, (LONG)StrLen(res));
|
||||
char buf[MAXLONGLONGCHARSIZE];
|
||||
LongLongToStr(Settings->Threshold, buf);
|
||||
ARexxResult(msg, buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxSetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxSetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
int param = ArexxFindParameter(parms++);
|
||||
int param = ARexxFindParameter(parms++);
|
||||
char *valueString = *parms;
|
||||
long long longlongValue;
|
||||
long longValue;
|
||||
@@ -364,47 +569,68 @@ static void ArexxSetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
switch (param)
|
||||
{
|
||||
case AREXX_PARAMETER_UNKNOWN:
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_UNKNOWN;
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
|
||||
break;
|
||||
case AREXX_PARAMETER_MISSING:
|
||||
ARexxError(msg, AREXX_ERROR_PARM_MISS);
|
||||
break;
|
||||
case AREXX_PARAMETER_SERVER:
|
||||
SetServer(valueString, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
break;
|
||||
case AREXX_PARAMETER_PORT:
|
||||
SetPort(valueString, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
break;
|
||||
case AREXX_PARAMETER_THRESHOLD:
|
||||
if (TryParseLongLong(valueString, &longlongValue))
|
||||
{
|
||||
SetThreshold(valueString, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_INTERVAL:
|
||||
if (TryParseLong(valueString, &longValue))
|
||||
{
|
||||
SetInterval(longValue, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_PRIORITY:
|
||||
if (TryParseLong(valueString, &longValue))
|
||||
{
|
||||
SetPriority(valueString, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_POPKEY:
|
||||
// TODO: Remove CX filter object and add new filter (Settings->PopKey)
|
||||
// http://amigadev.elowar.com/read/ADCD_2.1/Libraries_Manual_guide/node0587.html
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
|
||||
break;
|
||||
case AREXX_PARAMETER_POPUP:
|
||||
if (TryParseBoolean(valueString, &boolValue))
|
||||
{
|
||||
Settings->Popup = boolValue;
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_READONLY:
|
||||
if (TryParseBoolean(valueString, &boolValue))
|
||||
{
|
||||
Settings->Readonly = boolValue;
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_EXPERT:
|
||||
if (TryParseBoolean(valueString, &boolValue))
|
||||
@@ -412,80 +638,138 @@ static void ArexxSetValueCommand(struct RexxMsg *msg, char **parms)
|
||||
Settings->Expert = boolValue;
|
||||
SendWindowMessage(ATK_SHUTDOWN);
|
||||
ShowSettingWindow();
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_TIMEOUT:
|
||||
if (TryParseLong(valueString, &longValue))
|
||||
{
|
||||
SetTimeout(longValue, APPLY_VALUE);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_INVALID;
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_ACTIVE:
|
||||
if (TryParseBoolean(valueString, &boolValue))
|
||||
{
|
||||
if (boolValue)
|
||||
ARexxStartCommand(msg, NULL);
|
||||
else
|
||||
ARexxStopCommand(msg, NULL);
|
||||
}
|
||||
else
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
break;
|
||||
case AREXX_PARAMETER_NOLOG:
|
||||
if (TryParseBoolean(valueString, &boolValue))
|
||||
{
|
||||
Settings->NoLog = boolValue;
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
ARexxError(msg, AREXX_ERROR_PARM_INV);
|
||||
case AREXX_PARAMETER_TZ:
|
||||
SetTimeZoneSetting(SettingKeys->TZ, &Settings->TZ, valueString, APPLY_VALUE);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZD:
|
||||
SetTimeZoneSettingLong(SettingKeys->TimeZoneDisplay, &Settings->TimeZoneDisplay, valueString, APPLY_VALUE);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZNAME:
|
||||
SetTimeZoneSetting(SettingKeys->TimeZoneName, &Settings->TimeZoneName, valueString, APPLY_VALUE);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZVALUE:
|
||||
SetTimeZoneSettingLong(SettingKeys->TimeZoneValue, &Settings->TimeZoneValue, valueString, APPLY_VALUE);
|
||||
break;
|
||||
case AREXX_PARAMETER_TZDST:
|
||||
SetTimeZoneSettingLong(SettingKeys->TimeZoneDst, &Settings->TimeZoneDst, valueString, APPLY_VALUE);
|
||||
break;
|
||||
default:
|
||||
msg->rm_Result1 = AREXX_COMMAND_PARM_UNKNOWN;
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_PARM);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxShowCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxShowCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
ShowSettingWindow();
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
|
||||
static void ArexxHideCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxHideCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
SendWindowMessage(ATK_SHUTDOWN);
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
|
||||
static void ArexxStartCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxStartCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
if (!SynchronizerRunning)
|
||||
{
|
||||
Activate();
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Set error text
|
||||
msg->rm_Result1 = AREXX_COMMAND_ERROR;
|
||||
ARexxError(msg, AREXX_ERROR_SYNC_ON);
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxStopCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxStopCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
if (SynchronizerRunning)
|
||||
{
|
||||
Deactivate();
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Set error text
|
||||
msg->rm_Result1 = AREXX_COMMAND_ERROR;
|
||||
ARexxError(msg, AREXX_ERROR_SYNC_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
static void ArexxShutdownCommand(struct RexxMsg *msg, char **parms)
|
||||
static void ARexxShutdownCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
LogWarn("Requesting shutdown");
|
||||
msg->rm_Result1 = AREXX_COMMAND_SHUTDOWN;
|
||||
LogWarn(TextARexxShutdown);
|
||||
msg->rm_Result1 = AREXX_PARAMETER_SHUTDOWN;
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
|
||||
static bool HandleArexxMessage(struct RexxMsg *msg)
|
||||
static void ARexxLogTransitionsCommand(struct RexxMsg *msg, char **parms)
|
||||
{
|
||||
LogTransitionMap();
|
||||
ARexxErrorClear(msg);
|
||||
}
|
||||
|
||||
static void ExecuteARexxCommand(struct RexxMsg *msg, struct ARexxCommandDef *cmd, char **parms)
|
||||
{
|
||||
LogNotice(TextARexxReceived, cmd->Name);
|
||||
|
||||
bool execute = !cmd->ResultCommand || (cmd->ResultCommand && (msg->rm_Action & RXFF_RESULT));
|
||||
if (execute)
|
||||
{
|
||||
if (parms == NULL)
|
||||
LogTrace(TextARexxExecute1, cmd->Name);
|
||||
else
|
||||
LogTrace(TextARexxExecute2, cmd->Name, *parms);
|
||||
cmd->Command(msg, parms);
|
||||
}
|
||||
}
|
||||
|
||||
static bool HandleARexxMessage(struct RexxMsg *msg)
|
||||
{
|
||||
int i;
|
||||
bool found = false;
|
||||
bool cont = true;
|
||||
|
||||
msg->rm_Result1 = AREXX_COMMAND_UNKNOWN;
|
||||
msg->rm_Result2 = 0;
|
||||
|
||||
for (i = 0; i < AREXX_COMMAND_COUNT; i++)
|
||||
{
|
||||
if (arexxCommands[i].Parameters == 0 && Stricmp((STRPTR)msg->rm_Args[0], (STRPTR)arexxCommands[i].Name) == 0)
|
||||
struct ARexxCommandDef *cmd = &arexxCommands[i];
|
||||
if (cmd->Parameters == 0 && Stricmp((STRPTR)msg->rm_Args[0], (STRPTR)cmd->Name) == 0)
|
||||
{
|
||||
LogNotice("Received %s", arexxCommands[i].Name);
|
||||
msg->rm_Result1 = AREXX_COMMAND_OK;
|
||||
arexxCommands[i].Command(msg, NULL);
|
||||
ExecuteARexxCommand(msg, cmd, NULL);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -497,7 +781,7 @@ static bool HandleArexxMessage(struct RexxMsg *msg)
|
||||
char *buf = AllocStringSafe(StrLen(msg->rm_Args[0]) + 1);
|
||||
|
||||
StrCopy(buf, msg->rm_Args[0]);
|
||||
for (i = 1; i < AREXX_MAX_ARGS_COUNT; i++)
|
||||
for (i = 0; i < AREXX_MAX_ARGS_COUNT; i++)
|
||||
{
|
||||
args[i] = NULL;
|
||||
}
|
||||
@@ -505,11 +789,10 @@ static bool HandleArexxMessage(struct RexxMsg *msg)
|
||||
SplitAndTerminate(buf, args);
|
||||
for (i = 0; i < AREXX_COMMAND_COUNT; i++)
|
||||
{
|
||||
if (arexxCommands[i].Parameters > 0 && Stricmp((STRPTR)buf, (STRPTR)arexxCommands[i].Name) == 0)
|
||||
struct ARexxCommandDef *cmd = &arexxCommands[i];
|
||||
if (cmd->Parameters > 0 && Stricmp((STRPTR)buf, (STRPTR)cmd->Name) == 0)
|
||||
{
|
||||
LogNotice("Received %s", arexxCommands[i].Name);
|
||||
msg->rm_Result1 = AREXX_COMMAND_OK;
|
||||
arexxCommands[i].Command(msg, args);
|
||||
ExecuteARexxCommand(msg, cmd, args);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
@@ -518,9 +801,12 @@ static bool HandleArexxMessage(struct RexxMsg *msg)
|
||||
FreeMemSafe(buf);
|
||||
}
|
||||
|
||||
if (msg->rm_Result1 == AREXX_COMMAND_SHUTDOWN)
|
||||
if (!found)
|
||||
{
|
||||
ARexxError(msg, AREXX_ERROR_UNKNOWN_CMD);
|
||||
}
|
||||
else if (msg->rm_Result1 == AREXX_PARAMETER_SHUTDOWN)
|
||||
{
|
||||
msg->rm_Result1 = AREXX_COMMAND_OK;
|
||||
cont = false;
|
||||
}
|
||||
|
||||
@@ -534,7 +820,11 @@ bool HandleARexxMessages(void)
|
||||
|
||||
while ((msg = (struct RexxMsg *)GetNewMessage(MSGPORT_AREXX)))
|
||||
{
|
||||
cont &= HandleArexxMessage(msg);
|
||||
if (CheckRexxMsg(msg))
|
||||
{
|
||||
cont &= HandleARexxMessage(msg);
|
||||
msg->rm_Result1 = RC_OK;
|
||||
}
|
||||
ReplyMsg((struct Message *)msg);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Set TZ to Australian Central time zone */
|
||||
SAY ('Changing to Australian Central time zone ...')
|
||||
Address TIMEKEEPER.1 'SET TZ ACST-9'
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Set TZ to Central European time zone */
|
||||
SAY ('Changing to Central European time zone ...')
|
||||
Address TIMEKEEPER.1 'SET TZ CET-1CEST,M3.5.0,M10.5.0/3'
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Set TZ to Australian Eastern time zone */
|
||||
SAY ('Changing to Australian Eastern time zone ...')
|
||||
Address TIMEKEEPER.1 'SET TZ AEST-10AEDT,M10.1.0,M4.1.0/3'
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Set TZ to North East American time zone */
|
||||
SAY ('Changing to North East American time zone ...')
|
||||
Address TIMEKEEPER.1 'SET TZ EST5EDT,M3.2.0,M11.1.0'
|
||||
@@ -0,0 +1,23 @@
|
||||
/* Test time zone settings */
|
||||
SAY ('Testing time zone values ...')
|
||||
|
||||
Address TIMEKEEPER.1 SET TZ
|
||||
Address TIMEKEEPER.1'SET TZ CET-1'
|
||||
Address TIMEKEEPER.1'SET TZ CET-1CEST'
|
||||
Address TIMEKEEPER.1'SET TZ <GMT+3>-3'
|
||||
|
||||
Address TIMEKEEPER.1 'SET TZ CST6CDT,M3.2.0,M11.1.0'
|
||||
Address TIMEKEEPER.1 'SET TZ MST7MDT,M3.2.0,M11.1.0'
|
||||
Address TIMEKEEPER.1 'SET TZ AEST-10AEDT,M10.1.0,M4.1.0/3'
|
||||
Address TIMEKEEPER.1 'SET TZ NZST-12NZDT,M9.5.0,M4.1.0/3'
|
||||
Address TIMEKEEPER.1'SET TZ GMT0'
|
||||
|
||||
Address TIMEKEEPER.1 SET TZVALUE 10000
|
||||
Address TIMEKEEPER.1 'SET TZVALUE -10000'
|
||||
Address TIMEKEEPER.1 SET TZVALUE 200
|
||||
Address TIMEKEEPER.1 'SET TZVALUE -200'
|
||||
|
||||
Address TIMEKEEPER.1 'SET TZDST -1'
|
||||
Address TIMEKEEPER.1 SET TZDST 0
|
||||
Address TIMEKEEPER.1 SET TZDST 1
|
||||
Address TIMEKEEPER.1 'SET TZDST -1'
|
||||
@@ -0,0 +1,4 @@
|
||||
/* Show TimeKeeper synchronization status */
|
||||
Options RESULTS
|
||||
Address TIMEKEEPER.1 'GET ACTIVE'; SAY ('ACTIVE (YES/NO):' RESULT);
|
||||
Address TIMEKEEPER.1 'GET ACTIVE NUMBER'; SAY ('ACTIVE (0/1):' RESULT);
|
||||
@@ -0,0 +1,5 @@
|
||||
/* Show the NTP server address in use */
|
||||
Options RESULTS
|
||||
Address TIMEKEEPER.1 'GET SERVER';
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY (RESULT)
|
||||
ELSE SAY (TIMEKEEPER.ERRORTEXT)
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
/* Show the ARexx commands supported by TimeKeeper */
|
||||
Options RESULTS
|
||||
Address TIMEKEEPER.1 'help'
|
||||
Address TIMEKEEPER.1 HELP
|
||||
SAY (RESULT)
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
/* Hide TimeKeeper settings window */
|
||||
Address TIMEKEEPER.1 HIDE
|
||||
+17
-1
@@ -1,3 +1,19 @@
|
||||
/* Show when the last response from a NTP server was received */
|
||||
Options RESULTS
|
||||
Address TIMEKEEPER.1 'LastSync'; SAY (RESULT)
|
||||
Address TIMEKEEPER.1 'LastSync'
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY (RESULT)
|
||||
ELSE SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
Address TIMEKEEPER.1 LASTSYNC RFC3339
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY ('Time and date in RFC 3339 format:' RESULT)
|
||||
ELSE SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
Address TIMEKEEPER.1 LASTSYNC DATE
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY ('Sorted date (in the form YYYYMMDD):' RESULT)
|
||||
ELSE SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
Address TIMEKEEPER.1 LASTSYNC TIME
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY ('Time in seconds since midnight:' RESULT)
|
||||
ELSE SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
|
||||
|
||||
+10
-3
@@ -9,6 +9,13 @@ Address TIMEKEEPER.1 'get threshold'; SAY ('THRESHOLD =' RESULT 'microseconds')
|
||||
Address TIMEKEEPER.1 'get ReadOnly'; SAY ('READONLY =' RESULT)
|
||||
Address TIMEKEEPER.1 'get Expert'; SAY ('EXPERT =' RESULT)
|
||||
Address TIMEKEEPER.1 'get timeout'; SAY ('TIMEOUT =' RESULT 'milliseconds')
|
||||
Address TIMEKEEPER.1 'get CX_POPUP'; SAY ('POPUP =' RESULT)
|
||||
Address TIMEKEEPER.1 'get CX_POPKEY'; SAY ('POPKEY =' RESULT)
|
||||
Address TIMEKEEPER.1 'get CX_PRIORITY'; SAY ('PRIORITY =' RESULT)
|
||||
Address TIMEKEEPER.1 GET CX_POPUP; SAY ('POPUP =' RESULT)
|
||||
Address TIMEKEEPER.1 GET CX_POPKEY; SAY ('POPKEY =' RESULT)
|
||||
Address TIMEKEEPER.1 GET CX_PRIORITY; SAY ('PRIORITY =' RESULT)
|
||||
Address TIMEKEEPER.1 GET ACTIVE; SAY ('ACTIVE =' RESULT)
|
||||
Address TIMEKEEPER.1 GET NOLOG; SAY ('NOLOG =' RESULT)
|
||||
Address TIMEKEEPER.1 GET TZD; SAY ('TZD =' RESULT)
|
||||
Address TIMEKEEPER.1 GET TZ; SAY ('TZ =' RESULT)
|
||||
Address TIMEKEEPER.1 GET TZNAME; SAY ('TZNAME =' RESULT)
|
||||
Address TIMEKEEPER.1 GET TZVALUE; SAY ('TZVALUE =' RESULT)
|
||||
Address TIMEKEEPER.1 GET TZDST; SAY ('TZDST =' RESULT)
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
/* Start TimeKeeper synchronization */
|
||||
SAY ('Starting TimeKeeper synchronization ...')
|
||||
Address TIMEKEEPER.1 'start'
|
||||
Address TIMEKEEPER.1 START
|
||||
IF TIMEKEEPER.ERRORCODE ~= 0 THEN SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
+9
-2
@@ -1,5 +1,12 @@
|
||||
/* Show TimeKeeper synchronization status */
|
||||
Options RESULTS
|
||||
|
||||
Address TIMEKEEPER.1 'status'; SAY (RESULT)
|
||||
Address TIMEKEEPER.1 'LastSync'; SAY ('Last response from NTP server was:' RESULT)
|
||||
Address TIMEKEEPER.1 'LastAdjust'; SAY ('Last clock adjustment was:' RESULT)
|
||||
|
||||
Address TIMEKEEPER.1 'LastSync'
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY ('Last response from NTP server was:' RESULT)
|
||||
ELSE SAY ('LastSync:' TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
Address TIMEKEEPER.1 'LastAdj'
|
||||
IF TIMEKEEPER.ERRORCODE == 0 THEN SAY ('Last clock adjustment was:' RESULT)
|
||||
ELSE SAY ('LastAdj:' TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
+2
-1
@@ -1,3 +1,4 @@
|
||||
/* Stop TimeKeeper synchronization */
|
||||
SAY ('Stopping TimeKeeper synchronization ...')
|
||||
Address TIMEKEEPER.1 'stop'
|
||||
Address TIMEKEEPER.1 STOP
|
||||
IF TIMEKEEPER.ERRORCODE ~= 0 THEN SAY (TIMEKEEPER.ERRORTEXT)
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
/* Show current date and time */
|
||||
Options RESULTS
|
||||
|
||||
Address TIMEKEEPER.1 NOW ASCII LOCAL; SAY ('ASCII style:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW ASCII UTC; SAY ('ASCII style (UTC):' RESULT)
|
||||
Address TIMEKEEPER.1 NOW DOS LOCAL; SAY ('DOS style:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW DOS UTC; SAY ('DOS style (UTC):' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC850; SAY ('RFC850:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC1123; SAY ('RFC1123:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC2822 LOCAL; SAY ('RFC2822:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC2822 UTC; SAY ('RFC2822:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC3339 LOCAL; SAY ('RFC3339:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW RFC3339 UTC; SAY ('RFC3339:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW ISO8601 LOCAL; SAY ('ISO8601:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW ISO8601 UTC; SAY ('ISO8601:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW DATE LOCAL; SAY ('ARexx compatible sorted date:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW DATE UTC; SAY ('ARexx compatible sorted date (UTC):' RESULT)
|
||||
Address TIMEKEEPER.1 NOW TIME LOCAL; SAY ('ARexx compatible time in seconds since midnight:' RESULT)
|
||||
Address TIMEKEEPER.1 NOW TIME UTC; SAY ('ARexx compatible time in seconds since midnight (UTC):' RESULT)
|
||||
+12
-1
@@ -1,3 +1,14 @@
|
||||
/* Show current timezone in TimeKeeper */
|
||||
Options RESULTS
|
||||
Address TIMEKEEPER.1 'timezone'; SAY (RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 1; SAY (' 1:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 2; SAY (' 2:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 3; SAY (' 3:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 4; SAY (' 4:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 5; SAY (' 5:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 6; SAY (' 6:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 7; SAY (' 7:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 8; SAY (' 8:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 9; SAY (' 9:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 10; SAY ('10:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 11; SAY ('11:' RESULT)
|
||||
Address TIMEKEEPER.1 TIMEZONE 12; SAY ('12:' RESULT)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
/* Show time zone transition map in log */
|
||||
SAY ('Writing time zone transition map to log')
|
||||
Address TIMEKEEPER.1 LOGTRANS
|
||||
@@ -118,7 +118,7 @@ void StartBroker(void)
|
||||
LogError("System problems (CBERR_SYSERR). Could not allocate broker object");
|
||||
break;
|
||||
case CBERR_DUP:
|
||||
LogWarn(APP_SHORT_NAME " is already running");
|
||||
LogWarn(Text2P, APP_SHORT_NAME, TextAlreadyRunning);
|
||||
break;
|
||||
default:
|
||||
LogError("Could not allocate broker object (error code: %ld)", error);
|
||||
@@ -186,7 +186,12 @@ void StartBroker(void)
|
||||
#endif
|
||||
|
||||
ActivateNotifyPort(Broker.NotifyPort);
|
||||
StartSynchronizer();
|
||||
|
||||
if (Settings->Active)
|
||||
{
|
||||
ActivateCxObj(Broker.Object, 1);
|
||||
StartSynchronizer();
|
||||
}
|
||||
|
||||
MsgLoop();
|
||||
|
||||
@@ -207,14 +212,14 @@ void Deactivate(void)
|
||||
{
|
||||
if (SynchronizerRunning)
|
||||
{
|
||||
LogNotice("ACTIVE changed: 1 -> 0");
|
||||
LogNotice(KEYWORD_ACTIVE " changed: 1 -> 0");
|
||||
LogWarn("Disabling time synchronization");
|
||||
SendMessageWait(MSGPORT_SYNCER, ATK_DISABLE);
|
||||
ActivateCxObj(Broker.Object, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Synchronization is already deactivated");
|
||||
LogError(TextSyncAlreadyOff);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,30 +227,26 @@ void Activate(void)
|
||||
{
|
||||
if (!SynchronizerRunning)
|
||||
{
|
||||
LogNotice("ACTIVE changed: 0 -> 1");
|
||||
LogNotice(KEYWORD_ACTIVE " changed: 0 -> 1");
|
||||
LogWarn("Enabling time synchronization");
|
||||
ActivateCxObj(Broker.Object, 1);
|
||||
StartSynchronizer();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogError("Synchronization is already active");
|
||||
LogError(TextSyncAlreadyOn);
|
||||
}
|
||||
}
|
||||
|
||||
static void ChangeTimezone(void)
|
||||
{
|
||||
// TODO: Make thread safe
|
||||
CleanupTimezone();
|
||||
InitTimezone();
|
||||
SendWindowMessage(ATK_TZ_CHANGED);
|
||||
}
|
||||
|
||||
static void ChangeTimezoneDelayedProc(void)
|
||||
{
|
||||
// TODO: Make thread safe
|
||||
Delay(15 * 50);
|
||||
ReopenLocale();
|
||||
ChangeTimezone();
|
||||
SendWindowMessage(ATK_TZ_CHANGED);
|
||||
}
|
||||
@@ -382,9 +383,7 @@ static void MsgLoop(void)
|
||||
BrokerRunning = true;
|
||||
LogTrace("Loop started");
|
||||
|
||||
ActivateCxObj(Broker.Object, 1);
|
||||
|
||||
if (Settings->Popup)
|
||||
if (Settings->Popup || Settings->PopupOnStart)
|
||||
{
|
||||
ShowSettingWindow();
|
||||
}
|
||||
@@ -486,7 +485,6 @@ static void MsgLoop(void)
|
||||
{
|
||||
ShowSettingWindow();
|
||||
}
|
||||
ReopenLocale();
|
||||
ChangeTimezone();
|
||||
reopenWindow = false;
|
||||
}
|
||||
|
||||
+3
-2
@@ -58,7 +58,8 @@ typedef int bool;
|
||||
#define StrCopy(dest, src) strcpy((char *)dest, (const char *)src)
|
||||
#endif
|
||||
|
||||
#define MAXLONGCHARSIZE 12
|
||||
#define MAXLONGLONGCHARSIZE 22
|
||||
#define MAXLONGCHARSIZE 13
|
||||
#define MAXLONGLONGCHARSIZE 23
|
||||
#define MAXBOOLCHARSIZE 4
|
||||
|
||||
#endif
|
||||
|
||||
@@ -160,8 +160,8 @@ int poll(struct pollfd *, nfds_t, int);
|
||||
#define APP_LONG_NAME "Amiga Time Keeper"
|
||||
#endif
|
||||
|
||||
#define APP_VERSION "1.11"
|
||||
#define APP_DATE_VERSION "1.11 (11.01.2021)"
|
||||
#define APP_VERSION "1.12"
|
||||
#define APP_DATE_VERSION "1.12 (31.01.2021)"
|
||||
#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
|
||||
@@ -169,7 +169,7 @@ int poll(struct pollfd *, nfds_t, int);
|
||||
#include "log.h"
|
||||
#include "string.h"
|
||||
|
||||
#define KEYWORD_COUNT 10
|
||||
#define KEYWORD_COUNT 18
|
||||
#define KEYWORD_SERVER "SERVER"
|
||||
#define KEYWORD_PORT "PORT"
|
||||
#define KEYWORD_THRESHOLD "THRESHOLD"
|
||||
@@ -180,6 +180,35 @@ int poll(struct pollfd *, nfds_t, int);
|
||||
#define KEYWORD_READONLY "READONLY"
|
||||
#define KEYWORD_EXPERT "EXPERT"
|
||||
#define KEYWORD_TIMEOUT "TIMEOUT"
|
||||
#define KEYWORD_ACTIVE "ACTIVE"
|
||||
#define KEYWORD_NOLOG "NOLOG"
|
||||
#define KEYWORD_TZ "TZ"
|
||||
#define KEYWORD_TZD "TZD"
|
||||
#define KEYWORD_TZNAME "TZNAME"
|
||||
#define KEYWORD_TZVALUE "TZVALUE"
|
||||
#define KEYWORD_TZDST "TZDST"
|
||||
#define KEYWORD_POPUP2 "POPUP"
|
||||
|
||||
#define KEYWORD_FROM "FROM"
|
||||
|
||||
#define KEYWORD_TZ_ALIAS "TIMEZONE"
|
||||
#define KEYWORD_TZD_ALIAS "TIMEZONEDISPLAY"
|
||||
#define KEYWORD_TZNAME_ALIAS "TIMEZONEABBREVIATION"
|
||||
#define KEYWORD_TZVALUE_ALIAS "TIMEZONEVALUE"
|
||||
#define KEYWORD_TZDST_ALIAS "DST"
|
||||
|
||||
#define KEYWORD_NUMBER "NUMBER"
|
||||
#define KEYWORD_DATE "DATE"
|
||||
#define KEYWORD_TIME "TIME"
|
||||
#define KEYWORD_DOS "DOS"
|
||||
#define KEYWORD_ASCII "ASCII"
|
||||
#define KEYWORD_RFC850 "RFC850"
|
||||
#define KEYWORD_RFC1123 "RFC1123"
|
||||
#define KEYWORD_RFC2822 "RFC2822"
|
||||
#define KEYWORD_RFC3339 "RFC3339"
|
||||
#define KEYWORD_ISO8601 "ISO8601"
|
||||
#define KEYWORD_LOCAL "LOCAL"
|
||||
#define KEYWORD_UTC "UTC"
|
||||
|
||||
#define SERVER_DEF "pool.ntp.org"
|
||||
#define PORT_DEF "123"
|
||||
@@ -187,27 +216,73 @@ int poll(struct pollfd *, nfds_t, int);
|
||||
#define THRESHOLD_DEF 1000000LL
|
||||
#define INTERVAL_MIN 500
|
||||
#define INTERVAL_DEF 17500
|
||||
#define INTERVAL_MAX 2 * 24 * 60 * 60 * 1000
|
||||
#define PRIORITY_MIN -128
|
||||
#define PRIORITY_DEF 25
|
||||
#define PRIORITY_MAX 127
|
||||
#define READONLY_DEF 0
|
||||
#define EXPERT_DEF 0
|
||||
#define ACTIVE_DEF 0
|
||||
#define NOLOG_DEF 0
|
||||
#define TIMEOUT_MIN 100
|
||||
#define TIMEOUT_DEF 5000
|
||||
#define TIMEOUT_MAX 30000
|
||||
#define POPKEY_DEF "lshift control t"
|
||||
#define POPUP_DEF 0
|
||||
#define TZ_DEF ""
|
||||
#define TZD_MIN 1
|
||||
#define TZD_DEF 9
|
||||
#define TZD_MAX 10
|
||||
#define TZNAME_DEF ""
|
||||
#define TZVALUE_MIN -2400
|
||||
#define TZVALUE_DEF 16800
|
||||
#define TZVALUE_MAX 2400
|
||||
#define TZDST_DEF -1
|
||||
|
||||
#define KEYWORD_TEMPLATE_1 KEYWORD_READONLY "/S," KEYWORD_EXPERT "/S," KEYWORD_SERVER "/K," KEYWORD_PORT "/K," KEYWORD_TIMEOUT "/N/K,"
|
||||
#define KEYWORD_TEMPLATE_2 KEYWORD_THRESHOLD "/K," KEYWORD_INTERVAL "/N/K,"
|
||||
#define KEYWORD_TEMPLATE_3 KEYWORD_PRIORITY "/N/K," KEYWORD_POPKEY "/K," KEYWORD_POPUP "/K,"
|
||||
#define KEYWORD_TEMPLATE KEYWORD_TEMPLATE_1 KEYWORD_TEMPLATE_2 KEYWORD_TEMPLATE_3
|
||||
#define KWD_TMPL_01 KEYWORD_READONLY "/S,"
|
||||
#define KWD_TMPL_02 KEYWORD_EXPERT "/S,"
|
||||
#define KWD_TMPL_03 KEYWORD_ACTIVE "/S,"
|
||||
#define KWD_TMPL_04 KEYWORD_NOLOG "/S,"
|
||||
#define KWD_TMPL_05 KEYWORD_SERVER "/K,"
|
||||
#define KWD_TMPL_06 KEYWORD_PORT "/K,"
|
||||
#define KWD_TMPL_07 KEYWORD_TIMEOUT "/N/K,"
|
||||
#define KWD_TMPL_08 KEYWORD_THRESHOLD "/K,"
|
||||
#define KWD_TMPL_09 KEYWORD_INTERVAL "/N/K,"
|
||||
#define KWD_TMPL_10 KEYWORD_PRIORITY "/N/K,"
|
||||
#define KWD_TMPL_11 KEYWORD_POPKEY "/K,"
|
||||
#define KWD_TMPL_12 KEYWORD_POPUP "/K,"
|
||||
#define KWD_TMPL_13 KEYWORD_TZ_ALIAS "=" KEYWORD_TZ "/K,"
|
||||
#define KWD_TMPL_14 KEYWORD_TZD_ALIAS "=" KEYWORD_TZD "/N/K,"
|
||||
#define KWD_TMPL_15 KEYWORD_TZNAME_ALIAS "=" KEYWORD_TZNAME "/K,"
|
||||
#define KWD_TMPL_16 KEYWORD_TZVALUE_ALIAS "=" KEYWORD_TZVALUE "/N/K,"
|
||||
#define KWD_TMPL_17 KEYWORD_TZDST_ALIAS "=" KEYWORD_TZDST "/N/K,"
|
||||
#define KWD_TMPL_18 KEYWORD_POPUP2 "/S"
|
||||
|
||||
#define KWD_TMPL \
|
||||
KWD_TMPL_01 \
|
||||
KWD_TMPL_02 \
|
||||
KWD_TMPL_03 \
|
||||
KWD_TMPL_04 \
|
||||
KWD_TMPL_05 \
|
||||
KWD_TMPL_06 \
|
||||
KWD_TMPL_07 \
|
||||
KWD_TMPL_08 \
|
||||
KWD_TMPL_09 \
|
||||
KWD_TMPL_10 \
|
||||
KWD_TMPL_11 \
|
||||
KWD_TMPL_12 \
|
||||
KWD_TMPL_13 \
|
||||
KWD_TMPL_14 \
|
||||
KWD_TMPL_15 \
|
||||
KWD_TMPL_16 \
|
||||
KWD_TMPL_17 \
|
||||
KWD_TMPL_18
|
||||
|
||||
struct ControlMesage;
|
||||
|
||||
/* arexx.c */
|
||||
bool HandleARexxMessages(void);
|
||||
void CleanupArexx(void);
|
||||
void CleanupARexx(void);
|
||||
|
||||
/* broker.c */
|
||||
void StartBroker(void);
|
||||
@@ -222,6 +297,5 @@ bool HandleControlMessages(void);
|
||||
/* libraries.c */
|
||||
int OpenLibraries(void);
|
||||
void CloseLibraries(void);
|
||||
void ReopenLocale(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -109,6 +109,25 @@ int BoolToStr(bool value, char *string)
|
||||
return count;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a boolean to a null terminated numeral string.
|
||||
*/
|
||||
int BoolToStrNum(bool value, char *string)
|
||||
{
|
||||
char *s = string;
|
||||
|
||||
if (s == NULL)
|
||||
return 0;
|
||||
|
||||
if (value)
|
||||
*s++ = '1';
|
||||
else
|
||||
*s++ = '0';
|
||||
|
||||
*s = '\0';
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a long to a null terminated string.
|
||||
*/
|
||||
|
||||
@@ -33,6 +33,7 @@ bool TryParseBoolean(char *, bool *);
|
||||
bool TryParseLong(char *, long *);
|
||||
bool TryParseLongLong(char *, long long *);
|
||||
int BoolToStr(bool, char *);
|
||||
int BoolToStrNum(bool, char *);
|
||||
int LongToStr(signed long, char *);
|
||||
int LongLongToStr(signed long long, char *);
|
||||
int StrToLongLong(char *, unsigned long long *);
|
||||
|
||||
@@ -37,9 +37,9 @@
|
||||
#include "message.h"
|
||||
#include "string.h"
|
||||
|
||||
const char *vers = "\0$VER: TimeControl 1.11 (11.01.2021)";
|
||||
const char *vers = "\0$VER: TimeControl 1.12 (31.01.2021)";
|
||||
|
||||
#define ARGSFORMAT "ID/S,VERSION/S,STATUS/S,START/S,STOP/S,SHOW/S,HIDE/S,SHUTDOWN/S"
|
||||
#define ARGSFORMAT "ID/S,VERSION/S,STATUS/S,TIME/S,ZONE/S,START/S,STOP/S,SHOW/S,HIDE/S,SHUTDOWN/S"
|
||||
|
||||
struct RDArgs *rdargs = NULL;
|
||||
struct MsgPort *replyPort = NULL;
|
||||
@@ -50,6 +50,8 @@ struct progargs
|
||||
long id;
|
||||
long version;
|
||||
long status;
|
||||
long time;
|
||||
long timezone;
|
||||
long start;
|
||||
long stop;
|
||||
long show;
|
||||
@@ -62,6 +64,8 @@ void InitializeArgs(struct progargs *args)
|
||||
args->id = FALSE;
|
||||
args->version = FALSE;
|
||||
args->status = FALSE;
|
||||
args->time = FALSE;
|
||||
args->timezone = FALSE;
|
||||
args->start = FALSE;
|
||||
args->stop = FALSE;
|
||||
args->show = FALSE;
|
||||
@@ -107,7 +111,7 @@ void SendControlMessage(struct ControlMesage *message)
|
||||
|
||||
if (message->Code == ATK_CTRL_UNKNOWN)
|
||||
{
|
||||
Printf((STRPTR) APP_SHORT_NAME " could not process control command.\n");
|
||||
Printf((STRPTR)APP_SHORT_NAME " could not process control command.\n");
|
||||
}
|
||||
else if (*message->Result != '\0')
|
||||
{
|
||||
@@ -195,6 +199,18 @@ void ProcessArgs(struct progargs *args)
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
if (args->time)
|
||||
{
|
||||
SendSimpleMessage(ATK_TIME);
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
if (args->timezone)
|
||||
{
|
||||
SendSimpleMessage(ATK_TIMEZONE);
|
||||
processed = TRUE;
|
||||
}
|
||||
|
||||
if (args->show)
|
||||
{
|
||||
SendSimpleMessage(ATK_SHOW);
|
||||
@@ -262,7 +278,7 @@ int main(int argc, char **argv)
|
||||
port = FindPort((CONST_STRPTR)CONTROL_PORT_NAME);
|
||||
if (port == NULL)
|
||||
{
|
||||
Printf((STRPTR) APP_SHORT_NAME " is not running.\n");
|
||||
Printf((STRPTR)APP_SHORT_NAME " is not running.\n");
|
||||
Cleanup();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -26,9 +26,12 @@
|
||||
|
||||
#include "config.h"
|
||||
#include "message.h"
|
||||
#include "global.h"
|
||||
#include "locale.h"
|
||||
#include "text.h"
|
||||
#include "sync.h"
|
||||
#include "win.h"
|
||||
#include "mem.h"
|
||||
|
||||
#include "logmod.h"
|
||||
#define MODULENAME "Control"
|
||||
@@ -49,6 +52,22 @@ static bool HandleControlMessage(struct ControlMesage *msg)
|
||||
StrCopy(msg->Result, APP_VERSION);
|
||||
msg->Code = ATK_CTRL_OK;
|
||||
break;
|
||||
case ATK_TIME:
|
||||
LogDebug("Time request");
|
||||
char *time = GetTimeText(LOCAL_TIME_NOW);
|
||||
StrCopy(msg->Result, time);
|
||||
FreeMemSafe(time);
|
||||
msg->Code = ATK_CTRL_OK;
|
||||
break;
|
||||
case ATK_TIMEZONE:
|
||||
LogDebug("Timezone request");
|
||||
{
|
||||
char buf[TIMEZONE_TEXT_LEN];
|
||||
GetTimezoneText(buf, TZD_SECONDS_AHEAD);
|
||||
StrCopy(msg->Result, buf);
|
||||
}
|
||||
msg->Code = ATK_CTRL_OK;
|
||||
break;
|
||||
case ATK_STATUS:
|
||||
LogDebug("Status request");
|
||||
if (SynchronizerRunning)
|
||||
|
||||
@@ -32,6 +32,5 @@
|
||||
|
||||
#include <proto/exec.h>
|
||||
|
||||
struct AppLocale *AppLocale;
|
||||
struct PosixTimezone *Timezone;
|
||||
struct PosixTransitionTime *NextTransition;
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <exec/ports.h>
|
||||
#include "locale.h"
|
||||
|
||||
extern struct AppLocale *AppLocale;
|
||||
extern struct PosixTimezone *Timezone;
|
||||
extern struct PosixTransitionTime *NextTransition;
|
||||
extern struct Library *BattClockBase;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -27,6 +27,7 @@
|
||||
#include "config.h"
|
||||
#include "global.h"
|
||||
#include "timer.h"
|
||||
#include "text.h"
|
||||
#include "ptz.h"
|
||||
#include "mem.h"
|
||||
|
||||
@@ -85,9 +86,6 @@
|
||||
#define LIBREV 34L
|
||||
#endif
|
||||
|
||||
#ifndef CURRENTLOCALE
|
||||
#define CURRENTLOCALE "Current Locale Info"
|
||||
#endif
|
||||
#ifndef NOAREXX
|
||||
#define NOAREXX "No ARexx library found"
|
||||
#endif
|
||||
@@ -110,54 +108,25 @@ struct Device *TimerDevice = NULL;
|
||||
|
||||
static void OpenLibrarySuccess(char *name, char *ident)
|
||||
{
|
||||
if (ident == NULL)
|
||||
{
|
||||
LogDebug("Opened %s", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("Opened %s", ident);
|
||||
}
|
||||
}
|
||||
|
||||
static void OpenLibraryError(char *name, long version)
|
||||
{
|
||||
char message[64];
|
||||
SNPrintf(message, 63, "Cannot open %s %ld.0", name, version);
|
||||
Printf((STRPTR)message);
|
||||
LogError(message);
|
||||
LogDebug(Text2P, TextOpened, (ident == NULL ? name : ident));
|
||||
}
|
||||
|
||||
static void ClosingLibrary(char *name, char *ident)
|
||||
{
|
||||
if (ident == NULL)
|
||||
{
|
||||
LogDebug("Closing %s", name);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("Closing %s", ident);
|
||||
}
|
||||
LogDebug(Text2P, TextClosing, (ident == NULL ? name : ident));
|
||||
}
|
||||
|
||||
static void OpenResourceSuccess(char *name)
|
||||
static void OpenLibraryError(char *name, long version)
|
||||
{
|
||||
LogDebug("Opened %s", name);
|
||||
}
|
||||
|
||||
static void OpenResourceError(char *name)
|
||||
{
|
||||
LogError("Cannot open %s", name);
|
||||
}
|
||||
|
||||
static void ClosingResource(char *name)
|
||||
{
|
||||
LogDebug("Closing %s", name);
|
||||
char message[128];
|
||||
SNPrintf(message, 127, "%s %s %ld.0", TextNoOpen, name, version);
|
||||
Printf((STRPTR)message);
|
||||
LogError(message);
|
||||
}
|
||||
|
||||
int OpenLibraries(void)
|
||||
{
|
||||
LogInfo("Starting up");
|
||||
LogInfo(Text2P, TextStarting, "up");
|
||||
|
||||
// DOS Library
|
||||
if (!(DOSBase2 = (struct DosLibrary *)OpenLibrary((STRPTR)DOSNAME, LIBREV)))
|
||||
@@ -234,27 +203,19 @@ int OpenLibraries(void)
|
||||
LogWarn(NOAREXX);
|
||||
}
|
||||
|
||||
// Locale
|
||||
if (!(AppLocale = OpenAppLocale(NULL)))
|
||||
{
|
||||
OpenResourceError(CURRENTLOCALE);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
OpenResourceSuccess((char *)AppLocale->AmigaLocale->loc_LocaleName);
|
||||
|
||||
// Timer Device
|
||||
if (!(TimerDevice = OpenTimerBase()))
|
||||
{
|
||||
OpenResourceError(TIMERNAME);
|
||||
LogError(Text2P, TextNoOpen, TIMERNAME);
|
||||
return LIB_ERROR;
|
||||
}
|
||||
OpenResourceSuccess(TIMERNAME);
|
||||
LogDebug(Text2P, TextOpened, TIMERNAME);
|
||||
|
||||
// RTC Clock
|
||||
BattClockBase = OpenResource((STRPTR)BATTCLOCKNAME);
|
||||
if (BattClockBase != NULL)
|
||||
{
|
||||
OpenResourceSuccess(BATTCLOCKNAME);
|
||||
LogDebug(Text2P, TextOpened, BATTCLOCKNAME);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -265,7 +226,7 @@ int OpenLibraries(void)
|
||||
ScreenNotifyBase = OpenLibrary((STRPTR)SCREENNOTIFY_NAME, SCREENNOTIFY_VERSION);
|
||||
if (ScreenNotifyBase != NULL)
|
||||
{
|
||||
LogNotice("Found %s", SCREENNOTIFY_NAME);
|
||||
LogNotice(Text2P, TextFound, SCREENNOTIFY_NAME);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -278,18 +239,11 @@ void CloseLibraries(void)
|
||||
{
|
||||
if (TimerDevice != NULL)
|
||||
{
|
||||
ClosingResource(TIMERNAME);
|
||||
LogDebug(Text2P, TextClosing, TIMERNAME);
|
||||
CloseTimerBase();
|
||||
TimerDevice = NULL;
|
||||
}
|
||||
|
||||
if (AppLocale != NULL)
|
||||
{
|
||||
ClosingResource((char *)AppLocale->AmigaLocale->loc_LocaleName);
|
||||
CloseAppLocale(AppLocale);
|
||||
AppLocale = NULL;
|
||||
}
|
||||
|
||||
#if defined(SCREENNOTIFY)
|
||||
if (ScreenNotifyBase != NULL)
|
||||
{
|
||||
@@ -362,24 +316,3 @@ void CloseLibraries(void)
|
||||
DOSBase2 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void ReopenLocale(void)
|
||||
{
|
||||
struct AppLocale *locale, *temp;
|
||||
|
||||
if (!(locale = OpenAppLocale(NULL)))
|
||||
{
|
||||
OpenResourceError(CURRENTLOCALE);
|
||||
}
|
||||
else
|
||||
{
|
||||
temp = AppLocale;
|
||||
AppLocale = locale;
|
||||
|
||||
if (temp != NULL)
|
||||
{
|
||||
ClosingResource((char *)temp->AmigaLocale->loc_LocaleName);
|
||||
CloseAppLocale(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,130 +26,130 @@
|
||||
|
||||
#include "locale.h"
|
||||
#include "global.h"
|
||||
#include "string.h"
|
||||
#include "setting.h"
|
||||
#include "conv.h"
|
||||
#include "text.h"
|
||||
#include "ptz.h"
|
||||
#include "mem.h"
|
||||
#include "tz.h"
|
||||
|
||||
#include <proto/dos.h>
|
||||
#include <proto/timer.h>
|
||||
#include <proto/locale.h>
|
||||
#include <proto/utility.h>
|
||||
|
||||
struct AppLocale *OpenAppLocale(struct Locale *locale)
|
||||
#include <assert.h>
|
||||
|
||||
#define SECONDSPERDAY 86400
|
||||
|
||||
static const char *WeekdayShort[] = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
|
||||
static const char *WeekdayLong[] = {"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
|
||||
static const char *Month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
static void GetTimezoneCommon(char *text, struct PosixLocalTimezone *tz, long opt)
|
||||
{
|
||||
int i, j;
|
||||
struct AppLocale *l = AllocStructSafe(struct AppLocale);
|
||||
struct Locale *loc = locale;
|
||||
|
||||
if (!loc)
|
||||
if (tz->abbreviation[0] == 'G' && tz->abbreviation[1] == 'M' && tz->abbreviation[2] == 'T')
|
||||
{
|
||||
loc = OpenLocale(NULL);
|
||||
if (tz->offset.minutes == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%d", TimezoneSignChar(tz), tz->offset.hours);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%d:%02d",
|
||||
TimezoneSignChar(tz), tz->offset.hours, tz->offset.minutes);
|
||||
}
|
||||
|
||||
if (loc == NULL)
|
||||
else if (opt == TZD_ZONE_IN_PARENS)
|
||||
{
|
||||
return NULL;
|
||||
if (tz->offset.minutes == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s (GMT%s%d)",
|
||||
tz->abbreviation, TimezoneSignChar(tz), tz->offset.hours);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s (GMT%s%d:%02d)",
|
||||
tz->abbreviation, TimezoneSignChar(tz), tz->offset.hours, tz->offset.minutes);
|
||||
}
|
||||
|
||||
l->X_fmt = (const char *)loc->loc_TimeFormat;
|
||||
l->x_fmt = (const char *)loc->loc_ShortDateFormat;
|
||||
l->c_fmt = (const char *)loc->loc_DateTimeFormat;
|
||||
l->am = (const char *)GetLocaleStr(loc, AM_STR);
|
||||
l->pm = (const char *)GetLocaleStr(loc, PM_STR);
|
||||
l->date_fmt = "%a %b %e %H:%M:%S %Z %Y";
|
||||
|
||||
j = 0;
|
||||
for (i = 1; i < 8; i++)
|
||||
else if (opt == TZD_OFFSET_IN_PARENS)
|
||||
{
|
||||
l->weekday[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 8; i < 15; i++)
|
||||
{
|
||||
l->wday[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 15; i < 27; i++)
|
||||
{
|
||||
l->month[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
j = 0;
|
||||
for (i = 27; i < 39; i++)
|
||||
{
|
||||
l->mon[j++] = (const char *)GetLocaleStr(loc, i);
|
||||
}
|
||||
|
||||
l->AmigaLocale = loc;
|
||||
return l;
|
||||
}
|
||||
|
||||
void CloseAppLocale(struct AppLocale *lc)
|
||||
{
|
||||
if (lc->AmigaLocale)
|
||||
{
|
||||
CloseLocale(lc->AmigaLocale);
|
||||
}
|
||||
|
||||
FreeMemSafe(lc);
|
||||
}
|
||||
|
||||
void GetTimezoneText(struct AppLocale *loc, char *text, long opt)
|
||||
{
|
||||
if (loc == NULL || text == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Timezone == NULL)
|
||||
{
|
||||
long hoursOffset = (loc->AmigaLocale->loc_GMTOffset / -60L);
|
||||
long minutsOffset = (loc->AmigaLocale->loc_GMTOffset % -60L);
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%s%02ld:%02ld",
|
||||
(opt == UTC_NO_PARENS) ? "UTC" : "GMT",
|
||||
(loc->AmigaLocale->loc_GMTOffset < 0L) ? "+" : "",
|
||||
hoursOffset,
|
||||
minutsOffset);
|
||||
}
|
||||
else if (opt == ZONE_IN_PARENS)
|
||||
{
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%02d:%02d (%s)",
|
||||
PosixTimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours,
|
||||
Timezone->current.offset.minutes,
|
||||
Timezone->current.abbreviation);
|
||||
}
|
||||
else if (opt == OFFSET_IN_PARENS)
|
||||
{
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s (GMT%s%02d:%02d)",
|
||||
Timezone->current.abbreviation,
|
||||
PosixTimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours,
|
||||
Timezone->current.offset.minutes);
|
||||
}
|
||||
else if (opt == UTC_NO_PARENS)
|
||||
{
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "UTC%s%02d:%02d",
|
||||
PosixTimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours,
|
||||
Timezone->current.offset.minutes);
|
||||
if (tz->offset.minutes == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%d (%s)",
|
||||
TimezoneSignChar(tz), tz->offset.hours, tz->abbreviation);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%d:%02d (%s)",
|
||||
TimezoneSignChar(tz), tz->offset.hours, tz->offset.minutes, tz->abbreviation);
|
||||
}
|
||||
}
|
||||
|
||||
char *GetTimeText(struct AppLocale *loc, ULONG time)
|
||||
void GetTimezoneText(char *text, long opt)
|
||||
{
|
||||
char *out;
|
||||
long offset = -GetUtcOffsetValue();
|
||||
char *tzSign = (offset <= 0 ? "+" : "-");
|
||||
|
||||
switch (opt)
|
||||
{
|
||||
case TZD_SECONDS_AHEAD:
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%ld", offset);
|
||||
break;
|
||||
case TZD_MINUTES_AHEAD:
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%ld", offset / 60);
|
||||
break;
|
||||
case TZD_TZ_LONG:
|
||||
if (Timezone->current.offset.minutes == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "UTC%s%d", tzSign, Timezone->current.offset.hours);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "UTC%s%d:%02d",
|
||||
tzSign, Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
break;
|
||||
case TZD_TZ_SHORT:
|
||||
{
|
||||
if (Timezone->current.offset.minutes == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%d", tzSign, Timezone->current.offset.hours);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%d:%02d",
|
||||
tzSign, Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
}
|
||||
break;
|
||||
case TZD_ISO8601_NO_COLON:
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%02d%02d", TimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
break;
|
||||
case TZD_ISO8601_COLON:
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%02d:%02d", TimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
break;
|
||||
case TZD_ISO8601_SHORT:
|
||||
if (offset % 60 == 0)
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%d",
|
||||
TimezoneSignChar(&Timezone->current), Timezone->current.offset.hours);
|
||||
else
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "%s%d:%02d", TimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
break;
|
||||
case TZD_COMMON:
|
||||
SNPrintf(text, TIMEZONE_TEXT_LEN, "GMT%s%02d:%02d", TimezoneSignChar(&Timezone->current),
|
||||
Timezone->current.offset.hours, Timezone->current.offset.minutes);
|
||||
break;
|
||||
case TZD_ZONE_IN_PARENS:
|
||||
GetTimezoneCommon(text, &Timezone->current, TZD_ZONE_IN_PARENS);
|
||||
break;
|
||||
case TZD_OFFSET_IN_PARENS:
|
||||
GetTimezoneCommon(text, &Timezone->current, TZD_OFFSET_IN_PARENS);
|
||||
break;
|
||||
case TZD_STD:
|
||||
GetTimezoneCommon(text, &Timezone->std, TZD_OFFSET_IN_PARENS);
|
||||
break;
|
||||
case TZD_DST:
|
||||
GetTimezoneCommon(text, &Timezone->dst, TZD_OFFSET_IN_PARENS);
|
||||
break;
|
||||
default:
|
||||
text = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char *GetTimeText(ULONG time)
|
||||
{
|
||||
char *out = AllocStringSafe(128);
|
||||
struct ClockData cd;
|
||||
struct timeval tv;
|
||||
ULONG t = time;
|
||||
|
||||
out = AllocStringSafe(128);
|
||||
if (loc == NULL)
|
||||
{
|
||||
return out;
|
||||
}
|
||||
|
||||
if (t == LOCAL_TIME_NOW)
|
||||
{
|
||||
GetSysTime(&tv);
|
||||
@@ -157,36 +157,246 @@ char *GetTimeText(struct AppLocale *loc, ULONG time)
|
||||
}
|
||||
|
||||
Amiga2Date(t, &cd);
|
||||
|
||||
if (Timezone == NULL)
|
||||
{
|
||||
long hoursOffset = (loc->AmigaLocale->loc_GMTOffset / -60L);
|
||||
long minutsOffset = (loc->AmigaLocale->loc_GMTOffset % -60L);
|
||||
|
||||
SNPrintf(out, 128, "%s %02ld %s %02ld:%02ld:%02ld%s%02ld%02ld %ld",
|
||||
loc->weekday[cd.wday],
|
||||
(long)cd.mday,
|
||||
loc->month[cd.month - 1],
|
||||
(long)cd.hour,
|
||||
(long)cd.min,
|
||||
(long)cd.sec,
|
||||
(loc->AmigaLocale->loc_GMTOffset < 0L) ? "+" : "",
|
||||
hoursOffset,
|
||||
minutsOffset,
|
||||
(long)cd.year);
|
||||
}
|
||||
else
|
||||
{
|
||||
SNPrintf(out, 128, "%s %02ld %s %02ld:%02ld:%02ld %s %ld",
|
||||
loc->weekday[cd.wday],
|
||||
(long)cd.mday,
|
||||
loc->month[cd.month - 1],
|
||||
(long)cd.hour,
|
||||
(long)cd.min,
|
||||
(long)cd.sec,
|
||||
Timezone->current.abbreviation,
|
||||
(long)cd.year);
|
||||
}
|
||||
int weekday = (cd.wday == 0 ? 7 : cd.wday) - 1;
|
||||
SNPrintf(out, 128, "%s %02ld %s %02ld:%02ld:%02ld %s %ld",
|
||||
WeekdayLong[weekday],
|
||||
(long)cd.mday,
|
||||
Month[cd.month - 1],
|
||||
(long)cd.hour,
|
||||
(long)cd.min,
|
||||
(long)cd.sec,
|
||||
Timezone->current.abbreviation,
|
||||
(long)cd.year);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static void Amiga2DateStamp(time_t *time, struct DateStamp *date)
|
||||
{
|
||||
long t, d, m, q;
|
||||
|
||||
t = *time;
|
||||
d = t / SECONDSPERDAY;
|
||||
m = (t - SECONDSPERDAY * d) / 60;
|
||||
q = (t - SECONDSPERDAY * d - m * 60) * 50;
|
||||
|
||||
date->ds_Days = d;
|
||||
date->ds_Minute = m;
|
||||
date->ds_Tick = q;
|
||||
}
|
||||
|
||||
static void DateTimeString(struct DateStamp *ds, char *time, char *date, char *day)
|
||||
{
|
||||
struct DateTime dt;
|
||||
|
||||
assert(ds != NULL);
|
||||
assert(time != NULL);
|
||||
assert(date != NULL);
|
||||
assert(day != NULL);
|
||||
|
||||
dt.dat_Stamp = *ds;
|
||||
dt.dat_Format = FORMAT_DOS;
|
||||
dt.dat_Flags = 0;
|
||||
dt.dat_StrDay = (void *)day;
|
||||
dt.dat_StrDate = (void *)date;
|
||||
dt.dat_StrTime = (void *)time;
|
||||
|
||||
DateToStr(&dt);
|
||||
}
|
||||
|
||||
void Utc2DOS(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
char timeString[20];
|
||||
char dateString[20];
|
||||
char dayString[20];
|
||||
|
||||
struct DateStamp ds;
|
||||
struct timeval tv;
|
||||
|
||||
if (showUtc)
|
||||
Unix2Amiga(utv, &tv);
|
||||
else
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
|
||||
time_t time = tv.tv_secs;
|
||||
Amiga2DateStamp(&time, &ds);
|
||||
DateTimeString(&ds, timeString, dateString, dayString);
|
||||
SNPrintf(buffer, 64, "%s %s %s", dayString, dateString, timeString);
|
||||
}
|
||||
|
||||
void Utc2ARexxDate(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
if (showUtc)
|
||||
Unix2Amiga(utv, &tv);
|
||||
else
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, 10, "%04ld%02ld%02ld", (long)cd.year, (long)cd.month, (long)cd.mday);
|
||||
}
|
||||
|
||||
void Utc2ARexxTime(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
if (showUtc)
|
||||
Unix2Amiga(utv, &tv);
|
||||
else
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
|
||||
long time = tv.tv_secs % (24 * 60 * 60);
|
||||
LongToStr(time, buffer);
|
||||
}
|
||||
|
||||
void Utc2ASCII(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
if (showUtc)
|
||||
Unix2Amiga(utv, &tv);
|
||||
else
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, ASCIITEMPLATE,
|
||||
WeekdayShort[cd.wday - 1], Month[cd.month - 1], (long)cd.mday,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec, (long)cd.year);
|
||||
}
|
||||
|
||||
void Utc2RFC850(struct timeval *utv, char *buffer)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
Unix2Amiga(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC850TEMPLATE,
|
||||
WeekdayLong[cd.wday - 1], (long)cd.mday,
|
||||
Month[cd.month - 1], (long)cd.year % 100,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec);
|
||||
}
|
||||
|
||||
void Utc2RFC1123(struct timeval *utv, char *buffer)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
Unix2Amiga(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC1123TEMPLATE,
|
||||
WeekdayShort[cd.wday - 1], (long)cd.mday,
|
||||
Month[cd.month - 1], (long)cd.year,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec);
|
||||
}
|
||||
|
||||
void Utc2RFC2822(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
if (showUtc)
|
||||
{
|
||||
Unix2Amiga(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC2822TEMPLATE,
|
||||
(long)cd.mday, Month[cd.month - 1], (long)cd.year,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec,
|
||||
"+", 0L, 0L);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC2822TEMPLATE,
|
||||
(long)cd.mday, Month[cd.month - 1], (long)cd.year,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec,
|
||||
TimezoneSignChar(&Timezone->current),
|
||||
(long)Timezone->current.offset.hours,
|
||||
(long)Timezone->current.offset.minutes);
|
||||
}
|
||||
}
|
||||
|
||||
void Utc2RFC3339(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
if (showUtc)
|
||||
{
|
||||
Unix2Amiga(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC3339TEMPLATEUTC,
|
||||
(long)cd.year, (long)cd.month, (long)cd.mday,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec,
|
||||
(long)(tv.tv_micro / 10000));
|
||||
}
|
||||
else
|
||||
{
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, RFC3339TEMPLATELOC,
|
||||
(long)cd.year, (long)cd.month, (long)cd.mday,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec,
|
||||
(long)(tv.tv_micro / 10000),
|
||||
TimezoneSignChar(&Timezone->current),
|
||||
(long)Timezone->current.offset.hours,
|
||||
(long)Timezone->current.offset.minutes);
|
||||
}
|
||||
}
|
||||
|
||||
void Utc2ISO8601(struct timeval *utv, char *buffer, bool showUtc)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct ClockData cd;
|
||||
|
||||
if (showUtc)
|
||||
{
|
||||
Unix2Amiga(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, ISO8601TEMPLATEUTC,
|
||||
(long)cd.year, (long)cd.month, (long)cd.mday,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec);
|
||||
}
|
||||
else
|
||||
{
|
||||
UnixUtc2AmigaLocal(utv, &tv);
|
||||
Amiga2Date(tv.tv_secs, &cd);
|
||||
SNPrintf(buffer, DATETIME_TEXT_LEN, ISO8601TEMPLATELOC,
|
||||
(long)cd.year, (long)cd.month, (long)cd.mday,
|
||||
(long)cd.hour, (long)cd.min, (long)cd.sec,
|
||||
TimezoneSignChar(&Timezone->current),
|
||||
(long)Timezone->current.offset.hours,
|
||||
(long)Timezone->current.offset.minutes);
|
||||
}
|
||||
}
|
||||
|
||||
void LogTransitionMap(void)
|
||||
{
|
||||
struct PosixTransitionTime *transition;
|
||||
struct DateStamp ds;
|
||||
time_t next;
|
||||
char timeString[20];
|
||||
char dateString[20];
|
||||
char dayString[20];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 138; i++)
|
||||
{
|
||||
transition = &Timezone->transitions[i];
|
||||
next = transition->time;
|
||||
Amiga2DateStamp(&next, &ds);
|
||||
DateTimeString(&ds, timeString, dateString, dayString);
|
||||
LogNoticeMsg("Timezone",
|
||||
"Changing (%010ld) to %s time on %s %s at %s %s",
|
||||
(long)next,
|
||||
transition->isdst ? tzDstAbbr : tzStdAbbr,
|
||||
dayString, dateString, timeString,
|
||||
transition->isdst
|
||||
? Timezone->std.abbreviation
|
||||
: Timezone->dst.abbreviation);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,34 +27,49 @@
|
||||
#ifndef LOCALE_H_INCLUDED
|
||||
#define LOCALE_H_INCLUDED
|
||||
|
||||
#include <libraries/locale.h>
|
||||
#include "compiler.h"
|
||||
|
||||
struct AppLocale
|
||||
{
|
||||
const char *mon[12];
|
||||
const char *month[12];
|
||||
const char *wday[7];
|
||||
const char *weekday[7];
|
||||
const char *X_fmt;
|
||||
const char *x_fmt;
|
||||
const char *c_fmt;
|
||||
const char *t_fmt_ampm;
|
||||
const char *am;
|
||||
const char *pm;
|
||||
const char *am_pm[2];
|
||||
const char *date_fmt;
|
||||
struct Locale *AmigaLocale;
|
||||
};
|
||||
#include <libraries/locale.h>
|
||||
#include <devices/timer.h>
|
||||
|
||||
#define LOCAL_TIME_NOW 0
|
||||
#define ZONE_IN_PARENS 0
|
||||
#define OFFSET_IN_PARENS 1
|
||||
#define UTC_NO_PARENS 2
|
||||
|
||||
#define TZD_SECONDS_AHEAD 1
|
||||
#define TZD_MINUTES_AHEAD 2
|
||||
#define TZD_TZ_LONG 3
|
||||
#define TZD_TZ_SHORT 4
|
||||
#define TZD_ISO8601_NO_COLON 5
|
||||
#define TZD_ISO8601_COLON 6
|
||||
#define TZD_ISO8601_SHORT 7
|
||||
#define TZD_COMMON 8
|
||||
#define TZD_ZONE_IN_PARENS 9
|
||||
#define TZD_OFFSET_IN_PARENS 10
|
||||
#define TZD_STD 11
|
||||
#define TZD_DST 12
|
||||
|
||||
#define TIMEZONE_TEXT_LEN 32
|
||||
|
||||
struct AppLocale *OpenAppLocale(struct Locale *);
|
||||
void CloseAppLocale(struct AppLocale *);
|
||||
char* GetTimeText(struct AppLocale *, ULONG);
|
||||
void GetTimezoneText(struct AppLocale *, char *, long);
|
||||
#define DATETIME_TEXT_LEN 40
|
||||
#define ASCIITEMPLATE "%s %s %ld %02ld:%02ld:%02ld %04ld"
|
||||
#define RFC850TEMPLATE "%s, %02ld-%s-%02ld %02ld:%02ld:%02ld GMT"
|
||||
#define RFC1123TEMPLATE "%s, %02ld %s %04ld %02ld:%02ld:%02ld GMT"
|
||||
#define RFC2822TEMPLATE "%02ld. %s %04ld %02ld:%02ld:%02ld %s%02ld%02ld"
|
||||
#define RFC3339TEMPLATEUTC "%04ld-%02ld-%02ld %02ld:%02ld:%02ld.%02ldZ"
|
||||
#define RFC3339TEMPLATELOC "%04ld-%02ld-%02ld %02ld:%02ld:%02ld.%02ld%s%02ld:%02ld"
|
||||
#define ISO8601TEMPLATEUTC "%04ld%02ld%02ldT%02ld%02ld%02ldZ"
|
||||
#define ISO8601TEMPLATELOC "%04ld-%02ld-%02ldT%02ld:%02ld:%02ld%s%02ld:%02ld"
|
||||
|
||||
char *GetTimeText(ULONG);
|
||||
void GetTimezoneText(char *, long);
|
||||
void LogTransitionMap(void);
|
||||
void Utc2ASCII(struct timeval *, char *, bool);
|
||||
void Utc2DOS(struct timeval *, char *, bool);
|
||||
void Utc2ARexxDate(struct timeval *, char *, bool);
|
||||
void Utc2ARexxTime(struct timeval *, char *, bool);
|
||||
void Utc2RFC850(struct timeval *, char *);
|
||||
void Utc2RFC1123(struct timeval *, char *);
|
||||
void Utc2RFC2822(struct timeval *, char *, bool);
|
||||
void Utc2RFC3339(struct timeval *, char *, bool);
|
||||
void Utc2ISO8601(struct timeval *, char *, bool);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "message.h"
|
||||
#include "setting.h"
|
||||
|
||||
static void VLogLine(enum LogSeverity level, const char *module, const char *format, va_list ap)
|
||||
{
|
||||
@@ -49,6 +50,9 @@ static void VLogLine(enum LogSeverity level, const char *module, const char *for
|
||||
|
||||
void LogMemTraceMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(MemTraceMessage, module, format, args);
|
||||
@@ -57,6 +61,9 @@ void LogMemTraceMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogDebugMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(DebugMessage, module, format, args);
|
||||
@@ -65,6 +72,9 @@ void LogDebugMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogTraceMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(TraceMessage, module, format, args);
|
||||
@@ -73,6 +83,9 @@ void LogTraceMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogInfoMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(InfoMessage, module, format, args);
|
||||
@@ -81,6 +94,9 @@ void LogInfoMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogNoticeMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(NoticeMessage, module, format, args);
|
||||
@@ -89,6 +105,9 @@ void LogNoticeMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogWarnMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(WarningMessage, module, format, args);
|
||||
@@ -97,6 +116,9 @@ void LogWarnMsg(const char *module, const char *format, ...)
|
||||
|
||||
void LogErrorMsg(const char *module, const char *format, ...)
|
||||
{
|
||||
if (Settings->NoLog)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
VLogLine(ErrorMessage, module, format, args);
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
#define UTILITYNAME "utility.library"
|
||||
#endif
|
||||
|
||||
#define TIMELOGGER "TimeLogger 1.11 (11.01.2021)"
|
||||
#define TIMELOGGER "TimeLogger 1.12 (31.01.2021)"
|
||||
#define ARGSFORMAT "D=DEBUG/K/N,M=MODULEOFF/S,S=SEVERITYOFF/S,H=HELP/S"
|
||||
#define MODULENAME "Logger"
|
||||
|
||||
|
||||
@@ -41,18 +41,11 @@
|
||||
#define MODULENAME "Main"
|
||||
|
||||
const char *vers = "\0$VER: " APP_ID;
|
||||
static const char *template = KEYWORD_TEMPLATE;
|
||||
static const char *template = KWD_TMPL;
|
||||
|
||||
static void GetCliSettings(void);
|
||||
static void GetWbSettings(struct WBStartup *);
|
||||
|
||||
static void ShowLocalTime(void)
|
||||
{
|
||||
char *time = GetTimeText(AppLocale, LOCAL_TIME_NOW);
|
||||
LogInfo("Local time is %s", time);
|
||||
FreeMemSafe(time);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
InitMemSafe();
|
||||
@@ -69,10 +62,9 @@ int main(int argc, char **argv)
|
||||
return RETURN_FAIL;
|
||||
}
|
||||
|
||||
InitTimezone();
|
||||
LoadSettings();
|
||||
|
||||
if (argc != 0)
|
||||
if (Cli() != NULL)
|
||||
GetCliSettings();
|
||||
else
|
||||
GetWbSettings((struct WBStartup *)argv);
|
||||
@@ -81,14 +73,15 @@ int main(int argc, char **argv)
|
||||
SanitizeSettings();
|
||||
ShowSettings();
|
||||
|
||||
InitTimezone();
|
||||
StartBroker();
|
||||
|
||||
ShowLocalTime();
|
||||
CleanupTimezone();
|
||||
StopTimezoneCheck();
|
||||
CloseSocketLibrary();
|
||||
CloseLibraries();
|
||||
CleanupSettings();
|
||||
CleanupArexx();
|
||||
CleanupARexx();
|
||||
FreePosixTimezone(Timezone);
|
||||
FreeAllSafe();
|
||||
|
||||
LogNotice("Shutdown complete");
|
||||
@@ -99,23 +92,25 @@ static void GetCliSettings(void)
|
||||
{
|
||||
struct AppSettings *settings;
|
||||
struct RDArgs *inArgs;
|
||||
long args[KEYWORD_COUNT];
|
||||
LONG args[KEYWORD_COUNT];
|
||||
int i;
|
||||
|
||||
LogTrace("Parsing CLI settings");
|
||||
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
args[i] = 0;
|
||||
|
||||
settings = CreateSettings(CliSettingType);
|
||||
|
||||
inArgs = ReadArgs((void *)template, (void *)&args, NULL);
|
||||
inArgs = ReadArgs((CONST_STRPTR) template, (LONG *)&args, NULL);
|
||||
if (inArgs)
|
||||
{
|
||||
// Keyword order in template needs to match order in settingFunctions
|
||||
for (i = 0; i < KEYWORD_COUNT; i++)
|
||||
{
|
||||
if (args[i] != 0)
|
||||
LONG j = FindArg((STRPTR) template, (STRPTR)settingFunctions[i].Name);
|
||||
if (j != -1 && args[j] != 0)
|
||||
{
|
||||
settingFunctions[i].Function(settings, (void *)args[i]);
|
||||
settingFunctions[i].Function(settings, (void *)args[j]);
|
||||
}
|
||||
}
|
||||
FreeArgs(inArgs);
|
||||
@@ -132,6 +127,8 @@ static void GetWbSettings(struct WBStartup *wbs)
|
||||
BPTR oldDir;
|
||||
int argNo, i;
|
||||
|
||||
LogTrace("Parsing Workbench settings");
|
||||
|
||||
filename = (STRPTR)AllocStringSafe(MAXFILEPATHLEN);
|
||||
settings = CreateSettings(WbSettingType);
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ struct MsgPort *volatile SyncerPort;
|
||||
struct MsgPort *volatile WindowPort;
|
||||
struct MsgPort *volatile MemoryPort;
|
||||
struct MsgPort *volatile ControlPort;
|
||||
struct MsgPort *volatile ArexxPort;
|
||||
struct MsgPort *volatile ARexxPort;
|
||||
int outstanding;
|
||||
|
||||
static void PublishPort(long, char *);
|
||||
@@ -52,7 +52,7 @@ void InitMessages(void)
|
||||
WindowPort = NULL;
|
||||
MemoryPort = NULL;
|
||||
ControlPort = NULL;
|
||||
ArexxPort = NULL;
|
||||
ARexxPort = NULL;
|
||||
outstanding = 0;
|
||||
|
||||
CreateMessagePort(MSGPORT_MEMORY);
|
||||
@@ -93,9 +93,9 @@ void CleanupPorts(void)
|
||||
DestroyMessagePort(MSGPORT_CONTROL);
|
||||
}
|
||||
|
||||
if (ArexxPort != NULL)
|
||||
if (ARexxPort != NULL)
|
||||
{
|
||||
RemPort((struct MsgPort *)ArexxPort);
|
||||
RemPort((struct MsgPort *)ARexxPort);
|
||||
DestroyMessagePort(MSGPORT_AREXX);
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ static struct MsgPort *FindMessagePort(long port)
|
||||
return (struct MsgPort *)ControlPort;
|
||||
break;
|
||||
case MSGPORT_AREXX:
|
||||
return (struct MsgPort *)ArexxPort;
|
||||
return (struct MsgPort *)ARexxPort;
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
@@ -167,7 +167,7 @@ static struct MsgPort *volatile *FindMessagePortAddress(long port, char **name)
|
||||
s = "Control";
|
||||
break;
|
||||
case MSGPORT_AREXX:
|
||||
p = &ArexxPort;
|
||||
p = &ARexxPort;
|
||||
s = "ARexx";
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
#define LOGGER_PORT_NAME "TimeLoggerIn"
|
||||
#define CONTROL_PORT_NAME "TimeKeeperCtrl"
|
||||
#define AREXX_PORT_NAME "TIMEKEEPER.1"
|
||||
#define AREXX_ERROR_VAR_CODE "TIMEKEEPER.ERRORCODE"
|
||||
#define AREXX_ERROR_VAR_TEXT "TIMEKEEPER.ERRORTEXT"
|
||||
|
||||
#define ATK_DEFAULT 0
|
||||
#define ATK_LASTSYNC 1
|
||||
@@ -54,6 +56,8 @@
|
||||
#define ATK_ID 50
|
||||
#define ATK_VERSION 51
|
||||
#define ATK_STATUS 52
|
||||
#define ATK_TIME 53
|
||||
#define ATK_TIMEZONE 54
|
||||
|
||||
#define ATK_CTRL_OK 0
|
||||
#define ATK_CTRL_ERROR 10
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <dos/dos.h>
|
||||
#include <dos/notify.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "mem.h"
|
||||
@@ -37,21 +38,21 @@ struct NotifyRequestNode
|
||||
{
|
||||
long Registered;
|
||||
struct NotifyRequest *Request;
|
||||
volatile struct NotifyRequestNode *Next;
|
||||
struct NotifyRequestNode *Next;
|
||||
};
|
||||
|
||||
volatile static struct NotifyRequestNode *Last = NULL;
|
||||
static struct NotifyRequestNode *Last = NULL;
|
||||
|
||||
static void AddRequest(struct NotifyRequest *request)
|
||||
{
|
||||
volatile struct NotifyRequestNode *node;
|
||||
|
||||
node = AllocStructSafe(struct NotifyRequestNode);
|
||||
struct NotifyRequestNode *node = AllocStructSafe(struct NotifyRequestNode);
|
||||
if (node == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Init node
|
||||
node->Registered = DOSFALSE;
|
||||
node->Request = request;
|
||||
node->Next = NULL;
|
||||
|
||||
@@ -71,14 +72,9 @@ static void AddRequest(struct NotifyRequest *request)
|
||||
|
||||
void ActivateNotifyPort(struct MsgPort *port)
|
||||
{
|
||||
volatile struct NotifyRequestNode *current;
|
||||
assert(port != NULL);
|
||||
|
||||
if (port == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
current = Last;
|
||||
struct NotifyRequestNode *current = Last;
|
||||
while (current != NULL)
|
||||
{
|
||||
if (current->Registered != DOSTRUE)
|
||||
@@ -92,7 +88,7 @@ void ActivateNotifyPort(struct MsgPort *port)
|
||||
}
|
||||
else
|
||||
{
|
||||
LogWarn("Could not get notifications from %s", current->Request->nr_Name);
|
||||
LogWarn("Could not get notifications for %s", current->Request->nr_Name);
|
||||
}
|
||||
}
|
||||
current = current->Next;
|
||||
@@ -115,7 +111,7 @@ void WatchFile(char *file, long type)
|
||||
return;
|
||||
}
|
||||
|
||||
request->nr_Flags = NRF_SEND_MESSAGE | NRB_WAIT_REPLY;
|
||||
request->nr_Flags = NRF_SEND_MESSAGE | NRF_WAIT_REPLY;
|
||||
request->nr_UserData = type;
|
||||
|
||||
AddRequest(request);
|
||||
@@ -130,6 +126,7 @@ void CleanupNotifications(void)
|
||||
{
|
||||
if (current->Registered == DOSTRUE)
|
||||
{
|
||||
LogTrace("Removing notification for %s", current->Request->nr_Name);
|
||||
EndNotify(current->Request);
|
||||
}
|
||||
FreeMemSafe((void *)current->Request->nr_Name);
|
||||
@@ -139,4 +136,6 @@ void CleanupNotifications(void)
|
||||
FreeMemSafe((void *)current);
|
||||
current = next;
|
||||
}
|
||||
|
||||
Last = NULL;
|
||||
}
|
||||
@@ -32,9 +32,8 @@
|
||||
#include <proto/utility.h>
|
||||
|
||||
#include "ptz.h"
|
||||
#include "string.h"
|
||||
#include "global.h"
|
||||
#include "mem.h"
|
||||
#include "string.h"
|
||||
|
||||
#include "logmod.h"
|
||||
#define MODULENAME "Posix TZ"
|
||||
@@ -59,7 +58,7 @@ static const char *ParseInt(const char *p, int min, int max, int *result)
|
||||
/*
|
||||
* Parse abbreviation part of POSIX TZ string.
|
||||
*/
|
||||
static const char *ParseAbbr(const char *p, char **result)
|
||||
static const char *ParseAbbr(const char *p, char *result)
|
||||
{
|
||||
const char *start = p;
|
||||
|
||||
@@ -72,8 +71,8 @@ static const char *ParseAbbr(const char *p, char **result)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*result = AllocStringSafe(p - start);
|
||||
CopyMem((APTR)start, *result, p - start);
|
||||
int l = (p - start > MAX_ABBR - 1 ? MAX_ABBR - 1 : p - start);
|
||||
CopyMem((APTR)start, (APTR)result, (ULONG)l);
|
||||
|
||||
return ++p;
|
||||
}
|
||||
@@ -84,8 +83,8 @@ static const char *ParseAbbr(const char *p, char **result)
|
||||
if (p - start < 3)
|
||||
return NULL;
|
||||
|
||||
*result = AllocStringSafe(p - start + 1);
|
||||
CopyMem((APTR)start, *result, p - start);
|
||||
int l = (p - start > MAX_ABBR - 1 ? MAX_ABBR - 1 : p - start);
|
||||
CopyMem((APTR)start, (APTR)result, (ULONG)l);
|
||||
|
||||
return p;
|
||||
}
|
||||
@@ -215,7 +214,7 @@ static bool ParsePosixTz(const char *tz, struct PosixTimezone *result)
|
||||
if (*p == ':')
|
||||
return false;
|
||||
|
||||
p = ParseAbbr(p, &result->std.abbreviation);
|
||||
p = ParseAbbr(p, result->std.abbreviation);
|
||||
p = ParseTime(p, 0, 24, -1, &result->std.offset);
|
||||
|
||||
if (p == NULL)
|
||||
@@ -224,15 +223,15 @@ static bool ParsePosixTz(const char *tz, struct PosixTimezone *result)
|
||||
if (*p == '\0')
|
||||
return true;
|
||||
|
||||
p = ParseAbbr(p, &result->dst.abbreviation);
|
||||
p = ParseAbbr(p, result->dst.abbreviation);
|
||||
if (p == NULL)
|
||||
return false;
|
||||
|
||||
// Default is one hour ahead of std
|
||||
result->dst.offset.sign = result->std.offset.sign;
|
||||
result->dst.offset.hours = (result->dst.offset.sign < 0)
|
||||
? result->std.offset.hours - 1
|
||||
: result->std.offset.hours + 1;
|
||||
result->dst.offset.hours = (result->dst.offset.sign > 0)
|
||||
? result->std.offset.hours + 1
|
||||
: result->std.offset.hours - 1;
|
||||
result->dst.offset.minutes = result->std.offset.minutes;
|
||||
result->dst.offset.seconds = result->std.offset.seconds;
|
||||
|
||||
@@ -250,29 +249,6 @@ static bool ParsePosixTz(const char *tz, struct PosixTimezone *result)
|
||||
return p != NULL && *p == '\0';
|
||||
}
|
||||
|
||||
char *PosixTimezoneSignChar(struct PosixLocalTimezone *ptz)
|
||||
{
|
||||
static char *positive = "+";
|
||||
static char *negative = "-";
|
||||
|
||||
if (ptz == NULL)
|
||||
{
|
||||
return positive;
|
||||
}
|
||||
|
||||
if (ptz->offset.hours == 0 && ptz->offset.minutes == 0 && ptz->offset.seconds == 0)
|
||||
{
|
||||
return positive;
|
||||
}
|
||||
|
||||
if (ptz->offset.sign >= 0)
|
||||
{
|
||||
return positive;
|
||||
}
|
||||
|
||||
return negative;
|
||||
}
|
||||
|
||||
static int FindWeekDay(int year, int month, int day)
|
||||
{
|
||||
int h = 0;
|
||||
@@ -315,7 +291,19 @@ static int FindDay(int year, int month, int week, int day)
|
||||
days = 29;
|
||||
}
|
||||
|
||||
if (week == 5)
|
||||
if (week == 1)
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i <= days; i++)
|
||||
{
|
||||
int a = FindWeekDay(year, month, i);
|
||||
if (day == a)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (week == 5)
|
||||
{
|
||||
int i;
|
||||
for (i = (days - 6); i <= days; i++)
|
||||
@@ -334,25 +322,26 @@ static int FindDay(int year, int month, int week, int day)
|
||||
for (i = 1; i <= days; i++)
|
||||
{
|
||||
int a = FindWeekDay(year, month, i);
|
||||
if (a == 0 && i != 1)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
|
||||
if (day == a && week == j)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
|
||||
if (a == 0 && i != 1)
|
||||
{
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
LogError("Failed to find transition date");
|
||||
return 1;
|
||||
}
|
||||
|
||||
static ULONG FindTransitionTime(int year, struct PosixTransition *transition)
|
||||
static time_t FindTransitionTime(int year, struct PosixTransition *transition)
|
||||
{
|
||||
struct ClockData day;
|
||||
ULONG transitionTime = 0;
|
||||
signed long transitionTime = 0;
|
||||
|
||||
day.sec = 0;
|
||||
day.min = 0;
|
||||
@@ -387,7 +376,6 @@ static ULONG FindTransitionTime(int year, struct PosixTransition *transition)
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO: Validate sign
|
||||
transitionTime +=
|
||||
(transition->offset.sign < 0 ? -1 : 1) *
|
||||
(transition->offset.hours * 60 * 60 +
|
||||
@@ -397,90 +385,20 @@ static ULONG FindTransitionTime(int year, struct PosixTransition *transition)
|
||||
return transitionTime;
|
||||
}
|
||||
|
||||
struct PosixTransitionTime *FindNextTransition(time_t now)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
if (Timezone->start.type == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (Timezone->transitions[i].time < now)
|
||||
{
|
||||
i++;
|
||||
}
|
||||
|
||||
return &Timezone->transitions[i];
|
||||
}
|
||||
|
||||
static char *GetVariable(const char *variable)
|
||||
{
|
||||
unsigned long memsize = 256;
|
||||
STRPTR var = (STRPTR)variable;
|
||||
|
||||
STRPTR buf = (STRPTR)AllocStringSafe(memsize);
|
||||
if (!buf)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GetVar(var, buf, memsize - 1, GVF_GLOBAL_ONLY) > 0)
|
||||
{
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
FreeMemSafe(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CleanupPosixTimezone(void)
|
||||
{
|
||||
if (Timezone != NULL)
|
||||
{
|
||||
if (Timezone->std.abbreviation != NULL)
|
||||
{
|
||||
FreeMemSafe(Timezone->std.abbreviation);
|
||||
}
|
||||
if (Timezone->dst.abbreviation != NULL)
|
||||
{
|
||||
FreeMemSafe(Timezone->dst.abbreviation);
|
||||
}
|
||||
|
||||
FreeMemSafe(Timezone);
|
||||
Timezone = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void InitFromTZone(void)
|
||||
{
|
||||
if (Timezone->dst.abbreviation != NULL)
|
||||
{
|
||||
// DST is present
|
||||
Timezone->current.abbreviation = Timezone->dst.abbreviation;
|
||||
Timezone->current.offset = Timezone->dst.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Timezone->current.abbreviation = Timezone->std.abbreviation;
|
||||
Timezone->current.offset = Timezone->std.offset;
|
||||
}
|
||||
}
|
||||
|
||||
static void BuildTransitionMap()
|
||||
static void BuildTransitionMap(struct PosixTimezone *ptz)
|
||||
{
|
||||
int i = 0;
|
||||
bool isdst = false;
|
||||
bool north;
|
||||
|
||||
switch (Timezone->start.type)
|
||||
switch (ptz->start.type)
|
||||
{
|
||||
case JulianDay:
|
||||
case JulianDayLeap:
|
||||
isdst = Timezone->start.day > Timezone->end.day;
|
||||
isdst = ptz->start.day > ptz->end.day;
|
||||
break;
|
||||
case DayWeekMonth:
|
||||
isdst = Timezone->start.month > Timezone->end.month;
|
||||
isdst = ptz->start.month > ptz->end.month;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
@@ -489,103 +407,116 @@ static void BuildTransitionMap()
|
||||
|
||||
north = isdst ? false : true;
|
||||
|
||||
Timezone->transitions[0].time = 0;
|
||||
Timezone->transitions[0].isdst = isdst;
|
||||
ptz->transitions[0].time = 0;
|
||||
ptz->transitions[0].isdst = isdst;
|
||||
|
||||
for (i = 0; i < 138 / 2; i++)
|
||||
for (i = 0; i < MAX_TRANSITIONS / 2 - 1; i++)
|
||||
{
|
||||
ULONG time;
|
||||
time_t time;
|
||||
isdst = isdst ? false : true;
|
||||
time = north
|
||||
? FindTransitionTime(i + 1978, &ptz->start)
|
||||
: FindTransitionTime(i + 1978, &ptz->end);
|
||||
|
||||
ptz->transitions[i * 2 + 1].time = time;
|
||||
ptz->transitions[i * 2 + 1].isdst = isdst;
|
||||
|
||||
isdst = isdst ? false : true;
|
||||
time = north
|
||||
? FindTransitionTime(i + 1978, &Timezone->start)
|
||||
: FindTransitionTime(i + 1978, &Timezone->end);
|
||||
? FindTransitionTime(i + 1978, &ptz->end)
|
||||
: FindTransitionTime(i + 1978, &ptz->start);
|
||||
|
||||
Timezone->transitions[i * 2 + 1].time = time;
|
||||
Timezone->transitions[i * 2 + 1].isdst = isdst;
|
||||
|
||||
isdst = isdst ? false : true;
|
||||
time = north
|
||||
? FindTransitionTime(i + 1978, &Timezone->end)
|
||||
: FindTransitionTime(i + 1978, &Timezone->start);
|
||||
|
||||
Timezone->transitions[i * 2 + 2].time = time;
|
||||
Timezone->transitions[i * 2 + 2].isdst = isdst;
|
||||
ptz->transitions[i * 2 + 2].time = time;
|
||||
ptz->transitions[i * 2 + 2].isdst = isdst;
|
||||
}
|
||||
|
||||
Timezone->transitions[137].time = 2147483647;
|
||||
Timezone->transitions[137].isdst = false;
|
||||
ptz->transitions[MAX_TRANSITIONS - 1].time = 2147483647;
|
||||
ptz->transitions[MAX_TRANSITIONS - 1].isdst = false;
|
||||
}
|
||||
|
||||
int InitPosixTimezone(char **variable)
|
||||
char *TimezoneSignChar(struct PosixLocalTimezone *ptz)
|
||||
{
|
||||
int result = 5;
|
||||
char *var;
|
||||
static char *positive = "+";
|
||||
static char *negative = "-";
|
||||
|
||||
Timezone = NULL;
|
||||
|
||||
var = GetVariable("TZ");
|
||||
if (var == NULL)
|
||||
if (ptz == NULL)
|
||||
{
|
||||
var = GetVariable("TZONE");
|
||||
result = 4;
|
||||
return positive;
|
||||
}
|
||||
|
||||
if (var == NULL)
|
||||
if (ptz->offset.hours == 0 && ptz->offset.minutes == 0 && ptz->offset.seconds == 0)
|
||||
{
|
||||
return 1;
|
||||
return positive;
|
||||
}
|
||||
|
||||
*variable = StrDupSafe(var);
|
||||
Timezone = AllocStructSafe(struct PosixTimezone);
|
||||
|
||||
if (!ParsePosixTz(var, Timezone))
|
||||
if (ptz->offset.sign >= 0)
|
||||
{
|
||||
FreeMemSafe(var);
|
||||
CleanupPosixTimezone();
|
||||
return result - 2;
|
||||
return positive;
|
||||
}
|
||||
|
||||
FreeMemSafe(var);
|
||||
return negative;
|
||||
}
|
||||
|
||||
if (Timezone->start.type == 0)
|
||||
void FreePosixTimezone(struct PosixTimezone *ptz)
|
||||
{
|
||||
if (ptz == NULL)
|
||||
return;
|
||||
|
||||
FreeMemSafe(ptz);
|
||||
}
|
||||
|
||||
struct PosixTimezone *InitPosixTimezone(char *variable)
|
||||
{
|
||||
struct PosixTimezone *ptz = AllocStructSafe(struct PosixTimezone);
|
||||
ptz->source = PosixTypeTimezone;
|
||||
|
||||
if (ParsePosixTz(variable, ptz))
|
||||
{
|
||||
InitFromTZone();
|
||||
if (ptz->start.type != 0)
|
||||
{
|
||||
BuildTransitionMap(ptz);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BuildTransitionMap();
|
||||
FreePosixTimezone(ptz);
|
||||
ptz = NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
return ptz;
|
||||
}
|
||||
|
||||
bool SetPosixTimezone(struct timeval *tv)
|
||||
void SetPosixTimezone(struct PosixTimezone *ptz, struct timeval *tv)
|
||||
{
|
||||
if (ptz == NULL || ptz->start.type == 0)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
|
||||
if (Timezone->start.type == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
while (Timezone->transitions[i].time <= tv->tv_secs)
|
||||
{
|
||||
time_t time = (time_t)tv->tv_secs;
|
||||
while (i < MAX_TRANSITIONS && ptz->transitions[i].time <= time)
|
||||
i++;
|
||||
}
|
||||
|
||||
i--;
|
||||
|
||||
if (Timezone->transitions[i].isdst)
|
||||
if (ptz->transitions[--i].isdst)
|
||||
{
|
||||
Timezone->current.abbreviation = Timezone->dst.abbreviation;
|
||||
Timezone->current.offset = Timezone->dst.offset;
|
||||
StrCopy(ptz->current.abbreviation, ptz->dst.abbreviation);
|
||||
ptz->current.offset = ptz->dst.offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Timezone->current.abbreviation = Timezone->std.abbreviation;
|
||||
Timezone->current.offset = Timezone->std.offset;
|
||||
StrCopy(ptz->current.abbreviation, ptz->std.abbreviation);
|
||||
ptz->current.offset = ptz->std.offset;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
struct PosixTransitionTime *FindNextTransition(struct PosixTimezone *ptz, struct timeval *tv)
|
||||
{
|
||||
if (ptz->start.type == 0)
|
||||
return NULL;
|
||||
|
||||
int i = 0;
|
||||
time_t time = (time_t)tv->tv_secs;
|
||||
while (i < MAX_TRANSITIONS && ptz->transitions[i].time < time)
|
||||
i++;
|
||||
|
||||
return &ptz->transitions[i];
|
||||
}
|
||||
|
||||
@@ -37,6 +37,12 @@
|
||||
#define JulianDayLeap 2
|
||||
#define DayWeekMonth 3
|
||||
|
||||
#define CustomTypeTimezone 1
|
||||
#define PosixTypeTimezone 2
|
||||
|
||||
#define MAX_ABBR 10
|
||||
#define MAX_TRANSITIONS 138
|
||||
|
||||
struct PosixTimezoneOffset
|
||||
{
|
||||
int sign; // before/after 00:00:00, -1 or 1
|
||||
@@ -47,7 +53,7 @@ struct PosixTimezoneOffset
|
||||
|
||||
struct PosixTransition
|
||||
{
|
||||
int type; // type of transistion [0:2]
|
||||
int type; // type of transistion [0:3]
|
||||
int day; // day of year (leap or non-leap) [0:365]
|
||||
int weekday; // day of week [0:6]
|
||||
int week; // week of month [1:5]
|
||||
@@ -63,24 +69,25 @@ struct PosixTransitionTime
|
||||
|
||||
struct PosixLocalTimezone
|
||||
{
|
||||
char *abbreviation;
|
||||
char abbreviation[MAX_ABBR];
|
||||
struct PosixTimezoneOffset offset;
|
||||
};
|
||||
|
||||
struct PosixTimezone
|
||||
{
|
||||
int source; // time zone source [1:2]
|
||||
struct PosixLocalTimezone current;
|
||||
struct PosixLocalTimezone std;
|
||||
struct PosixLocalTimezone dst;
|
||||
struct PosixTransition start;
|
||||
struct PosixTransition end;
|
||||
struct PosixTransitionTime transitions[138];
|
||||
struct PosixTransitionTime transitions[MAX_TRANSITIONS];
|
||||
};
|
||||
|
||||
int InitPosixTimezone(char **);
|
||||
void CleanupPosixTimezone(void);
|
||||
bool SetPosixTimezone(struct timeval *tv);
|
||||
struct PosixTransitionTime *FindNextTransition(time_t);
|
||||
char* PosixTimezoneSignChar(struct PosixLocalTimezone *);
|
||||
char *TimezoneSignChar(struct PosixLocalTimezone *);
|
||||
struct PosixTimezone *InitPosixTimezone(char *);
|
||||
void FreePosixTimezone(struct PosixTimezone *);
|
||||
void SetPosixTimezone(struct PosixTimezone *, struct timeval *);
|
||||
struct PosixTransitionTime *FindNextTransition(struct PosixTimezone *, struct timeval *);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
; Set TZ to North East American time zone
|
||||
; Start with 'EXECUTE SetTZCentralEurope'
|
||||
;
|
||||
|
||||
ECHO "Changing to Central European time zone ..."
|
||||
SETENV TZ CET-1CEST,M3.5.0,M10.5.0/3
|
||||
|
||||
ECHO "To take effect restart AmiTimeKeeper first"
|
||||
|
||||
; Save between reboots with :
|
||||
; COPY CLONE ENV:TZ ENVARC:TZ
|
||||
@@ -0,0 +1,11 @@
|
||||
; Set TZ to North East American time zone
|
||||
; Start with 'EXECUTE SetTZNorthEastAmerica'
|
||||
;
|
||||
|
||||
ECHO "Changing to North East American time zone ..."
|
||||
SETENV TZ EST5EDT,M3.2.0,M11.1.0
|
||||
|
||||
ECHO "To take effect restart AmiTimeKeeper first"
|
||||
|
||||
; Save between reboots with :
|
||||
; COPY CLONE ENV:TZ ENVARC:TZ
|
||||
@@ -46,7 +46,15 @@ static const struct AppSettingKeys SettingKeyStruct = {
|
||||
.Popup = KEYWORD_POPUP,
|
||||
.Readonly = KEYWORD_READONLY,
|
||||
.Expert = KEYWORD_EXPERT,
|
||||
.Timeout = KEYWORD_TIMEOUT};
|
||||
.Timeout = KEYWORD_TIMEOUT,
|
||||
.Active = KEYWORD_ACTIVE,
|
||||
.NoLog = KEYWORD_NOLOG,
|
||||
.TZ = KEYWORD_TZ,
|
||||
.TimeZoneDisplay = KEYWORD_TZD,
|
||||
.TimeZoneName = KEYWORD_TZNAME,
|
||||
.TimeZoneValue = KEYWORD_TZVALUE,
|
||||
.TimeZoneDst = KEYWORD_TZDST,
|
||||
.PopupOnStart = KEYWORD_POPUP2};
|
||||
|
||||
const struct AppSettings DefaultSettings = {
|
||||
.Type = DefaultSettingType,
|
||||
@@ -60,7 +68,15 @@ const struct AppSettings DefaultSettings = {
|
||||
.Expert = EXPERT_DEF,
|
||||
.Priority = PRIORITY_DEF,
|
||||
.Threshold = THRESHOLD_DEF,
|
||||
.Values = 0xFFFF};
|
||||
.Active = ACTIVE_DEF,
|
||||
.NoLog = NOLOG_DEF,
|
||||
.TZ = TZ_DEF,
|
||||
.TimeZoneDisplay = TZD_DEF,
|
||||
.TimeZoneName = TZNAME_DEF,
|
||||
.TimeZoneValue = TZVALUE_DEF,
|
||||
.TimeZoneDst = TZDST_DEF,
|
||||
.Values = 0xFFFFF,
|
||||
.PopupOnStart = false};
|
||||
|
||||
static void SetPrioritySetting(struct AppSettings *, void *);
|
||||
static void SetIntervalSetting(struct AppSettings *, void *);
|
||||
@@ -72,11 +88,20 @@ static void SetReadOnlySetting(struct AppSettings *, void *);
|
||||
static void SetExpertSetting(struct AppSettings *, void *);
|
||||
static void SetPopupSetting(struct AppSettings *, void *);
|
||||
static void SetPopKeySetting(struct AppSettings *, void *);
|
||||
static void SetActiveSetting(struct AppSettings *, void *);
|
||||
static void SetNoLogSetting(struct AppSettings *, void *);
|
||||
static void SetTZSetting(struct AppSettings *, void *);
|
||||
static void SetTimeZoneDisplaySetting(struct AppSettings *, void *);
|
||||
static void SetTimeZoneNameSetting(struct AppSettings *, void *);
|
||||
static void SetTimeZoneValueSetting(struct AppSettings *, void *);
|
||||
static void SetTimeZoneDstSetting(struct AppSettings *, void *);
|
||||
static void ExecutePopupFunction(struct AppSettings *, void *);
|
||||
|
||||
// Keyword order in settingFunctions needs to match order in keyword template
|
||||
const struct SettingFunc settingFunctions[] = {
|
||||
{KEYWORD_READONLY, SetReadOnlySetting},
|
||||
{KEYWORD_EXPERT, SetExpertSetting},
|
||||
{KEYWORD_ACTIVE, SetActiveSetting},
|
||||
{KEYWORD_NOLOG, SetNoLogSetting},
|
||||
{KEYWORD_SERVER, SetDestinationAddressSetting},
|
||||
{KEYWORD_PORT, SetDestinationPortSetting},
|
||||
{KEYWORD_TIMEOUT, SetTimeoutSetting},
|
||||
@@ -84,7 +109,13 @@ const struct SettingFunc settingFunctions[] = {
|
||||
{KEYWORD_INTERVAL, SetIntervalSetting},
|
||||
{KEYWORD_PRIORITY, SetPrioritySetting},
|
||||
{KEYWORD_POPKEY, SetPopKeySetting},
|
||||
{KEYWORD_POPUP, SetPopupSetting}};
|
||||
{KEYWORD_POPUP, SetPopupSetting},
|
||||
{KEYWORD_TZ, SetTZSetting},
|
||||
{KEYWORD_TZD, SetTimeZoneDisplaySetting},
|
||||
{KEYWORD_TZNAME, SetTimeZoneNameSetting},
|
||||
{KEYWORD_TZVALUE, SetTimeZoneValueSetting},
|
||||
{KEYWORD_TZDST, SetTimeZoneDstSetting},
|
||||
{KEYWORD_POPUP2, ExecutePopupFunction}};
|
||||
|
||||
#define MAXSETTINGLINELEN 256
|
||||
|
||||
@@ -122,6 +153,13 @@ void ShowAppSettings(struct AppSettings *settings)
|
||||
LogDebug(settingValueLong, SettingKeys->Interval, settings->Interval);
|
||||
LogDebug(settingValueString, SettingKeys->Readonly, BooleanAsText(settings->Readonly));
|
||||
LogDebug(settingValueString, SettingKeys->Expert, BooleanAsText(settings->Expert));
|
||||
LogDebug(settingValueString, SettingKeys->Active, BooleanAsText(settings->Active));
|
||||
LogDebug(settingValueString, SettingKeys->NoLog, BooleanAsText(settings->NoLog));
|
||||
LogDebug(settingValueString, SettingKeys->TZ, settings->TZ);
|
||||
LogDebug(settingValueString, SettingKeys->TimeZoneName, settings->TimeZoneName);
|
||||
LogDebug(settingValueLong, SettingKeys->TimeZoneValue, settings->TimeZoneValue);
|
||||
LogDebug(settingValueLong, SettingKeys->TimeZoneDisplay, settings->TimeZoneDisplay);
|
||||
LogDebug(settingValueLong, SettingKeys->TimeZoneDst, settings->TimeZoneDst);
|
||||
}
|
||||
|
||||
void ShowSettings(void)
|
||||
@@ -278,12 +316,63 @@ static void SetExpertSetting(struct AppSettings *settings, void *value)
|
||||
&settings->Expert, value, true);
|
||||
}
|
||||
|
||||
static void SetActiveSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseBooleanSetting(settings, ActiveSet, SettingKeys->Active,
|
||||
&settings->Active, value, true);
|
||||
}
|
||||
|
||||
static void SetNoLogSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseBooleanSetting(settings, NoLogSet, SettingKeys->NoLog,
|
||||
&settings->NoLog, value, true);
|
||||
}
|
||||
|
||||
static void SetPopupSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseBooleanSetting(settings, PopUpSet, SettingKeys->Popup,
|
||||
&settings->Popup, value, false);
|
||||
}
|
||||
|
||||
static void SetTZSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
LogFoundSetting(settings->Type, SettingKeys->TZ);
|
||||
settings->TZ = StrDupSafe((const char *)value);
|
||||
settings->Values |= TzSet;
|
||||
}
|
||||
|
||||
static void SetTimeZoneDisplaySetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseLongSetting(settings, TimeZoneDisplaySet, SettingKeys->TimeZoneDisplay,
|
||||
&settings->TimeZoneDisplay, value);
|
||||
}
|
||||
|
||||
static void SetTimeZoneNameSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
LogFoundSetting(settings->Type, SettingKeys->TimeZoneName);
|
||||
settings->TimeZoneName = StrDupSafe((const char *)value);
|
||||
settings->Values |= TimeZoneNameSet;
|
||||
}
|
||||
|
||||
static void SetTimeZoneValueSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseLongSetting(settings, TimeZoneValueSet, SettingKeys->TimeZoneValue,
|
||||
&settings->TimeZoneValue, value);
|
||||
}
|
||||
|
||||
static void SetTimeZoneDstSetting(struct AppSettings *settings, void *value)
|
||||
{
|
||||
ParseLongSetting(settings, TimeZoneDstSet, SettingKeys->TimeZoneDst,
|
||||
&settings->TimeZoneDst, value);
|
||||
}
|
||||
|
||||
static void ExecutePopupFunction(struct AppSettings *settings, void *value)
|
||||
{
|
||||
// Run-time switch. Show settings window when starting
|
||||
LogFoundSetting(settings->Type, SettingKeys->PopupOnStart);
|
||||
settings->PopupOnStart = true;
|
||||
}
|
||||
|
||||
static void ParseSetting(struct AppSettings *settings, char *line)
|
||||
{
|
||||
char *value;
|
||||
@@ -399,7 +488,13 @@ static void WriteSetting(BPTR file, const char *format, ...)
|
||||
void SaveSettings(bool persist)
|
||||
{
|
||||
char low[MAXLONGLONGCHARSIZE];
|
||||
const char *dirName = persist ? persistentPrefsDir : prefsDir;
|
||||
const char *fileName = persist ? persistentPrefsFile : prefsFile;
|
||||
|
||||
BPTR lock = CreateDir((STRPTR)dirName);
|
||||
if (lock != NULL)
|
||||
UnLock(lock);
|
||||
|
||||
BPTR file = Open((STRPTR)fileName, MODE_NEWFILE);
|
||||
if (!file)
|
||||
{
|
||||
@@ -423,6 +518,21 @@ void SaveSettings(bool persist)
|
||||
WriteSetting(file, saveValueLong, SettingKeys->Interval, Settings->Interval);
|
||||
WriteSetting(file, saveValueString, SettingKeys->Readonly, BooleanAsText(Settings->Readonly));
|
||||
WriteSetting(file, saveValueString, SettingKeys->Expert, BooleanAsText(Settings->Expert));
|
||||
WriteSetting(file, saveValueString, SettingKeys->Active, BooleanAsText(Settings->Active));
|
||||
WriteSetting(file, saveValueString, SettingKeys->NoLog, BooleanAsText(Settings->NoLog));
|
||||
WriteSetting(file, saveValueLong, SettingKeys->TimeZoneDisplay, Settings->TimeZoneDisplay);
|
||||
|
||||
if (Settings->TZ != NULL && *Settings->TZ != '\0')
|
||||
WriteSetting(file, saveValueString, SettingKeys->TZ, Settings->TZ);
|
||||
|
||||
if (Settings->TimeZoneName != NULL && *Settings->TimeZoneName != '\0')
|
||||
WriteSetting(file, saveValueString, SettingKeys->TimeZoneName, Settings->TimeZoneName);
|
||||
|
||||
if (Settings->TimeZoneValue != TZVALUE_DEF)
|
||||
WriteSetting(file, saveValueLong, SettingKeys->TimeZoneValue, Settings->TimeZoneValue);
|
||||
|
||||
if (Settings->TimeZoneDst != TZDST_DEF)
|
||||
WriteSetting(file, saveValueLong, SettingKeys->TimeZoneDst, Settings->TimeZoneDst);
|
||||
|
||||
Close(file);
|
||||
}
|
||||
@@ -442,26 +552,28 @@ struct AppSettings *CopySettings(const struct AppSettings *settings)
|
||||
s->DestinationAddress = StrDupSafe(settings->DestinationAddress);
|
||||
s->DestinationPort = StrDupSafe(settings->DestinationPort);
|
||||
s->PopKey = StrDupSafe(settings->PopKey);
|
||||
s->Values = 0xFFFF;
|
||||
s->TZ = StrDupSafe(settings->TZ);
|
||||
s->TimeZoneName = StrDupSafe(settings->TimeZoneName);
|
||||
s->Values = 0xFFFFF;
|
||||
return s;
|
||||
}
|
||||
|
||||
void FreeSettings(struct AppSettings *settings)
|
||||
{
|
||||
if (settings->DestinationAddress != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->DestinationAddress);
|
||||
}
|
||||
|
||||
if (settings->DestinationPort != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->DestinationPort);
|
||||
}
|
||||
|
||||
if (settings->PopKey != NULL)
|
||||
{
|
||||
FreeMemSafe(settings->PopKey);
|
||||
}
|
||||
|
||||
if (settings->TZ != NULL)
|
||||
FreeMemSafe(settings->TZ);
|
||||
|
||||
if (settings->TimeZoneName != NULL)
|
||||
FreeMemSafe(settings->TimeZoneName);
|
||||
|
||||
FreeMemSafe(settings);
|
||||
}
|
||||
@@ -569,6 +681,21 @@ void ApplyAppSettings(struct AppSettings *settings, bool quiet)
|
||||
break;
|
||||
}
|
||||
|
||||
if (settings->Type == CliSettingType || settings->Type == WbSettingType)
|
||||
Settings->PopupOnStart = settings->PopupOnStart;
|
||||
|
||||
ApplyStringSetting(settings, TzSet, SettingKeys->TZ,
|
||||
&Settings->TZ, settings->TZ, quiet);
|
||||
|
||||
ApplyLongSetting(settings, TimeZoneDisplaySet, SettingKeys->TimeZoneDisplay,
|
||||
&Settings->TimeZoneDisplay, &settings->TimeZoneDisplay, quiet);
|
||||
|
||||
ApplyStringSetting(settings, TimeZoneNameSet, SettingKeys->TimeZoneName,
|
||||
&Settings->TimeZoneName, settings->TimeZoneName, quiet);
|
||||
|
||||
ApplyLongSetting(settings, TimeZoneValueSet, SettingKeys->TimeZoneValue,
|
||||
&Settings->TimeZoneValue, &settings->TimeZoneValue, quiet);
|
||||
|
||||
ApplyBooleanSetting(settings, PopUpSet, SettingKeys->Popup,
|
||||
&Settings->Popup, &settings->Popup, quiet);
|
||||
|
||||
@@ -584,12 +711,21 @@ void ApplyAppSettings(struct AppSettings *settings, bool quiet)
|
||||
ApplyLongSetting(settings, IntervalSet, SettingKeys->Interval,
|
||||
&Settings->Interval, &settings->Interval, quiet);
|
||||
|
||||
ApplyLongSetting(settings, TimeZoneDstSet, SettingKeys->TimeZoneDst,
|
||||
&Settings->TimeZoneDst, &settings->TimeZoneDst, quiet);
|
||||
|
||||
ApplyBooleanSetting(settings, ReadonlySet, SettingKeys->Readonly,
|
||||
&Settings->Readonly, &settings->Readonly, quiet);
|
||||
|
||||
ApplyBooleanSetting(settings, ExpertSet, SettingKeys->Expert,
|
||||
&Settings->Expert, &settings->Expert, quiet);
|
||||
|
||||
ApplyBooleanSetting(settings, ActiveSet, SettingKeys->Active,
|
||||
&Settings->Active, &settings->Active, quiet);
|
||||
|
||||
ApplyBooleanSetting(settings, NoLogSet, SettingKeys->NoLog,
|
||||
&Settings->NoLog, &settings->NoLog, quiet);
|
||||
|
||||
ApplyStringSetting(settings, DestinationAddressSet, SettingKeys->DestinationAddress,
|
||||
&Settings->DestinationAddress, settings->DestinationAddress, quiet);
|
||||
|
||||
|
||||
@@ -30,16 +30,23 @@
|
||||
#include "config.h"
|
||||
#include "locale.h"
|
||||
|
||||
#define PrioritySet 0x001
|
||||
#define TimeoutSet 0x004
|
||||
#define IntervalSet 0x008
|
||||
#define ReadonlySet 0x010
|
||||
#define ExpertSet 0x020
|
||||
#define DestinationAddressSet 0x040
|
||||
#define DestinationPortSet 0x080
|
||||
#define ThresholdSet 0x100
|
||||
#define PopKeySet 0x200
|
||||
#define PopUpSet 0x400
|
||||
#define PrioritySet 0x0001
|
||||
#define TimeoutSet 0x0002
|
||||
#define IntervalSet 0x0004
|
||||
#define ReadonlySet 0x0008
|
||||
#define ExpertSet 0x0010
|
||||
#define DestinationAddressSet 0x0020
|
||||
#define DestinationPortSet 0x0040
|
||||
#define ThresholdSet 0x0080
|
||||
#define PopKeySet 0x0100
|
||||
#define PopUpSet 0x0200
|
||||
#define ActiveSet 0x0400
|
||||
#define NoLogSet 0x0800
|
||||
#define TzSet 0x1000
|
||||
#define TimeZoneDisplaySet 0x2000
|
||||
#define TimeZoneNameSet 0x4000
|
||||
#define TimeZoneValueSet 0x8000
|
||||
#define TimeZoneDstSet 0x10000
|
||||
|
||||
#define DefaultSettingType 0x01
|
||||
#define PrefsSettingType 0x02
|
||||
@@ -59,8 +66,16 @@ struct AppSettings
|
||||
char *DestinationPort;
|
||||
char *PopKey;
|
||||
long Popup;
|
||||
long Active;
|
||||
long NoLog;
|
||||
char *TZ;
|
||||
long TimeZoneDisplay;
|
||||
char *TimeZoneName;
|
||||
long TimeZoneValue;
|
||||
long TimeZoneDst;
|
||||
long Values;
|
||||
long Type;
|
||||
long PopupOnStart;
|
||||
};
|
||||
|
||||
struct AppSettingKeys
|
||||
@@ -75,6 +90,14 @@ struct AppSettingKeys
|
||||
const char *Threshold;
|
||||
const char *PopKey;
|
||||
const char *Popup;
|
||||
const char *Active;
|
||||
const char *NoLog;
|
||||
const char *TZ;
|
||||
const char *TimeZoneDisplay;
|
||||
const char *TimeZoneName;
|
||||
const char *TimeZoneValue;
|
||||
const char *TimeZoneDst;
|
||||
const char *PopupOnStart;
|
||||
};
|
||||
|
||||
typedef void (*ParseSettingFunction)(struct AppSettings *, void *);
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "timer.h"
|
||||
#include "conv.h"
|
||||
#include "sntp.h"
|
||||
#include "text.h"
|
||||
#include "ptz.h"
|
||||
#include "mem.h"
|
||||
#include "net.h"
|
||||
@@ -54,7 +55,6 @@ struct AppCom
|
||||
struct sntp *Client;
|
||||
int TimerSigBit;
|
||||
bool Restart;
|
||||
int RunCount;
|
||||
int PoolServerNumber;
|
||||
char *ServerName;
|
||||
char *ServerPort;
|
||||
@@ -63,7 +63,6 @@ struct AppCom
|
||||
static void SyncProc(void);
|
||||
static int SyncClock(void);
|
||||
static void ChooseServer(void);
|
||||
static void CheckTimezone(void);
|
||||
static const char *SntpErrorText(enum sntp_err error);
|
||||
|
||||
static struct AppCom Synchronizer;
|
||||
@@ -100,7 +99,7 @@ void StartSynchronizer(void)
|
||||
|
||||
if (running)
|
||||
{
|
||||
LogDebug("Synchronizer process is already running");
|
||||
LogDebug(Text2P, "Synchronizer", TextAlreadyRunning);
|
||||
}
|
||||
else if (task != NULL)
|
||||
{
|
||||
@@ -112,13 +111,6 @@ void StartSynchronizer(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowLocalTime(void)
|
||||
{
|
||||
char *time = GetTimeText(AppLocale, LOCAL_TIME_NOW);
|
||||
LogNotice("Local time is %s", time);
|
||||
FreeMemSafe(time);
|
||||
}
|
||||
|
||||
static int ComInit(void)
|
||||
{
|
||||
if (OpenSocketLibrary() != LIB_OK)
|
||||
@@ -164,26 +156,9 @@ static void SendSync(void)
|
||||
if (ComInit() == COM_OK)
|
||||
{
|
||||
if (SyncClock() == COM_OK)
|
||||
{
|
||||
LogDebug("Sending next NTP request in %ld milliseconds", Settings->Interval);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogDebug("Retry in %ld milliseconds", Settings->Interval);
|
||||
}
|
||||
|
||||
Synchronizer.RunCount++;
|
||||
if (Synchronizer.RunCount % 10 == 0)
|
||||
{
|
||||
ShowLocalTime();
|
||||
}
|
||||
|
||||
if (Synchronizer.RunCount % 25 == 0)
|
||||
{
|
||||
long blocks, size;
|
||||
MemUsage(&blocks, &size, NULL);
|
||||
LogInfo("Currently using %ld bytes in %ld blocks on heap", size, blocks);
|
||||
}
|
||||
}
|
||||
|
||||
ComDestroy();
|
||||
@@ -250,7 +225,6 @@ static void SyncProc(void)
|
||||
Synchronizer.Client = NULL;
|
||||
Synchronizer.TimerSigBit = -1;
|
||||
Synchronizer.Restart = false;
|
||||
Synchronizer.RunCount = 0;
|
||||
Synchronizer.PoolServerNumber = -1;
|
||||
Synchronizer.ServerName = NULL;
|
||||
Synchronizer.ServerPort = NULL;
|
||||
@@ -454,38 +428,10 @@ static int SyncClock(void)
|
||||
|
||||
LastSync = rtv;
|
||||
SendWindowMessage(ATK_LASTSYNC);
|
||||
CheckTimezone();
|
||||
|
||||
return COM_OK;
|
||||
}
|
||||
|
||||
static void CheckTimezone(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
ULONG now;
|
||||
|
||||
if (NextTransition == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GetSysTime(&tv);
|
||||
now = (ULONG)(tv.tv_secs);
|
||||
|
||||
if (now > NextTransition->time)
|
||||
{
|
||||
char Timezone[TIMEZONE_TEXT_LEN];
|
||||
GetTimezoneText(AppLocale, Timezone, OFFSET_IN_PARENS);
|
||||
ShowLocalTime();
|
||||
LogNotice("Current time zone is %s", Timezone);
|
||||
LogWarn("Changing time zone");
|
||||
// TODO: Make thread safe
|
||||
ShowLocalTime();
|
||||
InitTimezoneShift();
|
||||
SendWindowMessage(ATK_TZ_CHANGED);
|
||||
}
|
||||
}
|
||||
|
||||
static const char *SntpErrorText(enum sntp_err error)
|
||||
{
|
||||
switch (error)
|
||||
|
||||
@@ -27,8 +27,10 @@
|
||||
#include "text.h"
|
||||
|
||||
// Settings
|
||||
const char *prefsFile = "ENV:timekeeper.prefs";
|
||||
const char *persistentPrefsFile = "ENVARC:timekeeper.prefs";
|
||||
const char *prefsDir = "ENV:AmiTimeKeeper";
|
||||
const char *prefsFile = "ENV:AmiTimeKeeper/timekeeper.prefs";
|
||||
const char *persistentPrefsDir = "ENVARC:AmiTimeKeeper";
|
||||
const char *persistentPrefsFile = "ENVARC:AmiTimeKeeper/timekeeper.prefs";
|
||||
const char *prefsFileSearch = "Searching for preference in %s";
|
||||
const char *prefsFileFound = "Found preference file";
|
||||
const char *prefsFileNotFound = "Preference file not found";
|
||||
@@ -52,6 +54,10 @@ const char *settingChangedLong = "%s changed: %ld -> %ld";
|
||||
const char *settingChangedString = "%s changed: %s -> %s";
|
||||
const char *settingSetLong = "%s is already set to %ld";
|
||||
const char *settingSetString = "%s is already set to %s";
|
||||
const char *settingTooLow = "%s < %ld (too low)";
|
||||
const char *settingTooHigh = "%s > %ld (too high)";
|
||||
const char *settingGreaterThan = "%s * 2 > %s";
|
||||
const char *settingInvalid = "%s is invalid (%ld)";
|
||||
const char *settingValueLong = "%s=%ld";
|
||||
const char *settingValueString = "%s=%s";
|
||||
const char *saveValueLong = "%s=%ld\n";
|
||||
@@ -60,9 +66,43 @@ const char *noValueString = "NO";
|
||||
const char *yesValueString = "YES";
|
||||
const char *falseValueString = "TRUE";
|
||||
const char *trueValueString = "FALSE";
|
||||
const char *validatingSettings = "Validating settings";
|
||||
const char *validatedSettings = "Settings validated";
|
||||
|
||||
// Time zone
|
||||
const char *applyTimeZone = "Setting local time zone from %s %s";
|
||||
const char *tzSettingValid = "Found valid %s %s";
|
||||
const char *tzSettingInvalid = "Found unknown %s %s";
|
||||
const char *tzFromEnv = "environment variable";
|
||||
const char *tzFromSet = "setting value in";
|
||||
const char *tzWorkbench = "Workbench";
|
||||
const char *tzPreferences = "preferences";
|
||||
const char *tzChange = "Changing to %s on %s";
|
||||
const char *tzDstAbbr = "DST";
|
||||
const char *tzStdAbbr = "standard time";
|
||||
const char *timezoneCur = "Current time zone is %s";
|
||||
const char *timezoneStd = "Standard time zone is %s";
|
||||
const char *timezoneDst = "DST time zone is %s";
|
||||
const char *timezoneNoTrans = "There are no time zone transitions";
|
||||
const char *tzChecker = "Timezone Checker";
|
||||
const char *tzCheck = "Checking for time zone transition";
|
||||
const char *tzTrans = "Performing time zone transition";
|
||||
|
||||
// Concat text
|
||||
const char *Text2P = "%s %s";
|
||||
|
||||
// Common text
|
||||
const char *TextEmpty = "Empty";
|
||||
const char *TextStarting = "Starting";
|
||||
const char *TextRestarting = "Restarting";
|
||||
const char *TextStarted = "started";
|
||||
const char *TextStopped = "stopped";
|
||||
const char *TextAlreadyRunning = "is already running";
|
||||
const char *TextNoStart = "Could not start";
|
||||
const char *TextClosing = "Closing";
|
||||
const char *TextOpened = "Opened";
|
||||
const char *TextNoOpen = "Cannot open";
|
||||
const char *TextFound = "Found";
|
||||
|
||||
// Error / debug messages
|
||||
const char *TextPortInitError = "%s message port failed to initialize";
|
||||
@@ -78,3 +118,14 @@ const char *TextSyncAlreadyOn = "Synchronization is already active";
|
||||
const char *TextSyncAlreadyOff = "Synchronization is already deactivated";
|
||||
const char *TextNoResponses = "No responses from NTP server";
|
||||
const char *TextNoClockAdjust = "Clock has not been adjusted";
|
||||
const char *TextARexxCmdUnknown = "Unknown ARexx command";
|
||||
const char *TextARexxParmUnknown = "Unknown parameter";
|
||||
const char *TextARexxParmInvalid = "Invalid parameter value";
|
||||
const char *TextARexxParmMiss = "Parameter is missing";
|
||||
const char *TextARexxVarError = "Could not set ARexx variable: %ld";
|
||||
const char *TextARexxVarValue = "ARexx variable %s = %s";
|
||||
const char *TextARexxResult = "ARexx result: %s";
|
||||
const char *TextARexxExecute1 = "Executing %s";
|
||||
const char *TextARexxExecute2 = "Executing %s %s";
|
||||
const char *TextARexxReceived = "Received %s";
|
||||
const char *TextARexxShutdown = "Requesting shutdown";
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
#include "config.h"
|
||||
|
||||
// Settings
|
||||
const char *prefsDir;
|
||||
const char *prefsFile;
|
||||
const char *persistentPrefsDir;
|
||||
const char *persistentPrefsFile;
|
||||
const char *prefsFileSearch;
|
||||
const char *prefsFileFound;
|
||||
@@ -55,6 +57,10 @@ const char *settingChangedLong;
|
||||
const char *settingChangedString;
|
||||
const char *settingSetLong;
|
||||
const char *settingSetString;
|
||||
const char *settingTooLow;
|
||||
const char *settingTooHigh;
|
||||
const char *settingGreaterThan;
|
||||
const char *settingInvalid;
|
||||
const char *settingValueLong;
|
||||
const char *settingValueString;
|
||||
const char *saveValueLong;
|
||||
@@ -63,9 +69,45 @@ const char *noValueString;
|
||||
const char *yesValueString;
|
||||
const char *falseValueString;
|
||||
const char *trueValueString;
|
||||
const char *validatingSettings;
|
||||
const char *validatedSettings;
|
||||
|
||||
// Library
|
||||
|
||||
// Time zone
|
||||
const char *applyTimeZone;
|
||||
const char *tzSettingValid;
|
||||
const char *tzSettingInvalid;
|
||||
const char *tzFromEnv;
|
||||
const char *tzFromSet;
|
||||
const char *tzWorkbench;
|
||||
const char *tzPreferences;
|
||||
const char *tzChange;
|
||||
const char *tzDstAbbr;
|
||||
const char *tzStdAbbr;
|
||||
const char *timezoneCur;
|
||||
const char *timezoneStd;
|
||||
const char *timezoneDst;
|
||||
const char *timezoneNoTrans;
|
||||
const char *tzChecker;
|
||||
const char *tzCheck;
|
||||
const char *tzTrans;
|
||||
|
||||
// Concat text
|
||||
const char *Text2P;
|
||||
|
||||
// Common text
|
||||
const char *TextEmpty;
|
||||
const char *TextStarting;
|
||||
const char *TextRestarting;
|
||||
const char *TextStarted;
|
||||
const char *TextStopped;
|
||||
const char *TextAlreadyRunning;
|
||||
const char *TextNoStart;
|
||||
const char *TextClosing;
|
||||
const char *TextOpened;
|
||||
const char *TextNoOpen;
|
||||
const char *TextFound;
|
||||
|
||||
// Error / debug messages
|
||||
const char *TextPortInitError;
|
||||
@@ -81,5 +123,16 @@ const char *TextSyncAlreadyOn;
|
||||
const char *TextSyncAlreadyOff;
|
||||
const char *TextNoResponses;
|
||||
const char *TextNoClockAdjust;
|
||||
const char *TextARexxCmdUnknown;
|
||||
const char *TextARexxParmUnknown;
|
||||
const char *TextARexxParmInvalid;
|
||||
const char *TextARexxParmMiss;
|
||||
const char *TextARexxVarError;
|
||||
const char *TextARexxVarValue;
|
||||
const char *TextARexxResult;
|
||||
const char *TextARexxExecute1;
|
||||
const char *TextARexxExecute2;
|
||||
const char *TextARexxReceived;
|
||||
const char *TextARexxShutdown;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,206 +28,330 @@
|
||||
#include "notify.h"
|
||||
#include "global.h"
|
||||
#include "message.h"
|
||||
#include "setting.h"
|
||||
#include "conv.h"
|
||||
#include "text.h"
|
||||
#include "ptz.h"
|
||||
#include "timer.h"
|
||||
#include "mem.h"
|
||||
#include "tz.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <utility/date.h>
|
||||
|
||||
#include "logmod.h"
|
||||
#define MODULENAME "Timezone"
|
||||
|
||||
#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"
|
||||
|
||||
/*
|
||||
* 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
|
||||
#define SECONDSPERDAY 86400
|
||||
|
||||
static long unixEpochOffset = 0;
|
||||
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;
|
||||
|
||||
void LogTzInfo()
|
||||
static void StartTimezoneCheck(void);
|
||||
|
||||
static void BuildTimezone(struct PosixLocalTimezone *timezone, int offset, bool std)
|
||||
{
|
||||
if (Timezone == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
long sign = (offset < 0 ? -1 : +1);
|
||||
long offsetPositive = (offset < 0 ? -offset : offset);
|
||||
long hoursOffset = (offsetPositive / 60L);
|
||||
long minutsOffset = (offsetPositive % 60L);
|
||||
|
||||
if (Timezone->dst.abbreviation != NULL)
|
||||
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)
|
||||
{
|
||||
LogInfo("Standard time zone is %s (GMT%s%02ld:%02ld)",
|
||||
Timezone->std.abbreviation,
|
||||
PosixTimezoneSignChar(&Timezone->std),
|
||||
(long)Timezone->std.offset.hours,
|
||||
(long)Timezone->std.offset.minutes);
|
||||
|
||||
LogInfo("DST time zone is %s (GMT%s%02ld:%02ld)",
|
||||
Timezone->dst.abbreviation,
|
||||
PosixTimezoneSignChar(&Timezone->dst),
|
||||
(long)Timezone->dst.offset.hours,
|
||||
(long)Timezone->dst.offset.minutes);
|
||||
SNPrintf(timezone->abbreviation, MAX_ABBR - 1, "GMT%s%ld",
|
||||
(sign <= 0 ? "+" : "-"), hoursOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogInfo("time zone is %s (GMT%s%02ld:%02ld)",
|
||||
Timezone->std.abbreviation,
|
||||
PosixTimezoneSignChar(&Timezone->std),
|
||||
(long)Timezone->std.offset.hours,
|
||||
(long)Timezone->std.offset.minutes);
|
||||
SNPrintf(timezone->abbreviation, MAX_ABBR - 1, "GMT%s%ld:%02ld",
|
||||
(sign <= 0 ? "+" : "-"), hoursOffset, minutsOffset);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
StrCopy(timezone->current.abbreviation, timezone->std.abbreviation);
|
||||
timezone->current.offset = timezone->std.offset;
|
||||
}
|
||||
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);
|
||||
else
|
||||
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)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (GetVar(var, buf, memsize - 1, GVF_GLOBAL_ONLY) > 0)
|
||||
{
|
||||
return (char *)buf;
|
||||
}
|
||||
|
||||
FreeMemSafe(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct PosixTimezone *ParseSettingsTZ()
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
case SetTZValTimezone:
|
||||
LogNotice(applyTimeZone, tzFromSet, SettingKeys->TimeZoneValue);
|
||||
break;
|
||||
case SetTZEnvTimezone:
|
||||
LogNotice(applyTimeZone, tzFromSet, SettingKeys->TZ);
|
||||
break;
|
||||
case EnvTZTimezone:
|
||||
LogNotice(applyTimeZone, tzFromEnv, ENV_TZ);
|
||||
break;
|
||||
case EnvTZOneTimezone:
|
||||
LogNotice(applyTimeZone, tzFromEnv, ENV_TZONE);
|
||||
break;
|
||||
case PrefsTimezone:
|
||||
LogNotice(applyTimeZone, tzWorkbench, tzPreferences);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void ShowNextTransition(void)
|
||||
{
|
||||
if (NextTransition != NULL)
|
||||
{
|
||||
char *nextTime = GetTimeText((ULONG)NextTransition->time);
|
||||
const char *nextTrans = NextTransition->isdst ? tzDstAbbr : tzStdAbbr;
|
||||
LogWarn(tzChange, nextTrans, nextTime);
|
||||
FreeMemSafe(nextTime);
|
||||
}
|
||||
}
|
||||
|
||||
void InitTimezone(void)
|
||||
{
|
||||
char TimezoneText[TIMEZONE_TEXT_LEN];
|
||||
char *tz;
|
||||
int result;
|
||||
CleanupNotifications();
|
||||
|
||||
tz = NULL;
|
||||
result = InitPosixTimezone(&tz);
|
||||
switch (result)
|
||||
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);
|
||||
|
||||
struct timeval tv;
|
||||
GetSysTime(&tv);
|
||||
SetPosixTimezone(set1Timezone, &tv);
|
||||
SetPosixTimezone(env1Timezone, &tv);
|
||||
SetPosixTimezone(env2Timezone, &tv);
|
||||
|
||||
long source = 0;
|
||||
struct PosixTimezone *timezone = NULL;
|
||||
if (Settings->TimeZoneValue != TZVALUE_DEF)
|
||||
{
|
||||
case 1:
|
||||
LogInfo("No TZ or TZONE variable found");
|
||||
break;
|
||||
case 2:
|
||||
LogInfo("Found unknown TZONE variable");
|
||||
LogDebug("TZONE = %s", tz);
|
||||
break;
|
||||
case 3:
|
||||
LogInfo("Found unknown TZ variable");
|
||||
LogDebug("TZ = %s", tz);
|
||||
break;
|
||||
case 4:
|
||||
LogInfo("Found valid TZONE variable");
|
||||
LogNotice("Using local time zone from the TZONE variable");
|
||||
LogDebug("TZONE = %s", tz);
|
||||
WatchFile("ENV:TZONE", ATK_TZONE_CHANGED);
|
||||
break;
|
||||
case 5:
|
||||
LogInfo("Found valid TZ variable");
|
||||
LogNotice("Using local time zone from the TZ variable");
|
||||
LogDebug("TZ = %s", tz);
|
||||
WatchFile("ENV:TZ", ATK_TZ_CHANGED);
|
||||
break;
|
||||
default:
|
||||
LogWarn("Unknown TZ or TZONE code");
|
||||
break;
|
||||
source = SetTZValTimezone;
|
||||
timezone = set2Timezone;
|
||||
}
|
||||
|
||||
if (tz != NULL)
|
||||
else if (set1Timezone != NULL)
|
||||
{
|
||||
FreeMemSafe(tz);
|
||||
source = SetTZEnvTimezone;
|
||||
timezone = set1Timezone;
|
||||
}
|
||||
|
||||
if (result == 4 || result == 5)
|
||||
else if (env1Timezone != NULL)
|
||||
{
|
||||
struct timeval tv;
|
||||
GetSysTime(&tv);
|
||||
SetPosixTimezone(&tv);
|
||||
LogTzInfo();
|
||||
unixEpochOffset =
|
||||
(Timezone->current.offset.sign < 0 ? +1 : -1) *
|
||||
(Timezone->current.offset.hours * 60 * 60 +
|
||||
Timezone->current.offset.minutes * 60 +
|
||||
Timezone->current.offset.seconds);
|
||||
unixEpochOffset += AMIGA_OFFSET;
|
||||
GetTimezoneText(AppLocale, TimezoneText, OFFSET_IN_PARENS);
|
||||
LogNotice("Current time zone is %s", TimezoneText);
|
||||
source = EnvTZTimezone;
|
||||
timezone = env1Timezone;
|
||||
}
|
||||
else if (env2Timezone != NULL)
|
||||
{
|
||||
source = EnvTZOneTimezone;
|
||||
timezone = env2Timezone;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogNotice("Using local time zone from Workbench preferences");
|
||||
WatchFile("ENV:Sys/locale.prefs", ATK_LOCALE_CHANGED);
|
||||
unixEpochOffset = AppLocale->AmigaLocale->loc_GMTOffset * 60 + AMIGA_OFFSET;
|
||||
GetTimezoneText(AppLocale, TimezoneText, OFFSET_IN_PARENS);
|
||||
LogNotice("Current time zone is %s", TimezoneText);
|
||||
source = PrefsTimezone;
|
||||
timezone = prefTimezone;
|
||||
}
|
||||
|
||||
InitTimezoneShift();
|
||||
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;
|
||||
}
|
||||
|
||||
ShowTimezoneSource();
|
||||
ShowTimezones();
|
||||
ShowNextTransition();
|
||||
StartTimezoneCheck();
|
||||
FreePosixTimezone(lastTimezone);
|
||||
}
|
||||
|
||||
void Amiga2DateStamp(time_t *time, struct DateStamp *date)
|
||||
void Unix2Amiga(struct timeval *utc, struct timeval *tv)
|
||||
{
|
||||
long t, d, m, q;
|
||||
assert(utc != NULL);
|
||||
assert(tv != NULL);
|
||||
|
||||
t = *time;
|
||||
d = t / SECONDSPERDAY;
|
||||
m = (t - SECONDSPERDAY * d) / 60;
|
||||
q = (t - SECONDSPERDAY * d - m * 60) * 60;
|
||||
|
||||
date->ds_Days = d;
|
||||
date->ds_Minute = m;
|
||||
date->ds_Tick = q;
|
||||
tv->tv_secs = utc->tv_secs - AMIGA_OFFSET;
|
||||
tv->tv_micro = utc->tv_micro;
|
||||
}
|
||||
|
||||
void InitTimezoneShift(void)
|
||||
{
|
||||
struct PosixTransitionTime *transition;
|
||||
struct timeval tv;
|
||||
char *nextTime;
|
||||
char *nextTrans;
|
||||
time_t next;
|
||||
ULONG now;
|
||||
|
||||
if (Timezone == NULL || Timezone->start.type == 0)
|
||||
{
|
||||
NextTransition = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 138; i++)
|
||||
{
|
||||
transition = &Timezone->transitions[i];
|
||||
next = transition->time;
|
||||
Amiga2DateStamp(&next, &ds);
|
||||
DateTimeString(&ds, timeString, dateString, dayString);
|
||||
LogWarn("XChanging (%ld) to %s time on %s %s at %s %s",
|
||||
next,
|
||||
transition->isdst ? "DST" : "standard",
|
||||
dayString, dateString, timeString,
|
||||
transition->isdst
|
||||
? Timezone->std.abbreviation
|
||||
: Timezone->dst.abbreviation);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
GetSysTime(&tv);
|
||||
now = (ULONG)(tv.tv_secs);
|
||||
transition = FindNextTransition(now);
|
||||
|
||||
if (transition == NULL)
|
||||
{
|
||||
NextTransition = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (NextTransition != NULL)
|
||||
{
|
||||
FreeMemSafe(NextTransition);
|
||||
}
|
||||
|
||||
NextTransition = transition;
|
||||
next = transition->time;
|
||||
|
||||
nextTime = GetTimeText(AppLocale, next);
|
||||
nextTrans = transition->isdst ? "DST" : "standard time";
|
||||
LogWarn("Changing to %s on %s", nextTrans, nextTime);
|
||||
FreeMemSafe(nextTime);
|
||||
}
|
||||
|
||||
void CleanupTimezone(void)
|
||||
{
|
||||
CleanupPosixTimezone();
|
||||
}
|
||||
|
||||
void Utc2Local(struct timeval *utc, struct timeval *tv)
|
||||
void UnixUtc2AmigaLocal(struct timeval *utc, struct timeval *tv)
|
||||
{
|
||||
assert(utc != NULL);
|
||||
assert(tv != NULL);
|
||||
@@ -251,6 +375,11 @@ void GetLocalTimeOfDay(struct timeval *tv)
|
||||
GetSysTime(tv);
|
||||
}
|
||||
|
||||
long GetUtcOffsetValue(void)
|
||||
{
|
||||
return (unixEpochOffset - AMIGA_OFFSET);
|
||||
}
|
||||
|
||||
void SetTimeOfDay(const struct TimerInfo *info, const struct timeval *tv)
|
||||
{
|
||||
struct timeval t;
|
||||
@@ -269,39 +398,118 @@ void SaveTimeOfDay(const struct timeval *tv)
|
||||
WriteBattClock((long)tv->tv_secs - unixEpochOffset);
|
||||
}
|
||||
|
||||
void DateTimeString(struct DateStamp *ds, char *time, char *date, char *day)
|
||||
static long GetNextTransition(void)
|
||||
{
|
||||
struct DateTime dt;
|
||||
|
||||
assert(ds != NULL);
|
||||
assert(time != NULL);
|
||||
assert(date != NULL);
|
||||
assert(day != NULL);
|
||||
|
||||
dt.dat_Stamp = *ds;
|
||||
dt.dat_Format = FORMAT_DOS;
|
||||
dt.dat_Flags = 0;
|
||||
dt.dat_StrDay = (void *)day;
|
||||
dt.dat_StrDate = (void *)date;
|
||||
dt.dat_StrTime = (void *)time;
|
||||
|
||||
DateToStr(&dt);
|
||||
time_t next = (NextTransition != NULL ? NextTransition->time : 2147483647);
|
||||
return (long)next;
|
||||
}
|
||||
|
||||
void Utc2Str(struct timeval *tv, char *buffer)
|
||||
static long GetNextTransitionCheck(long now)
|
||||
{
|
||||
char timeString[20];
|
||||
char dateString[20];
|
||||
char dayString[20];
|
||||
long diff = GetNextTransition() - now;
|
||||
diff = (diff > 60 ? 60 : diff);
|
||||
return diff;
|
||||
}
|
||||
|
||||
struct DateStamp ds;
|
||||
struct timeval last;
|
||||
time_t time;
|
||||
static void CheckTransition(void)
|
||||
{
|
||||
TimezoneCheckerShutdown = false;
|
||||
TimezoneCheckerRestart = false;
|
||||
|
||||
Utc2Local(tv, &last);
|
||||
time = last.tv_secs;
|
||||
if (NextTransition == NULL)
|
||||
{
|
||||
LogNotice(timezoneNoTrans);
|
||||
LogInfo(Text2P, tzChecker, TextStopped);
|
||||
TimezoneCheckerRunning = false;
|
||||
return;
|
||||
}
|
||||
|
||||
Amiga2DateStamp(&time, &ds);
|
||||
DateTimeString(&ds, timeString, dateString, dayString);
|
||||
SNPrintf(buffer, 64, "%s %s %s", dayString, dateString, timeString);
|
||||
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);
|
||||
}
|
||||
|
||||
diff--;
|
||||
Delay(50);
|
||||
|
||||
if (TimezoneCheckerRestart)
|
||||
{
|
||||
LogInfo(Text2P, TextRestarting, tzChecker);
|
||||
TimezoneCheckerRestart = false;
|
||||
diff = -1;
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo(Text2P, tzChecker, TextStopped);
|
||||
TimezoneCheckerRunning = false;
|
||||
TimezoneCheckerShutdown = false;
|
||||
}
|
||||
|
||||
void StopTimezoneCheck(void)
|
||||
{
|
||||
TimezoneCheckerShutdown = true;
|
||||
while (TimezoneCheckerRunning)
|
||||
Delay(10);
|
||||
}
|
||||
|
||||
static void StartTimezoneCheck(void)
|
||||
{
|
||||
if (TimezoneCheckerRunning)
|
||||
{
|
||||
LogTrace(Text2P, tzChecker, TextAlreadyRunning);
|
||||
TimezoneCheckerRestart = true;
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,14 +31,13 @@
|
||||
#include "timer.h"
|
||||
|
||||
void InitTimezone(void);
|
||||
void InitTimezoneShift(void);
|
||||
void CleanupTimezone(void);
|
||||
void GetTimeOfDay(struct timeval *);
|
||||
void SetTimeOfDay(const struct TimerInfo *, const struct timeval *);
|
||||
void SaveTimeOfDay(const struct timeval *);
|
||||
void GetLocalTimeOfDay(struct timeval *);
|
||||
void Amiga2DateStamp(time_t *, struct DateStamp *);
|
||||
void Utc2Local(struct timeval *, struct timeval *);
|
||||
void Utc2Str(struct timeval *, char *);
|
||||
long GetUtcOffsetValue(void);
|
||||
void UnixUtc2AmigaLocal(struct timeval *, struct timeval *);
|
||||
void Unix2Amiga(struct timeval *, struct timeval *);
|
||||
void StopTimezoneCheck(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,21 +27,18 @@
|
||||
#include "config.h"
|
||||
#include "message.h"
|
||||
#include "setting.h"
|
||||
#include "text.h"
|
||||
#include "conv.h"
|
||||
#include "sync.h"
|
||||
#include "log.h"
|
||||
#include "mem.h"
|
||||
#include "val.h"
|
||||
#include "win.h"
|
||||
#include "tz.h"
|
||||
|
||||
#include "logmod.h"
|
||||
#define MODULENAME "Settings"
|
||||
|
||||
static const char *settingChangedLong = "%s changed: %ld -> %ld";
|
||||
static const char *settingChangedString = "%s changed: %s -> %s";
|
||||
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 ValidateInterval(void)
|
||||
{
|
||||
if (Settings->Interval < INTERVAL_MIN)
|
||||
@@ -55,6 +52,17 @@ static void ValidateInterval(void)
|
||||
INTERVAL_MIN);
|
||||
Settings->Interval = INTERVAL_MIN;
|
||||
}
|
||||
else if (Settings->Interval > INTERVAL_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh,
|
||||
SettingKeys->Interval,
|
||||
INTERVAL_MAX);
|
||||
LogNotice(settingChangedLong,
|
||||
SettingKeys->Interval,
|
||||
Settings->Interval,
|
||||
INTERVAL_MAX);
|
||||
Settings->Interval = INTERVAL_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeout(void)
|
||||
@@ -126,17 +134,59 @@ static void ValidateThreshold(void)
|
||||
{
|
||||
if (Settings->Threshold < THRESHOLD_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow,
|
||||
SettingKeys->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
LogNotice(settingChangedLong,
|
||||
SettingKeys->Threshold,
|
||||
Settings->Threshold,
|
||||
THRESHOLD_MIN);
|
||||
LogInfo(settingTooLow, SettingKeys->Threshold, THRESHOLD_MIN);
|
||||
LogNotice(settingChangedLong, SettingKeys->Threshold,
|
||||
Settings->Threshold, THRESHOLD_MIN);
|
||||
Settings->Threshold = THRESHOLD_MIN;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeZoneDisplay(void)
|
||||
{
|
||||
if (Settings->TimeZoneDisplay < TZD_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow, SettingKeys->TimeZoneDisplay, TZD_MIN);
|
||||
LogNotice(settingChangedLong, SettingKeys->TimeZoneDisplay,
|
||||
Settings->TimeZoneDisplay, TZD_MIN);
|
||||
Settings->TimeZoneDisplay = TZD_MIN;
|
||||
}
|
||||
else if (Settings->TimeZoneDisplay > TZD_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh, SettingKeys->TimeZoneDisplay, TZD_MAX);
|
||||
LogNotice(settingChangedLong, SettingKeys->TimeZoneDisplay,
|
||||
Settings->TimeZoneDisplay, TZD_MAX);
|
||||
Settings->TimeZoneDisplay = TZD_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static void ValidateTimeZoneValue(void)
|
||||
{
|
||||
if (Settings->TimeZoneValue < TZVALUE_MIN)
|
||||
{
|
||||
LogInfo(settingTooLow, SettingKeys->TimeZoneValue, TZVALUE_MIN);
|
||||
LogNotice(settingChangedLong, SettingKeys->TimeZoneValue,
|
||||
Settings->TimeZoneValue, TZVALUE_MIN);
|
||||
Settings->TimeZoneValue = TZVALUE_MIN;
|
||||
}
|
||||
else if (Settings->TimeZoneValue != TZVALUE_DEF &&
|
||||
Settings->TimeZoneValue > TZVALUE_MAX)
|
||||
{
|
||||
LogInfo(settingTooHigh, SettingKeys->TimeZoneValue, TZVALUE_MAX);
|
||||
LogNotice(settingChangedLong, SettingKeys->TimeZoneValue,
|
||||
Settings->TimeZoneValue, TZVALUE_MAX);
|
||||
Settings->TimeZoneValue = TZVALUE_MAX;
|
||||
}
|
||||
|
||||
if (Settings->TimeZoneValue % 60 >= 60)
|
||||
{
|
||||
long oldValue = Settings->TimeZoneValue;
|
||||
Settings->TimeZoneValue = (Settings->TimeZoneValue / 60) * 60;
|
||||
LogInfo(settingInvalid, SettingKeys->TimeZoneValue, oldValue);
|
||||
LogNotice(settingChangedLong, SettingKeys->TimeZoneValue,
|
||||
oldValue, Settings->TimeZoneValue);
|
||||
}
|
||||
}
|
||||
|
||||
static bool ValidateServer(char *name)
|
||||
{
|
||||
return true;
|
||||
@@ -149,12 +199,14 @@ static bool ValidatePort(char *name)
|
||||
|
||||
void SanitizeSettings(void)
|
||||
{
|
||||
LogTrace("Validating settings");
|
||||
LogDebug(validatingSettings);
|
||||
ValidateInterval();
|
||||
ValidateTimeout();
|
||||
ValidatePriority();
|
||||
ValidateThreshold();
|
||||
LogTrace("Settings validated");
|
||||
ValidateTimeZoneDisplay();
|
||||
ValidateTimeZoneValue();
|
||||
LogTrace(validatedSettings);
|
||||
}
|
||||
|
||||
void SetInterval(long value, long opt)
|
||||
@@ -323,7 +375,8 @@ void SetServer(char *valueString, long opt)
|
||||
valueString);
|
||||
FreeMemSafe(oldValue);
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
bool active = SynchronizerRunning;
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
@@ -359,8 +412,10 @@ void SetServer(char *valueString, long opt)
|
||||
WriteUiServer();
|
||||
}
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
while (SynchronizerRunning)
|
||||
Delay(10);
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
@@ -386,7 +441,8 @@ void SetPort(char *valueString, long opt)
|
||||
valueString);
|
||||
FreeMemSafe(oldValue);
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
bool active = SynchronizerRunning;
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
@@ -422,8 +478,92 @@ void SetPort(char *valueString, long opt)
|
||||
WriteUiPort();
|
||||
}
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
while (SynchronizerRunning)
|
||||
Delay(10);
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
|
||||
void SetTimeZoneSetting(const char *settingKey, char **setting, char *valueString, long opt)
|
||||
{
|
||||
char *oldSettingValue, *newSettingValue;
|
||||
char *oldValue;
|
||||
|
||||
oldValue = StrDupSafe(*setting);
|
||||
if (Stricmp((STRPTR)oldValue, (STRPTR)valueString) == 0)
|
||||
{
|
||||
FreeMemSafe(oldValue);
|
||||
return;
|
||||
}
|
||||
|
||||
LogNotice(settingChangedString,
|
||||
settingKey,
|
||||
oldValue,
|
||||
valueString);
|
||||
FreeMemSafe(oldValue);
|
||||
|
||||
bool active = SynchronizerRunning;
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
Deactivate();
|
||||
}
|
||||
|
||||
newSettingValue = StrDupSafe(valueString);
|
||||
Forbid();
|
||||
oldSettingValue = *setting;
|
||||
*setting = newSettingValue;
|
||||
Permit();
|
||||
FreeMemSafe(oldSettingValue);
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && settingKey == SettingKeys->TZ)
|
||||
{
|
||||
InitTimezone();
|
||||
}
|
||||
|
||||
if ((opt & APPLY_UI_FRONT) == APPLY_UI_FRONT)
|
||||
{
|
||||
SendWindowMessage(ATK_TZ_CHANGED);
|
||||
}
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME && active)
|
||||
{
|
||||
while (SynchronizerRunning)
|
||||
Delay(10);
|
||||
Activate();
|
||||
}
|
||||
}
|
||||
|
||||
void SetTimeZoneSettingLong(const char *settingKey, long *setting, char *valueString, long opt)
|
||||
{
|
||||
LONG value, oldValue = *setting;
|
||||
int p = StrToLong((STRPTR)valueString, &value);
|
||||
|
||||
if (p != -1 && oldValue != value)
|
||||
{
|
||||
LogNotice(settingChangedLong,
|
||||
settingKey,
|
||||
oldValue,
|
||||
value);
|
||||
*setting = value;
|
||||
}
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
{
|
||||
if (settingKey == SettingKeys->TimeZoneValue || settingKey == SettingKeys->TimeZoneDst)
|
||||
{
|
||||
InitTimezone();
|
||||
}
|
||||
}
|
||||
|
||||
if ((opt & APPLY_UI_FRONT) == APPLY_UI_FRONT)
|
||||
{
|
||||
SendWindowMessage(ATK_TZ_CHANGED);
|
||||
}
|
||||
|
||||
if ((opt & APPLY_RUNTIME) == APPLY_RUNTIME)
|
||||
{
|
||||
SendBrokerMessage(ATK_RESTART);
|
||||
}
|
||||
}
|
||||
@@ -46,5 +46,7 @@ void SetInterval(long, long);
|
||||
void SetTimeout(long, long);
|
||||
void SetThreshold(char *, long);
|
||||
void SetPriority(char *, long);
|
||||
void SetTimeZoneSetting(const char *, char **, char *, long);
|
||||
void SetTimeZoneSettingLong(const char *, long *, char *, long);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -583,7 +583,7 @@ void ShowLastSync(struct timeval *tv)
|
||||
}
|
||||
|
||||
GetLocalTimeOfDay(&nowLocal);
|
||||
Utc2Local(tv, &lastLocal);
|
||||
UnixUtc2AmigaLocal(tv, &lastLocal);
|
||||
seconds = nowLocal.tv_secs - lastLocal.tv_secs;
|
||||
|
||||
if (seconds > 60 * 60 * 24)
|
||||
@@ -615,7 +615,7 @@ void ShowNewTimezone(void)
|
||||
char *temp = SettingWindow.TimezoneText;
|
||||
char *new = AllocStringSafe(TIMEZONE_TEXT_LEN);
|
||||
|
||||
GetTimezoneText(AppLocale, new, ZONE_IN_PARENS);
|
||||
GetTimezoneText(new, TZD_ZONE_IN_PARENS);
|
||||
GT_SetGadgetAttrs(
|
||||
SettingWindow.Gadgets->TimezoneGadget,
|
||||
SettingWindow.Window, NULL,
|
||||
|
||||
+16
-3
@@ -52,10 +52,12 @@ volatile bool WindowProcRunning = false;
|
||||
struct AppSettings *WindowSettings = NULL;
|
||||
struct AppSettingWindow SettingWindow;
|
||||
|
||||
static APTR OrgWindowPtr = NULL;
|
||||
|
||||
void ShowSettingWindow(void)
|
||||
{
|
||||
bool running;
|
||||
struct Task *task;
|
||||
struct Task *task = NULL;
|
||||
|
||||
if (GadToolsBase == NULL)
|
||||
{
|
||||
@@ -84,7 +86,7 @@ void ShowSettingWindow(void)
|
||||
|
||||
if (running)
|
||||
{
|
||||
LogDebug("Setting process is already running");
|
||||
LogDebug(Text2P, "Setting process", TextAlreadyRunning);
|
||||
SendWindowMessage(ATK_SHOW);
|
||||
}
|
||||
else if (task != NULL)
|
||||
@@ -143,7 +145,7 @@ static bool InitWindow(void)
|
||||
|
||||
LongToStr(Settings->Priority, SettingWindow.PriorityText);
|
||||
LongLongToStr(Settings->Threshold, SettingWindow.ThresholdText);
|
||||
GetTimezoneText(AppLocale, SettingWindow.TimezoneText, ZONE_IN_PARENS);
|
||||
GetTimezoneText(SettingWindow.TimezoneText, Settings->TimeZoneDisplay);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -159,6 +161,11 @@ static void DestroyWindow(void)
|
||||
while ((msg = GetMsg(SettingWindow.Window->UserPort)))
|
||||
ReplyMsg(msg);
|
||||
|
||||
Forbid();
|
||||
struct Process *proc = (struct Process *)FindTask(NULL);
|
||||
proc->pr_WindowPtr = OrgWindowPtr;
|
||||
Permit();
|
||||
|
||||
CloseWindow(SettingWindow.Window);
|
||||
SettingWindow.Window = NULL;
|
||||
}
|
||||
@@ -215,6 +222,12 @@ static bool CreateWindow(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
Forbid();
|
||||
struct Process *proc = (struct Process *)FindTask(NULL);
|
||||
OrgWindowPtr = proc->pr_WindowPtr;
|
||||
proc->pr_WindowPtr = x;
|
||||
Permit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user